Hello, 
during my last job's project I had to use very often the AV library for many 
purposes. Then, I created many snippets of code which are aligned to the 
ffmpeg's 3.2 version: they don't use deprecated functions (no warnings from 
compiler) and can be useful as API usage examples, considering that the current 
state of the doc/examples directory seems not good and a bit messy. All the 
snippets that I wrote are short, and they cover many audio+video tasks, from 
grabbing from audio/video devices to network streaming. If the FFMPEG 
developers think that they can be pushed in the doc/examples directory, I can 
spend time in re-organizing all the material and send it progressively to the 
FFMPEG project. For now, I send an example which converts a raw audio file to 
float-planar and encodes it to adts-aac. Please, give me some feedback and I'll 
go on in contributing to the project by sending other examples.


/* * Copyright (c) 2017 Paolo Prete ([email protected]) * * Permission is 
hereby granted, free of charge, to any person obtaining a copy * of this 
software and associated documentation files (the "Software"), to deal * in the 
Software without restriction, including without limitation the rights * to use, 
copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of 
the Software, and to permit persons to whom the Software is * furnished to do 
so, subject to the following conditions: * * The above copyright notice and 
this permission notice shall be included in * all copies or substantial 
portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT 
WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND 
NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR 
THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */
/** * @file * API example for adts-aac encoding raw audio files.  * This 
example reads a raw audio input file, converts it to float-planar format, 
performs aac encoding and puts the encoded frames into an ADTS container. The 
encoded stream is written to  * a file named "out.aac" * The raw input audio 
file can be created with: ffmpeg -i some_audio_file -f f32le -acodec pcm_f32le 
-ac 2 -ar 16000 raw_audio_file.raw *  * @example encode_raw_audio_file_to_aac.c 
*/
#include <libavcodec/avcodec.h>#include <libavformat/avformat.h>#include 
<libavutil/timestamp.h>#include <libswresample/swresample.h>

#define ENCODER_BITRATE 64000#define SAMPLE_RATE 16000#define INPUT_SAMPLE_FMT 
AV_SAMPLE_FMT_FLT#define CHANNELS 2

static char *const get_error_text(const int error){    static char 
error_buffer[255];    av_strerror(error, error_buffer, sizeof(error_buffer));   
 return error_buffer;}

static int write_adts_muxed_data (void *opaque, uint8_t *adts_data, int size){  
  FILE *encoded_audio_file = (FILE *)opaque;    fwrite(adts_data, 1, size, 
encoded_audio_file); //(f)    return size;}

int main(int argc, char **argv){            if (argc != 2) {        
av_log(NULL, AV_LOG_ERROR, "Usage: %s <raw audio input file (CHANNELS, 
INPUT_SAMPLE_FMT, SAMPLE_RATE)>\n", argv[0]);        return 1;    }             
   int ret_val = 0;    int cleanup_step = 1;                    FILE 
*input_audio_file = fopen(argv[1], "rb");    if(!input_audio_file){        
av_log(NULL, AV_LOG_ERROR, "Could not open input audio file\n");        return 
AVERROR_EXIT;    }        FILE *encoded_audio_file = fopen("out.aac", "wb");    
  if(!encoded_audio_file){        av_log(NULL, AV_LOG_ERROR, "Could not open 
output audio file\n");        ret_val = AVERROR_EXIT;        goto cleanup;    } 
        ++cleanup_step;    
            av_register_all();
            //    // Allocate the encoder's context and open the encoder    //  
  AVCodec *audio_codec = avcodec_find_encoder(AV_CODEC_ID_AAC);    
if(!audio_codec){        av_log(NULL, AV_LOG_ERROR, "Could not find aac 
codec\n");        ret_val = AVERROR_EXIT;        goto cleanup;    }    
AVCodecContext *audio_encoder_ctx = avcodec_alloc_context3(audio_codec);    
if(!audio_codec){        av_log(NULL, AV_LOG_ERROR, "Could not allocate the 
encoding context\n");        ret_val = AVERROR_EXIT;        goto cleanup;    }  
      ++cleanup_step;    audio_encoder_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;    
audio_encoder_ctx->bit_rate = ENCODER_BITRATE;    
audio_encoder_ctx->sample_rate = SAMPLE_RATE; // You can use any other sample 
rate provided by the input file on condition that it is supported by the codec 
(use AVCodec::supported_samplerates for listing supported sample rates)    
audio_encoder_ctx->channels = CHANNELS;    audio_encoder_ctx->channel_layout = 
av_get_default_channel_layout(CHANNELS);    audio_encoder_ctx->time_base = 
(AVRational){1, SAMPLE_RATE};    audio_encoder_ctx->codec_type = 
AVMEDIA_TYPE_AUDIO ;    if ((ret_val = avcodec_open2(audio_encoder_ctx, 
audio_codec, NULL)) < 0) {        av_log(NULL, AV_LOG_ERROR, "Could not open 
input codec (error '%s')\n", get_error_text(ret_val));        goto cleanup;    
}    ++cleanup_step;            //    // Allocate an AVFrame which will be 
filled with the input file's data.     //    AVFrame *input_audio_frame;    if 
(!(input_audio_frame = av_frame_alloc())) {        av_log(NULL, AV_LOG_ERROR, 
"Could not allocate input frame\n");        ret_val = AVERROR(ENOMEM);        
goto cleanup;    }        input_audio_frame->nb_samples     = 
audio_encoder_ctx->frame_size;    input_audio_frame->format         = 
INPUT_SAMPLE_FMT;    input_audio_frame->channels       = CHANNELS;    
input_audio_frame->sample_rate    = SAMPLE_RATE;    
input_audio_frame->channel_layout = av_get_default_channel_layout(CHANNELS);    
// Allocate the frame's data buffer     if ((ret_val = 
av_frame_get_buffer(input_audio_frame, 0)) < 0) {        av_log(NULL, 
AV_LOG_ERROR, "Could not allocate container for input frame samples (error 
'%s')\n", get_error_text(ret_val));        ret_val = AVERROR(ENOMEM);        
goto cleanup;    }                    //    // Input data must be converted to 
float-planar format, which is the format required by the AAC encoder. We 
allocate a SwrContext and an AVFrame (which will contain the converted samples) 
   // for this task. The AVFrame will feed the encoding function 
(avcodec_send_frame())    //    SwrContext *audio_convert_context = 
swr_alloc_set_opts(NULL, av_get_default_channel_layout(CHANNELS), 
AV_SAMPLE_FMT_FLTP, SAMPLE_RATE, av_get_default_channel_layout(CHANNELS), 
INPUT_SAMPLE_FMT, SAMPLE_RATE, 0, NULL);    if (!audio_convert_context) {       
 av_log(NULL, AV_LOG_ERROR, "Could not allocate resample context\n");           
              ret_val = AVERROR(ENOMEM);        goto cleanup;    }        
++cleanup_step;    AVFrame *converted_audio_frame;    if 
(!(converted_audio_frame = av_frame_alloc())) {        av_log(NULL, 
AV_LOG_ERROR, "Could not allocate resampled frame\n");        ret_val = 
AVERROR(ENOMEM);        goto cleanup;    }         ++cleanup_step;    
converted_audio_frame->nb_samples     = audio_encoder_ctx->frame_size;    
converted_audio_frame->format         = audio_encoder_ctx->sample_fmt;    
converted_audio_frame->channels       = audio_encoder_ctx->channels;    
converted_audio_frame->channel_layout = audio_encoder_ctx->channel_layout;    
converted_audio_frame->sample_rate    = SAMPLE_RATE;         if ((ret_val = 
av_frame_get_buffer(converted_audio_frame, 0)) < 0) {        av_log(NULL, 
AV_LOG_ERROR, "Could not allocate a buffer for resampled frame samples (error 
'%s')\n", get_error_text(ret_val));        goto cleanup;    }                   
 //    // Create the ADTS container for the encoded frames    //    
AVOutputFormat *adts_container = av_guess_format("adts", NULL, NULL);    if 
(!adts_container) {        av_log(NULL, AV_LOG_ERROR, "Could not find adts 
output format\n");               ret_val = AVERROR_EXIT;        goto cleanup;   
 }         AVFormatContext *adts_container_ctx;    if ((ret_val = 
avformat_alloc_output_context2(&adts_container_ctx, adts_container, "", NULL)) 
< 0){        av_log(NULL, AV_LOG_ERROR, "Could not create output context (error 
'%s')\n", get_error_text(ret_val));        goto cleanup;    }    
++cleanup_step;    size_t adts_container_buffer_size = 4096;    uint8_t 
*adts_container_buffer;    if(!(adts_container_buffer = (uint8_t* 
)av_malloc(adts_container_buffer_size))){        av_log(NULL, AV_LOG_ERROR, 
"Could not allocate a buffer for the I/O output context\n");               
ret_val = AVERROR(ENOMEM);        goto cleanup;     }    ++cleanup_step;    // 
Create an I/O context for the adts container with a write callback 
(write_adts_muxed_data()), so that muxed data will be accessed through this 
function.    AVIOContext *adts_avio_ctx;    if (!(adts_avio_ctx = 
avio_alloc_context(adts_container_buffer, adts_container_buffer_size, 1, 
encoded_audio_file, NULL , &write_adts_muxed_data, NULL))) {        
av_log(NULL, AV_LOG_ERROR, "Could not create I/O output context\n");        
ret_val = AVERROR_EXIT;        goto cleanup;    }    ++cleanup_step;    // Link 
the container's context to the previous I/O context    adts_container_ctx->pb = 
adts_avio_ctx;    AVStream *adts_stream;    if (!(adts_stream = 
avformat_new_stream(adts_container_ctx, NULL))) {        av_log(NULL, 
AV_LOG_ERROR, "Could not create new stream\n");               ret_val = 
AVERROR(ENOMEM);        goto cleanup;            }        adts_stream->id = 
adts_container_ctx->nb_streams-1;    // Copy the encoder's parameters     
avcodec_parameters_from_context(adts_stream->codecpar, audio_encoder_ctx);      
  // Allocate the stream private data and write the stream header    
if(avformat_write_header(adts_container_ctx, NULL) < 0){        av_log(NULL, 
AV_LOG_ERROR, "avformat_write_header() error\n");        ret_val = 
AVERROR_EXIT;        goto cleanup;    }            ++cleanup_step;              
  //    // Fill the input frame's data buffer with input file data (a),     // 
Convert the input frame to float-planar format (b),     // Send the converted 
frame to the encoder (c),     // Get the encoded packet (d),    // Send the 
encoded packet to the adts muxer (e).     // Muxed data is caught in 
write_adts_muxed_data() callback and it is written to the output audio file ( 
(f) : see above)    //    AVPacket encoded_audio_packet;    
av_init_packet(&encoded_audio_packet);    int encoded_pkt_counter = 1;    
while(1) {        int audio_bytes_to_encode = fread(input_audio_frame->data[0], 
1, input_audio_frame->linesize[0], input_audio_file); //(a)        
swr_convert_frame(audio_convert_context, converted_audio_frame, (const AVFrame 
*)input_audio_frame); //(b)        if(audio_bytes_to_encode != 
input_audio_frame->linesize[0]){                        break;        }        
else {            // Do encode            ret_val = 
avcodec_send_frame(audio_encoder_ctx, converted_audio_frame);  //(c)            
if(ret_val == 0)                 ret_val = 
avcodec_receive_packet(audio_encoder_ctx, &encoded_audio_packet); //(d)         
   else{                av_log(NULL, AV_LOG_ERROR, "Error encoding frame (error 
'%s')\n", get_error_text(ret_val));                goto cleanup;            }   
                     if(ret_val == 0){                                int64_t 
pts = converted_audio_frame->nb_samples*(encoded_pkt_counter-1);                
encoded_audio_packet.pts = encoded_audio_packet.dts = pts;                      
     if((ret_val == av_write_frame(adts_container_ctx, &encoded_audio_packet)) 
< 0){ //(e)                    av_log(NULL, AV_LOG_ERROR, "Error calling 
av_write_frame() (error '%s')\n", get_error_text(ret_val));                    
goto cleanup;                }                else{                    
av_log(NULL, AV_LOG_INFO, "Encoded AAC packet %d, size=%d, pts_time=%s\n", 
encoded_pkt_counter, encoded_audio_packet.size, 
av_ts2timestr(encoded_audio_packet.pts, &audio_encoder_ctx->time_base));        
            ++encoded_pkt_counter;                }            }        }       
         }    // Flush delayed packets    int still_pkts_to_flush = 1;    int 
delayed_pkt_counter = 1;        while(still_pkts_to_flush){        int ret = 
avcodec_send_frame(audio_encoder_ctx, NULL);        if(ret != 0)            
still_pkts_to_flush = 0;        ret = avcodec_receive_packet(audio_encoder_ctx, 
&encoded_audio_packet);        if(ret == 0){            int64_t pts = 
converted_audio_frame->nb_samples*(encoded_pkt_counter-1);            
encoded_audio_packet.pts = encoded_audio_packet.dts = pts;             
av_write_frame(adts_container_ctx, &encoded_audio_packet);            
av_log(NULL, AV_LOG_INFO, "Flushed encoded AAC delayed packet %d, size=%d, 
pts_time=%s\n", delayed_pkt_counter, encoded_audio_packet.size, 
av_ts2timestr(encoded_audio_packet.pts, &audio_encoder_ctx->time_base));        
    ++delayed_pkt_counter;            ++encoded_pkt_counter;        }           
 }
        av_write_trailer(adts_container_ctx);  
            cleanup:    

    if(cleanup_step > 0)        fclose(input_audio_file);    if(cleanup_step > 
1)        fclose(encoded_audio_file);     if(cleanup_step > 2)            
avcodec_free_context(&audio_encoder_ctx);    if(cleanup_step > 3)             
av_frame_free(&input_audio_frame);    if(cleanup_step > 4)             
swr_free(&audio_convert_context);       if(cleanup_step > 5)             
av_frame_free(&converted_audio_frame);    if(cleanup_step > 6)            
avformat_free_context(adts_container_ctx);    if(cleanup_step > 7)            
av_free(adts_container_buffer);    if(cleanup_step > 8)            
av_free(adts_avio_ctx);      if(cleanup_step > 9)            
av_packet_unref(&encoded_audio_packet);                return ret_val;    }










/*
 * Copyright (c) 2017 Paolo Prete ([email protected])
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/**
 * @file
 * API example for adts-aac encoding raw audio files. 
 * This example reads a raw audio input file, converts it to float-planar format, performs aac encoding and puts the encoded frames into an ADTS container. The encoded stream is written to 
 * a file named "out.aac"
 * The raw input audio file can be created with: ffmpeg -i some_audio_file -f f32le -acodec pcm_f32le -ac 2 -ar 16000 raw_audio_file.raw
 * 
 * @example encode_raw_audio_file_to_aac.c
 */

#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/timestamp.h>
#include <libswresample/swresample.h>


#define ENCODER_BITRATE 64000
#define SAMPLE_RATE 16000
#define INPUT_SAMPLE_FMT AV_SAMPLE_FMT_FLT
#define CHANNELS 2


static char *const get_error_text(const int error)
{
    static char error_buffer[255];
    av_strerror(error, error_buffer, sizeof(error_buffer));
    return error_buffer;
}


static int write_adts_muxed_data (void *opaque, uint8_t *adts_data, int size)
{
    FILE *encoded_audio_file = (FILE *)opaque;
    fwrite(adts_data, 1, size, encoded_audio_file); //(f)
    return size;
}


int main(int argc, char **argv)
{
    
    
    if (argc != 2) {
        av_log(NULL, AV_LOG_ERROR, "Usage: %s <raw audio input file (CHANNELS, INPUT_SAMPLE_FMT, SAMPLE_RATE)>\n", argv[0]);
        return 1;
    }    
    
    
    int ret_val = 0;
    int cleanup_step = 1;    
    
    
    
    FILE *input_audio_file = fopen(argv[1], "rb");
    if(!input_audio_file){
        av_log(NULL, AV_LOG_ERROR, "Could not open input audio file\n");
        return AVERROR_EXIT;
    }
    
    FILE *encoded_audio_file = fopen("out.aac", "wb");  
    if(!encoded_audio_file){
        av_log(NULL, AV_LOG_ERROR, "Could not open output audio file\n");
        ret_val = AVERROR_EXIT;
        goto cleanup;
    }     
    ++cleanup_step;    

    
    
    av_register_all();

    
    
    //
    // Allocate the encoder's context and open the encoder
    //
    AVCodec *audio_codec = avcodec_find_encoder(AV_CODEC_ID_AAC);
    if(!audio_codec){
        av_log(NULL, AV_LOG_ERROR, "Could not find aac codec\n");
        ret_val = AVERROR_EXIT;
        goto cleanup;
    }
    AVCodecContext *audio_encoder_ctx = avcodec_alloc_context3(audio_codec);
    if(!audio_codec){
        av_log(NULL, AV_LOG_ERROR, "Could not allocate the encoding context\n");
        ret_val = AVERROR_EXIT;
        goto cleanup;
    }    
    ++cleanup_step;
    audio_encoder_ctx->sample_fmt = AV_SAMPLE_FMT_FLTP;
    audio_encoder_ctx->bit_rate = ENCODER_BITRATE;
    audio_encoder_ctx->sample_rate = SAMPLE_RATE; // You can use any other sample rate provided by the input file on condition that it is supported by the codec (use AVCodec::supported_samplerates for listing supported sample rates)
    audio_encoder_ctx->channels = CHANNELS;
    audio_encoder_ctx->channel_layout = av_get_default_channel_layout(CHANNELS);
    audio_encoder_ctx->time_base = (AVRational){1, SAMPLE_RATE};
    audio_encoder_ctx->codec_type = AVMEDIA_TYPE_AUDIO ;
    if ((ret_val = avcodec_open2(audio_encoder_ctx, audio_codec, NULL)) < 0) {
        av_log(NULL, AV_LOG_ERROR, "Could not open input codec (error '%s')\n", get_error_text(ret_val));
        goto cleanup;
    }
    ++cleanup_step;
    
    
    //
    // Allocate an AVFrame which will be filled with the input file's data. 
    //
    AVFrame *input_audio_frame;
    if (!(input_audio_frame = av_frame_alloc())) {
        av_log(NULL, AV_LOG_ERROR, "Could not allocate input frame\n");
        ret_val = AVERROR(ENOMEM);
        goto cleanup;
    }    
    input_audio_frame->nb_samples     = audio_encoder_ctx->frame_size;
    input_audio_frame->format         = INPUT_SAMPLE_FMT;
    input_audio_frame->channels       = CHANNELS;
    input_audio_frame->sample_rate    = SAMPLE_RATE;
    input_audio_frame->channel_layout = av_get_default_channel_layout(CHANNELS);
    // Allocate the frame's data buffer 
    if ((ret_val = av_frame_get_buffer(input_audio_frame, 0)) < 0) {
        av_log(NULL, AV_LOG_ERROR, "Could not allocate container for input frame samples (error '%s')\n", get_error_text(ret_val));
        ret_val = AVERROR(ENOMEM);
        goto cleanup;
    }    
    
    
    
    //
    // Input data must be converted to float-planar format, which is the format required by the AAC encoder. We allocate a SwrContext and an AVFrame (which will contain the converted samples)
    // for this task. The AVFrame will feed the encoding function (avcodec_send_frame())
    //
    SwrContext *audio_convert_context = swr_alloc_set_opts(NULL, av_get_default_channel_layout(CHANNELS), AV_SAMPLE_FMT_FLTP, SAMPLE_RATE, av_get_default_channel_layout(CHANNELS), INPUT_SAMPLE_FMT, SAMPLE_RATE, 0, NULL);
    if (!audio_convert_context) {
        av_log(NULL, AV_LOG_ERROR, "Could not allocate resample context\n");                 
        ret_val = AVERROR(ENOMEM);
        goto cleanup;
    }    
    ++cleanup_step;
    AVFrame *converted_audio_frame;
    if (!(converted_audio_frame = av_frame_alloc())) {
        av_log(NULL, AV_LOG_ERROR, "Could not allocate resampled frame\n");
        ret_val = AVERROR(ENOMEM);
        goto cleanup;
    }     
    ++cleanup_step;
    converted_audio_frame->nb_samples     = audio_encoder_ctx->frame_size;
    converted_audio_frame->format         = audio_encoder_ctx->sample_fmt;
    converted_audio_frame->channels       = audio_encoder_ctx->channels;
    converted_audio_frame->channel_layout = audio_encoder_ctx->channel_layout;
    converted_audio_frame->sample_rate    = SAMPLE_RATE;     
    if ((ret_val = av_frame_get_buffer(converted_audio_frame, 0)) < 0) {
        av_log(NULL, AV_LOG_ERROR, "Could not allocate a buffer for resampled frame samples (error '%s')\n", get_error_text(ret_val));
        goto cleanup;
    }    
    
    
    
    //
    // Create the ADTS container for the encoded frames
    //
    AVOutputFormat *adts_container = av_guess_format("adts", NULL, NULL);
    if (!adts_container) {
        av_log(NULL, AV_LOG_ERROR, "Could not find adts output format\n");       
        ret_val = AVERROR_EXIT;
        goto cleanup;
    }     
    AVFormatContext *adts_container_ctx;
    if ((ret_val = avformat_alloc_output_context2(&adts_container_ctx, adts_container, "", NULL)) < 0){
        av_log(NULL, AV_LOG_ERROR, "Could not create output context (error '%s')\n", get_error_text(ret_val));
        goto cleanup;
    }
    ++cleanup_step;
    size_t adts_container_buffer_size = 4096;
    uint8_t *adts_container_buffer;
    if(!(adts_container_buffer = (uint8_t* )av_malloc(adts_container_buffer_size))){
        av_log(NULL, AV_LOG_ERROR, "Could not allocate a buffer for the I/O output context\n");       
        ret_val = AVERROR(ENOMEM);
        goto cleanup; 
    }
    ++cleanup_step;
    // Create an I/O context for the adts container with a write callback (write_adts_muxed_data()), so that muxed data will be accessed through this function.
    AVIOContext *adts_avio_ctx;
    if (!(adts_avio_ctx = avio_alloc_context(adts_container_buffer, adts_container_buffer_size, 1, encoded_audio_file, NULL , &write_adts_muxed_data, NULL))) {
        av_log(NULL, AV_LOG_ERROR, "Could not create I/O output context\n");
        ret_val = AVERROR_EXIT;
        goto cleanup;
    }
    ++cleanup_step;
    // Link the container's context to the previous I/O context
    adts_container_ctx->pb = adts_avio_ctx;
    AVStream *adts_stream;
    if (!(adts_stream = avformat_new_stream(adts_container_ctx, NULL))) {
        av_log(NULL, AV_LOG_ERROR, "Could not create new stream\n");       
        ret_val = AVERROR(ENOMEM);
        goto cleanup;        
    }    
    adts_stream->id = adts_container_ctx->nb_streams-1;
    // Copy the encoder's parameters 
    avcodec_parameters_from_context(adts_stream->codecpar, audio_encoder_ctx);    
    // Allocate the stream private data and write the stream header
    if(avformat_write_header(adts_container_ctx, NULL) < 0){
        av_log(NULL, AV_LOG_ERROR, "avformat_write_header() error\n");
        ret_val = AVERROR_EXIT;
        goto cleanup;
    }        
    ++cleanup_step;
    
    
    
    //
    // Fill the input frame's data buffer with input file data (a), 
    // Convert the input frame to float-planar format (b), 
    // Send the converted frame to the encoder (c), 
    // Get the encoded packet (d),
    // Send the encoded packet to the adts muxer (e). 
    // Muxed data is caught in write_adts_muxed_data() callback and it is written to the output audio file ( (f) : see above)
    //
    AVPacket encoded_audio_packet;
    av_init_packet(&encoded_audio_packet);
    int encoded_pkt_counter = 1;
    while(1) {
        int audio_bytes_to_encode = fread(input_audio_frame->data[0], 1, input_audio_frame->linesize[0], input_audio_file); //(a)
        swr_convert_frame(audio_convert_context, converted_audio_frame, (const AVFrame *)input_audio_frame); //(b)
        if(audio_bytes_to_encode != input_audio_frame->linesize[0]){            
            break;
        }
        else {
            // Do encode
            ret_val = avcodec_send_frame(audio_encoder_ctx, converted_audio_frame);  //(c)
            if(ret_val == 0) 
                ret_val = avcodec_receive_packet(audio_encoder_ctx, &encoded_audio_packet); //(d)
            else{
                av_log(NULL, AV_LOG_ERROR, "Error encoding frame (error '%s')\n", get_error_text(ret_val));
                goto cleanup;
            }
            
            if(ret_val == 0){                
                int64_t pts = converted_audio_frame->nb_samples*(encoded_pkt_counter-1);
                encoded_audio_packet.pts = encoded_audio_packet.dts = pts;           
                if((ret_val == av_write_frame(adts_container_ctx, &encoded_audio_packet)) < 0){ //(e)
                    av_log(NULL, AV_LOG_ERROR, "Error calling av_write_frame() (error '%s')\n", get_error_text(ret_val));
                    goto cleanup;
                }
                else{
                    av_log(NULL, AV_LOG_INFO, "Encoded AAC packet %d, size=%d, pts_time=%s\n", encoded_pkt_counter, encoded_audio_packet.size, av_ts2timestr(encoded_audio_packet.pts, &audio_encoder_ctx->time_base));
                    ++encoded_pkt_counter;
                }
            }
        }            
    }
    // Flush delayed packets
    int still_pkts_to_flush = 1;
    int delayed_pkt_counter = 1;    
    while(still_pkts_to_flush){
        int ret = avcodec_send_frame(audio_encoder_ctx, NULL);
        if(ret != 0)
            still_pkts_to_flush = 0;
        ret = avcodec_receive_packet(audio_encoder_ctx, &encoded_audio_packet);
        if(ret == 0){
            int64_t pts = converted_audio_frame->nb_samples*(encoded_pkt_counter-1);
            encoded_audio_packet.pts = encoded_audio_packet.dts = pts; 
            av_write_frame(adts_container_ctx, &encoded_audio_packet);
            av_log(NULL, AV_LOG_INFO, "Flushed encoded AAC delayed packet %d, size=%d, pts_time=%s\n", delayed_pkt_counter, encoded_audio_packet.size, av_ts2timestr(encoded_audio_packet.pts, &audio_encoder_ctx->time_base));
            ++delayed_pkt_counter;
            ++encoded_pkt_counter;
        }        
    }

    
    av_write_trailer(adts_container_ctx);  

    
    
    
cleanup:    


    if(cleanup_step > 0)
        fclose(input_audio_file);
    if(cleanup_step > 1)
        fclose(encoded_audio_file); 
    if(cleanup_step > 2)    
        avcodec_free_context(&audio_encoder_ctx);
    if(cleanup_step > 3)     
        av_frame_free(&input_audio_frame);
    if(cleanup_step > 4)     
        swr_free(&audio_convert_context);   
    if(cleanup_step > 5)     
        av_frame_free(&converted_audio_frame);
    if(cleanup_step > 6)    
        avformat_free_context(adts_container_ctx);
    if(cleanup_step > 7)    
        av_free(adts_container_buffer);
    if(cleanup_step > 8)    
        av_free(adts_avio_ctx);  
    if(cleanup_step > 9)    
        av_packet_unref(&encoded_audio_packet);    
    
    
    return ret_val;
    
}



_______________________________________________
Libav-user mailing list
[email protected]
http://ffmpeg.org/mailman/listinfo/libav-user

Reply via email to