[FFmpeg-devel] [PATCH] av_find_best_stream

Stefano Sabatini stefano.sabatini-lala
Wed Dec 22 15:29:30 CET 2010


On date Wednesday 2010-12-22 10:12:01 +0100, Nicolas George encoded:
> Le primidi 1er niv?se, an CCXIX, Stefano Sabatini a ?crit?:
> > Uhm I believe you posted the old patch.
> 
> Indeed. Sorry anout that.
> 
> Regards,
> 
> -- 
>   Nicolas George

>  doc/APIchanges         |    3 +++
>  ffplay.c               |   40 ++++++++++++----------------------------
>  libavformat/avformat.h |   26 ++++++++++++++++++++++++++
>  libavformat/utils.c    |   36 ++++++++++++++++++++++++++++++++++++
>  4 files changed, 77 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..e1651bf 100644
> --- a/libavformat/avformat.h
> +++ b/libavformat/avformat.h
> @@ -1140,6 +1140,32 @@ 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.
> + * If the decoder parameter is not NULL, av_find_best_stream will find the
> + * default decoder for the stream's codec; streams for which no decoder can
> + * be found are ignored.
> + *
> + * @param ic       media file handle
> + * @param type     stream type: video, audio, subtitles, etc.

> + * @param user     user-requested stream number, or -1 for automatic selection

user is a confusing name, I'd prefer something like user_stream_nb or
wanted_stream_nb.

> + * @param decoder  if not NULL, returns the decoder for the stream's codec

not NULL -> non-NULL

"returns the decoder for the stream's codec"

a bit confusing, I suggest:
returns the decoder for the selected stream

> + * @param flags    flags; none are currently defined
> + * @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.

*codec -> *decoder (or ther other way change the parameter name as it
fits you best)

> + */
> +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..6c3ecce 100644
> --- a/libavformat/utils.c
> +++ b/libavformat/utils.c
> @@ -2457,6 +2457,42 @@ 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, ret = AVERROR_STREAM_NOT_FOUND, stream_number = 0, best_count = -1;
> +    AVCodec *dec = NULL, *best_dec = NULL;

dec and decoder -> confusing

my suggestion:
decoder_ptr
decoder
best_decoder

> +    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 && stream_number++ != 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;
> +}
-- 
FFmpeg = Friendly and Fostering Mean Perennial Ermetic Governor



More information about the ffmpeg-devel mailing list