changeset 383:1674ed5ca2f0 libavformat

Parse stss info in MOV files to get key frames patch by ("Brian Becker" <Brian dot Becker at palmone dot com>)
author michael
date Sat, 13 Mar 2004 21:02:26 +0000
parents 37a29b5200d8
children 9479dac25620
files mov.c
diffstat 1 files changed, 54 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/mov.c	Sat Mar 13 17:30:37 2004 +0000
+++ b/mov.c	Sat Mar 13 21:02:26 2004 +0000
@@ -220,6 +220,8 @@
     long sample_size;
     long sample_count;
     long *sample_sizes;
+    long keyframe_count;
+    long *keyframes;
     int time_scale;
     long current_sample;
     long left_in_chunk; /* how many samples before next chunk */
@@ -1102,6 +1104,34 @@
     return 0;
 }
 
+static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+{
+    AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+    MOVStreamContext *sc = (MOVStreamContext *)st->priv_data;
+    int entries, i;
+
+    print_atom("stss", atom);
+
+    get_byte(pb); /* version */
+    get_byte(pb); get_byte(pb); get_byte(pb); /* flags */
+
+    entries = get_be32(pb);
+    sc->keyframe_count = entries;
+#ifdef DEBUG
+    av_log(NULL, AV_LOG_DEBUG, "keyframe_count = %ld\n", sc->keyframe_count);
+#endif
+    sc->keyframes = (long*) av_malloc(entries * sizeof(long));
+    if (!sc->keyframes)
+        return -1;
+    for(i=0; i<entries; i++) {
+        sc->keyframes[i] = get_be32(pb);
+#ifdef DEBUG
+/*        av_log(NULL, AV_LOG_DEBUG, "keyframes[]=%ld\n", sc->keyframes[i]); */
+#endif
+    }
+    return 0;
+}
+
 static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
 {
     AVStream *st = c->fc->streams[c->fc->nb_streams-1];
@@ -1409,7 +1439,7 @@
 { MKTAG( 's', 't', 's', 'c' ), mov_read_stsc },
 { MKTAG( 's', 't', 's', 'd' ), mov_read_stsd }, /* sample description */
 { MKTAG( 's', 't', 's', 'h' ), mov_read_default },
-{ MKTAG( 's', 't', 's', 's' ), mov_read_leaf }, /* sync sample */
+{ MKTAG( 's', 't', 's', 's' ), mov_read_stss }, /* sync sample */
 { MKTAG( 's', 't', 's', 'z' ), mov_read_stsz }, /* sample size */
 { MKTAG( 's', 't', 't', 's' ), mov_read_stts },
 { MKTAG( 't', 'k', 'h', 'd' ), mov_read_tkhd }, /* track header */
@@ -1455,6 +1485,7 @@
         av_free(sc->chunk_offsets);
         av_free(sc->sample_to_chunk);
         av_free(sc->sample_sizes);
+        av_free(sc->keyframes);
         av_free(sc->header_data);
         av_free(sc);
     }
@@ -1583,7 +1614,7 @@
     MOVContext *mov = (MOVContext *) s->priv_data;
     MOVStreamContext *sc;
     int64_t offset = 0x0FFFFFFFFFFFFFFFLL;
-    int i;
+    int i, a, b, m;
     int size;
     size = 0x0FFFFFFF;
 
@@ -1717,6 +1748,27 @@
         get_buffer(&s->pb, pkt->data, pkt->size);
     }
     pkt->stream_index = sc->ffindex;
+    
+    // If the keyframes table exists, mark any samples that are in the table as key frames.
+    // If no table exists, treat very sample as a key frame.
+    if (sc->keyframes) {        
+        a = 0;
+        b = sc->keyframe_count - 1;
+        
+        while (a < b) {
+            m = (a + b + 1) >> 1;
+            if (sc->keyframes[m] > sc->current_sample) {
+                b = m - 1;
+            } else {
+                a = m;
+            }    
+        }
+        
+        if (sc->keyframes[a] == sc->current_sample)
+            pkt->flags |= PKT_FLAG_KEY;
+    }
+    else
+        pkt->flags |= PKT_FLAG_KEY;
 
 #ifdef DEBUG
 /*