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. AVCodecParserContext
What is the main function of this structure? What is the core function?
- Initialize the
av_parser_init(codec->id);
The parameter iscodec_id
, so only one kind of data can be parsed at a time AVCodecParserContext
Compressed encoded data used to parse incoming data and divide them into frame by frame- The core function
av_parser_parse2()
The data is parsed to get a Packet from the incoming data streamSeparate out frame by frame
theEncoded 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