From patchwork Fri Dec 23 12:51:56 2022 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: 39743 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:bc95:b0:ad:ade2:bfd2 with SMTP id fx21csp451062pzb; Fri, 23 Dec 2022 04:52:26 -0800 (PST) X-Google-Smtp-Source: AMrXdXvSwxnnKYMSy7Rp8/jBkBDoQdtJ95bn6XTAMTScO3vtHgB7EwC0bew1gn52j2ZmIxQyBhoM X-Received: by 2002:a17:906:fb9a:b0:7c0:996b:be7f with SMTP id lr26-20020a170906fb9a00b007c0996bbe7fmr7736493ejb.29.1671799946279; Fri, 23 Dec 2022 04:52:26 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1671799946; cv=none; d=google.com; s=arc-20160816; b=mumCu0B43rr7IsMasuLXTb6ryfLo6POjWrtQQMBrsE8GS4ZwdMtoai9CegmcZQwLOw 2LlKHa6AL8LrupWP6+T90GX/78Gcxvihes39mgsY/uI1uvwVkDBNiG864hAuFjF8RGDV jjq8fC1RVFQ2xxUcvMiMWRRWSxBLaIMkvoxi5AHJzOO+BN6NCMdlcy5x/7VKfFdHD/yb 7sN1QU3ZdK0SvRV51BUrSr8VRq/5rZQFoE5gYMgbwOMky+vD4ZHtL35njioY9spYUeNB jBJhgUS9xYiFcF2Trtz89PzOiZVlCpo+tg81DCho1zZag/iEdIBqX/XkwBfulE/pS4lT s8rw== 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; bh=adHDRRw+r7MliiA73eNWmM1elE51/HOgyLP0sqZN0LI=; b=LEAPpmzbnxLSfnsCJZmevpcSN+dJB0mVO1PpTvp9Qr/364YS/8y5hoDR42vWQ1PNoD k2/MFOfUhV7Gtmq3LQ2TfvJnsYWZC8POOt/t7MaHcR5YBrRT3jj2R0VpNuISoiTzVVQ1 g6wmXj1IPu39On0ap7Ee+vuA+i7MAupld387qyEEnfEsU0K+pjKmRmllo3nUjmP2Jjqp xFqhptnHMp4K/G8PxXJRl0O5ahCb2XbP4Bqq8y7m4MdeMQIG/YvKjoxbOjIq1W9cS/Gw K3SjrtQgdKzCi7B4U42d9Wy2elO6+wvYODLYM3FrvJ42RgOfHN4dpBSC5l4DjkAt7al8 0zjA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b="h/bMGo3v"; 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 hv9-20020a17090760c900b007adcc8fb7a0si2681832ejc.399.2022.12.23.04.52.25; Fri, 23 Dec 2022 04:52:26 -0800 (PST) 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=20210112 header.b="h/bMGo3v"; 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 96F8168BAA5; Fri, 23 Dec 2022 14:52:13 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-lf1-f52.google.com (mail-lf1-f52.google.com [209.85.167.52]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5E41D6806E2 for ; Fri, 23 Dec 2022 14:52:06 +0200 (EET) Received: by mail-lf1-f52.google.com with SMTP id g13so6993152lfv.7 for ; Fri, 23 Dec 2022 04:52:06 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=ild4DpfDhQ/baFdtGqJRpaAupEekerz5r5cWYrp5zKg=; b=h/bMGo3vY+E5dvsrUEROpa/W6oib3pmdIzudTzi7K5Trgwnbk7+FNK3Mn2vNI7Kz+K CO162foptfJ93ZHlG1BPdfkOtt6aKREAhfNDR4b6Lz3kCzNfLwlmmNkku6PLF1WpxbKo gS5yyYPefnCYvgnWj1/PHoFAs6B7bjk+v7UyxPl6n5fZFKw+fkeBG/4SBm5s5b6g/8bZ P8Fzq473sbPxSRoDABXey00fuX4pwR0oTgFOEP1y06tBVG467VPnPHcjK2p6gBuoj7XP dJTka7mpK5j5FRIkO0Hq3VoNe2MsBKtzrPQ+as7R7SViMk8APNN646pEF+dZwExGdD/I vssg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ild4DpfDhQ/baFdtGqJRpaAupEekerz5r5cWYrp5zKg=; b=th5rYWUW7Fj+86OMyjxurkBz+zM19sg2u6coMEFNkFVuSGAiMN5vv9Ku0d2tmsCwZ0 d6YecBG1cbZ4bQ37CzQBu4KMYx1UU+EWKR/mZiArHNVqZxLX5D9sKJwD2wVi9mZRN6yG cW48xNESCeA7aKg2ArKk7QXBuZtlvr8CS1dV4Q2O4+XoH+Q0HQdYemP09Qjy7PaUMTCV 4QMHHl5ffYD/FoePHSSE8wr+UdjBr3nZ1W9HBM0VMXxxHMZg23GdJz96jztio1Uxk6ZS JwpT5UrA8wqQbFzyV34Ibx0Hcr4Y+EnA+Qpvb8HUYADkEitMeyR28NVv89qjFoahwr3h 9wLg== X-Gm-Message-State: AFqh2kpATrLVd53QJX8UJDTtyW6hBM1LWE/oQrz38qWg4KjDnTJLSkLI Yc84RHW1nEdiEaE4WFT8Ki2JoQuX0gw= X-Received: by 2002:ac2:59c9:0:b0:4c4:6a8e:24 with SMTP id x9-20020ac259c9000000b004c46a8e0024mr2507553lfn.5.1671799925703; Fri, 23 Dec 2022 04:52:05 -0800 (PST) Received: from localhost.localdomain (91-153-198-187.elisa-laajakaista.fi. [91.153.198.187]) by smtp.gmail.com with ESMTPSA id x14-20020a056512078e00b004b4f1ea713csm512600lfr.73.2022.12.23.04.52.04 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 23 Dec 2022 04:52:05 -0800 (PST) From: =?utf-8?q?Jan_Ekstr=C3=B6m?= To: ffmpeg-devel@ffmpeg.org Date: Fri, 23 Dec 2022 14:51:56 +0200 Message-Id: <20221223125157.83340-2-jeebjp@gmail.com> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221223125157.83340-1-jeebjp@gmail.com> References: <20221223125157.83340-1-jeebjp@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/2] avcodec/avpacket: add functionality to prepend to AVPacketLists 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: JN156OmaSn+b From: Jan Ekström Signed-off-by: Jan Ekström --- libavcodec/avpacket.c | 20 +++++++++++++++----- libavcodec/packet_internal.h | 2 ++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c index 5fef65e97a..01eb9896d5 100644 --- a/libavcodec/avpacket.c +++ b/libavcodec/avpacket.c @@ -539,6 +539,7 @@ int avpriv_packet_list_put(PacketList *packet_buffer, int flags) { PacketListEntry *pktl = av_malloc(sizeof(*pktl)); + unsigned int update_end_point = 1; int ret; if (!pktl) @@ -562,13 +563,22 @@ int avpriv_packet_list_put(PacketList *packet_buffer, pktl->next = NULL; - if (packet_buffer->head) - packet_buffer->tail->next = pktl; - else + if (packet_buffer->head) { + if (flags & FF_PACKETLIST_FLAG_PREPEND) { + pktl->next = packet_buffer->head; + packet_buffer->head = pktl; + update_end_point = 0; + } else { + packet_buffer->tail->next = pktl; + } + } else packet_buffer->head = pktl; - /* Add the packet in the buffered packet list. */ - packet_buffer->tail = pktl; + if (update_end_point) { + /* Add the packet in the buffered packet list. */ + packet_buffer->tail = pktl; + } + return 0; } diff --git a/libavcodec/packet_internal.h b/libavcodec/packet_internal.h index 92a0d4e6d5..43dc6222ce 100644 --- a/libavcodec/packet_internal.h +++ b/libavcodec/packet_internal.h @@ -32,6 +32,8 @@ typedef struct PacketList { PacketListEntry *head, *tail; } PacketList; +#define FF_PACKETLIST_FLAG_PREPEND (1 << 0) /**< Prepend created AVPacketList instead of appending */ + /** * Append an AVPacket to the list. * From patchwork Fri Dec 23 12:51:57 2022 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: 39744 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:bc95:b0:ad:ade2:bfd2 with SMTP id fx21csp451147pzb; Fri, 23 Dec 2022 04:52:35 -0800 (PST) X-Google-Smtp-Source: AMrXdXuQWvPBjHBQBHWCys6MQMFRF+ZFUb0iQcxFNwk6IsB8xBvQV5xaXy/gZy9U2SNIXshkkLYM X-Received: by 2002:a17:906:71c3:b0:7c0:dd80:e95e with SMTP id i3-20020a17090671c300b007c0dd80e95emr11436444ejk.51.1671799954789; Fri, 23 Dec 2022 04:52:34 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1671799954; cv=none; d=google.com; s=arc-20160816; b=lGl88z4ZxiwoN6SKVHSP10IO/DBfIH+13rldq1H2ylDXbi+hqjJGxkIu9ixgz/K9xG H5d+ogL9gvR64ycnwGHGJ/ejZ7enme4aw1sYZx4nyztG+o+IUBdO2vG7Lf4yqxCGQgvD 2l3ausr0i/c9b4uUl+h5sIF7E9NwXC11GtX3G0n5XDLbBNBJLCy3MbIX/rqU0IOqH7tu TA+nfyepN8o6Mb7D6Q7Oq9tPigygavua9151S+f8vF4P/A+8FsP4MN+re30gkSXH6bd1 NdewrSoDVpv9UxpR1HjlQlySnUPUrrZYArnxvv3TePQ5rS7mYl8euxxyOerIV8WUh+z2 MDYA== 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; bh=rPcRoV+y0oUZoWWQg/ksJIAOp+I25X2ggYy++K03PKc=; b=nEawpcENrKQz5VgHugBHBY78+5mEiTDCXA5eYcJMbsGps7V98tNEaCLFYCQE+mMT2s 76ZXopgHlZzS0CU2TqGyW+HEvXkZM7gujadXkrVgjuoQ5ETACKUXTcWcnX0clkTKEOzA cUE5+8bj37ANocrgYSRJcUpBhC4dKCjYavtzsV7UuhgrL5KaN9yaaEaIvGYt5gw+lSOH ulmqVGrZVUALYxy5v7eg9fnIz6Gsb8rx/EPMJ/FkEZIWc618cJ5OSQXFIzX5apCstr0m 4HIoJt9gdnYtKDOxUnCMOb15r7MaxlTS5hRS6hNuuDfgnKgbuezjJfXoidbM0DOhzVi0 QMYg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20210112 header.b=i6WKUzJp; 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 dt3-20020a170907728300b007c151fd4953si2763403ejc.213.2022.12.23.04.52.34; Fri, 23 Dec 2022 04:52:34 -0800 (PST) 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=20210112 header.b=i6WKUzJp; 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 C948F68BABB; Fri, 23 Dec 2022 14:52:14 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-lf1-f53.google.com (mail-lf1-f53.google.com [209.85.167.53]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 4C2796806E2 for ; Fri, 23 Dec 2022 14:52:07 +0200 (EET) Received: by mail-lf1-f53.google.com with SMTP id bp15so6958616lfb.13 for ; Fri, 23 Dec 2022 04:52:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=BLQ1bYlvkilNG5W1kqWtQaPw32tRBL+iNEaY+3p7dmw=; b=i6WKUzJpxEORzVpbAD5R4OO3rke0k3UKQWz8t4PHm1rZS6SGf6PapiX2/3/o+4G8Bl 78L8RvwR4ezAQ4e9MKrImkDnx+2371SD7/Gd92EPJeriKbtnd6mwHBOjr0wSiR8sd3j1 ypW2mbTjilwreXvNSY1AbXNpe4px/TD6z/hIumTJrQse1WmxVgrJ7AbzBSHrzue3mXY9 7lLei8i7T541QDzQ9w3M9DCRURa1xow5i261luzZKXBbE9uCLZoFRzcbcX07+ZEzry7R GZEqZcMnEw+0yBcxvgOSe+sVZMiP87xUZdxVuQt3mddQv6nvshnamHtx75+HYxfUBzNR oaGg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BLQ1bYlvkilNG5W1kqWtQaPw32tRBL+iNEaY+3p7dmw=; b=nTdjYUhZ6dv5bXWAsvoP+3UKNhnZUoLKZ6FAqJP/vpYxpc3dJ43S9MQPPxFCmjRMy2 zKnGQ3ex0Nuf9xso+kBMTCd5iFKwFqG0dfVMnKxrKx2EtWUJwigClcqHIrTLAWYsOkbV Oemvk5y7eG2w/k6Qa9uwhSKcntqQ5rAqWiWwhyP/lU6aLqavFiRk7CPIMGSnI+8FDCWI qsJCOP90mm3l6hjkuKSOmnBep5AKztoxT52rW6i8HpOP3ZYxt+b2M7GhgkqxPCCR6tzI JmF+oYwpAyGz5fT7R6VqAwzT4fmy30qHwxowdWmUJSsMOcaaAwLJmCXgT1yt1LqbpExr pLew== X-Gm-Message-State: AFqh2kqOhRzatOQ61Q/obbymvTAcTZIYVT2IJfmAge7DVmO+MqwZLCJ1 z9jKONuWEJ+udZ9txqUhP+qh1a/7HeI= X-Received: by 2002:a05:6512:3c89:b0:4b6:fddc:1fcd with SMTP id h9-20020a0565123c8900b004b6fddc1fcdmr4766903lfv.23.1671799926504; Fri, 23 Dec 2022 04:52:06 -0800 (PST) Received: from localhost.localdomain (91-153-198-187.elisa-laajakaista.fi. [91.153.198.187]) by smtp.gmail.com with ESMTPSA id x14-20020a056512078e00b004b4f1ea713csm512600lfr.73.2022.12.23.04.52.05 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 23 Dec 2022 04:52:05 -0800 (PST) From: =?utf-8?q?Jan_Ekstr=C3=B6m?= To: ffmpeg-devel@ffmpeg.org Date: Fri, 23 Dec 2022 14:51:57 +0200 Message-Id: <20221223125157.83340-3-jeebjp@gmail.com> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221223125157.83340-1-jeebjp@gmail.com> References: <20221223125157.83340-1-jeebjp@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/2] avformat/movenc: add support for fragmented TTML muxing 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: cdmIOewexaBQ From: Jan Ekström Attempts to base the fragmentation timing on other streams as most receivers expect media fragments to be more or less aligned. Currently does not support fragmentation on subtitle track only, as the subtitle packet queue timings would have to be checked in addition to the current fragmentation timing logic. Signed-off-by: Jan Ekström --- libavformat/movenc.c | 9 --- libavformat/movenc_ttml.c | 163 +++++++++++++++++++++++++++++++++++++- 2 files changed, 159 insertions(+), 13 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 7d49892283..e9a7984f8a 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -7188,15 +7188,6 @@ static int mov_init(AVFormatContext *s) track->squash_fragment_samples_to_one = ff_is_ttml_stream_paragraph_based(track->par); - if (mov->flags & FF_MOV_FLAG_FRAGMENT && - track->squash_fragment_samples_to_one) { - av_log(s, AV_LOG_ERROR, - "Fragmentation is not currently supported for " - "TTML in MP4/ISMV (track synchronization between " - "subtitles and other media is not yet implemented)!\n"); - return AVERROR_PATCHWELCOME; - } - if (track->mode != MODE_ISM && track->par->codec_tag == MOV_ISMV_TTML_TAG && s->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) { diff --git a/libavformat/movenc_ttml.c b/libavformat/movenc_ttml.c index 6deae49657..27ec7d9487 100644 --- a/libavformat/movenc_ttml.c +++ b/libavformat/movenc_ttml.c @@ -54,6 +54,50 @@ static int mov_init_ttml_writer(MOVTrack *track, AVFormatContext **out_ctx) return 0; } +static void mov_calculate_start_and_end_of_other_tracks( + AVFormatContext *s, MOVTrack *track, int64_t *start_pts, int64_t *end_pts) +{ + MOVMuxContext *mov = s->priv_data; + + // Initialize at the end of the previous document/fragment, which is NOPTS + // until the first fragment is created. + int64_t max_track_end_dts = *start_pts = track->end_pts; + + for (unsigned int i = 0; i < s->nb_streams; i++) { + MOVTrack *other_track = &mov->tracks[i]; + + // Skip our own track, any other track that needs squashing, + // or any track which still has its start_dts at NOPTS or + // any track that did not yet get any packets. + if (track == other_track || + other_track->squash_fragment_samples_to_one || + other_track->start_dts == AV_NOPTS_VALUE || + !other_track->entry) { + continue; + } + + { + int64_t picked_start = av_rescale_q_rnd(other_track->cluster[0].dts + other_track->cluster[0].cts, + other_track->st->time_base, + track->st->time_base, + AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); + int64_t picked_end = av_rescale_q_rnd(other_track->end_pts, + other_track->st->time_base, + track->st->time_base, + AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX); + + if (*start_pts == AV_NOPTS_VALUE) + *start_pts = picked_start; + else if (picked_start >= track->end_pts) + *start_pts = FFMIN(*start_pts, picked_start); + + max_track_end_dts = FFMAX(max_track_end_dts, picked_end); + } + } + + *end_pts = max_track_end_dts; +} + static int mov_write_ttml_document_from_queue(AVFormatContext *s, AVFormatContext *ttml_ctx, MOVTrack *track, @@ -65,13 +109,87 @@ static int mov_write_ttml_document_from_queue(AVFormatContext *s, int64_t start_ts = track->start_dts == AV_NOPTS_VALUE ? 0 : (track->start_dts + track->track_duration); int64_t end_ts = start_ts; + unsigned int time_limited = 0; + PacketList back_to_queue_list = { 0 }; + + if (*out_start_ts != AV_NOPTS_VALUE) { + // we have non-nopts values here, thus we have been given a time range + time_limited = 1; + start_ts = *out_start_ts; + end_ts = *out_start_ts + *out_duration; + } if ((ret = avformat_write_header(ttml_ctx, NULL)) < 0) { return ret; } while (!avpriv_packet_list_get(&track->squashed_packet_queue, pkt)) { - end_ts = FFMAX(end_ts, pkt->pts + pkt->duration); + unsigned int stop_at_current_packet = 0; + int64_t pts_before = pkt->pts; + int64_t duration_before = pkt->duration; + + if (time_limited) { + // special cases first: + if (pkt->pts + pkt->duration < start_ts) { + // too late for our fragment, unfortunately + // unref and proceed to next packet in queue. + av_log(s, AV_LOG_WARNING, + "Very late TTML packet in queue, dropping packet with " + "pts: %"PRId64", duration: %"PRId64"\n", + pkt->pts, pkt->duration); + av_packet_unref(pkt); + goto next_iteration; + } else if (pkt->pts >= end_ts) { + // starts after this fragment, put back to original queue + ret = avpriv_packet_list_put(&track->squashed_packet_queue, + pkt, av_packet_ref, + FF_PACKETLIST_FLAG_PREPEND); + if (ret < 0) + goto cleanup; + + stop_at_current_packet = 1; + goto next_iteration; + } + + // limit packet pts to start_ts + if (pkt->pts < start_ts) { + pkt->duration -= start_ts - pkt->pts; + pkt->pts = start_ts; + } + + if (pkt->pts + pkt->duration > end_ts) { + // goes over our current fragment, create duplicate and + // put it back to list after iteration has finished in + // order to handle multiple subtitles at the same time. + int64_t offset = end_ts - pkt->pts; + + ret = avpriv_packet_list_put(&back_to_queue_list, + pkt, av_packet_ref, + FF_PACKETLIST_FLAG_PREPEND); + if (ret < 0) + goto cleanup; + + back_to_queue_list.head->pkt.pts = + back_to_queue_list.head->pkt.dts = + back_to_queue_list.head->pkt.pts + offset; + back_to_queue_list.head->pkt.duration -= offset; + + // and for our normal packet we just set duration to offset + pkt->duration = offset; + } + } else { + end_ts = FFMAX(end_ts, pkt->pts + pkt->duration); + } + + av_log(s, AV_LOG_TRACE, + "TTML packet writeout: pts: %"PRId64" (%"PRId64"), " + "duration: %"PRId64"\n", + pkt->pts, pkt->pts - start_ts, pkt->duration); + if (pkt->pts != pts_before || pkt->duration != duration_before) { + av_log(s, AV_LOG_TRACE, + "Adjustments: pts: %"PRId64", duration: %"PRId64"\n", + pkt->pts - pts_before, pkt->duration - duration_before); + } // in case of the 'dfxp' muxing mode, each written document is offset // to its containing sample's beginning. @@ -89,6 +207,10 @@ static int mov_write_ttml_document_from_queue(AVFormatContext *s, } av_packet_unref(pkt); + +next_iteration: + if (stop_at_current_packet) + break; } if ((ret = av_write_trailer(ttml_ctx)) < 0) @@ -100,15 +222,30 @@ static int mov_write_ttml_document_from_queue(AVFormatContext *s, ret = 0; cleanup: + while (!avpriv_packet_list_get(&back_to_queue_list, pkt)) { + ret = avpriv_packet_list_put(&track->squashed_packet_queue, + pkt, av_packet_ref, + FF_PACKETLIST_FLAG_PREPEND); + + // unrelated to whether we succeed or not, we unref the packet + // received from the temporary list. + av_packet_unref(pkt); + + if (ret < 0) { + avpriv_packet_list_free(&back_to_queue_list); + break; + } + } return ret; } int ff_mov_generate_squashed_ttml_packet(AVFormatContext *s, MOVTrack *track, AVPacket *pkt) { + MOVMuxContext *mov = s->priv_data; AVFormatContext *ttml_ctx = NULL; // values for the generated AVPacket - int64_t start_ts = 0; + int64_t start_ts = AV_NOPTS_VALUE; int64_t duration = 0; int ret = AVERROR_BUG; @@ -119,12 +256,30 @@ int ff_mov_generate_squashed_ttml_packet(AVFormatContext *s, goto cleanup; } + if (mov->flags & FF_MOV_FLAG_FRAGMENT) { + int64_t calculated_start = AV_NOPTS_VALUE; + int64_t calculated_end = AV_NOPTS_VALUE; + + mov_calculate_start_and_end_of_other_tracks(s, track, &calculated_start, &calculated_end); + + if (calculated_start != AV_NOPTS_VALUE) { + start_ts = calculated_start; + duration = calculated_end - calculated_start; + av_log(s, AV_LOG_VERBOSE, + "Calculated subtitle fragment start: %"PRId64", " + "duration: %"PRId64"\n", + start_ts, duration); + } + } + if (!track->squashed_packet_queue.head) { // empty queue, write minimal empty document with zero duration avio_write(ttml_ctx->pb, empty_ttml_document, sizeof(empty_ttml_document) - 1); - start_ts = 0; - duration = 0; + if (start_ts == AV_NOPTS_VALUE) { + start_ts = 0; + duration = 0; + } goto generate_packet; }