音视频处理 ffmpeg中级开发 AAC编码

介绍

  • 编码流程类似于视频编码,1,查找编码器;2,设定参数,打开编码器;3,数据编码
  • 编码函数 avcodec_encode_audio2 已经被弃用
  • FFmpeg 过时 Api 汇总整理 - 灰色飘零 - 博客园  未成功
  • 使用
    • 旧版本
    • if (avcodec_encode_audio2(tmpAvCodecCtx, &pkt_out, frame, &got_picture) < 0)
    • 新版本
    • if(avcodec_send_frame(tmpAvCodecCtx, frame)<0 || (got_picture=avcodec_receive_packet(tmpAvCodecCtx, &pkt_out))<0) 
  • 本文研究的是 官方的例子,并未使用 上述函数

参考链接

  • FFmpeg/transcode_aac.c at release/4.1 · FFmpeg/FFmpeg · GitHub  修改后成功
  • 源码示例  存放路径/home/chy-cpabe/ffmpeg-source/ffmpeg/doc/examples/transcode_aac.c
  • GitHub - FFmpeg/FFmpeg: Mirror of https://git.ffmpeg.org/ffmpeg.git Github官网
  • 编解码API的详细介绍参见 FFmpeg音频解码。
  • 转封装流程的详细介绍参见 FFmpeg转封装(remuxing)。
  • 其中音频重采样流程的介绍见 FFmpeg音频重采样API(libswresample)。
  • AVAudioFifo的介绍参见FFmpeg 示例转封装转码-transcoding。
  • 作者:smallest_one  链接:FFmpeg 示例音频转码为AAC - 简书
  • AAC编解码简析_Geek.Fan的博客-CSDN博客_aac解码什么意思

注意事项

  • ffplay播放工具 存储路径 /home/chy-cpabe/ffmpeg-source/ffmpeg
  • 引入ffmpeg编译错误taking address of temporary array
  • ibavutil/error.h:120:95: 错误:taking address of temporary array av_make_error_string((char[AV_ERROR_MAX_STRING_SIZE]){0}, AV_ERROR_MAX_STRING_SIZE, errnum) 这里使用了的临时变量作为返回值,因此报错。把这个宏定义改为一个函数,仍然不可以避免这个报错
  • normalize_ts.cpp:217:49: error: taking address of temporary array · Issue #5 · joncampbell123/composite-video-simulator · GitHub
  • 补充代码
#ifdef av_err2str
#undef av_err2str
#include <string>
av_always_inline std::string av_err2string(int errnum) {char str[AV_ERROR_MAX_STRING_SIZE];return av_make_error_string(str, AV_ERROR_MAX_STRING_SIZE, errnum);
}
#define av_err2str(err) av_err2string(err).c_str()
#endif  // av_err2str
  • 输入的文件中只能有一个音频流,否则会报错
  • 输出的音频的编码格式为AAC
  • 使用这个示例程序将其他格式的音频文件比如mp3、wav等格式转换为aac格式

执行流程

完整代码

