diff options
author | Aurelien Jacobs <aurel@gnuage.org> | 2007-03-11 23:40:57 +0000 |
---|---|---|
committer | Aurelien Jacobs <aurel@gnuage.org> | 2007-03-11 23:40:57 +0000 |
commit | ac9073c926c15a1295cee0cf20b315d67ea695ed (patch) | |
tree | f01c8b79e3499e286fc79ec6412919c0121e64de /libavformat/matroska.c | |
parent | 3d20538d070e04fb90524ab36e6c5cc18f099778 (diff) | |
download | ffmpeg-ac9073c926c15a1295cee0cf20b315d67ea695ed.tar.gz |
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.c | 60 |
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]; |