/*
* MOV demuxer
- * Copyright (c) 2001 Fabrice Bellard.
+ * Copyright (c) 2001 Fabrice Bellard
*
* This file is part of FFmpeg.
*
//#define DEBUG
+#include "libavutil/intreadwrite.h"
#include "avformat.h"
#include "riff.h"
#include "isom.h"
#include "libavcodec/mpeg4audio.h"
#include "libavcodec/mpegaudiodata.h"
-#ifdef CONFIG_ZLIB
+#if CONFIG_ZLIB
#include <zlib.h>
#endif
int first;
int count;
int id;
-} MOV_stsc_t;
+} MOVStsc;
typedef struct {
uint32_t type;
char *path;
-} MOV_dref_t;
+} MOVDref;
typedef struct {
uint32_t type;
int64_t offset;
int64_t size; /* total size (excluding the size and type fields) */
-} MOV_atom_t;
+} MOVAtom;
struct MOVParseTableEntry;
unsigned int chunk_count;
int64_t *chunk_offsets;
unsigned int stts_count;
- MOV_stts_t *stts_data;
+ MOVStts *stts_data;
unsigned int ctts_count;
- MOV_stts_t *ctts_data;
+ MOVStts *ctts_data;
unsigned int edit_count; /* number of 'edit' (elst atom) */
unsigned int sample_to_chunk_sz;
- MOV_stsc_t *sample_to_chunk;
+ MOVStsc *sample_to_chunk;
int sample_to_ctime_index;
int sample_to_ctime_sample;
unsigned int sample_size;
int pseudo_stream_id; ///< -1 means demux all ids
int16_t audio_cid; ///< stsd audio compression id
unsigned drefs_count;
- MOV_dref_t *drefs;
+ MOVDref *drefs;
int dref_id;
int wrong_dts; ///< dts are wrong due to negative ctts
+ int width; ///< tkhd width
+ int height; ///< tkhd height
} MOVStreamContext;
typedef struct MOVContext {
MOVFragment fragment; ///< current fragment in moof atom
MOVTrackExt *trex_data;
unsigned trex_count;
+ int itunes_metadata; ///< metadata are itunes style
} MOVContext;
/* links atom IDs to parse functions */
typedef struct MOVParseTableEntry {
uint32_t type;
- int (*parse)(MOVContext *ctx, ByteIOContext *pb, MOV_atom_t atom);
+ int (*parse)(MOVContext *ctx, ByteIOContext *pb, MOVAtom atom);
} MOVParseTableEntry;
static const MOVParseTableEntry mov_default_parse_table[];
-static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
int64_t total_size = 0;
- MOV_atom_t a;
+ MOVAtom a;
int i;
int err = 0;
return err;
}
-static int mov_read_dref(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_dref(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
MOVStreamContext *sc = st->priv_data;
sc->drefs = av_mallocz(entries * sizeof(*sc->drefs));
for (i = 0; i < sc->drefs_count; i++) {
- MOV_dref_t *dref = &sc->drefs[i];
+ MOVDref *dref = &sc->drefs[i];
uint32_t size = get_be32(pb);
int64_t next = url_ftell(pb) + size - 4;
return 0;
}
-static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
uint32_t type;
{ CODEC_ID_NONE, 0 },
};
-static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
int tag, len;
return 0;
}
+static int mov_read_pasp(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
+{
+ const int num = get_be32(pb);
+ const int den = get_be32(pb);
+ AVStream * const st = c->fc->streams[c->fc->nb_streams-1];
+ if (den != 0) {
+ if ((st->sample_aspect_ratio.den != 1 || st->sample_aspect_ratio.num) && // default
+ (den != st->sample_aspect_ratio.den || num != st->sample_aspect_ratio.num))
+ av_log(c->fc, AV_LOG_WARNING,
+ "sample aspect ratio already set to %d:%d, overriding by 'pasp' atom\n",
+ st->sample_aspect_ratio.num, st->sample_aspect_ratio.den);
+ st->sample_aspect_ratio.num = num;
+ st->sample_aspect_ratio.den = den;
+ }
+ return 0;
+}
+
/* this atom contains actual media data */
-static int mov_read_mdat(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_mdat(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
if(atom.size == 0) /* wrong one (MP4) */
return 0;
return 0; /* now go for moov */
}
-static int mov_read_ftyp(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_ftyp(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
uint32_t type = get_le32(pb);
}
/* this atom should contain all header atoms */
-static int mov_read_moov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_moov(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
if (mov_read_default(c, pb, atom) < 0)
return -1;
return 0; /* now go for mdat */
}
-static int mov_read_moof(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_moof(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
c->fragment.moof_offset = url_ftell(pb) - 8;
dprintf(c->fc, "moof offset %llx\n", c->fragment.moof_offset);
return mov_read_default(c, pb, atom);
}
-static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
MOVStreamContext *sc = st->priv_data;
int version = get_byte(pb);
- int lang;
+ unsigned lang;
if (version > 1)
return -1; /* unsupported */
return 0;
}
-static int mov_read_mvhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_mvhd(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
int version = get_byte(pb); /* version */
get_be24(pb); /* flags */
return 0;
}
-static int mov_read_smi(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_smi(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
return 0;
}
-static int mov_read_enda(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_enda(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
int little_endian = get_be16(pb);
- if (little_endian) {
+ dprintf(c->fc, "enda %d\n", little_endian);
+ if (little_endian == 1) {
switch (st->codec->codec_id) {
case CODEC_ID_PCM_S24BE:
st->codec->codec_id = CODEC_ID_PCM_S24LE;
}
/* FIXME modify qdm2/svq3/h264 decoders to take full atom as extradata */
-static int mov_read_extradata(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_extradata(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
- AVStream *st = c->fc->streams[c->fc->nb_streams-1];
- uint64_t size= (uint64_t)st->codec->extradata_size + atom.size + 8 + FF_INPUT_BUFFER_PADDING_SIZE;
+ AVStream *st;
+ uint64_t size;
uint8_t *buf;
+
+ if (c->fc->nb_streams < 1) // will happen with jp2 files
+ return 0;
+ st= c->fc->streams[c->fc->nb_streams-1];
+ size= (uint64_t)st->codec->extradata_size + atom.size + 8 + FF_INPUT_BUFFER_PADDING_SIZE;
if(size > INT_MAX || (uint64_t)atom.size > INT_MAX)
return -1;
buf= av_realloc(st->codec->extradata, size);
return 0;
}
-static int mov_read_wave(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_wave(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
* This function reads atom content and puts data in extradata without tag
* nor size unlike mov_read_extradata.
*/
-static int mov_read_glbl(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_glbl(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
return 0;
}
-static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
MOVStreamContext *sc = st->priv_data;
return CODEC_ID_NONE;
}
-static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
MOVStreamContext *sc = st->priv_data;
//Parsing Sample description table
enum CodecID id;
int dref_id;
- MOV_atom_t a = { 0, 0, 0 };
+ MOVAtom a = { 0, 0, 0 };
int64_t start_pos = url_ftell(pb);
int size = get_be32(pb); /* size */
uint32_t format = get_le32(pb); /* data format */
sc->sample_size = (bits_per_sample >> 3) * st->codec->channels;
}
} else if(st->codec->codec_type==CODEC_TYPE_SUBTITLE){
+ // ttxt stsd contains display flags, justification, background
+ // color, fonts, and default styles, so fake an atom to read it
+ MOVAtom fake_atom = { .size = size - (url_ftell(pb) - start_pos) };
+ mov_read_glbl(c, pb, fake_atom);
st->codec->codec_id= id;
+ st->codec->width = sc->width;
+ st->codec->height = sc->height;
} else {
/* other codec type, just skip (rtp, mp4s, tmcd ...) */
url_fskip(pb, size - (url_ftell(pb) - start_pos));
/* special codec parameters handling */
switch (st->codec->codec_id) {
-#ifdef CONFIG_DV_DEMUXER
+#if CONFIG_DV_DEMUXER
case CODEC_ID_DVAUDIO:
c->dv_fctx = av_alloc_format_context();
c->dv_demux = dv_init_demux(c->dv_fctx);
#endif
/* no ifdef since parameters are always those */
case CODEC_ID_QCELP:
+ st->codec->frame_size= 160;
+ st->codec->channels= 1; /* really needed */
+ break;
case CODEC_ID_AMR_NB:
case CODEC_ID_AMR_WB:
st->codec->frame_size= sc->samples_per_frame;
st->codec->channels= 1; /* really needed */
+ /* force sample rate for amr, stsd in 3gp does not store sample rate */
+ if (st->codec->codec_id == CODEC_ID_AMR_NB)
+ st->codec->sample_rate = 8000;
+ else if (st->codec->codec_id == CODEC_ID_AMR_WB)
+ st->codec->sample_rate = 16000;
break;
case CODEC_ID_MP2:
case CODEC_ID_MP3:
st->codec->block_align = sc->bytes_per_frame;
break;
case CODEC_ID_ALAC:
- if (st->codec->extradata_size == 36)
- st->codec->frame_size = AV_RB32((st->codec->extradata+12));
+ if (st->codec->extradata_size == 36) {
+ st->codec->frame_size = AV_RB32(st->codec->extradata+12);
+ st->codec->channels = AV_RB8 (st->codec->extradata+21);
+ }
break;
default:
break;
return 0;
}
-static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_stsc(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
MOVStreamContext *sc = st->priv_data;
entries = get_be32(pb);
- if(entries >= UINT_MAX / sizeof(MOV_stsc_t))
+ if(entries >= UINT_MAX / sizeof(*sc->sample_to_chunk))
return -1;
dprintf(c->fc, "track[%i].stsc.entries = %i\n", c->fc->nb_streams-1, entries);
sc->sample_to_chunk_sz = entries;
- sc->sample_to_chunk = av_malloc(entries * sizeof(MOV_stsc_t));
+ sc->sample_to_chunk = av_malloc(entries * sizeof(*sc->sample_to_chunk));
if (!sc->sample_to_chunk)
return -1;
for(i=0; i<entries; i++) {
return 0;
}
-static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_stss(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
MOVStreamContext *sc = st->priv_data;
return 0;
}
-static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_stsz(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
MOVStreamContext *sc = st->priv_data;
return 0;
}
-static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_stts(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
MOVStreamContext *sc = st->priv_data;
get_byte(pb); /* version */
get_be24(pb); /* flags */
entries = get_be32(pb);
- if(entries >= UINT_MAX / sizeof(MOV_stts_t))
+ if(entries >= UINT_MAX / sizeof(*sc->stts_data))
return -1;
sc->stts_count = entries;
- sc->stts_data = av_malloc(entries * sizeof(MOV_stts_t));
+ sc->stts_data = av_malloc(entries * sizeof(*sc->stts_data));
if (!sc->stts_data)
return -1;
dprintf(c->fc, "track[%i].stts.entries = %i\n", c->fc->nb_streams-1, entries);
sc->stts_data[i].count= sample_count;
sc->stts_data[i].duration= sample_duration;
- sc->time_rate= ff_gcd(sc->time_rate, sample_duration);
+ sc->time_rate= av_gcd(sc->time_rate, sample_duration);
dprintf(c->fc, "sample_count=%d, sample_duration=%d\n",sample_count,sample_duration);
return 0;
}
-static int mov_read_ctts(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_ctts(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
MOVStreamContext *sc = st->priv_data;
get_byte(pb); /* version */
get_be24(pb); /* flags */
entries = get_be32(pb);
- if(entries >= UINT_MAX / sizeof(MOV_stts_t))
+ if(entries >= UINT_MAX / sizeof(*sc->ctts_data))
return -1;
sc->ctts_count = entries;
- sc->ctts_data = av_malloc(entries * sizeof(MOV_stts_t));
+ sc->ctts_data = av_malloc(entries * sizeof(*sc->ctts_data));
if (!sc->ctts_data)
return -1;
dprintf(c->fc, "track[%i].ctts.entries = %i\n", c->fc->nb_streams-1, entries);
sc->ctts_data[i].count = count;
sc->ctts_data[i].duration= duration;
- sc->time_rate= ff_gcd(sc->time_rate, FFABS(duration));
+ sc->time_rate= av_gcd(sc->time_rate, FFABS(duration));
}
return 0;
}
sc->sample_count = st->nb_index_entries;
}
-static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
AVStream *st;
MOVStreamContext *sc;
st->priv_data = sc;
st->codec->codec_type = CODEC_TYPE_DATA;
st->start_time = 0; /* XXX: check */
+ sc->ffindex = st->index;
if ((ret = mov_read_default(c, pb, atom)) < 0)
return ret;
assert(st->duration % sc->time_rate == 0);
st->duration /= sc->time_rate;
}
- sc->ffindex = st->index;
+
mov_build_index(c, st);
if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) {
sc->pb = c->fc->pb;
switch (st->codec->codec_id) {
-#ifdef CONFIG_H261_DECODER
+#if CONFIG_H261_DECODER
case CODEC_ID_H261:
#endif
-#ifdef CONFIG_H263_DECODER
+#if CONFIG_H263_DECODER
case CODEC_ID_H263:
#endif
-#ifdef CONFIG_MPEG4_DECODER
+#if CONFIG_MPEG4_DECODER
case CODEC_ID_MPEG4:
#endif
st->codec->width= 0; /* let decoder init width/height */
return 0;
}
-static void mov_parse_udta_string(ByteIOContext *pb, char *str, int size)
+static int mov_read_ilst(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
- uint16_t str_size = get_be16(pb); /* string length */;
-
- get_be16(pb); /* skip language */
- get_buffer(pb, str, FFMIN(size, str_size));
+ int ret;
+ c->itunes_metadata = 1;
+ ret = mov_read_default(c, pb, atom);
+ c->itunes_metadata = 0;
+ return ret;
}
-static int mov_read_udta(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_meta(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
- uint64_t end = url_ftell(pb) + atom.size;
-
- while (url_ftell(pb) + 8 < end) {
- uint32_t tag_size = get_be32(pb);
- uint32_t tag = get_le32(pb);
- uint64_t next = url_ftell(pb) + tag_size - 8;
-
- if (tag_size < 8 || next > end) // stop if tag_size is wrong
- break;
+ url_fskip(pb, 4); // version + flags
+ atom.size -= 4;
+ return mov_read_default(c, pb, atom);
+}
- switch (tag) {
- case MKTAG(0xa9,'n','a','m'):
- mov_parse_udta_string(pb, c->fc->title, sizeof(c->fc->title));
- break;
- case MKTAG(0xa9,'w','r','t'):
- mov_parse_udta_string(pb, c->fc->author, sizeof(c->fc->author));
- break;
- case MKTAG(0xa9,'c','p','y'):
- mov_parse_udta_string(pb, c->fc->copyright, sizeof(c->fc->copyright));
- break;
- case MKTAG(0xa9,'i','n','f'):
- mov_parse_udta_string(pb, c->fc->comment, sizeof(c->fc->comment));
- break;
- default:
- break;
- }
+static int mov_read_trkn(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
+{
+ get_be32(pb); // type
+ get_be32(pb); // unknown
+ c->fc->track = get_be32(pb);
+ dprintf(c->fc, "%.4s %d\n", (char*)&atom.type, c->fc->track);
+ return 0;
+}
- url_fseek(pb, next, SEEK_SET);
+static int mov_read_udta_string(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
+{
+ char *str = NULL;
+ int size;
+ uint16_t str_size;
+
+ if (c->itunes_metadata) {
+ int data_size = get_be32(pb);
+ int tag = get_le32(pb);
+ if (tag == MKTAG('d','a','t','a')) {
+ get_be32(pb); // type
+ get_be32(pb); // unknown
+ str_size = data_size - 16;
+ } else return 0;
+ } else {
+ str_size = get_be16(pb); // string length
+ get_be16(pb); // language
}
-
+ switch (atom.type) {
+ case MKTAG(0xa9,'n','a','m'):
+ str = c->fc->title; size = sizeof(c->fc->title); break;
+ case MKTAG(0xa9,'A','R','T'):
+ case MKTAG(0xa9,'w','r','t'):
+ str = c->fc->author; size = sizeof(c->fc->author); break;
+ case MKTAG(0xa9,'c','p','y'):
+ str = c->fc->copyright; size = sizeof(c->fc->copyright); break;
+ case MKTAG(0xa9,'c','m','t'):
+ case MKTAG(0xa9,'i','n','f'):
+ str = c->fc->comment; size = sizeof(c->fc->comment); break;
+ case MKTAG(0xa9,'a','l','b'):
+ str = c->fc->album; size = sizeof(c->fc->album); break;
+ }
+ if (!str)
+ return 0;
+ get_buffer(pb, str, FFMIN(size, str_size));
+ dprintf(c->fc, "%.4s %s\n", (char*)&atom.type, str);
return 0;
}
-static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_tkhd(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
int i;
int width;
int64_t disp_transform[2];
int display_matrix[3][2];
AVStream *st = c->fc->streams[c->fc->nb_streams-1];
+ MOVStreamContext *sc = st->priv_data;
int version = get_byte(pb);
get_be24(pb); /* flags */
width = get_be32(pb); // 16.16 fixed point track width
height = get_be32(pb); // 16.16 fixed point track height
+ sc->width = width >> 16;
+ sc->height = height >> 16;
//transform the display width/height according to the matrix
// skip this if the display matrix is the default identity matrix
return 0;
}
-static int mov_read_tfhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_tfhd(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
MOVFragment *frag = &c->fragment;
MOVTrackExt *trex = NULL;
return 0;
}
-static int mov_read_trex(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_trex(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
MOVTrackExt *trex;
return 0;
}
-static int mov_read_trun(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_trun(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
MOVFragment *frag = &c->fragment;
AVStream *st;
/* 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/ */
-static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
int err;
return err;
}
-static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
-#ifdef CONFIG_ZLIB
+#if CONFIG_ZLIB
ByteIOContext ctx;
uint8_t *cmov_data;
uint8_t *moov_data; /* uncompressed data */
}
/* edit list atom */
-static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom)
+static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOVAtom atom)
{
MOVStreamContext *sc = c->fc->streams[c->fc->nb_streams-1]->priv_data;
int i, edit_count;
{ MKTAG('f','t','y','p'), mov_read_ftyp },
{ MKTAG('g','l','b','l'), mov_read_glbl },
{ MKTAG('h','d','l','r'), mov_read_hdlr },
+{ MKTAG('i','l','s','t'), mov_read_ilst },
{ MKTAG('j','p','2','h'), mov_read_extradata },
{ MKTAG('m','d','a','t'), mov_read_mdat },
{ MKTAG('m','d','h','d'), mov_read_mdhd },
{ MKTAG('m','d','i','a'), mov_read_default },
+{ MKTAG('m','e','t','a'), mov_read_meta },
{ MKTAG('m','i','n','f'), mov_read_default },
{ MKTAG('m','o','o','f'), mov_read_moof },
{ MKTAG('m','o','o','v'), mov_read_moov },
{ MKTAG('S','M','I',' '), mov_read_smi }, /* Sorenson extension ??? */
{ MKTAG('a','l','a','c'), mov_read_extradata }, /* alac specific atom */
{ MKTAG('a','v','c','C'), mov_read_glbl },
+{ MKTAG('p','a','s','p'), mov_read_pasp },
{ MKTAG('s','t','b','l'), mov_read_default },
{ MKTAG('s','t','c','o'), mov_read_stco },
{ MKTAG('s','t','s','c'), mov_read_stsc },
{ MKTAG('t','r','a','k'), mov_read_trak },
{ MKTAG('t','r','a','f'), mov_read_default },
{ MKTAG('t','r','e','x'), mov_read_trex },
+{ MKTAG('t','r','k','n'), mov_read_trkn },
{ MKTAG('t','r','u','n'), mov_read_trun },
-{ MKTAG('u','d','t','a'), mov_read_udta },
+{ MKTAG('u','d','t','a'), mov_read_default },
{ MKTAG('w','a','v','e'), mov_read_wave },
{ MKTAG('e','s','d','s'), mov_read_esds },
{ MKTAG('w','i','d','e'), mov_read_wide }, /* place holder */
{ MKTAG('c','m','o','v'), mov_read_cmov },
+{ MKTAG(0xa9,'n','a','m'), mov_read_udta_string },
+{ MKTAG(0xa9,'w','r','t'), mov_read_udta_string },
+{ MKTAG(0xa9,'c','p','y'), mov_read_udta_string },
+{ MKTAG(0xa9,'i','n','f'), mov_read_udta_string },
+{ MKTAG(0xa9,'i','n','f'), mov_read_udta_string },
+{ MKTAG(0xa9,'A','R','T'), mov_read_udta_string },
+{ MKTAG(0xa9,'a','l','b'), mov_read_udta_string },
+{ MKTAG(0xa9,'c','m','t'), mov_read_udta_string },
{ 0, NULL }
};
MOVContext *mov = s->priv_data;
ByteIOContext *pb = s->pb;
int err;
- MOV_atom_t atom = { 0, 0, 0 };
+ MOVAtom atom = { 0, 0, 0 };
mov->fc = s;
/* .mov and .mp4 aren't streamable anyway (only progressive download if moov is before mdat) */
if (!sample) {
mov->found_mdat = 0;
if (!url_is_streamed(s->pb) ||
- mov_read_default(mov, s->pb, (MOV_atom_t){ 0, 0, INT64_MAX }) < 0 ||
+ mov_read_default(mov, s->pb, (MOVAtom){ 0, 0, INT64_MAX }) < 0 ||
url_feof(s->pb))
return -1;
dprintf(s, "read fragments, offset 0x%llx\n", url_ftell(s->pb));
return -1;
}
av_get_packet(sc->pb, pkt, sample->size);
-#ifdef CONFIG_DV_DEMUXER
+#if CONFIG_DV_DEMUXER
if (mov->dv_demux && sc->dv_audio_container) {
dv_produce_packet(mov->dv_demux, pkt, pkt->data, pkt->size);
av_free(pkt->data);
if (stream_index >= s->nb_streams)
return -1;
+ if (sample_time < 0)
+ sample_time = 0;
st = s->streams[stream_index];
sample = mov_seek_stream(st, sample_time, flags);