--- ffmpeg.c | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- ffplay.c | 17 +++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletions(-)
diff --git a/ffmpeg.c b/ffmpeg.c index d54785d..1f6a86a 100644 --- a/ffmpeg.c +++ b/ffmpeg.c @@ -543,6 +543,37 @@ static void choose_sample_fmt(AVStream *st, AVCodec *codec) } } +/** + * Update the requested input sample format based on the output sample format. + * This is currently only used to request float output from decoders which + * support multiple sample formats, one of which is AV_SAMPLE_FMT_FLT. + * Ideally this will be removed in the future when decoders do not do format + * conversion and only output in their native format. + */ +static void update_sample_fmt(AVCodecContext *dec, AVCodec *dec_codec, + AVCodecContext *enc) +{ + /* if sample formats match or a decoder sample format has already been + requested, just return */ + if (enc->sample_fmt == dec->sample_fmt || + dec->request_sample_fmt > AV_SAMPLE_FMT_NONE) + return; + + if (dec_codec && dec_codec->sample_fmts) { + if (enc->sample_fmt == AV_SAMPLE_FMT_FLT || + enc->sample_fmt == AV_SAMPLE_FMT_DBL || + enc->sample_fmt == AV_SAMPLE_FMT_S32) { + const enum AVSampleFormat *p = dec_codec->sample_fmts; + for (; *p != AV_SAMPLE_FMT_NONE; p++) { + if (*p == AV_SAMPLE_FMT_FLT) { + dec->request_sample_fmt = *p; + break; + } + } + } + } +} + static void choose_sample_rate(AVStream *st, AVCodec *codec) { if(codec && codec->supported_samplerates){ @@ -765,7 +796,7 @@ need_realloc: ost->resample_sample_rate == enc->sample_rate) { ost->resample = NULL; ost->audio_resample = 0; - } else { + } else if (ost->audio_resample) { if (dec->sample_fmt != AV_SAMPLE_FMT_S16) fprintf(stderr, "Warning, using s16 intermediate sample format for resampling\n"); ost->resample = av_audio_resample_init(enc->channels, dec->channels, @@ -2287,6 +2318,17 @@ static int transcode(AVFormatContext **output_files, ret = AVERROR(EINVAL); goto dump_format; } + + /* update requested sample format for the decoder based on the + corresponding encoder sample format */ + for (j = 0; j < nb_ostreams; j++) { + ost = ost_table[j]; + if (ost->source_index == i) { + update_sample_fmt(ist->st->codec, codec, ost->st->codec); + break; + } + } + if (avcodec_open(ist->st->codec, codec) < 0) { snprintf(error, sizeof(error), "Error while opening decoder for input stream #%d.%d", ist->file_index, ist->index); @@ -3163,6 +3205,23 @@ static void opt_input_file(const char *filename) ic->loop_input = loop_input; + /* Set AVCodecContext options so they will be seen by av_find_stream_info() */ + for (i = 0; i < ic->nb_streams; i++) { + AVCodecContext *dec = ic->streams[i]->codec; + switch (dec->codec_type) { + case AVMEDIA_TYPE_AUDIO: + set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_AUDIO], + AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM, + NULL); + break; + case AVMEDIA_TYPE_VIDEO: + set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_VIDEO], + AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM, + NULL); + break; + } + } + /* If not enough info to get the stream parameters, we decode the first frames to get it. (used in mpeg case for example) */ ret = av_find_stream_info(ic); diff --git a/ffplay.c b/ffplay.c index 18010ef..cb3c5b8 100644 --- a/ffplay.c +++ b/ffplay.c @@ -2416,6 +2416,23 @@ static int decode_thread(void *arg) if(genpts) ic->flags |= AVFMT_FLAG_GENPTS; + /* Set AVCodecContext options so they will be seen by av_find_stream_info() */ + for (i = 0; i < ic->nb_streams; i++) { + AVCodecContext *dec = ic->streams[i]->codec; + switch (dec->codec_type) { + case AVMEDIA_TYPE_AUDIO: + set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_AUDIO], + AV_OPT_FLAG_AUDIO_PARAM | AV_OPT_FLAG_DECODING_PARAM, + NULL); + break; + case AVMEDIA_TYPE_VIDEO: + set_context_opts(dec, avcodec_opts[AVMEDIA_TYPE_VIDEO], + AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM, + NULL); + break; + } + } + err = av_find_stream_info(ic); if (err < 0) { fprintf(stderr, "%s: could not find codec parameters\n", is->filename);
_______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel