FFmpeg
fifo.c
Go to the documentation of this file.
1 /*
2  * FIFO pseudo-muxer
3  * Copyright (c) 2016 Jan Sebechlebsky
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 #include <stdatomic.h>
23 
24 #include "libavutil/avassert.h"
25 #include "libavutil/opt.h"
26 #include "libavutil/time.h"
27 #include "libavutil/thread.h"
29 #include "avformat.h"
30 #include "internal.h"
31 #include "mux.h"
32 
33 #define FIFO_DEFAULT_QUEUE_SIZE 60
34 #define FIFO_DEFAULT_MAX_RECOVERY_ATTEMPTS 0
35 #define FIFO_DEFAULT_RECOVERY_WAIT_TIME_USEC 5000000 // 5 seconds
36 
37 typedef struct FifoContext {
38  const AVClass *class;
40 
41  char *format;
43 
46 
48 
49  /* Return value of last write_trailer_call */
51 
52  /* Time to wait before next recovery attempt
53  * This can refer to the time in processed stream,
54  * or real time. */
56 
57  /* Maximal number of unsuccessful successive recovery attempts */
59 
60  /* Whether to attempt recovery from failure */
62 
63  /* If >0 stream time will be used when waiting
64  * for the recovery attempt instead of real time */
66 
67  /* If >0 recovery will be attempted regardless of error code
68  * (except AVERROR_EXIT, so exit request is never ignored) */
70 
71  /* Whether to drop packets in case the queue is full. */
73 
74  /* Whether to wait for keyframe when recovering
75  * from failure or queue overflow */
77 
80  /* Value > 0 signals queue overflow */
81  volatile uint8_t overflow_flag;
82 
84  int64_t last_sent_dts;
85  int64_t timeshift;
86 } FifoContext;
87 
88 typedef struct FifoThreadContext {
90 
91  /* Timestamp of last failure.
92  * This is either pts in case stream time is used,
93  * or microseconds as returned by av_getttime_relative() */
95 
96  /* Number of current recovery process
97  * Value > 0 means we are in recovery process */
99 
100  /* If > 0 all frames will be dropped until keyframe is received */
102 
103  /* Value > 0 means that the previous write_header call was successful
104  * so finalization by calling write_trailer and ff_io_close must be done
105  * before exiting / reinitialization of underlying muxer */
106  uint8_t header_written;
107 
110 
111 typedef enum FifoMessageType {
117 
118 typedef struct FifoMessage {
121 } FifoMessage;
122 
124 {
125  AVFormatContext *avf = ctx->avf;
126  FifoContext *fifo = avf->priv_data;
127  AVFormatContext *avf2 = fifo->avf;
128  AVDictionary *format_options = NULL;
129  int ret, i;
130 
131  ret = av_dict_copy(&format_options, fifo->format_options, 0);
132  if (ret < 0)
133  goto end;
134 
135  ret = ff_format_output_open(avf2, avf->url, &format_options);
136  if (ret < 0) {
137  av_log(avf, AV_LOG_ERROR, "Error opening %s: %s\n", avf->url,
138  av_err2str(ret));
139  goto end;
140  }
141 
142  for (i = 0;i < avf2->nb_streams; i++)
143  ffstream(avf2->streams[i])->cur_dts = 0;
144 
145  ret = avformat_write_header(avf2, &format_options);
146  if (!ret)
147  ctx->header_written = 1;
148 
149  // Check for options unrecognized by underlying muxer
150  if (format_options) {
151  AVDictionaryEntry *entry = NULL;
152  while ((entry = av_dict_get(format_options, "", entry, AV_DICT_IGNORE_SUFFIX)))
153  av_log(avf2, AV_LOG_ERROR, "Unknown option '%s'\n", entry->key);
154  ret = AVERROR(EINVAL);
155  }
156 
157 end:
158  av_dict_free(&format_options);
159  return ret;
160 }
161 
163 {
164  AVFormatContext *avf = ctx->avf;
165  FifoContext *fifo = avf->priv_data;
166  AVFormatContext *avf2 = fifo->avf;
167 
168  return av_write_frame(avf2, NULL);
169 }
170 
171 static int64_t next_duration(AVFormatContext *avf, AVPacket *pkt, int64_t *last_dts)
172 {
173  AVStream *st = avf->streams[pkt->stream_index];
174  int64_t dts = av_rescale_q(pkt->dts, st->time_base, AV_TIME_BASE_Q);
175  int64_t duration = (*last_dts == AV_NOPTS_VALUE ? 0 : dts - *last_dts);
176  *last_dts = dts;
177  return duration;
178 }
179 
181 {
182  AVFormatContext *avf = ctx->avf;
183  FifoContext *fifo = avf->priv_data;
184  AVFormatContext *avf2 = fifo->avf;
185  AVRational src_tb, dst_tb;
186  int ret, s_idx;
187  int64_t orig_pts, orig_dts, orig_duration;
188 
189  if (fifo->timeshift && pkt->dts != AV_NOPTS_VALUE)
190  atomic_fetch_sub_explicit(&fifo->queue_duration, next_duration(avf, pkt, &ctx->last_received_dts), memory_order_relaxed);
191 
192  if (ctx->drop_until_keyframe) {
193  if (pkt->flags & AV_PKT_FLAG_KEY) {
194  ctx->drop_until_keyframe = 0;
195  av_log(avf, AV_LOG_VERBOSE, "Keyframe received, recovering...\n");
196  } else {
197  av_log(avf, AV_LOG_VERBOSE, "Dropping non-keyframe packet\n");
199  return 0;
200  }
201  }
202 
203  orig_pts = pkt->pts;
204  orig_dts = pkt->dts;
205  orig_duration = pkt->duration;
206  s_idx = pkt->stream_index;
207  src_tb = avf->streams[s_idx]->time_base;
208  dst_tb = avf2->streams[s_idx]->time_base;
209  av_packet_rescale_ts(pkt, src_tb, dst_tb);
210 
211  ret = av_write_frame(avf2, pkt);
212  if (ret >= 0) {
214  } else {
215  // avoid scaling twice
216  pkt->pts = orig_pts;
217  pkt->dts = orig_dts;
218  pkt->duration = orig_duration;
219  }
220  return ret;
221 }
222 
224 {
225  AVFormatContext *avf = ctx->avf;
226  FifoContext *fifo = avf->priv_data;
227  AVFormatContext *avf2 = fifo->avf;
228  int ret;
229 
230  if (!ctx->header_written)
231  return 0;
232 
233  ret = av_write_trailer(avf2);
234  ff_format_io_close(avf2, &avf2->pb);
235 
236  return ret;
237 }
238 
240 {
241  int ret = AVERROR(EINVAL);
242 
243  if (msg->type == FIFO_NOOP)
244  return 0;
245 
246  if (!ctx->header_written) {
248  if (ret < 0)
249  return ret;
250  }
251 
252  switch(msg->type) {
253  case FIFO_WRITE_HEADER:
254  av_assert0(ret >= 0);
255  return ret;
256  case FIFO_WRITE_PACKET:
257  return fifo_thread_write_packet(ctx, &msg->pkt);
258  case FIFO_FLUSH_OUTPUT:
260  }
261 
262  av_assert0(0);
263  return AVERROR(EINVAL);
264 }
265 
266 static int is_recoverable(const FifoContext *fifo, int err_no) {
267  if (!fifo->attempt_recovery)
268  return 0;
269 
270  if (fifo->recover_any_error)
271  return err_no != AVERROR_EXIT;
272 
273  switch (err_no) {
274  case AVERROR(EINVAL):
275  case AVERROR(ENOSYS):
276  case AVERROR_EOF:
277  case AVERROR_EXIT:
279  return 0;
280  default:
281  return 1;
282  }
283 }
284 
285 static void free_message(void *msg)
286 {
287  FifoMessage *fifo_msg = msg;
288 
289  if (fifo_msg->type == FIFO_WRITE_PACKET)
290  av_packet_unref(&fifo_msg->pkt);
291 }
292 
294  int err_no)
295 {
296  AVFormatContext *avf = ctx->avf;
297  FifoContext *fifo = avf->priv_data;
298  int ret;
299 
300  av_log(avf, AV_LOG_INFO, "Recovery failed: %s\n",
301  av_err2str(err_no));
302 
303  if (fifo->recovery_wait_streamtime) {
304  if (pkt->pts == AV_NOPTS_VALUE)
305  av_log(avf, AV_LOG_WARNING, "Packet does not contain presentation"
306  " timestamp, recovery will be attempted immediately");
307  ctx->last_recovery_ts = pkt->pts;
308  } else {
309  ctx->last_recovery_ts = av_gettime_relative();
310  }
311 
312  if (fifo->max_recovery_attempts &&
313  ctx->recovery_nr >= fifo->max_recovery_attempts) {
314  av_log(avf, AV_LOG_ERROR,
315  "Maximal number of %d recovery attempts reached.\n",
316  fifo->max_recovery_attempts);
317  ret = err_no;
318  } else {
319  ret = AVERROR(EAGAIN);
320  }
321 
322  return ret;
323 }
324 
326 {
327  AVFormatContext *avf = ctx->avf;
328  FifoContext *fifo = avf->priv_data;
329  AVPacket *pkt = &msg->pkt;
330  int64_t time_since_recovery;
331  int ret;
332 
333  if (!is_recoverable(fifo, err_no)) {
334  ret = err_no;
335  goto fail;
336  }
337 
338  if (ctx->header_written) {
340  ctx->header_written = 0;
341  }
342 
343  if (!ctx->recovery_nr) {
344  ctx->last_recovery_ts = fifo->recovery_wait_streamtime ?
345  AV_NOPTS_VALUE : 0;
346  } else {
347  if (fifo->recovery_wait_streamtime) {
348  if (ctx->last_recovery_ts == AV_NOPTS_VALUE) {
350  time_since_recovery = av_rescale_q(pkt->pts - ctx->last_recovery_ts,
351  tb, AV_TIME_BASE_Q);
352  } else {
353  /* Enforce recovery immediately */
354  time_since_recovery = fifo->recovery_wait_time;
355  }
356  } else {
357  time_since_recovery = av_gettime_relative() - ctx->last_recovery_ts;
358  }
359 
360  if (time_since_recovery < fifo->recovery_wait_time)
361  return AVERROR(EAGAIN);
362  }
363 
364  ctx->recovery_nr++;
365 
366  if (fifo->max_recovery_attempts) {
367  av_log(avf, AV_LOG_VERBOSE, "Recovery attempt #%d/%d\n",
368  ctx->recovery_nr, fifo->max_recovery_attempts);
369  } else {
370  av_log(avf, AV_LOG_VERBOSE, "Recovery attempt #%d\n",
371  ctx->recovery_nr);
372  }
373 
374  if (fifo->restart_with_keyframe && fifo->drop_pkts_on_overflow)
375  ctx->drop_until_keyframe = 1;
376 
378  if (ret < 0) {
379  if (is_recoverable(fifo, ret)) {
381  } else {
382  goto fail;
383  }
384  } else {
385  av_log(avf, AV_LOG_INFO, "Recovery successful\n");
386  ctx->recovery_nr = 0;
387  }
388 
389  return 0;
390 
391 fail:
392  free_message(msg);
393  return ret;
394 }
395 
396 static int fifo_thread_recover(FifoThreadContext *ctx, FifoMessage *msg, int err_no)
397 {
398  AVFormatContext *avf = ctx->avf;
399  FifoContext *fifo = avf->priv_data;
400  int ret;
401 
402  do {
403  if (!fifo->recovery_wait_streamtime && ctx->recovery_nr > 0) {
404  int64_t time_since_recovery = av_gettime_relative() - ctx->last_recovery_ts;
405  int64_t time_to_wait = FFMAX(0, fifo->recovery_wait_time - time_since_recovery);
406  if (time_to_wait)
407  av_usleep(FFMIN(10000, time_to_wait));
408  }
409 
410  ret = fifo_thread_attempt_recovery(ctx, msg, err_no);
411  } while (ret == AVERROR(EAGAIN) && !fifo->drop_pkts_on_overflow);
412 
413  if (ret == AVERROR(EAGAIN) && fifo->drop_pkts_on_overflow) {
414  if (msg->type == FIFO_WRITE_PACKET)
415  av_packet_unref(&msg->pkt);
416  ret = 0;
417  }
418 
419  return ret;
420 }
421 
422 static void *fifo_consumer_thread(void *data)
423 {
424  AVFormatContext *avf = data;
425  FifoContext *fifo = avf->priv_data;
426  AVThreadMessageQueue *queue = fifo->queue;
427  FifoMessage msg = {fifo->timeshift ? FIFO_NOOP : FIFO_WRITE_HEADER, {0}};
428  int ret;
429 
430  FifoThreadContext fifo_thread_ctx;
431  memset(&fifo_thread_ctx, 0, sizeof(FifoThreadContext));
432  fifo_thread_ctx.avf = avf;
433  fifo_thread_ctx.last_received_dts = AV_NOPTS_VALUE;
434 
435  while (1) {
436  uint8_t just_flushed = 0;
437 
438  if (!fifo_thread_ctx.recovery_nr)
439  ret = fifo_thread_dispatch_message(&fifo_thread_ctx, &msg);
440 
441  if (ret < 0 || fifo_thread_ctx.recovery_nr > 0) {
442  int rec_ret = fifo_thread_recover(&fifo_thread_ctx, &msg, ret);
443  if (rec_ret < 0) {
444  av_thread_message_queue_set_err_send(queue, rec_ret);
445  break;
446  }
447  }
448 
449  /* If the queue is full at the moment when fifo_write_packet
450  * attempts to insert new message (packet) to the queue,
451  * it sets the fifo->overflow_flag to 1 and drops packet.
452  * Here in consumer thread, the flag is checked and if it is
453  * set, the queue is flushed and flag cleared. */
455  if (fifo->overflow_flag) {
457  if (fifo->restart_with_keyframe)
458  fifo_thread_ctx.drop_until_keyframe = 1;
459  fifo->overflow_flag = 0;
460  just_flushed = 1;
461  }
463 
464  if (just_flushed)
465  av_log(avf, AV_LOG_INFO, "FIFO queue flushed\n");
466 
467  if (fifo->timeshift)
468  while (atomic_load_explicit(&fifo->queue_duration, memory_order_relaxed) < fifo->timeshift)
469  av_usleep(10000);
470 
471  ret = av_thread_message_queue_recv(queue, &msg, 0);
472  if (ret < 0) {
474  break;
475  }
476  }
477 
478  fifo->write_trailer_ret = fifo_thread_write_trailer(&fifo_thread_ctx);
479 
480  return NULL;
481 }
482 
483 static int fifo_mux_init(AVFormatContext *avf, const AVOutputFormat *oformat,
484  const char *filename)
485 {
486  FifoContext *fifo = avf->priv_data;
487  AVFormatContext *avf2;
488  int ret = 0, i;
489 
490  ret = avformat_alloc_output_context2(&avf2, oformat, NULL, filename);
491  if (ret < 0)
492  return ret;
493 
494  fifo->avf = avf2;
495 
497  avf2->max_delay = avf->max_delay;
498  ret = av_dict_copy(&avf2->metadata, avf->metadata, 0);
499  if (ret < 0)
500  return ret;
501  avf2->opaque = avf->opaque;
502  avf2->io_close = avf->io_close;
503  avf2->io_close2 = avf->io_close2;
504  avf2->io_open = avf->io_open;
505  avf2->flags = avf->flags;
506 
507  for (i = 0; i < avf->nb_streams; ++i) {
508  AVStream *st = avformat_new_stream(avf2, NULL);
509  if (!st)
510  return AVERROR(ENOMEM);
511 
513  if (ret < 0)
514  return ret;
515  }
516 
517  return 0;
518 }
519 
520 static int fifo_init(AVFormatContext *avf)
521 {
522  FifoContext *fifo = avf->priv_data;
523  const AVOutputFormat *oformat;
524  int ret = 0;
525 
526  if (fifo->recovery_wait_streamtime && !fifo->drop_pkts_on_overflow) {
527  av_log(avf, AV_LOG_ERROR, "recovery_wait_streamtime can be turned on"
528  " only when drop_pkts_on_overflow is also turned on\n");
529  return AVERROR(EINVAL);
530  }
531  atomic_init(&fifo->queue_duration, 0);
533 
534  oformat = av_guess_format(fifo->format, avf->url, NULL);
535  if (!oformat) {
537  return ret;
538  }
539 
540  ret = fifo_mux_init(avf, oformat, avf->url);
541  if (ret < 0)
542  return ret;
543 
544  ret = av_thread_message_queue_alloc(&fifo->queue, (unsigned) fifo->queue_size,
545  sizeof(FifoMessage));
546  if (ret < 0)
547  return ret;
548 
550 
552  if (ret < 0)
553  return AVERROR(ret);
555 
556  return 0;
557 }
558 
560 {
561  FifoContext * fifo = avf->priv_data;
562  int ret;
563 
565  if (ret) {
566  av_log(avf, AV_LOG_ERROR, "Failed to start thread: %s\n",
568  ret = AVERROR(ret);
569  }
570 
571  return ret;
572 }
573 
575 {
576  FifoContext *fifo = avf->priv_data;
578  int ret;
579 
580  if (pkt) {
581  ret = av_packet_ref(&msg.pkt,pkt);
582  if (ret < 0)
583  return ret;
584  }
585 
586  ret = av_thread_message_queue_send(fifo->queue, &msg,
587  fifo->drop_pkts_on_overflow ?
589  if (ret == AVERROR(EAGAIN)) {
590  uint8_t overflow_set = 0;
591 
592  /* Queue is full, set fifo->overflow_flag to 1
593  * to let consumer thread know the queue should
594  * be flushed. */
596  if (!fifo->overflow_flag)
597  fifo->overflow_flag = overflow_set = 1;
599 
600  if (overflow_set)
601  av_log(avf, AV_LOG_WARNING, "FIFO queue full\n");
602  ret = 0;
603  goto fail;
604  } else if (ret < 0) {
605  goto fail;
606  }
607 
608  if (fifo->timeshift && pkt && pkt->dts != AV_NOPTS_VALUE)
609  atomic_fetch_add_explicit(&fifo->queue_duration, next_duration(avf, pkt, &fifo->last_sent_dts), memory_order_relaxed);
610 
611  return ret;
612 fail:
613  if (pkt)
614  av_packet_unref(&msg.pkt);
615  return ret;
616 }
617 
619 {
620  FifoContext *fifo= avf->priv_data;
621  int ret;
622 
624  if (fifo->timeshift) {
625  int64_t now = av_gettime_relative();
626  int64_t elapsed = 0;
627  FifoMessage msg = {FIFO_NOOP};
628  do {
629  int64_t delay = av_gettime_relative() - now;
630  if (delay < 0) { // Discontinuity?
631  delay = 10000;
632  now = av_gettime_relative();
633  } else {
634  now += delay;
635  }
636  atomic_fetch_add_explicit(&fifo->queue_duration, delay, memory_order_relaxed);
637  elapsed += delay;
638  if (elapsed > fifo->timeshift)
639  break;
640  av_usleep(10000);
642  } while (ret >= 0 || ret == AVERROR(EAGAIN));
643  atomic_store(&fifo->queue_duration, INT64_MAX);
644  }
645 
647  if (ret < 0) {
648  av_log(avf, AV_LOG_ERROR, "pthread join error: %s\n",
650  return AVERROR(ret);
651  }
652 
653  ret = fifo->write_trailer_ret;
654  return ret;
655 }
656 
657 static void fifo_deinit(AVFormatContext *avf)
658 {
659  FifoContext *fifo = avf->priv_data;
660 
661  avformat_free_context(fifo->avf);
665 }
666 
667 #define OFFSET(x) offsetof(FifoContext, x)
668 static const AVOption options[] = {
669  {"fifo_format", "Target muxer", OFFSET(format),
671 
672  {"queue_size", "Size of fifo queue", OFFSET(queue_size),
674 
675  {"format_opts", "Options to be passed to underlying muxer", OFFSET(format_options),
677 
678  {"drop_pkts_on_overflow", "Drop packets on fifo queue overflow not to block encoder", OFFSET(drop_pkts_on_overflow),
679  AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
680 
681  {"restart_with_keyframe", "Wait for keyframe when restarting output", OFFSET(restart_with_keyframe),
682  AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
683 
684  {"attempt_recovery", "Attempt recovery in case of failure", OFFSET(attempt_recovery),
685  AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
686 
687  {"max_recovery_attempts", "Maximal number of recovery attempts", OFFSET(max_recovery_attempts),
689 
690  {"recovery_wait_time", "Waiting time between recovery attempts", OFFSET(recovery_wait_time),
692 
693  {"recovery_wait_streamtime", "Use stream time instead of real time while waiting for recovery",
694  OFFSET(recovery_wait_streamtime), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
695 
696  {"recover_any_error", "Attempt recovery regardless of type of the error", OFFSET(recover_any_error),
697  AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
698 
699  {"timeshift", "Delay fifo output", OFFSET(timeshift),
700  AV_OPT_TYPE_DURATION, {.i64 = 0}, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM},
701 
702  {NULL},
703 };
704 
705 static const AVClass fifo_muxer_class = {
706  .class_name = "Fifo muxer",
707  .item_name = av_default_item_name,
708  .option = options,
709  .version = LIBAVUTIL_VERSION_INT,
710 };
711 
713  .name = "fifo",
714  .long_name = NULL_IF_CONFIG_SMALL("FIFO queue pseudo-muxer"),
715  .priv_data_size = sizeof(FifoContext),
716  .init = fifo_init,
720  .deinit = fifo_deinit,
721  .priv_class = &fifo_muxer_class,
723 };
pthread_mutex_t
_fmutex pthread_mutex_t
Definition: os2threads.h:53
av_packet_unref
void av_packet_unref(AVPacket *pkt)
Wipe the packet.
Definition: avpacket.c:422
pthread_join
static av_always_inline int pthread_join(pthread_t thread, void **value_ptr)
Definition: os2threads.h:94
av_gettime_relative
int64_t av_gettime_relative(void)
Get the current time in microseconds since some unspecified starting point.
Definition: time.c:56
fifo_init
static int fifo_init(AVFormatContext *avf)
Definition: fifo.c:520
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
fifo_thread_flush_output
static int fifo_thread_flush_output(FifoThreadContext *ctx)
Definition: fifo.c:162
atomic_store
#define atomic_store(object, desired)
Definition: stdatomic.h:85
AVOutputFormat::name
const char * name
Definition: avformat.h:510
AVERROR
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
FifoContext::write_trailer_ret
int write_trailer_ret
Definition: fifo.c:50
opt.h
avformat_new_stream
AVStream * avformat_new_stream(AVFormatContext *s, const AVCodec *c)
Add a new stream to a media file.
Definition: options.c:237
FifoContext::queue
AVThreadMessageQueue * queue
Definition: fifo.c:45
FIFO_WRITE_PACKET
@ FIFO_WRITE_PACKET
Definition: fifo.c:114
FifoContext::avf
AVFormatContext * avf
Definition: fifo.c:39
thread.h
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
pthread_mutex_init
static av_always_inline int pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)
Definition: os2threads.h:104
fifo_deinit
static void fifo_deinit(AVFormatContext *avf)
Definition: fifo.c:657
FifoContext
Definition: fifo.c:38
AV_TIME_BASE_Q
#define AV_TIME_BASE_Q
Internal time base represented as fractional value.
Definition: avutil.h:260
fifo_write_packet
static int fifo_write_packet(AVFormatContext *avf, AVPacket *pkt)
Definition: fifo.c:574
AV_THREAD_MESSAGE_NONBLOCK
@ AV_THREAD_MESSAGE_NONBLOCK
Perform non-blocking operation.
Definition: threadmessage.h:31
ff_stream_encode_params_copy
int ff_stream_encode_params_copy(AVStream *dst, const AVStream *src)
Copy encoding parameters from source to destination stream.
Definition: mux_utils.c:124
AVFormatContext::streams
AVStream ** streams
A list of all streams in the file.
Definition: avformat.h:1281
deinit
static void deinit(AVFormatContext *s)
Definition: chromaprint.c:49
free_message
static void free_message(void *msg)
Definition: fifo.c:285
FifoContext::format_options
AVDictionary * format_options
Definition: fifo.c:42
AVOption
AVOption.
Definition: opt.h:251
FIFO_NOOP
@ FIFO_NOOP
Definition: fifo.c:112
data
const char data[16]
Definition: mxf.c:143
AV_OPT_TYPE_DURATION
@ AV_OPT_TYPE_DURATION
Definition: opt.h:239
AV_DICT_IGNORE_SUFFIX
#define AV_DICT_IGNORE_SUFFIX
Return first entry in a dictionary whose first part corresponds to the search key,...
Definition: dict.h:68
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
FifoThreadContext::drop_until_keyframe
uint8_t drop_until_keyframe
Definition: fifo.c:101
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:392
AVDictionary
Definition: dict.c:30
FFMAX
#define FFMAX(a, b)
Definition: macros.h:47
FIFO_WRITE_HEADER
@ FIFO_WRITE_HEADER
Definition: fifo.c:113
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:429
FifoContext::overflow_flag
volatile uint8_t overflow_flag
Definition: fifo.c:81
AVFormatContext::interrupt_callback
AVIOInterruptCB interrupt_callback
Custom interrupt callbacks for the I/O layer.
Definition: avformat.h:1480
FifoContext::last_sent_dts
int64_t last_sent_dts
Definition: fifo.c:84
ffstream
static av_always_inline FFStream * ffstream(AVStream *st)
Definition: internal.h:407
FifoMessage::type
FifoMessageType type
Definition: fifo.c:119
fail
#define fail()
Definition: checkasm.h:131
FifoMessage
Definition: fifo.c:118
FifoContext::queue_size
int queue_size
Definition: fifo.c:44
av_thread_message_queue_recv
int av_thread_message_queue_recv(AVThreadMessageQueue *mq, void *msg, unsigned flags)
Receive a message from the queue.
Definition: threadmessage.c:174
is_recoverable
static int is_recoverable(const FifoContext *fifo, int err_no)
Definition: fifo.c:266
avassert.h
fifo_thread_process_recovery_failure
static int fifo_thread_process_recovery_failure(FifoThreadContext *ctx, AVPacket *pkt, int err_no)
Definition: fifo.c:293
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
AVFormatContext::metadata
AVDictionary * metadata
Metadata that applies to the whole file.
Definition: avformat.h:1442
av_thread_message_queue_send
int av_thread_message_queue_send(AVThreadMessageQueue *mq, void *msg, unsigned flags)
Send a message on the queue.
Definition: threadmessage.c:158
av_thread_message_flush
void av_thread_message_flush(AVThreadMessageQueue *mq)
Flush the message queue.
Definition: threadmessage.c:223
duration
int64_t duration
Definition: movenc.c:64
av_dict_get
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
FifoContext::overflow_flag_lock
pthread_mutex_t overflow_flag_lock
Definition: fifo.c:78
AV_OPT_FLAG_ENCODING_PARAM
#define AV_OPT_FLAG_ENCODING_PARAM
a generic parameter which can be set by the user for muxing or encoding
Definition: opt.h:281
FifoContext::max_recovery_attempts
int max_recovery_attempts
Definition: fifo.c:58
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1331
format
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
AVDictionaryEntry::key
char * key
Definition: dict.h:80
fifo_thread_write_packet
static int fifo_thread_write_packet(FifoThreadContext *ctx, AVPacket *pkt)
Definition: fifo.c:180
options
static const AVOption options[]
Definition: fifo.c:668
OFFSET
#define OFFSET(x)
Definition: fifo.c:667
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
ctx
AVFormatContext * ctx
Definition: movenc.c:48
av_rescale_q
int64_t av_rescale_q(int64_t a, AVRational bq, AVRational cq)
Rescale a 64-bit integer by 2 rational numbers.
Definition: mathematics.c:142
FIFO_DEFAULT_QUEUE_SIZE
#define FIFO_DEFAULT_QUEUE_SIZE
Definition: fifo.c:33
AVFormatContext::opaque
void * opaque
User data.
Definition: avformat.h:1719
AVThreadMessageQueue
Definition: threadmessage.c:27
fifo_thread_write_trailer
static int fifo_thread_write_trailer(FifoThreadContext *ctx)
Definition: fifo.c:223
av_usleep
int av_usleep(unsigned usec)
Sleep for a period of time.
Definition: time.c:84
avformat_write_header
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:449
pthread_create
static av_always_inline int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine)(void *), void *arg)
Definition: os2threads.h:80
AVFormatContext
Format I/O context.
Definition: avformat.h:1213
internal.h
FifoThreadContext
Definition: fifo.c:88
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:66
AVStream::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition: avformat.h:978
NULL
#define NULL
Definition: coverity.c:32
AVERROR_PATCHWELCOME
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
Definition: error.h:64
write_trailer
static int write_trailer(AVFormatContext *s1)
Definition: v4l2enc.c:100
AVRational
Rational number (pair of numerator and denominator).
Definition: rational.h:58
AV_OPT_TYPE_DICT
@ AV_OPT_TYPE_DICT
Definition: opt.h:232
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:237
AVFormatContext::pb
AVIOContext * pb
I/O context.
Definition: avformat.h:1255
fifo_write_header
static int fifo_write_header(AVFormatContext *avf)
Definition: fifo.c:559
fifo_thread_dispatch_message
static int fifo_thread_dispatch_message(FifoThreadContext *ctx, FifoMessage *msg)
Definition: fifo.c:239
time.h
av_write_frame
int av_write_frame(AVFormatContext *s, AVPacket *pkt)
Write a packet to an output media file.
Definition: mux.c:1188
av_packet_ref
int av_packet_ref(AVPacket *dst, const AVPacket *src)
Setup a new reference to the data described by a given packet.
Definition: avpacket.c:430
atomic_fetch_sub_explicit
#define atomic_fetch_sub_explicit(object, operand, order)
Definition: stdatomic.h:152
atomic_load_explicit
#define atomic_load_explicit(object, order)
Definition: stdatomic.h:96
FifoContext::writer_thread
pthread_t writer_thread
Definition: fifo.c:47
pthread_mutex_unlock
#define pthread_mutex_unlock(a)
Definition: ffprobe.c:77
AVFormatContext::nb_streams
unsigned int nb_streams
Number of elements in AVFormatContext.streams.
Definition: avformat.h:1269
FifoContext::recover_any_error
int recover_any_error
Definition: fifo.c:69
FifoThreadContext::last_received_dts
int64_t last_received_dts
Definition: fifo.c:108
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
fifo_consumer_thread
static void * fifo_consumer_thread(void *data)
Definition: fifo.c:422
threadmessage.h
av_err2str
#define av_err2str(errnum)
Convenience macro, the return value should be used only directly in function arguments but never stan...
Definition: error.h:121
FifoContext::drop_pkts_on_overflow
int drop_pkts_on_overflow
Definition: fifo.c:72
FifoThreadContext::last_recovery_ts
int64_t last_recovery_ts
Definition: fifo.c:94
AVFormatContext::url
char * url
input or output URL.
Definition: avformat.h:1296
atomic_fetch_add_explicit
#define atomic_fetch_add_explicit(object, operand, order)
Definition: stdatomic.h:149
AV_NOPTS_VALUE
#define AV_NOPTS_VALUE
Undefined timestamp value.
Definition: avutil.h:248
AVFMT_ALLOW_FLUSH
#define AVFMT_ALLOW_FLUSH
Format allows flushing.
Definition: avformat.h:490
AVFMT_NOFILE
#define AVFMT_NOFILE
Demuxer will use avio_open, no opened file should be provided by the caller.
Definition: avformat.h:470
ff_format_io_close
int ff_format_io_close(AVFormatContext *s, AVIOContext **pb)
Definition: avformat.c:779
ff_fifo_muxer
const AVOutputFormat ff_fifo_muxer
Definition: fifo.c:712
FifoContext::timeshift
int64_t timeshift
Definition: fifo.c:85
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:373
FifoMessageType
FifoMessageType
Definition: fifo.c:111
FifoContext::recovery_wait_streamtime
int recovery_wait_streamtime
Definition: fifo.c:65
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:380
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:203
av_packet_rescale_ts
void av_packet_rescale_ts(AVPacket *pkt, AVRational src_tb, AVRational dst_tb)
Convert valid timing fields (timestamps / durations) in a packet from one timebase to another.
Definition: avpacket.c:526
pthread_t
Definition: os2threads.h:44
FifoContext::queue_duration
atomic_int_least64_t queue_duration
Definition: fifo.c:83
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:191
av_thread_message_queue_alloc
int av_thread_message_queue_alloc(AVThreadMessageQueue **mq, unsigned nelem, unsigned elsize)
Allocate a new message queue.
Definition: threadmessage.c:42
pthread_mutex_destroy
static av_always_inline int pthread_mutex_destroy(pthread_mutex_t *mutex)
Definition: os2threads.h:112
av_write_trailer
int av_write_trailer(AVFormatContext *s)
Write the stream trailer to an output media file and free the file private data.
Definition: mux.c:1250
FIFO_DEFAULT_MAX_RECOVERY_ATTEMPTS
#define FIFO_DEFAULT_MAX_RECOVERY_ATTEMPTS
Definition: fifo.c:34
FifoMessage::pkt
AVPacket pkt
Definition: fifo.c:120
AVOutputFormat
Definition: avformat.h:509
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:367
AVERROR_MUXER_NOT_FOUND
#define AVERROR_MUXER_NOT_FOUND
Muxer not found.
Definition: error.h:62
av_thread_message_queue_set_err_send
void av_thread_message_queue_set_err_send(AVThreadMessageQueue *mq, int err)
Set the sending error code.
Definition: threadmessage.c:190
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
AVFormatContext::max_delay
int max_delay
Definition: avformat.h:1325
tb
#define tb
Definition: regdef.h:68
FifoThreadContext::recovery_nr
int recovery_nr
Definition: fifo.c:98
AVFMT_TS_NEGATIVE
#define AVFMT_TS_NEGATIVE
Format allows muxing negative timestamps.
Definition: avformat.h:494
atomic_int_least64_t
intptr_t atomic_int_least64_t
Definition: stdatomic.h:68
ret
ret
Definition: filter_design.txt:187
AVStream
Stream structure.
Definition: avformat.h:948
AVClass::class_name
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:71
FifoContext::restart_with_keyframe
int restart_with_keyframe
Definition: fifo.c:76
avformat.h
fifo_thread_write_header
static int fifo_thread_write_header(FifoThreadContext *ctx)
Definition: fifo.c:123
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:225
FifoThreadContext::avf
AVFormatContext * avf
Definition: fifo.c:89
avformat_free_context
void avformat_free_context(AVFormatContext *s)
Free an AVFormatContext and all its streams.
Definition: avformat.c:95
fifo_muxer_class
static const AVClass fifo_muxer_class
Definition: fifo.c:705
AVFormatContext::io_close
void(* io_close)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition: avformat.h:1779
AVFormatContext::io_open
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:1773
AVPacket::stream_index
int stream_index
Definition: packet.h:376
next_duration
static int64_t next_duration(AVFormatContext *avf, AVPacket *pkt, int64_t *last_dts)
Definition: fifo.c:171
av_guess_format
const AVOutputFormat * av_guess_format(const char *short_name, const char *filename, const char *mime_type)
Return the output format in the list of registered output formats which best matches the provided par...
Definition: format.c:53
FifoContext::attempt_recovery
int attempt_recovery
Definition: fifo.c:61
FIFO_DEFAULT_RECOVERY_WAIT_TIME_USEC
#define FIFO_DEFAULT_RECOVERY_WAIT_TIME_USEC
Definition: fifo.c:35
fifo_thread_recover
static int fifo_thread_recover(FifoThreadContext *ctx, FifoMessage *msg, int err_no)
Definition: fifo.c:396
AVDictionaryEntry
Definition: dict.h:79
fifo_write_trailer
static int fifo_write_trailer(AVFormatContext *avf)
Definition: fifo.c:618
AVPacket
This structure stores compressed data.
Definition: packet.h:351
AV_OPT_TYPE_BOOL
@ AV_OPT_TYPE_BOOL
Definition: opt.h:244
av_thread_message_queue_free
void av_thread_message_queue_free(AVThreadMessageQueue **mq)
Free a message queue.
Definition: threadmessage.c:93
av_dict_copy
int av_dict_copy(AVDictionary **dst, const AVDictionary *src, int flags)
Copy entries from one AVDictionary struct into another.
Definition: dict.c:217
fifo_thread_attempt_recovery
static int fifo_thread_attempt_recovery(FifoThreadContext *ctx, FifoMessage *msg, int err_no)
Definition: fifo.c:325
FFStream::cur_dts
int64_t cur_dts
Definition: internal.h:404
AVFormatContext::io_close2
int(* io_close2)(struct AVFormatContext *s, AVIOContext *pb)
A callback for closing the streams opened with AVFormatContext.io_open().
Definition: avformat.h:1820
flags
#define flags(name, subs,...)
Definition: cbs_av1.c:561
ff_format_output_open
int ff_format_output_open(AVFormatContext *s, const char *url, AVDictionary **options)
Utility function to open IO stream of output format.
Definition: mux_utils.c:114
av_thread_message_queue_set_err_recv
void av_thread_message_queue_set_err_recv(AVThreadMessageQueue *mq, int err)
Set the receiving error code.
Definition: threadmessage.c:201
av_thread_message_queue_set_free_func
void av_thread_message_queue_set_free_func(AVThreadMessageQueue *mq, void(*free_func)(void *msg))
Set the optional free message callback function which will be called if an operation is removing mess...
Definition: threadmessage.c:85
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
AVERROR_EXIT
#define AVERROR_EXIT
Immediate exit was requested; the called function should not be restarted.
Definition: error.h:58
FifoContext::recovery_wait_time
int64_t recovery_wait_time
Definition: fifo.c:55
write_packet
static int write_packet(AVFormatContext *s1, AVPacket *pkt)
Definition: v4l2enc.c:92
atomic_init
#define atomic_init(obj, value)
Definition: stdatomic.h:33
AV_OPT_TYPE_STRING
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
write_header
static void write_header(FFV1Context *f)
Definition: ffv1enc.c:346
init
static av_cold int init(AVFilterContext *ctx)
Definition: fifo.c:50
FIFO_FLUSH_OUTPUT
@ FIFO_FLUSH_OUTPUT
Definition: fifo.c:115
fifo_mux_init
static int fifo_mux_init(AVFormatContext *avf, const AVOutputFormat *oformat, const char *filename)
Definition: fifo.c:483
avformat_alloc_output_context2
int avformat_alloc_output_context2(AVFormatContext **ctx, const AVOutputFormat *oformat, const char *format_name, const char *filename)
Allocate an AVFormatContext for an output format.
Definition: mux.c:91
FifoContext::overflow_flag_lock_initialized
int overflow_flag_lock_initialized
Definition: fifo.c:79
AVFormatContext::priv_data
void * priv_data
Format private data.
Definition: avformat.h:1241
FifoThreadContext::header_written
uint8_t header_written
Definition: fifo.c:106
FifoContext::format
char * format
Definition: fifo.c:41
pthread_mutex_lock
#define pthread_mutex_lock(a)
Definition: ffprobe.c:73
mux.h