#include <cstdio>
#include <cstdlib>
#include <cstdint>extern "C" {
#include<libavcodec/avcodec.h>#include "libavformat/avformat.h"
#include "libavformat/avio.h"#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/frame.h>
#include <libavutil/samplefmt.h>
#include <libavutil/audio_fifo.h>
#include "libavutil/avassert.h"
#include "libavutil/avstring.h"
#include "libavutil/opt.h"#include "libswresample/swresample.h"
}/** Copyright (c) 2013-2022 Andreas Unterweger** This file is part of FFmpeg.** FFmpeg is free software; you can redistribute it and/or* modify it under the terms of the GNU Lesser General Public* License as published by the Free Software Foundation; either* version 2.1 of the License, or (at your option) any later version.** FFmpeg is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU* Lesser General Public License for more details.** You should have received a copy of the GNU Lesser General Public* License along with FFmpeg; if not, write to the Free Software* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA*//*** @file* Simple audio converter** @example transcode_aac.c* Convert an input audio file to AAC in an MP4 container using FFmpeg.* Formats other than MP4 are supported based on the output file extension.* @author Andreas Unterweger (dustsigns@gmail.com)*//* The output bit rate in bit/s */
#define OUTPUT_BIT_RATE 96000
/* The number of output channels */
#define OUTPUT_CHANNELS 2#ifdef av_err2str
#undef av_err2str
#include <string>
av_always_inline std::string av_err2string(int errnum) {char str[AV_ERROR_MAX_STRING_SIZE];return av_make_error_string(str, AV_ERROR_MAX_STRING_SIZE, errnum);
}
#define av_err2str(err) av_err2string(err).c_str()
#endif  // av_err2str/*** Open an input file and the required decoder.* @param      filename             File to be opened* @param[out] input_format_context Format context of opened file* @param[out] input_codec_context  Codec context of opened file* @return Error code (0 if successful)*/
static int open_input_file(const char *filename,AVFormatContext **input_format_context,AVCodecContext **input_codec_context)
{AVCodecContext *avctx;const AVCodec *input_codec;const AVStream *stream;int error;/* Open the input file to read from it. */if ((error = avformat_open_input(input_format_context, filename, NULL,NULL)) < 0) {fprintf(stderr, "Could not open input file '%s' (error '%s')\n",filename, av_err2str(error));*input_format_context = NULL;return error;}/* Get information on the input file (number of streams etc.). */if ((error = avformat_find_stream_info(*input_format_context, NULL)) < 0) {fprintf(stderr, "Could not open find stream info (error '%s')\n",av_err2str(error));avformat_close_input(input_format_context);return error;}/* Make sure that there is only one stream in the input file. */if ((*input_format_context)->nb_streams != 1) {fprintf(stderr, "Expected one audio input stream, but found %d\n",(*input_format_context)->nb_streams);avformat_close_input(input_format_context);return AVERROR_EXIT;}stream = (*input_format_context)->streams[0];/* Find a decoder for the audio stream. */if (!(input_codec = avcodec_find_decoder(stream->codecpar->codec_id))) {fprintf(stderr, "Could not find input codec\n");avformat_close_input(input_format_context);return AVERROR_EXIT;}/* Allocate a new decoding context. */avctx = avcodec_alloc_context3(input_codec);if (!avctx) {fprintf(stderr, "Could not allocate a decoding context\n");avformat_close_input(input_format_context);return AVERROR(ENOMEM);}/* Initialize the stream parameters with demuxer information. */error = avcodec_parameters_to_context(avctx, stream->codecpar);if (error < 0) {avformat_close_input(input_format_context);avcodec_free_context(&avctx);return error;}/* Open the decoder for the audio stream to use it later. */if ((error = avcodec_open2(avctx, input_codec, NULL)) < 0) {fprintf(stderr, "Could not open input codec (error '%s')\n",av_err2str(error));avcodec_free_context(&avctx);avformat_close_input(input_format_context);return error;}/* Set the packet timebase for the decoder. */avctx->pkt_timebase = stream->time_base;/* Save the decoder context for easier access later. */*input_codec_context = avctx;return 0;
}/*** Open an output file and the required encoder.* Also set some basic encoder parameters.* Some of these parameters are based on the input file's parameters.* @param      filename              File to be opened* @param      input_codec_context   Codec context of input file* @param[out] output_format_context Format context of output file* @param[out] output_codec_context  Codec context of output file* @return Error code (0 if successful)*/
static int open_output_file(const char *filename,AVCodecContext *input_codec_context,AVFormatContext **output_format_context,AVCodecContext **output_codec_context)
{AVCodecContext *avctx          = NULL;AVIOContext *output_io_context = NULL;AVStream *stream               = NULL;const AVCodec *output_codec    = NULL;int error;/* Open the output file to write to it. */if ((error = avio_open(&output_io_context, filename,AVIO_FLAG_WRITE)) < 0) {fprintf(stderr, "Could not open output file '%s' (error '%s')\n",filename, av_err2str(error));return error;}/* Create a new format context for the output container format. */if (!(*output_format_context = avformat_alloc_context())) {fprintf(stderr, "Could not allocate output format context\n");return AVERROR(ENOMEM);}/* Associate the output file (pointer) with the container format context. */(*output_format_context)->pb = output_io_context;/* Guess the desired container format based on the file extension. */if (!((*output_format_context)->oformat = av_guess_format(NULL, filename,NULL))) {fprintf(stderr, "Could not find output file format\n");goto cleanup;}if (!((*output_format_context)->url = av_strdup(filename))) {fprintf(stderr, "Could not allocate url.\n");error = AVERROR(ENOMEM);goto cleanup;}/* Find the encoder to be used by its name. */if (!(output_codec = avcodec_find_encoder(AV_CODEC_ID_AAC))) {fprintf(stderr, "Could not find an AAC encoder.\n");goto cleanup;}/* Create a new audio stream in the output file container. */if (!(stream = avformat_new_stream(*output_format_context, NULL))) {fprintf(stderr, "Could not create new stream\n");error = AVERROR(ENOMEM);goto cleanup;}avctx = avcodec_alloc_context3(output_codec);if (!avctx) {fprintf(stderr, "Could not allocate an encoding context\n");error = AVERROR(ENOMEM);goto cleanup;}/* Set the basic encoder parameters.* The input file's sample rate is used to avoid a sample rate conversion. */av_channel_layout_default(&avctx->ch_layout, OUTPUT_CHANNELS);avctx->sample_rate    = input_codec_context->sample_rate;avctx->sample_fmt     = output_codec->sample_fmts[0];avctx->bit_rate       = OUTPUT_BIT_RATE;/* Set the sample rate for the container. */stream->time_base.den = input_codec_context->sample_rate;stream->time_base.num = 1;/* Some container formats (like MP4) require global headers to be present.* Mark the encoder so that it behaves accordingly. */if ((*output_format_context)->oformat->flags & AVFMT_GLOBALHEADER)avctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER;/* Open the encoder for the audio stream to use it later. */if ((error = avcodec_open2(avctx, output_codec, NULL)) < 0) {fprintf(stderr, "Could not open output codec (error '%s')\n",av_err2str(error));goto cleanup;}error = avcodec_parameters_from_context(stream->codecpar, avctx);if (error < 0) {fprintf(stderr, "Could not initialize stream parameters\n");goto cleanup;}/* Save the encoder context for easier access later. */*output_codec_context = avctx;return 0;cleanup:avcodec_free_context(&avctx);avio_closep(&(*output_format_context)->pb);avformat_free_context(*output_format_context);*output_format_context = NULL;return error < 0 ? error : AVERROR_EXIT;
}/*** Initialize one data packet for reading or writing.* @param[out] packet Packet to be initialized* @return Error code (0 if successful)*/
static int init_packet(AVPacket **packet)
{if (!(*packet = av_packet_alloc())) {fprintf(stderr, "Could not allocate packet\n");return AVERROR(ENOMEM);}return 0;
}/*** Initialize one audio frame for reading from the input file.* @param[out] frame Frame to be initialized* @return Error code (0 if successful)*/
static int init_input_frame(AVFrame **frame)
{if (!(*frame = av_frame_alloc())) {fprintf(stderr, "Could not allocate input frame\n");return AVERROR(ENOMEM);}return 0;
}/*** Initialize the audio resampler based on the input and output codec settings.* If the input and output sample formats differ, a conversion is required* libswresample takes care of this, but requires initialization.* @param      input_codec_context  Codec context of the input file* @param      output_codec_context Codec context of the output file* @param[out] resample_context     Resample context for the required conversion* @return Error code (0 if successful)*/
static int init_resampler(AVCodecContext *input_codec_context,AVCodecContext *output_codec_context,SwrContext **resample_context)
{int error;/** Create a resampler context for the conversion.* Set the conversion parameters.*/error = swr_alloc_set_opts2(resample_context,&output_codec_context->ch_layout,output_codec_context->sample_fmt,output_codec_context->sample_rate,&input_codec_context->ch_layout,input_codec_context->sample_fmt,input_codec_context->sample_rate,0, NULL);if (error < 0) {fprintf(stderr, "Could not allocate resample context\n");return error;}/** Perform a sanity check so that the number of converted samples is* not greater than the number of samples to be converted.* If the sample rates differ, this case has to be handled differently*/av_assert0(output_codec_context->sample_rate == input_codec_context->sample_rate);/* Open the resampler with the specified parameters. */if ((error = swr_init(*resample_context)) < 0) {fprintf(stderr, "Could not open resample context\n");swr_free(resample_context);return error;}return 0;
}/*** Initialize a FIFO buffer for the audio samples to be encoded.* @param[out] fifo                 Sample buffer* @param      output_codec_context Codec context of the output file* @return Error code (0 if successful)*/
static int init_fifo(AVAudioFifo **fifo, AVCodecContext *output_codec_context)
{/* Create the FIFO buffer based on the specified output sample format. */if (!(*fifo = av_audio_fifo_alloc(output_codec_context->sample_fmt,output_codec_context->ch_layout.nb_channels, 1))) {fprintf(stderr, "Could not allocate FIFO\n");return AVERROR(ENOMEM);}return 0;
}/*** Write the header of the output file container.* @param output_format_context Format context of the output file* @return Error code (0 if successful)*/
static int write_output_file_header(AVFormatContext *output_format_context)
{int error;if ((error = avformat_write_header(output_format_context, NULL)) < 0) {fprintf(stderr, "Could not write output file header (error '%s')\n",av_err2str(error));return error;}return 0;
}/*** Decode one audio frame from the input file.* @param      frame                Audio frame to be decoded* @param      input_format_context Format context of the input file* @param      input_codec_context  Codec context of the input file* @param[out] data_present         Indicates whether data has been decoded* @param[out] finished             Indicates whether the end of file has*                                  been reached and all data has been*                                  decoded. If this flag is false, there*                                  is more data to be decoded, i.e., this*                                  function has to be called again.* @return Error code (0 if successful)*/
static int decode_audio_frame(AVFrame *frame,AVFormatContext *input_format_context,AVCodecContext *input_codec_context,int *data_present, int *finished)
{/* Packet used for temporary storage. */AVPacket *input_packet;int error;error = init_packet(&input_packet);if (error < 0)return error;*data_present = 0;*finished = 0;/* Read one audio frame from the input file into a temporary packet. */if ((error = av_read_frame(input_format_context, input_packet)) < 0) {/* If we are at the end of the file, flush the decoder below. */if (error == AVERROR_EOF)*finished = 1;else {fprintf(stderr, "Could not read frame (error '%s')\n",av_err2str(error));goto cleanup;}}/* Send the audio frame stored in the temporary packet to the decoder.* The input audio stream decoder is used to do this. */if ((error = avcodec_send_packet(input_codec_context, input_packet)) < 0) {fprintf(stderr, "Could not send packet for decoding (error '%s')\n",av_err2str(error));goto cleanup;}/* Receive one frame from the decoder. */error = avcodec_receive_frame(input_codec_context, frame);/* If the decoder asks for more data to be able to decode a frame,* return indicating that no data is present. */if (error == AVERROR(EAGAIN)) {error = 0;goto cleanup;/* If the end of the input file is reached, stop decoding. */} else if (error == AVERROR_EOF) {*finished = 1;error = 0;goto cleanup;} else if (error < 0) {fprintf(stderr, "Could not decode frame (error '%s')\n",av_err2str(error));goto cleanup;/* Default case: Return decoded data. */} else {*data_present = 1;goto cleanup;}cleanup:av_packet_free(&input_packet);return error;
}/*** Initialize a temporary storage for the specified number of audio samples.* The conversion requires temporary storage due to the different format.* The number of audio samples to be allocated is specified in frame_size.* @param[out] converted_input_samples Array of converted samples. The*                                     dimensions are reference, channel*                                     (for multi-channel audio), sample.* @param      output_codec_context    Codec context of the output file* @param      frame_size              Number of samples to be converted in*                                     each round* @return Error code (0 if successful)*/
static int init_converted_samples(uint8_t ***converted_input_samples,AVCodecContext *output_codec_context,int frame_size)
{int error;/* Allocate as many pointers as there are audio channels.* Each pointer will later point to the audio samples of the corresponding* channels (although it may be NULL for interleaved formats).*/if (!(*converted_input_samples = static_cast<uint8_t **>(calloc(output_codec_context->ch_layout.nb_channels,sizeof(**converted_input_samples))))) {fprintf(stderr, "Could not allocate converted input sample pointers\n");return AVERROR(ENOMEM);}/* Allocate memory for the samples of all channels in one consecutive* block for convenience. */if ((error = av_samples_alloc(*converted_input_samples, NULL,output_codec_context->ch_layout.nb_channels,frame_size,output_codec_context->sample_fmt, 0)) < 0) {fprintf(stderr,"Could not allocate converted input samples (error '%s')\n",av_err2str(error));av_freep(&(*converted_input_samples)[0]);free(*converted_input_samples);return error;}return 0;
}/*** Convert the input audio samples into the output sample format.* The conversion happens on a per-frame basis, the size of which is* specified by frame_size.* @param      input_data       Samples to be decoded. The dimensions are*                              channel (for multi-channel audio), sample.* @param[out] converted_data   Converted samples. The dimensions are channel*                              (for multi-channel audio), sample.* @param      frame_size       Number of samples to be converted* @param      resample_context Resample context for the conversion* @return Error code (0 if successful)*/
static int convert_samples(const uint8_t **input_data,uint8_t **converted_data, const int frame_size,SwrContext *resample_context)
{int error;/* Convert the samples using the resampler. */if ((error = swr_convert(resample_context,converted_data, frame_size,input_data    , frame_size)) < 0) {fprintf(stderr, "Could not convert input samples (error '%s')\n",av_err2str(error));return error;}return 0;
}/*** Add converted input audio samples to the FIFO buffer for later processing.* @param fifo                    Buffer to add the samples to* @param converted_input_samples Samples to be added. The dimensions are channel*                                (for multi-channel audio), sample.* @param frame_size              Number of samples to be converted* @return Error code (0 if successful)*/
static int add_samples_to_fifo(AVAudioFifo *fifo,uint8_t **converted_input_samples,const int frame_size)
{int error;/* Make the FIFO as large as it needs to be to hold both,* the old and the new samples. */if ((error = av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame_size)) < 0) {fprintf(stderr, "Could not reallocate FIFO\n");return error;}/* Store the new samples in the FIFO buffer. */if (av_audio_fifo_write(fifo, (void **)converted_input_samples,frame_size) < frame_size) {fprintf(stderr, "Could not write data to FIFO\n");return AVERROR_EXIT;}return 0;
}/*** Read one audio frame from the input file, decode, convert and store* it in the FIFO buffer.* @param      fifo                 Buffer used for temporary storage* @param      input_format_context Format context of the input file* @param      input_codec_context  Codec context of the input file* @param      output_codec_context Codec context of the output file* @param      resampler_context    Resample context for the conversion* @param[out] finished             Indicates whether the end of file has*                                  been reached and all data has been*                                  decoded. If this flag is false,*                                  there is more data to be decoded,*                                  i.e., this function has to be called*                                  again.* @return Error code (0 if successful)*/
static int read_decode_convert_and_store(AVAudioFifo *fifo,AVFormatContext *input_format_context,AVCodecContext *input_codec_context,AVCodecContext *output_codec_context,SwrContext *resampler_context,int *finished)
{/* Temporary storage of the input samples of the frame read from the file. */AVFrame *input_frame = NULL;/* Temporary storage for the converted input samples. */uint8_t **converted_input_samples = NULL;int data_present;int ret = AVERROR_EXIT;/* Initialize temporary storage for one input frame. */if (init_input_frame(&input_frame))goto cleanup;/* Decode one frame worth of audio samples. */if (decode_audio_frame(input_frame, input_format_context,input_codec_context, &data_present, finished))goto cleanup;/* If we are at the end of the file and there are no more samples* in the decoder which are delayed, we are actually finished.* This must not be treated as an error. */if (*finished) {ret = 0;goto cleanup;}/* If there is decoded data, convert and store it. */if (data_present) {/* Initialize the temporary storage for the converted input samples. */if (init_converted_samples(&converted_input_samples, output_codec_context,input_frame->nb_samples))goto cleanup;/* Convert the input samples to the desired output sample format.* This requires a temporary storage provided by converted_input_samples. */if (convert_samples((const uint8_t**)input_frame->extended_data, converted_input_samples,input_frame->nb_samples, resampler_context))goto cleanup;/* Add the converted input samples to the FIFO buffer for later processing. */if (add_samples_to_fifo(fifo, converted_input_samples,input_frame->nb_samples))goto cleanup;ret = 0;}ret = 0;cleanup:if (converted_input_samples) {av_freep(&converted_input_samples[0]);free(converted_input_samples);}av_frame_free(&input_frame);return ret;
}/*** Initialize one input frame for writing to the output file.* The frame will be exactly frame_size samples large.* @param[out] frame                Frame to be initialized* @param      output_codec_context Codec context of the output file* @param      frame_size           Size of the frame* @return Error code (0 if successful)*/
static int init_output_frame(AVFrame **frame,AVCodecContext *output_codec_context,int frame_size)
{int error;/* Create a new frame to store the audio samples. */if (!(*frame = av_frame_alloc())) {fprintf(stderr, "Could not allocate output frame\n");return AVERROR_EXIT;}/* Set the frame's parameters, especially its size and format.* av_frame_get_buffer needs this to allocate memory for the* audio samples of the frame.* Default channel layouts based on the number of channels* are assumed for simplicity. */(*frame)->nb_samples     = frame_size;av_channel_layout_copy(&(*frame)->ch_layout, &output_codec_context->ch_layout);(*frame)->format         = output_codec_context->sample_fmt;(*frame)->sample_rate    = output_codec_context->sample_rate;/* Allocate the samples of the created frame. This call will make* sure that the audio frame can hold as many samples as specified. */if ((error = av_frame_get_buffer(*frame, 0)) < 0) {fprintf(stderr, "Could not allocate output frame samples (error '%s')\n",av_err2str(error));av_frame_free(frame);return error;}return 0;
}/* Global timestamp for the audio frames. */
static int64_t pts = 0;/*** Encode one frame worth of audio to the output file.* @param      frame                 Samples to be encoded* @param      output_format_context Format context of the output file* @param      output_codec_context  Codec context of the output file* @param[out] data_present          Indicates whether data has been*                                   encoded* @return Error code (0 if successful)*/
static int encode_audio_frame(AVFrame *frame,AVFormatContext *output_format_context,AVCodecContext *output_codec_context,int *data_present)
{/* Packet used for temporary storage. */AVPacket *output_packet;int error;error = init_packet(&output_packet);if (error < 0)return error;/* Set a timestamp based on the sample rate for the container. */if (frame) {frame->pts = pts;pts += frame->nb_samples;}*data_present = 0;/* Send the audio frame stored in the temporary packet to the encoder.* The output audio stream encoder is used to do this. */error = avcodec_send_frame(output_codec_context, frame);/* Check for errors, but proceed with fetching encoded samples if the*  encoder signals that it has nothing more to encode. */if (error < 0 && error != AVERROR_EOF) {fprintf(stderr, "Could not send packet for encoding (error '%s')\n",av_err2str(error));goto cleanup;}/* Receive one encoded frame from the encoder. */error = avcodec_receive_packet(output_codec_context, output_packet);/* If the encoder asks for more data to be able to provide an* encoded frame, return indicating that no data is present. */if (error == AVERROR(EAGAIN)) {error = 0;goto cleanup;/* If the last frame has been encoded, stop encoding. */} else if (error == AVERROR_EOF) {error = 0;goto cleanup;} else if (error < 0) {fprintf(stderr, "Could not encode frame (error '%s')\n",av_err2str(error));goto cleanup;/* Default case: Return encoded data. */} else {*data_present = 1;}/* Write one audio frame from the temporary packet to the output file. */if (*data_present &&(error = av_write_frame(output_format_context, output_packet)) < 0) {fprintf(stderr, "Could not write frame (error '%s')\n",av_err2str(error));goto cleanup;}cleanup:av_packet_free(&output_packet);return error;
}/*** Load one audio frame from the FIFO buffer, encode and write it to the* output file.* @param fifo                  Buffer used for temporary storage* @param output_format_context Format context of the output file* @param output_codec_context  Codec context of the output file* @return Error code (0 if successful)*/
static int load_encode_and_write(AVAudioFifo *fifo,AVFormatContext *output_format_context,AVCodecContext *output_codec_context)
{/* Temporary storage of the output samples of the frame written to the file. */AVFrame *output_frame;/* Use the maximum number of possible samples per frame.* If there is less than the maximum possible frame size in the FIFO* buffer use this number. Otherwise, use the maximum possible frame size. */const int frame_size = FFMIN(av_audio_fifo_size(fifo),output_codec_context->frame_size);int data_written;/* Initialize temporary storage for one output frame. */if (init_output_frame(&output_frame, output_codec_context, frame_size))return AVERROR_EXIT;/* Read as many samples from the FIFO buffer as required to fill the frame.* The samples are stored in the frame temporarily. */if (av_audio_fifo_read(fifo, (void **)output_frame->data, frame_size) < frame_size) {fprintf(stderr, "Could not read data from FIFO\n");av_frame_free(&output_frame);return AVERROR_EXIT;}/* Encode one frame worth of audio samples. */if (encode_audio_frame(output_frame, output_format_context,output_codec_context, &data_written)) {av_frame_free(&output_frame);return AVERROR_EXIT;}av_frame_free(&output_frame);return 0;
}/*** Write the trailer of the output file container.* @param output_format_context Format context of the output file* @return Error code (0 if successful)*/
static int write_output_file_trailer(AVFormatContext *output_format_context)
{int error;if ((error = av_write_trailer(output_format_context)) < 0) {fprintf(stderr, "Could not write output file trailer (error '%s')\n",av_err2str(error));return error;}return 0;
}int main(int argc, char **argv)
{AVFormatContext *input_format_context = NULL, *output_format_context = NULL;AVCodecContext *input_codec_context = NULL, *output_codec_context = NULL;SwrContext *resample_context = NULL;AVAudioFifo *fifo = NULL;int ret = AVERROR_EXIT;if (argc != 3) {fprintf(stderr, "Usage: %s <input file> <output file>\n", argv[0]);exit(1);}/* Open the input file for reading. */if (open_input_file(argv[1], &input_format_context,&input_codec_context))goto cleanup;/* Open the output file for writing. */if (open_output_file(argv[2], input_codec_context,&output_format_context, &output_codec_context))goto cleanup;/* Initialize the resampler to be able to convert audio sample formats. */if (init_resampler(input_codec_context, output_codec_context,&resample_context))goto cleanup;/* Initialize the FIFO buffer to store audio samples to be encoded. */if (init_fifo(&fifo, output_codec_context))goto cleanup;/* Write the header of the output file container. */if (write_output_file_header(output_format_context))goto cleanup;/* Loop as long as we have input samples to read or output samples* to write; abort as soon as we have neither. */while (1) {/* Use the encoder's desired frame size for processing. */const int output_frame_size = output_codec_context->frame_size;int finished                = 0;/* Make sure that there is one frame worth of samples in the FIFO* buffer so that the encoder can do its work.* Since the decoder's and the encoder's frame size may differ, we* need to FIFO buffer to store as many frames worth of input samples* that they make up at least one frame worth of output samples. */while (av_audio_fifo_size(fifo) < output_frame_size) {/* Decode one frame worth of audio samples, convert it to the* output sample format and put it into the FIFO buffer. */if (read_decode_convert_and_store(fifo, input_format_context,input_codec_context,output_codec_context,resample_context, &finished))goto cleanup;/* If we are at the end of the input file, we continue* encoding the remaining audio samples to the output file. */if (finished)break;}/* If we have enough samples for the encoder, we encode them.* At the end of the file, we pass the remaining samples to* the encoder. */while (av_audio_fifo_size(fifo) >= output_frame_size ||(finished && av_audio_fifo_size(fifo) > 0))/* Take one frame worth of audio samples from the FIFO buffer,* encode it and write it to the output file. */if (load_encode_and_write(fifo, output_format_context,output_codec_context))goto cleanup;/* If we are at the end of the input file and have encoded* all remaining samples, we can exit this loop and finish. */if (finished) {int data_written;/* Flush the encoder as it may have delayed frames. */do {if (encode_audio_frame(NULL, output_format_context,output_codec_context, &data_written))goto cleanup;} while (data_written);break;}}/* Write the trailer of the output file container. */if (write_output_file_trailer(output_format_context))goto cleanup;ret = 0;cleanup:if (fifo)av_audio_fifo_free(fifo);swr_free(&resample_context);if (output_codec_context)avcodec_free_context(&output_codec_context);if (output_format_context) {avio_closep(&output_format_context->pb);avformat_free_context(output_format_context);}if (input_codec_context)avcodec_free_context(&input_codec_context);if (input_format_context)avformat_close_input(&input_format_context);return ret;
}

 

执行结果

CLion

 MP3

 aac

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/446031.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

虚拟机为Ubuntu分配空间

当虚拟机里面的创建的ubuntu镜像需要更大的空间&#xff0c;将ubuntu关掉之后&#xff0c;对应调整硬盘的空间大小&#xff0c;由先前的20G上调至50G&#xff0c;但是先前的20G内存空间映射的位置是/dev/sda&#xff0c;后面增加的这段内存空间30G映射到/dev/sda1因此&#xff…

为什么人会摆高姿态_Yo , 你为什么喜欢冲浪?

“你为什么喜欢冲浪&#xff1f;” 那天木木突然问我。我愣住了。此时一道碧波恰从防泼堤&#xff08;jetty&#xff09;的那头升起&#xff0c;木木转头望去&#xff0c;视线追着那道浪缓缓向西&#xff0c;直至它破碎成白色的浪花。我瞥见他眼神中的光亮&#xff0c;就和小孩…

音视频处理 ffmpeg初级开发 命令行工具-实用命令

参考链接 ffmpeg Documentation作者&#xff1a;smallest_one 链接&#xff1a;FFmpeg命令行工具-实用命令 - 简书 目录 1&#xff0c;help命令使用 1.1 ffmpeg命令的语法结构1.2 获取详细的help信息1.3 打印帮助或者支持能力的信息1.4 全局选项1.5 文件选项1.6 视频/音频/字…

