From patchwork Tue Mar 16 08:29:52 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 26409 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 6242F44B21B for ; Tue, 16 Mar 2021 10:30:09 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 3DA9A68AF1C; Tue, 16 Mar 2021 10:30:09 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-ej1-f47.google.com (mail-ej1-f47.google.com [209.85.218.47]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id B955268AEA7 for ; Tue, 16 Mar 2021 10:30:02 +0200 (EET) Received: by mail-ej1-f47.google.com with SMTP id p8so70654799ejb.10 for ; Tue, 16 Mar 2021 01:30:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:reply-to:mime-version :content-transfer-encoding; bh=Y8qAb2FqSGwjN5d3Ry1dt+PBcRjbMYf6dC9vLFP2jf0=; b=CUJu7XNxDNCfymt2GfhJSzF21E+a5nLIV3d7khytahlFrCOcS5/GO+wtPDhbbtqpxZ WRvSxILppyQwwnlBt9OKpZI6QzTlUoEydD1u1SnuZFaMERZwThVNDAgXW42b9HjVF2VQ 4Ns3sP9nOoMCk9VsxnKN7jRw8ynZFpDDn8/HVEtolgbmvH/favhWSeyiObXAPXBcoLOU Rm3qD6tfht9i++MB3Papqf0oreTVNu/hgYlECp2J4t4/5A0zZuHn4DnXTHdjiX51PA++ izN9FIy9vmgChWDp8VwfpmIgSr9lTbEw/YA/IjhYYWoeW9RoNe9vUzwZ+NpRRONHxEl2 oZBA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :mime-version:content-transfer-encoding; bh=Y8qAb2FqSGwjN5d3Ry1dt+PBcRjbMYf6dC9vLFP2jf0=; b=KtQEJfQp83EV7ylh2yIbS9cC2u9VAydmpWh4AG7eIHCRlKHRfuwy0M/yzQ3f7EZAOf AEn4SYvNIY3JLxvmGRNPIpt72d65SEu3vKF/A58I8vWsKXxIeD9ESr45DuKEvOv4pGgJ h8PEDXXQBYkBlHI3M6rB2Ifb7HiN3GxWTRAtluz7oKa2ZEAzmXSTaAfgeVlmxmzQiGCj ZZ02UI/CUJLOEEr1l/1FVk6LW6B5pAcqxv0qOqnXoAcDCvCUmQCvLHcyQDiHMxSI9seN QpfNuF41uN18DxHUgoNZ4sHiGS+J3PHytF7SaEwNW+juRRKQhkYg2fzMb123A43YSKg+ dJkA== X-Gm-Message-State: AOAM532L0nnIjwkgq86ld1TFQ50FxAeWsKfXIvgEMdzJep37CiMzV+T2 QONTq7wNqxEqfKJG5mYQIu1OqvNI2S1glw== X-Google-Smtp-Source: ABdhPJw33tDsUkzBvnF/65UlECPuC8aFFWby7JZPv1cW8npNpjyS8VazpOw+Wmq+tUYYRYh4st9SWA== X-Received: by 2002:a17:906:b20b:: with SMTP id p11mr28804972ejz.0.1615883401956; Tue, 16 Mar 2021 01:30:01 -0700 (PDT) Received: from sblaptop.fritz.box (ipbcc08960.dynamic.kabel-deutschland.de. [188.192.137.96]) by smtp.gmail.com with ESMTPSA id y9sm8882757ejd.110.2021.03.16.01.30.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 16 Mar 2021 01:30:01 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Tue, 16 Mar 2021 09:29:52 +0100 Message-Id: <20210316082953.273550-1-andreas.rheinhardt@gmail.com> X-Mailer: git-send-email 2.27.0 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/2] avformat/matroskaenc: Check chapter ids for duplicates 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 Cc: Andreas Rheinhardt Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Up until now, there has been no check that each chapter has a unique id; there was only a check for whether a chapter id is zero (this happens often when the chapters originated from a format that lacks the concept of chapter id and simply counts from zero) which is invalid in Matroska. In this case the chapter ids are offset by 1 to make them nonnegative. Yet offsetting won't fix duplicate ids, therefore this is changed to simply create new chapter uids when the input chapter uids don't conform to the requirements of Matroska (in which case it can be presumed that they did not originate from Matroska, so that we don't need to bother to preserve them). Signed-off-by: Andreas Rheinhardt --- libavformat/matroskaenc.c | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 1749b7fd37..8f29d64e72 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -1625,24 +1625,29 @@ static int mkv_write_tags(AVFormatContext *s) return 0; } +static int mkv_new_chapter_ids_needed(const AVFormatContext *s) +{ + for (unsigned i = 0; i < s->nb_chapters; i++) { + if (!s->chapters[i]->id) + return 1; + for (unsigned j = 0; j < i; j++) + if (s->chapters[j]->id == s->chapters[i]->id) + return 1; + } + return 0; +} + static int mkv_write_chapters(AVFormatContext *s) { MatroskaMuxContext *mkv = s->priv_data; AVIOContext *dyn_cp = NULL, *dyn_tags = NULL, **tags, *pb = s->pb; ebml_master editionentry; - uint64_t chapter_id_offset = 0; AVRational scale = {1, 1E9}; - int i, ret; + int ret, create_new_ids; if (!s->nb_chapters || mkv->wrote_chapters) return 0; - for (i = 0; i < s->nb_chapters; i++) - if (!s->chapters[i]->id) { - chapter_id_offset = 1; - break; - } - ret = start_ebml_master_crc32(&dyn_cp, mkv); if (ret < 0) return ret; @@ -1656,12 +1661,15 @@ static int mkv_write_chapters(AVFormatContext *s) } else tags = NULL; - for (i = 0; i < s->nb_chapters; i++) { + create_new_ids = mkv_new_chapter_ids_needed(s); + + for (unsigned i = 0; i < s->nb_chapters; i++) { ebml_master chapteratom, chapterdisplay; const AVChapter *c = s->chapters[i]; int64_t chapterstart = av_rescale_q(c->start, c->time_base, scale); int64_t chapterend = av_rescale_q(c->end, c->time_base, scale); const AVDictionaryEntry *t; + uint64_t uid = create_new_ids ? i + 1ULL : (uint32_t)c->id; if (chapterstart < 0 || chapterstart > chapterend || chapterend < 0) { av_log(s, AV_LOG_ERROR, "Invalid chapter start (%"PRId64") or end (%"PRId64").\n", @@ -1671,8 +1679,7 @@ static int mkv_write_chapters(AVFormatContext *s) } chapteratom = start_ebml_master(dyn_cp, MATROSKA_ID_CHAPTERATOM, 0); - put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERUID, - (uint32_t)c->id + chapter_id_offset); + put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERUID, uid); put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMESTART, chapterstart); put_ebml_uint(dyn_cp, MATROSKA_ID_CHAPTERTIMEEND, chapterend); if ((t = av_dict_get(c->metadata, "title", NULL, 0))) { @@ -1685,8 +1692,7 @@ static int mkv_write_chapters(AVFormatContext *s) if (tags && mkv_check_tag(c->metadata, MATROSKA_ID_TAGTARGETS_CHAPTERUID)) { ret = mkv_write_tag(mkv, c->metadata, tags, NULL, - MATROSKA_ID_TAGTARGETS_CHAPTERUID, - (uint32_t)c->id + chapter_id_offset); + MATROSKA_ID_TAGTARGETS_CHAPTERUID, uid); if (ret < 0) goto fail; }