From patchwork Mon Sep 25 23:55:30 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: 5269 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.36.26 with SMTP id f26csp3194529jaa; Mon, 25 Sep 2017 16:55:40 -0700 (PDT) X-Received: by 10.28.93.84 with SMTP id r81mr1698312wmb.149.1506383740291; Mon, 25 Sep 2017 16:55:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1506383740; cv=none; d=google.com; s=arc-20160816; b=IxdNBcDEu9N9EjVTIYgks7e/GgP9kJ39RX0z+wfftBaM0VyFj/DiJZ7peap/VHzoaY 4oGrlZTzPEdKqg90vBiXd7f9jvxTzmNRlwM3zb6bFTcS+3+YEdLHi2qLHE5hNPETZvkC BYYbIo93ZLAzvbeEpdRo9tdwj8QGE0xwiEfsJycCLVlWwI83BJnFcbhjpWuCOWCUxaJZ Z6y3Q9fJjtUxokPPaI13qf0bpbDmzJKaBu1fJiP4ctW7AlCLmjvL4fmgk0QhKiu+Z4Oq Yu8XY9Eop9njbrm/o88epzpPCP93mKuPDWIebOmHcYBZ9PB10PJPwy4op3Kbn7rnC1Sd v8UQ== 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=eUemLPeZM06DXw2lYQlPwpdeiEHsEN4BtzfYIgolIeI=; b=Fc9Z7tMgMEadly93l8Mt0FNDAJiwrOyW67fHwFWANgqoPv53yW4XD931/GKqF1Xiv6 cCgu/YlA42af+q/gIV2Dm14ZByIvT3e1f3E6g3ldLrBdRPde0G5n38FdOQep5LwTRovt LSKiJr3Bjw6rbDqfj9DNIB3ZV5YwaTJf5Gddf8VonmTZq9p6zD77wVK0zp7Z4Ae4KKeR IFBlwwdPS+ELbquegcQEX3IaxEx6Ze3Yef8qv0p/j4bN2M2ZMzUFVL3Y7+uYC1e5IbNO hBCXbCmbCehbhSLV9dyWwWp3TVUF8JCA6NT5a8bP/ILqXB1cmnSq6oNi8n0uXTjBrxpG yekA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=pjRS4NWl; 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 j144si466233wmj.34.2017.09.25.16.55.39; Mon, 25 Sep 2017 16:55:40 -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=pjRS4NWl; 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 97AC6689A50; Tue, 26 Sep 2017 02:55:27 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr0-f195.google.com (mail-wr0-f195.google.com [209.85.128.195]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 3839B6809AC for ; Tue, 26 Sep 2017 02:55:21 +0300 (EEST) Received: by mail-wr0-f195.google.com with SMTP id b9so967158wra.0 for ; Mon, 25 Sep 2017 16:55:33 -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=EyiQrrJAxM9oXb6UJlJhnDtCwySsqsuxBSwLPr+60aU=; b=pjRS4NWlmq36Ly0SxyWdr/z+2OMv12jaHOtZ9rgY6d7V8lLsXVnlvKVk2wobjZSERP qDRmS15GEUxHeK3FzF+PX7/iJPr/fsyd4FlDf9qeIpif4L7k76MBk3zHyKNX6CWsXNaz 1MvI0UKbflLUzeFEs+1t757PHy0N/Sa8bY/d/uGu1hblfm0iTc8UtBubd29j390Nafcr 1IGdeEZu+89Ya6kZQQ35txPU7THMkr1suuiyhhNGT2aLlwhfKD1okvvUppsvQqvwT4Tc /QXFG0L/XSClyhuqbgFj+gWl1HTYYvBofk5bYKKHtSyDBMwU9M2EzRCzXjkxqSuMmPOz Yb5Q== 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=EyiQrrJAxM9oXb6UJlJhnDtCwySsqsuxBSwLPr+60aU=; b=b2AEW2LaigEUcrqtYHsNyH/PunNPmLzKhHV4qSr+B2lyD4SCUPFPD5rQyf/59590Th E+11JiwjmclV/Vr21ETYiVE6j7leVM2c0euJ+8O85BcqHHWdNYiuQhaOz5ioWuCIFQy3 Dna6EWQS3nzo0e6l94juA/oV4L26GefsAjqFd/BjlWSw3gvketBQfyuMtjKIi+/mnZG8 JHzoKYAiOMVCZ4KPCMQhH9PSD8g3T3c69ZIJAKyYGAAHW/foNXSzIX6mBoiA9vmaIOzn JH3wJiy31jTZfqQrLutFQssJIPq64RUuD15bkI/W/oHgLD8yUXlCCNSatRz0e6ifInYd mIfQ== X-Gm-Message-State: AHPjjUgFjpeyz0HB1dhqiVWOs1U4bMZgK7WEX/wSgzNdYS1z+DLOOFX3 gwDEVFomJKpQSucelS7BChQVJHGX X-Google-Smtp-Source: AOwi7QA+qh6Q9ocopb20WGbOP1czp/5HzNwpCXN3u/qgnB9+IWvDVYhLN9vLUMNvR0UjmZf8qUGiOA== X-Received: by 10.25.78.212 with SMTP id u81mr2667051lfk.4.1506383732331; Mon, 25 Sep 2017 16:55:32 -0700 (PDT) Received: from localhost.localdomain (91-159-194-103.elisa-laajakaista.fi. [91.159.194.103]) by smtp.gmail.com with ESMTPSA id b4sm1136805lfg.90.2017.09.25.16.55.31 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 25 Sep 2017 16:55:31 -0700 (PDT) From: =?UTF-8?q?Jan=20Ekstr=C3=B6m?= To: ffmpeg-devel@ffmpeg.org Date: Tue, 26 Sep 2017 02:55:30 +0300 Message-Id: <20170925235530.30365-1-jeebjp@gmail.com> X-Mailer: git-send-email 2.13.5 In-Reply-To: <20170925234827.29229-1-jeebjp@gmail.com> References: <20170925234827.29229-1-jeebjp@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/2 v3] 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 | 6 ++++++ libavformat/movenc.c | 28 ++++++++++++++++++++++++---- libavformat/movenc.h | 2 ++ 3 files changed, 32 insertions(+), 4 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 36769b8c1a..8a1319c153 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -1055,6 +1055,12 @@ 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);