av_interleave_packet_per_dts waits untill 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.

Flush the packet queue if the packets in the queue have a delay
larger than the max_delay.

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

diff --git a/libavformat/avformat.h b/libavformat/avformat.h
index 33e820e..09960ec 100644
--- a/libavformat/avformat.h
+++ b/libavformat/avformat.h
@@ -853,6 +853,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 b8262ec..686ecd8 100644
--- a/libavformat/utils.c
+++ b/libavformat/utils.c
@@ -3140,19 +3140,45 @@ 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 *last_pkt;
     AVPacketList *pktl;
-    int stream_count=0;
+    int stream_count = 0;
+    int64_t delta_dts = INT64_MIN;
+    int64_t 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) {
+        last_pkt = &s->packet_buffer->pkt;
+        last_dts = av_rescale_q(last_pkt->dts,
+                                s->streams[last_pkt->stream_index]->time_base,
+                                AV_TIME_BASE_Q);
+
+        for (i=0; i < s->nb_streams; i++)
+            if (s->streams[i]->last_in_packet_buffer) {
+                delta_dts = FFMAX(delta_dts,
+                    av_rescale_q(s->streams[i]->last_in_packet_buffer->pkt.dts,
+                                 s->streams[i]->time_base,
+                                 AV_TIME_BASE_Q) - last_dts);
+                stream_count++;
+            }
+
+        if (delta_dts > s->max_delay) {
+            av_log(s, AV_LOG_DEBUG, "Sparse stream detected, forcing flush\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