| @@ -61,6 +61,7 @@ static int open_input_file(const char *filename, | |||
| AVFormatContext **input_format_context, | |||
| AVCodecContext **input_codec_context) | |||
| { | |||
| AVCodecContext *avctx; | |||
| AVCodec *input_codec; | |||
| int error; | |||
| @@ -90,23 +91,39 @@ static int open_input_file(const char *filename, | |||
| } | |||
| /** Find a decoder for the audio stream. */ | |||
| if (!(input_codec = avcodec_find_decoder((*input_format_context)->streams[0]->codec->codec_id))) { | |||
| if (!(input_codec = avcodec_find_decoder((*input_format_context)->streams[0]->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, (*input_format_context)->streams[0]->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((*input_format_context)->streams[0]->codec, | |||
| input_codec, NULL)) < 0) { | |||
| if ((error = avcodec_open2(avctx, input_codec, NULL)) < 0) { | |||
| fprintf(stderr, "Could not open input codec (error '%s')\n", | |||
| get_error_text(error)); | |||
| avcodec_free_context(&avctx); | |||
| avformat_close_input(input_format_context); | |||
| return error; | |||
| } | |||
| /** Save the decoder context for easier access later. */ | |||
| *input_codec_context = (*input_format_context)->streams[0]->codec; | |||
| *input_codec_context = avctx; | |||
| return 0; | |||
| } | |||
| @@ -121,6 +138,7 @@ static int open_output_file(const char *filename, | |||
| AVFormatContext **output_format_context, | |||
| AVCodecContext **output_codec_context) | |||
| { | |||
| AVCodecContext *avctx = NULL; | |||
| AVIOContext *output_io_context = NULL; | |||
| AVStream *stream = NULL; | |||
| AVCodec *output_codec = NULL; | |||
| @@ -160,27 +178,31 @@ static int open_output_file(const char *filename, | |||
| } | |||
| /** Create a new audio stream in the output file container. */ | |||
| if (!(stream = avformat_new_stream(*output_format_context, output_codec))) { | |||
| if (!(stream = avformat_new_stream(*output_format_context, NULL))) { | |||
| fprintf(stderr, "Could not create new stream\n"); | |||
| error = AVERROR(ENOMEM); | |||
| goto cleanup; | |||
| } | |||
| /** Save the encoder context for easier access later. */ | |||
| *output_codec_context = stream->codec; | |||
| 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. | |||
| */ | |||
| (*output_codec_context)->channels = OUTPUT_CHANNELS; | |||
| (*output_codec_context)->channel_layout = av_get_default_channel_layout(OUTPUT_CHANNELS); | |||
| (*output_codec_context)->sample_rate = input_codec_context->sample_rate; | |||
| (*output_codec_context)->sample_fmt = output_codec->sample_fmts[0]; | |||
| (*output_codec_context)->bit_rate = OUTPUT_BIT_RATE; | |||
| avctx->channels = OUTPUT_CHANNELS; | |||
| avctx->channel_layout = av_get_default_channel_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; | |||
| /** Allow the use of the experimental AAC encoder */ | |||
| (*output_codec_context)->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; | |||
| avctx->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL; | |||
| /** Set the sample rate for the container. */ | |||
| stream->time_base.den = input_codec_context->sample_rate; | |||
| @@ -191,18 +213,28 @@ static int open_output_file(const char *filename, | |||
| * Mark the encoder so that it behaves accordingly. | |||
| */ | |||
| if ((*output_format_context)->oformat->flags & AVFMT_GLOBALHEADER) | |||
| (*output_codec_context)->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; | |||
| avctx->flags |= AV_CODEC_FLAG_GLOBAL_HEADER; | |||
| /** Open the encoder for the audio stream to use it later. */ | |||
| if ((error = avcodec_open2(*output_codec_context, output_codec, NULL)) < 0) { | |||
| if ((error = avcodec_open2(avctx, output_codec, NULL)) < 0) { | |||
| fprintf(stderr, "Could not open output codec (error '%s')\n", | |||
| get_error_text(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_close((*output_format_context)->pb); | |||
| avformat_free_context(*output_format_context); | |||
| *output_format_context = NULL; | |||
| @@ -773,13 +805,13 @@ cleanup: | |||
| avresample_free(&resample_context); | |||
| } | |||
| if (output_codec_context) | |||
| avcodec_close(output_codec_context); | |||
| avcodec_free_context(&output_codec_context); | |||
| if (output_format_context) { | |||
| avio_close(output_format_context->pb); | |||
| avformat_free_context(output_format_context); | |||
| } | |||
| if (input_codec_context) | |||
| avcodec_close(input_codec_context); | |||
| avcodec_free_context(&input_codec_context); | |||
| if (input_format_context) | |||
| avformat_close_input(&input_format_context); | |||