lavf/tee: allow multiple stream specifiers in select.

It makes possible to put multiple stream specifier into the select
option separated by comma.
eg. select=\'a:0,v\'

Signed-off-by: Bela Bodecs <bodecsb@vivanet.hu>
Signed-off-by: Nicolas George <george@nsup.org>
pull/154/head
Bela Bodecs 9 years ago committed by Nicolas George
parent b3deaece87
commit 1f3a29e999
  1. 3
      doc/muxers.texi
  2. 27
      libavformat/tee.c

@ -1272,7 +1272,8 @@ Several bitstream filters can be specified, separated by ",".
@item select @item select
Select the streams that should be mapped to the slave output, Select the streams that should be mapped to the slave output,
specified by a stream specifier. If not specified, this defaults to specified by a stream specifier. If not specified, this defaults to
all the input streams. all the input streams. You may use multiple stream specifiers
separated by commas (@code{,}) e.g.: @code{a:0,v}
@end table @end table
@subsection Examples @subsection Examples

@ -47,6 +47,7 @@ static const char *const slave_opt_open = "[";
static const char *const slave_opt_close = "]"; static const char *const slave_opt_close = "]";
static const char *const slave_opt_delim = ":]"; /* must have the close too */ static const char *const slave_opt_delim = ":]"; /* must have the close too */
static const char *const slave_bsfs_spec_sep = "/"; static const char *const slave_bsfs_spec_sep = "/";
static const char *const slave_select_sep = ",";
static const AVClass tee_muxer_class = { static const AVClass tee_muxer_class = {
.class_name = "Tee muxer", .class_name = "Tee muxer",
@ -142,6 +143,8 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
AVFormatContext *avf2 = NULL; AVFormatContext *avf2 = NULL;
AVStream *st, *st2; AVStream *st, *st2;
int stream_count; int stream_count;
int fullret;
char *subselect = NULL, *next_subselect = NULL, *first_subselect = NULL, *tmp_select = NULL;
if ((ret = parse_slave_options(avf, slave, &options, &filename)) < 0) if ((ret = parse_slave_options(avf, slave, &options, &filename)) < 0)
return ret; return ret;
@ -172,15 +175,32 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
for (i = 0; i < avf->nb_streams; i++) { for (i = 0; i < avf->nb_streams; i++) {
st = avf->streams[i]; st = avf->streams[i];
if (select) { if (select) {
ret = avformat_match_stream_specifier(avf, avf->streams[i], select); tmp_select = av_strdup(select); // av_strtok is destructive so we regenerate it in each loop
if (!tmp_select) {
ret = AVERROR(ENOMEM);
goto end;
}
fullret = 0;
first_subselect = tmp_select;
next_subselect = NULL;
while (subselect = av_strtok(first_subselect, slave_select_sep, &next_subselect)) {
first_subselect = NULL;
ret = avformat_match_stream_specifier(avf, avf->streams[i], subselect);
if (ret < 0) { if (ret < 0) {
av_log(avf, AV_LOG_ERROR, av_log(avf, AV_LOG_ERROR,
"Invalid stream specifier '%s' for output '%s'\n", "Invalid stream specifier '%s' for output '%s'\n",
select, slave); subselect, slave);
goto end; goto end;
} }
if (ret != 0) {
fullret = 1; // match
break;
}
}
av_freep(&tmp_select);
if (ret == 0) { /* no match */ if (fullret == 0) { /* no match */
tee_slave->stream_map[i] = -1; tee_slave->stream_map[i] = -1;
continue; continue;
} }
@ -282,6 +302,7 @@ end:
av_free(format); av_free(format);
av_free(select); av_free(select);
av_dict_free(&options); av_dict_free(&options);
av_freep(&tmp_select);
return ret; return ret;
} }

Loading…
Cancel
Save