summaryrefslogtreecommitdiff
path: root/libavformat/matroska.c
diff options
context:
space:
mode:
authorAurelien Jacobs <aurel@gnuage.org>2007-03-11 23:40:57 +0000
committerAurelien Jacobs <aurel@gnuage.org>2007-03-11 23:40:57 +0000
commitac9073c926c15a1295cee0cf20b315d67ea695ed (patch)
treef01c8b79e3499e286fc79ec6412919c0121e64de /libavformat/matroska.c
parent3d20538d070e04fb90524ab36e6c5cc18f099778 (diff)
reorder pts of packets from tracks using V_MPEG* codecs
Originally committed as revision 8334 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavformat/matroska.c')
-rw-r--r--libavformat/matroska.c60
1 files changed, 60 insertions, 0 deletions
diff --git a/libavformat/matroska.c b/libavformat/matroska.c
index f01cfff126..e74bf3d23e 100644
--- a/libavformat/matroska.c
+++ b/libavformat/matroska.c
@@ -178,6 +178,7 @@ typedef enum {
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 @@ typedef struct MatroskaDemuxContext {
/* 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 @@ matroska_queue_packet (MatroskaDemuxContext *matroska,
}
/*
+ * 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 @@ matroska_read_header (AVFormatContext *s,
}
+ 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 @@ matroska_parse_block(MatroskaDemuxContext *matroska, uint8_t *data, int size,
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 @@ matroska_read_close (AVFormatContext *s)
}
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];