1. How to view the AAC codecs supported in FFMPEG?

admindeMac-mini:$ ffmpeg -codecs | grep aac
DEAIL. aac                  AAC (Advanced Audio Coding) (decoders: aac aac_fixed aac_at libfdk_aac ) (encoders: aac aac_at libfdk_aac )
D.AIL. aac_latm             AAC LATM (Advanced Audio Coding LATM syntax)
Copy the code

2. AVCodecIs an important structure, mainly store what information?

  • AVCodec is storedcodecsThe structure of information
  • The main variables are as follows:
const char*name: Short codec nameconst char*long_name: The codec name, full name, is longerenum AVMediaType type: Indicates the type, video, audio, or subtitlesenum AVCodecID id:IDDon't repeatconst AVRational *supported_framerates: Supported frame rate (video only)const enum AVPixelFormat *pix_fmts: Supported pixel formats (video only)const int *supported_samplerates: Supported sampling rate (audio only)const enum AVSampleFormat *sample_fmts: Supported sampling formats (audio only)const uint64_t *channel_layouts: Number of supported channels (audio only)int priv_data_size: Size of private dataCopy the code

3. AVFrameIs an important structure, mainly store what information?

  • AVFrameUsed to store pre-coded data (such as raw data such as PCM)
  • The main variables are as follows:
uint8_t*data[AV_NUM_DATA_POINTERS] : Raw data after decoding (YUV, RGB for video, PCM for audio)intLinesize [AV_NUM_DATA_POINTERS] : Indicates the size of a row in data. Note: not necessarily equal to the width of the image, generally greater than the width of the image.intWidth, height: video frame width and height (1920x1080,1280X720...).intNb_samples: An AVFrame of audio may contain multiple audio frames, several of which are included in this tagintFormat: original data type after decoding (YUV420, YUV422, RGB24...)intKey_frame: indicates whether it is a key frameenum AVPictureType pict_type: Frame type (I.B.P...).AVRational sample_aspect_ratio: aspect ratio (16:9.4:3...)int64_tPTS: Displays the timestampintCoded_picture_number: encoding frame numberintDisplay_picture_number: displays the frame numberint8_t* qscale_table: QP tableuint8_t*mbskip_table: skip the macroblock tableint16_t (*motion_val[2[])2] : Motion vector tableuint32_t* MB_type: macro block type tableshort* DCT_COeff: DCT coefficient, which has not been extractedint8_t *ref_index[2] : motion estimation frame list (looks like H264.This relatively new standard involves multiple reference frames.)intInterlaced_frame: indicates whether interlacing scan is performeduint8_tMotion_subsample_log2: the number of motion vector samples in a macro blocklogtheCopy the code

4. AVPacketIs an important structure, mainly store what information?

  • AVPacketIs to store encoded data (such as aAC compressed data)
  • The important variables are the following
uint8_t*data: compressed encoded data. For example, for H264.Speaking.1The data of avpackets usually corresponds to one NAL. Note: this is only the correspondence, not the exact same. There is a slight difference: use the FFMPEG class library to isolate H from multimedia files264.Therefore, when FFMPEG is used for visual and audio processing, AVPacket data can often be directly written into files, so as to obtain visual and audio code stream files.intSize: Indicates the size of dataint64_tPTS: Displays the timestampint64_tDTS: timestamp of decodingintStream_index: Identifies the video/audio stream to which this AVPacket belongs.Copy the code

5. AVCodecContext is an important structure. What information is stored in it?

  • AVCodecContext is a structure that contains a lot of variables. Note that many of the parameters in AVCodecContext are encoded rather than decoded.
  • The important variables are the following
