[FFmpeg-devel] [PATCH v2 1/3] avformat/fifo: add options to slow down writing packets to match real time approximately

leozhang leozhang at qiyi.com
Thu May 7 09:16:48 EEST 2020


Suggested-by: Nicolas George <george at nsup.org>
Reviewed-by:  Nicolas George <george at nsup.org>
Reviewed-by:  Marton Balint <cus at passwd.hu>
Reviewed-by:  Andreas Rheinhardt <andreas.rheinhardt at gmail.com>
Signed-off-by: leozhang <leozhang at qiyi.com>
---
 doc/muxers.texi    | 21 +++++++++++++++++++++
 libavformat/fifo.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 67 insertions(+)

diff --git a/doc/muxers.texi b/doc/muxers.texi
index 536433b..14528f1 100644
--- a/doc/muxers.texi
+++ b/doc/muxers.texi
@@ -2274,6 +2274,17 @@ certain (usually permanent) errors the recovery is not attempted even when
 Specify whether to wait for the keyframe after recovering from
 queue overflow or failure. This option is set to 0 (false) by default.
 
+ at item realtime @var{bool}
+If set to 1 (true), slow down writing packets to match real time approximately.
+This is similar to @ref{the realtime or arealtime filters,,the "realtime_002c-arealtime" section in the ffmpeg-filters manual,ffmpeg-filters}.
+Please note that in some cases without filtering, such as stream copy, you can also use it.
+
+ at item realtime_speed
+It is the same as the speed option to realtime or arealtime filters.
+
+ at item realtime_limit @var{duration}
+It is the same as the limit option to realtime or arealtime filters.
+
 @end table
 
 @subsection Examples
@@ -2291,6 +2302,16 @@ ffmpeg -re -i ... -c:v libx264 -c:a aac -f fifo -fifo_format flv -map 0:v -map 0
 
 @end itemize
 
+ at itemize
+
+ at item
+Stream something to rtmp server, instead of using -re option.
+ at example
+ffmpeg -i your_input_file -c copy -map 0:v -map 0:a -f fifo -fifo_format flv -realtime 1 rtmp://example.com/live/stream_name
+ at end example
+
+ at end itemize
+
 @anchor{tee}
 @section tee
 
diff --git a/libavformat/fifo.c b/libavformat/fifo.c
index d11dc66..7acc420 100644
--- a/libavformat/fifo.c
+++ b/libavformat/fifo.c
@@ -26,6 +26,7 @@
 #include "libavutil/threadmessage.h"
 #include "avformat.h"
 #include "internal.h"
+#include <float.h>
 
 #define FIFO_DEFAULT_QUEUE_SIZE              60
 #define FIFO_DEFAULT_MAX_RECOVERY_ATTEMPTS   0
@@ -77,6 +78,17 @@ typedef struct FifoContext {
     /* Value > 0 signals queue overflow */
     volatile uint8_t overflow_flag;
 
+    /* Slow down writing packets to match real time approximately */
+    int realtime;
+
+    /* Speed factor for the processing when realtime */
+    double realtime_speed;
+
+    /* Time limit for the pauses when realtime */
+    int64_t realtime_limit;
+
+    int64_t delta;
+    unsigned inited;
 } FifoContext;
 
 typedef struct FifoThreadContext {
@@ -183,6 +195,31 @@ static int fifo_thread_write_packet(FifoThreadContext *ctx, AVPacket *pkt)
     dst_tb = avf2->streams[s_idx]->time_base;
     av_packet_rescale_ts(pkt, src_tb, dst_tb);
 
+    if (fifo->realtime) {
+        int64_t pts = av_rescale_q(pkt->dts, dst_tb, AV_TIME_BASE_Q) / fifo->realtime_speed;
+        int64_t now = av_gettime_relative();
+        int64_t sleep = pts - now + fifo->delta;
+
+        if (!fifo->inited) {
+            sleep = 0;
+            fifo->delta = now - pts;
+            fifo->inited = 1;
+        }
+
+        if (FFABS(sleep) > fifo->realtime_limit / fifo->realtime_speed) {
+            av_log(avf, AV_LOG_WARNING, "time discontinuity detected: %"PRIi64" us, resetting\n", sleep);
+            sleep = 0;
+            fifo->delta = now - pts;
+        }
+
+        if (sleep > 0) {
+            av_log(avf, AV_LOG_DEBUG, "sleeping %"PRIi64" us\n", sleep);
+            for (; sleep > 600000000; sleep -= 600000000)
+                av_usleep(600000000);
+            av_usleep(sleep);
+        }
+    }
+
     ret = av_write_frame(avf2, pkt);
     if (ret >= 0)
         av_packet_unref(pkt);
@@ -630,6 +667,15 @@ static const AVOption options[] = {
         {"recover_any_error", "Attempt recovery regardless of type of the error", OFFSET(recover_any_error),
          AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
 
+        {"realtime", "Slow down writing packets to match real time approximately", OFFSET(realtime),
+         AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM},
+
+        {"realtime_speed", "Speed factor for the processing when realtime", OFFSET(realtime_speed),
+         AV_OPT_TYPE_DOUBLE, {.dbl = 1.0}, DBL_MIN, DBL_MAX, AV_OPT_FLAG_ENCODING_PARAM},
+
+        {"realtime_limit", "Time limit for the pauses when realtime", OFFSET(realtime_limit),
+         AV_OPT_TYPE_DURATION, {.i64 = 2000000}, 0, INT64_MAX, AV_OPT_FLAG_ENCODING_PARAM},
+
         {NULL},
 };
 
-- 
1.8.3.1



More information about the ffmpeg-devel mailing list