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