diff --git a/doc/ffplay.texi b/doc/ffplay.texi index 556fc39ebc..45731a2dc6 100644 --- a/doc/ffplay.texi +++ b/doc/ffplay.texi @@ -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 diff --git a/ffplay.c b/ffplay.c index bd156dfb7d..655af6ddaa 100644 --- 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" },