如何解码一个AAC帧在一个时间使用c++

How to decode one AAC frame at a time using C++?

本文关键字:一个 时间 c++ 何解码 AAC 解码      更新时间:2023-10-16

我想连续解码AAC帧流,每次解码一帧。

我浏览了ffmpeg示例(正确的答案不一定需要使用ffmpeg),并且我只找到了使用完整AAC文件和批处理算法的示例。但我想解码一个连续的AAC流。我该怎么做呢?

UPDATE:在android上使用ffmpeg解码AAC到PCM之后,我能够使用ffmpeg解码到PCM,但是输出非常金属和嘈杂。当为每个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;
}

您必须在后续解码调用之间保持解码器活动。AAC解码器必须解码前一个缓冲区才能正确地"预充"。

请查看详细信息:

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

下面的代码假设"ReceiveBuffer"函数只返回一个完整的AAC存取单元

(顺便说一句:你不能在二进制缓冲区上使用strlen;您将获得到第一个零的距离,而不是缓冲区长度)

#include <iostream>
#include <fstream>
#include "libavcodecavcodec.h"
#include "libavformatavformat.h"
#include "libavdeviceavdevice.h"
#include "libavfilteravfilter.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;
}
相关文章: