avformat/utils: Stream specifier enhancement

Currently when specifying the program id you can only decide to select
all stream of the specified program (e.g. p:103 will select all streams
of program 103) or narrow the selection to a specific stream sub index
(e.g. p:145:1 will select 2nd stream of program 145.) But you can not
specify like all audio streams of program 145 or 3rd video stream of
program 311.
In some case, mainly working with multiprogram mpeg-ts containers as
input, this feature would be handy.
This patch makes it possible to narrow the stream selection among
streams of the specified program by stream type and optionally its
index. Handled types: a, v, s, d.
Examples: p:601:a  will select all audio streams of program 601,
p:603:a:1 will select 2nd audio streams of program 603,
p:604:v:0 will select first video stream of program 604.

Signed-off-by: Bela Bodecs <bodecsb@vivanet.hu>
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
Bela Bodecs 2018-04-01 23:29:14 +02:00 committed by Michael Niedermayer
parent 4d544f6086
commit 37d0213968
2 changed files with 67 additions and 8 deletions

View File

@ -42,10 +42,14 @@ streams, 'V' only matches video streams which are not attached pictures, video
thumbnails or cover arts. If @var{stream_index} is given, then it matches
stream number @var{stream_index} of this type. Otherwise, it matches all
streams of this type.
@item p:@var{program_id}[:@var{stream_index}]
If @var{stream_index} is given, then it matches the stream with number @var{stream_index}
@item p:@var{program_id}[:@var{stream_index}] or p:@var{program_id}[:@var{stream_type}[:@var{stream_index}]]
In first version, if @var{stream_index} is given, then it matches the stream with number @var{stream_index}
in the program with the id @var{program_id}. Otherwise, it matches all streams in the
program.
program. In the latter version, @var{stream_type} is one of following: 'v' for video, 'a' for audio, 's'
for subtitle, 'd' for data. If @var{stream_index} is also given, then it matches
stream number @var{stream_index} of this type in the program with the id @var{program_id}.
Otherwise, if only @var{stream_type} is given, it matches all
streams of this type in the program with the id @var{program_id}.
@item #@var{stream_id} or i:@var{stream_id}
Match the stream by stream id (e.g. PID in MPEG-TS container).
@item m:@var{key}[:@var{value}]

View File

@ -5070,11 +5070,66 @@ FF_ENABLE_DEPRECATION_WARNINGS
if (s->programs[i]->id != prog_id)
continue;
if (*endptr++ == ':') {
int stream_idx = strtol(endptr, NULL, 0);
return stream_idx >= 0 &&
stream_idx < s->programs[i]->nb_stream_indexes &&
st->index == s->programs[i]->stream_index[stream_idx];
if (*endptr++ == ':') { // p:<id>:....
if ( *endptr == 'a' || *endptr == 'v' ||
*endptr == 's' || *endptr == 'd') { // p:<id>:<st_type>[:<index>]
enum AVMediaType type;
switch (*endptr++) {
case 'v': type = AVMEDIA_TYPE_VIDEO; break;
case 'a': type = AVMEDIA_TYPE_AUDIO; break;
case 's': type = AVMEDIA_TYPE_SUBTITLE; break;
case 'd': type = AVMEDIA_TYPE_DATA; break;
default: av_assert0(0);
}
if (*endptr++ == ':') { // p:<id>:<st_type>:<index>
int stream_idx = strtol(endptr, NULL, 0), type_counter = 0;
for (j = 0; j < s->programs[i]->nb_stream_indexes; j++) {
int stream_index = s->programs[i]->stream_index[j];
if (st->index == s->programs[i]->stream_index[j]) {
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
return type_counter == stream_idx &&
(type == st->codecpar->codec_type ||
type == st->codec->codec_type);
FF_ENABLE_DEPRECATION_WARNINGS
#else
return type_counter == stream_idx &&
type == st->codecpar->codec_type;
#endif
}
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
if (type == s->streams[stream_index]->codecpar->codec_type ||
type == s->streams[stream_index]->codec->codec_type)
type_counter++;
FF_ENABLE_DEPRECATION_WARNINGS
#else
if (type == s->streams[stream_index]->codecpar->codec_type)
type_counter++;
#endif
}
return 0;
} else { // p:<id>:<st_type>
for (j = 0; j < s->programs[i]->nb_stream_indexes; j++)
if (st->index == s->programs[i]->stream_index[j]) {
#if FF_API_LAVF_AVCTX
FF_DISABLE_DEPRECATION_WARNINGS
return type == st->codecpar->codec_type ||
type == st->codec->codec_type;
FF_ENABLE_DEPRECATION_WARNINGS
#else
return type == st->codecpar->codec_type;
#endif
}
return 0;
}
} else { // p:<id>:<index>
int stream_idx = strtol(endptr, NULL, 0);
return stream_idx >= 0 &&
stream_idx < s->programs[i]->nb_stream_indexes &&
st->index == s->programs[i]->stream_index[stream_idx];
}
}
for (j = 0; j < s->programs[i]->nb_stream_indexes; j++)