enum AVMediaType codec_type: Type of codec (video, audio...)struct AVCodec  *codec: Used decoderAVCodec(H264,MPEG2...).int bit_rate: Average bit rateuint8_t *extradata; intExtradata_size: Additional information contained for a particular encoder (e.g. for H264.For decoders, store SPS, PPS, etc.) AVRational time_base: Based on this parameter, PTS can be converted to the actual time (in seconds s)intWidth, height: represents the width and height of a videointRefs: number of motion estimation reference frames (H264.If there are multiple frames, MPEG2 and so on are generally not available.intSample_rate: sampling rate (audio)int-Leonard: Could you tell me the number of channels?enum AVSampleFormat sample_fmt: Sampling formatint profileType: (H.264 has it, and other coding standards should have it too.int level: (with aprofileNot much)Copy the code

6. Use the command line to encode PCM into AAC in the specified format. Then use ffproble out.acc to view relevant parameters

ffmpeg -ar 44100 -ac 2 -f s16le -i 44100_s16le_2.pcm -c:a libfdk_aac -profile:a aac_he_v2 -b:a 32k out_terminal.aac

Copy the code
admindeMac-mini:$ ffprobe out_terminal.aac
Input #0, aac, from 'out_terminal.aac':
Duration: 00:00:10.16, bitrate: 32 kb/s
 Stream #0:0: Audio: aac (HE-AACv2), 44100 Hz, stereo, fltp, 32 kb/s
Copy the code

7. Please briefly describe the key steps of implementing PCM to AAC in code (5 elements, important).

8. Use the code to achieve the same effect as the command line above, the main code inffmpegs.cppIn, the correctness of the code can be verified by comparing the command line with the size of the AAC file generated by the code.

#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));

FFmpegs::FFmpegs()
{

}

// Check the sampling format
static int check_sample_fmt(const AVCodec *codec,
                         enum AVSampleFormat sample_fmt) {
 const enum AVSampleFormat *p = codec->sample_fmts;
 
 while(*p ! = AV_SAMPLE_FMT_NONE) {// qDebug() << "Supported sampling format av_get_sample_fmt_name" << av_get_sample_fmt_name(*p);
     if (*p == sample_fmt) {
         return 1;
     }
     p++;
 }
 return 0;
}

// Audio encoding
// return negative numbers: an error occurred halfway through
// Return 0: encoding operation completed normally
static int encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, QFile &outFile) {
 // Send data to the encoder
 int ret = avcodec_send_frame(ctx, frame);
 if (ret < 0) {
     ERROR_BUF(ret);
     qDebug() << "avcodec_send_frame error" << errbuf;
     return ret;
 }
 
 // Retrieve data from encoder continuously
 // while (ret > 0)
 while (true) {
     ret = avcodec_receive_packet(ctx, pkt);
     if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
         // Continue reading the data into the frame, which is then sent to the encoder
         return 0;
     } else if (ret < 0) { // Other errors
         return ret;
     }
     
     // Get data from encoder successfully
     // Write the encoded data to a file
     outFile.write((char *)pkt->data, pkt->size);
     
     // Release PKT internal resourcesav_packet_unref(pkt); }}void FFmpegs::accEncode(AudioEncodeSpec &in, const char *outFilename) {
 / / file
 QFile inFile(in.filename);
 QFile outFile(outFilename);
 
 // Return the result
 int ret = 0;
 
 / / encoder
 AVCodec *codec = nullptr;
 
 // Encoding context
 AVCodecContext *ctx = nullptr;
 
 // Store PCM
 AVFrame *frame = nullptr;
 
 // Store encoded data (AAC)
 AVPacket *pkt = nullptr;
 
 // Get the encoder
 codec = avcodec_find_encoder_by_name("libfdk_aac");
 if(! codec) { qDebug() <<"encoder not found";
     return;
 }
 
 // libfdk_aAC requirements for input data: The sampling format must be a 16-bit integer
 // Check the input data sampling format
 if(! check_sample_fmt(codec, in.sampleFmt)) { qDebug() <<"unsupported sample format"
              << av_get_sample_fmt_name(in.sampleFmt);
     return;
 }
 
 // Create the encoding context
 ctx = avcodec_alloc_context3(codec);
 if(! ctx) { qDebug() <<"avcodec_alloc_context3 error" ;
     return;
 }
 
 // Set PCM parameters
 ctx->sample_rate = in.sampleRate;
 ctx->sample_fmt = in.sampleFmt;
 ctx->channel_layout = in.chLayout;
 
 / / bitrate
 ctx->bit_rate = 32000;
 / / specification
 ctx->profile = FF_PROFILE_AAC_HE_V2;
 
 // Open the encoder
 ret = avcodec_open2(ctx, codec, nullptr);
 if (ret < 0) {
     ERROR_BUF(ret);
     qDebug() << "avcodec_open2 error" << errbuf;
     goto end;
 }
 
 / / create AVFrame
 frame = av_frame_alloc();
 if(! frame) { qDebug() <<"av_frame_alloc error";
     goto end;
 }
 
 // The number of sample frames in the frame buffer (CTX ->frame_size)
 frame->nb_samples = ctx->frame_size;
 frame->format = ctx->sample_fmt;
 frame->channel_layout = ctx->channel_layout;
 
 // Create buffers with NB_samples, format, channel_layout
 ret = av_frame_get_buffer(frame, 0);
 if (ret) {
     ERROR_BUF(ret);
     qDebug() << "av_frame_get_buffer error" << errbuf;
     goto end;
 }
 
 / / create the AVPacket
 pkt = av_packet_alloc();
 if(! pkt) { qDebug() <<"av_packet_alloc error";
     goto end;
 }
 
 // Open the file
 if(! inFile.open(QFile::ReadOnly)) { qDebug() <<"file open error" << in.filename;
     goto end;
 }
 if(! outFile.open(QFile::WriteOnly)) { qDebug() <<"file open error" << outFilename;
     goto end;
 }
 
 // Get data into frame
 while ((ret = inFile.read((char *)frame->data[0],
                           frame->linesize[0)) >0) {
     // Not enough data is read from the file to fill the frame buffer
     if (ret < frame->linesize[0]) {
         int bytes = av_get_bytes_per_sample((AVSampleFormat)frame->format);
         int ch = av_get_channel_layout_nb_channels(frame->channel_layout);
         // Set the actual valid sample frame carding
         // Prevent the encoder from encoding some redundant data
         frame->nb_samples = ret/(bytes * ch);
     }
     
     // Encode
     if (encode(ctx, frame, pkt, outFile)) {
         gotoend; }}// Flush the buffer
 encode(ctx, nullptr, pkt, outFile);
 
 
end:
 // Close the file
 inFile.close();
 outFile.close();

 // Release resources
 av_frame_free(&frame);
 av_packet_free(&pkt);
 avcodec_free_context(&ctx);

 qDebug() << "Thread terminates normally";
}

Copy the code