From patchwork Wed Jan 1 00:58:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 17087 Delivered-To: andriy.gelman@gmail.com Received: by 2002:a05:6214:1865:0:0:0:0 with SMTP id eh5csp220055qvb; Tue, 31 Dec 2019 17:01:47 -0800 (PST) X-Google-Smtp-Source: APXvYqwL4TIaQTuOZ5tR9KB9YUBTsQ1IP0V01CeaBY87RKH5nibOlIA5EB+OfYFujRBb/lCEQNO1 X-Received: by 2002:a50:fb90:: with SMTP id e16mr80353873edq.64.1577840506916; Tue, 31 Dec 2019 17:01:46 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1577840506; cv=none; d=google.com; s=arc-20160816; b=oPXQTjJgKYICc4a9XBdCgyiq/94rh7+bhhYkgCiefE6uymQ8QpDLXzaCupkCaEwP2u BKgCTdsSR9tsBGrgBlGY2L1wNNN0lamCQLdZlYwZFhuNUFcZMX9UqjCX8akX3MA9BHS5 iJGuiV8gs3wpGhEkJQDfaGwMu+27NP/ubq3LlafpCHV98nHBwLTVsHpeb9rAST2F2OrS KvJAnhUCQumcsVujHMqEnIWCRkzUVHu312j/N4bhHVdv1qRkYVaAYWaG2R/ZdDiMN6oM ELFKyMjWjf9lknvs1SWNhw6ahoCbUsLNI3Mh5ALnrIELHJcHABFAdyfgiXWjq5wvmpQS 5Rfg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc: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=KhOLrEJzYjNmwYxZiO0Z/xWd6eqEtK9xByZFLP8MGts=; b=1BmCvV3BCtYCkaR5p9PsrQflHViHvSrmCojvoGw1wEaOA6UY2bbRf2A5/GFyte13fI SjxfOGMtjnpO42QVuMe5lGP2kCzsC/2i0zujFcAUlMnra3yXWZSX9KqmlJ1d5d3GxKaC 8i1Pkw6JgFCyX08C0mFFRV71DoRscXw1Nu6K+fOzH+B2eu7dJ9JW+RXurhGZsTsNUJC2 oD2YD/uKhIPj5cHEf2DEt+LxuWFKnrKQRkltLmNyD/9gwZhTgyDH3VNmE2soWtU4K771 4bEQ9En4EKcb7nwKSQ8vwlN1uvyZ5R5TpV4TSSrOvO/40AABs+BnV0+YGRTd+2KLYA3Y EZwg== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=k6ICt8SW; 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 t17si34728554edt.379.2019.12.31.17.01.46; Tue, 31 Dec 2019 17:01:46 -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=20161025 header.b=k6ICt8SW; 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 B188E68AD57; Wed, 1 Jan 2020 02:59:26 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f68.google.com (mail-wm1-f68.google.com [209.85.128.68]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5373068AC3F for ; Wed, 1 Jan 2020 02:59:16 +0200 (EET) Received: by mail-wm1-f68.google.com with SMTP id m24so2819557wmc.3 for ; Tue, 31 Dec 2019 16:59:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=/SM5FzkVQCqHr4FIchXv3lzquYIGkfkjO9l05skGgbw=; b=k6ICt8SW8SfWLHDk/A5TGUR+yj0RzcfGdeXzXpypUwbDJrNaIY31s0tyVZS6NAiTF2 5eNwZLo5MTmTHdiKWS1T9DCmFe85BSeeIkI/4hfDoXphhA2bRLdes6TlUGWUG8F2BzKz C90FLx1Zg6LLCM+h5/rRbhYSo6oFUJ7MfTW7WTE2i58zD1BSyfiSd11EbJV/A7UtF9DP Wy6rI9bueGItoFXoVDxux7Yc1OlDENAoWvzGMtT3R4JjTrXxD7A2te5FlUS95IxQP16Y FFBuKnLBXuf8/z8tJ2T4g085vizTXVppfAgDyfpykWQunABHcJ12617SoyrAhUuMqtTI Bdjg== 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:in-reply-to :references:mime-version:content-transfer-encoding; bh=/SM5FzkVQCqHr4FIchXv3lzquYIGkfkjO9l05skGgbw=; b=uiegCNa2a5g0bLqdzWOhn2fFY30SUPhQJpxwnc2/CfyI0v55ZBKos+skUKaqAQ+0Y8 BXK8lO2f/3M8F9KU4siGQcS7SBOsAzLb/epqozL0rFFbkCHkInVA/LaB3fwqUgrM2KZp jGADfrr4lWtp1mPnouxMCzq2dzOmY5vFY/q2ZVuiIjnzUGsbNPK9gyaTSsEklSL1ITCt Y9u1CK9N68XoCPApYituUFFOGX/Nxu4xkVVS97paSHlHl/GLXqyBggZ3s2PQNApy/WqC Kh/LHPXWU6wWU6p2/52v9T2uH2zB0zsWZnkYxE1cKlCo8MwbyPuqlRUORXmN8xF5yHac V4Iw== X-Gm-Message-State: APjAAAXFoENMSn28zVlFiOhNZ0GB4/3+vJCLdvkFOvacSvxP/6l/x1Bm 72gm1RYn1MK3a9DpFF1zzZoOpzW2 X-Received: by 2002:a1c:a404:: with SMTP id n4mr6026925wme.109.1577840355547; Tue, 31 Dec 2019 16:59:15 -0800 (PST) Received: from sblaptop.fritz.box (ipbcc08bbf.dynamic.kabel-deutschland.de. [188.192.139.191]) by smtp.gmail.com with ESMTPSA id w17sm52431655wrt.89.2019.12.31.16.59.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 31 Dec 2019 16:59:15 -0800 (PST) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Wed, 1 Jan 2020 01:58:35 +0100 Message-Id: <20200101005837.11356-19-andreas.rheinhardt@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200101005837.11356-1-andreas.rheinhardt@gmail.com> References: <20200101005837.11356-1-andreas.rheinhardt@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 18/20] avformat/matroskaenc: Don't fail if reserved Cues space doesn't suffice 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" X-TUID: HtFdiWP8mzTS Content-Length: 9350 When the user opted to write the Cues at the beginning, the Cues were simply written without checking in advance whether enough space has been reserved for them. If it wasn't enough, the data following the space reserved for the Cues was simply overwritten, corrupting the file. This commit changes this by checking whether enough space has been reserved for the Cues before outputting anything. If it isn't enough, the Cues will be output at the end as usual. Signed-off-by: Andreas Rheinhardt --- doc/muxers.texi | 4 +- libavformat/matroskaenc.c | 79 ++++++++++++++++++++------------------- 2 files changed, 43 insertions(+), 40 deletions(-) diff --git a/doc/muxers.texi b/doc/muxers.texi index 5d7ff1ab3b..9eca32c1ca 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -1314,8 +1314,8 @@ index at the beginning of the file. If this option is set to a non-zero value, the muxer will reserve a given amount of space in the file header and then try to write the cues there when the muxing -finishes. If the available space does not suffice, muxing will fail. A safe size -for most use cases should be about 50kB per hour of video. +finishes. If the reserved space does not suffice, the Cues will be written at +the end. A safe size for most use cases should be about 50kB per hour of video. Note that cues are only written if the output is seekable and this option will have no effect if it is not. diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index d7aa832eb3..4e739d245b 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -503,23 +503,15 @@ static int mkv_add_cuepoint(MatroskaMuxContext *mkv, int stream, int tracknum, i return 0; } -static int64_t mkv_write_cues(AVFormatContext *s, mkv_cues *cues, mkv_track *tracks, int num_tracks) +static int mkv_assemble_cues(AVStream **streams, AVIOContext *dyn_cp, + mkv_cues *cues, mkv_track *tracks, int num_tracks) { - MatroskaMuxContext *mkv = s->priv_data; - AVIOContext *dyn_cp, *pb = s->pb, *cuepoint; - int64_t currentpos; + AVIOContext *cuepoint; int ret; - currentpos = avio_tell(pb); - ret = start_ebml_master_crc32(&dyn_cp, mkv); - if (ret < 0) - return ret; - ret = avio_open_dyn_buf(&cuepoint); - if (ret < 0) { - ffio_free_dyn_buf(&dyn_cp); + if (ret < 0) return ret; - } for (mkv_cuepoint *entry = cues->entries, *end = entry + cues->num_entries; entry < end;) { @@ -538,7 +530,7 @@ static int64_t mkv_write_cues(AVFormatContext *s, mkv_cues *cues, mkv_track *tra int idx = entry->stream_idx; av_assert0(idx >= 0 && idx < num_tracks); - if (tracks[idx].has_cue && s->streams[idx]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) + if (tracks[idx].has_cue && streams[idx]->codecpar->codec_type != AVMEDIA_TYPE_SUBTITLE) continue; tracks[idx].has_cue = 1; track_positions = start_ebml_master(cuepoint, MATROSKA_ID_CUETRACKPOSITION, MAX_CUETRACKPOS_SIZE); @@ -554,9 +546,8 @@ static int64_t mkv_write_cues(AVFormatContext *s, mkv_cues *cues, mkv_track *tra ffio_reset_dyn_buf(cuepoint); } ffio_free_dyn_buf(&cuepoint); - end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CUES); - return currentpos; + return 0; } static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb, AVCodecParameters *par) @@ -2457,7 +2448,7 @@ static int mkv_write_trailer(AVFormatContext *s) { MatroskaMuxContext *mkv = s->priv_data; AVIOContext *pb = s->pb; - int64_t currentpos, cuespos; + int64_t currentpos; int ret; // check if we have an audio packet cached @@ -2480,33 +2471,45 @@ static int mkv_write_trailer(AVFormatContext *s) if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) { + int64_t ret64; + if (mkv->cues.num_entries) { - if (mkv->reserve_cues_space) { - int64_t cues_end; - - currentpos = avio_tell(pb); - avio_seek(pb, mkv->cues_pos, SEEK_SET); - - cuespos = mkv_write_cues(s, &mkv->cues, mkv->tracks, s->nb_streams); - cues_end = avio_tell(pb); - if (cues_end > cuespos + mkv->reserve_cues_space) { - av_log(s, AV_LOG_ERROR, - "Insufficient space reserved for cues: %d " - "(needed: %" PRId64 ").\n", - mkv->reserve_cues_space, cues_end - cuespos); - return AVERROR(EINVAL); - } + AVIOContext *cues; + uint64_t size; - if (cues_end < cuespos + mkv->reserve_cues_space) - put_ebml_void(pb, mkv->reserve_cues_space - - (cues_end - cuespos)); + ret = start_ebml_master_crc32(&cues, mkv); + if (ret < 0) + return ret; + ret = mkv_assemble_cues(s->streams, cues, &mkv->cues, + mkv->tracks, s->nb_streams); + if (ret < 0) + return ret; + + if (mkv->reserve_cues_space) { + size = avio_tell(cues); + size += 4 + ebml_num_size(size); + if (mkv->reserve_cues_space < size) { + av_log(s, AV_LOG_WARNING, + "Insufficient space reserved for Cues: %d < " + "%"PRIu64". Writing Cues at the end of the file.\n", + mkv->reserve_cues_space, size); + mkv->reserve_cues_space = 0; + } else { + currentpos = avio_tell(pb); + if ((ret64 = avio_seek(pb, mkv->cues_pos, SEEK_SET)) < 0) { + ffio_free_dyn_buf(&cues); + return ret64; + } + } + } + mkv_add_seekhead_entry(mkv, MATROSKA_ID_CUES, avio_tell(pb)); + end_ebml_master_crc32(pb, &cues, mkv, MATROSKA_ID_CUES); + if (mkv->reserve_cues_space) { + if (size < mkv->reserve_cues_space) + put_ebml_void(pb, mkv->reserve_cues_space - size); avio_seek(pb, currentpos, SEEK_SET); - } else { - cuespos = mkv_write_cues(s, &mkv->cues, mkv->tracks, s->nb_streams); } - - mkv_add_seekhead_entry(mkv, MATROSKA_ID_CUES, cuespos); } currentpos = avio_tell(pb);