Message ID | 1588166736-82427-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 |
leozhang (12020-04-29): > Signed-off-by: leozhang <leozhang@qiyi.com> > --- > doc/muxers.texi | 3 +++ > libavformat/fifo.c | 19 +++++++++++++++++++ > 2 files changed, 22 insertions(+) > > diff --git a/doc/muxers.texi b/doc/muxers.texi > index a74cbc4..5140c00 100644 > --- a/doc/muxers.texi > +++ b/doc/muxers.texi > @@ -2274,6 +2274,9 @@ queue overflow or failure. This option is set to 0 (false) by default. > @item output_delay > Time to delay output, in microseconds. Default value is 0. > > +@item paced > +If set to 1 (true), write packets in paced way. Default value is 0 (false). This does not explain to somebody who does not already know. Please have a look at the doc for the filter "realtime" and use a similar wording, preferably with cross-references. > + > @end table > > @subsection Examples > diff --git a/libavformat/fifo.c b/libavformat/fifo.c > index bdecf2d..81b7e9e 100644 > --- a/libavformat/fifo.c > +++ b/libavformat/fifo.c > @@ -79,6 +79,12 @@ typedef struct FifoContext { > > /* Time to delay output, in microseconds */ > uint64_t output_delay; > + > + /* If set to 1, write packets in paced way */ > + int paced; > + > + /* Time to start */ > + uint64_t start_time; The return value of av_gettime_relative() is signed. > } FifoContext; > > typedef struct FifoThreadContext { > @@ -184,6 +190,14 @@ static int fifo_thread_write_packet(FifoThreadContext *ctx, AVPacket *pkt) > src_tb = avf->streams[s_idx]->time_base; > dst_tb = avf2->streams[s_idx]->time_base; > av_packet_rescale_ts(pkt, src_tb, dst_tb); > + if (fifo->paced) { > + uint64_t pts = av_rescale_q(pkt->dts, dst_tb, AV_TIME_BASE_Q); > + uint64_t now = av_gettime_relative() - fifo->start_time; > + av_assert0(now >= fifo->output_delay); av_gettime_relative() is not guaranteed to be monotonic, an assert is not acceptable here. > + if (pts > now - fifo->output_delay) { You probably need to make provisions for when the process was paused and then resumed, and for timestamps discontinuities. > + av_usleep(pts - (now - fifo->output_delay)); The argument to av_usleep() is unsigned, you are passing uint64_t, it can overflow. > + } > + } > > ret = av_write_frame(avf2, pkt); > if (ret >= 0) > @@ -515,6 +529,8 @@ static int fifo_init(AVFormatContext *avf) > return AVERROR(ret); > fifo->overflow_flag_lock_initialized = 1; > > + fifo->start_time = av_gettime_relative(); > + > return 0; > } > > @@ -637,6 +653,9 @@ static const AVOption options[] = { > {"output_delay", "Time to delay output, in microseconds", OFFSET(output_delay), > AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, > > + {"paced", "Write packets in paced way", OFFSET(paced), > + AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, > + > {NULL}, > }; > Regards,
Nicolas George <george@nsup.org> 于2020年4月29日周三 下午9:51写道: > > leozhang (12020-04-29): > > Signed-off-by: leozhang <leozhang@qiyi.com> > > --- > > doc/muxers.texi | 3 +++ > > libavformat/fifo.c | 19 +++++++++++++++++++ > > 2 files changed, 22 insertions(+) > > > > diff --git a/doc/muxers.texi b/doc/muxers.texi > > index a74cbc4..5140c00 100644 > > --- a/doc/muxers.texi > > +++ b/doc/muxers.texi > > @@ -2274,6 +2274,9 @@ queue overflow or failure. This option is set to 0 (false) by default. > > @item output_delay > > Time to delay output, in microseconds. Default value is 0. > > > > > +@item paced > > +If set to 1 (true), write packets in paced way. Default value is 0 (false). > > This does not explain to somebody who does not already know. Please have > a look at the doc for the filter "realtime" and use a similar wording, > preferably with cross-references. I'm reading the realtime filter and have learned a lot. Will make more clear description in v2 version. > > > + > > @end table > > > > @subsection Examples > > diff --git a/libavformat/fifo.c b/libavformat/fifo.c > > index bdecf2d..81b7e9e 100644 > > --- a/libavformat/fifo.c > > +++ b/libavformat/fifo.c > > @@ -79,6 +79,12 @@ typedef struct FifoContext { > > > > /* Time to delay output, in microseconds */ > > uint64_t output_delay; > > + > > + /* If set to 1, write packets in paced way */ > > + int paced; > > + > > + /* Time to start */ > > > + uint64_t start_time; > > The return value of av_gettime_relative() is signed. will fix it in v2 version. > > > } FifoContext; > > > > typedef struct FifoThreadContext { > > @@ -184,6 +190,14 @@ static int fifo_thread_write_packet(FifoThreadContext *ctx, AVPacket *pkt) > > src_tb = avf->streams[s_idx]->time_base; > > dst_tb = avf2->streams[s_idx]->time_base; > > av_packet_rescale_ts(pkt, src_tb, dst_tb); > > + if (fifo->paced) { > > + uint64_t pts = av_rescale_q(pkt->dts, dst_tb, AV_TIME_BASE_Q); > > + uint64_t now = av_gettime_relative() - fifo->start_time; > > > + av_assert0(now >= fifo->output_delay); > > av_gettime_relative() is not guaranteed to be monotonic, an assert is > not acceptable here. will fix it in v2 version. > > > + if (pts > now - fifo->output_delay) { > > You probably need to make provisions for when the process was paused and > then resumed, and for timestamps discontinuities. will fix it in v2 version. > > > + av_usleep(pts - (now - fifo->output_delay)); > > The argument to av_usleep() is unsigned, you are passing uint64_t, it > can overflow. will fix it in v2 version. > > > + } > > > + } > > > > ret = av_write_frame(avf2, pkt); > > if (ret >= 0) > > @@ -515,6 +529,8 @@ static int fifo_init(AVFormatContext *avf) > > return AVERROR(ret); > > fifo->overflow_flag_lock_initialized = 1; > > > > + fifo->start_time = av_gettime_relative(); > > + > > return 0; > > } > > > > @@ -637,6 +653,9 @@ static const AVOption options[] = { > > {"output_delay", "Time to delay output, in microseconds", OFFSET(output_delay), > > AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, > > > > + {"paced", "Write packets in paced way", OFFSET(paced), > > + AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, > > + > > {NULL}, > > }; > > > > Regards, > > -- > Nicolas George > _______________________________________________ > 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 a74cbc4..5140c00 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -2274,6 +2274,9 @@ queue overflow or failure. This option is set to 0 (false) by default. @item output_delay Time to delay output, in microseconds. Default value is 0. +@item paced +If set to 1 (true), write packets in paced way. Default value is 0 (false). + @end table @subsection Examples diff --git a/libavformat/fifo.c b/libavformat/fifo.c index bdecf2d..81b7e9e 100644 --- a/libavformat/fifo.c +++ b/libavformat/fifo.c @@ -79,6 +79,12 @@ typedef struct FifoContext { /* Time to delay output, in microseconds */ uint64_t output_delay; + + /* If set to 1, write packets in paced way */ + int paced; + + /* Time to start */ + uint64_t start_time; } FifoContext; typedef struct FifoThreadContext { @@ -184,6 +190,14 @@ static int fifo_thread_write_packet(FifoThreadContext *ctx, AVPacket *pkt) src_tb = avf->streams[s_idx]->time_base; dst_tb = avf2->streams[s_idx]->time_base; av_packet_rescale_ts(pkt, src_tb, dst_tb); + if (fifo->paced) { + uint64_t pts = av_rescale_q(pkt->dts, dst_tb, AV_TIME_BASE_Q); + uint64_t now = av_gettime_relative() - fifo->start_time; + av_assert0(now >= fifo->output_delay); + if (pts > now - fifo->output_delay) { + av_usleep(pts - (now - fifo->output_delay)); + } + } ret = av_write_frame(avf2, pkt); if (ret >= 0) @@ -515,6 +529,8 @@ static int fifo_init(AVFormatContext *avf) return AVERROR(ret); fifo->overflow_flag_lock_initialized = 1; + fifo->start_time = av_gettime_relative(); + return 0; } @@ -637,6 +653,9 @@ static const AVOption options[] = { {"output_delay", "Time to delay output, in microseconds", OFFSET(output_delay), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, + {"paced", "Write packets in paced way", OFFSET(paced), + AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, + {NULL}, };
Signed-off-by: leozhang <leozhang@qiyi.com> --- doc/muxers.texi | 3 +++ libavformat/fifo.c | 19 +++++++++++++++++++ 2 files changed, 22 insertions(+)