139 lines
3.6 KiB
C++
139 lines
3.6 KiB
C++
#include "AACDecoder.h"
|
|
#include "Debuger.h"
|
|
|
|
|
|
void AACDecoder::OnRtmpFrame(void * dat, uint32_t size)
|
|
{
|
|
this->Decode((uint8_t *)dat, size);
|
|
}
|
|
AACDecoder::AACDecoder() :mObserver(nullptr)
|
|
{
|
|
mStatus = RUNNING;
|
|
this->mObserverType = Observer_Audio;
|
|
mCodec = avcodec_find_decoder(AV_CODEC_ID_AAC);
|
|
if (mCodec == NULL) {
|
|
Debuger::Debug(L"find codec fail\r\n");
|
|
mStatus = FAIL;
|
|
}
|
|
mCodecCtx = avcodec_alloc_context3(mCodec);
|
|
if (nullptr == mCodecCtx) {
|
|
Debuger::Debug(L"find codec ctx fail\r\n");
|
|
mStatus = FAIL;
|
|
}
|
|
mCodecCtx->codec = mCodec;
|
|
mCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
|
|
mCodecCtx->sample_rate = 44100;
|
|
mCodecCtx->channels = 2;
|
|
mCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO;
|
|
mCodecCtx->sample_fmt = AV_SAMPLE_FMT_FLTP;
|
|
mCodecCtx->frame_size = 2048;
|
|
#if LIBSWRESAMPLE_VERSION_MINOR >= 17 // 根据版本不同,选用适当函数
|
|
mSwrCtx = swr_alloc();
|
|
|
|
av_opt_set_int(mSwrCtx, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0);
|
|
av_opt_set_int(mSwrCtx, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
|
|
av_opt_set_int(mSwrCtx, "in_sample_rate", 44100, 0);
|
|
av_opt_set_int(mSwrCtx, "out_sample_rate", 44100, 0);
|
|
av_opt_set_sample_fmt(mSwrCtx, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);
|
|
av_opt_set_sample_fmt(mSwrCtx, "out_sample_fmt", AV_SAMPLE_FMT_S16, 0);
|
|
swr_init(mSwrCtx);
|
|
|
|
#else
|
|
mSwrCtx = swr_alloc();
|
|
|
|
mSwrCtx = swr_alloc_set_opts(mSwrCtx,
|
|
AV_CH_LAYOUT_STEREO, //output
|
|
AV_SAMPLE_FMT_S16,
|
|
44100,
|
|
AV_CH_LAYOUT_STEREO, // input
|
|
AV_SAMPLE_FMT_FLTP,
|
|
44100,
|
|
0, NULL);
|
|
swr_init(mSwrCtx);
|
|
#endif
|
|
|
|
if (avcodec_open2(mCodecCtx, mCodec, NULL) < 0) {
|
|
Debuger::Debug(L"can't open codec\r\n");
|
|
mStatus = FAIL;
|
|
}
|
|
mSampleRate = 44100;
|
|
mChannel = 2;
|
|
mChannelLayout = AV_CH_LAYOUT_STEREO;
|
|
mSampleFmt = AV_SAMPLE_FMT_FLTP;
|
|
mStatus = RUNNING;
|
|
mU16Data = (uint8_t *)av_malloc(192000);
|
|
}
|
|
#define MAX_AUDIO_FRAME_SIZE 192000
|
|
|
|
AACDecoder::AACDecoder(AVStream * p):mObserver(nullptr)
|
|
{
|
|
mStatus = RUNNING;
|
|
this->mObserverType = Observer_Audio;
|
|
if (nullptr == p) {
|
|
Debuger::Debug(L"find codec fail\r\n");
|
|
mStatus = FAIL;
|
|
}
|
|
mCodecCtx = p->codec;
|
|
mCodec = avcodec_find_decoder(mCodecCtx->codec_id);
|
|
if (mCodec == NULL) {
|
|
Debuger::Debug(L"find codec fail\r\n");
|
|
mStatus = FAIL;
|
|
}
|
|
if (avcodec_open2(mCodecCtx, mCodec, NULL) < 0) {
|
|
Debuger::Debug(L"can't open codec\r\n");
|
|
mStatus = FAIL;
|
|
}
|
|
mSampleRate = mCodecCtx->sample_rate;
|
|
mChannel = mCodecCtx->channels;
|
|
mChannelLayout = mCodecCtx->channel_layout;
|
|
mSampleFmt = mCodecCtx->sample_fmt;
|
|
}
|
|
|
|
int AACDecoder::Decode(uint8_t * dat, uint16_t size)
|
|
{
|
|
AVPacket pkt;
|
|
int got_pcm = 0;
|
|
int len = 0;
|
|
|
|
if (mStatus == RUNNING) {
|
|
mPcmDat = av_frame_alloc();
|
|
av_init_packet(&pkt);
|
|
|
|
char* data = (char*)dat;
|
|
pkt.data = (uint8_t *)data;
|
|
pkt.size = size;
|
|
|
|
len = avcodec_decode_audio4(this->mCodecCtx, mPcmDat, &got_pcm, &pkt);
|
|
if (len < 0) {
|
|
printf("Error while decoding a frame.\n");
|
|
return -1;
|
|
}
|
|
if (got_pcm == 0) {
|
|
return 0;
|
|
}
|
|
int buffer_size = av_samples_get_buffer_size(NULL, AV_CH_LAYOUT_STEREO,
|
|
mPcmDat->nb_samples,
|
|
AV_SAMPLE_FMT_S16, 1);
|
|
|
|
swr_convert(mSwrCtx, &mU16Data, buffer_size, (const uint8_t **)mPcmDat->data,
|
|
mPcmDat->nb_samples);
|
|
|
|
//Debuger::Debug(L"get %d audio samples\r\n", mPcmDat->nb_samples);
|
|
if (nullptr != this->mObserver) {
|
|
int out_buffer_size = av_samples_get_buffer_size(NULL, 2, mPcmDat->nb_samples,
|
|
AV_SAMPLE_FMT_FLTP, 1);
|
|
this->mObserver->OnAudioDecode(mU16Data, buffer_size);
|
|
}
|
|
//(const uint8_t **)mPcmDat->data, mPcmDat->nb_samples;
|
|
av_frame_free(&mPcmDat);
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int AACDecoder::SetObserver(AACDecoderObserver *p)
|
|
{
|
|
if(nullptr != p)
|
|
this->mObserver = p;
|
|
return 0;
|
|
}
|