@@ -77,6 +77,7 @@ typedef struct {
unsigned duration;
unsigned size;
unsigned flags;
+ unsigned trun_entries;
} MOVFragment;
typedef struct {
@@ -138,6 +139,7 @@ typedef struct MOVContext {
DVDemuxContext *dv_demux;
AVFormatContext *dv_fctx;
int isom; ///< 1 if file is ISO Media (mp4/3gp)
+ int ismv; ///< 1 if file is ISMV/ISMA
MOVFragment fragment; ///< current fragment in moof atom
MOVTrackExt *trex_data;
unsigned trex_count;
@@ -664,6 +664,8 @@ static int mov_read_ftyp(MOVContext *c, AVIOContext *pb, MOVAtom atom)
avio_read(pb, type, 4);
if (strcmp(type, "qt "))
c->isom = 1;
+ if (!strcmp(type, "isml"))
+ c->ismv = 1;
av_log(c->fc, AV_LOG_DEBUG, "ISO: File Type Major Brand: %.4s\n",(char *)&type);
av_dict_set(&c->fc->metadata, "major_brand", type, 0);
minor_ver = avio_rb32(pb); /* minor version */
@@ -2292,10 +2294,54 @@ 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;
+
+ /* Interpret the ismv specific sdtp atom. After the version+flags,
+ * there's one byte per sample in the trun. The bytes seem to be 0x28
+ * for audio streams, 0x24 for video keyframes and 0x14 for video
+ * nonkeyframes.
+ * The sample flags seem to have a different meaning in these files, too,
+ * compared to the iso media spec. For ismv, the flags normally are
+ * 0x8002 for audio samples, 0x4002 for video keyframes and 0x4001 for
+ * nonkeyframes. However, some files don't have sample flags at all,
+ * others don't indicate any difference between keyframes and
+ * nonkeyframes in the flags. By parsing the sdtp, we get keyframes
+ * marked properly. */
+ if (!c->ismv)
+ return 0;
+
+ 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 +2501,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 },