changeset 5210:36d130853c9b libavformat

Improve amortized worst case speed of the muxers packet interleaving code from O(packets_in_the_file) to O(num_of_streams).
author michael
date Wed, 16 Sep 2009 20:04:04 +0000
parents 2b52ec1e8619
children 78065d4a5ae1
files avformat.h mxfenc.c oggenc.c utils.c
diffstat 4 files changed, 34 insertions(+), 14 deletions(-) [+]
line wrap: on
line diff
--- a/avformat.h	Wed Sep 16 18:06:29 2009 +0000
+++ b/avformat.h	Wed Sep 16 20:04:04 2009 +0000
@@ -452,10 +452,10 @@
     int probe_packets;
 
     /**
-     * Number of packets in packet_buffer for this stream when muxing.
+     * last packet in packet_buffer for this stream when muxing.
      * used internally, NOT PART OF PUBLIC API, dont read or write from outside of libav*
      */
-    int num_in_packet_buffer;
+    struct AVPacketList *last_in_packet_buffer;
 } AVStream;
 
 #define AV_PROGRAM_RUNNING 1
--- a/mxfenc.c	Wed Sep 16 18:06:29 2009 +0000
+++ b/mxfenc.c	Wed Sep 16 20:04:04 2009 +0000
@@ -1836,6 +1836,9 @@
             // purge packet queue
             while (pktl) {
                 AVPacketList *next = pktl->next;
+
+                if(s->streams[pktl->pkt.stream_index]->last_in_packet_buffer == pktl)
+                    s->streams[pktl->pkt.stream_index]->last_in_packet_buffer= NULL;
                 av_free_packet(&pktl->pkt);
                 av_freep(&pktl);
                 pktl = next;
@@ -1844,6 +1847,7 @@
                 last->next = NULL;
             else {
                 s->packet_buffer = NULL;
+                s->packet_buffer_end= NULL;
                 goto out;
             }
             pktl = s->packet_buffer;
@@ -1852,6 +1856,10 @@
         *out = pktl->pkt;
         //av_log(s, AV_LOG_DEBUG, "out st:%d dts:%lld\n", (*out).stream_index, (*out).dts);
         s->packet_buffer = pktl->next;
+        if(s->streams[pktl->pkt.stream_index]->last_in_packet_buffer == pktl)
+            s->streams[pktl->pkt.stream_index]->last_in_packet_buffer= NULL;
+        if(!s->packet_buffer)
+            s->packet_buffer_end= NULL;
         av_freep(&pktl);
         return 1;
     } else {
--- a/oggenc.c	Wed Sep 16 18:06:29 2009 +0000
+++ b/oggenc.c	Wed Sep 16 20:04:04 2009 +0000
@@ -261,6 +261,12 @@
             OGGStreamContext *ogg = s->streams[out->stream_index]->priv_data;
             ogg->eos = 1;
         }
+        if(!s->packet_buffer)
+            s->packet_buffer_end= NULL;
+
+        if(s->streams[out->stream_index]->last_in_packet_buffer == pktl)
+            s->streams[out->stream_index]->last_in_packet_buffer= NULL;
+
         av_freep(&pktl);
         return 1;
     } else {
--- a/utils.c	Wed Sep 16 18:06:29 2009 +0000
+++ b/utils.c	Wed Sep 16 20:04:04 2009 +0000
@@ -2657,25 +2657,30 @@
     pkt->destruct= NULL;             // do not free original but only the copy
     av_dup_packet(&this_pktl->pkt);  // duplicate the packet if it uses non-alloced memory
 
-    if(!s->packet_buffer_end || compare(s, &s->packet_buffer_end->pkt, pkt)){
+    if(s->streams[pkt->stream_index]->last_in_packet_buffer){
+        next_point = &(s->streams[pkt->stream_index]->last_in_packet_buffer->next);
+    }else
         next_point = &s->packet_buffer;
-        while(*next_point){
-            if(compare(s, &(*next_point)->pkt, pkt))
-                break;
+
+    if(*next_point){
+        if(compare(s, &s->packet_buffer_end->pkt, pkt)){
+            while(!compare(s, &(*next_point)->pkt, pkt)){
             next_point= &(*next_point)->next;
         }
+            goto next_non_null;
     }else{
         next_point = &(s->packet_buffer_end->next);
+        }
+    }
         assert(!*next_point);
-    }
+
+        s->packet_buffer_end= this_pktl;
+next_non_null:
+
     this_pktl->next= *next_point;
 
-    if(!*next_point)
-        s->packet_buffer_end= this_pktl;
-
+    s->streams[pkt->stream_index]->last_in_packet_buffer=
     *next_point= this_pktl;
-
-    s->streams[pkt->stream_index]->num_in_packet_buffer++;
 }
 
 int ff_interleave_compare_dts(AVFormatContext *s, AVPacket *next, AVPacket *pkt)
@@ -2701,7 +2706,7 @@
     }
 
     for(i=0; i < s->nb_streams; i++)
-        stream_count+= !!s->streams[i]->num_in_packet_buffer;
+        stream_count+= !!s->streams[i]->last_in_packet_buffer;
 
     if(stream_count && (s->nb_streams == stream_count || flush)){
         pktl= s->packet_buffer;
@@ -2711,7 +2716,8 @@
         if(!s->packet_buffer)
             s->packet_buffer_end= NULL;
 
-        s->streams[out->stream_index]->num_in_packet_buffer--;
+        if(s->streams[out->stream_index]->last_in_packet_buffer == pktl)
+            s->streams[out->stream_index]->last_in_packet_buffer= NULL;
         av_freep(&pktl);
         return 1;
     }else{