完善对高规格aac的支持

This commit is contained in:
xiongziliang 2020-06-11 19:21:46 +08:00
parent b9006a90d4
commit efa92752c7
6 changed files with 107 additions and 66 deletions

View File

@ -9,6 +9,9 @@
*/
#include "AAC.h"
#ifdef ENABLE_MP4
#include "mpeg4-aac.h"
#endif
namespace mediakit{
@ -89,7 +92,8 @@ static void parseAacConfig(const string &config, AdtsHeader &adts) {
adts.no_raw_data_blocks_in_frame = 0;
}
string makeAacConfig(const uint8_t *hex){
string makeAacConfig(const uint8_t *hex, int length){
#ifndef ENABLE_MP4
if (!(hex[0] == 0xFF && (hex[1] & 0xF0) == 0xF0)) {
return "";
}
@ -112,20 +116,58 @@ string makeAacConfig(const uint8_t *hex){
audioSpecificConfig[0] = (audioObjectType << 3) | (sampling_frequency_index >> 1);
audioSpecificConfig[1] = (sampling_frequency_index << 7) | (channel_configuration << 3);
return string((char *)audioSpecificConfig,2);
#else
struct mpeg4_aac_t aac = {0};
if (mpeg4_aac_adts_load(hex, length, &aac) > 0) {
char buf[32] = {0};
int len = mpeg4_aac_audio_specific_config_save(&aac, (uint8_t *) buf, sizeof(buf));
if (len > 0) {
return string(buf, len);
}
}
WarnL << "生成aac config失败, adts header:" << hexdump(hex, length);
return "";
#endif
}
void dumpAacConfig(const string &config, int length, uint8_t *out){
int dumpAacConfig(const string &config, int length, uint8_t *out, int out_size) {
#ifndef ENABLE_MP4
AdtsHeader header;
parseAacConfig(config, header);
header.aac_frame_length = length;
dumpAdtsHeader(header, out);
return ADTS_HEADER_LEN;
#else
struct mpeg4_aac_t aac = {0};
int ret = mpeg4_aac_audio_specific_config_load((uint8_t *) config.data(), config.size(), &aac);
if (ret > 0) {
ret = mpeg4_aac_adts_save(&aac, length, out, out_size);
}
if (ret < 0) {
WarnL << "生成adts头失败:" << ret << ", aac config:" << hexdump(config.data(), config.size());
}
return ret;
#endif
}
void parseAacConfig(const string &config, int &samplerate, int &channels){
bool parseAacConfig(const string &config, int &samplerate, int &channels){
#ifndef ENABLE_MP4
AdtsHeader header;
parseAacConfig(config, header);
samplerate = samplingFrequencyTable[header.sf_index];
channels = header.channel_configuration;
return true;
#else
struct mpeg4_aac_t aac = {0};
int ret = mpeg4_aac_audio_specific_config_load((uint8_t *) config.data(), config.size(), &aac);
if (ret > 0) {
samplerate = aac.sampling_frequency;
channels = aac.channels;
return true;
}
WarnL << "获取aac采样率、声道数失败:" << hexdump(config.data(), config.size());
return false;
#endif
}
Sdp::Ptr AACTrack::getSdp() {

View File

@ -17,9 +17,9 @@
namespace mediakit{
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);
string makeAacConfig(const uint8_t *hex, int length);
int dumpAacConfig(const string &config, int length, uint8_t *out, int out_size);
bool parseAacConfig(const string &config, int &samplerate, int &channels);
/**
* aac帧adts头
@ -137,9 +137,9 @@ public:
void inputFrame(const Frame::Ptr &frame) override{
if (_cfg.empty()) {
//未获取到aac_cfg信息
if (frame->prefixSize() >= ADTS_HEADER_LEN) {
if (frame->prefixSize()) {
//7个字节的adts头
_cfg = makeAacConfig((uint8_t *) (frame->data()));
_cfg = makeAacConfig((uint8_t *) (frame->data()), frame->prefixSize());
onReady();
} else {
WarnL << "无法获取adts头!";

View File

@ -13,20 +13,6 @@
namespace mediakit{
AACRtmpDecoder::AACRtmpDecoder(const Track::Ptr &track) {
_frame = obtainFrame();
_track = dynamic_pointer_cast<AACTrack>(track);
}
AACFrame::Ptr AACRtmpDecoder::obtainFrame() {
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto frame = ResourcePoolHelper<AACFrame>::obtainObj();
frame->_prefix_size = ADTS_HEADER_LEN;
//预留7个字节的空位以便后续覆盖
frame->_buffer.assign(ADTS_HEADER_LEN,(char)0);
return frame;
}
static string getAacCfg(const RtmpPacket &thiz) {
string ret;
if (thiz.getMediaType() != FLV_CODEC_AAC) {
@ -46,12 +32,6 @@ static string getAacCfg(const RtmpPacket &thiz) {
bool AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool) {
if (pkt->isCfgFrame()) {
_aac_cfg = getAacCfg(*pkt);
if (_track) {
//设置aac config
_track->setAacCfg(_aac_cfg);
//不再强引用
_track = nullptr;
}
return false;
}
if (!_aac_cfg.empty()) {
@ -61,20 +41,30 @@ bool AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool) {
}
void AACRtmpDecoder::onGetAAC(const char* data, int len, uint32_t stamp) {
_frame->_dts = stamp;
//先追加数据
_frame->_buffer.append(data, len);
//覆盖adts头
dumpAacConfig(_aac_cfg, _frame->size(), (uint8_t *) _frame->data());
auto frame = ResourcePoolHelper<AACFrame>::obtainObj();
//生成adts头
char adts_header[32] = {0};
auto size = dumpAacConfig(_aac_cfg, len, (uint8_t *) adts_header, sizeof(adts_header));
if (size > 0) {
frame->_buffer.assign(adts_header, size);
frame->_prefix_size = size;
} else {
frame->_buffer.clear();
frame->_prefix_size = 0;
}
//追加负载数据
frame->_buffer.append(data, len);
frame->_dts = stamp;
//写入环形缓存
RtmpCodec::inputFrame(_frame);
_frame = obtainFrame();
RtmpCodec::inputFrame(frame);
}
/////////////////////////////////////////////////////////////////////////////////////
AACRtmpEncoder::AACRtmpEncoder(const Track::Ptr &track): AACRtmpDecoder(track) {
AACRtmpEncoder::AACRtmpEncoder(const Track::Ptr &track) {
_track = dynamic_pointer_cast<AACTrack>(track);
}
@ -91,9 +81,9 @@ void AACRtmpEncoder::makeConfigPacket() {
void AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) {
if (_aac_cfg.empty()) {
if (frame->prefixSize() >= 7) {
if (frame->prefixSize()) {
//包含adts头,从adts头获取aac配置信息
_aac_cfg = makeAacConfig((uint8_t *) (frame->data()));
_aac_cfg = makeAacConfig((uint8_t *) (frame->data()), frame->prefixSize());
}
makeConfigPacket();
}

View File

@ -23,7 +23,7 @@ class AACRtmpDecoder : public RtmpCodec , public ResourcePoolHelper<AACFrame> {
public:
typedef std::shared_ptr<AACRtmpDecoder> Ptr;
AACRtmpDecoder(const Track::Ptr &track);
AACRtmpDecoder() {}
~AACRtmpDecoder() {}
/**
@ -37,13 +37,10 @@ public:
return CodecAAC;
}
protected:
private:
void onGetAAC(const char *data, int len, uint32_t stamp);
AACFrame::Ptr obtainFrame();
protected:
AACFrame::Ptr _frame;
AACTrack::Ptr _track;
private:
string _aac_cfg;
};
@ -80,6 +77,8 @@ private:
private:
uint8_t _audio_flv_flags;
AACTrack::Ptr _track;
string _aac_cfg;
};
}//namespace mediakit

View File

@ -68,18 +68,18 @@ AACRtpDecoder::AACRtpDecoder(const Track::Ptr &track){
} else {
_aac_cfg = aacTrack->getAacCfg();
}
_adts = obtainFrame();
_frame = obtainFrame();
}
AACRtpDecoder::AACRtpDecoder() {
_adts = obtainFrame();
_frame = obtainFrame();
}
AACFrame::Ptr AACRtpDecoder::obtainFrame() {
//从缓存池重新申请对象,防止覆盖已经写入环形缓存的对象
auto frame = ResourcePoolHelper<AACFrame>::obtainObj();
frame->_prefix_size = ADTS_HEADER_LEN;
//预留7个字节的空位以便后续覆盖
frame->_buffer.assign(ADTS_HEADER_LEN,(char)0);
frame->_prefix_size = 0;
frame->_buffer.clear();
return frame;
}
@ -94,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 = AAC_MAX_FRAME_SIZE - ADTS_HEADER_LEN;
while (ptr < end) {
auto size = (uint32_t) (end - ptr);
if(size > max_size){
size = max_size;
if (size > AAC_MAX_FRAME_SIZE) {
size = AAC_MAX_FRAME_SIZE;
}
if (_adts->size() + size > AAC_MAX_FRAME_SIZE) {
if (_frame->size() + size > AAC_MAX_FRAME_SIZE) {
//数据太多了,先清空
flushData();
}
//追加aac数据
_adts->_buffer.append((char *)ptr, size);
_adts->_dts = rtppack->timeStamp;
_frame->_buffer.append((char *) ptr, size);
_frame->_dts = rtppack->timeStamp;
ptr += size;
}
@ -118,15 +117,21 @@ bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) {
}
void AACRtpDecoder::flushData() {
if (_adts->size() == ADTS_HEADER_LEN) {
if (_frame->_buffer.empty()) {
//没有有效数据
return;
}
//覆盖adts头
dumpAacConfig(_aac_cfg, _adts->size(), (uint8_t *) _adts->data());
RtpCodec::inputFrame(_adts);
_adts = obtainFrame();
//插入adts头
char adts_header[32] = {0};
auto size = dumpAacConfig(_aac_cfg, _frame->_buffer.size(), (uint8_t *) adts_header, sizeof(adts_header));
if (size > 0) {
//插入adts头
_frame->_buffer.insert(0, adts_header, size);
_frame->_prefix_size = size;
}
RtpCodec::inputFrame(_frame);
_frame = obtainFrame();
}

View File

@ -34,13 +34,16 @@ public:
CodecId getCodecId() const override {
return CodecAAC;
}
protected:
AACRtpDecoder();
private:
AACFrame::Ptr obtainFrame();
void flushData();
private:
AACFrame::Ptr _adts;
AACFrame::Ptr _frame;
string _aac_cfg;
};
@ -71,8 +74,10 @@ public:
* @param frame dats头的aac数据
*/
void inputFrame(const Frame::Ptr &frame) override;
private:
void makeAACRtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp);
private:
unsigned char _aucSectionBuf[1600];
};