From f4bce611ef97e8649ce70d23384341f4011f3ee7 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Wed, 24 Oct 2018 14:21:59 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90AAC=20RTMP=E7=BC=96=E8=A7=A3?= =?UTF-8?q?=E7=A0=81=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/RTP/AACRtpCodec.cpp | 4 +- src/RTP/AACRtpCodec.h | 2 +- src/Rtmp/RtmpToRtspMediaSource.cpp | 2 +- src/Rtmp/RtmpToRtspMediaSource.h | 4 +- src/RtmpCodec/AACRtmpCodec.cpp | 122 +++++++++++++++++++++++++++++ src/RtmpCodec/AACRtmpCodec.h | 69 ++++++++++++++++ src/RtmpCodec/H264RtmpCodec.cpp | 10 +-- src/RtmpCodec/H264RtmpCodec.h | 11 +-- src/Rtsp/RtspToRtmpMediaSource.cpp | 2 +- src/Rtsp/RtspToRtmpMediaSource.h | 4 +- 10 files changed, 209 insertions(+), 21 deletions(-) create mode 100644 src/RtmpCodec/AACRtmpCodec.cpp create mode 100644 src/RtmpCodec/AACRtmpCodec.h diff --git a/src/RTP/AACRtpCodec.cpp b/src/RTP/AACRtpCodec.cpp index 59136c0c..414ffe3e 100644 --- a/src/RTP/AACRtpCodec.cpp +++ b/src/RTP/AACRtpCodec.cpp @@ -114,12 +114,12 @@ bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) { m_adts->sequence = rtppack->sequence; m_adts->timeStamp = rtppack->timeStamp * (1000.0 / m_sampleRate); writeAdtsHeader(*m_adts, m_adts->buffer); - onGetAdts(m_adts); + onGetAAC(m_adts); } return false; } -void AACRtpDecoder::onGetAdts(const AACFrame::Ptr &frame) { +void AACRtpDecoder::onGetAAC(const AACFrame::Ptr &frame) { //写入环形缓存 RtpCodec::inputFrame(frame); m_adts = obtainFrame(); diff --git a/src/RTP/AACRtpCodec.h b/src/RTP/AACRtpCodec.h index 9d56a449..2b8dd92c 100644 --- a/src/RTP/AACRtpCodec.h +++ b/src/RTP/AACRtpCodec.h @@ -35,7 +35,7 @@ public: return CodecAAC; } private: - void onGetAdts(const AACFrame::Ptr &frame); + void onGetAAC(const AACFrame::Ptr &frame); AACFrame::Ptr obtainFrame(); private: AACFrame::Ptr m_adts; diff --git a/src/Rtmp/RtmpToRtspMediaSource.cpp b/src/Rtmp/RtmpToRtspMediaSource.cpp index c61a4e3f..e3059bb4 100644 --- a/src/Rtmp/RtmpToRtspMediaSource.cpp +++ b/src/Rtmp/RtmpToRtspMediaSource.cpp @@ -55,7 +55,7 @@ void RtmpToRtspMediaSource::onGetH264(const H264Frame &frame) { m_pRtpMaker_h264->makeRtp(frame.data() + 4, frame.size() - 4, frame.timeStamp); } } -inline void RtmpToRtspMediaSource::onGetAdts(const AACFrame &frame) { +inline void RtmpToRtspMediaSource::onGetAAC(const AACFrame &frame) { if(m_pRecorder){ m_pRecorder->inputAAC((char *) frame.buffer, frame.aac_frame_length, frame.timeStamp); } diff --git a/src/Rtmp/RtmpToRtspMediaSource.h b/src/Rtmp/RtmpToRtspMediaSource.h index a402e501..2caef88f 100644 --- a/src/Rtmp/RtmpToRtspMediaSource.h +++ b/src/Rtmp/RtmpToRtspMediaSource.h @@ -69,7 +69,7 @@ public: m_pRecorder.reset(new MediaRecorder(getVhost(),getApp(),getId(),m_pParser,m_bEnableHls,m_bEnableMp4)); //todo(xzl) 修复此处 -// m_pParser->setOnAudioCB(std::bind(&RtmpToRtspMediaSource::onGetAdts, this, placeholders::_1)); +// m_pParser->setOnAudioCB(std::bind(&RtmpToRtspMediaSource::onGetAAC, this, placeholders::_1)); // m_pParser->setOnVideoCB(std::bind(&RtmpToRtspMediaSource::onGetH264, this, placeholders::_1)); } catch (exception &ex) { WarnL << ex.what(); @@ -96,7 +96,7 @@ private: bool m_bEnableHls; bool m_bEnableMp4; void onGetH264(const H264Frame &frame); - void onGetAdts(const AACFrame &frame); + void onGetAAC(const AACFrame &frame); void makeSDP(); }; diff --git a/src/RtmpCodec/AACRtmpCodec.cpp b/src/RtmpCodec/AACRtmpCodec.cpp new file mode 100644 index 00000000..84da145c --- /dev/null +++ b/src/RtmpCodec/AACRtmpCodec.cpp @@ -0,0 +1,122 @@ +// +// Created by xzl on 2018/10/24. +// + +#include +#include "AACRtmpCodec.h" + +namespace ZL{ +namespace Rtmp { + +AACRtmpDecoder::AACRtmpDecoder() { + _adts = obtainFrame(); +} + +AACFrame::Ptr AACRtmpDecoder::obtainFrame() { + //从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象 + auto frame = ResourcePoolHelper::obtainObj(); + frame->aac_frame_length = 7; + frame->iPrefixSize = 7; + return frame; +} + +bool AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool key_pos) { + RtmpCodec::inputRtmp(pkt, false); + + if (pkt->isCfgFrame()) { + _aac_cfg = pkt->getAacCfg(); + return false; + } + if (!_aac_cfg.empty()) { + onGetAAC(pkt->strBuf.data() + 2, pkt->strBuf.size() - 2, pkt->timeStamp); + } + return false; +} + +void AACRtmpDecoder::onGetAAC(const char* pcData, int iLen, uint32_t ui32TimeStamp) { + if(iLen + 7 > sizeof(_adts->buffer)){ + WarnL << "Illegal adts data, exceeding the length limit."; + return; + } + //写adts结构头 + makeAdtsHeader(_aac_cfg,*_adts); + + //拷贝aac负载 + memcpy(_adts->buffer + 7, pcData, iLen); + _adts->aac_frame_length = 7 + iLen; + _adts->timeStamp = ui32TimeStamp; + + //adts结构头转成头7个字节 + writeAdtsHeader(*_adts, _adts->buffer); + + //写入环形缓存 + RtmpCodec::inputFrame(_adts); + _adts = obtainFrame(); +} +///////////////////////////////////////////////////////////////////////////////////// + +void AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) { + RtmpCodec::inputFrame(frame); + if(frame->prefixSize() == 7 && _aac_cfg.empty()){ + //包含adts头 + _aac_cfg = makeAdtsConfig(reinterpret_cast(frame->data())); + makeAudioConfigPkt(); + } +} + +void AACRtmpEncoder::makeAudioConfigPkt() { + makeAdtsHeader(_aac_cfg,*_adts); + int iSampleRate , iChannel , iSampleBit = 16; + getAACInfo(*_adts,iSampleRate,iChannel); + + uint8_t flvStereoOrMono = (iChannel > 1); + uint8_t flvSampleRate; + switch (iSampleRate) { + case 48000: + case 44100: + flvSampleRate = 3; + break; + case 24000: + case 22050: + flvSampleRate = 2; + break; + case 12000: + case 11025: + flvSampleRate = 1; + break; + default: + flvSampleRate = 0; + break; + } + uint8_t flvSampleBit = iSampleBit == 16; + uint8_t flvAudioType = 10; //aac + + uint8_t m_ui8AudioFlags = (flvAudioType << 4) | (flvSampleRate << 2) | (flvSampleBit << 1) | flvStereoOrMono; + + RtmpPacket::Ptr rtmpPkt = ResourcePoolHelper::obtainObj(); + //////////header + uint8_t is_config = true; + rtmpPkt->strBuf.push_back(m_ui8AudioFlags); + rtmpPkt->strBuf.push_back(!is_config); + rtmpPkt->strBuf.append(_aac_cfg); + + rtmpPkt->bodySize = rtmpPkt->strBuf.size(); + rtmpPkt->chunkId = CHUNK_AUDIO; + rtmpPkt->streamId = STREAM_MEDIA; + rtmpPkt->timeStamp = 0; + rtmpPkt->typeId = MSG_AUDIO; + inputRtmp(rtmpPkt, true); +} + + + + + + + + + + + +}//namespace Rtmp +}//namespace ZL \ No newline at end of file diff --git a/src/RtmpCodec/AACRtmpCodec.h b/src/RtmpCodec/AACRtmpCodec.h new file mode 100644 index 00000000..c326835a --- /dev/null +++ b/src/RtmpCodec/AACRtmpCodec.h @@ -0,0 +1,69 @@ +// +// Created by xzl on 2018/10/24. +// + +#ifndef ZLMEDIAKIT_AACRTMPCODEC_H +#define ZLMEDIAKIT_AACRTMPCODEC_H + +#include "RtmpCodec.h" + +namespace ZL{ +namespace Rtmp { +/** + * aac Rtmp转adts类 + */ +class AACRtmpDecoder : public RtmpCodec , public ResourcePoolHelper { +public: + typedef std::shared_ptr Ptr; + + AACRtmpDecoder(); + ~AACRtmpDecoder() {} + + /** + * 输入Rtmp并解码 + * @param Rtmp Rtmp数据包 + * @param key_pos 此参数内部强制转换为false,请忽略之 + */ + bool inputRtmp(const RtmpPacket::Ptr &Rtmp, bool key_pos = false) override; + + TrackType getTrackType() const override{ + return TrackAudio; + } + + CodecId getCodecId() const override{ + return CodecAAC; + } + +protected: + void onGetAAC(const char* pcData, int iLen, uint32_t ui32TimeStamp); + AACFrame::Ptr obtainFrame(); +protected: + AACFrame::Ptr _adts; + string _aac_cfg; +}; + + +/** + * aac adts转Rtmp类 + */ +class AACRtmpEncoder : public AACRtmpDecoder , public ResourcePoolHelper { +public: + typedef std::shared_ptr Ptr; + + AACRtmpEncoder(); + ~AACRtmpEncoder() {} + + /** + * 输入aac 数据,必须带dats头 + * @param frame 带dats头的aac数据 + */ + void inputFrame(const Frame::Ptr &frame) override; + +private: + void makeAudioConfigPkt(); +}; + +}//namespace Rtmp +}//namespace ZL + +#endif //ZLMEDIAKIT_AACRTMPCODEC_H diff --git a/src/RtmpCodec/H264RtmpCodec.cpp b/src/RtmpCodec/H264RtmpCodec.cpp index 21456d63..4a2f7dff 100644 --- a/src/RtmpCodec/H264RtmpCodec.cpp +++ b/src/RtmpCodec/H264RtmpCodec.cpp @@ -26,12 +26,12 @@ bool H264RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &rtmp, bool key_pos) { bool H264RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) { if (pkt->isCfgFrame()) { //缓存sps pps,后续插入到I帧之前 - m_strSPS = pkt->getH264SPS(); - m_strPPS = pkt->getH264PPS(); + m_sps = pkt->getH264SPS(); + m_pps = pkt->getH264PPS(); return false; } - if (m_strSPS.size()) { + if (m_sps.size()) { uint32_t iTotalLen = pkt->strBuf.size(); uint32_t iOffset = 5; while(iOffset + 4 < iTotalLen){ @@ -54,8 +54,8 @@ inline void H264RtmpDecoder::onGetH264_l(const char* pcData, int iLen, uint32_t switch (pcData[0] & 0x1F) { case 5: { //I frame - onGetH264(m_strSPS.data(), m_strSPS.length(), ui32TimeStamp); - onGetH264(m_strPPS.data(), m_strPPS.length(), ui32TimeStamp); + onGetH264(m_sps.data(), m_sps.length(), ui32TimeStamp); + onGetH264(m_pps.data(), m_pps.length(), ui32TimeStamp); } case 1: { //I or P or B frame diff --git a/src/RtmpCodec/H264RtmpCodec.h b/src/RtmpCodec/H264RtmpCodec.h index aa0cf49f..27992228 100644 --- a/src/RtmpCodec/H264RtmpCodec.h +++ b/src/RtmpCodec/H264RtmpCodec.h @@ -34,15 +34,15 @@ public: CodecId getCodecId() const override{ return CodecH264; } -private: +protected: bool decodeRtmp(const RtmpPacket::Ptr &Rtmp); void onGetH264_l(const char *pcData, int iLen, uint32_t ui32TimeStamp); void onGetH264(const char *pcData, int iLen, uint32_t ui32TimeStamp); H264Frame::Ptr obtainFrame(); -private: +protected: H264Frame::Ptr m_h264frame; - string m_strSPS; - string m_strPPS; + string m_sps; + string m_pps; }; /** @@ -62,9 +62,6 @@ public: void inputFrame(const Frame::Ptr &frame) override; private: void makeVideoConfigPkt(); -private: - string m_sps; - string m_pps; }; #endif //ZLMEDIAKIT_H264RTMPCODEC_H diff --git a/src/Rtsp/RtspToRtmpMediaSource.cpp b/src/Rtsp/RtspToRtmpMediaSource.cpp index 38eccf30..e9001522 100644 --- a/src/Rtsp/RtspToRtmpMediaSource.cpp +++ b/src/Rtsp/RtspToRtmpMediaSource.cpp @@ -126,7 +126,7 @@ void RtspToRtmpMediaSource::onGetH264(const H264Frame& frame) { rtmpPkt->typeId = MSG_VIDEO; m_pRtmpSrc->onGetMedia(rtmpPkt); } -void RtspToRtmpMediaSource::onGetAdts(const AACFrame& frame) { +void RtspToRtmpMediaSource::onGetAAC(const AACFrame& frame) { if(m_pRecorder){ m_pRecorder->inputAAC((char *) frame.buffer, frame.aac_frame_length, frame.timeStamp); } diff --git a/src/Rtsp/RtspToRtmpMediaSource.h b/src/Rtsp/RtspToRtmpMediaSource.h index 2ff057cc..35c9f336 100644 --- a/src/Rtsp/RtspToRtmpMediaSource.h +++ b/src/Rtsp/RtspToRtmpMediaSource.h @@ -55,7 +55,7 @@ public: m_pParser.reset(new RtpParser(strSdp)); m_pRecorder.reset(new MediaRecorder(getVhost(),getApp(),getId(),m_pParser,m_bEnableHls,m_bEnableMp4)); //todo(xzl) 修复此处 -// m_pParser->setOnAudioCB( std::bind(&RtspToRtmpMediaSource::onGetAdts, this, placeholders::_1)); +// m_pParser->setOnAudioCB( std::bind(&RtspToRtmpMediaSource::onGetAAC, this, placeholders::_1)); // m_pParser->setOnVideoCB( std::bind(&RtspToRtmpMediaSource::onGetH264, this, placeholders::_1)); makeMetaData(); } catch (exception &ex) { @@ -94,7 +94,7 @@ public: protected: void onGetH264(const H264Frame &frame); - void onGetAdts(const AACFrame &frame); + void onGetAAC(const AACFrame &frame); private: void makeVideoConfigPkt(); void makeAudioConfigPkt();