Message ID | 1588832208-63370-1-git-send-email-leozhang@qiyi.com |
---|---|
State | New |
Headers | show |
Series | Patch set to delay output live stream | expand |
Context | Check | Description |
---|---|---|
andriy/default | pending | |
andriy/make | success | Make finished |
andriy/make_fate | success | Make fate finished |
On Thu, 7 May 2020, leozhang wrote: > Suggested-by: Nicolas George <george@nsup.org> > Reviewed-by: Nicolas George <george@nsup.org> > Reviewed-by: Marton Balint <cus@passwd.hu> > Reviewed-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com> You seem to misunderstand the use of this tag. You should only add these if you received an explict LGTM for your patches. This has not happened here, you only got suggestions, and those suggestions were concerning your earlier patch versions. Also, what happened to the suggestion of using a buffer based approach and using realtime only for flushing? I will code something, and see how it goes, and will post a result as an RFC patch. Regards, Marton > Signed-off-by: leozhang <leozhang@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. > > +@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. > + > +@item realtime_speed > +It is the same as the speed option to realtime or arealtime filters. > + > +@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 > > +@itemize > + > +@item > +Stream something to rtmp server, instead of using -re option. > +@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 > +@end example > + > +@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 > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
Marton Balint <cus@passwd.hu> 于2020年5月7日周四 下午6:23写道: > > > > On Thu, 7 May 2020, leozhang wrote: > > > Suggested-by: Nicolas George <george@nsup.org> > > Reviewed-by: Nicolas George <george@nsup.org> > > Reviewed-by: Marton Balint <cus@passwd.hu> > > Reviewed-by: Andreas Rheinhardt <andreas.rheinhardt@gmail.com> > > You seem to misunderstand the use of this tag. You should only add these > if you received an explict LGTM for your patches. This has not happened > here, you only got suggestions, and those suggestions were concerning your > earlier patch versions. Yes, I have. Please ignore above Reviewed-by > > Also, what happened to the suggestion of using a buffer based approach and > using realtime only for flushing? I will code something, and see how it > goes, and will post a result as an RFC patch. I didn't try using a buffer based approach in fifo.c. If you're willing to post such RFC patch, I'm OK. Thanks > > Regards, > Marton > > > > Signed-off-by: leozhang <leozhang@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. > > > > +@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. > > + > > +@item realtime_speed > > +It is the same as the speed option to realtime or arealtime filters. > > + > > +@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 > > > > +@itemize > > + > > +@item > > +Stream something to rtmp server, instead of using -re option. > > +@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 > > +@end example > > + > > +@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 > > > > _______________________________________________ > > ffmpeg-devel mailing list > > ffmpeg-devel@ffmpeg.org > > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > > > To unsubscribe, visit link above, or email > > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe". > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > https://ffmpeg.org/mailman/listinfo/ffmpeg-devel > > To unsubscribe, visit link above, or email > ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
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. +@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. + +@item realtime_speed +It is the same as the speed option to realtime or arealtime filters. + +@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 +@itemize + +@item +Stream something to rtmp server, instead of using -re option. +@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 +@end example + +@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}, };