不同的电脑打印预览不同怎么解决_条码打印软件中标签预览正常打印无反应怎么解决...

在使用条码打印软件制作标签时&#xff0c;有客户反馈,标签打印预览正常的&#xff0c;但是打印无反应&#xff0c;咨询是怎么回事?今天针对这个情况&#xff0c;可以参考以下方法进行解决。一、预览正常情况下&#xff0c;打印没反应(1)在条码打印软件中设计好标签之后&#…

MP4文件格式的相关内容

参考链接 FFmpeg中mp4的demuxer(mov.c)代码阅读 - 简书mp4文件格式解析 - 简书mp4封装格式各box类型讲解及IBP帧计算_青丶空゛的博客-CSDN博客5分钟入门MP4文件格式 - 程序猿小卡 - 博客园​关于M4A文件的随机访问 - 云社区 - 腾讯云 MP4文件格式相关内容 MP4文件由许多box组…

华三交换机如何进入配置_学校机房项目交换机的如何配置,理解这篇,交换机配置不再难...

弱电项目中&#xff0c;交换机的配置是无法避免的&#xff0c;大部分的项目都有可能会涉及到&#xff0c;尤其是机房等网络项目&#xff0c;本期我们就通过一个实际项目案例来详细了解交换机在项目中的应用配置&#xff0c;如果我们平时对交换机配置不熟&#xff0c;这个案例可…

