movdec: Parse the ismv specific sdtp atom

Message ID 1329520533-79595-1-git-send-email-martin@martin.st
State Superseded
Headers show

Commit Message

Martin Storsjö Feb. 17, 2012, 11:15 p.m.
Set keyframe flags based on this atom, too.

This atom contains info about which samples are keyframes in
some files where it isn't indicated in any other way. (Smooth
streaming fragments produced by Wowza and ismv files produced
by Sorenson Squeeze don't indicate any difference at all between
keyframes and nonkeyframes via sample flags.)
---
I realized the way this is used in ismv actually is consistent
with the iso media specs (I had misread it before), so updated
the patch to be less vague, and do the same code for non-ismv
files, too.

This fixes bug 215.

 libavformat/isom.h |    1 +
 libavformat/mov.c  |   38 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+), 0 deletions(-)

Comments

Martin Storsjö Feb. 17, 2012, 11:18 p.m. | #1
On Sat, 18 Feb 2012, Martin Storsjö wrote:

> Set keyframe flags based on this atom, too.
>
> This atom contains info about which samples are keyframes in
> some files where it isn't indicated in any other way. (Smooth
> streaming fragments produced by Wowza and ismv files produced
> by Sorenson Squeeze don't indicate any difference at all between
> keyframes and nonkeyframes via sample flags.)
> ---
> I realized the way this is used in ismv actually is consistent
> with the iso media specs (I had misread it before), so updated
> the patch to be less vague, and do the same code for non-ismv
> files, too.

Ah, crap, still didn't update the patch subject properly. I removed the 
"ismv specific" part of the subject locally now.

// Martin

Patch

diff --git a/libavformat/isom.h b/libavformat/isom.h
index e74a552..c6cce04 100644
--- a/libavformat/isom.h
+++ b/libavformat/isom.h
@@ -77,6 +77,7 @@  typedef struct {
     unsigned duration;
     unsigned size;
     unsigned flags;
+    unsigned trun_entries;
 } MOVFragment;
 
 typedef struct {
diff --git a/libavformat/mov.c b/libavformat/mov.c
index 690cd1e..216b39f 100644
--- a/libavformat/mov.c
+++ b/libavformat/mov.c
@@ -2175,6 +2175,7 @@  static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom)
     frag->duration = flags & 0x08 ? avio_rb32(pb) : trex->duration;
     frag->size     = flags & 0x10 ? avio_rb32(pb) : trex->size;
     frag->flags    = flags & 0x20 ? avio_rb32(pb) : trex->flags;
+    frag->trun_entries = 0;
     av_dlog(c->fc, "frag flags 0x%x\n", frag->flags);
     return 0;
 }
@@ -2292,10 +2293,46 @@  static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom)
         sc->data_size += sample_size;
     }
     frag->moof_offset = offset;
+    frag->trun_entries = entries;
     st->duration = sc->track_end = dts + sc->time_offset;
     return 0;
 }
 
+static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+    MOVFragment *frag = &c->fragment;
+    AVStream *st = NULL;
+    int i;
+
+    /* This seems to be used in ismv files, where the entries normally are
+     * 0x28 for audio samples, 0x24 for video keyframes and 0x14 for video
+     * nonkeyframes. For some ismv files, this is the only way of identifying
+     * keyframes.
+     */
+
+    for (i = 0; i < c->fc->nb_streams && !st; i++)
+        if (c->fc->streams[i]->id == frag->track_id)
+            st = c->fc->streams[i];
+    if (!st) {
+        av_log(c->fc, AV_LOG_ERROR,
+               "could not find corresponding track id %d\n", frag->track_id);
+        return AVERROR_INVALIDDATA;
+    }
+    avio_r8(pb); /* version */
+    avio_rb24(pb); /* flags */
+
+    if (frag->trun_entries == atom.size - 4 &&
+        st->nb_index_entries >= frag->trun_entries) {
+        for (i = 0; i < frag->trun_entries; i++) {
+            int entry = st->nb_index_entries - frag->trun_entries + i;
+            AVIndexEntry *ie = &st->index_entries[entry];
+            if (avio_r8(pb) & 0x20)
+                ie->flags |= AVINDEX_KEYFRAME;
+        }
+    }
+    return 0;
+}
+
 /* this atom should be null (from specs), but some buggy files put the 'moov' atom inside it... */
 /* like the files created with Adobe Premiere 5.0, for samples see */
 /* http://graphics.tudelft.nl/~wouter/publications/soundtests/ */
@@ -2455,6 +2492,7 @@  static const MOVParseTableEntry mov_default_parse_table[] = {
 { MKTAG('c','h','a','p'), mov_read_chap },
 { MKTAG('t','r','e','x'), mov_read_trex },
 { MKTAG('t','r','u','n'), mov_read_trun },
+{ MKTAG('s','d','t','p'), mov_read_sdtp },
 { MKTAG('u','d','t','a'), mov_read_default },
 { MKTAG('w','a','v','e'), mov_read_wave },
 { MKTAG('e','s','d','s'), mov_read_esds },