[FFmpeg-devel] [PATCH] av_find_best_stream

Stefano Sabatini stefano.sabatini-lala
Tue Dec 21 17:43:06 CET 2010


On date Sunday 2010-12-19 14:34:11 +0100, Nicolas George encoded:
> Hi.
> 
> The attached patch implements the av_find_best_stream, as discussed in a
> recent thread. The API is different from the one I suggested back then, I
> think this version is less likely to need change soon (because of new media
> types for example).
> 
> The patch also changes ffplay to use the new function; this part should
> probably go to a separate commit. I tested ffplay with hpim0074.mpg from
> issue #1668, it works.
> 
> Regards,
> 
> -- 
>   Nicolas George

>  doc/APIchanges         |    3 +++
>  ffplay.c               |   40 ++++++++++++----------------------------
>  libavformat/avformat.h |   24 ++++++++++++++++++++++++
>  libavformat/utils.c    |   39 +++++++++++++++++++++++++++++++++++++++
>  4 files changed, 78 insertions(+), 28 deletions(-)
> 
> diff --git a/doc/APIchanges b/doc/APIchanges
> index 9612a9f..99752b9 100644
> --- a/doc/APIchanges
> +++ b/doc/APIchanges
> @@ -13,6 +13,9 @@ libavutil:   2009-03-08
>  
>  API changes, most recent first:
>  
> +2010-12-XX - r260XX - lavformat 52.XX.0 - av_find_best_stream()
> +  Add av_find_best_stream to libavformat/avformat.h.
> +
>  2010-12-19 - r26056 - lavutil 50.35.0 - error.h
>    Add "not found" error codes:
>    AVERROR_DEMUXER_NOT_FOUND
> diff --git a/ffplay.c b/ffplay.c
> index 38a2fe1..8229005 100644
> --- a/ffplay.c
> +++ b/ffplay.c
> @@ -2398,8 +2398,6 @@ static int decode_thread(void *arg)
>      AVFormatContext *ic;
>      int err, i, ret;
>      int st_index[AVMEDIA_TYPE_NB];
> -    int st_count[AVMEDIA_TYPE_NB]={0};
> -    int st_best_packet_count[AVMEDIA_TYPE_NB];
>      AVPacket pkt1, *pkt = &pkt1;
>      AVFormatParameters params, *ap = ¶ms;
>      int eof=0;
> @@ -2408,7 +2406,6 @@ static int decode_thread(void *arg)
>      ic = avformat_alloc_context();
>  
>      memset(st_index, -1, sizeof(st_index));
> -    memset(st_best_packet_count, -1, sizeof(st_best_packet_count));
>      is->video_stream = -1;
>      is->audio_stream = -1;
>      is->subtitle_stream = -1;
> @@ -2464,32 +2461,19 @@ static int decode_thread(void *arg)
>          }
>      }
>  
> -    for(i = 0; i < ic->nb_streams; i++) {
> -        AVStream *st= ic->streams[i];
> -        AVCodecContext *avctx = st->codec;
> +    for (i = 0; i < ic->nb_streams; i++)
>          ic->streams[i]->discard = AVDISCARD_ALL;
> -        if(avctx->codec_type >= (unsigned)AVMEDIA_TYPE_NB)
> -            continue;
> -        if(st_count[avctx->codec_type]++ != wanted_stream[avctx->codec_type] && wanted_stream[avctx->codec_type] >= 0)
> -            continue;
> -
> -        if(st_best_packet_count[avctx->codec_type] >= st->codec_info_nb_frames)
> -            continue;
> -        st_best_packet_count[avctx->codec_type]= st->codec_info_nb_frames;
> -
> -        switch(avctx->codec_type) {
> -        case AVMEDIA_TYPE_AUDIO:
> -            if (!audio_disable)
> -                st_index[AVMEDIA_TYPE_AUDIO] = i;
> -            break;
> -        case AVMEDIA_TYPE_VIDEO:
> -        case AVMEDIA_TYPE_SUBTITLE:
> -            if (!video_disable)
> -                st_index[avctx->codec_type] = i;
> -            break;
> -        default:
> -            break;
> -        }
> +    if (!audio_disable)
> +        st_index[AVMEDIA_TYPE_AUDIO] =
> +            av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO,
> +                                wanted_stream[AVMEDIA_TYPE_AUDIO], NULL, 0);
> +    if (!video_disable) {
> +        st_index[AVMEDIA_TYPE_VIDEO] =
> +            av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO,
> +                                wanted_stream[AVMEDIA_TYPE_VIDEO], NULL, 0);
> +        st_index[AVMEDIA_TYPE_SUBTITLE] =
> +            av_find_best_stream(ic, AVMEDIA_TYPE_SUBTITLE,
> +                                wanted_stream[AVMEDIA_TYPE_SUBTITLE], NULL, 0);
>      }
>      if (show_status) {
>          dump_format(ic, 0, is->filename, 0);
> diff --git a/libavformat/avformat.h b/libavformat/avformat.h
> index 3079b38..9056a9c 100644
> --- a/libavformat/avformat.h
> +++ b/libavformat/avformat.h
> @@ -1140,6 +1140,30 @@ AVFormatContext *avformat_alloc_context(void);
>  int av_find_stream_info(AVFormatContext *ic);
>  
>  /**
> + * Find the "best" stream in the file.
> + * The best stream is determined according to various heuristics as the most
> + * likely to be what the user expects.
> + * @param ic       media file handle.

Nit: missing empty line before @param; also I suggest fmtctx or avctx
and no need for the ending point (no complete sentence)

> + * @param type     stream type: video, audio, subtitles, etc.

> + * @param user     user-requested stream number, or -1.

-1 for enabling automatic selection I suppose, same for the final
 trailing dot

> + * @param decoder  if not NULL, returns the default decoder for the stream's
> + *                 codec; streams for which no decoder can be found are
> + *                 ignored.

I'd put this into the main description, since this affects the
function behavior.

> + * @param flags    flags; none are currently defied.

defied -> defined, also skip the trailing dot

> + * @return  the non-negative stream number in case of success,
> + *          AVERROR_STREAM_NOT_FOUND if no stream with the requested type
> + *          could be found,
> + *          AVERROR_DECODER_NOT_FOUND if streams were found but no decoder.
> + * @note  If av_find_best_stream returns successfully and codec is not NULL,
> + *        then *codec is guaranteed to be set to a valid AVCodec.
> + */
> +int av_find_best_stream(AVFormatContext *ic,
> +                        enum AVMediaType type,
> +                        int user,
> +                        AVCodec **decoder,
> +                        int flags);
> +
> +/**
>   * Read a transport packet from a media file.
>   *
>   * This function is obsolete and should never be used.
> diff --git a/libavformat/utils.c b/libavformat/utils.c
> index c8e6d66..3eca5de 100644
> --- a/libavformat/utils.c
> +++ b/libavformat/utils.c
> @@ -2457,6 +2457,45 @@ int av_find_stream_info(AVFormatContext *ic)
>      return ret;
>  }
>  
> +int av_find_best_stream(AVFormatContext *ic,
> +                        enum AVMediaType type,
> +                        int user,
> +                        AVCodec **decoder,
> +                        int flags)
> +{
> +    int i;
> +    int ret = AVERROR_STREAM_NOT_FOUND;
> +    int snum = 0;

I suggest st_nb or something more explicit about the term "stream",
also you can merge many int declaration in one line.

> +    int best_count = -1;

> +    AVCodec *dec = NULL, *best_dec = NULL;
> +
> +    for (i = 0; i < ic->nb_streams; i++) {
> +        AVStream *st= ic->streams[i];
> +        AVCodecContext *avctx = st->codec;
> +        ic->streams[i]->discard = AVDISCARD_ALL;
> +        if (avctx->codec_type != type)
> +            continue;
> +        if (user >= 0 && snum++ != user)
> +            continue;
> +        if (decoder) {
> +            dec = avcodec_find_decoder(ic->streams[i]->codec->codec_id);
> +            if (!dec) {
> +                if (ret < 0)
> +                    ret = AVERROR_DECODER_NOT_FOUND;
> +                continue;
> +            }
> +        }
> +        if (best_count >= st->codec_info_nb_frames)
> +            continue;
> +        best_count = st->codec_info_nb_frames;
> +        ret = i;
> +        best_dec = dec;
> +    }
> +    if (decoder)
> +        *decoder = best_dec;
> +    return ret;
> +}

No more nits from me.
-- 
FFmpeg = Fancy and Fantastic Mastering Patchable Ecumenical Geisha



More information about the ffmpeg-devel mailing list