百度地图迁徙大数据_百度地图大数据:五一高速拥堵不似预期,广深成热门迁出入地...

五一假期在即&#xff0c;你是否做好了“出行功课”&#xff1f;高速拥堵水平降低、公众出门不出城、公园成踏青赏景热门目的地……在全国疫情防控仍未松懈的时刻&#xff0c;2020年的五一或许注定与往年不同。近日&#xff0c;百度地图发布2020五一假期安全出行大数据&#xf…

音视频的基础知识 视频播放器原理/封装格式/视频音频编码数据/视频像素数据/音频采样数据

参考链接 FFMpeg视频播放器的制作-雷霄骅&#xff08;去除电流音版本&#xff09;_哔哩哔哩_bilibili 视频播放器原理 播放视频文件的流程YUV是一张屏幕中像素点的数值封装格式 MP4 RMVB TS FLV AVI将视频和音频码流按照一定的格式存储在一个文件中封装格式分析工具&#xf…

科立捷7代写频软件_天大厦大“两硕士论文雷同”通报,代写买卖论文

澎湃新闻记者 薛莎莎天津大学、厦门大学7月10日晚就“两硕士论文雷同”一事&#xff0c;分别发出调查处理通报。通报称&#xff0c;涉事两名学生存在由他人代写、买卖论文的学术作假的行为&#xff0c;均撤销其所获硕士学位&#xff0c;收回、注销硕士学位证书。澎湃新闻注意到…

FFMpeg命令行基础

参考链接 FFMpeg视频播放器的制作-雷霄骅&#xff08;去除电流音版本&#xff09;_哔哩哔哩_bilibili音视频处理 ffmpeg初级开发 命令行工具-实用命令_MY CUP OF TEA的博客-CSDN博客 介绍 FFMpeg是视频播放和转码的内核 使用 win中ffmpeg.exe用于视频转码简单命令&#xff1…

悲观锁和乐观锁_面试必备之乐观锁与悲观锁

何谓悲观锁与乐观锁乐观锁对应于生活中乐观的人总是想着事情往好的方向发展&#xff0c;悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。这两种人各有优缺点&#xff0c;不能不以场景而定说一种人好于另外一种人。大家可以点击加群【JAVA架构知识学习讨论群】47398464…

Microsoft Visual Studio2019环境下搭建FFmpeg开发环境

参考链接 《基于 FFmpeg SDL 的视频播放器的制作》课程的视频_雷霄骅的博客-CSDN博客_雷霄骅ffmpeg视频教程小学期课程资料 - 基于FFmpegSDL的视频播放器的制作.zip_免费高速下载|百度网盘-分享无限制辅助参考链接使用VS2019创建项目&#xff0c;添加文件和库地址_MY CUP OF …

