From patchwork Mon Sep 25 23:48:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?q?Jan_Ekstr=C3=B6m?= X-Patchwork-Id: 5268 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.36.26 with SMTP id f26csp3194336jaa; Mon, 25 Sep 2017 16:55:18 -0700 (PDT) X-Received: by 10.28.0.7 with SMTP id 7mr1541257wma.109.1506383717986; Mon, 25 Sep 2017 16:55:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1506383717; cv=none; d=google.com; s=arc-20160816; b=a1yumdbfQFpFxQ6USJ0OJXSeBO2ixeqFN7tMiUn+bOSgWLPKPaYYUTKVibKtH7YW9w r7rB4E+dEUdBLLzSP5R6weayzaf0tfqVyvzS0T9O/jaJKEP85h9uzGLx7R1PD70HUduZ +z/4LWveluTMTTcXDzdOeTfnMaklSBrz97LUQfuaMo0MVQCNpR/wdsXz7iwuOF8o/m98 1Q/quVFyY5Zc5HN0q6XNTjJdrbFebCY4+iROQFZ8QIqAlKlVKs2KHTbquMKWbiPg+bE+ uqBCMUL3T99YXXWrablEfGuk9U3qHZn/T4LnmkJ0yYlLnmOAWcGFsftbXErcsRkgeFra pbyw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:dkim-signature:delivered-to:arc-authentication-results; bh=4+cfGH7iXh4n/eCIQiLuwz1PPjHMapCU4nYWQf5wZsU=; b=ymJ656K3NG1WqCqYYVqrpu0ZJRPLSD7tZGPGDaEK9POBvexrzr0N5rFxT/69kwsf/O PjDWs4Ei2bc4W+yF1RrxgtY9u7rqCuaOEHf9YQKF3dVapaKjgOlXgya7uM/VCTWQIw/W 9yiBUWP+owga09/yNPbiTmIa059lFunHyiyuVfrwI+rKeUY2ih+hEVFQnAs30aCmnuUw ZyxsAqgrsvPZc8ZjL/zDS5HWtgCJefyAf8RIRkO4FSt6qPYWeLLw28g6K9eRtVQYyZpz hCWIo9KEtX5PAM2OsXvbWkj7mv9ZNAos6L1vRfzVqtOT+b3nxm/uesaljiqcXxaAjloG 0e8g== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=RGAqCCyZ; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id b3si6292126wrb.18.2017.09.25.16.55.16; Mon, 25 Sep 2017 16:55:17 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=RGAqCCyZ; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1085F689A1B; Tue, 26 Sep 2017 02:55:04 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr0-f194.google.com (mail-wr0-f194.google.com [209.85.128.194]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 8982B6898AC for ; Tue, 26 Sep 2017 02:54:57 +0300 (EEST) Received: by mail-wr0-f194.google.com with SMTP id b9so966648wra.0 for ; Mon, 25 Sep 2017 16:55:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=2CANx5aIoMD7MZSGieQn0Znoy1YO12l5A6Z0GgNZjbs=; b=RGAqCCyZxULtDjN9L8E+3z8ufYU3KTL5mWu8HiByaImxcBxl+Hd7uJx1g8fXd3blCb 31t11kbQf9Cdwr7vCUaunCPxjFz85/e8hQdkvybD5El8PZZzsTveNsIR8cKoTayCTXvR Q98nC81VAhGBTnoNx5F0vfNAX3K5UZ0HRWKt19Ac/HgBVVBxKXXqPosKw4ZG/scxc0Ud MJwHuDTnRGDzuwTml2wNLb8skp+8p7zsf5U/aOwAWEmDLrcR47Niy3dokLOAW2dNWTz9 P4UhtdnygHN7tcml4EQ13IeRj9Uh/DTnCI6M/tYYuhiMos0x4d6r92trrZJdicJfXARi cDUQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=2CANx5aIoMD7MZSGieQn0Znoy1YO12l5A6Z0GgNZjbs=; b=a9Yy6ZGgiFYX7lUunJQ6BWPvQ5icoaFiqaaJPl6Dm7I6oKvhKIUZd043IISw2NWu0L UOVRAmUTs0FCBtaHmJEkDb+G4T29kF44FZqJCooYRzsryuGXmmcoKUk/s0/BIxXHDnNf Ku/cQkFHmUG7Ps3aN4aLRb3j6H/MYz3dKWpWleSa69r7AbrQuSXJevd/oJxSYNI4oO8h Ik33bBf6gwsiusKE9slhQPTAfyKS2KfvCGSf2iKwSvdLQokiGJB7rH5NnK5OX25Uf3p6 tAvoFmVArUh0ckfekTF2dtGakjyW03MZGPvfpT98jY/sn+XzPwmwVzDMV4iWAw245QFW wEuQ== X-Gm-Message-State: AHPjjUiDHkfqNUTvY/j6RFBBKFecSrGlrLNzuYglIlZYf5rFL8CNCVqs fgXDwg/v2Fb6SYrDGPeZzZhpnb6B X-Google-Smtp-Source: AOwi7QBybykP1BHoFrXqOcRLScrSgc0j8DKWTQL5XQYONoo7Z8JQLhuddJZVMwVsiKZb13BTHaFv/Q== X-Received: by 10.25.233.8 with SMTP id g8mr2912937lfh.197.1506383309005; Mon, 25 Sep 2017 16:48:29 -0700 (PDT) Received: from localhost.localdomain (91-159-194-103.elisa-laajakaista.fi. [91.159.194.103]) by smtp.gmail.com with ESMTPSA id t20sm1626718ljb.91.2017.09.25.16.48.28 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 25 Sep 2017 16:48:28 -0700 (PDT) From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= To: ffmpeg-devel@ffmpeg.org Date: Tue, 26 Sep 2017 02:48:27 +0300 Message-Id: <20170925234827.29229-1-jeebjp@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170924173729.GY7094@nb4> References: <20170924173729.GY7094@nb4> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/2 v2] movenc: Add an option for enabling negative CTS offsets X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Martin Storsjö This reduces the need for an edit list; streams that start with e.g. dts=-1, pts=0 can be encoded as dts=0, pts=0 (which is valid in mov/mp4) by shifting the dts values of all packets forward. This avoids the need for edit lists for such streams (while they still are needed for audio streams with encoder delay). This eases conformance with the DASH-IF interoperability guidelines. Signed-off-by: Martin Storsjö --- doc/muxers.texi | 2 ++ libavformat/movenc.c | 28 ++++++++++++++++++++++++---- libavformat/movenc.h | 2 ++ 3 files changed, 28 insertions(+), 4 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 36769b8c1a..312749942c 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -1055,6 +1055,8 @@ on the implicit end of the previous track fragment). @item -write_tmcd Specify @code{on} to force writing a timecode track, @code{off} to disable it and @code{auto} to write a timecode track only for mov and mp4 output (default). +@item -movflags negative_cts_offsets +Enables utilization of version 1 of the CTTS box, in which the CTS offsets can be negative. This enables the initial sample to have DTS/CTS of zero, and reduces the need for edit lists for some cases such as video tracks with B-frames. Additionally, eases conformance with the DASH-IF interoperability guidelines. @end table @subsection Example diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 10b959ad02..917486384a 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -77,6 +77,7 @@ static const AVOption options[] = { { "write_gama", "Write deprecated gama atom", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_WRITE_GAMA}, INT_MIN, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM, "movflags" }, { "use_metadata_tags", "Use mdta atom for metadata.", 0, AV_OPT_TYPE_CONST, {.i64 = FF_MOV_FLAG_USE_MDTA}, 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_BOOL, {.i64 = 1}, 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}, @@ -2094,8 +2095,9 @@ static int mov_write_stsd_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext 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; @@ -2119,7 +2121,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); @@ -2303,7 +2309,7 @@ static int mov_write_stbl_tag(AVFormatContext *s, AVIOContext *pb, MOVMuxContext if (track->par->codec_type == AVMEDIA_TYPE_VIDEO && track->flags & MOV_TRACK_CTTS && track->entry) { - if ((ret = mov_write_ctts_tag(pb, track)) < 0) + if ((ret = mov_write_ctts_tag(s, pb, track)) < 0) return ret; } mov_write_stsc_tag(pb, track); @@ -4044,7 +4050,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 */ @@ -4489,6 +4498,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) @@ -4759,6 +4770,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; @@ -5282,6 +5295,12 @@ static int mov_write_single_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 (trk->par->codec_id == AV_CODEC_ID_MP4ALS || trk->par->codec_id == AV_CODEC_ID_AAC || trk->par->codec_id == AV_CODEC_ID_FLAC) { @@ -5922,6 +5941,7 @@ static int mov_init(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 4c4f3cdfc3..cc2a155d79 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -116,6 +116,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 (or tmcd) track describes @@ -241,6 +242,7 @@ typedef struct MOVMuxContext { #define FF_MOV_FLAG_WRITE_GAMA (1 << 16) #define FF_MOV_FLAG_USE_MDTA (1 << 17) #define FF_MOV_FLAG_SKIP_TRAILER (1 << 18) +#define FF_MOV_FLAG_NEGATIVE_CTS_OFFSETS (1 << 19) int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt);