changeset 1904:df5fe029a504 libavformat

reorder pts of packets from tracks using V_MPEG* codecs
author aurel
date Sun, 11 Mar 2007 23:40:57 +0000
parents 0f2186d1cc19
children 54d1bdcb47e2
files matroska.c
diffstat 1 files changed, 60 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/matroska.c	Sun Mar 11 23:19:27 2007 +0000
+++ b/matroska.c	Sun Mar 11 23:40:57 2007 +0000
@@ -178,6 +178,7 @@
   MATROSKA_TRACK_DEFAULT = (1<<1),
   MATROSKA_TRACK_LACING  = (1<<2),
   MATROSKA_TRACK_REAL_V  = (1<<4),
+  MATROSKA_TRACK_REORDER = (1<<8),
   MATROSKA_TRACK_SHIFT   = (1<<16)
 } MatroskaTrackFlags;
 
@@ -336,6 +337,10 @@
     /* The packet queue. */
     AVPacket **packets;
     int num_packets;
+    /* Second packet queue used to reorder pts of some video track. */
+    AVPacket **packets_reorder;
+    int num_packets_reorder;
+    uint64_t reorder_max_pts;
 
     /* have we already parse metadata/cues/clusters? */
     int metadata_parsed,
@@ -1021,6 +1026,43 @@
 }
 
 /*
+ * Put a packet into our internal reordering queue. Will be moved to the
+ * main packet queue when enough packets are available to reorder pts.
+ */
+
+static void
+matroska_queue_packet_reordered (MatroskaDemuxContext *matroska,
+                                 AVPacket             *pkt,
+                                 int                   is_bframe)
+{
+    if (matroska->num_packets_reorder && !is_bframe
+        && pkt->pts > matroska->reorder_max_pts) {
+        /* reorder pts */
+        int i, j, k = 1;
+        for (j=matroska->num_packets_reorder-1; j && k; j--) {
+            k = 0;
+            for (i=0; i<j; i++) {
+                if (matroska->packets_reorder[i]->pts > matroska->packets_reorder[i+1]->pts) {
+                    FFSWAP(uint64_t, matroska->packets_reorder[i]->pts, matroska->packets_reorder[i+1]->pts);
+                    k = 1;
+                }
+            }
+        }
+        /* then really queue the packets */
+        for (i=0; i<matroska->num_packets_reorder; i++)
+            matroska_queue_packet (matroska, matroska->packets_reorder[i]);
+        matroska->num_packets_reorder = 0;
+    }
+    matroska->packets_reorder =
+        av_realloc(matroska->packets_reorder,
+                   (matroska->num_packets_reorder + 1) * sizeof(AVPacket *));
+    matroska->packets_reorder[matroska->num_packets_reorder++] = pkt;
+    if (pkt->pts > matroska->reorder_max_pts)
+        matroska->reorder_max_pts = pkt->pts;
+}
+
+
+/*
  * Autodetecting...
  */
 
@@ -2245,6 +2287,14 @@
 
             }
 
+            else if (codec_id == CODEC_ID_MPEG1VIDEO ||
+                     codec_id == CODEC_ID_MPEG2VIDEO ||
+                     codec_id == CODEC_ID_MPEG4      ||
+                     codec_id == CODEC_ID_MSMPEG4V3  ||
+                     codec_id == CODEC_ID_H264) {
+                track->flags |= MATROSKA_TRACK_REORDER;
+            }
+
             else if (codec_id == CODEC_ID_AAC && !track->codec_priv_size) {
                 MatroskaAudioTrack *audiotrack = (MatroskaAudioTrack *) track;
                 int profile = matroska_aac_profile(track->codec_id);
@@ -2541,6 +2591,9 @@
                 pkt->pts = timecode;
                 pkt->pos = pos;
 
+                if (matroska->tracks[track]->flags & MATROSKA_TRACK_REORDER)
+                    matroska_queue_packet_reordered(matroska, pkt, is_bframe);
+                else
                 matroska_queue_packet(matroska, pkt);
             }
             data += lace_size[n];
@@ -2775,6 +2828,13 @@
         }
         av_free(matroska->packets);
     }
+    if (matroska->packets_reorder) {
+        for (n = 0; n < matroska->num_packets_reorder; n++) {
+            av_free_packet(matroska->packets_reorder[n]);
+            av_free(matroska->packets_reorder[n]);
+        }
+        av_free(matroska->packets_reorder);
+    }
 
     for (n = 0; n < matroska->num_tracks; n++) {
         MatroskaTrack *track = matroska->tracks[n];