vue process.env获取不到_从文档开始,重学vue(下)源码级别

此篇文章主要是从应用及源码层面讲解vue部分常用api,阅读起来可能略有难度,新手可以看《从文档开始,重学vue(上)》示例代码均在vue-cli3中完成Vue.extend()可以使用 extend 创建一个子类,该方法通常用于构建全局组件,如弹框组件等,下面我们就用它来制作个全局alert组件吧首先我…

Microsoft Visual Studio2019环境下搭建SDL开发环境

参考链接 《基于 FFmpeg SDL 的视频播放器的制作》课程的视频_雷霄骅的博客-CSDN博客_雷霄骅ffmpeg视频教程小学期课程资料 - 基于FFmpegSDL的视频播放器的制作.zip_免费高速下载|百度网盘-分享无限制辅助参考链接VS自动链接到Windows上随vcpkg安装的SDL2库 | 码农俱乐部 - G…

不关注公众号可以获取openid吗_微信公众号粉丝迁移

目录 [toc] 微信公众号迁移 正常的公众号迁移直接通过微信操作就可以&#xff0c;如下图。但是因为udb数据里面存的是迁移前公众号的openid以及unionid,需要自行获取新旧openid以及unionid。 旧的用户信息要在迁移之前获取&#xff0c;第三步点击同意之后就公众号的接口就调不通…

