[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