changeset 5200:cd884511ec8b libavformat

Make packet interleaving in the muxer not scan through the whole buffer when simply appending at the end works. Much faster if one stream ends prematurely. Fixes issue1379.
author michael
date Wed, 16 Sep 2009 00:59:15 +0000
parents fc6e05b7709d
children 12bd8561aed1
files avformat.h utils.c
diffstat 2 files changed, 24 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/avformat.h	Wed Sep 16 00:56:31 2009 +0000
+++ b/avformat.h	Wed Sep 16 00:59:15 2009 +0000
@@ -450,6 +450,12 @@
      */
 #define MAX_PROBE_PACKETS 100
     int probe_packets;
+
+    /**
+     * Number of packets 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;
 } AVStream;
 
 #define AV_PROGRAM_RUNNING 1
--- a/utils.c	Wed Sep 16 00:56:31 2009 +0000
+++ b/utils.c	Wed Sep 16 00:59:15 2009 +0000
@@ -2657,14 +2657,25 @@
     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)){
     next_point = &s->packet_buffer;
     while(*next_point){
         if(compare(s, &(*next_point)->pkt, pkt))
             break;
         next_point= &(*next_point)->next;
     }
+    }else{
+        next_point = &(s->packet_buffer_end->next);
+        assert(!*next_point);
+    }
     this_pktl->next= *next_point;
+
+    if(!*next_point)
+        s->packet_buffer_end= this_pktl;
+
     *next_point= this_pktl;
+
+    s->streams[pkt->stream_index]->num_in_packet_buffer++;
 }
 
 int ff_interleave_compare_dts(AVFormatContext *s, AVPacket *next, AVPacket *pkt)
@@ -2683,27 +2694,24 @@
 int av_interleave_packet_per_dts(AVFormatContext *s, AVPacket *out, AVPacket *pkt, int flush){
     AVPacketList *pktl;
     int stream_count=0;
-    int streams[MAX_STREAMS];
+    int i;
 
     if(pkt){
         ff_interleave_add_packet(s, pkt, ff_interleave_compare_dts);
     }
 
-    memset(streams, 0, sizeof(streams));
-    pktl= s->packet_buffer;
-    while(pktl){
-//av_log(s, AV_LOG_DEBUG, "show st:%d dts:%"PRId64"\n", pktl->pkt.stream_index, pktl->pkt.dts);
-        if(streams[ pktl->pkt.stream_index ] == 0)
-            stream_count++;
-        streams[ pktl->pkt.stream_index ]++;
-        pktl= pktl->next;
-    }
+    for(i=0; i < s->nb_streams; i++)
+        stream_count+= !!s->streams[i]->num_in_packet_buffer;
 
     if(stream_count && (s->nb_streams == stream_count || flush)){
         pktl= s->packet_buffer;
         *out= pktl->pkt;
 
         s->packet_buffer= pktl->next;
+        if(!s->packet_buffer)
+            s->packet_buffer_end= NULL;
+
+        s->streams[out->stream_index]->num_in_packet_buffer--;
         av_freep(&pktl);
         return 1;
     }else{