int flags = MOV_TKHD_FLAG_IN_MOVIE;
int group = 0;
+ uint32_t *display_matrix = NULL;
+ int display_matrix_size, i;
if (st) {
if (mov->per_stream_grouping)
group = st->index;
else
group = st->codec->codec_type;
+
+ display_matrix = (uint32_t*)av_stream_get_side_data(st, AV_PKT_DATA_DISPLAYMATRIX,
+ &display_matrix_size);
+ if (display_matrix_size < 9 * sizeof(*display_matrix))
+ display_matrix = NULL;
}
if (track->flags & MOV_TRACK_ENABLED)
avio_wb16(pb, 0); /* reserved */
/* Matrix structure */
- avio_wb32(pb, 0x00010000); /* reserved */
- avio_wb32(pb, 0x0); /* reserved */
- avio_wb32(pb, 0x0); /* reserved */
- avio_wb32(pb, 0x0); /* reserved */
- avio_wb32(pb, 0x00010000); /* reserved */
- avio_wb32(pb, 0x0); /* reserved */
- avio_wb32(pb, 0x0); /* reserved */
- avio_wb32(pb, 0x0); /* reserved */
- avio_wb32(pb, 0x40000000); /* reserved */
+ if (display_matrix) {
+ for (i = 0; i < 9; i++)
+ avio_wb32(pb, display_matrix[i]);
+ } else {
+ avio_wb32(pb, 0x00010000); /* reserved */
+ avio_wb32(pb, 0x0); /* reserved */
+ avio_wb32(pb, 0x0); /* reserved */
+ avio_wb32(pb, 0x0); /* reserved */
+ avio_wb32(pb, 0x00010000); /* reserved */
+ avio_wb32(pb, 0x0); /* reserved */
+ avio_wb32(pb, 0x0); /* reserved */
+ avio_wb32(pb, 0x0); /* reserved */
+ avio_wb32(pb, 0x40000000); /* reserved */
+ }
/* Track width and height, for visual only */
if (st && (track->enc->codec_type == AVMEDIA_TYPE_VIDEO ||
mov_write_string_metadata(s, pb_buf, "\251des", "comment", 0);
mov_write_string_metadata(s, pb_buf, "\251gen", "genre", 0);
mov_write_string_metadata(s, pb_buf, "\251cpy", "copyright", 0);
+ mov_write_string_metadata(s, pb_buf, "\251mak", "make", 0);
+ mov_write_string_metadata(s, pb_buf, "\251mod", "model", 0);
} else {
/* iTunes meta data */
mov_write_meta_tag(pb_buf, mov, s);
avio_wb24(pb, 0);
avio_wb64(pb, track->start_dts + track->frag_start +
track->cluster[0].cts);
- avio_wb64(pb, track->start_dts + track->track_duration -
- track->cluster[0].dts);
+ avio_wb64(pb, track->end_pts -
+ (track->cluster[0].dts + track->cluster[0].cts));
return update_size(pb, pos);
}
// from the fields we have stored
info->time = track->start_dts + track->frag_start +
track->cluster[0].cts;
+ info->duration = track->end_pts -
+ (track->cluster[0].dts + track->cluster[0].cts);
// If the pts is less than zero, we will have trimmed
// away parts of the media track using an edit list,
// and the corresponding start presentation time is zero.
- if (info->time < 0)
+ if (info->time < 0) {
+ info->duration += info->time;
info->time = 0;
- info->duration = track->start_dts + track->track_duration -
- track->cluster[0].dts;
+ }
info->tfrf_offset = 0;
mov_write_tfrf_tags(pb, mov, track);
}
entries = 1;
presentation_time = track->start_dts + track->frag_start +
track->cluster[0].cts;
- duration = track->start_dts + track->track_duration -
- track->cluster[0].dts;
+ duration = track->end_pts -
+ (track->cluster[0].dts + track->cluster[0].cts);
starts_with_SAP = track->cluster[0].flags & MOV_SYNC_SAMPLE;
// pts<0 should be cut away using edts
- if (presentation_time < 0)
+ if (presentation_time < 0) {
+ duration += presentation_time;
presentation_time = 0;
+ }
} else {
entries = track->nb_frag_info;
presentation_time = track->frag_info[0].time;
// to be too long), but probably the best we can do - having a zero
// duration is bad as well.
track->track_duration += get_cluster_duration(track, track->entry - 2);
+ track->end_pts += get_cluster_duration(track, track->entry - 2);
if (!mov->missing_duration_warned) {
av_log(s, AV_LOG_WARNING,
"Estimating the duration of the last packet in a "
* be the same in all fragments. */
if ((mov->flags & FF_MOV_FLAG_DASH && !(mov->flags & FF_MOV_FLAG_FASTSTART)) ||
mov->mode == MODE_ISM)
- pkt->pts = pkt->dts + trk->start_cts;
+ pkt->pts = pkt->dts + trk->end_pts - trk->cluster[trk->entry].dts;
} else {
/* New fragment, but discontinuous from previous fragments.
* Pretend the duration sum of the earlier fragments is
* pkt->dts - trk->start_dts. */
trk->frag_start = pkt->dts - trk->start_dts;
+ trk->end_pts = AV_NOPTS_VALUE;
trk->frag_discont = 0;
}
}
trk->cluster[trk->entry].flags = 0;
if (trk->start_cts == AV_NOPTS_VALUE)
trk->start_cts = pkt->pts - pkt->dts;
+ if (trk->end_pts == AV_NOPTS_VALUE)
+ trk->end_pts = trk->cluster[trk->entry].dts +
+ trk->cluster[trk->entry].cts + pkt->duration;
+ else
+ trk->end_pts = FFMAX(trk->end_pts, trk->cluster[trk->entry].dts +
+ trk->cluster[trk->entry].cts +
+ pkt->duration);
if (enc->codec_id == AV_CODEC_ID_VC1) {
mov_parse_vc1_frame(pkt, trk);
// duration, but only helps for this particular track, not
// for the other ones that are flushed at the same time.
trk->track_duration = pkt->dts - trk->start_dts;
+ trk->end_pts = pkt->pts;
mov_auto_flush_fragment(s);
}
}
track->hint_track = -1;
track->start_dts = AV_NOPTS_VALUE;
track->start_cts = AV_NOPTS_VALUE;
+ track->end_pts = AV_NOPTS_VALUE;
if (st->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
if (track->tag == MKTAG('m','x','3','p') || track->tag == MKTAG('m','x','3','n') ||
track->tag == MKTAG('m','x','4','p') || track->tag == MKTAG('m','x','4','n') ||