X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavformat%2Fmov.c;h=7553a7fdfc2152583e8c63ff69a01f4ee7b3d110;hb=a87b5d5e8c9424b5cadd46abba98dae8edd454df;hp=a7d444b0eeea128e18312a4c6415380a24c396de;hpb=c2631dfd0a0a12050cc1765fd41702c5e93abee5;p=ffmpeg diff --git a/libavformat/mov.c b/libavformat/mov.c index a7d444b0eee..7553a7fdfc2 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -49,6 +49,7 @@ #include "libavcodec/ac3tab.h" #include "libavcodec/flac.h" #include "libavcodec/mpegaudiodecheader.h" +#include "libavcodec/mlp_parse.h" #include "avformat.h" #include "internal.h" #include "avio_internal.h" @@ -1393,14 +1394,14 @@ static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom) return mov_read_default(c, pb, atom); } -static void mov_metadata_creation_time(AVDictionary **metadata, int64_t time) +static void mov_metadata_creation_time(AVDictionary **metadata, int64_t time, void *logctx) { if (time) { if(time >= 2082844800) time -= 2082844800; /* seconds between 1904-01-01 and Epoch */ if ((int64_t)(time * 1000000ULL) / 1000000 != time) { - av_log(NULL, AV_LOG_DEBUG, "creation_time is not representable\n"); + av_log(logctx, AV_LOG_DEBUG, "creation_time is not representable\n"); return; } @@ -1440,7 +1441,7 @@ static int mov_read_mdhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) creation_time = avio_rb32(pb); avio_rb32(pb); /* modification time */ } - mov_metadata_creation_time(&st->metadata, creation_time); + mov_metadata_creation_time(&st->metadata, creation_time, c->fc); sc->time_scale = avio_rb32(pb); if (sc->time_scale <= 0) { @@ -1471,7 +1472,7 @@ static int mov_read_mvhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) creation_time = avio_rb32(pb); avio_rb32(pb); /* modification time */ } - mov_metadata_creation_time(&c->fc->metadata, creation_time); + mov_metadata_creation_time(&c->fc->metadata, creation_time, c->fc); c->time_scale = avio_rb32(pb); /* time scale */ if (c->time_scale <= 0) { av_log(c->fc, AV_LOG_ERROR, "Invalid mvhd time scale %d, defaulting to 1\n", c->time_scale); @@ -1620,7 +1621,7 @@ static int mov_read_fiel(MOVContext *c, AVIOContext *pb, MOVAtom atom) } } if (decoded_field_order == AV_FIELD_UNKNOWN && mov_field_order) { - av_log(NULL, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order); + av_log(c->fc, AV_LOG_ERROR, "Unknown MOV field order 0x%04x\n", mov_field_order); } st->codecpar->field_order = decoded_field_order; @@ -1797,19 +1798,19 @@ static int mov_read_aclr(MOVContext *c, AVIOContext *pb, MOVAtom atom) par->color_range = AVCOL_RANGE_JPEG; break; default: - av_log(c, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value); + av_log(c->fc, AV_LOG_WARNING, "ignored unknown aclr value (%d)\n", range_value); break; } - ff_dlog(c, "color_range: %d\n", par->color_range); + ff_dlog(c->fc, "color_range: %d\n", par->color_range); } else { /* For some reason the whole atom was not added to the extradata */ - av_log(c, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n"); + av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - incomplete atom\n"); } } else { - av_log(c, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n"); + av_log(c->fc, AV_LOG_ERROR, "aclr not decoded - unable to add atom to extradata\n"); } } else { - av_log(c, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size); + av_log(c->fc, AV_LOG_WARNING, "aclr not decoded - unexpected size %"PRId64"\n", atom.size); } } @@ -1901,7 +1902,7 @@ static int mov_read_glbl(MOVContext *c, AVIOContext *pb, MOVAtom atom) return mov_read_default(c, pb, atom); } if (st->codecpar->extradata_size > 1 && st->codecpar->extradata) { - av_log(c, AV_LOG_WARNING, "ignoring multiple glbl\n"); + av_log(c->fc, AV_LOG_WARNING, "ignoring multiple glbl\n"); return 0; } av_freep(&st->codecpar->extradata); @@ -2303,8 +2304,8 @@ static int mov_parse_stsd_data(MOVContext *c, AVIOContext *pb, int val; val = AV_RB32(st->codecpar->extradata + 4); tmcd_ctx->tmcd_flags = val; - st->avg_frame_rate.num = st->codecpar->extradata[16]; /* number of frame */ - st->avg_frame_rate.den = 1; + st->avg_frame_rate.num = AV_RB32(st->codecpar->extradata + 8); /* timescale */ + st->avg_frame_rate.den = AV_RB32(st->codecpar->extradata + 12); /* frameDuration */ #if FF_API_LAVF_AVCTX FF_DISABLE_DEPRECATION_WARNINGS st->codec->time_base = av_inv_q(st->avg_frame_rate); @@ -2940,7 +2941,7 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (duration > 0 && duration <= INT64_MAX - sc->duration_for_fps && - total_sample_count <= INT64_MAX - sc->nb_frames_for_fps + total_sample_count <= INT_MAX - sc->nb_frames_for_fps ) { sc->duration_for_fps += duration; sc->nb_frames_for_fps += total_sample_count; @@ -2958,11 +2959,45 @@ static int mov_read_stts(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } -static void mov_update_dts_shift(MOVStreamContext *sc, int duration) +static int mov_read_sdtp(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + AVStream *st; + MOVStreamContext *sc; + int64_t i, entries; + + if (c->fc->nb_streams < 1) + return 0; + st = c->fc->streams[c->fc->nb_streams - 1]; + sc = st->priv_data; + + avio_r8(pb); /* version */ + avio_rb24(pb); /* flags */ + entries = atom.size - 4; + + av_log(c->fc, AV_LOG_TRACE, "track[%u].sdtp.entries = %" PRId64 "\n", + c->fc->nb_streams - 1, entries); + + if (sc->sdtp_data) + av_log(c->fc, AV_LOG_WARNING, "Duplicated SDTP atom\n"); + av_freep(&sc->sdtp_data); + sc->sdtp_count = 0; + + sc->sdtp_data = av_mallocz(entries); + if (!sc->sdtp_data) + return AVERROR(ENOMEM); + + for (i = 0; i < entries && !pb->eof_reached; i++) + sc->sdtp_data[i] = avio_r8(pb); + sc->sdtp_count = i; + + return 0; +} + +static void mov_update_dts_shift(MOVStreamContext *sc, int duration, void *logctx) { if (duration < 0) { if (duration == INT_MIN) { - av_log(NULL, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX); + av_log(logctx, AV_LOG_WARNING, "mov_update_dts_shift(): dts_shift set to %d\n", INT_MAX); duration++; } sc->dts_shift = FFMAX(sc->dts_shift, -duration); @@ -3020,7 +3055,7 @@ static int mov_read_ctts(MOVContext *c, AVIOContext *pb, MOVAtom atom) } if (i+2fc); } sc->ctts_count = ctts_count; @@ -4418,7 +4453,10 @@ static int mov_read_custom(MOVContext *c, AVIOContext *pb, MOVAtom atom) static int mov_read_meta(MOVContext *c, AVIOContext *pb, MOVAtom atom) { while (atom.size > 8) { - uint32_t tag = avio_rl32(pb); + uint32_t tag; + if (avio_feof(pb)) + return AVERROR_EOF; + tag = avio_rl32(pb); atom.size -= 4; if (tag == MKTAG('h','d','l','r')) { avio_seek(pb, -8, SEEK_CUR); @@ -4562,8 +4600,6 @@ static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) MOVTrackExt *trex = NULL; int flags, track_id, i; - c->fragment.found_tfhd = 1; - avio_r8(pb); /* version */ flags = avio_rb24(pb); @@ -4579,6 +4615,7 @@ static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_log(c->fc, AV_LOG_WARNING, "could not find corresponding trex (id %u)\n", track_id); return 0; } + c->fragment.found_tfhd = 1; frag->track_id = track_id; set_frag_stream(&c->frag_index, track_id); @@ -4778,12 +4815,12 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags); // realloc space for new index entries - if((unsigned)st->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) { + if((uint64_t)st->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) { entries = UINT_MAX / sizeof(AVIndexEntry) - st->nb_index_entries; av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n"); } - if (entries <= 0) - return -1; + if (entries == 0) + return 0; requested_size = (st->nb_index_entries + entries) * sizeof(AVIndexEntry); new_entries = av_fast_realloc(st->index_entries, @@ -4844,7 +4881,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) if (flags & MOV_TRUN_SAMPLE_FLAGS) sample_flags = avio_rb32(pb); if (flags & MOV_TRUN_SAMPLE_CTS) ctts_duration = avio_rb32(pb); - mov_update_dts_shift(sc, ctts_duration); + mov_update_dts_shift(sc, ctts_duration, c->fc); if (pts != AV_NOPTS_VALUE) { dts = pts - sc->dts_shift; if (flags & MOV_TRUN_SAMPLE_CTS) { @@ -4897,7 +4934,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) sc->data_size += sample_size; if (sample_duration <= INT64_MAX - sc->duration_for_fps && - 1 <= INT64_MAX - sc->nb_frames_for_fps + 1 <= INT_MAX - sc->nb_frames_for_fps ) { sc->duration_for_fps += sample_duration; sc->nb_frames_for_fps ++; @@ -5017,7 +5054,7 @@ static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom) return AVERROR_PATCHWELCOME; } avio_rb32(pb); // sap_flags - timestamp = av_rescale_q(pts, st->time_base, timescale); + timestamp = av_rescale_q(pts, timescale, st->time_base); index = update_frag_index(c, offset); frag_stream_info = get_frag_stream_info(&c->frag_index, index, track_id); @@ -6684,6 +6721,38 @@ static int mov_read_dops(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } +static int mov_read_dmlp(MOVContext *c, AVIOContext *pb, MOVAtom atom) +{ + AVStream *st; + unsigned format_info; + int channel_assignment, channel_assignment1, channel_assignment2; + int ratebits; + + if (c->fc->nb_streams < 1) + return 0; + st = c->fc->streams[c->fc->nb_streams-1]; + + if (atom.size < 10) + return AVERROR_INVALIDDATA; + + format_info = avio_rb32(pb); + + ratebits = (format_info >> 28) & 0xF; + channel_assignment1 = (format_info >> 15) & 0x1F; + channel_assignment2 = format_info & 0x1FFF; + if (channel_assignment2) + channel_assignment = channel_assignment2; + else + channel_assignment = channel_assignment1; + + st->codecpar->frame_size = 40 << (ratebits & 0x7); + st->codecpar->sample_rate = mlp_samplerate(ratebits); + st->codecpar->channels = truehd_channels(channel_assignment); + st->codecpar->channel_layout = truehd_layout(channel_assignment); + + return 0; +} + static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('A','C','L','R'), mov_read_aclr }, { MKTAG('A','P','R','G'), mov_read_avid }, @@ -6732,6 +6801,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('s','t','s','z'), mov_read_stsz }, /* sample size */ { MKTAG('s','t','t','s'), mov_read_stts }, { MKTAG('s','t','z','2'), mov_read_stsz }, /* compact sample size */ +{ MKTAG('s','d','t','p'), mov_read_sdtp }, /* independent and disposable samples */ { MKTAG('t','k','h','d'), mov_read_tkhd }, /* track header */ { MKTAG('t','f','d','t'), mov_read_tfdt }, { MKTAG('t','f','h','d'), mov_read_tfhd }, /* track fragment header */ @@ -6772,6 +6842,7 @@ static const MOVParseTableEntry mov_default_parse_table[] = { { MKTAG('s','t','3','d'), mov_read_st3d }, /* stereoscopic 3D video box */ { MKTAG('s','v','3','d'), mov_read_sv3d }, /* spherical video box */ { MKTAG('d','O','p','s'), mov_read_dops }, +{ MKTAG('d','m','l','p'), mov_read_dmlp }, { MKTAG('S','m','D','m'), mov_read_smdm }, { MKTAG('C','o','L','L'), mov_read_coll }, { MKTAG('v','p','c','C'), mov_read_vpcc }, @@ -6901,7 +6972,7 @@ static int mov_read_default(MOVContext *c, AVIOContext *pb, MOVAtom atom) return 0; } -static int mov_probe(AVProbeData *p) +static int mov_probe(const AVProbeData *p) { int64_t offset; uint32_t tag; @@ -7195,6 +7266,7 @@ static int mov_read_close(AVFormatContext *s) av_freep(&sc->sample_sizes); av_freep(&sc->keyframes); av_freep(&sc->stts_data); + av_freep(&sc->sdtp_data); av_freep(&sc->stps_data); av_freep(&sc->elst_data); av_freep(&sc->rap_group); @@ -7784,6 +7856,11 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) } if (st->discard == AVDISCARD_ALL) goto retry; + if (sc->sdtp_data && sc->current_sample <= sc->sdtp_count) { + uint8_t sample_flags = sc->sdtp_data[sc->current_sample - 1]; + uint8_t sample_is_depended_on = (sample_flags >> 2) & 0x3; + pkt->flags |= sample_is_depended_on == MOV_SAMPLE_DEPENDENCY_NO ? AV_PKT_FLAG_DISPOSABLE : 0; + } pkt->flags |= sample->flags & AVINDEX_KEYFRAME ? AV_PKT_FLAG_KEY : 0; pkt->pos = sample->pos; @@ -7810,8 +7887,10 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) aax_filter(pkt->data, pkt->size, mov); ret = cenc_filter(mov, st, sc, pkt, current_index); - if (ret < 0) + if (ret < 0) { + av_packet_unref(pkt); return ret; + } return 0; } @@ -7872,6 +7951,7 @@ static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, } /* adjust stsd index */ + if (sc->chunk_count) { time_sample = 0; for (i = 0; i < sc->stsc_count; i++) { int64_t next = time_sample + mov_get_stsc_samples(sc, i); @@ -7883,6 +7963,7 @@ static int mov_seek_stream(AVFormatContext *s, AVStream *st, int64_t timestamp, av_assert0(next == (int)next); time_sample = next; } + } return sample; } @@ -7947,7 +8028,7 @@ static const AVOption mov_options[] = { OFFSET(use_absolute_path), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, FLAGS}, {"seek_streams_individually", - "Seek each stream individually to the to the closest point", + "Seek each stream individually to the closest point", OFFSET(seek_individually), AV_OPT_TYPE_BOOL, { .i64 = 1 }, 0, 1, FLAGS}, {"ignore_editlist", "Ignore the edit list atom.", OFFSET(ignore_editlist), AV_OPT_TYPE_BOOL, {.i64 = 0}, @@ -8004,5 +8085,5 @@ AVInputFormat ff_mov_demuxer = { .read_packet = mov_read_packet, .read_close = mov_read_close, .read_seek = mov_read_seek, - .flags = AVFMT_NO_BYTE_SEEK, + .flags = AVFMT_NO_BYTE_SEEK | AVFMT_SEEK_TO_PTS, };