ffplay: add support for stream specifiers in -ast, -vst, -sst options
authorMarton Balint <cus@passwd.hu>
Sat, 20 Dec 2014 17:18:48 +0000 (18:18 +0100)
committerMarton Balint <cus@passwd.hu>
Thu, 1 Jan 2015 13:38:12 +0000 (14:38 +0100)
Also fix the outdated documentation of these options.

Signed-off-by: Marton Balint <cus@passwd.hu>
doc/ffplay.texi
ffplay.c

index 556fc39..45731a2 100644 (file)
@@ -124,21 +124,20 @@ master clock is used to control audio-video synchronization. Most media
 players use audio as master clock, but in some cases (streaming or high
 quality broadcast) it is necessary to change that. This option is mainly
 used for debugging purposes.
-@item -ast @var{audio_stream_number}
-Select the desired audio stream number, counting from 0. The number
-refers to the list of all the input audio streams. If it is greater
-than the number of audio streams minus one, then the last one is
-selected, if it is negative the audio playback is disabled.
-@item -vst @var{video_stream_number}
-Select the desired video stream number, counting from 0. The number
-refers to the list of all the input video streams. If it is greater
-than the number of video streams minus one, then the last one is
-selected, if it is negative the video playback is disabled.
-@item -sst @var{subtitle_stream_number}
-Select the desired subtitle stream number, counting from 0. The number
-refers to the list of all the input subtitle streams. If it is greater
-than the number of subtitle streams minus one, then the last one is
-selected, if it is negative the subtitle rendering is disabled.
+@item -ast @var{audio_stream_specifier}
+Select the desired audio stream using the given stream specifier. The stream
+specifiers are described in the @ref{Stream specifiers} chapter. If this option
+is not specified, the "best" audio stream is selected in the program of the
+already selected video stream.
+@item -vst @var{video_stream_specifier}
+Select the desired video stream using the given stream specifier. The stream
+specifiers are described in the @ref{Stream specifiers} chapter. If this option
+is not specified, the "best" video stream is selected.
+@item -sst @var{subtitle_stream_specifier}
+Select the desired subtitle stream using the given stream specifier. The stream
+specifiers are described in the @ref{Stream specifiers} chapter. If this option
+is not specified, the "best" subtitle stream is selected in the program of the
+already selected video or audio stream.
 @item -autoexit
 Exit when video is done playing.
 @item -exitonkeydown
index bd156df..655af6d 100644 (file)
--- a/ffplay.c
+++ b/ffplay.c
@@ -312,11 +312,7 @@ static int screen_height = 0;
 static int audio_disable;
 static int video_disable;
 static int subtitle_disable;
-static int wanted_stream[AVMEDIA_TYPE_NB] = {
-    [AVMEDIA_TYPE_AUDIO]    = -1,
-    [AVMEDIA_TYPE_VIDEO]    = -1,
-    [AVMEDIA_TYPE_SUBTITLE] = -1,
-};
+static const char* wanted_stream_spec[AVMEDIA_TYPE_NB] = {0};
 static int seek_by_bytes = -1;
 static int display_disable;
 static int show_status = 1;
@@ -2963,22 +2959,35 @@ static int read_thread(void *arg)
 
     is->realtime = is_realtime(ic);
 
-    for (i = 0; i < ic->nb_streams; i++)
-        ic->streams[i]->discard = AVDISCARD_ALL;
+    for (i = 0; i < ic->nb_streams; i++) {
+        AVStream *st = ic->streams[i];
+        enum AVMediaType type = st->codec->codec_type;
+        st->discard = AVDISCARD_ALL;
+        if (wanted_stream_spec[type] && st_index[type] == -1)
+            if (avformat_match_stream_specifier(ic, st, wanted_stream_spec[type]) > 0)
+                st_index[type] = i;
+    }
+    for (i = 0; i < AVMEDIA_TYPE_NB; i++) {
+        if (wanted_stream_spec[i] && st_index[i] == -1) {
+            av_log(NULL, AV_LOG_ERROR, "Stream specifier %s does not match any %s stream\n", wanted_stream_spec[i], av_get_media_type_string(i));
+            st_index[i] = INT_MAX;
+        }
+    }
+
     if (!video_disable)
         st_index[AVMEDIA_TYPE_VIDEO] =
             av_find_best_stream(ic, AVMEDIA_TYPE_VIDEO,
-                                wanted_stream[AVMEDIA_TYPE_VIDEO], -1, NULL, 0);
+                                st_index[AVMEDIA_TYPE_VIDEO], -1, NULL, 0);
     if (!audio_disable)
         st_index[AVMEDIA_TYPE_AUDIO] =
             av_find_best_stream(ic, AVMEDIA_TYPE_AUDIO,
-                                wanted_stream[AVMEDIA_TYPE_AUDIO],
+                                st_index[AVMEDIA_TYPE_AUDIO],
                                 st_index[AVMEDIA_TYPE_VIDEO],
                                 NULL, 0);
     if (!video_disable && !subtitle_disable)
         st_index[AVMEDIA_TYPE_SUBTITLE] =
             av_find_best_stream(ic, AVMEDIA_TYPE_SUBTITLE,
-                                wanted_stream[AVMEDIA_TYPE_SUBTITLE],
+                                st_index[AVMEDIA_TYPE_SUBTITLE],
                                 (st_index[AVMEDIA_TYPE_AUDIO] >= 0 ?
                                  st_index[AVMEDIA_TYPE_AUDIO] :
                                  st_index[AVMEDIA_TYPE_VIDEO]),
@@ -3669,9 +3678,9 @@ static const OptionDef options[] = {
     { "an", OPT_BOOL, { &audio_disable }, "disable audio" },
     { "vn", OPT_BOOL, { &video_disable }, "disable video" },
     { "sn", OPT_BOOL, { &subtitle_disable }, "disable subtitling" },
-    { "ast", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_number" },
-    { "vst", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_number" },
-    { "sst", OPT_INT | HAS_ARG | OPT_EXPERT, { &wanted_stream[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_number" },
+    { "ast", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_AUDIO] }, "select desired audio stream", "stream_specifier" },
+    { "vst", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_VIDEO] }, "select desired video stream", "stream_specifier" },
+    { "sst", OPT_STRING | HAS_ARG | OPT_EXPERT, { &wanted_stream_spec[AVMEDIA_TYPE_SUBTITLE] }, "select desired subtitle stream", "stream_specifier" },
     { "ss", HAS_ARG, { .func_arg = opt_seek }, "seek to a given position in seconds", "pos" },
     { "t", HAS_ARG, { .func_arg = opt_duration }, "play  \"duration\" seconds of audio/video", "duration" },
     { "bytes", OPT_INT | HAS_ARG, { &seek_by_bytes }, "seek by bytes 0=off 1=on -1=auto", "val" },