[FFmpeg-devel] [PATCH v1] lavf/dashenc: Add option for calculting pkt duration
Jun Li
junli1026 at gmail.com
Wed Apr 24 21:00:16 EEST 2019
On Sun, Apr 21, 2019 at 5:51 PM Jun Li <junli1026 at gmail.com> wrote:
> Fix #7144.
> The current packet duration calculation is heuristic, which uses the
> historical durtion as current duration. This commit adds the option
> to buffer one packet and calcuate its duration when next packet arrives.
> Obviously it adds one frame latency, which might be significant for
> VFR live content, so expose it as an option for user to choose.
> ---
> doc/muxers.texi | 4 ++++
> libavformat/dashenc.c | 44 +++++++++++++++++++++++++++++++++++++++++--
> 2 files changed, 46 insertions(+), 2 deletions(-)
>
> diff --git a/doc/muxers.texi b/doc/muxers.texi
> index ee99ef621e..76954877a6 100644
> --- a/doc/muxers.texi
> +++ b/doc/muxers.texi
> @@ -321,6 +321,10 @@ This is an experimental feature.
> @item -master_m3u8_publish_rate @var{master_m3u8_publish_rate}
> Publish master playlist repeatedly every after specified number of
> segment intervals.
>
> + at item -skip_estimate_pkt_duration
> +If this flag is set, packet duration will be calcuated as the diff of the
> current and next packet timestamp. The option is not for constant frame rate
> +content because heuristic estimation will be accurate in this case.
> Default value is 0.
> +
> @end table
>
> @anchor{framecrc}
> diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c
> index 5f1333e436..f89d68a51b 100644
> --- a/libavformat/dashenc.c
> +++ b/libavformat/dashenc.c
> @@ -101,6 +101,7 @@ typedef struct OutputStream {
> double availability_time_offset;
> int total_pkt_size;
> int muxer_overhead;
> + AVPacket* prev_pkt;
> } OutputStream;
>
> typedef struct DASHContext {
> @@ -145,6 +146,7 @@ typedef struct DASHContext {
> int ignore_io_errors;
> int lhls;
> int master_publish_rate;
> + int skip_estiamte_pkt_duration;
> int nr_of_streams_to_flush;
> int nr_of_streams_flushed;
> } DASHContext;
> @@ -1559,7 +1561,7 @@ static int dash_flush(AVFormatContext *s, int final,
> int stream)
> } else {
> snprintf(os->full_path, sizeof(os->full_path), "%s%s",
> c->dirname, os->initfile);
> }
> -
> +
> ret = flush_dynbuf(c, os, &range_length);
> if (ret < 0)
> break;
> @@ -1643,7 +1645,7 @@ static int dash_flush(AVFormatContext *s, int final,
> int stream)
> return ret;
> }
>
> -static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
> +static int dash_write_packet_internal(AVFormatContext *s, AVPacket *pkt)
> {
> DASHContext *c = s->priv_data;
> AVStream *st = s->streams[pkt->stream_index];
> @@ -1789,11 +1791,47 @@ static int dash_write_packet(AVFormatContext *s,
> AVPacket *pkt)
> return ret;
> }
>
> +static int dash_write_packet(AVFormatContext *s, AVPacket *pkt)
> +{
> + DASHContext *c = s->priv_data;
> + if (!c->skip_estiamte_pkt_duration)
> + return dash_write_packet_internal(s, pkt);
> +
> + AVStream *st = s->streams[pkt->stream_index];
> + OutputStream *os = &c->streams[pkt->stream_index];
> + int ret = 0;
> +
> + if (os->prev_pkt) {
> + if (!os->prev_pkt->duration && pkt->dts >= os->prev_pkt->dts)
> + os->prev_pkt->duration = pkt->dts - os->prev_pkt->dts;
> + ret = dash_write_packet_internal(s, os->prev_pkt);
> + av_packet_unref(os->prev_pkt);
> + if (av_packet_ref(os->prev_pkt, pkt)) {
> + av_log(s, AV_LOG_ERROR, "Failed to set up a reference to
> current packet, lost one packet for muxing.\n");
> + av_packet_free(&os->prev_pkt);
> + }
> + } else {
> + os->prev_pkt = av_packet_clone(pkt);
> + }
> + return ret;
> +}
> +
> static int dash_write_trailer(AVFormatContext *s)
> {
> DASHContext *c = s->priv_data;
> int i;
>
> + if (c->skip_estiamte_pkt_duration) {
> + for (i = 0; i < s->nb_streams; i++) {
> + OutputStream *os = &c->streams[i];
> + if (os->prev_pkt) {
> + // write last packet
> + dash_write_packet_internal(s, os->prev_pkt);
> + av_packet_free(&os->prev_pkt);
> + }
> + }
> + }
> +
> if (s->nb_streams > 0) {
> OutputStream *os = &c->streams[0];
> // If no segments have been written so far, try to do a crude
> @@ -1888,6 +1926,8 @@ static const AVOption options[] = {
> { "ignore_io_errors", "Ignore IO errors during open and write. Useful
> for long-duration runs with network output", OFFSET(ignore_io_errors),
> AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E },
> { "lhls", "Enable Low-latency HLS(Experimental). Adds #EXT-X-PREFETCH
> tag with current segment's URI", OFFSET(lhls), AV_OPT_TYPE_BOOL, { .i64 = 0
> }, 0, 1, E },
> { "master_m3u8_publish_rate", "Publish master playlist every after
> this many segment intervals", OFFSET(master_publish_rate), AV_OPT_TYPE_INT,
> {.i64 = 0}, 0, UINT_MAX, E},
> + { "skip_estimate_pkt_duration", "Skip estimate packet duration,
> buffer previous packet for calculating its duration.",
> OFFSET(skip_estiamte_pkt_duration), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, E
> },
> +
> { NULL },
> };
>
> --
> 2.17.1
Ping.
More information about the ffmpeg-devel
mailing list