#include "libavutil/spherical.h"
#include "libavutil/stereo3d.h"
#include "libavutil/timecode.h"
+#include "libavutil/dovi_meta.h"
#include "libavcodec/ac3tab.h"
#include "libavcodec/flac.h"
#include "libavcodec/mpegaudiodecheader.h"
frag_stream_info[i].id = c->fc->streams[i]->id;
frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE;
frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE;
+ frag_stream_info[i].next_trun_dts = AV_NOPTS_VALUE;
frag_stream_info[i].first_tfra_pts = AV_NOPTS_VALUE;
frag_stream_info[i].index_entry = -1;
frag_stream_info[i].encryption_index = NULL;
for (i = 0; i < entries && !pb->eof_reached; i++) {
sc->sample_sizes[i] = get_bits_long(&gb, field_size);
+ if (sc->sample_sizes[i] < 0) {
+ av_free(buf);
+ av_log(c->fc, AV_LOG_ERROR, "Invalid sample size %d\n", sc->sample_sizes[i]);
+ return AVERROR_INVALIDDATA;
+ }
sc->data_size += sc->sample_sizes[i];
}
MOVFragment *frag = &c->fragment;
MOVTrackExt *trex = NULL;
int flags, track_id, i;
+ MOVFragmentStreamInfo * frag_stream_info;
avio_r8(pb); /* version */
flags = avio_rb24(pb);
avio_rb32(pb) : trex->flags;
av_log(c->fc, AV_LOG_TRACE, "frag flags 0x%x\n", frag->flags);
+ frag_stream_info = get_current_frag_stream_info(&c->frag_index);
+ if (frag_stream_info)
+ frag_stream_info->next_trun_dts = AV_NOPTS_VALUE;
+
return 0;
}
frag_stream_info = get_current_frag_stream_info(&c->frag_index);
if (frag_stream_info)
{
- if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
+ if (frag_stream_info->next_trun_dts != AV_NOPTS_VALUE) {
+ dts = frag_stream_info->next_trun_dts - sc->time_offset;
+ } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
c->use_mfra_for == FF_MOV_FLAG_MFRA_PTS) {
pts = frag_stream_info->first_tfra_pts;
av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
", using it for pts\n", pts);
+ } else if (frag_stream_info->first_tfra_pts != AV_NOPTS_VALUE &&
+ c->use_mfra_for == FF_MOV_FLAG_MFRA_DTS) {
+ dts = frag_stream_info->first_tfra_pts;
+ av_log(c->fc, AV_LOG_DEBUG, "found mfra time %"PRId64
+ ", using it for dts\n", pts);
} else if (frag_stream_info->sidx_pts != AV_NOPTS_VALUE) {
// FIXME: sidx earliest_presentation_time is *PTS*, s.b.
// pts = frag_stream_info->sidx_pts;
sc->nb_frames_for_fps ++;
}
}
+ if (frag_stream_info)
+ frag_stream_info->next_trun_dts = dts + sc->time_offset;
if (i < entries) {
// EOF found before reading all entries. Fix the hole this would
// leave in index_entries and ctts_data
return 0;
}
+static int mov_read_dvcc_dvvc(MOVContext *c, AVIOContext *pb, MOVAtom atom)
+{
+ AVStream *st;
+ uint32_t buf;
+ AVDOVIDecoderConfigurationRecord *dovi;
+ size_t dovi_size;
+ int ret;
+
+ if (c->fc->nb_streams < 1)
+ return 0;
+ st = c->fc->streams[c->fc->nb_streams-1];
+
+ if ((uint64_t)atom.size > (1<<30) || atom.size < 4)
+ return AVERROR_INVALIDDATA;
+
+ dovi = av_dovi_alloc(&dovi_size);
+ if (!dovi)
+ return AVERROR(ENOMEM);
+
+ dovi->dv_version_major = avio_r8(pb);
+ dovi->dv_version_minor = avio_r8(pb);
+
+ buf = avio_rb16(pb);
+ dovi->dv_profile = (buf >> 9) & 0x7f; // 7 bits
+ dovi->dv_level = (buf >> 3) & 0x3f; // 6 bits
+ dovi->rpu_present_flag = (buf >> 2) & 0x01; // 1 bit
+ dovi->el_present_flag = (buf >> 1) & 0x01; // 1 bit
+ dovi->bl_present_flag = buf & 0x01; // 1 bit
+ if (atom.size >= 24) { // 4 + 4 + 4 * 4
+ buf = avio_r8(pb);
+ dovi->dv_bl_signal_compatibility_id = (buf >> 4) & 0x0f; // 4 bits
+ } else {
+ // 0 stands for None
+ // Dolby Vision V1.2.93 profiles and levels
+ dovi->dv_bl_signal_compatibility_id = 0;
+ }
+
+ ret = av_stream_add_side_data(st, AV_PKT_DATA_DOVI_CONF,
+ (uint8_t *)dovi, dovi_size);
+ if (ret < 0) {
+ av_free(dovi);
+ return ret;
+ }
+
+ av_log(c, AV_LOG_TRACE, "DOVI in dvcC/dvvC box, version: %d.%d, profile: %d, level: %d, "
+ "rpu flag: %d, el flag: %d, bl flag: %d, compatibility id: %d\n",
+ dovi->dv_version_major, dovi->dv_version_minor,
+ dovi->dv_profile, dovi->dv_level,
+ dovi->rpu_present_flag,
+ dovi->el_present_flag,
+ dovi->bl_present_flag,
+ dovi->dv_bl_signal_compatibility_id
+ );
+
+ 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 },
{ MKTAG('v','p','c','C'), mov_read_vpcc },
{ MKTAG('m','d','c','v'), mov_read_mdcv },
{ MKTAG('c','l','l','i'), mov_read_clli },
+{ MKTAG('d','v','c','C'), mov_read_dvcc_dvvc },
+{ MKTAG('d','v','v','C'), mov_read_dvcc_dvvc },
{ 0, NULL }
};
if (atom.size >= 8) {
a.size = avio_rb32(pb);
a.type = avio_rl32(pb);
- if (a.type == MKTAG('f','r','e','e') &&
+ if (((a.type == MKTAG('f','r','e','e') && c->moov_retry) ||
+ a.type == MKTAG('h','o','o','v')) &&
a.size >= 8 &&
- c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT &&
- c->moov_retry) {
+ c->fc->strict_std_compliance < FF_COMPLIANCE_STRICT) {
uint8_t buf[8];
uint32_t *type = (uint32_t *)buf + 1;
if (avio_read(pb, buf, 8) != 8)
avio_seek(pb, -8, SEEK_CUR);
if (*type == MKTAG('m','v','h','d') ||
*type == MKTAG('c','m','o','v')) {
- av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free atom.\n");
+ av_log(c->fc, AV_LOG_ERROR, "Detected moov in a free or hoov atom.\n");
a.type = MKTAG('m','o','o','v');
}
}
// https://developer.apple.com/library/mac/documentation/QuickTime/QTFF/Metadata/Metadata.html
if (!parse && c->found_hdlr_mdta &&
atom.type == MKTAG('m','e','t','a') &&
- a.type == MKTAG('k','e','y','s')) {
+ a.type == MKTAG('k','e','y','s') &&
+ c->meta_keys_count == 0) {
parse = mov_read_keys;
}
mov->next_root_atom = 0;
if (index < 0 || index >= mov->frag_index.nb_items)
index = search_frag_moof_offset(&mov->frag_index, target);
- if (index < mov->frag_index.nb_items) {
+ if (index < mov->frag_index.nb_items &&
+ mov->frag_index.item[index].moof_offset == target) {
if (index + 1 < mov->frag_index.nb_items)
mov->next_root_atom = mov->frag_index.item[index + 1].moof_offset;
if (mov->frag_index.item[index].headers_read)