建筑专业规范大全 2020版_房屋建筑工程现行规范标准目录汇编(2020版)—建筑电气...

房屋建筑工程现行规范标准目录汇编(2020版)建筑电气规范编号规范名称GB 50034-2013建筑照明设计标准GB 50052-2009供配电系统设计规范GB 50053-201320kV及以下变电所设计规范GB 50057-2010建筑物防雷设计规范GB 50147-2010电气装置安装工程 高压电器施工及验收规范GB 50148-201…

基于Microsoft Visual Studio2019环境编写ffmpeg视频解码代码

旧代码 旧代码使用了很多过时的API&#xff0c;这些API使用后&#xff0c;vs会报编译器警告 (级别 3) C4996的错误即 函数被声明为已否决 报 C4996的错误 // test_ffmpeg.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。 // #define SDL_MAIN_HANDLED …

16进制转double dotnet_终于把计算机进制弄明白了!

And theres one thing that I need from you我只需要你为我做一-件事Can you come through, through待在我的身边就好Through, yeah你可以抚慰一切不满And theres one thing that I need from you你可以过来Can you come through?待在我的身边吗-comethruJeremy Zucker进制进制…

FFmpeg源代码简单分析-架构图-解码

参考链接 FFmpeg源代码结构图 - 解码_雷霄骅的博客-CSDN博客_ffmpeg雷霄骅函数背景色 函数在图中以方框的形式表现出来。不同的背景色标志了该函数不同的作用&#xff1a; 粉红色背景函数&#xff1a;FFmpeg的API函数。白色背景的函数&#xff1a;FFmpeg的内部函数。黄色背景…

JUnit单元测试笔记

#01 JUnit简介 1.在项目工程中的Library,add 一个JUnit的Jar包&#xff0c;按需要添加JUnit 3 或 JUnit 4&#xff08;分为被测试类与测试类较佳&#xff09;。 2.单元测试是由程序员完成的。 3.Java 5 之前的版本只能 用JUnit 4前的版本&#xff08;因为JUnit 4用到Java 5的…