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;
59 } TeeContext;
60 
61 static const char *const slave_delim = "|";
62 static const char *const slave_bsfs_spec_sep = "/";
63 static const char *const slave_select_sep = ",";
64 
65 #define OFFSET(x) offsetof(TeeContext, x)
66 static const AVOption options[] = {
67  {"use_fifo", "Use fifo pseudo-muxer to separate actual muxers from encoder",
69  {"fifo_options", "fifo pseudo-muxer options", OFFSET(fifo_options),
71  {NULL}
72 };
73 
74 static const AVClass tee_muxer_class = {
75  .class_name = "Tee muxer",
76  .item_name = av_default_item_name,
77  .option = options,
78  .version = LIBAVUTIL_VERSION_INT,
79 };
80 
81 static inline int parse_slave_failure_policy_option(const char *opt, TeeSlave *tee_slave)
82 {
83  if (!opt) {
85  return 0;
86  } else if (!av_strcasecmp("abort", opt)) {
87  tee_slave->on_fail = ON_SLAVE_FAILURE_ABORT;
88  return 0;
89  } else if (!av_strcasecmp("ignore", opt)) {
90  tee_slave->on_fail = ON_SLAVE_FAILURE_IGNORE;
91  return 0;
92  }
93  /* Set failure behaviour to abort, so invalid option error will not be ignored */
94  tee_slave->on_fail = ON_SLAVE_FAILURE_ABORT;
95  return AVERROR(EINVAL);
96 }
97 
98 static int parse_slave_fifo_options(const char *use_fifo,
99  const char *fifo_options, TeeSlave *tee_slave)
100 {
101  int ret = 0;
102 
103  if (use_fifo) {
104  /*TODO - change this to use proper function for parsing boolean
105  * options when there is one */
106  if (av_match_name(use_fifo, "true,y,yes,enable,enabled,on,1")) {
107  tee_slave->use_fifo = 1;
108  } else if (av_match_name(use_fifo, "false,n,no,disable,disabled,off,0")) {
109  tee_slave->use_fifo = 0;
110  } else {
111  return AVERROR(EINVAL);
112  }
113  }
114 
115  if (fifo_options)
116  ret = av_dict_parse_string(&tee_slave->fifo_options, fifo_options, "=", ":", 0);
117 
118  return ret;
119 }
120 
121 static int close_slave(TeeSlave *tee_slave)
122 {
123  AVFormatContext *avf;
124  unsigned i;
125  int ret = 0;
126 
127  avf = tee_slave->avf;
128  if (!avf)
129  return 0;
130 
131  if (tee_slave->header_written)
132  ret = av_write_trailer(avf);
133 
134  if (tee_slave->bsfs) {
135  for (i = 0; i < avf->nb_streams; ++i)
136  av_bsf_free(&tee_slave->bsfs[i]);
137  }
138  av_freep(&tee_slave->stream_map);
139  av_freep(&tee_slave->bsfs);
140 
141  ff_format_io_close(avf, &avf->pb);
143  tee_slave->avf = NULL;
144  return ret;
145 }
146 
147 static void close_slaves(AVFormatContext *avf)
148 {
149  TeeContext *tee = avf->priv_data;
150  unsigned i;
151 
152  for (i = 0; i < tee->nb_slaves; i++) {
153  close_slave(&tee->slaves[i]);
154  }
155  av_freep(&tee->slaves);
156 }
157 
158 static int open_slave(AVFormatContext *avf, char *slave, TeeSlave *tee_slave)
159 {
160  int i, ret;
161  AVDictionary *options = NULL, *bsf_options = NULL;
162  AVDictionaryEntry *entry;
163  char *filename;
164  char *format = NULL, *select = NULL, *on_fail = NULL;
165  char *use_fifo = NULL, *fifo_options_str = NULL;
166  AVFormatContext *avf2 = NULL;
167  AVStream *st, *st2;
168  int stream_count;
169  int fullret;
170  char *subselect = NULL, *next_subselect = NULL, *first_subselect = NULL, *tmp_select = NULL;
171 
172  if ((ret = ff_tee_parse_slave_options(avf, slave, &options, &filename)) < 0)
173  return ret;
174 
175 #define STEAL_OPTION(option, field) do { \
176  if ((entry = av_dict_get(options, option, NULL, 0))) { \
177  field = entry->value; \
178  entry->value = NULL; /* prevent it from being freed */ \
179  av_dict_set(&options, option, NULL, 0); \
180  } \
181  } while (0)
182 
183  STEAL_OPTION("f", format);
184  STEAL_OPTION("select", select);
185  STEAL_OPTION("onfail", on_fail);
186  STEAL_OPTION("use_fifo", use_fifo);
187  STEAL_OPTION("fifo_options", fifo_options_str);
188  entry = NULL;
189  while ((entry = av_dict_get(options, "bsfs", entry, AV_DICT_IGNORE_SUFFIX))) {
190  /* trim out strlen("bsfs") characters from key */
191  av_dict_set(&bsf_options, entry->key + 4, entry->value, 0);
192  av_dict_set(&options, entry->key, NULL, 0);
193  }
194 
195  ret = parse_slave_failure_policy_option(on_fail, tee_slave);
196  if (ret < 0) {
197  av_log(avf, AV_LOG_ERROR,
198  "Invalid onfail option value, valid options are 'abort' and 'ignore'\n");
199  goto end;
200  }
201 
202  ret = parse_slave_fifo_options(use_fifo, fifo_options_str, tee_slave);
203  if (ret < 0) {
204  av_log(avf, AV_LOG_ERROR, "Error parsing fifo options: %s\n", av_err2str(ret));
205  goto end;
206  }
207 
208  if (tee_slave->use_fifo) {
209 
210  if (options) {
211  char *format_options_str = NULL;
212  ret = av_dict_get_string(options, &format_options_str, '=', ':');
213  if (ret < 0)
214  goto end;
215 
216  ret = av_dict_set(&tee_slave->fifo_options, "format_opts", format_options_str,
218  if (ret < 0)
219  goto end;
220  }
221 
222  if (format) {
223  ret = av_dict_set(&tee_slave->fifo_options, "fifo_format", format,
225  format = NULL;
226  if (ret < 0)
227  goto end;
228  }
229 
230  av_dict_free(&options);
231  options = tee_slave->fifo_options;
232  }
234  tee_slave->use_fifo ? "fifo" :format, filename);
235  if (ret < 0)
236  goto end;
237  tee_slave->avf = avf2;
238  av_dict_copy(&avf2->metadata, avf->metadata, 0);
239  avf2->opaque = avf->opaque;
240  avf2->io_open = avf->io_open;
241  avf2->io_close = avf->io_close;
243  avf2->flags = avf->flags;
245 
246  tee_slave->stream_map = av_calloc(avf->nb_streams, sizeof(*tee_slave->stream_map));
247  if (!tee_slave->stream_map) {
248  ret = AVERROR(ENOMEM);
249  goto end;
250  }
251 
252  stream_count = 0;
253  for (i = 0; i < avf->nb_streams; i++) {
254  st = avf->streams[i];
255  if (select) {
256  tmp_select = av_strdup(select); // av_strtok is destructive so we regenerate it in each loop
257  if (!tmp_select) {
258  ret = AVERROR(ENOMEM);
259  goto end;
260  }
261  fullret = 0;
262  first_subselect = tmp_select;
263  next_subselect = NULL;
264  while (subselect = av_strtok(first_subselect, slave_select_sep, &next_subselect)) {
265  first_subselect = NULL;
266 
267  ret = avformat_match_stream_specifier(avf, avf->streams[i], subselect);
268  if (ret < 0) {
269  av_log(avf, AV_LOG_ERROR,
270  "Invalid stream specifier '%s' for output '%s'\n",
271  subselect, slave);
272  goto end;
273  }
274  if (ret != 0) {
275  fullret = 1; // match
276  break;
277  }
278  }
279  av_freep(&tmp_select);
280 
281  if (fullret == 0) { /* no match */
282  tee_slave->stream_map[i] = -1;
283  continue;
284  }
285  }
286  tee_slave->stream_map[i] = stream_count++;
287 
288  if (!(st2 = avformat_new_stream(avf2, NULL))) {
289  ret = AVERROR(ENOMEM);
290  goto end;
291  }
292 
293  ret = ff_stream_encode_params_copy(st2, st);
294  if (ret < 0)
295  goto end;
296  }
297 
298  ret = ff_format_output_open(avf2, filename, NULL);
299  if (ret < 0) {
300  av_log(avf, AV_LOG_ERROR, "Slave '%s': error opening: %s\n", slave,
301  av_err2str(ret));
302  goto end;
303  }
304 
305  if ((ret = avformat_write_header(avf2, &options)) < 0) {
306  av_log(avf, AV_LOG_ERROR, "Slave '%s': error writing header: %s\n",
307  slave, av_err2str(ret));
308  goto end;
309  }
310  tee_slave->header_written = 1;
311 
312  tee_slave->bsfs = av_calloc(avf2->nb_streams, sizeof(*tee_slave->bsfs));
313  if (!tee_slave->bsfs) {
314  ret = AVERROR(ENOMEM);
315  goto end;
316  }
317 
318  entry = NULL;
319  while (entry = av_dict_get(bsf_options, "", NULL, AV_DICT_IGNORE_SUFFIX)) {
320  const char *spec = entry->key;
321  if (*spec) {
322  if (strspn(spec, slave_bsfs_spec_sep) != 1) {
323  av_log(avf, AV_LOG_ERROR,
324  "Specifier separator in '%s' is '%c', but only characters '%s' "
325  "are allowed\n", entry->key, *spec, slave_bsfs_spec_sep);
326  ret = AVERROR(EINVAL);
327  goto end;
328  }
329  spec++; /* consume separator */
330  }
331 
332  for (i = 0; i < avf2->nb_streams; i++) {
333  ret = avformat_match_stream_specifier(avf2, avf2->streams[i], spec);
334  if (ret < 0) {
335  av_log(avf, AV_LOG_ERROR,
336  "Invalid stream specifier '%s' in bsfs option '%s' for slave "
337  "output '%s'\n", spec, entry->key, filename);
338  goto end;
339  }
340 
341  if (ret > 0) {
342  av_log(avf, AV_LOG_DEBUG, "spec:%s bsfs:%s matches stream %d of slave "
343  "output '%s'\n", spec, entry->value, i, filename);
344  if (tee_slave->bsfs[i]) {
345  av_log(avf, AV_LOG_WARNING,
346  "Duplicate bsfs specification associated to stream %d of slave "
347  "output '%s', filters will be ignored\n", i, filename);
348  continue;
349  }
350  ret = av_bsf_list_parse_str(entry->value, &tee_slave->bsfs[i]);
351  if (ret < 0) {
352  av_log(avf, AV_LOG_ERROR,
353  "Error parsing bitstream filter sequence '%s' associated to "
354  "stream %d of slave output '%s'\n", entry->value, i, filename);
355  goto end;
356  }
357  }
358  }
359 
360  av_dict_set(&bsf_options, entry->key, NULL, 0);
361  }
362 
363  for (i = 0; i < avf->nb_streams; i++){
364  int target_stream = tee_slave->stream_map[i];
365  if (target_stream < 0)
366  continue;
367 
368  if (!tee_slave->bsfs[target_stream]) {
369  /* Add pass-through bitstream filter */
370  ret = av_bsf_get_null_filter(&tee_slave->bsfs[target_stream]);
371  if (ret < 0) {
372  av_log(avf, AV_LOG_ERROR,
373  "Failed to create pass-through bitstream filter: %s\n",
374  av_err2str(ret));
375  goto end;
376  }
377  }
378 
379  tee_slave->bsfs[target_stream]->time_base_in = avf->streams[i]->time_base;
380  ret = avcodec_parameters_copy(tee_slave->bsfs[target_stream]->par_in,
381  avf->streams[i]->codecpar);
382  if (ret < 0)
383  goto end;
384 
385  ret = av_bsf_init(tee_slave->bsfs[target_stream]);
386  if (ret < 0) {
387  av_log(avf, AV_LOG_ERROR,
388  "Failed to initialize bitstream filter(s): %s\n",
389  av_err2str(ret));
390  goto end;
391  }
392  }
393 
394  if (options) {
395  entry = NULL;
396  while ((entry = av_dict_get(options, "", entry, AV_DICT_IGNORE_SUFFIX)))
397  av_log(avf2, AV_LOG_ERROR, "Unknown option '%s'\n", entry->key);
399  goto end;
400  }
401 
402 end:
403  av_free(format);
404  av_free(select);
405  av_free(on_fail);
406  av_dict_free(&options);
407  av_dict_free(&bsf_options);
408  av_freep(&tmp_select);
409  return ret;
410 }
411 
412 static void log_slave(TeeSlave *slave, void *log_ctx, int log_level)
413 {
414  int i;
415  av_log(log_ctx, log_level, "filename:'%s' format:%s\n",
416  slave->avf->url, slave->avf->oformat->name);
417  for (i = 0; i < slave->avf->nb_streams; i++) {
418  AVStream *st = slave->avf->streams[i];
419  AVBSFContext *bsf = slave->bsfs[i];
420  const char *bsf_name;
421 
422  av_log(log_ctx, log_level, " stream:%d codec:%s type:%s",
425 
426  bsf_name = bsf->filter->priv_class ?
427  bsf->filter->priv_class->item_name(bsf) : bsf->filter->name;
428  av_log(log_ctx, log_level, " bsfs: %s\n", bsf_name);
429  }
430 }
431 
432 static int tee_process_slave_failure(AVFormatContext *avf, unsigned slave_idx, int err_n)
433 {
434  TeeContext *tee = avf->priv_data;
435  TeeSlave *tee_slave = &tee->slaves[slave_idx];
436 
437  tee->nb_alive--;
438 
439  close_slave(tee_slave);
440 
441  if (!tee->nb_alive) {
442  av_log(avf, AV_LOG_ERROR, "All tee outputs failed.\n");
443  return err_n;
444  } else if (tee_slave->on_fail == ON_SLAVE_FAILURE_ABORT) {
445  av_log(avf, AV_LOG_ERROR, "Slave muxer #%u failed, aborting.\n", slave_idx);
446  return err_n;
447  } else {
448  av_log(avf, AV_LOG_ERROR, "Slave muxer #%u failed: %s, continuing with %u/%u slaves.\n",
449  slave_idx, av_err2str(err_n), tee->nb_alive, tee->nb_slaves);
450  return 0;
451  }
452 }
453 
455 {
456  TeeContext *tee = avf->priv_data;
457  unsigned nb_slaves = 0, i;
458  const char *filename = avf->url;
459  char **slaves = NULL;
460  int ret;
461 
462  while (*filename) {
463  char *slave = av_get_token(&filename, slave_delim);
464  if (!slave) {
465  ret = AVERROR(ENOMEM);
466  goto fail;
467  }
468  ret = av_dynarray_add_nofree(&slaves, &nb_slaves, slave);
469  if (ret < 0) {
470  av_free(slave);
471  goto fail;
472  }
473  if (strspn(filename, slave_delim))
474  filename++;
475  }
476 
477  if (!(tee->slaves = av_mallocz_array(nb_slaves, sizeof(*tee->slaves)))) {
478  ret = AVERROR(ENOMEM);
479  goto fail;
480  }
481  tee->nb_slaves = tee->nb_alive = nb_slaves;
482 
483  for (i = 0; i < nb_slaves; i++) {
484 
485  tee->slaves[i].use_fifo = tee->use_fifo;
486  ret = av_dict_copy(&tee->slaves[i].fifo_options, tee->fifo_options, 0);
487  if (ret < 0)
488  goto fail;
489 
490  if ((ret = open_slave(avf, slaves[i], &tee->slaves[i])) < 0) {
491  ret = tee_process_slave_failure(avf, i, ret);
492  if (ret < 0)
493  goto fail;
494  } else {
495  log_slave(&tee->slaves[i], avf, AV_LOG_VERBOSE);
496  }
497  av_freep(&slaves[i]);
498  }
499 
500  for (i = 0; i < avf->nb_streams; i++) {
501  int j, mapped = 0;
502  for (j = 0; j < tee->nb_slaves; j++)
503  if (tee->slaves[j].avf)
504  mapped += tee->slaves[j].stream_map[i] >= 0;
505  if (!mapped)
506  av_log(avf, AV_LOG_WARNING, "Input stream #%d is not mapped "
507  "to any slave.\n", i);
508  }
509  av_free(slaves);
510  return 0;
511 
512 fail:
513  for (i = 0; i < nb_slaves; i++)
514  av_freep(&slaves[i]);
515  close_slaves(avf);
516  av_free(slaves);
517  return ret;
518 }
519 
521 {
522  TeeContext *tee = avf->priv_data;
523  int ret_all = 0, ret;
524  unsigned i;
525 
526  for (i = 0; i < tee->nb_slaves; i++) {
527  if ((ret = close_slave(&tee->slaves[i])) < 0) {
528  ret = tee_process_slave_failure(avf, i, ret);
529  if (!ret_all && ret < 0)
530  ret_all = ret;
531  }
532  }
533  av_freep(&tee->slaves);
534  return ret_all;
535 }
536 
538 {
539  TeeContext *tee = avf->priv_data;
540  AVFormatContext *avf2;
541  AVBSFContext *bsfs;
542  AVPacket pkt2;
543  int ret_all = 0, ret;
544  unsigned i, s;
545  int s2;
546 
547  for (i = 0; i < tee->nb_slaves; i++) {
548  if (!(avf2 = tee->slaves[i].avf))
549  continue;
550 
551  /* Flush slave if pkt is NULL*/
552  if (!pkt) {
554  if (ret < 0) {
555  ret = tee_process_slave_failure(avf, i, ret);
556  if (!ret_all && ret < 0)
557  ret_all = ret;
558  }
559  continue;
560  }
561 
562  s = pkt->stream_index;
563  s2 = tee->slaves[i].stream_map[s];
564  if (s2 < 0)
565  continue;
566 
567  if ((ret = av_packet_ref(&pkt2, pkt)) < 0)
568  if (!ret_all) {
569  ret_all = ret;
570  continue;
571  }
572  bsfs = tee->slaves[i].bsfs[s2];
573  pkt2.stream_index = s2;
574 
575  ret = av_bsf_send_packet(bsfs, &pkt2);
576  if (ret < 0) {
577  av_log(avf, AV_LOG_ERROR, "Error while sending packet to bitstream filter: %s\n",
578  av_err2str(ret));
579  ret = tee_process_slave_failure(avf, i, ret);
580  if (!ret_all && ret < 0)
581  ret_all = ret;
582  }
583 
584  while(1) {
585  ret = av_bsf_receive_packet(bsfs, &pkt2);
586  if (ret == AVERROR(EAGAIN)) {
587  ret = 0;
588  break;
589  } else if (ret < 0) {
590  break;
591  }
592 
593  av_packet_rescale_ts(&pkt2, bsfs->time_base_out,
594  avf2->streams[s2]->time_base);
595  ret = av_interleaved_write_frame(avf2, &pkt2);
596  if (ret < 0)
597  break;
598  };
599 
600  if (ret < 0) {
601  ret = tee_process_slave_failure(avf, i, ret);
602  if (!ret_all && ret < 0)
603  ret_all = ret;
604  }
605  }
606  return ret_all;
607 }
608 
610  .name = "tee",
611  .long_name = NULL_IF_CONFIG_SMALL("Multiple muxer tee"),
612  .priv_data_size = sizeof(TeeContext),
616  .priv_class = &tee_muxer_class,
618 };
static void write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost, int unqueue)
Definition: ffmpeg.c:698
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:1934
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:537
const AVClass * priv_class
A class for the private data, used to declare bitstream filter private AVOptions. ...
Definition: avcodec.h:5911
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:1190
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1630
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:98
TeeSlave * slaves
Definition: tee.c:56
static int tee_write_trailer(AVFormatContext *avf)
Definition: tee.c:520
enum AVCodecID codec_id
Specific type of the encoded data (the codec used).
Definition: avcodec.h:4036
const struct AVBitStreamFilter * filter
The bitstream filter this context is an instance of.
Definition: avcodec.h:5852
The bitstream filter state.
Definition: avcodec.h:5843
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
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:62
Convenience header that includes libavutil&#39;s core.
static void log_slave(TeeSlave *slave, void *log_ctx, int log_level)
Definition: tee.c:412
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:571
#define AVFMT_ALLOW_FLUSH
Format allows flushing.
Definition: avformat.h:471
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:432
int strict_std_compliance
Allow non-standard and experimental extension.
Definition: avformat.h:1660
static const char *const slave_delim
Definition: tee.c:61
int av_bsf_init(AVBSFContext *ctx)
Prepare the filter for use, after all the parameters and options have been set.
Definition: bsf.c:139
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:1352
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:219
AVOutputFormat ff_tee_muxer
Definition: tee.c:609
static int close_slave(TeeSlave *tee_slave)
Definition: tee.c:121
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:5697
static void close_slaves(AVFormatContext *avf)
Definition: tee.c:147
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:5324
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: utils.c:4524
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1420
const char * name
Definition: avcodec.h:5893
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:1483
int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **options)
Utility function to open IO stream of output format.
Definition: utils.c:5687
int ff_stream_encode_params_copy(AVStream *dst, const AVStream *src)
Copy encoding parameters from source to destination stream.
Definition: utils.c:4332
#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:158
#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:63
int av_packet_ref(AVPacket *dst, const AVPacket *src)
Setup a new reference to the data described by a given packet.
Definition: avpacket.c:609
#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:2051
#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:1592
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:707
#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:1448
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:4032
AVRational time_base_in
The timebase used for the timestamps of the input packets.
Definition: avcodec.h:5883
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:350
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:65
void * opaque
User data.
Definition: avformat.h:1858
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1408
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:74
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:5889
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:192
const char * name
Definition: avformat.h:500
#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:66
const char * avcodec_get_name(enum AVCodecID id)
Get the name of a codec.
Definition: utils.c:1172
ff_const59 struct AVOutputFormat * oformat
The output container format.
Definition: avformat.h:1371
Stream structure.
Definition: avformat.h:875
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:1394
void(* io_close)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition: avformat.h:1940
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:4453
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:564
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:533
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:458
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:1380
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:346
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1248
#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:1022
int stream_index
Definition: avcodec.h:1535
static int parse_slave_failure_policy_option(const char *opt, TeeSlave *tee_slave)
Definition: tee.c:81
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avformat.h:904
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:1510
AVCodecParameters * par_in
Parameters of the input stream.
Definition: avcodec.h:5871
AVFormatContext * avf
Definition: tee.c:39
static int tee_write_header(AVFormatContext *avf)
Definition: tee.c:454
#define STEAL_OPTION(option, field)
void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.c:191