changeset 3773:2533332ca752 libavformat

matroskadec: on the fly index construction for index-less files each cluster that is read and that contains a video key frame is added to the index
author aurel
date Mon, 25 Aug 2008 00:09:08 +0000
parents 7814581e98ff
children fa5cc40e0164
files matroskadec.c
diffstat 1 files changed, 16 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/matroskadec.c	Sun Aug 24 23:57:29 2008 +0000
+++ b/matroskadec.c	Mon Aug 25 00:09:08 2008 +0000
@@ -204,6 +204,7 @@
     AVPacket **packets;
     int num_packets;
 
+    AVStream *vstream;
     int done;
     int has_cluster_id;
 
@@ -1270,6 +1271,7 @@
         }
 
         if (track->type == MATROSKA_TRACK_TYPE_VIDEO) {
+            if (!matroska->vstream)  matroska->vstream = st;
             st->codec->codec_type = CODEC_TYPE_VIDEO;
             st->codec->codec_tag  = track->video.fourcc;
             st->codec->width  = track->video.pixel_width;
@@ -1390,7 +1392,7 @@
                                 uint64_t duration, int is_keyframe)
 {
     MatroskaTrack *track;
-    int res = 0;
+    int is_video_key_frame = is_keyframe, res = 0;
     AVStream *st;
     AVPacket *pkt;
     int16_t block_time;
@@ -1430,6 +1432,8 @@
         matroska->skip_to_keyframe = 0;
     }
 
+    is_video_key_frame &= st == matroska->vstream;
+
     switch ((flags & 0x06) >> 1) {
         case 0x0: /* no lacing */
             laces = 1;
@@ -1592,7 +1596,7 @@
     }
 
     av_free(lace_size);
-    return res;
+    return res < 0 ? res : is_video_key_frame;
 }
 
 static int matroska_parse_cluster(MatroskaDemuxContext *matroska)
@@ -1600,23 +1604,31 @@
     MatroskaCluster cluster = { 0 };
     EbmlList *blocks_list;
     MatroskaBlock *blocks;
-    int i, res;
+    int i, res, key_frame = 0;
+    offset_t pos = url_ftell(matroska->ctx->pb);
     if (matroska->has_cluster_id){
         /* For the first cluster we parse, its ID was already read as
            part of matroska_read_header(), so don't read it again */
         res = ebml_parse_id(matroska, matroska_clusters,
                             MATROSKA_ID_CLUSTER, &cluster);
+        pos -= 4;  /* sizeof the ID which was already read */
         matroska->has_cluster_id = 0;
     } else
         res = ebml_parse(matroska, matroska_clusters, &cluster);
     blocks_list = &cluster.blocks;
     blocks = blocks_list->elem;
     for (i=0; i<blocks_list->nb_elem; i++)
-        if (blocks[i].bin.size > 0)
+        if (blocks[i].bin.size > 0) {
             res=matroska_parse_block(matroska,
                                      blocks[i].bin.data, blocks[i].bin.size,
                                      blocks[i].bin.pos,  cluster.timecode,
                                      blocks[i].duration, !blocks[i].reference);
+            key_frame |= res > 0;
+        }
+    if (key_frame)
+        av_add_index_entry(matroska->vstream, pos,
+                           cluster.timecode*matroska->time_scale/AV_TIME_BASE,
+                           0, 0, AVINDEX_KEYFRAME);
     ebml_free(matroska_cluster, &cluster);
     if (res < 0)  matroska->done = 1;
     return res;