FFmpeg
tee.c
Go to the documentation of this file.
1 /*
2  * Tee pseudo-muxer
3  * Copyright (c) 2012 Nicolas George
4  *
5  * This file is part of FFmpeg.
6  *
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.
11  *
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.
16  *
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
20  */
21 
22 
23 #include "libavutil/avutil.h"
24 #include "libavutil/avstring.h"
25 #include "libavutil/opt.h"
26 #include "internal.h"
27 #include "avformat.h"
28 #include "avio_internal.h"
29 #include "tee_common.h"
30 
31 typedef enum {
35 
36 #define DEFAULT_SLAVE_FAILURE_POLICY ON_SLAVE_FAILURE_ABORT
37 
38 typedef struct {
40  AVBSFContext **bsfs; ///< bitstream filters per stream
41 
43  int use_fifo;
45 
46  /** map from input to output streams indexes,
47  * disabled output streams are set to -1 */
48  int *stream_map;
50 } TeeSlave;
51 
52 typedef struct TeeContext {
53  const AVClass *class;
54  unsigned nb_slaves;
55  unsigned nb_alive;
57  int use_fifo;
60 } TeeContext;
61 
62 static const char *const slave_delim = "|";
63 static const char *const slave_bsfs_spec_sep = "/";
64 static const char *const slave_select_sep = ",";
65 
66 #define OFFSET(x) offsetof(TeeContext, x)
67 static const AVOption options[] = {
68  {"use_fifo", "Use fifo pseudo-muxer to separate actual muxers from encoder",
70  {"fifo_options", "fifo pseudo-muxer options", OFFSET(fifo_options_str),
72  {NULL}
73 };
74 
75 static const AVClass tee_muxer_class = {
76  .class_name = "Tee muxer",
77  .item_name = av_default_item_name,
78  .option = options,
79  .version = LIBAVUTIL_VERSION_INT,
80 };
81 
82 static inline int parse_slave_failure_policy_option(const char *opt, TeeSlave *tee_slave)
83 {
84  if (!opt) {
86  return 0;
87  } else if (!av_strcasecmp("abort", opt)) {
88  tee_slave->on_fail = ON_SLAVE_FAILURE_ABORT;
89  return 0;
90  } else if (!av_strcasecmp("ignore", opt)) {
91  tee_slave->on_fail = ON_SLAVE_FAILURE_IGNORE;
92  return 0;
93  }
94  /* Set failure behaviour to abort, so invalid option error will not be ignored */
95  tee_slave->on_fail = ON_SLAVE_FAILURE_ABORT;
96  return AVERROR(EINVAL);
97 }
98 
99 static int parse_slave_fifo_options(const char *use_fifo,
100  const char *fifo_options, TeeSlave *tee_slave)
101 {
102  int ret = 0;
103 
104  if (use_fifo) {
105  /*TODO - change this to use proper function for parsing boolean
106  * options when there is one */
107  if (av_match_name(use_fifo, "true,y,yes,enable,enabled,on,1")) {
108  tee_slave->use_fifo = 1;
109  } else if (av_match_name(use_fifo, "false,n,no,disable,disabled,off,0")) {
110  tee_slave->use_fifo = 0;
111  } else {
112  return AVERROR(EINVAL);
113  }
114  }
115 
116  if (fifo_options)
117  ret = av_dict_parse_string(&tee_slave->fifo_options, fifo_options, "=", ":", 0);
118 
119  return ret;
120 }
121 
122 static int close_slave(TeeSlave *tee_slave)
123 {
124  AVFormatContext *avf;
125  unsigned i;
126  int ret = 0;
127 
128  avf = tee_slave->avf;
129  if (!avf)
130  return 0;
131 
132  if (tee_slave->header_written)
133  ret = av_write_trailer(avf);
134 
135  if (tee_slave->bsfs) {
136  for (i = 0; i < avf->nb_streams; ++i)
137  av_bsf_free(&tee_slave->bsfs[i]);
138  }
139  av_freep(&tee_slave->stream_map);
140  av_freep(&tee_slave->bsfs);
141 
142  ff_format_io_close(avf, &avf->pb);
144  tee_slave->avf = NULL;
145  return ret;
146 }
147 
148 static void close_slaves(AVFormatContext *avf)
149 {
150  TeeContext *tee = avf->priv_data;
151  unsigned i;
152 
153  for (i = 0; i < tee->nb_slaves; i++) {
154  close_slave(&tee->slaves[i]);
155  }
156  av_freep(&tee->slaves);
157 }
158 
159 static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
160 {
161  int i, ret;
162  AVDictionary *options = NULL, *bsf_options = NULL;
163  AVDictionaryEntry *entry;
164  char *filename;
165  char *format = NULL, *select = NULL, *on_fail = NULL;
166  char *use_fifo = NULL, *fifo_options_str = NULL;
167  AVFormatContext *avf2 = NULL;
168  AVStream *st, *st2;
169  int stream_count;
170  int fullret;
171  char *subselect = NULL, *next_subselect = NULL, *first_subselect = NULL, *tmp_select = NULL;
172 
173  if ((ret = ff_tee_parse_slave_options(avf, slave, &options, &filename)) < 0)
174  return ret;
175 
176 #define STEAL_OPTION(option, field) do { \
177  if ((entry = av_dict_get(options, option, NULL, 0))) { \
178  field = entry->value; \
179  entry->value = NULL; /* prevent it from being freed */ \
180  av_dict_set(&options, option, NULL, 0); \
181  } \
182  } while (0)
183 
184  STEAL_OPTION("f", format);
185  STEAL_OPTION("select", select);
186  STEAL_OPTION("onfail", on_fail);
187  STEAL_OPTION("use_fifo", use_fifo);
188  STEAL_OPTION("fifo_options", fifo_options_str);
189  entry = NULL;
190  while ((entry = av_dict_get(options, "bsfs", entry, AV_DICT_IGNORE_SUFFIX))) {
191  /* trim out strlen("bsfs") characters from key */
192  av_dict_set(&bsf_options, entry->key + 4, entry->value, 0);
193  av_dict_set(&options, entry->key, NULL, 0);
194  }
195 
196  ret = parse_slave_failure_policy_option(on_fail, tee_slave);
197  if (ret < 0) {
198  av_log(avf, AV_LOG_ERROR,
199  "Invalid onfail option value, valid options are 'abort' and 'ignore'\n");
200  goto end;
201  }
202 
203  ret = parse_slave_fifo_options(use_fifo, fifo_options_str, tee_slave);
204  if (ret < 0) {
205  av_log(avf, AV_LOG_ERROR, "Error parsing fifo options: %s\n", av_err2str(ret));
206  goto end;
207  }
208 
209  if (tee_slave->use_fifo) {
210 
211  if (options) {
212  char *format_options_str = NULL;
213  ret = av_dict_get_string(options, &format_options_str, '=', ':');
214  if (ret < 0)
215  goto end;
216 
217  ret = av_dict_set(&tee_slave->fifo_options, "format_opts", format_options_str,
219  if (ret < 0)
220  goto end;
221  }
222 
223  if (format) {
224  ret = av_dict_set(&tee_slave->fifo_options, "fifo_format", format,
226  format = NULL;
227  if (ret < 0)
228  goto end;
229  }
230 
231  av_dict_free(&options);
232  options = tee_slave->fifo_options;
233  }
235  tee_slave->use_fifo ? "fifo" :format, filename);
236  if (ret < 0)
237  goto end;
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_close = avf->io_close;
244  avf2->flags = avf->flags;
246 
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);
250  goto end;
251  }
252 
253  stream_count = 0;
254  for (i = 0; i < avf->nb_streams; i++) {
255  st = avf->streams[i];
256  if (select) {
257  tmp_select = av_strdup(select); // av_strtok is destructive so we regenerate it in each loop
258  if (!tmp_select) {
259  ret = AVERROR(ENOMEM);
260  goto end;
261  }
262  fullret = 0;
263  first_subselect = tmp_select;
264  next_subselect = NULL;
265  while (subselect = av_strtok(first_subselect, slave_select_sep, &next_subselect)) {
266  first_subselect = NULL;
267 
268  ret = avformat_match_stream_specifier(avf, avf->streams[i], subselect);
269  if (ret < 0) {
270  av_log(avf, AV_LOG_ERROR,
271  "Invalid stream specifier '%s' for output '%s'\n",
272  subselect, slave);
273  goto end;
274  }
275  if (ret != 0) {
276  fullret = 1; // match
277  break;
278  }
279  }
280  av_freep(&tmp_select);
281 
282  if (fullret == 0) { /* no match */
283  tee_slave->stream_map[i] = -1;
284  continue;
285  }
286  }
287  tee_slave->stream_map[i] = stream_count++;
288 
289  if (!(st2 = avformat_new_stream(avf2, NULL))) {
290  ret = AVERROR(ENOMEM);
291  goto end;
292  }
293 
294  ret = ff_stream_encode_params_copy(st2, st);
295  if (ret < 0)
296  goto end;
297  }
298 
299  ret = ff_format_output_open(avf2, filename, NULL);
300  if (ret < 0) {
301  av_log(avf, AV_LOG_ERROR, "Slave '%s': error opening: %s\n", slave,
302  av_err2str(ret));
303  goto end;
304  }
305 
306  if ((ret = avformat_write_header(avf2, &options)) < 0) {
307  av_log(avf, AV_LOG_ERROR, "Slave '%s': error writing header: %s\n",
308  slave, av_err2str(ret));
309  goto end;
310  }
311  tee_slave->header_written = 1;
312 
313  tee_slave->bsfs = av_calloc(avf2->nb_streams, sizeof(*tee_slave->bsfs));
314  if (!tee_slave->bsfs) {
315  ret = AVERROR(ENOMEM);
316  goto end;
317  }
318 
319  entry = NULL;
320  while (entry = av_dict_get(bsf_options, "", NULL, AV_DICT_IGNORE_SUFFIX)) {
321  const char *spec = entry->key;
322  if (*spec) {
323  if (strspn(spec, slave_bsfs_spec_sep) != 1) {
324  av_log(avf, AV_LOG_ERROR,
325  "Specifier separator in '%s' is '%c', but only characters '%s' "
326  "are allowed\n", entry->key, *spec, slave_bsfs_spec_sep);
327  ret = AVERROR(EINVAL);
328  goto end;
329  }
330  spec++; /* consume separator */
331  }
332 
333  for (i = 0; i < avf2->nb_streams; i++) {
334  ret = avformat_match_stream_specifier(avf2, avf2->streams[i], spec);
335  if (ret < 0) {
336  av_log(avf, AV_LOG_ERROR,
337  "Invalid stream specifier '%s' in bsfs option '%s' for slave "
338  "output '%s'\n", spec, entry->key, filename);
339  goto end;
340  }
341 
342  if (ret > 0) {
343  av_log(avf, AV_LOG_DEBUG, "spec:%s bsfs:%s matches stream %d of slave "
344  "output '%s'\n", spec, entry->value, i, filename);
345  if (tee_slave->bsfs[i]) {
346  av_log(avf, AV_LOG_WARNING,
347  "Duplicate bsfs specification associated to stream %d of slave "
348  "output '%s', filters will be ignored\n", i, filename);
349  continue;
350  }
351  ret = av_bsf_list_parse_str(entry->value, &tee_slave->bsfs[i]);
352  if (ret < 0) {
353  av_log(avf, AV_LOG_ERROR,
354  "Error parsing bitstream filter sequence '%s' associated to "
355  "stream %d of slave output '%s'\n", entry->value, i, filename);
356  goto end;
357  }
358  }
359  }
360 
361  av_dict_set(&bsf_options, entry->key, NULL, 0);
362  }
363 
364  for (i = 0; i < avf->nb_streams; i++){
365  int target_stream = tee_slave->stream_map[i];
366  if (target_stream < 0)
367  continue;
368 
369  if (!tee_slave->bsfs[target_stream]) {
370  /* Add pass-through bitstream filter */
371  ret = av_bsf_get_null_filter(&tee_slave->bsfs[target_stream]);
372  if (ret < 0) {
373  av_log(avf, AV_LOG_ERROR,
374  "Failed to create pass-through bitstream filter: %s\n",
375  av_err2str(ret));
376  goto end;
377  }
378  }
379 
380  tee_slave->bsfs[target_stream]->time_base_in = avf->streams[i]->time_base;
381  ret = avcodec_parameters_copy(tee_slave->bsfs[target_stream]->par_in,
382  avf->streams[i]->codecpar);
383  if (ret < 0)
384  goto end;
385 
386  ret = av_bsf_init(tee_slave->bsfs[target_stream]);
387  if (ret < 0) {
388  av_log(avf, AV_LOG_ERROR,
389  "Failed to initialize bitstream filter(s): %s\n",
390  av_err2str(ret));
391  goto end;
392  }
393  }
394 
395  if (options) {
396  entry = NULL;
397  while ((entry = av_dict_get(options, "", entry, AV_DICT_IGNORE_SUFFIX)))
398  av_log(avf2, AV_LOG_ERROR, "Unknown option '%s'\n", entry->key);
400  goto end;
401  }
402 
403 end:
404  av_free(format);
405  av_free(select);
406  av_free(on_fail);
407  av_dict_free(&options);
408  av_dict_free(&bsf_options);
409  av_freep(&tmp_select);
410  return ret;
411 }
412 
413 static void log_slave(TeeSlave *slave, void *log_ctx, int log_level)
414 {
415  int i;
416  av_log(log_ctx, log_level, "filename:'%s' format:%s\n",
417  slave->avf->url, slave->avf->oformat->name);
418  for (i = 0; i < slave->avf->nb_streams; i++) {
419  AVStream *st = slave->avf->streams[i];
420  AVBSFContext *bsf = slave->bsfs[i];
421  const char *bsf_name;
422 
423  av_log(log_ctx, log_level, " stream:%d codec:%s type:%s",
426 
427  bsf_name = bsf->filter->priv_class ?
428  bsf->filter->priv_class->item_name(bsf) : bsf->filter->name;
429  av_log(log_ctx, log_level, " bsfs: %s\n", bsf_name);
430  }
431 }
432 
433 static int tee_process_slave_failure(AVFormatContext *avf, unsigned slave_idx, int err_n)
434 {
435  TeeContext *tee = avf->priv_data;
436  TeeSlave *tee_slave = &tee->slaves[slave_idx];
437 
438  tee->nb_alive--;
439 
440  close_slave(tee_slave);
441 
442  if (!tee->nb_alive) {
443  av_log(avf, AV_LOG_ERROR, "All tee outputs failed.\n");
444  return err_n;
445  } else if (tee_slave->on_fail == ON_SLAVE_FAILURE_ABORT) {
446  av_log(avf, AV_LOG_ERROR, "Slave muxer #%u failed, aborting.\n", slave_idx);
447  return err_n;
448  } else {
449  av_log(avf, AV_LOG_ERROR, "Slave muxer #%u failed: %s, continuing with %u/%u slaves.\n",
450  slave_idx, av_err2str(err_n), tee->nb_alive, tee->nb_slaves);
451  return 0;
452  }
453 }
454 
456 {
457  TeeContext *tee = avf->priv_data;
458  unsigned nb_slaves = 0, i;
459  const char *filename = avf->url;
460  char **slaves = NULL;
461  int ret;
462 
463  while (*filename) {
464  char *slave = av_get_token(&filename, slave_delim);
465  if (!slave) {
466  ret = AVERROR(ENOMEM);
467  goto fail;
468  }
469  ret = av_dynarray_add_nofree(&slaves, &nb_slaves, slave);
470  if (ret < 0) {
471  av_free(slave);
472  goto fail;
473  }
474  if (strspn(filename, slave_delim))
475  filename++;
476  }
477 
478  if (tee->fifo_options_str) {
479  ret = av_dict_parse_string(&tee->fifo_options, tee->fifo_options_str, "=", ":", 0);
480  if (ret < 0)
481  goto fail;
482  }
483 
484  if (!(tee->slaves = av_mallocz_array(nb_slaves, sizeof(*tee->slaves)))) {
485  ret = AVERROR(ENOMEM);
486  goto fail;
487  }
488  tee->nb_slaves = tee->nb_alive = nb_slaves;
489 
490  for (i = 0; i < nb_slaves; i++) {
491 
492  tee->slaves[i].use_fifo = tee->use_fifo;
493  ret = av_dict_copy(&tee->slaves[i].fifo_options, tee->fifo_options, 0);
494  if (ret < 0)
495  goto fail;
496 
497  if ((ret = open_slave(avf, slaves[i], &tee->slaves[i])) < 0) {
498  ret = tee_process_slave_failure(avf, i, ret);
499  if (ret < 0)
500  goto fail;
501  } else {
502  log_slave(&tee->slaves[i], avf, AV_LOG_VERBOSE);
503  }
504  av_freep(&slaves[i]);
505  }
506 
507  for (i = 0; i < avf->nb_streams; i++) {
508  int j, mapped = 0;
509  for (j = 0; j < tee->nb_slaves; j++)
510  if (tee->slaves[j].avf)
511  mapped += tee->slaves[j].stream_map[i] >= 0;
512  if (!mapped)
513  av_log(avf, AV_LOG_WARNING, "Input stream #%d is not mapped "
514  "to any slave.\n", i);
515  }
516  av_free(slaves);
517  return 0;
518 
519 fail:
520  for (i = 0; i < nb_slaves; i++)
521  av_freep(&slaves[i]);
522  close_slaves(avf);
523  av_free(slaves);
524  return ret;
525 }
526 
528 {
529  TeeContext *tee = avf->priv_data;
530  int ret_all = 0, ret;
531  unsigned i;
532 
533  for (i = 0; i < tee->nb_slaves; i++) {
534  if ((ret = close_slave(&tee->slaves[i])) < 0) {
535  ret = tee_process_slave_failure(avf, i, ret);
536  if (!ret_all && ret < 0)
537  ret_all = ret;
538  }
539  }
540  av_freep(&tee->slaves);
541  return ret_all;
542 }
543 
545 {
546  TeeContext *tee = avf->priv_data;
547  AVFormatContext *avf2;
548  AVBSFContext *bsfs;
549  AVPacket pkt2;
550  int ret_all = 0, ret;
551  unsigned i, s;
552  int s2;
553 
554  for (i = 0; i < tee->nb_slaves; i++) {
555  if (!(avf2 = tee->slaves[i].avf))
556  continue;
557 
558  /* Flush slave if pkt is NULL*/
559  if (!pkt) {
561  if (ret < 0) {
562  ret = tee_process_slave_failure(avf, i, ret);
563  if (!ret_all && ret < 0)
564  ret_all = ret;
565  }
566  continue;
567  }
568 
569  s = pkt->stream_index;
570  s2 = tee->slaves[i].stream_map[s];
571  if (s2 < 0)
572  continue;
573 
574  memset(&pkt2, 0, sizeof(AVPacket));
575  if ((ret = av_packet_ref(&pkt2, pkt)) < 0)
576  if (!ret_all) {
577  ret_all = ret;
578  continue;
579  }
580  bsfs = tee->slaves[i].bsfs[s2];
581  pkt2.stream_index = s2;
582 
583  ret = av_bsf_send_packet(bsfs, &pkt2);
584  if (ret < 0) {
585  av_log(avf, AV_LOG_ERROR, "Error while sending packet to bitstream filter: %s\n",
586  av_err2str(ret));
587  ret = tee_process_slave_failure(avf, i, ret);
588  if (!ret_all && ret < 0)
589  ret_all = ret;
590  }
591 
592  while(1) {
593  ret = av_bsf_receive_packet(bsfs, &pkt2);
594  if (ret == AVERROR(EAGAIN)) {
595  ret = 0;
596  break;
597  } else if (ret < 0) {
598  break;
599  }
600 
601  av_packet_rescale_ts(&pkt2, bsfs->time_base_out,
602  avf2->streams[s2]->time_base);
603  ret = av_interleaved_write_frame(avf2, &pkt2);
604  if (ret < 0)
605  break;
606  };
607 
608  if (ret < 0) {
609  ret = tee_process_slave_failure(avf, i, ret);
610  if (!ret_all && ret < 0)
611  ret_all = ret;
612  }
613  }
614  return ret_all;
615 }
616 
618  .name = "tee",
619  .long_name = NULL_IF_CONFIG_SMALL("Multiple muxer tee"),
620  .priv_data_size = sizeof(TeeContext),
624  .priv_class = &tee_muxer_class,
626 };
static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
Definition: ffmpeg.c:690
int(* io_open)(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags, AVDictionary **options)
A callback for opening new IO streams.
Definition: avformat.h:1940
void av_bsf_free(AVBSFContext **ctx)
Free a bitstream filter context and everything associated with it; write NULL into the supplied point...
Definition: bsf.c:35
#define NULL
Definition: coverity.c:32
static int tee_write_packet(AVFormatContext *avf, AVPacket *pkt)
Definition: tee.c:544
const AVClass * priv_class
A class for the private data, used to declare bitstream filter private AVOptions. ...
Definition: avcodec.h:5842
SlaveFailurePolicy
Definition: tee.c:31
int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file ensuring correct interleaving.
Definition: mux.c:1199
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1636
AVOption.
Definition: opt.h:246
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
static int parse_slave_fifo_options(const char *use_fifo, const char *fifo_options, TeeSlave *tee_slave)
Definition: tee.c:99
TeeSlave * slaves
Definition: tee.c:56
static int tee_write_trailer(AVFormatContext *avf)
Definition: tee.c:527
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:3968
const struct AVBitStreamFilter * filter
The bitstream filter this context is an instance of.
Definition: avcodec.h:5783
The bitstream filter state.
Definition: avcodec.h:5774
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:191
int av_dict_get_string(const AVDictionary *m, char **buffer, const char key_val_sep, const char pairs_sep)
Get dictionary entries as a string.
Definition: dict.c:230
static const char *const slave_bsfs_spec_sep
Definition: tee.c:63
Convenience header that includes libavutil&#39;s core.
static void log_slave(TeeSlave *slave, void *log_ctx, int log_level)
Definition: tee.c:413
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition: dict.c:217
static AVPacket pkt
int header_written
Definition: tee.c:49
SlaveFailurePolicy on_fail
Definition: tee.c:42
int av_bsf_get_null_filter(AVBSFContext **bsf)
Get null/pass-through bitstream filter.
Definition: bsf.c:564
#define AVFMT_ALLOW_FLUSH
Format allows flushing.
Definition: avformat.h:476
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample format(the sample packing is implied by the sample format) and sample rate.The lists are not just lists
static int tee_process_slave_failure(AVFormatContext *avf, unsigned slave_idx, int err_n)
Definition: tee.c:433
int strict_std_compliance
Allow non-standard and experimental extension.
Definition: avformat.h:1666
static const char *const slave_delim
Definition: tee.c:62
int av_bsf_init(AVBSFContext *ctx)
Prepare the filter for use, after all the parameters and options have been set.
Definition: bsf.c:135
void * av_calloc(size_t nmemb, size_t size)
Non-inlined equivalent of av_mallocz_array().
Definition: mem.c:244
Format I/O context.
Definition: avformat.h:1358
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
int av_bsf_receive_packet(AVBSFContext *ctx, AVPacket *pkt)
Retrieve a filtered packet.
Definition: bsf.c:212
AVOutputFormat ff_tee_muxer
Definition: tee.c:617
static int close_slave(TeeSlave *tee_slave)
Definition: tee.c:122
AVOptions.
const char *(* item_name)(void *ctx)
A pointer to a function which returns the name of a context instance ctx associated with the class...
Definition: log.h:78
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
void ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: utils.c:5684
static void close_slaves(AVFormatContext *avf)
Definition: tee.c:148
int avformat_match_stream_specifier(AVFormatContext *s, AVStream *st, const char *spec)
Check if the stream st contained in s is matched by the stream specifier spec.
Definition: utils.c:5310
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4502
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1426
const char * name
Definition: avcodec.h:5824
unsigned nb_alive
Definition: tee.c:55
AVDictionaryEntry * av_dict_get(const AVDictionary *m, const char *key, const AVDictionaryEntry *prev, int flags)
Get a dictionary entry with matching key.
Definition: dict.c:40
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1489
int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **options)
Utility function to open IO stream of output format.
Definition: utils.c:5674
int ff_stream_encode_params_copy(AVStream *dst, const AVStream *src)
Copy encoding parameters from source to destination stream.
Definition: utils.c:4312
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
int av_dynarray_add_nofree(void *tab_ptr, int *nb_ptr, void *elem)
Add an element to a dynamic array.
Definition: mem.c:294
static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
Definition: tee.c:159
#define av_log(a,...)
#define AV_OPT_FLAG_ENCODING_PARAM
a generic parameter which can be set by the user for muxing or encoding
Definition: opt.h:276
static const char *const slave_select_sep
Definition: tee.c:64
int av_packet_ref(AVPacket *dst, const AVPacket *src)
Setup a new reference to the data described by a given packet.
Definition: avpacket.c:608
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
int avcodec_parameters_copy(AVCodecParameters *dst, const AVCodecParameters *src)
Copy the contents of src to dst.
Definition: utils.c:2040
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
AVDictionary * metadata
Metadata that applies to the whole file.
Definition: avformat.h:1598
int use_fifo
Definition: tee.c:57
void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst)
Convert valid timing fields (timestamps / durations) in a packet from one timebase to another...
Definition: avpacket.c:704
#define s2
Definition: regdef.h:39
#define DEFAULT_SLAVE_FAILURE_POLICY
Definition: tee.c:36
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
char * url
input or output URL.
Definition: avformat.h:1454
AVBSFContext ** bsfs
bitstream filters per stream
Definition: tee.c:40
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
unsigned nb_slaves
Definition: tee.c:54
int * stream_map
map from input to output streams indexes, disabled output streams are set to -1
Definition: tee.c:48
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:203
enum AVMediaType codec_type
General type of the encoded data.
Definition: avcodec.h:3964
AVRational time_base_in
The timebase used for the timestamps of the input packets.
Definition: avcodec.h:5814
int avformat_alloc_output_context2(AVFormatContext **ctx, ff_const59 AVOutputFormat *oformat, const char *format_name, const char *filename)
Allocate an AVFormatContext for an output format.
Definition: mux.c:148
int av_match_name(const char *name, const char *names)
Match instances of a name in a comma-separated list of names.
Definition: avstring.c:348
AVDictionary * fifo_options
Definition: tee.c:58
AVDictionary * fifo_options
Definition: tee.c:44
#define fail()
Definition: checkasm.h:122
char * av_get_token(const char **buf, const char *term)
Unescape the given string until a non escaped terminating char, and return the token corresponding to...
Definition: avstring.c:149
#define OFFSET(x)
Definition: tee.c:66
void * opaque
User data.
Definition: avformat.h:1864
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1414
Definition: tee.c:38
int ff_tee_parse_slave_options(void *log, char *slave, AVDictionary **options, char **filename)
Definition: tee_common.c:32
av_warn_unused_result int avformat_write_header(AVFormatContext *s, AVDictionary **options)
Allocate the stream private data and write the stream header to an output media file.
Definition: mux.c:516
static const AVClass tee_muxer_class
Definition: tee.c:75
int av_strcasecmp(const char *a, const char *b)
Locale-independent case-insensitive compare.
Definition: avstring.c:213
#define AV_DICT_DONT_STRDUP_VAL
Take ownership of a value that&#39;s been allocated with av_malloc() or another memory allocation functio...
Definition: dict.h:76
AVRational time_base_out
The timebase used for the timestamps of the output packets.
Definition: avcodec.h:5820
static int write_trailer(AVFormatContext *s1)
Definition: v4l2enc.c:94
int av_bsf_send_packet(AVBSFContext *ctx, AVPacket *pkt)
Submit a packet for filtering.
Definition: bsf.c:186
const char * name
Definition: avformat.h:505
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:119
#define s(width, name)
Definition: cbs_vp9.c:257
int use_fifo
Definition: tee.c:43
static const AVOption options[]
Definition: tee.c:67
const char * avcodec_get_name(enum AVCodecID id)
Get the name of a codec.
Definition: utils.c:1166
ff_const59 struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1377
Stream structure.
Definition: avformat.h:881
char * fifo_options_str
Definition: tee.c:59
int av_dict_parse_string(AVDictionary **pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags)
Parse the key/value pairs list and add the parsed entries to a dictionary.
Definition: dict.c:180
char * av_strdup(const char *s)
Duplicate a string.
Definition: mem.c:251
Definition: tee.c:52
AVIOContext * pb
I/O context.
Definition: avformat.h:1400
void(* io_close)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition: avformat.h:1946
int av_dict_set(AVDictionary **pm, const char *key, const char *value, int flags)
Set the given entry in *pm, overwriting an existing entry.
Definition: dict.c:70
Describe the class of an AVClass context structure.
Definition: log.h:67
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: utils.c:4433
const char * av_get_media_type_string(enum AVMediaType media_type)
Return a string describing the media_type enum, NULL if media_type is unknown.
Definition: utils.c:76
#define flags(name, subs,...)
Definition: cbs_av1.c:561
char * av_strtok(char *s, const char *delim, char **saveptr)
Split the string into several tokens which can be accessed by successive calls to av_strtok()...
Definition: avstring.c:184
Main libavformat public API header.
int av_bsf_list_parse_str(const char *str, AVBSFContext **bsf)
Parse string describing list of bitstream filters and create single AVBSFContext describing the whole...
Definition: bsf.c:526
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:463
char * key
Definition: dict.h:86
#define av_free(p)
#define AVERROR_OPTION_NOT_FOUND
Option not found.
Definition: error.h:61
char * value
Definition: dict.h:87
void * priv_data
Format private data.
Definition: avformat.h:1386
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:349
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1261
#define av_freep(p)
#define AV_DICT_IGNORE_SUFFIX
Return first entry in a dictionary whose first part corresponds to the search key, ignoring the suffix of the found key string.
Definition: dict.h:70
AVCodecParameters * codecpar
Codec parameters associated with this stream.
Definition: avformat.h:1028
int stream_index
Definition: avcodec.h:1482
static int parse_slave_failure_policy_option(const char *opt, TeeSlave *tee_slave)
Definition: tee.c:82
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:910
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
This structure stores compressed data.
Definition: avcodec.h:1457
AVCodecParameters * par_in
Parameters of the input stream.
Definition: avcodec.h:5802
AVFormatContext * avf
Definition: tee.c:39
static int tee_write_header(AVFormatContext *avf)
Definition: tee.c:455
#define STEAL_OPTION(option, field)
void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.c:191