#include "AACAudioCoder.h" //#include "Debuger.h" using namespace AAC_CODER; AACAudioCoder::~AACAudioCoder() { } void AACAudioCoder::OnAudioData(const void *frameaddress, uint32_t framelen) { this->Encode((unsigned char *)frameaddress, framelen * 4); } AACAudioCoder::AACAudioCoder(unsigned int smprate, unsigned int channel) { AVCodecID codec_id = AV_CODEC_ID_AAC; pCodec = (AVCodec *)avcodec_find_encoder_by_name("libfdk_aac"); if (!pCodec) { printf("Codec not found\n"); this->mStatus = FAIL; } mCodecCtx = avcodec_alloc_context3(pCodec); if (!mCodecCtx) { printf("Could not allocate video codec context\n"); this->mStatus = FAIL; } mCodecCtx->codec_id = pCodec->id; mCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO; mCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16; ///< float mCodecCtx->sample_rate = 44100; mCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO; mCodecCtx->channels = 2; mCodecCtx->bit_rate = 640000; mCodecCtx->time_base.den = 1; mCodecCtx->time_base.num = 23; mCodecCtx->frame_size = 1024; this->mObserver = nullptr; if (avcodec_open2(mCodecCtx, pCodec, NULL) < 0) { this->mStatus = FAIL; } mFrame = av_frame_alloc(); mFrame->nb_samples = mCodecCtx->frame_size; mFrame->format = mCodecCtx->sample_fmt; int size = av_samples_get_buffer_size(NULL, mCodecCtx->channels, mCodecCtx->frame_size, mCodecCtx->sample_fmt, 1); mFrameBuf = (uint8_t *)av_malloc(size); avcodec_fill_audio_frame(mFrame, mCodecCtx->channels, mCodecCtx->sample_fmt, (const uint8_t*)mFrameBuf, size, 1); mPts = 0; } int adts_sample_rates[]={96000,882000,64000,48000,441000,32000,24000,22050,16000,12000,11025,8000,7350,0,0,0}; int FindAdstSRIndex(int samplerate) { int i; for (i = 0; i < 16; i++) { if (samplerate == adts_sample_rates[i]) return i; } return 16 - 1; } #define ADTS_HEAD_LEN 7 void MakeAdtsHeader(unsigned char *data, int samplerate, int channels, int iFrameLen) { int profile = 2; //AAC LC,MediaCodecInfo.CodecProfileLevel.AACObjectLC; int freqIdx = 4; //32K, 见后面注释avpriv_mpeg4audio_sample_rates中32000对应的数组下标,来自ffmpeg源码 int chanCfg = channels; //见后面注释channel_configuration,Stero双声道立体声 /*int avpriv_mpeg4audio_sample_rates[] = { 96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350 }; channel_configuration: 表示声道数chanCfg 0: Defined in AOT Specifc Config 1: 1 channel: front-center 2: 2 channels: front-left, front-right 3: 3 channels: front-center, front-left, front-right 4: 4 channels: front-center, front-left, front-right, back-center 5: 5 channels: front-center, front-left, front-right, back-left, back-right 6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel 7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel 8-15: Reserved */ // fill in ADTS data data[0] = (uint8_t)0xFF; data[1] = (uint8_t)0xF9; data[2] = (uint8_t)(((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2)); data[3] = (uint8_t)(((chanCfg & 3) << 6) + (iFrameLen >> 11)); data[4] = (uint8_t)((iFrameLen & 0x7FF) >> 3); data[5] = (uint8_t)(((iFrameLen & 7) << 5) + 0x1F); data[6] = (uint8_t)0xFC; } FILE *ptest = nullptr; int once = 1; int AACAudioCoder::Encode( unsigned char *input, unsigned int num) { mFrame->nb_samples = mCodecCtx->frame_size; mFrame->format = mCodecCtx->sample_fmt; avcodec_fill_audio_frame(mFrame, mCodecCtx->channels, mCodecCtx->sample_fmt, input, num, 1); int aac_out_len = 0; unsigned char*aac_buf; if (nullptr == input) { return -1; } if (nullptr == ptest) { ptest = fopen("dst.aac", "wb"); } av_init_packet(&pkt); pkt.data = NULL; // packet data will be allocated by the encoder pkt.size = 0; int got_output = 0; mFrame->pts = mPts += 23; int ret = avcodec_encode_audio2(mCodecCtx, &pkt, mFrame, &got_output); if (ret < 0) { printf("Error encoding frame\n"); return -1; } if (got_output) { if (nullptr != mObserver) { mObserver->OnAudioEncode(pkt.data, pkt.size, mFrame->pts); } fwrite(pkt.data, 1, pkt.size, ptest); av_free_packet(&pkt); } return 0; } int AAC_CODER::AACAudioCoder::SetObserver(EncodeAudioObserver *p) { if (nullptr == this->mObserver) { this->mObserver = p; } return 0; }