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.
 
+@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

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to