146 lines
4.3 KiB
C++
146 lines
4.3 KiB
C++
|
#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<4C><43>MediaCodecInfo.CodecProfileLevel.AACObjectLC;
|
|||
|
int freqIdx = 4; //32K, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>avpriv_mpeg4audio_sample_rates<65><73>32000<30><30>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>±꣬<C2B1><EAA3AC><EFBFBD><EFBFBD>ffmpegԴ<67><D4B4>
|
|||
|
int chanCfg = channels; //<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ע<EFBFBD><D7A2>channel_configuration<6F><6E>Stero˫<6F><CBAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
|||
|
|
|||
|
/*int avpriv_mpeg4audio_sample_rates[] = {
|
|||
|
96000, 88200, 64000, 48000, 44100, 32000,
|
|||
|
24000, 22050, 16000, 12000, 11025, 8000, 7350
|
|||
|
};
|
|||
|
channel_configuration: <EFBFBD><EFBFBD>ʾ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>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;
|
|||
|
}
|