Потоковое аудио — Как декодировать один кадр AAC за раз, используя C ++?

Я хочу декодировать поток кадров AAC непрерывно, по одному кадру за раз.

Я просмотрел примеры ffmpeg (для правильного ответа необязательно обязательно использовать ffmpeg), и я нашел только примеры, использующие полные файлы AAC и пакетные алгоритмы. Но я хочу декодировать непрерывный поток AAC. Как я могу это сделать?

ОБНОВИТЬ: После комментариев и Декодировать AAC в PCM с помощью ffmpeg на Android , Я был в состоянии декодировать в PCM с помощью ffmpeg, однако на выходе очень металлический и шумный. Что я делаю не так при вызове этого метода для каждого кадра AAC:

...
/*loop that receives frame in buffer*/
while(1){
/*receive frame*/
input = receive_one_buffer();

/*decode frame*/
decodeBuffer(input,strlen(input),Outfile);
}

...

/*decode frame*/
void decodeBuffer(char * input, int numBytes, ofstream& Outfile) {
/*"input" contains one AAC-LC frame*/
//copy bytes from buffer
uint8_t inputBytes[numBytes + FF_INPUT_BUFFER_PADDING_SIZE];
memset(inputBytes, 0, numBytes + FF_INPUT_BUFFER_PADDING_SIZE);
memcpy(inputBytes, input, numBytes);

av_register_all();

AVCodec *codec = avcodec_find_decoder(CODEC_ID_AAC);

AVCodecContext *avCtx = avcodec_alloc_context();
avCtx->channels = 1;
avCtx->sample_rate = 44100;

//the input buffer
AVPacket avPacket;
av_init_packet(&avPacket);

avPacket.size = numBytes; //input buffer size
avPacket.data = inputBytes; // the input buffer

int outSize;
int len;
uint8_t *outbuf = static_cast<uint8_t *>(malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE));

while (avPacket.size > 0) {
outSize = AVCODEC_MAX_AUDIO_FRAME_SIZE;
len = avcodec_decode_audio3(avCtx, (short *) outbuf, &outSize,
&avPacket);

Outfile.write((char*)outbuf, outSize);

avPacket.size -= len;
avPacket.data += len;
}

av_free_packet(&avPacket);
avcodec_close(avCtx);
//av_free(avCtx);

return;
}

2

Решение

Вы должны поддерживать декодер между последующими вызовами декодирования.
Декодер AAC должен декодировать предыдущий буфер, чтобы он был правильно «заполнен».

Пожалуйста, проверьте детали:

https://developer.apple.com/library/mac/technotes/tn2258/_index.html

В следующем коде предполагается, что функция «ReceiveBuffer» возвращает ровно один
полный блок доступа AAC.

(Кстати: вы не можете использовать strlen для двоичного буфера; вы получите расстояние до первого нуля, а не длину буфера)

#include <iostream>
#include <fstream>

#include "libavcodec\avcodec.h"#include "libavformat\avformat.h"#include "libavdevice\avdevice.h"#include "libavfilter\avfilter.h"
AVCodecContext * CreateContext()
{
av_register_all();

AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_AAC);

AVCodecContext *avCtx = avcodec_alloc_context3(codec);

return avCtx;
}

int32_t DecodeBuffer
(
std::ostream   & output,
uint8_t        * pInput,
uint32_t         cbInputSize,
AVCodecContext * pAVContext
)
{
int32_t cbDecoded = 0;

//the input buffer
AVPacket avPacket;
av_init_packet(&avPacket);

avPacket.size = cbInputSize; //input buffer size
avPacket.data = pInput; // the input bufferra

AVFrame * pDecodedFrame = av_frame_alloc();

int nGotFrame = 0;

cbDecoded = avcodec_decode_audio4(    pAVContext,
pDecodedFrame,
& nGotFrame,
& avPacket);

int data_size = av_samples_get_buffer_size( NULL,
pAVContext->channels,
pDecodedFrame->nb_samples,
pAVContext->sample_fmt,
1);

output.write((const char*)pDecodedFrame->data[0],data_size);av_frame_free(&pDecodedFrame);

return cbDecoded;
}uint8_t * ReceiveBuffer( uint32_t * cbBufferSize)
{
// TODO implement

return NULL;
}

int main
(
int argc,
char *argv[]
)
{
int nResult = 0;

AVCodecContext * pAVContext = CreateContext();

std::ofstream myOutputFile("audio.pcm",std::ios::binary);

while(1)
{
uint32_t cbBufferSize = 0;
uint8_t *pCompressedAudio = ReceiveBuffer( &cbBufferSize);

if(cbBufferSize && pCompressedAudio)
{
DecodeBuffer(   myOutputFile,
pCompressedAudio,
cbBufferSize,
pAVContext);
}
else
{
break;
}
}

avcodec_close(pAVContext);
av_free(pAVContext);

return nResult;
}
4

Другие решения