X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmov.c;h=611d547734f00e11915c38e4d9656939af224d88;hb=690bfceb204147d28d8a51b573b518d8e059462d;hp=9d3431689ceb485b6a6a991835dae9dad1c3d290;hpb=48a5529016261c05e5e1b3c2e70a07fb1023109d;p=ffmpeg diff --git a/libavformat/mov.c b/libavformat/mov.c index 9d3431689ce..611d547734f 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -27,6 +27,8 @@ #include "riff.h" #include "isom.h" #include "dv.h" +#include "mpeg4audio.h" +#include "mpegaudiodata.h" #ifdef CONFIG_ZLIB #include @@ -153,9 +155,8 @@ typedef struct MOVContext { /* those functions parse an atom */ /* return code: - 1: found what I wanted, exit 0: continue to parse next atom - <0: error occured, exit + <0: error occurred, exit */ /* links atom IDs to parse functions */ typedef struct MOVParseTableEntry { @@ -223,9 +224,8 @@ static int mov_read_default(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) total_size += a.size; } - if (!err && total_size < atom.size && atom.size < 0x7ffff) { + if (!err && total_size < atom.size && atom.size < 0x7ffff) url_fskip(pb, atom.size - total_size); - } return err; } @@ -317,13 +317,13 @@ static int mov_read_hdlr(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) *((char *)&type), ((char *)&type)[1], ((char *)&type)[2], ((char *)&type)[3]); if(!ctype) c->isom = 1; - if(type == MKTAG('v', 'i', 'd', 'e')) + if (type == MKTAG('v','i','d','e')) st->codec->codec_type = CODEC_TYPE_VIDEO; - else if(type == MKTAG('s', 'o', 'u', 'n')) + else if(type == MKTAG('s','o','u','n')) st->codec->codec_type = CODEC_TYPE_AUDIO; - else if(type == MKTAG('m', '1', 'a', ' ')) + else if(type == MKTAG('m','1','a',' ')) st->codec->codec_id = CODEC_ID_MP2; - else if(type == MKTAG('s', 'u', 'b', 'p')) { + else if(type == MKTAG('s','u','b','p')) { st->codec->codec_type = CODEC_TYPE_SUBTITLE; } get_be32(pb); /* component manufacture */ @@ -363,6 +363,14 @@ static int mp4_read_descr(MOVContext *c, ByteIOContext *pb, int *tag) #define MP4DecConfigDescrTag 0x04 #define MP4DecSpecificDescrTag 0x05 +static const AVCodecTag mp4_audio_types[] = { + { CODEC_ID_MP3ON4, 29 }, /* old mp3on4 draft */ + { CODEC_ID_MP3ON4, 32 }, /* layer 1 */ + { CODEC_ID_MP3ON4, 33 }, /* layer 2 */ + { CODEC_ID_MP3ON4, 34 }, /* layer 3 */ + { CODEC_ID_NONE, 0 }, +}; + static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) { AVStream *st = c->fc->streams[c->fc->nb_streams-1]; @@ -396,9 +404,24 @@ static int mov_read_esds(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) return AVERROR(ENOMEM); get_buffer(pb, st->codec->extradata, len); st->codec->extradata_size = len; - /* from mplayer */ - if ((*st->codec->extradata >> 3) == 29) { - st->codec->codec_id = CODEC_ID_MP3ON4; + if (st->codec->codec_id == CODEC_ID_AAC) { + MPEG4AudioConfig cfg; + ff_mpeg4audio_get_config(&cfg, st->codec->extradata, + st->codec->extradata_size); + if (!cfg.chan_config || cfg.chan_config > 7) + return -1; + st->codec->channels = ff_mpeg4audio_channels[cfg.chan_config]; + if (cfg.object_type == 29 && cfg.sampling_index < 3) // old mp3on4 + st->codec->sample_rate = ff_mpa_freq_tab[cfg.sampling_index]; + else + st->codec->sample_rate = cfg.sample_rate; // ext sample rate ? + dprintf(c->fc, "mp4a config channels %d obj %d ext obj %d " + "sample rate %d ext sample rate %d\n", st->codec->channels, + cfg.object_type, cfg.ext_object_type, + cfg.sample_rate, cfg.ext_sample_rate); + if (!(st->codec->codec_id = codec_get_id(mp4_audio_types, + cfg.object_type))) + st->codec->codec_id = CODEC_ID_AAC; } } } @@ -452,7 +475,7 @@ static int mov_read_mdhd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) int lang; if (version > 1) - return 1; /* unsupported */ + return -1; /* unsupported */ get_be24(pb); /* flags */ if (version == 1) { @@ -630,15 +653,13 @@ static int mov_read_stco(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) sc->chunk_offsets = av_malloc(entries * sizeof(int64_t)); if (!sc->chunk_offsets) return -1; - if (atom.type == MKTAG('s', 't', 'c', 'o')) { - for(i=0; ichunk_offsets[i] = get_be32(pb); - } - } else if (atom.type == MKTAG('c', 'o', '6', '4')) { - for(i=0; ichunk_offsets[i] = get_be64(pb); - } - } else + else return -1; return 0; @@ -648,21 +669,7 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) { AVStream *st = c->fc->streams[c->fc->nb_streams-1]; MOVStreamContext *sc = st->priv_data; - int entries, frames_per_sample; - uint32_t format; - uint8_t codec_name[32]; - - /* for palette traversal */ - unsigned int color_depth; - unsigned int color_start; - unsigned int color_count; - unsigned int color_end; - int color_index; - int color_dec; - int color_greyscale; - const uint8_t *color_table; - int j, pseudo_stream_id; - unsigned char r, g, b; + int j, entries, pseudo_stream_id; get_byte(pb); /* version */ get_be24(pb); /* flags */ @@ -676,7 +683,7 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) MOV_atom_t a = { 0, 0, 0 }; offset_t start_pos = url_ftell(pb); int size = get_be32(pb); /* size */ - format = get_le32(pb); /* data format */ + uint32_t format = get_le32(pb); /* data format */ get_be32(pb); /* reserved */ get_be16(pb); /* reserved */ @@ -684,7 +691,7 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) if (st->codec->codec_tag && (c->fc->video_codec_id ? codec_get_id(codec_movvideo_tags, format) != c->fc->video_codec_id - : st->codec->codec_tag != MKTAG('j', 'p', 'e', 'g')) + : st->codec->codec_tag != MKTAG('j','p','e','g')) ){ /* Multiple fourcc, we skip JPEG. This is not correct, we should * export it as a separate AVStream but this needs a few changes @@ -697,13 +704,13 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) st->codec->codec_tag = format; id = codec_get_id(codec_movaudio_tags, format); - if (id<=0 && (format&0xFFFF) == 'm' + ('s'<<8)) + if (id<=0 && (format&0xFFFF) == 'm'+('s'<<8)) id = codec_get_id(codec_wav_tags, bswap_32(format)&0xFFFF); if (st->codec->codec_type != CODEC_TYPE_VIDEO && id > 0) { st->codec->codec_type = CODEC_TYPE_AUDIO; } else if (st->codec->codec_type != CODEC_TYPE_AUDIO && /* do not overwrite codec type */ - format && format != MKTAG('m', 'p', '4', 's')) { /* skip old asf mpeg4 tag */ + format && format != MKTAG('m','p','4','s')) { /* skip old asf mpeg4 tag */ id = codec_get_id(codec_movvideo_tags, format); if (id <= 0) id = codec_get_id(codec_bmp_tags, format); @@ -721,6 +728,10 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) (format >> 24) & 0xff, st->codec->codec_type); if(st->codec->codec_type==CODEC_TYPE_VIDEO) { + uint8_t codec_name[32]; + unsigned int color_depth; + int color_greyscale; + st->codec->codec_id = id; get_be16(pb); /* version */ get_be16(pb); /* revision level */ @@ -734,11 +745,9 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) get_be32(pb); /* horiz resolution */ get_be32(pb); /* vert resolution */ get_be32(pb); /* data size, always 0 */ - frames_per_sample = get_be16(pb); /* frames per samples */ + get_be16(pb); /* frames per samples */ - dprintf(c->fc, "frames/samples = %d\n", frames_per_sample); - - get_buffer(pb, codec_name, 32); /* codec name, pascal string (FIXME: true for mp4?) */ + get_buffer(pb, codec_name, 32); /* codec name, pascal string */ if (codec_name[0] <= 31) { memcpy(st->codec->codec_name, &codec_name[1],codec_name[0]); st->codec->codec_name[codec_name[0]] = 0; @@ -755,7 +764,12 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) /* if the depth is 2, 4, or 8 bpp, file is palettized */ if ((color_depth == 2) || (color_depth == 4) || (color_depth == 8)) { + /* for palette traversal */ + unsigned int color_start, color_count, color_end; + unsigned char r, g, b; + if (color_greyscale) { + int color_index, color_dec; /* compute the greyscale palette */ st->codec->bits_per_sample = color_depth; color_count = 1 << color_depth; @@ -769,7 +783,8 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) if (color_index < 0) color_index = 0; } - } else if (st->codec->color_table_id & 0x08) { + } else if (st->codec->color_table_id) { + const uint8_t *color_table; /* if flag bit 3 is set, use the default palette */ color_count = 1 << color_depth; if (color_depth == 2) @@ -857,6 +872,10 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) sc->samples_per_frame = 64; sc->bytes_per_frame = 34*st->codec->channels; break; + case CODEC_ID_GSM: + sc->samples_per_frame = 160; + sc->bytes_per_frame = 33; + break; default: break; } @@ -923,7 +942,9 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) st->codec->sample_rate= 16000; st->codec->channels= 1; /* really needed */ break; + case CODEC_ID_QCELP: case CODEC_ID_AMR_NB: + st->codec->frame_size= sc->samples_per_frame; st->codec->sample_rate= 8000; st->codec->channels= 1; /* really needed */ break; @@ -932,10 +953,15 @@ static int mov_read_stsd(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) st->codec->codec_type = CODEC_TYPE_AUDIO; /* force type after stsd for m1a hdlr */ st->need_parsing = AVSTREAM_PARSE_FULL; break; + case CODEC_ID_GSM: case CODEC_ID_ADPCM_MS: case CODEC_ID_ADPCM_IMA_WAV: 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)); + break; default: break; } @@ -1120,8 +1146,9 @@ static void mov_build_index(MOVContext *mov, AVStream *st) unsigned int stss_index = 0; unsigned int i, j; - if (sc->sample_sizes || st->codec->codec_type == CODEC_TYPE_VIDEO || - sc->audio_cid == -2) { + /* only use old uncompressed audio chunk demuxing when stts specifies it */ + if (!(st->codec->codec_type == CODEC_TYPE_AUDIO && + sc->stts_count == 1 && sc->stts_data[0].duration == 1)) { unsigned int current_sample = 0; unsigned int stts_sample = 0; unsigned int keyframe, sample_size; @@ -1176,7 +1203,7 @@ static void mov_build_index(MOVContext *mov, AVStream *st) /* get chunk size, beware of alaw/ulaw/mace */ if (sc->samples_per_frame > 0 && (chunk_samples * sc->bytes_per_frame % sc->samples_per_frame == 0)) { - if (sc->samples_per_frame < 1024) + if (sc->samples_per_frame < 160) chunk_size = chunk_samples * sc->bytes_per_frame / sc->samples_per_frame; else { chunk_size = sc->bytes_per_frame; @@ -1234,9 +1261,10 @@ static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) return ret; /* sanity checks */ - if(!sc->stts_count || !sc->chunk_count || !sc->sample_to_chunk_sz || - (!sc->sample_size && !sc->sample_count)){ - av_log(c->fc, AV_LOG_ERROR, "missing mandatory atoms, broken header\n"); + if(sc->chunk_count && (!sc->stts_count || !sc->sample_to_chunk_sz || + (!sc->sample_size && !sc->sample_count))){ + av_log(c->fc, AV_LOG_ERROR, "stream %d, missing mandatory atoms, broken header\n", + st->index); sc->sample_count = 0; //ignore track return 0; } @@ -1246,7 +1274,8 @@ static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) sc->time_scale= c->time_scale; av_set_pts_info(st, 64, sc->time_rate, sc->time_scale); - if (st->codec->codec_type == CODEC_TYPE_AUDIO && sc->stts_count == 1) + if (st->codec->codec_type == CODEC_TYPE_AUDIO && + !st->codec->frame_size && sc->stts_count == 1) st->codec->frame_size = av_rescale(sc->time_rate, st->codec->sample_rate, sc->time_scale); if(st->duration != AV_NOPTS_VALUE){ @@ -1258,8 +1287,8 @@ static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) if (sc->dref_id-1 < sc->drefs_count && sc->drefs[sc->dref_id-1].path) { if (url_fopen(&sc->pb, sc->drefs[sc->dref_id-1].path, URL_RDONLY) < 0) - av_log(c->fc, AV_LOG_ERROR, "stream %d, error opening external essence: %s\n", - st->index, strerror(errno)); + av_log(c->fc, AV_LOG_ERROR, "stream %d, error opening file %s: %s\n", + st->index, sc->drefs[sc->dref_id-1].path, strerror(errno)); } else sc->pb = c->fc->pb; @@ -1276,13 +1305,9 @@ static int mov_read_trak(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) st->codec->width= 0; /* let decoder init width/height */ st->codec->height= 0; break; -#ifdef CONFIG_LIBFAAD - case CODEC_ID_AAC: -#endif #ifdef CONFIG_VORBIS_DECODER case CODEC_ID_VORBIS: #endif - case CODEC_ID_MP3ON4: st->codec->sample_rate= 0; /* let decoder init parameters properly */ break; } @@ -1440,18 +1465,20 @@ static int mov_read_trex(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) static int mov_read_trun(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) { MOVFragment *frag = &c->fragment; - AVStream *st = c->fc->streams[frag->track_id-1]; - MOVStreamContext *sc = st->priv_data; + AVStream *st; + MOVStreamContext *sc; uint64_t offset; int64_t dts; int data_offset = 0; unsigned entries, first_sample_flags = frag->flags; int flags, distance, i; + if (!frag->track_id || frag->track_id > c->fc->nb_streams) + return -1; + st = c->fc->streams[frag->track_id-1]; + sc = st->priv_data; if (sc->pseudo_stream_id+1 != frag->stsd_id) return 0; - if (!st->nb_index_entries) - return -1; get_byte(pb); /* version */ flags = get_be24(pb); entries = get_be32(pb); @@ -1519,7 +1546,7 @@ static int mov_read_wide(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) atom.type = get_le32(pb); atom.offset += 8; atom.size -= 8; - if (atom.type != MKTAG('m', 'd', 'a', 't')) { + if (atom.type != MKTAG('m','d','a','t')) { url_fskip(pb, atom.size); return 0; } @@ -1537,14 +1564,14 @@ static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) int ret; get_be32(pb); /* dcom atom */ - if (get_le32(pb) != MKTAG( 'd', 'c', 'o', 'm' )) + if (get_le32(pb) != MKTAG('d','c','o','m')) return -1; - if (get_le32(pb) != MKTAG( 'z', 'l', 'i', 'b' )) { + if (get_le32(pb) != MKTAG('z','l','i','b')) { av_log(NULL, AV_LOG_ERROR, "unknown compression for cmov atom !"); return -1; } get_be32(pb); /* cmvd atom */ - if (get_le32(pb) != MKTAG( 'c', 'm', 'v', 'd' )) + if (get_le32(pb) != MKTAG('c','m','v','d')) return -1; moov_len = get_be32(pb); /* uncompressed size */ cmov_len = atom.size - 6 * 4; @@ -1562,7 +1589,7 @@ static int mov_read_cmov(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) return -1; if(init_put_byte(&ctx, moov_data, moov_len, 0, NULL, NULL, NULL, NULL) != 0) return -1; - atom.type = MKTAG( 'm', 'o', 'o', 'v' ); + atom.type = MKTAG('m','o','o','v'); atom.offset = 0; atom.size = moov_len; #ifdef DEBUG @@ -1602,47 +1629,47 @@ static int mov_read_elst(MOVContext *c, ByteIOContext *pb, MOV_atom_t atom) } static const MOVParseTableEntry mov_default_parse_table[] = { -{ MKTAG( 'c', 'o', '6', '4' ), mov_read_stco }, -{ MKTAG( 'c', 't', 't', 's' ), mov_read_ctts }, /* composition time to sample */ -{ MKTAG( 'd', 'i', 'n', 'f' ), mov_read_default }, -{ MKTAG( 'd', 'r', 'e', 'f' ), mov_read_dref }, -{ MKTAG( 'e', 'd', 't', 's' ), mov_read_default }, -{ MKTAG( 'e', 'l', 's', 't' ), mov_read_elst }, -{ MKTAG( 'e', 'n', 'd', 'a' ), mov_read_enda }, -{ MKTAG( 'f', 'i', 'e', 'l' ), mov_read_extradata }, -{ 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( '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', 'i', 'n', 'f' ), mov_read_default }, -{ MKTAG( 'm', 'o', 'o', 'f' ), mov_read_moof }, -{ MKTAG( 'm', 'o', 'o', 'v' ), mov_read_moov }, -{ MKTAG( 'm', 'v', 'e', 'x' ), mov_read_default }, -{ MKTAG( 'm', 'v', 'h', 'd' ), mov_read_mvhd }, -{ 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( 's', 't', 'b', 'l' ), mov_read_default }, -{ MKTAG( 's', 't', 'c', 'o' ), mov_read_stco }, -{ MKTAG( 's', 't', 's', 'c' ), mov_read_stsc }, -{ MKTAG( 's', 't', 's', 'd' ), mov_read_stsd }, /* sample description */ -{ 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 */ -{ MKTAG( 't', 'f', 'h', 'd' ), mov_read_tfhd }, /* track fragment header */ -{ 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', 'u', 'n' ), mov_read_trun }, -{ MKTAG( 'u', 'd', 't', 'a' ), mov_read_udta }, -{ 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('c','o','6','4'), mov_read_stco }, +{ MKTAG('c','t','t','s'), mov_read_ctts }, /* composition time to sample */ +{ MKTAG('d','i','n','f'), mov_read_default }, +{ MKTAG('d','r','e','f'), mov_read_dref }, +{ MKTAG('e','d','t','s'), mov_read_default }, +{ MKTAG('e','l','s','t'), mov_read_elst }, +{ MKTAG('e','n','d','a'), mov_read_enda }, +{ MKTAG('f','i','e','l'), mov_read_extradata }, +{ 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('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','i','n','f'), mov_read_default }, +{ MKTAG('m','o','o','f'), mov_read_moof }, +{ MKTAG('m','o','o','v'), mov_read_moov }, +{ MKTAG('m','v','e','x'), mov_read_default }, +{ MKTAG('m','v','h','d'), mov_read_mvhd }, +{ 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('s','t','b','l'), mov_read_default }, +{ MKTAG('s','t','c','o'), mov_read_stco }, +{ MKTAG('s','t','s','c'), mov_read_stsc }, +{ MKTAG('s','t','s','d'), mov_read_stsd }, /* sample description */ +{ 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 */ +{ MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */ +{ 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','u','n'), mov_read_trun }, +{ MKTAG('u','d','t','a'), mov_read_udta }, +{ 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 }, { 0, NULL } }; @@ -1661,23 +1688,24 @@ static int mov_probe(AVProbeData *p) tag = AV_RL32(p->buf + offset + 4); switch(tag) { /* check for obvious tags */ - case MKTAG( 'j', 'P', ' ', ' ' ): /* jpeg 2000 signature */ - case MKTAG( 'm', 'o', 'o', 'v' ): - case MKTAG( 'm', 'd', 'a', 't' ): - case MKTAG( 'p', 'n', 'o', 't' ): /* detect movs with preview pics like ew.mov and april.mov */ - case MKTAG( 'u', 'd', 't', 'a' ): /* Packet Video PVAuthor adds this and a lot of more junk */ + case MKTAG('j','P',' ',' '): /* jpeg 2000 signature */ + case MKTAG('m','o','o','v'): + case MKTAG('m','d','a','t'): + case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */ + case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */ return AVPROBE_SCORE_MAX; /* those are more common words, so rate then a bit less */ - case MKTAG( 'e', 'd', 'i', 'w' ): /* xdcam files have reverted first tags */ - case MKTAG( 'w', 'i', 'd', 'e' ): - case MKTAG( 'f', 'r', 'e', 'e' ): - case MKTAG( 'j', 'u', 'n', 'k' ): - case MKTAG( 'p', 'i', 'c', 't' ): + case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */ + case MKTAG('w','i','d','e'): + case MKTAG('f','r','e','e'): + case MKTAG('j','u','n','k'): + case MKTAG('p','i','c','t'): return AVPROBE_SCORE_MAX - 5; case MKTAG(0x82,0x82,0x7f,0x7d ): - case MKTAG( 'f', 't', 'y', 'p' ): - case MKTAG( 's', 'k', 'i', 'p' ): - case MKTAG( 'u', 'u', 'i', 'd' ): + case MKTAG('f','t','y','p'): + case MKTAG('s','k','i','p'): + case MKTAG('u','u','i','d'): + case MKTAG('p','r','f','l'): offset = AV_RB32(p->buf+offset) + offset; /* if we only find those cause probedata is too small at least rate them */ score = AVPROBE_SCORE_MAX - 50; @@ -1705,13 +1733,15 @@ static int mov_read_header(AVFormatContext *s, AVFormatParameters *ap) atom.size = INT64_MAX; /* check MOV header */ - err = mov_read_default(mov, pb, atom); - if (err<0 || (!mov->found_moov && !mov->found_mdat)) { - av_log(s, AV_LOG_ERROR, "mov: header not found !!! (err:%d, moov:%d, mdat:%d) pos:%"PRId64"\n", - err, mov->found_moov, mov->found_mdat, url_ftell(pb)); + if ((err = mov_read_default(mov, pb, atom)) < 0) { + av_log(s, AV_LOG_ERROR, "error reading header: %d\n", err); + return err; + } + if (!mov->found_moov) { + av_log(s, AV_LOG_ERROR, "moov atom not found\n"); return -1; } - dprintf(mov->fc, "on_parse_exit_offset=%d\n", (int) url_ftell(pb)); + dprintf(mov->fc, "on_parse_exit_offset=%lld\n", url_ftell(pb)); return 0; } @@ -1782,6 +1812,10 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) sc->sample_to_ctime_sample = 0; } } else { + AVStream *st = s->streams[sc->ffindex]; + int64_t next_dts = (sc->current_sample < sc->sample_count) ? + st->index_entries[sc->current_sample].timestamp : st->duration; + pkt->duration = next_dts - pkt->dts; pkt->pts = pkt->dts; } pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? PKT_FLAG_KEY : 0;