From 70e9a20352ad97e1c0dd5d1776f40b9281a2f906 Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Mon, 11 May 2020 23:25:12 +0800 Subject: [PATCH] =?UTF-8?q?=E7=B2=BE=E7=AE=80aac=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Extension/AAC.cpp | 144 ++++++++++++++++++++++---------------- src/Extension/AAC.h | 71 ++++--------------- src/Extension/AACRtmp.cpp | 31 ++++---- src/Extension/AACRtmp.h | 2 +- src/Extension/AACRtp.cpp | 22 +++--- 5 files changed, 120 insertions(+), 150 deletions(-) diff --git a/src/Extension/AAC.cpp b/src/Extension/AAC.cpp index 282bd2f0..71bbd5d0 100644 --- a/src/Extension/AAC.cpp +++ b/src/Extension/AAC.cpp @@ -12,62 +12,55 @@ namespace mediakit{ -void writeAdtsHeader(const AACFrame &hed, uint8_t *pcAdts) { - pcAdts[0] = (hed.syncword >> 4 & 0xFF); //8bit - pcAdts[1] = (hed.syncword << 4 & 0xF0); //4 bit - pcAdts[1] |= (hed.id << 3 & 0x08); //1 bit - pcAdts[1] |= (hed.layer << 1 & 0x06); //2bit - pcAdts[1] |= (hed.protection_absent & 0x01); //1 bit +class AdtsHeader{ +public: + unsigned int syncword = 0; //12 bslbf 同步字The bit string ‘1111 1111 1111’,说明一个ADTS帧的开始 + unsigned int id; //1 bslbf MPEG 标示符, 设置为1 + unsigned int layer; //2 uimsbf Indicates which layer is used. Set to ‘00’ + unsigned int protection_absent; //1 bslbf 表示是否误码校验 + unsigned int profile; //2 uimsbf 表示使用哪个级别的AAC,如01 Low Complexity(LC)--- AACLC + unsigned int sf_index; //4 uimsbf 表示使用的采样率下标 + unsigned int private_bit; //1 bslbf + unsigned int channel_configuration; //3 uimsbf 表示声道数 + unsigned int original; //1 bslbf + unsigned int home; //1 bslbf + //下面的为改变的参数即每一帧都不同 + unsigned int copyright_identification_bit; //1 bslbf + unsigned int copyright_identification_start; //1 bslbf + unsigned int aac_frame_length; // 13 bslbf 一个ADTS帧的长度包括ADTS头和raw data block + unsigned int adts_buffer_fullness; //11 bslbf 0x7FF 说明是码率可变的码流 + //no_raw_data_blocks_in_frame 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧. + //所以说number_of_raw_data_blocks_in_frame == 0 + //表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据) + unsigned int no_raw_data_blocks_in_frame; //2 uimsfb +}; - pcAdts[2] = (hed.profile << 6 & 0xC0); // 2 bit - pcAdts[2] |= (hed.sf_index << 2 & 0x3C); //4bit - pcAdts[2] |= (hed.private_bit << 1 & 0x02); //1 bit - pcAdts[2] |= (hed.channel_configuration >> 2 & 0x03); //1 bit - - pcAdts[3] = (hed.channel_configuration << 6 & 0xC0); // 2 bit - pcAdts[3] |= (hed.original << 5 & 0x20); //1 bit - pcAdts[3] |= (hed.home << 4 & 0x10); //1 bit - pcAdts[3] |= (hed.copyright_identification_bit << 3 & 0x08); //1 bit - pcAdts[3] |= (hed.copyright_identification_start << 2 & 0x04); //1 bit - pcAdts[3] |= (hed.aac_frame_length >> 11 & 0x03); //2 bit - - pcAdts[4] = (hed.aac_frame_length >> 3 & 0xFF); //8 bit - - pcAdts[5] = (hed.aac_frame_length << 5 & 0xE0); //3 bit - pcAdts[5] |= (hed.adts_buffer_fullness >> 6 & 0x1F); //5 bit - - pcAdts[6] = (hed.adts_buffer_fullness << 2 & 0xFC); //6 bit - pcAdts[6] |= (hed.no_raw_data_blocks_in_frame & 0x03); //2 bit +static void dumpAdtsHeader(const AdtsHeader &hed, uint8_t *out) { + out[0] = (hed.syncword >> 4 & 0xFF); //8bit + out[1] = (hed.syncword << 4 & 0xF0); //4 bit + out[1] |= (hed.id << 3 & 0x08); //1 bit + out[1] |= (hed.layer << 1 & 0x06); //2bit + out[1] |= (hed.protection_absent & 0x01); //1 bit + out[2] = (hed.profile << 6 & 0xC0); // 2 bit + out[2] |= (hed.sf_index << 2 & 0x3C); //4bit + out[2] |= (hed.private_bit << 1 & 0x02); //1 bit + out[2] |= (hed.channel_configuration >> 2 & 0x03); //1 bit + out[3] = (hed.channel_configuration << 6 & 0xC0); // 2 bit + out[3] |= (hed.original << 5 & 0x20); //1 bit + out[3] |= (hed.home << 4 & 0x10); //1 bit + out[3] |= (hed.copyright_identification_bit << 3 & 0x08); //1 bit + out[3] |= (hed.copyright_identification_start << 2 & 0x04); //1 bit + out[3] |= (hed.aac_frame_length >> 11 & 0x03); //2 bit + out[4] = (hed.aac_frame_length >> 3 & 0xFF); //8 bit + out[5] = (hed.aac_frame_length << 5 & 0xE0); //3 bit + out[5] |= (hed.adts_buffer_fullness >> 6 & 0x1F); //5 bit + out[6] = (hed.adts_buffer_fullness << 2 & 0xFC); //6 bit + out[6] |= (hed.no_raw_data_blocks_in_frame & 0x03); //2 bit } -string makeAdtsConfig(const uint8_t *pcAdts){ - if (!(pcAdts[0] == 0xFF && (pcAdts[1] & 0xF0) == 0xF0)) { - return ""; - } - // Get and check the 'profile': - unsigned char profile = (pcAdts[2] & 0xC0) >> 6; // 2 bits - if (profile == 3) { - return ""; - } - // Get and check the 'sampling_frequency_index': - unsigned char sampling_frequency_index = (pcAdts[2] & 0x3C) >> 2; // 4 bits - if (samplingFrequencyTable[sampling_frequency_index] == 0) { - return ""; - } - - // Get and check the 'channel_configuration': - unsigned char channel_configuration = ((pcAdts[2] & 0x01) << 2) - | ((pcAdts[3] & 0xC0) >> 6); // 3 bits - - unsigned char audioSpecificConfig[2]; - unsigned char const audioObjectType = profile + 1; - audioSpecificConfig[0] = (audioObjectType << 3) | (sampling_frequency_index >> 1); - audioSpecificConfig[1] = (sampling_frequency_index << 7) | (channel_configuration << 3); - return string((char *)audioSpecificConfig,2); -} -void makeAdtsHeader(const string &strAudioCfg,AACFrame &adts) { - uint8_t cfg1 = strAudioCfg[0]; - uint8_t cfg2 = strAudioCfg[1]; +static void parseAacConfig(const string &config, AdtsHeader &adts) { + uint8_t cfg1 = config[0]; + uint8_t cfg2 = config[1]; int audioObjectType; int sampling_frequency_index; @@ -93,9 +86,44 @@ void makeAdtsHeader(const string &strAudioCfg,AACFrame &adts) { adts.adts_buffer_fullness = 2047; adts.no_raw_data_blocks_in_frame = 0; } -void getAACInfo(const AACFrame &adts,int &iSampleRate,int &iChannel){ - iSampleRate = samplingFrequencyTable[adts.sf_index]; - iChannel = adts.channel_configuration; + +string makeAacConfig(const uint8_t *hex){ + if (!(hex[0] == 0xFF && (hex[1] & 0xF0) == 0xF0)) { + return ""; + } + // Get and check the 'profile': + unsigned char profile = (hex[2] & 0xC0) >> 6; // 2 bits + if (profile == 3) { + return ""; + } + + // Get and check the 'sampling_frequency_index': + unsigned char sampling_frequency_index = (hex[2] & 0x3C) >> 2; // 4 bits + if (samplingFrequencyTable[sampling_frequency_index] == 0) { + return ""; + } + + // Get and check the 'channel_configuration': + unsigned char channel_configuration = ((hex[2] & 0x01) << 2) | ((hex[3] & 0xC0) >> 6); // 3 bits + unsigned char audioSpecificConfig[2]; + unsigned char const audioObjectType = profile + 1; + audioSpecificConfig[0] = (audioObjectType << 3) | (sampling_frequency_index >> 1); + audioSpecificConfig[1] = (sampling_frequency_index << 7) | (channel_configuration << 3); + return string((char *)audioSpecificConfig,2); +} + +void dumpAacConfig(const string &config, int length, uint8_t *out){ + AdtsHeader header; + parseAacConfig(config, header); + header.aac_frame_length = length; + dumpAdtsHeader(header, out); +} + +void parseAacConfig(const string &config, int &samplerate, int &channels){ + AdtsHeader header; + parseAacConfig(config, header); + samplerate = samplingFrequencyTable[header.sf_index]; + channels = header.channel_configuration; } Sdp::Ptr AACTrack::getSdp() { @@ -106,6 +134,4 @@ Sdp::Ptr AACTrack::getSdp() { return std::make_shared(getAacCfg(),getAudioSampleRate(), getAudioChannel()); } -}//namespace mediakit - - +}//namespace mediakit \ No newline at end of file diff --git a/src/Extension/AAC.h b/src/Extension/AAC.h index 40a3b6c2..fa83722c 100644 --- a/src/Extension/AAC.h +++ b/src/Extension/AAC.h @@ -13,71 +13,26 @@ #include "Frame.h" #include "Track.h" +#define ADTS_HEADER_LEN 7 namespace mediakit{ class AACFrame; unsigned const samplingFrequencyTable[16] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350, 0, 0, 0 }; -void makeAdtsHeader(const string &strAudioCfg,AACFrame &adts); -void writeAdtsHeader(const AACFrame &adts, uint8_t *pcAdts) ; -string makeAdtsConfig(const uint8_t *pcAdts); -void getAACInfo(const AACFrame &adts,int &iSampleRate,int &iChannel); +string makeAacConfig(const uint8_t *hex); +void dumpAacConfig(const string &config, int length, uint8_t *out); +void parseAacConfig(const string &config, int &samplerate, int &channels); /** * aac帧,包含adts头 */ -class AACFrame : public Frame { +class AACFrame : public FrameImp { public: typedef std::shared_ptr Ptr; - - char *data() const override{ - return (char *)buffer; + AACFrame(){ + _codecid = CodecAAC; } - uint32_t size() const override { - return aac_frame_length; - } - uint32_t dts() const override { - return _dts; - } - uint32_t prefixSize() const override{ - return _prefix_size; - } - - CodecId getCodecId() const override{ - return CodecAAC; - } - - bool keyFrame() const override { - return false; - } - - bool configFrame() const override{ - return false; - } -public: - unsigned int syncword = 0; //12 bslbf 同步字The bit string ‘1111 1111 1111’,说明一个ADTS帧的开始 - unsigned int id; //1 bslbf MPEG 标示符, 设置为1 - unsigned int layer; //2 uimsbf Indicates which layer is used. Set to ‘00’ - unsigned int protection_absent; //1 bslbf 表示是否误码校验 - unsigned int profile; //2 uimsbf 表示使用哪个级别的AAC,如01 Low Complexity(LC)--- AACLC - unsigned int sf_index; //4 uimsbf 表示使用的采样率下标 - unsigned int private_bit; //1 bslbf - unsigned int channel_configuration; //3 uimsbf 表示声道数 - unsigned int original; //1 bslbf - unsigned int home; //1 bslbf - //下面的为改变的参数即每一帧都不同 - unsigned int copyright_identification_bit; //1 bslbf - unsigned int copyright_identification_start; //1 bslbf - unsigned int aac_frame_length; // 13 bslbf 一个ADTS帧的长度包括ADTS头和raw data block - unsigned int adts_buffer_fullness; //11 bslbf 0x7FF 说明是码率可变的码流 - //no_raw_data_blocks_in_frame 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧. - //所以说number_of_raw_data_blocks_in_frame == 0 - //表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据) - unsigned int no_raw_data_blocks_in_frame; //2 uimsfb - unsigned char buffer[2 * 1024 + 7]; - uint32_t _dts; - uint32_t _prefix_size = 7; }; class AACFrameNoCacheAble : public FrameFromPtr { @@ -138,7 +93,7 @@ public: if(adts_header_len < 7){ throw std::invalid_argument("adts头必须不少于7个字节"); } - _cfg = makeAdtsConfig((uint8_t*)adts_header); + _cfg = makeAacConfig((uint8_t *) adts_header); onReady(); } @@ -150,7 +105,7 @@ public: if(aac_frame_with_adts->getCodecId() != CodecAAC || aac_frame_with_adts->prefixSize() < 7){ throw std::invalid_argument("必须输入带adts头的aac帧"); } - _cfg = makeAdtsConfig((uint8_t*)aac_frame_with_adts->data()); + _cfg = makeAacConfig((uint8_t *) aac_frame_with_adts->data()); onReady(); } @@ -205,7 +160,7 @@ public: //未获取到aac_cfg信息 if (frame->prefixSize() >= 7) { //7个字节的adts头 - _cfg = makeAdtsConfig((uint8_t *)(frame->data())); + _cfg = makeAacConfig((uint8_t *) (frame->data())); onReady(); } else { WarnL << "无法获取adts头!"; @@ -218,12 +173,10 @@ private: * 解析2个字节的aac配置 */ void onReady(){ - if(_cfg.size() < 2){ + if (_cfg.size() < 2) { return; } - AACFrame aacFrame; - makeAdtsHeader(_cfg,aacFrame); - getAACInfo(aacFrame,_sampleRate,_channel); + parseAacConfig(_cfg, _sampleRate, _channel); } Track::Ptr clone() override { diff --git a/src/Extension/AACRtmp.cpp b/src/Extension/AACRtmp.cpp index 0367664f..2009dbc9 100644 --- a/src/Extension/AACRtmp.cpp +++ b/src/Extension/AACRtmp.cpp @@ -20,8 +20,9 @@ AACRtmpDecoder::AACRtmpDecoder() { AACFrame::Ptr AACRtmpDecoder::obtainFrame() { //从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象 auto frame = ResourcePoolHelper::obtainObj(); - frame->aac_frame_length = 7; - frame->_prefix_size = 7; + frame->_prefix_size = ADTS_HEADER_LEN; + //预留7个字节的空位以便后续覆盖 + frame->_buffer.assign(ADTS_HEADER_LEN,(char)0); return frame; } @@ -41,7 +42,7 @@ static string getAacCfg(const RtmpPacket &thiz) { return ret; } -bool AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool key_pos) { +bool AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool) { if (pkt->isCfgFrame()) { _aac_cfg = getAacCfg(*pkt); return false; @@ -52,26 +53,18 @@ bool AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool key_pos) { 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->_dts = ui32TimeStamp; - - //adts结构头转成头7个字节 - writeAdtsHeader(*_adts, _adts->buffer); +void AACRtmpDecoder::onGetAAC(const char* data, int len, uint32_t stamp) { + _adts->_dts = stamp; + //先追加数据 + _adts->_buffer.append(data, len); + //覆盖adts头 + dumpAacConfig(_aac_cfg, _adts->size(), (uint8_t *) _adts->data()); //写入环形缓存 RtmpCodec::inputFrame(_adts); _adts = obtainFrame(); } + ///////////////////////////////////////////////////////////////////////////////////// AACRtmpEncoder::AACRtmpEncoder(const Track::Ptr &track) { @@ -93,7 +86,7 @@ void AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) { if (_aac_cfg.empty()) { if (frame->prefixSize() >= 7) { //包含adts头,从adts头获取aac配置信息 - _aac_cfg = makeAdtsConfig((uint8_t *)(frame->data())); + _aac_cfg = makeAacConfig((uint8_t *) (frame->data())); } makeConfigPacket(); } diff --git a/src/Extension/AACRtmp.h b/src/Extension/AACRtmp.h index 207fc18f..653ac122 100644 --- a/src/Extension/AACRtmp.h +++ b/src/Extension/AACRtmp.h @@ -38,7 +38,7 @@ public: } protected: - void onGetAAC(const char* pcData, int iLen, uint32_t ui32TimeStamp); + void onGetAAC(const char* data, int len, uint32_t stamp); AACFrame::Ptr obtainFrame(); protected: AACFrame::Ptr _adts; diff --git a/src/Extension/AACRtp.cpp b/src/Extension/AACRtp.cpp index b3d7cc1b..3baadb36 100644 --- a/src/Extension/AACRtp.cpp +++ b/src/Extension/AACRtp.cpp @@ -9,7 +9,7 @@ */ #include "AACRtp.h" -#define ADTS_HEADER_LEN 7 +#define AAC_MAX_FRAME_SIZE (2 * 1024) namespace mediakit{ @@ -77,11 +77,9 @@ AACRtpDecoder::AACRtpDecoder() { AACFrame::Ptr AACRtpDecoder::obtainFrame() { //从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象 auto frame = ResourcePoolHelper::obtainObj(); - frame->aac_frame_length = ADTS_HEADER_LEN; frame->_prefix_size = ADTS_HEADER_LEN; - if(frame->syncword == 0 && !_aac_cfg.empty()) { - makeAdtsHeader(_aac_cfg,*frame); - } + //预留7个字节的空位以便后续覆盖 + frame->_buffer.assign(ADTS_HEADER_LEN,(char)0); return frame; } @@ -96,19 +94,18 @@ bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) { //忽略Au-Header区 ptr += 2 + au_header_count * 2; - static const uint32_t max_size = sizeof(AACFrame::buffer) - ADTS_HEADER_LEN; + static const uint32_t max_size = AAC_MAX_FRAME_SIZE - ADTS_HEADER_LEN; while (ptr < end) { auto size = (uint32_t) (end - ptr); if(size > max_size){ size = max_size; } - if (_adts->aac_frame_length + size > sizeof(AACFrame::buffer)) { + if (_adts->size() + size > AAC_MAX_FRAME_SIZE) { //数据太多了,先清空 flushData(); } //追加aac数据 - memcpy(_adts->buffer + _adts->aac_frame_length, ptr, size); - _adts->aac_frame_length += size; + _adts->_buffer.append((char *)ptr, size); _adts->_dts = rtppack->timeStamp; ptr += size; } @@ -120,13 +117,14 @@ bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) { return false; } - void AACRtpDecoder::flushData() { - if(_adts->aac_frame_length == ADTS_HEADER_LEN){ + if (_adts->size() == ADTS_HEADER_LEN) { //没有有效数据 return; } - writeAdtsHeader(*_adts, _adts->buffer); + + //覆盖adts头 + dumpAacConfig(_aac_cfg, _adts->size(), (uint8_t *) _adts->data()); RtpCodec::inputFrame(_adts); _adts = obtainFrame(); }