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>
... | ... |
@@ -1272,7 +1272,8 @@ Several bitstream filters can be specified, separated by ",". |
1272 | 1272 |
@item select |
1273 | 1273 |
Select the streams that should be mapped to the slave output, |
1274 | 1274 |
specified by a stream specifier. If not specified, this defaults to |
1275 |
-all the input streams. |
|
1275 |
+all the input streams. You may use multiple stream specifiers |
|
1276 |
+separated by commas (@code{,}) e.g.: @code{a:0,v} |
|
1276 | 1277 |
@end table |
1277 | 1278 |
|
1278 | 1279 |
@subsection Examples |
... | ... |
@@ -47,6 +47,7 @@ static const char *const slave_opt_open = "["; |
47 | 47 |
static const char *const slave_opt_close = "]"; |
48 | 48 |
static const char *const slave_opt_delim = ":]"; /* must have the close too */ |
49 | 49 |
static const char *const slave_bsfs_spec_sep = "/"; |
50 |
+static const char *const slave_select_sep = ","; |
|
50 | 51 |
|
51 | 52 |
static const AVClass tee_muxer_class = { |
52 | 53 |
.class_name = "Tee muxer", |
... | ... |
@@ -142,6 +143,8 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave) |
142 | 142 |
AVFormatContext *avf2 = NULL; |
143 | 143 |
AVStream *st, *st2; |
144 | 144 |
int stream_count; |
145 |
+ int fullret; |
|
146 |
+ char *subselect = NULL, *next_subselect = NULL, *first_subselect = NULL, *tmp_select = NULL; |
|
145 | 147 |
|
146 | 148 |
if ((ret = parse_slave_options(avf, slave, &options, &filename)) < 0) |
147 | 149 |
return ret; |
... | ... |
@@ -172,15 +175,32 @@ static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave) |
172 | 172 |
for (i = 0; i < avf->nb_streams; i++) { |
173 | 173 |
st = avf->streams[i]; |
174 | 174 |
if (select) { |
175 |
- ret = avformat_match_stream_specifier(avf, avf->streams[i], select); |
|
176 |
- if (ret < 0) { |
|
177 |
- av_log(avf, AV_LOG_ERROR, |
|
178 |
- "Invalid stream specifier '%s' for output '%s'\n", |
|
179 |
- select, slave); |
|
175 |
+ tmp_select = av_strdup(select); // av_strtok is destructive so we regenerate it in each loop |
|
176 |
+ if (!tmp_select) { |
|
177 |
+ ret = AVERROR(ENOMEM); |
|
180 | 178 |
goto end; |
181 | 179 |
} |
180 |
+ fullret = 0; |
|
181 |
+ first_subselect = tmp_select; |
|
182 |
+ next_subselect = NULL; |
|
183 |
+ while (subselect = av_strtok(first_subselect, slave_select_sep, &next_subselect)) { |
|
184 |
+ first_subselect = NULL; |
|
185 |
+ |
|
186 |
+ ret = avformat_match_stream_specifier(avf, avf->streams[i], subselect); |
|
187 |
+ if (ret < 0) { |
|
188 |
+ av_log(avf, AV_LOG_ERROR, |
|
189 |
+ "Invalid stream specifier '%s' for output '%s'\n", |
|
190 |
+ subselect, slave); |
|
191 |
+ goto end; |
|
192 |
+ } |
|
193 |
+ if (ret != 0) { |
|
194 |
+ fullret = 1; // match |
|
195 |
+ break; |
|
196 |
+ } |
|
197 |
+ } |
|
198 |
+ av_freep(&tmp_select); |
|
182 | 199 |
|
183 |
- if (ret == 0) { /* no match */ |
|
200 |
+ if (fullret == 0) { /* no match */ |
|
184 | 201 |
tee_slave->stream_map[i] = -1; |
185 | 202 |
continue; |
186 | 203 |
} |
... | ... |
@@ -282,6 +302,7 @@ end: |
282 | 282 |
av_free(format); |
283 | 283 |
av_free(select); |
284 | 284 |
av_dict_free(&options); |
285 |
+ av_freep(&tmp_select); |
|
285 | 286 |
return ret; |
286 | 287 |
} |
287 | 288 |
|