[FFmpeg-devel] [PATCH] ffplay: fix and extend option -codec option

Marton Balint cus at passwd.hu
Sun Dec 9 20:03:03 CET 2012



On Sat, 8 Dec 2012, Stefano Sabatini wrote:

> Allow to specify the stream for which the codec name is set. Also make
> parsing and error reporting more robust.
> ---
> doc/ffplay.texi |    6 ++++--
> ffplay.c        |   50 ++++++++++++++++++++++++++++++++++++++++----------
> 2 files changed, 44 insertions(+), 12 deletions(-)
>
> diff --git a/doc/ffplay.texi b/doc/ffplay.texi
> index e2bded7..7923492 100644
> --- a/doc/ffplay.texi
> +++ b/doc/ffplay.texi
> @@ -134,8 +134,10 @@ Exit when video is done playing.
> Exit if any key is pressed.
> @item -exitonmousedown
> Exit if any mouse button is pressed.
> - at item -codec:@var{stream_type}
> -Force a specific decoder implementation
> +
> + at item -codec:@var{stream_specifier} @var{codec_name}
> +Force a specific decoder implementation for the stream specified by
> + at var{stream_specifier}.
> @end table
>
> @section While playing
> diff --git a/ffplay.c b/ffplay.c
> index d6b17c2..f4f924d 100644
> --- a/ffplay.c
> +++ b/ffplay.c
> @@ -92,6 +92,13 @@ const int program_birth_year = 2003;
>
> static int64_t sws_flags = SWS_BICUBIC;
>
> +typedef struct {
> +    const char *codec_name, *stream_specifier;
> +} StreamCodecSpecifier;
> +
> +StreamCodecSpecifier *stream_codec_specifiers = NULL;
> +int                nb_stream_codec_specifiers = 0;
> +
> typedef struct MyAVPacketList {
>     AVPacket pkt;
>     struct MyAVPacketList *next;
> @@ -299,9 +306,6 @@ static int loop = 1;
> static int framedrop = -1;
> static int infinite_buffer = -1;
> static enum ShowMode show_mode = SHOW_MODE_NONE;
> -static const char *audio_codec_name;
> -static const char *subtitle_codec_name;
> -static const char *video_codec_name;
> static int rdftspeed = 20;
> #if CONFIG_AVFILTER
> static char *vfilters = NULL;
> @@ -2302,6 +2306,7 @@ static int stream_component_open(VideoState *is, int stream_index)
>     AVCodec *codec;
>     AVDictionary *opts;
>     AVDictionaryEntry *t = NULL;
> +    int i, ret;
>
>     if (stream_index < 0 || stream_index >= ic->nb_streams)
>         return -1;
> @@ -2310,9 +2315,24 @@ static int stream_component_open(VideoState *is, int stream_index)
>     codec = avcodec_find_decoder(avctx->codec_id);
>
>     switch(avctx->codec_type){
> -        case AVMEDIA_TYPE_AUDIO   : is->last_audio_stream    = stream_index; if(audio_codec_name   ) codec= avcodec_find_decoder_by_name(   audio_codec_name); break;
> -        case AVMEDIA_TYPE_SUBTITLE: is->last_subtitle_stream = stream_index; if(subtitle_codec_name) codec= avcodec_find_decoder_by_name(subtitle_codec_name); break;
> -        case AVMEDIA_TYPE_VIDEO   : is->last_video_stream    = stream_index; if(video_codec_name   ) codec= avcodec_find_decoder_by_name(   video_codec_name); break;
> +        case AVMEDIA_TYPE_AUDIO   : is->last_audio_stream    = stream_index;
> +        case AVMEDIA_TYPE_SUBTITLE: is->last_subtitle_stream = stream_index;
> +        case AVMEDIA_TYPE_VIDEO   : is->last_video_stream    = stream_index;
> +    }
> +
> +    for (i = 0; i < nb_stream_codec_specifiers; i++) {
> +        ret = avformat_match_stream_specifier(ic, ic->streams[stream_index],
> +                                              stream_codec_specifiers[i].stream_specifier);
> +        if (ret > 0) {
> +            codec = avcodec_find_decoder_by_name(stream_codec_specifiers[i].codec_name);
> +            avctx->codec_id = codec->id;

Codec may be null, you should either check for !codec here, or put the 
assignment to the main code path after the !codec check later in the code.

> +            break;
> +        }
> +        if (ret < 0) {
> +            fprintf(stderr, "Invalid stream specifier '%s' was specified\n",
> +                    stream_codec_specifiers[i].stream_specifier);
> +            return AVERROR(EINVAL);
> +        }
>     }
>     if (!codec)
>         return -1;
> @@ -3149,11 +3169,21 @@ static void opt_input_file(void *optctx, const char *filename)
>
> static int opt_codec(void *o, const char *opt, const char *arg)
> {
> -    switch(opt[strlen(opt)-1]){
> -    case 'a' :    audio_codec_name = arg; break;
> -    case 's' : subtitle_codec_name = arg; break;
> -    case 'v' :    video_codec_name = arg; break;
> +    const char *specifier = strchr(opt, ':');
> +    if (!specifier) {
> +        fprintf(stderr, "No stream specifier was specified in option name '%s'\n", opt);
> +        return AVERROR(EINVAL);
>     }
> +    specifier++;
> +
> +    stream_codec_specifiers =
> +        grow_array(stream_codec_specifiers, sizeof(StreamCodecSpecifier),
> +                   &nb_stream_codec_specifiers, nb_stream_codec_specifiers+1);
> +    if (!stream_codec_specifiers)
> +        return AVERROR(ENOMEM);
> +
> +    stream_codec_specifiers[nb_stream_codec_specifiers-1].stream_specifier = specifier;
> +    stream_codec_specifiers[nb_stream_codec_specifiers-1].codec_name       = arg;
>     return 0;
> }
>

Otherwise LGTM, thanks.

Regards,
Marton


More information about the ffmpeg-devel mailing list