On 04/25/2011 10:14 AM, Ronald S. Bultje wrote:
> Hi,
>
> On Sun, Apr 24, 2011 at 10:06 PM, Justin Ruggles
> <[email protected]> wrote:
>> ---
>> Updated patch.
>> Need to initialize resampling if sample rate changes mid-stream.
>>
>> ffmpeg.c | 63
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>> ffplay.c | 17 ++++++++++++++++
>> 2 files changed, 78 insertions(+), 2 deletions(-)
> [..]
>> +/**
>> + * 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;
>> + }
>> + }
>> + }
>> + }
>> +}
>
> This smells a little like a hack. How about:
Well, I see what you mean. It's written specifically for decoders that
support S16 or FLT. I decided to make it less generic because ideally
we would like to remove this function rather than expand its use.
> /* if decoder supports more than one output format */
> if (dec_codec->sample_fmts[0] != AV_SAMPLE_FMT_NONE &&
> dec_codec->sample_fmts[1] != AV_SAMPLE_FMT_NONE) {
> int min_dec = -1, min_inc = -1;
>
> /* 1) find a matching one */
> for (p = dec_codec->sample_fmts; *p != AV_SAMPLE_FMT_NONE; p++) {
> if (*p == enc->sample_fmt) {
> dec->request_sample_fmt = *p;
> return;
> } else if (*p > enc->sample_fmt) {
> min_inc = FFMIN(min_inc, *p - enc->sample_fmt);
> } else
> min_dec = FFMIN(min_dec, enc->sample_fmt - *p);
> }
>
> /* if none match, provide the one that matches quality closest */
> dec->request_sample_fmt = min_inc > 0 ? enc->sample_fmt + min_inc
> : enc->sample_fmt - min_dec;
> }
>
> That would be a little bit more generic.
That looks fine though. It's simple enough. I'll integrate it into the
next patch revision.
>> @@ -3163,6 +3205,23 @@ static void opt_input_file(const char *filename)
>> + 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;
>> + }
>> + }
> [..]
>> diff --git a/ffplay.c b/ffplay.c
> [..]
>> @@ -2416,6 +2416,23 @@ static int decode_thread(void *arg)
>> + /* 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;
>> + }
>> + }
>
> Can possibly be generalized in cmdutils.c...
possibly... it doesn't do much though. if not for the flags it would
basically be a loop around set_context_opts().
i can shorten it if you want. :)
for (i = 0; i < ic->nb_streams; i++) {
AVCodecContext *dec = ic->streams[i]->codec;
int oflag = 0;
switch (dec->codec_type) {
case AVMEDIA_TYPE_AUDIO: oflag = AVMEDIA_TYPE_AUDIO; break;
case AVMEDIA_TYPE_VIDEO: oflag = AVMEDIA_TYPE_VIDEO; break;
}
if (oflag)
set_context_opts(dec, avcodec_opts[dec->codec_type],
oflag | AV_OPT_FLAG_DECODING_PARAM, NULL);
}
Thanks,
Justin
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel