diff options
-rw-r--r-- | libavformat/movenc.c | 28 | ||||
-rw-r--r-- | libavformat/movenc.h | 2 |
2 files changed, 26 insertions, 4 deletions
diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 840190dbfa..356d1d6b71 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -62,6 +62,7 @@ static const AVOption options[] = { { "delay_moov", "Delay writing the initial moov until the first fragment is cut, or until the first fragment flush", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_DELAY_MOOV}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "global_sidx", "Write a global sidx index at the start of the file", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_GLOBAL_SIDX}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "skip_trailer", "Skip writing the mfra/tfra/mfro trailer for fragmented files", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_SKIP_TRAILER}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, + { "negative_cts_offsets", "Use negative CTS offsets (reducing the need for edit lists)", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, FF_RTP_FLAG_OPTS(MOVMuxContext, rtp_flags), { "skip_iods", "Skip writing iods atom.", offsetof(MOVMuxContext, iods_skip), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, { "iods_audio_profile", "iods audio profile atom.", offsetof(MOVMuxContext, iods_audio_profile), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 255, AV_OPT_FLAG_ENCODING_PARAM}, @@ -1163,8 +1164,9 @@ static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra return update_size(pb, pos); } -static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track) +static int mov_write_ctts_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *track) { + MOVMuxContext *mov = s->priv_data; MOVStts *ctts_entries; uint32_t entries = 0; uint32_t atom_size; @@ -1188,7 +1190,11 @@ static int mov_write_ctts_tag(AVIOContext *pb, MOVTrack *track) atom_size = 16 + (entries * 8); avio_wb32(pb, atom_size); /* size */ ffio_wfourcc(pb, "ctts"); - avio_wb32(pb, 0); /* version & flags */ + if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) + avio_w8(pb, 1); /* version */ + else + avio_w8(pb, 0); /* version */ + avio_wb24(pb, 0); /* flags */ avio_wb32(pb, entries); /* entry count */ for (i = 0; i < entries; i++) { avio_wb32(pb, ctts_entries[i].count); @@ -1273,7 +1279,7 @@ static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVTrack *tra mov_write_stss_tag(pb, track, MOV_PARTIAL_SYNC_SAMPLE); if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && track->flags & MOV_TRACK_CTTS && track->entry) - mov_write_ctts_tag(pb, track); + mov_write_ctts_tag(s, pb, track); mov_write_stsc_tag(pb, track); mov_write_stsz_tag(pb, track); mov_write_stco_tag(pb, track); @@ -2594,7 +2600,10 @@ static int mov_write_trun_tag(AVIOContext *pb, MOVMuxContext *mov, avio_wb32(pb, 0); /* size placeholder */ ffio_wfourcc(pb, "trun"); - avio_w8(pb, 0); /* version */ + if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) + avio_w8(pb, 1); /* version */ + else + avio_w8(pb, 0); /* version */ avio_wb24(pb, flags); avio_wb32(pb, end - first); /* sample count */ @@ -3040,6 +3049,8 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) ffio_wfourcc(pb, "MSNV"); else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_DEFAULT_BASE_MOOF) ffio_wfourcc(pb, "iso5"); // Required when using default-base-is-moof + else if (mov->mode == MODE_MP4 && mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) + ffio_wfourcc(pb, "iso4"); else if (mov->mode == MODE_MP4) ffio_wfourcc(pb, "isom"); else if (mov->mode == MODE_IPOD) @@ -3288,6 +3299,8 @@ static int mov_flush_fragment(AVFormatContext *s, int force) if (!track->end_reliable) { AVPacket pkt; if (!ff_interleaved_peek(s, i, &pkt, 1)) { + if (track->dts_shift != AV_NOPTS_VALUE) + pkt.dts += track->dts_shift; track->track_duration = pkt.dts - track->start_dts; if (pkt.pts != AV_NOPTS_VALUE) track->end_pts = pkt.pts; @@ -3729,6 +3742,12 @@ static int mov_write_packet(AVFormatContext *s, AVPacket *pkt) mov->flags &= ~FF_MOV_FLAG_FRAG_DISCONT; } + if (mov->flags & FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS) { + if (trk->dts_shift == AV_NOPTS_VALUE) + trk->dts_shift = pkt->pts - pkt->dts; + pkt->dts += trk->dts_shift; + } + if (!pkt->size) { if (trk->start_dts == AV_NOPTS_VALUE && trk->frag_discont) { trk->start_dts = pkt->dts; @@ -4095,6 +4114,7 @@ static int mov_write_header(AVFormatContext *s) track->start_dts = AV_NOPTS_VALUE; track->start_cts = AV_NOPTS_VALUE; track->end_pts = AV_NOPTS_VALUE; + track->dts_shift = AV_NOPTS_VALUE; if (st->codecpar->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') || diff --git a/libavformat/movenc.h b/libavformat/movenc.h index f4ed188c38..008f4671c6 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -107,6 +107,7 @@ typedef struct MOVTrack { int64_t start_cts; int64_t end_pts; int end_reliable; + int64_t dts_shift; int hint_track; ///< the track that hints this track, -1 if no hint track is set int src_track; ///< the track that this hint track describes @@ -195,6 +196,7 @@ typedef struct MOVMuxContext { #define FF_MOV_FLAG_DELAY_MOOV (1 << 13) #define FF_MOV_FLAG_GLOBAL_SIDX (1 << 14) #define FF_MOV_FLAG_SKIP_TRAILER (1 << 15) +#define FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS (1 << 16) int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt); |