3 * Copyright (c) 2012 Nicolas George
5 * This file is part of FFmpeg.
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public License
9 * as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with FFmpeg; if not, write to the Free Software * Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 #include "libavutil/avutil.h"
24 #include "libavutil/avstring.h"
25 #include "libavutil/mem.h"
26 #include "libavutil/opt.h"
27 #include "libavcodec/bsf.h"
31 #include "tee_common.h"
34 ON_SLAVE_FAILURE_ABORT
= 1,
35 ON_SLAVE_FAILURE_IGNORE
= 2
38 #define DEFAULT_SLAVE_FAILURE_POLICY ON_SLAVE_FAILURE_ABORT
42 AVBSFContext
**bsfs
; ///< bitstream filters per stream
44 SlaveFailurePolicy on_fail
;
46 AVDictionary
*fifo_options
;
48 /** map from input to output streams indexes,
49 * disabled output streams are set to -1 */
54 typedef struct TeeContext
{
60 AVDictionary
*fifo_options
;
63 static const char *const slave_delim
= "|";
64 static const char *const slave_bsfs_spec_sep
= "/";
65 static const char *const slave_select_sep
= ",";
67 #define OFFSET(x) offsetof(TeeContext, x)
68 static const AVOption options
[] = {
69 {"use_fifo", "Use fifo pseudo-muxer to separate actual muxers from encoder",
70 OFFSET(use_fifo
), AV_OPT_TYPE_BOOL
, {.i64
= 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM
},
71 {"fifo_options", "fifo pseudo-muxer options", OFFSET(fifo_options
),
72 AV_OPT_TYPE_DICT
, {.str
= NULL
}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM
},
76 static const AVClass tee_muxer_class
= {
77 .class_name
= "Tee muxer",
78 .item_name
= av_default_item_name
,
80 .version
= LIBAVUTIL_VERSION_INT
,
83 static inline int parse_slave_failure_policy_option(const char *opt
, TeeSlave
*tee_slave
)
86 tee_slave
->on_fail
= DEFAULT_SLAVE_FAILURE_POLICY
;
88 } else if (!av_strcasecmp("abort", opt
)) {
89 tee_slave
->on_fail
= ON_SLAVE_FAILURE_ABORT
;
91 } else if (!av_strcasecmp("ignore", opt
)) {
92 tee_slave
->on_fail
= ON_SLAVE_FAILURE_IGNORE
;
95 /* Set failure behaviour to abort, so invalid option error will not be ignored */
96 tee_slave
->on_fail
= ON_SLAVE_FAILURE_ABORT
;
97 return AVERROR(EINVAL
);
100 static int parse_slave_fifo_policy(const char *use_fifo
, TeeSlave
*tee_slave
)
102 /*TODO - change this to use proper function for parsing boolean
103 * options when there is one */
104 if (av_match_name(use_fifo
, "true,y,yes,enable,enabled,on,1")) {
105 tee_slave
->use_fifo
= 1;
106 } else if (av_match_name(use_fifo
, "false,n,no,disable,disabled,off,0")) {
107 tee_slave
->use_fifo
= 0;
109 return AVERROR(EINVAL
);
114 static int parse_slave_fifo_options(const char *fifo_options
, TeeSlave
*tee_slave
)
116 return av_dict_parse_string(&tee_slave
->fifo_options
, fifo_options
, "=", ":", 0);
119 static int close_slave(TeeSlave
*tee_slave
)
121 AVFormatContext
*avf
;
124 av_dict_free(&tee_slave
->fifo_options
);
125 avf
= tee_slave
->avf
;
129 if (tee_slave
->header_written
)
130 ret
= av_write_trailer(avf
);
132 if (tee_slave
->bsfs
) {
133 for (unsigned i
= 0; i
< avf
->nb_streams
; ++i
)
134 av_bsf_free(&tee_slave
->bsfs
[i
]);
136 av_freep(&tee_slave
->stream_map
);
137 av_freep(&tee_slave
->bsfs
);
139 ff_format_io_close(avf
, &avf
->pb
);
140 avformat_free_context(avf
);
141 tee_slave
->avf
= NULL
;
145 static void close_slaves(AVFormatContext
*avf
)
147 TeeContext
*tee
= avf
->priv_data
;
149 for (unsigned i
= 0; i
< tee
->nb_slaves
; i
++) {
150 close_slave(&tee
->slaves
[i
]);
152 av_freep(&tee
->slaves
);
155 static int open_slave(AVFormatContext
*avf
, char *slave
, TeeSlave
*tee_slave
)
158 AVDictionary
*options
= NULL
, *bsf_options
= NULL
;
159 const AVDictionaryEntry
*entry
;
161 char *format
= NULL
, *select
= NULL
;
162 AVFormatContext
*avf2
= NULL
;
165 char *subselect
= NULL
, *next_subselect
= NULL
, *first_subselect
= NULL
, *tmp_select
= NULL
;
167 if ((ret
= ff_tee_parse_slave_options(avf
, slave
, &options
, &filename
)) < 0)
170 tee_slave
->on_fail
= DEFAULT_SLAVE_FAILURE_POLICY
;
172 #define CONSUME_OPTION(option, field, action) do { \
173 AVDictionaryEntry *en = av_dict_get(options, option, NULL, 0); \
177 av_dict_set(&options, option, NULL, 0); \
180 #define STEAL_OPTION(option, field) \
181 CONSUME_OPTION(option, field, \
182 en->value = NULL; /* prevent it from being freed */)
183 #define PROCESS_OPTION(option, function, on_error) do { \
185 CONSUME_OPTION(option, value, if ((ret = function) < 0) \
186 { { on_error } goto end; }); \
189 STEAL_OPTION("f", format
);
190 STEAL_OPTION("select", select
);
191 PROCESS_OPTION("onfail",
192 parse_slave_failure_policy_option(value
, tee_slave
),
193 av_log(avf
, AV_LOG_ERROR
, "Invalid onfail option value, "
194 "valid options are 'abort' and 'ignore'\n"););
195 PROCESS_OPTION("use_fifo",
196 parse_slave_fifo_policy(value
, tee_slave
),
197 av_log(avf
, AV_LOG_ERROR
, "Error parsing fifo options: %s\n",
199 PROCESS_OPTION("fifo_options",
200 parse_slave_fifo_options(value
, tee_slave
), ;);
202 while ((entry
= av_dict_get(options
, "bsfs", NULL
, AV_DICT_IGNORE_SUFFIX
))) {
203 /* trim out strlen("bsfs") characters from key */
204 av_dict_set(&bsf_options
, entry
->key
+ 4, entry
->value
, 0);
205 av_dict_set(&options
, entry
->key
, NULL
, 0);
208 if (tee_slave
->use_fifo
) {
211 char *format_options_str
= NULL
;
212 ret
= av_dict_get_string(options
, &format_options_str
, '=', ':');
216 ret
= av_dict_set(&tee_slave
->fifo_options
, "format_opts", format_options_str
,
217 AV_DICT_DONT_STRDUP_VAL
);
223 ret
= av_dict_set(&tee_slave
->fifo_options
, "fifo_format", format
,
224 AV_DICT_DONT_STRDUP_VAL
);
230 av_dict_free(&options
);
231 options
= tee_slave
->fifo_options
;
232 tee_slave
->fifo_options
= NULL
;
234 ret
= avformat_alloc_output_context2(&avf2
, NULL
,
235 tee_slave
->use_fifo
? "fifo" :format
, filename
);
238 tee_slave
->avf
= avf2
;
239 av_dict_copy(&avf2
->metadata
, avf
->metadata
, 0);
240 avf2
->opaque
= avf
->opaque
;
241 avf2
->io_open
= avf
->io_open
;
242 avf2
->io_close2
= avf
->io_close2
;
243 avf2
->interrupt_callback
= avf
->interrupt_callback
;
244 avf2
->flags
= avf
->flags
;
245 avf2
->strict_std_compliance
= avf
->strict_std_compliance
;
247 tee_slave
->stream_map
= av_calloc(avf
->nb_streams
, sizeof(*tee_slave
->stream_map
));
248 if (!tee_slave
->stream_map
) {
249 ret
= AVERROR(ENOMEM
);
254 for (unsigned i
= 0; i
< avf
->nb_streams
; i
++) {
255 const AVStream
*st
= avf
->streams
[i
];
258 tmp_select
= av_strdup(select
); // av_strtok is destructive so we regenerate it in each loop
260 ret
= AVERROR(ENOMEM
);
264 first_subselect
= tmp_select
;
265 next_subselect
= NULL
;
266 while (subselect
= av_strtok(first_subselect
, slave_select_sep
, &next_subselect
)) {
267 first_subselect
= NULL
;
269 ret
= avformat_match_stream_specifier(avf
, avf
->streams
[i
], subselect
);
271 av_log(avf
, AV_LOG_ERROR
,
272 "Invalid stream specifier '%s' for output '%s'\n",
277 fullret
= 1; // match
281 av_freep(&tmp_select
);
283 if (fullret
== 0) { /* no match */
284 tee_slave
->stream_map
[i
] = -1;
288 tee_slave
->stream_map
[i
] = stream_count
++;
290 st2
= ff_stream_clone(avf2
, st
);
292 ret
= AVERROR(ENOMEM
);
297 ret
= ff_format_output_open(avf2
, filename
, &options
);
299 av_log(avf
, AV_LOG_ERROR
, "Slave '%s': error opening: %s\n", slave
,
304 if ((ret
= avformat_write_header(avf2
, &options
)) < 0) {
305 av_log(avf
, AV_LOG_ERROR
, "Slave '%s': error writing header: %s\n",
306 slave
, av_err2str(ret
));
309 tee_slave
->header_written
= 1;
311 tee_slave
->bsfs
= av_calloc(avf2
->nb_streams
, sizeof(*tee_slave
->bsfs
));
312 if (!tee_slave
->bsfs
) {
313 ret
= AVERROR(ENOMEM
);
318 while (entry
= av_dict_iterate(bsf_options
, NULL
)) {
319 const char *spec
= entry
->key
;
321 if (strspn(spec
, slave_bsfs_spec_sep
) != 1) {
322 av_log(avf
, AV_LOG_ERROR
,
323 "Specifier separator in '%s' is '%c', but only characters '%s' "
324 "are allowed\n", entry
->key
, *spec
, slave_bsfs_spec_sep
);
325 ret
= AVERROR(EINVAL
);
328 spec
++; /* consume separator */
331 for (unsigned i
= 0; i
< avf2
->nb_streams
; i
++) {
332 ret
= avformat_match_stream_specifier(avf2
, avf2
->streams
[i
], spec
);
334 av_log(avf
, AV_LOG_ERROR
,
335 "Invalid stream specifier '%s' in bsfs option '%s' for slave "
336 "output '%s'\n", spec
, entry
->key
, filename
);
341 av_log(avf
, AV_LOG_DEBUG
, "spec:%s bsfs:%s matches stream %d of slave "
342 "output '%s'\n", spec
, entry
->value
, i
, filename
);
343 if (tee_slave
->bsfs
[i
]) {
344 av_log(avf
, AV_LOG_WARNING
,
345 "Duplicate bsfs specification associated to stream %d of slave "
346 "output '%s', filters will be ignored\n", i
, filename
);
349 ret
= av_bsf_list_parse_str(entry
->value
, &tee_slave
->bsfs
[i
]);
351 av_log(avf
, AV_LOG_ERROR
,
352 "Error parsing bitstream filter sequence '%s' associated to "
353 "stream %d of slave output '%s'\n", entry
->value
, i
, filename
);
359 av_dict_set(&bsf_options
, entry
->key
, NULL
, 0);
362 for (unsigned i
= 0; i
< avf
->nb_streams
; i
++){
363 int target_stream
= tee_slave
->stream_map
[i
];
364 if (target_stream
< 0)
367 if (!tee_slave
->bsfs
[target_stream
]) {
368 /* Add pass-through bitstream filter */
369 ret
= av_bsf_get_null_filter(&tee_slave
->bsfs
[target_stream
]);
371 av_log(avf
, AV_LOG_ERROR
,
372 "Failed to create pass-through bitstream filter: %s\n",
378 tee_slave
->bsfs
[target_stream
]->time_base_in
= avf
->streams
[i
]->time_base
;
379 ret
= avcodec_parameters_copy(tee_slave
->bsfs
[target_stream
]->par_in
,
380 avf
->streams
[i
]->codecpar
);
384 ret
= av_bsf_init(tee_slave
->bsfs
[target_stream
]);
386 av_log(avf
, AV_LOG_ERROR
,
387 "Failed to initialize bitstream filter(s): %s\n",
395 while ((entry
= av_dict_iterate(options
, entry
)))
396 av_log(avf2
, AV_LOG_ERROR
, "Unknown option '%s'\n", entry
->key
);
397 ret
= AVERROR_OPTION_NOT_FOUND
;
404 av_dict_free(&options
);
405 av_dict_free(&bsf_options
);
406 av_freep(&tmp_select
);
410 static void log_slave(TeeSlave
*slave
, void *log_ctx
, int log_level
)
412 av_log(log_ctx
, log_level
, "filename:'%s' format:%s\n",
413 slave
->avf
->url
, slave
->avf
->oformat
->name
);
414 for (unsigned i
= 0; i
< slave
->avf
->nb_streams
; i
++) {
415 AVStream
*st
= slave
->avf
->streams
[i
];
416 AVBSFContext
*bsf
= slave
->bsfs
[i
];
417 const char *bsf_name
;
419 av_log(log_ctx
, log_level
, " stream:%d codec:%s type:%s",
420 i
, avcodec_get_name(st
->codecpar
->codec_id
),
421 av_get_media_type_string(st
->codecpar
->codec_type
));
423 bsf_name
= bsf
->filter
->priv_class
?
424 bsf
->filter
->priv_class
->item_name(bsf
) : bsf
->filter
->name
;
425 av_log(log_ctx
, log_level
, " bsfs: %s\n", bsf_name
);
429 static int tee_process_slave_failure(AVFormatContext
*avf
, unsigned slave_idx
, int err_n
)
431 TeeContext
*tee
= avf
->priv_data
;
432 TeeSlave
*tee_slave
= &tee
->slaves
[slave_idx
];
436 close_slave(tee_slave
);
438 if (!tee
->nb_alive
) {
439 av_log(avf
, AV_LOG_ERROR
, "All tee outputs failed.\n");
441 } else if (tee_slave
->on_fail
== ON_SLAVE_FAILURE_ABORT
) {
442 av_log(avf
, AV_LOG_ERROR
, "Slave muxer #%u failed, aborting.\n", slave_idx
);
445 av_log(avf
, AV_LOG_ERROR
, "Slave muxer #%u failed: %s, continuing with %u/%u slaves.\n",
446 slave_idx
, av_err2str(err_n
), tee
->nb_alive
, tee
->nb_slaves
);
451 static int tee_write_header(AVFormatContext
*avf
)
453 TeeContext
*tee
= avf
->priv_data
;
454 unsigned nb_slaves
= 0;
455 const char *filename
= avf
->url
;
456 char **slaves
= NULL
;
460 char *slave
= av_get_token(&filename
, slave_delim
);
462 ret
= AVERROR(ENOMEM
);
465 ret
= av_dynarray_add_nofree(&slaves
, &nb_slaves
, slave
);
470 if (strspn(filename
, slave_delim
))
474 if (!FF_ALLOCZ_TYPED_ARRAY(tee
->slaves
, nb_slaves
)) {
475 ret
= AVERROR(ENOMEM
);
478 tee
->nb_slaves
= tee
->nb_alive
= nb_slaves
;
480 for (unsigned i
= 0; i
< nb_slaves
; i
++) {
482 tee
->slaves
[i
].use_fifo
= tee
->use_fifo
;
483 ret
= av_dict_copy(&tee
->slaves
[i
].fifo_options
, tee
->fifo_options
, 0);
487 if ((ret
= open_slave(avf
, slaves
[i
], &tee
->slaves
[i
])) < 0) {
488 ret
= tee_process_slave_failure(avf
, i
, ret
);
492 log_slave(&tee
->slaves
[i
], avf
, AV_LOG_VERBOSE
);
494 av_freep(&slaves
[i
]);
497 for (unsigned i
= 0; i
< avf
->nb_streams
; i
++) {
499 for (unsigned j
= 0; j
< tee
->nb_slaves
; j
++)
500 if (tee
->slaves
[j
].avf
)
501 mapped
+= tee
->slaves
[j
].stream_map
[i
] >= 0;
503 av_log(avf
, AV_LOG_WARNING
, "Input stream #%d is not mapped "
504 "to any slave.\n", i
);
510 for (unsigned i
= 0; i
< nb_slaves
; i
++)
511 av_freep(&slaves
[i
]);
517 static int tee_write_trailer(AVFormatContext
*avf
)
519 TeeContext
*tee
= avf
->priv_data
;
520 int ret_all
= 0, ret
;
522 for (unsigned i
= 0; i
< tee
->nb_slaves
; i
++) {
523 if ((ret
= close_slave(&tee
->slaves
[i
])) < 0) {
524 ret
= tee_process_slave_failure(avf
, i
, ret
);
525 if (!ret_all
&& ret
< 0)
529 av_freep(&tee
->slaves
);
533 static int tee_write_packet(AVFormatContext
*avf
, AVPacket
*pkt
)
535 TeeContext
*tee
= avf
->priv_data
;
536 AVPacket
*const pkt2
= ffformatcontext(avf
)->pkt
;
537 int ret_all
= 0, ret
;
541 for (unsigned i
= 0; i
< tee
->nb_slaves
; i
++) {
542 AVFormatContext
*avf2
= tee
->slaves
[i
].avf
;
548 /* Flush slave if pkt is NULL*/
550 ret
= av_interleaved_write_frame(avf2
, NULL
);
552 ret
= tee_process_slave_failure(avf
, i
, ret
);
553 if (!ret_all
&& ret
< 0)
559 s
= pkt
->stream_index
;
560 s2
= tee
->slaves
[i
].stream_map
[s
];
564 if ((ret
= av_packet_ref(pkt2
, pkt
)) < 0) {
569 bsfs
= tee
->slaves
[i
].bsfs
[s2
];
570 pkt2
->stream_index
= s2
;
572 ret
= av_bsf_send_packet(bsfs
, pkt2
);
574 av_packet_unref(pkt2
);
575 av_log(avf
, AV_LOG_ERROR
, "Error while sending packet to bitstream filter: %s\n",
577 ret
= tee_process_slave_failure(avf
, i
, ret
);
578 if (!ret_all
&& ret
< 0)
583 ret
= av_bsf_receive_packet(bsfs
, pkt2
);
584 if (ret
== AVERROR(EAGAIN
)) {
587 } else if (ret
< 0) {
591 av_packet_rescale_ts(pkt2
, bsfs
->time_base_out
,
592 avf2
->streams
[s2
]->time_base
);
593 ret
= av_interleaved_write_frame(avf2
, pkt2
);
599 ret
= tee_process_slave_failure(avf
, i
, ret
);
600 if (!ret_all
&& ret
< 0)
607 const FFOutputFormat ff_tee_muxer
= {
609 .p
.long_name
= NULL_IF_CONFIG_SMALL("Multiple muxer tee"),
610 .priv_data_size
= sizeof(TeeContext
),
611 .write_header
= tee_write_header
,
612 .write_trailer
= tee_write_trailer
,
613 .write_packet
= tee_write_packet
,
614 .p
.priv_class
= &tee_muxer_class
,
615 .p
.flags
= AVFMT_NOFILE
| AVFMT_TS_NEGATIVE
,
616 .flags_internal
= FF_OFMT_FLAG_ALLOW_FLUSH
,