av_interleave_packet_per_dts waits until it gets a frame for each
stream before outputting packets in interleaved order.

Sparse streams tend to add up latency and in specific cases end up
allocating a large amount of memory.

Emit the top packet from the packet_buffer if it has a time delta
larger than max_delay.

Original report of the issue and initial proposed solution by
[email protected] on bug 31.
---
 libavformat/avformat.h |    3 +++
 libavformat/utils.c    |   39 ++++++++++++++++++++++++++++++++++-----
 2 files changed, 37 insertions(+), 5 deletions(-)

diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 367ba1e..7a73866 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -887,6 +887,9 @@ typedef struct AVFormatContext {
 #if FF_API_PRELOAD
     attribute_deprecated int preload;
 #endif
+    /**
+     * maximum muxing/demuxing delay in microseconds
+     */
     int max_delay;
 
 #if FF_API_LOOP_OUTPUT
diff --git a/libavformat/utils.c b/libavformat/utils.c
index 10e79eb..d036480 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -3138,19 +3138,48 @@ static int ff_interleave_compare_dts(AVFormatContext 
*s, AVPacket *next, AVPacke
     return comp > 0;
 }
 
-int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket 
*pkt, int flush){
+int av_interleave_packet_per_dts(AVFormatContext *s,
+                                 AVPacket *out, AVPacket *pkt, int flush)
+{
+    AVPacket *top_pkt;
     AVPacketList *pktl;
-    int stream_count=0;
+    int stream_count = 0;
+    int64_t delta_dts = INT64_MIN;
+    int64_t top_dts, last_dts;
     int i;
 
     if(pkt){
         ff_interleave_add_packet(s, pkt, ff_interleave_compare_dts);
     }
 
-    for(i=0; i < s->nb_streams; i++)
-        stream_count+= !!s->streams[i]->last_in_packet_buffer;
+    if (s->max_delay && s->packet_buffer) {
+        top_pkt = &s->packet_buffer->pkt;
+        top_dts = av_rescale_q(top_pkt->dts,
+                                s->streams[top_pkt->stream_index]->time_base,
+                                AV_TIME_BASE_Q);
+
+        for (i = 0; i < s->nb_streams; i++) {
+            const AVPacketList *last = s->streams[i]->last_in_packet_buffer;
+            if (!last) continue;
+
+            last_dts = av_rescale_q(last->pkt.dts,
+                                   s->streams[i]->time_base,
+                                   AV_TIME_BASE_Q);
+            delta_dts = FFMAX(delta_dts, last_dts - top_dts);
+            stream_count++;
+        }
+
+        if (delta_dts > s->max_delay) {
+            av_log(s, AV_LOG_DEBUG,
+                   "Deadline reached, emitting a packet\n");
+            flush = 1;
+        }
+    } else {
+        for (i = 0; i < s->nb_streams; i++)
+            stream_count += !!s->streams[i]->last_in_packet_buffer;
+    }
 
-    if(stream_count && (s->nb_streams == stream_count || flush)){
+    if (stream_count && (s->nb_streams == stream_count || flush)) {
         pktl= s->packet_buffer;
         *out= pktl->pkt;
 
-- 
1.7.8.rc1

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to