1. How to decode AAC to PCM using command line?

ffmpeg -c:a libfdk_aac -i in.aac -f s16le out.pcm
Copy the code

2. AVCodecParserContextWhat is the main function of this structure? What is the core function?

  • Initialize theav_parser_init(codec->id);The parameter iscodec_id, so only one kind of data can be parsed at a time
  • AVCodecParserContextCompressed encoded data used to parse incoming data and divide them into frame by frame
  • The core functionav_parser_parse2()The data is parsed to get a Packet from the incoming data streamSeparate out frame by frametheEncoded compressed data.

3. The process of decoding AAC to PCM using code (involving 6 elements, one more than the code)?

4. Use code to decode AAC into the complete code of PCM

#include "ffmpegs.h"
#include <QDebug>
#include <QFile>

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavutil/avutil.h>
}

#define ERROR_BUF(ret) \
    char errbuf[1024]; \
    av_strerror(ret, errbuf, sizeof (errbuf));

// Enter the size of the buffer
#define IN_DATA_SIZE 20480
// The threshold at which input file data needs to be read again
#define REFILL_THRESH 4096



FFmpegs::FFmpegs()
{

}


static int decode(AVCodecContext *ctx, AVPacket *pkt, AVFrame *frame, QFile &outFile) {
    // Sends decoded data to the decoder
    int ret = avcodec_send_packet(ctx, pkt);
    if (ret < 0) {
        ERROR_BUF(ret);
        qDebug() << "avcodec_send_packet error" << errbuf;
        return ret;
    }
    
    while (true) {
        // Get the decoded data
        ret = avcodec_receive_frame(ctx, frame);
        
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
            return 0;
        } else if (ret < 0) {
            ERROR_BUF(ret);
            qDebug() << "avcodec_receive_frame error" << errbuf;
            return ret;
        }
        
        // Write the decoded data to a file
        outFile.write((char *)frame->data[0], frame->linesize[0]); }}void FFmpegs::accDecode(const char *inFilename, AudioEncodeSpec &out) {
    // Return the result
    int ret = 0;
    
    // store input file data (aAC)
    // AV_INPUT_BUFFER_PADDING_SIZE is added to prevent some optimizations from crossing the boundary by reading too many readers at once
    char inDataArray[IN_DATA_SIZE + AV_INPUT_BUFFER_MIN_SIZE];
    char *inData = inDataArray;
    
    // The length of each read from the input file (aac)
    int inLen;
    
    // Whether the end of the input file has been read
    int inEnd = 0;
    
    / / file
    QFile inFile(inFilename);
    QFile outFile(out.filename);
    
    / / decoder
    AVCodec *codec = nullptr;
    / / context
    AVCodecContext *ctx = nullptr;
    // Parser context
    AVCodecParserContext *parserCtx = nullptr;
    
    // Store data before decoding (aAC)
    AVPacket *pkt = nullptr;
    
    // Store PCM
    AVFrame *frame = nullptr;
    
    // Get the decoder
    codec = avcodec_find_decoder_by_name("libfdk_aac");
    if(! codec) { qDebug() <<"avcodec_find_decoder_by_name error";
        return;
    }
    
    // Initialize the parser context
    parserCtx = av_parser_init(codec->id);
    if(! parserCtx) { qDebug() <<"av_parser_init error";
        return;
    }
    
    // Create context
    ctx = avcodec_alloc_context3(codec);
    if(! ctx) { qDebug() <<"avcodec_alloc_context3 error";
        goto end;
    }
    
    / / create the AVPacket
    pkt = av_packet_alloc();
    if(! pkt) { qDebug() <<"av_packet_alloc error";
        goto end;
    }
    
    / / create AVFrame
    frame = av_frame_alloc();
    if(! frame) { qDebug() <<"av_frame_alloc error";
        goto end;
    }
    
    // Open the decoder
    ret = avcodec_open2(ctx, codec, nullptr);
    if (ret < 0) {
        ERROR_BUF(ret);
        qDebug() << "avcodec_open2 error" << errbuf;
        goto end;
    }
    
    // Open the file
    if(! inFile.open(QFile::ReadOnly)) { qDebug() <<"file open error:" << inFilename;
        goto end;
    }
    if(! outFile.open(QFile::WriteOnly)) { qDebug() <<"file open error:" << out.filename;
        goto end;
    }
    
    // Read file data
    inLen = inFile.read(inData, IN_DATA_SIZE);
    while (inLen > 0) {
        // It is parsed by the parser
        // The core logic of the internal call is ff_aac_ac3_parse
        ret = av_parser_parse2(parserCtx, ctx,
                               &pkt->data, &pkt->size,
                               (uint8_t *)inData, inLen,
                               AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
        
        if (ret < 0) {
            ERROR_BUF(ret);
            qDebug() << "av_parser_parse2 error" << errbuf;
            goto end;
        }
        
        // Skip parsed data
        inData += ret;
        // Subtract the size of the parsed data
        inLen -= ret;
        
        / / decoding
        if (pkt->size > 0 && decode(ctx, pkt, frame, outFile) < 0 ) {
            goto end;
        }
        
        // Check whether new file data needs to be read
        if(inLen < REFILL_THRESH && ! inEnd) {// The remaining data is moved to the front of the buffer
            memmove(inDataArray, inData, inLen);
            
            / / reset inData
            inData = inDataArray;
            
            // Read file data to inData+inLen
            int len = inFile.read(inData + inLen, IN_DATA_SIZE - inLen);
            if (len > 0) { // File data has been read
                inLen += len;
            } else { // There is no data in the file
                // mark the end of the file as read
                inEnd = 1; }}}// Flush the buffer
    decode(ctx, nullptr, frame, outFile);
    
    // Assign input parameters
    out.sampleRate = ctx->sample_rate;
    out.sampleFmt = ctx->sample_fmt;
    out.chLayout = ctx->channel_layout;
    
    
end:
    inFile.close();
    outFile.close();
    av_packet_free(&pkt);
    av_frame_free(&frame);
    av_parser_close(parserCtx);
    avcodec_free_context(&ctx);
}

Copy the code