From patchwork Sat May 2 17:16:58 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 19440 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 034A044BB45 for ; Sat, 2 May 2020 20:17:59 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id DDE6A68C8A5; Sat, 2 May 2020 20:17:58 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f66.google.com (mail-wm1-f66.google.com [209.85.128.66]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 85AB068C884 for ; Sat, 2 May 2020 20:17:51 +0300 (EEST) Received: by mail-wm1-f66.google.com with SMTP id y24so3776682wma.4 for ; Sat, 02 May 2020 10:17:51 -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:in-reply-to:references :mime-version:content-transfer-encoding; bh=vbhMcFeHTHBzynHHw9flcT8LCFK9Hg27Wx/Z0DNMz3c=; b=oBHh27b8E3vy3TTtbyWOhOJm52L3f1j6sVFwtLF+0siGzZFbHeWQ0enoqBvn2zqR1D /tqqzkdOLRsxWtuxliqhCV7Vl4UMpvfl2XWmYJypJxgGjY3wpKdlWXzIulTN4yook7vZ TH1lgQl/BRoo6kq1Qt6mz7JdBoWroMWcTo0jm1A1BsvWTBo1/yuplxZoUPMcIz9arhtl eQUClB8acUCsxUNNJte7atlK6A5nZDU5dwSUGWckL0xoIo+Mh/XDH2nxgHg8s5vwvB4L bux1oldI8NN1OiEbY8kyA90WfdWG99RpRMp+YwE06/zWRBr9v4zB9jYNHPeHq829yCuJ gfCA== 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=vbhMcFeHTHBzynHHw9flcT8LCFK9Hg27Wx/Z0DNMz3c=; b=AyKEXQp6goujuyZ6obycliNrj/uFATFcDeCT9Kplqnz4D0KZf9OoRS/VqaPo7i4oJb qcQGHCA0fv8zbf09zIyxwDoh2F+33A9GNchHmvdakXGddfub+E+sBxFFiZrDx/Wxg/1e 2JH0mFQEI0Wk6Sd3kVOsbyt8vKoNgTWzU9jDtJwzsnN492JrIZYhm3DUcYT6il4YOmoZ uiPZjarHem2myQanJc1WyGSaSOJtv6K2Pc7U/8nkzAf/QAlLHSUUKdihbUQiIK1PtgOV 1FPNnXfjGk+3Xv3n5SScpYm77sKdwzoLi3CMuE6s44pNwyfLTq0aOl3QO8kFcD5PtjpX 1wgw== X-Gm-Message-State: AGi0PuanGTBoiMld6OH7O1WBoFG4yD5cGtmI1+NwTTctIoI5kNOkmzdy etrV+q3nX5FO/yJ5+n5LF5d7b68h X-Google-Smtp-Source: APiQypJiGPLsu91QPGzOBBQVicWWEqwQGw4MgKjIG32//XHEsIXNOww8wD1Ga0KnjWypqM9JF9wYAg== X-Received: by 2002:a1c:49:: with SMTP id 70mr5116598wma.184.1588439870660; Sat, 02 May 2020 10:17:50 -0700 (PDT) Received: from sblaptop.fritz.box (ipbcc1ab57.dynamic.kabel-deutschland.de. [188.193.171.87]) by smtp.gmail.com with ESMTPSA id u74sm5241524wmu.13.2020.05.02.10.17.49 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 10:17:50 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Sat, 2 May 2020 19:16:58 +0200 Message-Id: <20200502171700.28991-6-andreas.rheinhardt@gmail.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200429222156.29129-1-andreas.rheinhardt@gmail.com> References: <20200429222156.29129-1-andreas.rheinhardt@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 11/13] avformat/matroskaenc: Avoid unnecessary seek 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" The Matroska muxer has a pair of functions designed to write master elements whose exact length is not known in advance: start_ebml_master() and end_ebml_master(). The first one of these would write the EBML ID of the master element that is about to be started, reserve some bytes for the length field and record the current position as well as how many bytes were used for the length field. When writing the master's contents is finished, end_ebml_master() gets the current position (at the end of the master element), seeks to the length field using the recorded position, writes the length field and seeks back to the end of the master element so that one can continue writing other elements. But if one wants to modify the content of the master element itself, then the seek back is superfluous. This is the scenario that presents itself when writing the trailer: One wants to update several elements contained in the Segment master element (this is the main/root master element of a Matroska file) that were already written when writing the header. The current approach is to seek to the beginning of the file to update the elements, then seek to the end, call end_ebml_master() which immediately seeks to the beginning to write the length and seeks back. The seek to the end (which has only been performed because end_ebml_master() uses the initial position to determine the length of the master element) and the seek back are of course superfluous. This commit avoids these seeks by no longer using start/end_ebml_master() to write the segment's length field. Instead, they are now written manually. The new approach is: Seek to the beginning to write the length field, then update the elements (in the order they appear in the file) and seek back to the end. This reduces the ordinary amount of seeks of the Matroska muxer to two (ordinary excludes scenarios where one has big Chapters or Attachments or where one writes the Cues at the front). Signed-off-by: Andreas Rheinhardt --- Does one actually have to seek back to the end at the end? libavformat/matroskaenc.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index e9b2be3d42..dfc1563fc1 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -126,7 +126,6 @@ typedef struct MatroskaMuxContext { ebml_stored_master info; ebml_stored_master track; ebml_stored_master tags; - ebml_master segment; int64_t segment_offset; AVIOContext *cluster_bc; int64_t cluster_pos; ///< file offset of the current cluster @@ -1817,7 +1816,8 @@ static int mkv_write_header(AVFormatContext *s) put_ebml_uint (pb, EBML_ID_DOCTYPEREADVERSION, 2); end_ebml_master(pb, ebml_header); - mkv->segment = start_ebml_master(pb, MATROSKA_ID_SEGMENT, 0); + put_ebml_id(pb, MATROSKA_ID_SEGMENT); + put_ebml_size_unknown(pb, 8); mkv->segment_offset = avio_tell(pb); // we write a seek head at the beginning to point to all other level @@ -2542,6 +2542,10 @@ static int mkv_write_trailer(AVFormatContext *s) } after_cues: + if ((ret64 = avio_seek(pb, mkv->segment_offset - 8, SEEK_SET)) < 0) + return ret64; + put_ebml_length(pb, endpos - mkv->segment_offset, 8); + ret = mkv_write_seekhead(pb, mkv, 1, mkv->info.pos); if (ret < 0) return ret; @@ -2599,8 +2603,6 @@ static int mkv_write_trailer(AVFormatContext *s) avio_seek(pb, endpos, SEEK_SET); - end_ebml_master(pb, mkv->segment); - return ret2; }