From patchwork Tue Apr 27 21:35:26 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vittorio Giovara X-Patchwork-Id: 27449 Delivered-To: andriy.gelman@gmail.com Received: by 2002:a25:49c5:0:0:0:0:0 with SMTP id w188csp4836319yba; Tue, 27 Apr 2021 15:03:27 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyQ9WlyDrLjhlNeNP83C/7lseORVl2/BWKk92ehUnfkGHP02sqG0CHhcvrLsEzMD8DpIGS1 X-Received: by 2002:a05:6402:451:: with SMTP id p17mr6970083edw.223.1619561007304; Tue, 27 Apr 2021 15:03:27 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1619561007; cv=none; d=google.com; s=arc-20160816; b=O4OsN9k+SPyHoradg7enbyLxz6FgNiAkmKmFvEskKTsdzMimV7A7bOW+6oz2VWKAAZ abZa0aXxR7z7AyixC2Utclqg06pQuxBor6Qa3v1jTzQMJKuDoq5tTL1uT2mtsLTOcXnE YCUc4k0o337n2B+258VlhzQTrYzVaIdvwc638lu2XQlE4lpPDrkbjWATHqOMHeoad618 xegClX4PFYM5ZmfawffBfcLTG7jpPlW1PHSyDVQwgKdbfxc57sx0ie/R+3oXB4gaGYfV 4D2iIMfTr5p6ltjpIU+t6YLBWVnURI2Apv8aBVIGOV8JJK/7eRxhMvSXn6eNgH0fGqZP scQQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:subject:to :message-id:date:from:mime-version:dkim-signature:delivered-to; bh=O8T8knebsNaS3JtdnruxgEPuJwMXt9Zqs4l7KvzhznQ=; b=aceGfY/HJFLH+rkPRyHp8sMDu5j+sUw94Vjw2Gp8zDORmEkOoGBIziVx0PrSo+K5CD UZJ96spWZqinmlbrtiyslSYs5uQqYhEI7sAi9IopPWwtjEdO7TFWX0O+kgq/+gOyJDCj GPTb3/w0dusFY/pQxP5mvMNMQPLn1Mf1meVttslnHLfn541EYtHfZrzvv9HNQ0iYZJDV /DnvH54sfkTflpQh/ghVk8t9GhUvxOnnCJl+rrMJq9fvCoNACp1xnTvcc1D9ev+ZNBoH Hg1xjygkVQrZVsbSEC5oiyBRrBFjChVNCkw3wTrOgWt/F49LPcj4sRKtf0Lyi+2TbhKh 7SOQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=YXMc3acJ; 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=QUARANTINE 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 u19si3595125edo.410.2021.04.27.15.03.03; Tue, 27 Apr 2021 15:03:27 -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=YXMc3acJ; 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=QUARANTINE 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 7EFAD689F8F; Wed, 28 Apr 2021 01:03:02 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ed1-f49.google.com (mail-ed1-f49.google.com [209.85.208.49]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 715F96883D3 for ; Wed, 28 Apr 2021 01:02:56 +0300 (EEST) Received: by mail-ed1-f49.google.com with SMTP id s15so71822672edd.4 for ; Tue, 27 Apr 2021 15:02:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:from:date:message-id:subject:to; bh=JTzOY7h9mBfPyXuVHUxiPYWZMHtbfFnrN48EOVS88og=; b=YXMc3acJBpDfrjdLxOw6SRi/DGLilst9J5b9Ak5DVdr+ondKBe4mBUDWmcNv8CbmnV Jw7bIOOg/ytUI/GExz8Wkj291Mcl9I4YE0tUSf/edF1iVhOW25cZyRxbFv0903qFSYHR NOluoIpS0vIdXcSxJVgnkrwO4In8Hq6acdMNhkfEMa+6MmLCksH0Owo5ZdsMBxJR2m2Y ogw+V5XjSyHKyGpluoTk9HnUHm5AehScdW4PA1IU9eZPOZorVpUHcbtpLr8C4eoXLUOa SmBs8xwh/4rbpwFma/+d6GwdWF/ZtOJOHb56o6eKPJp/2R8AZSSi6lJpRO3wu5zsZEZq slKw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=JTzOY7h9mBfPyXuVHUxiPYWZMHtbfFnrN48EOVS88og=; b=m/70MZzuT8vKcZJuAub6VVRAhqiqa7E0kUEVjkGwtTKuXZNbeXLLkkqVXEhBDQ+6hr ITahj6rUIPExAdui2+fP6CXTV5zUHyLGWEawc5JgDHU8eHnLWRjY/Uvnx+lfRxxMeUz7 IhTJOCb//3aOhbOl2/ck/UJy35436uxlT+g/HX5jID6HiG45gA88u/LjpU3mSZ0zjFf5 x9l/Za51PNKSyHjBbaDPa9OGo7l5VzX1YH5hDZq7ApdDF6JpFddOncOzIikmtZMR/Yl/ FK5o0lapiTUvfCMgyaBtbwyT5Bvkuz3bZq5pHdbsMubGsVo7MTSPihpsxgOono46CsHr PyyA== X-Gm-Message-State: AOAM5309rs+6/YBjD1ysIrxdxsJNtrPiwIqx5quYBNKIXRbsrOCYLw8Z cmKStyqM77d9kBrHaoPw8n5WQT5c3EYOiv/GzNPyGrok8xE= X-Received: by 2002:a2e:b4f5:: with SMTP id s21mr12840395ljm.320.1619559337348; Tue, 27 Apr 2021 14:35:37 -0700 (PDT) MIME-Version: 1.0 From: Vittorio Giovara Date: Tue, 27 Apr 2021 23:35:26 +0200 Message-ID: To: FFmpeg development discussions and patches X-Content-Filtered-By: Mailman/MimeDel 2.1.29 Subject: [FFmpeg-devel] [PATCH] movenc: add movie_timescale option instead of hardcoding 1000 X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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" X-TUID: ERphN1zSXq9S From: Justin Ruggles There are cases where using 1000 as the MP4 timescale is not accurate enough, for example when one needs sample-accurate audio handling. This adds a new AVOption to the MOV/MP4 muxer to override the movie timescale, but it still defaults to 1000 to maintain current default behavior. diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 8e6ed81..93f93e4 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -107,6 +107,7 @@ static const AVOption options[] = { { "wallclock", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_WALLCLOCK}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "prft"}, { "pts", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = MOV_PRFT_SRC_PTS}, 0, 0, AV_OPT_FLAG_ENCODING_PARAM, "prft"}, { "empty_hdlr_name", "write zero-length name string in hdlr atoms within mdia and minf atoms", offsetof(MOVMuxContext, empty_hdlr_name), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_ENCODING_PARAM}, + { "movie_timescale", "set movie timescale", offsetof(MOVMuxContext, movie_timescale), AV_OPT_TYPE_INT, {.i64 = MOV_TIMESCALE}, 1, INT_MAX, AV_OPT_FLAG_ENCODING_PARAM}, { NULL }, }; @@ -3039,7 +3040,7 @@ static int mov_write_tkhd_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track, AVStream *st) { int64_t duration = av_rescale_rnd(calc_pts_duration(mov, track), - MOV_TIMESCALE, track->timescale, + mov->movie_timescale, track->timescale, AV_ROUND_UP); int version = duration < INT32_MAX ? 0 : 1; int flags = MOV_TKHD_FLAG_IN_MOVIE; @@ -3188,7 +3189,7 @@ static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov, MOVTrack *track) { int64_t duration = av_rescale_rnd(calc_samples_pts_duration(mov, track), - MOV_TIMESCALE, track->timescale, + mov->movie_timescale, track->timescale, AV_ROUND_UP); int version = duration < INT32_MAX ? 0 : 1; int entry_size, entry_count, size; @@ -3207,7 +3208,7 @@ static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov, } } - delay = av_rescale_rnd(start_dts + start_ct, MOV_TIMESCALE, + delay = av_rescale_rnd(start_dts + start_ct, mov->movie_timescale, track->timescale, AV_ROUND_DOWN); version |= delay < INT32_MAX ? 0 : 1; @@ -3242,8 +3243,8 @@ static int mov_write_edts_tag(AVIOContext *pb, MOVMuxContext *mov, /* Avoid accidentally ending up with start_ct = -1 which has got a * special meaning. Normally start_ct should end up positive or zero * here, but use FFMIN in case dts is a small positive integer - * rounded to 0 when represented in MOV_TIMESCALE units. */ - av_assert0(av_rescale_rnd(start_dts, MOV_TIMESCALE, track->timescale, AV_ROUND_DOWN) <= 0); + * rounded to 0 when represented in movie timescale units. */ + av_assert0(av_rescale_rnd(start_dts, mov->movie_timescale, track->timescale, AV_ROUND_DOWN) <= 0); start_ct = -FFMIN(start_dts, 0); /* Note, this delay is calculated from the pts of the first sample, * ensuring that we don't reduce the duration for cases with @@ -3477,7 +3478,7 @@ static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov) if (mov->tracks[i].entry > 0 && mov->tracks[i].timescale) { int64_t max_track_len_temp = av_rescale_rnd( calc_pts_duration(mov, &mov->tracks[i]), - MOV_TIMESCALE, + mov->movie_timescale, mov->tracks[i].timescale, AV_ROUND_UP); if (max_track_len < max_track_len_temp) @@ -3506,7 +3507,7 @@ static int mov_write_mvhd_tag(AVIOContext *pb, MOVMuxContext *mov) avio_wb32(pb, mov->time); /* creation time */ avio_wb32(pb, mov->time); /* modification time */ } - avio_wb32(pb, MOV_TIMESCALE); + avio_wb32(pb, mov->movie_timescale); (version == 1) ? avio_wb64(pb, max_track_len) : avio_wb32(pb, max_track_len); /* duration of longest track */ avio_wb32(pb, 0x00010000); /* reserved (preferred rate) 1.0 = normal */ @@ -6115,7 +6116,7 @@ static int mov_create_chapter_track(AVFormatContext *s, int tracknum) track->mode = mov->mode; track->tag = MKTAG('t','e','x','t'); - track->timescale = MOV_TIMESCALE; + track->timescale = mov->movie_timescale; track->par = avcodec_parameters_alloc(); if (!track->par) return AVERROR(ENOMEM); @@ -6179,8 +6180,8 @@ static int mov_create_chapter_track(AVFormatContext *s, int tracknum) AVChapter *c = s->chapters[i]; AVDictionaryEntry *t; - int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,MOV_TIMESCALE}); - pkt->pts = pkt->dts = av_rescale_q(c->start, c->time_base, (AVRational){1,MOV_TIMESCALE}); + int64_t end = av_rescale_q(c->end, c->time_base, (AVRational){1,mov->movie_timescale}); + pkt->pts = pkt->dts = av_rescale_q(c->start, c->time_base, (AVRational){1,mov->movie_timescale}); pkt->duration = end - pkt->dts; if ((t = av_dict_get(c->metadata, "title", NULL, 0))) { @@ -6737,7 +6738,7 @@ static int mov_init(AVFormatContext *s) } else if (st->codecpar->codec_type == AVMEDIA_TYPE_DATA) { track->timescale = st->time_base.den; } else { - track->timescale = MOV_TIMESCALE; + track->timescale = mov->movie_timescale; } if (!track->height) track->height = st->codecpar->height; diff --git a/libavformat/movenc.h b/libavformat/movenc.h index cdbc407..af1ea0b 100644 --- a/libavformat/movenc.h +++ b/libavformat/movenc.h @@ -237,6 +237,7 @@ typedef struct MOVMuxContext { int write_tmcd; MOVPrftBox write_prft; int empty_hdlr_name; + int movie_timescale; } MOVMuxContext; #define FF_MOV_FLAG_RTP_HINT (1 << 0)