From patchwork Wed Apr 29 22:21:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 19383 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 02A5944B57C for ; Thu, 30 Apr 2020 01:22:13 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id D57C768C1E3; Thu, 30 Apr 2020 01:22:12 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f67.google.com (mail-wm1-f67.google.com [209.85.128.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 69D4868C099 for ; Thu, 30 Apr 2020 01:22:06 +0300 (EEST) Received: by mail-wm1-f67.google.com with SMTP id x25so3790965wmc.0 for ; Wed, 29 Apr 2020 15:22:06 -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:mime-version :content-transfer-encoding; bh=clMGnfpnRuvDrIhFOXO8HXqGPGt2ZIDAkONCpoJj9JM=; b=WOThSfOuAWdWptLHB7My6ZN4YPFj2BEeE7MfL62k/ENlObja6FJ/qKn+6KQcX9bR9l ssqlUVpUlIoKlDa7lA9MYsL5e5N3APQPYFwiDyrOdasZRODA7iIYx+04lHRvOGk03PnY bpA9Os3uVxyYW2Y/AEooe9U55NVwbp4s40KSQm37vHKgotc5/TYFY+O644Lvpf443X0I okDkZ0beBZr+eO2f4pDnhAASWqZcIyOS7MNz6XxxQY7Y3FId2zi3EreDwW+OYb+0sitj sLZfYaGjkqKjXT9zTICMA1DGNHJsVXCTdLxgMcdXcgKVBmm5L492h2zTVtSO/HdwvgyT 2m0A== 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:mime-version :content-transfer-encoding; bh=clMGnfpnRuvDrIhFOXO8HXqGPGt2ZIDAkONCpoJj9JM=; b=riyj9bmeaNQ/PlpewmPnDuIsjHFKDAKy9n/M1Jdf5qXMY5E0viGU3dTAfFu8MexL1z gIw0XMdpAp0G4RaRyB8cXtqyrKKGVKBbiK6Bk9xi9yDVUTMdycaaQA245FgI13PF8ede ypAJhR3vxU434lYWZAQw/0qKSc2vPZHmHW9jBNgDfT+CYbrrIECKdL5JBWIkYeOr6RhA HhmTv0vObajPImmiFciSmDVQgXBAq8OVWES/3pnvhLue4UugCg2WUYIzOdtQv8Ikzfrb mECX7a/QiOwlUgqdIsOMVwQ08q5bmnsxzRlJnpcR6+C1nicdsZpakM3TBBvFZY3N9cBT aaCg== X-Gm-Message-State: AGi0PuZ4OJ2viPRyK2R/EJx1VZfEXCmzz5KBquiJYWdId4PvFAu+hrKT O4mCfOaqJCVh1ur3cZR95k7FvPh8 X-Google-Smtp-Source: APiQypJzadrBKAdXUQJdCBbBwnOqFRF67DWrbGJO157cxoBHnAghZlarzSP+5lzVWGcyMBgl5NFZuw== X-Received: by 2002:a1c:7f91:: with SMTP id a139mr42634wmd.164.1588198925397; Wed, 29 Apr 2020 15:22:05 -0700 (PDT) Received: from sblaptop.fritz.box (ipbcc1ab57.dynamic.kabel-deutschland.de. [188.193.171.87]) by smtp.gmail.com with ESMTPSA id x6sm1071555wrg.58.2020.04.29.15.22.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Apr 2020 15:22:04 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Thu, 30 Apr 2020 00:21:51 +0200 Message-Id: <20200429222156.29129-1-andreas.rheinhardt@gmail.com> X-Mailer: git-send-email 2.20.1 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/6] avformat/matroskaenc: Move adding SeekEntry into end_ebml_master_crc32() 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, SeekEntries were already added before start_ebml_master_crc32() was even called and before we were actually sure that we really write the element the SeekHead references; after all, we might also error out later; and given that the allocations implicit in dynamic buffers should be checked, end_ebml_master_crc32() will eventually have to return errors itself, so that it is the right place to add SeekHead entries. The earlier behaviour is of course a remnant of the time in which start_ebml_master_crc32() really did output something, so that the position before start_ebml_master_crc32() needed to be recorded. Erroring out later is also not as dangerous as it seems because in this case no SeekHead will be written (if it happened when writing the header, the whole muxing process would abort; if it happened when writing the trailer (when writing chapters not available initially), writing the trailer would be aborted and no SeekHead containing the bogus chapter entry would be written). This commit does not change the way the SeekEntries are added for those elements that are output preliminarily; this is so because the SeekHead is written before those elements are finally output and doing it otherwise would increase the amount of seeks. Signed-off-by: Andreas Rheinhardt --- libavformat/matroskaenc.c | 64 ++++++++++++++++++++------------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index a1b613290c..b50fd8dd9b 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -349,6 +349,17 @@ static void end_ebml_master(AVIOContext *pb, ebml_master master) avio_seek(pb, pos, SEEK_SET); } +static void mkv_add_seekhead_entry(MatroskaMuxContext *mkv, uint32_t elementid, + uint64_t filepos) +{ + mkv_seekhead *seekhead = &mkv->seekhead; + + av_assert1(seekhead->num_entries < MAX_SEEKHEAD_ENTRIES); + + seekhead->entries[seekhead->num_entries].elementid = elementid; + seekhead->entries[seekhead->num_entries++].segmentpos = filepos - mkv->segment_offset; +} + static int start_ebml_master_crc32(AVIOContext **dyn_cp, MatroskaMuxContext *mkv) { int ret; @@ -364,11 +375,15 @@ static int start_ebml_master_crc32(AVIOContext **dyn_cp, MatroskaMuxContext *mkv static void end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp, MatroskaMuxContext *mkv, uint32_t id, - int length_size, int keep_buffer) + int length_size, int keep_buffer, + int add_seekentry) { uint8_t *buf, crc[4]; int size, skip = 0; + if (add_seekentry) + mkv_add_seekhead_entry(mkv, id, avio_tell(pb)); + put_ebml_id(pb, id); size = avio_get_dyn_buf(*dyn_cp, &buf); put_ebml_length(pb, size, length_size); @@ -441,17 +456,6 @@ static void mkv_start_seekhead(MatroskaMuxContext *mkv, AVIOContext *pb) put_ebml_void(pb, mkv->seekhead.reserved_size); } -static void mkv_add_seekhead_entry(MatroskaMuxContext *mkv, uint32_t elementid, - uint64_t filepos) -{ - mkv_seekhead *seekhead = &mkv->seekhead; - - av_assert1(seekhead->num_entries < MAX_SEEKHEAD_ENTRIES); - - seekhead->entries[seekhead->num_entries].elementid = elementid; - seekhead->entries[seekhead->num_entries++].segmentpos = filepos - mkv->segment_offset; -} - /** * Write the SeekHead to the file at the location reserved for it * and seek to destpos afterwards. When error_on_seek_failure @@ -489,7 +493,7 @@ static int mkv_write_seekhead(AVIOContext *pb, MatroskaMuxContext *mkv, put_ebml_uint(dyn_cp, MATROSKA_ID_SEEKPOSITION, entry->segmentpos); end_ebml_master(dyn_cp, seekentry); } - end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_SEEKHEAD, 0, 0); + end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_SEEKHEAD, 0, 0, 0); remaining = seekhead->filepos + seekhead->reserved_size - avio_tell(pb); put_ebml_void(pb, remaining); @@ -1421,7 +1425,8 @@ static int mkv_write_tracks(AVFormatContext *s) end_ebml_master_crc32_preliminary(pb, mkv->tracks_bc, MATROSKA_ID_TRACKS, &mkv->tracks_pos); else - end_ebml_master_crc32(pb, &mkv->tracks_bc, mkv, MATROSKA_ID_TRACKS, 0, 0); + end_ebml_master_crc32(pb, &mkv->tracks_bc, mkv, + MATROSKA_ID_TRACKS, 0, 0, 0); return 0; } @@ -1443,8 +1448,6 @@ static int mkv_write_chapters(AVFormatContext *s) break; } - mkv_add_seekhead_entry(mkv, MATROSKA_ID_CHAPTERS, avio_tell(pb)); - ret = start_ebml_master_crc32(&dyn_cp, mkv); if (ret < 0) return ret; @@ -1481,7 +1484,7 @@ static int mkv_write_chapters(AVFormatContext *s) end_ebml_master(dyn_cp, chapteratom); } end_ebml_master(dyn_cp, editionentry); - end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CHAPTERS, 0, 0); + end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CHAPTERS, 0, 0, 1); mkv->wrote_chapters = 1; return 0; @@ -1682,7 +1685,8 @@ static int mkv_write_tags(AVFormatContext *s) end_ebml_master_crc32_preliminary(s->pb, mkv->tags_bc, MATROSKA_ID_TAGS, &mkv->tags_pos); else - end_ebml_master_crc32(s->pb, &mkv->tags_bc, mkv, MATROSKA_ID_TAGS, 0, 0); + end_ebml_master_crc32(s->pb, &mkv->tags_bc, mkv, + MATROSKA_ID_TAGS, 0, 0, 0); } return 0; } @@ -1713,8 +1717,6 @@ static int mkv_write_attachments(AVFormatContext *s) if (!mkv->nb_attachments) return 0; - mkv_add_seekhead_entry(mkv, MATROSKA_ID_ATTACHMENTS, avio_tell(pb)); - ret = start_ebml_master_crc32(&dyn_cp, mkv); if (ret < 0) return ret; @@ -1746,7 +1748,7 @@ static int mkv_write_attachments(AVFormatContext *s) put_ebml_uid(dyn_cp, MATROSKA_ID_FILEUID, track->uid); end_ebml_master(dyn_cp, attached_file); } - end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_ATTACHMENTS, 0, 0); + end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_ATTACHMENTS, 0, 0, 1); return 0; } @@ -1868,7 +1870,8 @@ static int mkv_write_header(AVFormatContext *s) end_ebml_master_crc32_preliminary(s->pb, mkv->info_bc, MATROSKA_ID_INFO, &mkv->info_pos); else - end_ebml_master_crc32(s->pb, &mkv->info_bc, mkv, MATROSKA_ID_INFO, 0, 0); + end_ebml_master_crc32(s->pb, &mkv->info_bc, mkv, + MATROSKA_ID_INFO, 0, 0, 0); pb = s->pb; ret = mkv_write_tracks(s); @@ -2153,7 +2156,8 @@ static void mkv_end_cluster(AVFormatContext *s) { MatroskaMuxContext *mkv = s->priv_data; - end_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv, MATROSKA_ID_CLUSTER, 0, 1); + end_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv, + MATROSKA_ID_CLUSTER, 0, 1, 0); if (!mkv->have_video) { for (unsigned i = 0; i < s->nb_streams; i++) mkv->tracks[i].has_cue = 0; @@ -2447,7 +2451,7 @@ static int mkv_write_trailer(AVFormatContext *s) if (mkv->cluster_bc) { end_ebml_master_crc32(pb, &mkv->cluster_bc, mkv, - MATROSKA_ID_CLUSTER, 0, 0); + MATROSKA_ID_CLUSTER, 0, 0, 0); } ret = mkv_write_chapters(s); @@ -2463,7 +2467,6 @@ static int mkv_write_trailer(AVFormatContext *s) if (mkv->cues.num_entries) { AVIOContext *cues = NULL; uint64_t size; - int64_t cuespos = endpos; int length_size = 0; ret = start_ebml_master_crc32(&cues, mkv); @@ -2490,7 +2493,6 @@ static int mkv_write_trailer(AVFormatContext *s) ffio_free_dyn_buf(&cues); goto after_cues; } else { - cuespos = mkv->cues_pos; if ((ret64 = avio_seek(pb, mkv->cues_pos, SEEK_SET)) < 0) { ffio_free_dyn_buf(&cues); return ret64; @@ -2506,9 +2508,8 @@ static int mkv_write_trailer(AVFormatContext *s) } } } - mkv_add_seekhead_entry(mkv, MATROSKA_ID_CUES, cuespos); end_ebml_master_crc32(pb, &cues, mkv, MATROSKA_ID_CUES, - length_size, 0); + length_size, 0, 1); if (mkv->reserve_cues_space) { if (size < mkv->reserve_cues_space) put_ebml_void(pb, mkv->reserve_cues_space - size); @@ -2525,13 +2526,13 @@ static int mkv_write_trailer(AVFormatContext *s) av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration); avio_seek(mkv->info_bc, mkv->duration_offset, SEEK_SET); put_ebml_float(mkv->info_bc, MATROSKA_ID_DURATION, mkv->duration); - end_ebml_master_crc32(pb, &mkv->info_bc, mkv, MATROSKA_ID_INFO, 0, 0); + end_ebml_master_crc32(pb, &mkv->info_bc, mkv, MATROSKA_ID_INFO, 0, 0, 0); if (mkv->tracks_bc) { // write Tracks master avio_seek(pb, mkv->tracks_pos, SEEK_SET); end_ebml_master_crc32(pb, &mkv->tracks_bc, mkv, - MATROSKA_ID_TRACKS, 0, 0); + MATROSKA_ID_TRACKS, 0, 0, 0); } // update stream durations @@ -2559,7 +2560,8 @@ static int mkv_write_trailer(AVFormatContext *s) } avio_seek(pb, mkv->tags_pos, SEEK_SET); - end_ebml_master_crc32(pb, &mkv->tags_bc, mkv, MATROSKA_ID_TAGS, 0, 0); + end_ebml_master_crc32(pb, &mkv->tags_bc, mkv, + MATROSKA_ID_TAGS, 0, 0, 0); } avio_seek(pb, endpos, SEEK_SET); From patchwork Wed Apr 29 22:21:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 19384 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 0FB4744B57C for ; Thu, 30 Apr 2020 01:22:32 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E6D1F68C205; Thu, 30 Apr 2020 01:22:31 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f67.google.com (mail-wm1-f67.google.com [209.85.128.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5941F68C1EE for ; Thu, 30 Apr 2020 01:22:25 +0300 (EEST) Received: by mail-wm1-f67.google.com with SMTP id u16so3799096wmc.5 for ; Wed, 29 Apr 2020 15:22:25 -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=wgfqXqg7fAJSNJxnJ7AGv2/5X/EjzUdFuVcVzUEPT2c=; b=QjpNeJQgb2cWvGC42gYy/SU4Bpb1vvJtd0vNE+QX++e3RN9U4EsrM/XLnG68TLbCGu 1XpIeOej8VOMz479eAfZCpTTIGqRvv/fuDcx4xQuHfUHnvQqaCJ3W08q6otC9PFcqXAS PvyCU7TRXkGzfuuqJfxQBphsbXrnUv0kdy3tE23NbQa/Rfg4AVuB6pIv+Al6HdxmIvmB SBVekfNevuI2/GUeGJVBJ+JVSRukyUgAyBDRbQxN7h8r4wloW3uEoK3g3F6axCsxzqC5 W2uPE0yvA3pKTWgK1CATjn25YrPr9JMOYZUo5m8IY9wfVU/BpbRKrtOamTfr0yBoNLU2 8ewQ== 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=wgfqXqg7fAJSNJxnJ7AGv2/5X/EjzUdFuVcVzUEPT2c=; b=r+9NaztmJCyCBUGbPT0I7YDVrS1O6xiwg7+F3f0oPd3ne0sB+LoKB5nuWhgf20FwsW Ra2ADfwgOHF+JCeKwpUFR1WvozDBv5WTYbnDq1004NPuyF7sN0mOhxU6d2IL5gRv3DIi rJzwfXXWvUXu+/ufUT5nhn9asRZReQJP/SIr7yLWyzMcGL86+NI5t63HjWQTXgWOoqUn Lh4LgDDv8/JvstuxvriNSOt4qClMvwat4s8qpF5KTOnioNQMyuzz9ZAWMWJVHMZOFYDr 5i9G0oymvHT8K0hihNCwQuiCowkLA17Qe8EiM7LwhqGP90H9mcE6XvY6cP0SS6yn227R dkrA== X-Gm-Message-State: AGi0PuYLo8RtSEA8/rfOQpInItw/bSzwZWoHLUwe3GCmcodibWMHA3Jn 7vDdYjl9MLHQ95HrEQRWYBYW3mR4 X-Google-Smtp-Source: APiQypLO/SbQHNuiEo9C5i6nHfwQ/cfRoiEFV4NawKL5CtjL5j0IWZt97kKaqpdj04PZkO4crcpaJw== X-Received: by 2002:a7b:c858:: with SMTP id c24mr32716wml.51.1588198944129; Wed, 29 Apr 2020 15:22:24 -0700 (PDT) Received: from sblaptop.fritz.box (ipbcc1ab57.dynamic.kabel-deutschland.de. [188.193.171.87]) by smtp.gmail.com with ESMTPSA id x6sm1071555wrg.58.2020.04.29.15.22.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Apr 2020 15:22:23 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Thu, 30 Apr 2020 00:21:52 +0200 Message-Id: <20200429222156.29129-2-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 2/6] avformat/matroskaenc: Unify writing level 1 elements preliminarily 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 updates several header elements when the output is seekable; if unseekable, the buffer containing the contents of the element is immediately freed after writing. Before this commit, there were three places doing exactly the same: Checking whether the output is seekable and calling the function that writes and frees or the function that just writes the EBML master. This has been unified; adding SeekHead entries for these elements has been unified, too. Signed-off-by: Andreas Rheinhardt --- There was unfortunately a naming collision: The MatroskaMuxContext already contains an element tracks, so I settled for track for the stored EBML master. libavformat/matroskaenc.c | 135 +++++++++++++++++--------------------- 1 file changed, 62 insertions(+), 73 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index b50fd8dd9b..31f75abc64 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -69,6 +69,11 @@ typedef struct ebml_master { int sizebytes; ///< how many bytes were reserved for the size } ebml_master; +typedef struct ebml_stored_master { + AVIOContext *bc; + int64_t pos; +} ebml_stored_master; + typedef struct mkv_seekhead_entry { uint32_t elementid; uint64_t segmentpos; @@ -115,12 +120,9 @@ typedef struct mkv_track { typedef struct MatroskaMuxContext { const AVClass *class; int mode; - AVIOContext *tags_bc; - int64_t tags_pos; - AVIOContext *info_bc; - int64_t info_pos; - AVIOContext *tracks_bc; - int64_t tracks_pos; + ebml_stored_master info; + ebml_stored_master track; + ebml_stored_master tags; ebml_master segment; int64_t segment_offset; AVIOContext *cluster_bc; @@ -402,19 +404,25 @@ static void end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp, } /** -* Complete ebml master without destroying the buffer, allowing for later updates -*/ -static void end_ebml_master_crc32_preliminary(AVIOContext *pb, AVIOContext *dyn_cp, - uint32_t id, int64_t *pos) + * Output EBML master. Keep the buffer if seekable, allowing for later updates. + * Furthermore always add a SeekHead Entry for this element. + */ +static void end_ebml_master_crc32_tentatively(AVIOContext *pb, + ebml_stored_master *elem, + MatroskaMuxContext *mkv, uint32_t id) { + if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) { uint8_t *buf; - int size = avio_get_dyn_buf(dyn_cp, &buf); + int size = avio_get_dyn_buf(elem->bc, &buf); - *pos = avio_tell(pb); + elem->pos = avio_tell(pb); + mkv_add_seekhead_entry(mkv, id, elem->pos); put_ebml_id(pb, id); put_ebml_length(pb, size, 0); avio_write(pb, buf, size); + } else + end_ebml_master_crc32(pb, &elem->bc, mkv, id, 0, 0, 1); } static void put_xiph_size(AVIOContext *pb, int size) @@ -433,9 +441,9 @@ static void mkv_deinit(AVFormatContext *s) av_packet_unref(&mkv->cur_audio_pkt); ffio_free_dyn_buf(&mkv->cluster_bc); - ffio_free_dyn_buf(&mkv->info_bc); - ffio_free_dyn_buf(&mkv->tracks_bc); - ffio_free_dyn_buf(&mkv->tags_bc); + ffio_free_dyn_buf(&mkv->info.bc); + ffio_free_dyn_buf(&mkv->track.bc); + ffio_free_dyn_buf(&mkv->tags.bc); av_freep(&mkv->cues.entries); av_freep(&mkv->tracks); @@ -1374,9 +1382,7 @@ static int mkv_write_tracks(AVFormatContext *s) if (mkv->nb_attachments == s->nb_streams) return 0; - mkv_add_seekhead_entry(mkv, MATROSKA_ID_TRACKS, avio_tell(pb)); - - ret = start_ebml_master_crc32(&mkv->tracks_bc, mkv); + ret = start_ebml_master_crc32(&mkv->track.bc, mkv); if (ret < 0) return ret; @@ -1416,17 +1422,13 @@ static int mkv_write_tracks(AVFormatContext *s) i == video_default_idx || i == audio_default_idx || i == subtitle_default_idx; ret = mkv_write_track(s, mkv, st, &mkv->tracks[i], - mkv->tracks_bc, is_default); + mkv->track.bc, is_default); if (ret < 0) return ret; } - if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) - end_ebml_master_crc32_preliminary(pb, mkv->tracks_bc, - MATROSKA_ID_TRACKS, &mkv->tracks_pos); - else - end_ebml_master_crc32(pb, &mkv->tracks_bc, mkv, - MATROSKA_ID_TRACKS, 0, 0, 0); + end_ebml_master_crc32_tentatively(pb, &mkv->track, mkv, + MATROSKA_ID_TRACKS); return 0; } @@ -1532,14 +1534,12 @@ static int mkv_write_tag_targets(AVFormatContext *s, uint32_t elementid, ebml_master targets; int ret; - if (!mkv->tags_bc) { - mkv_add_seekhead_entry(mkv, MATROSKA_ID_TAGS, avio_tell(s->pb)); - - ret = start_ebml_master_crc32(&mkv->tags_bc, mkv); + if (!mkv->tags.bc) { + ret = start_ebml_master_crc32(&mkv->tags.bc, mkv); if (ret < 0) return ret; } - pb = mkv->tags_bc; + pb = mkv->tags.bc; *tag = start_ebml_master(pb, MATROSKA_ID_TAG, 0); targets = start_ebml_master(pb, MATROSKA_ID_TAGTARGETS, 4 + 1 + 8); @@ -1577,14 +1577,14 @@ static int mkv_write_tag(AVFormatContext *s, const AVDictionary *m, while ((t = av_dict_get(m, "", t, AV_DICT_IGNORE_SUFFIX))) { if (mkv_check_tag_name(t->key, elementid)) { - ret = mkv_write_simpletag(mkv->tags_bc, t); + ret = mkv_write_simpletag(mkv->tags.bc, t); if (ret < 0) return ret; } } if (!tag) - end_ebml_master(mkv->tags_bc, tag2); + end_ebml_master(mkv->tags.bc, tag2); return 0; } @@ -1631,7 +1631,7 @@ static int mkv_write_tags(AVFormatContext *s) return ret; if (tagp) { - AVIOContext *pb = mkv->tags_bc; + AVIOContext *pb = mkv->tags.bc; ebml_master simpletag; simpletag = start_ebml_master(pb, MATROSKA_ID_SIMPLETAG, @@ -1680,13 +1680,9 @@ static int mkv_write_tags(AVFormatContext *s) } } - if (mkv->tags_bc) { - if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) - end_ebml_master_crc32_preliminary(s->pb, mkv->tags_bc, - MATROSKA_ID_TAGS, &mkv->tags_pos); - else - end_ebml_master_crc32(s->pb, &mkv->tags_bc, mkv, - MATROSKA_ID_TAGS, 0, 0, 0); + if (mkv->tags.bc) { + end_ebml_master_crc32_tentatively(s->pb, &mkv->tags, mkv, + MATROSKA_ID_TAGS); } return 0; } @@ -1815,12 +1811,10 @@ static int mkv_write_header(AVFormatContext *s) // one elements (except Clusters). mkv_start_seekhead(mkv, pb); - mkv_add_seekhead_entry(mkv, MATROSKA_ID_INFO, avio_tell(pb)); - - ret = start_ebml_master_crc32(&mkv->info_bc, mkv); + ret = start_ebml_master_crc32(&mkv->info.bc, mkv); if (ret < 0) return ret; - pb = mkv->info_bc; + pb = mkv->info.bc; put_ebml_uint(pb, MATROSKA_ID_TIMECODESCALE, 1000000); if ((tag = av_dict_get(s->metadata, "title", NULL, 0))) @@ -1866,12 +1860,7 @@ static int mkv_write_header(AVFormatContext *s) put_ebml_void(pb, 11); // assumes double-precision float to be written } } - if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) - end_ebml_master_crc32_preliminary(s->pb, mkv->info_bc, - MATROSKA_ID_INFO, &mkv->info_pos); - else - end_ebml_master_crc32(s->pb, &mkv->info_bc, mkv, - MATROSKA_ID_INFO, 0, 0, 0); + end_ebml_master_crc32_tentatively(s->pb, &mkv->info, mkv, MATROSKA_ID_INFO); pb = s->pb; ret = mkv_write_tracks(s); @@ -2191,14 +2180,14 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) if (ret < 0) return ret; memcpy(par->extradata, side_data, side_data_size); - avio_seek(mkv->tracks_bc, track->codecpriv_offset, SEEK_SET); - mkv_write_codecprivate(s, mkv->tracks_bc, par, 1, 0); - filler = MAX_PCE_SIZE + 2 + 4 - (avio_tell(mkv->tracks_bc) - track->codecpriv_offset); + avio_seek(mkv->track.bc, track->codecpriv_offset, SEEK_SET); + mkv_write_codecprivate(s, mkv->track.bc, par, 1, 0); + filler = MAX_PCE_SIZE + 2 + 4 - (avio_tell(mkv->track.bc) - track->codecpriv_offset); if (filler) - put_ebml_void(mkv->tracks_bc, filler); - avio_seek(mkv->tracks_bc, track->sample_rate_offset, SEEK_SET); - put_ebml_float(mkv->tracks_bc, MATROSKA_ID_AUDIOSAMPLINGFREQ, track->sample_rate); - put_ebml_float(mkv->tracks_bc, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate); + put_ebml_void(mkv->track.bc, filler); + avio_seek(mkv->track.bc, track->sample_rate_offset, SEEK_SET); + put_ebml_float(mkv->track.bc, MATROSKA_ID_AUDIOSAMPLINGFREQ, track->sample_rate); + put_ebml_float(mkv->track.bc, MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, output_sample_rate); } else if (!par->extradata_size && !track->sample_rate) { // No extradata (codecpar or packet side data). av_log(s, AV_LOG_ERROR, "Error parsing AAC extradata, unable to determine samplerate.\n"); @@ -2214,8 +2203,8 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) return AVERROR(EINVAL); } par->extradata = side_data; - avio_seek(mkv->tracks_bc, track->codecpriv_offset, SEEK_SET); - mkv_write_codecprivate(s, mkv->tracks_bc, par, 1, 0); + avio_seek(mkv->track.bc, track->codecpriv_offset, SEEK_SET); + mkv_write_codecprivate(s, mkv->track.bc, par, 1, 0); par->extradata = old_extradata; } break; @@ -2236,9 +2225,9 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) av_free(codecpriv); return AVERROR_INVALIDDATA; } - avio_seek(mkv->tracks_bc, track->codecpriv_offset, SEEK_SET); + avio_seek(mkv->track.bc, track->codecpriv_offset, SEEK_SET); // Do not write the OBUs as we don't have space saved for them - put_ebml_binary(mkv->tracks_bc, MATROSKA_ID_CODECPRIVATE, codecpriv, 4); + put_ebml_binary(mkv->track.bc, MATROSKA_ID_CODECPRIVATE, codecpriv, 4); av_free(codecpriv); ret = ff_alloc_extradata(par, side_data_size); if (ret < 0) @@ -2518,25 +2507,25 @@ static int mkv_write_trailer(AVFormatContext *s) } after_cues: - ret = mkv_write_seekhead(pb, mkv, 1, mkv->info_pos); + ret = mkv_write_seekhead(pb, mkv, 1, mkv->info.pos); if (ret < 0) return ret; // update the duration av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration); - avio_seek(mkv->info_bc, mkv->duration_offset, SEEK_SET); - put_ebml_float(mkv->info_bc, MATROSKA_ID_DURATION, mkv->duration); - end_ebml_master_crc32(pb, &mkv->info_bc, mkv, MATROSKA_ID_INFO, 0, 0, 0); + avio_seek(mkv->info.bc, mkv->duration_offset, SEEK_SET); + put_ebml_float(mkv->info.bc, MATROSKA_ID_DURATION, mkv->duration); + end_ebml_master_crc32(pb, &mkv->info.bc, mkv, MATROSKA_ID_INFO, 0, 0, 0); - if (mkv->tracks_bc) { + if (mkv->track.bc) { // write Tracks master - avio_seek(pb, mkv->tracks_pos, SEEK_SET); - end_ebml_master_crc32(pb, &mkv->tracks_bc, mkv, + avio_seek(pb, mkv->track.pos, SEEK_SET); + end_ebml_master_crc32(pb, &mkv->track.bc, mkv, MATROSKA_ID_TRACKS, 0, 0, 0); } // update stream durations - if (mkv->tags_bc) { + if (mkv->tags.bc) { int i; for (i = 0; i < s->nb_streams; ++i) { const AVStream *st = s->streams[i]; @@ -2549,18 +2538,18 @@ static int mkv_write_trailer(AVFormatContext *s) av_log(s, AV_LOG_DEBUG, "stream %d end duration = %" PRIu64 "\n", i, track->duration); - avio_seek(mkv->tags_bc, track->duration_offset, SEEK_SET); + avio_seek(mkv->tags.bc, track->duration_offset, SEEK_SET); snprintf(duration_string, 20, "%02d:%02d:%012.9f", (int) duration_sec / 3600, ((int) duration_sec / 60) % 60, fmod(duration_sec, 60)); - put_ebml_binary(mkv->tags_bc, MATROSKA_ID_TAGSTRING, duration_string, 20); + put_ebml_binary(mkv->tags.bc, MATROSKA_ID_TAGSTRING, duration_string, 20); } } - avio_seek(pb, mkv->tags_pos, SEEK_SET); - end_ebml_master_crc32(pb, &mkv->tags_bc, mkv, + avio_seek(pb, mkv->tags.pos, SEEK_SET); + end_ebml_master_crc32(pb, &mkv->tags.bc, mkv, MATROSKA_ID_TAGS, 0, 0, 0); } From patchwork Wed Apr 29 22:21:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 19385 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 031FD44B57C for ; Thu, 30 Apr 2020 01:22:33 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E574A68C221; Thu, 30 Apr 2020 01:22:32 +0300 (EEST) 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 E24A568C1EE for ; Thu, 30 Apr 2020 01:22:25 +0300 (EEST) Received: by mail-wm1-f68.google.com with SMTP id u127so3816023wmg.1 for ; Wed, 29 Apr 2020 15:22:25 -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=ZKjj58WQFhUg/piXveQq/Yk+UUGyUMqKwWTcSDLdA/M=; b=FFpF3jmSFmGtHdi3f14r+hoFjHL6Y3Tq7JzLoE0WqlbKvvOwadJSXd8oWm7IIBi73j C3y1x2AESDXRN26tuZiTsYKoCvrEPavWmsZT9CdfXS3QGBndbReUSMhB7SIVyBk/Xs7p UxW1GnKOYtHRBQ6fbzLJcNUt8IruI8pW311dL/KSiZ9HoB8MSoJzlxhn74bCjI3yVept MScOJu8Zyz6FOh6M0xlB7rdizoiOp/USAruObYTaxsDziNEZNtAA+BAtDVcTQ+75GpWx U/TM4OON4gEIEBqMQhoLNE79YFMnoMaG9d8gOT7sieh8tFbPiOaLsh0vL23v15YB+waK nl1A== 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=ZKjj58WQFhUg/piXveQq/Yk+UUGyUMqKwWTcSDLdA/M=; b=P+GeB6mLlOyt3YR/P8q/iX6eW93u4K+Tjf/pXKhLwxp4YGPDGl0CUuj0Kng2WvD0+N VK0lDbLfE+dcbd678258oVYPONX8XSusctO+/RKSbQlal8JLSzYnrb/UjspE2R3BLEiU HQAMcd0uLdUpzD94DeYnGKrMkf2cabIKeqWhNid0Tcdu8sISATyqTlEEZNznYenUlOGd ZNDaDaSfUxMIYllTKl+T124FlUhK+Zbtj1SJVl+rPum8Pw541UPupu5pzGqY3BoUONiM GfVWW3QB+b4/tP/FmohCmo6pEC+3qDf9s/NzvwfHS6sOprOt0z/L3DXKG/WDEOTuGR+7 NyWQ== X-Gm-Message-State: AGi0PuY5Yg2xxDvZs3IeDPf/xlm2wIs1eg40Y7fkcJ9YEWv/04UzpY45 4p6j6ooi4qqvPijDJRWQIMNH2wvk X-Google-Smtp-Source: APiQypJNjTToR/mlmYZtVICMsupv7CkR2iBZEB7eaNntSpUogT65+VDUehbK/WfNsuZ6QY7MPG0ojg== X-Received: by 2002:a1c:7ed7:: with SMTP id z206mr63037wmc.64.1588198945014; Wed, 29 Apr 2020 15:22:25 -0700 (PDT) Received: from sblaptop.fritz.box (ipbcc1ab57.dynamic.kabel-deutschland.de. [188.193.171.87]) by smtp.gmail.com with ESMTPSA id x6sm1071555wrg.58.2020.04.29.15.22.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Apr 2020 15:22:24 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Thu, 30 Apr 2020 00:21:53 +0200 Message-Id: <20200429222156.29129-3-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 3/6] avformat/matroskaenc: Avoid dynamic buffer when writing Colour 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" There is a good upper bound for the maximum length of the Colour master element; it is therefore unnecessary to use a dynamic buffer for it. A simple buffer on the stack is enough. This commit implements this. Signed-off-by: Andreas Rheinhardt --- libavformat/matroskaenc.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 31f75abc64..36c9ea1d9c 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -808,18 +808,19 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, return ret; } -static int mkv_write_video_color(AVIOContext *pb, const AVCodecParameters *par, +static void mkv_write_video_color(AVIOContext *pb, const AVCodecParameters *par, const AVStream *st) { - AVIOContext *dyn_cp; - uint8_t *colorinfo_ptr; + /* 18 Elements with two bytes ID, one byte length field, 8 bytes payload + * a master element with two bytes ID and one byte length field + * plus another byte to stay clear of the end. */ + uint8_t colour[(2 + 1 + 8) * 18 + (2 + 1) + 1]; + AVIOContext buf, *dyn_cp = &buf; int side_data_size = 0; - int ret, colorinfo_size; + int colorinfo_size; const uint8_t *side_data; - ret = avio_open_dyn_buf(&dyn_cp); - if (ret < 0) - return ret; + ffio_init_context(dyn_cp, colour, sizeof(colour), 1, NULL, NULL, NULL, NULL); if (par->color_trc != AVCOL_TRC_UNSPECIFIED && par->color_trc < AVCOL_TRC_NB) { @@ -890,14 +891,12 @@ static int mkv_write_video_color(AVIOContext *pb, const AVCodecParameters *par, end_ebml_master(dyn_cp, meta_element); } - colorinfo_size = avio_get_dyn_buf(dyn_cp, &colorinfo_ptr); + colorinfo_size = avio_tell(dyn_cp); if (colorinfo_size) { ebml_master colorinfo = start_ebml_master(pb, MATROSKA_ID_VIDEOCOLOR, colorinfo_size); - avio_write(pb, colorinfo_ptr, colorinfo_size); + avio_write(pb, colour, colorinfo_size); end_ebml_master(pb, colorinfo); } - ffio_free_dyn_buf(&dyn_cp); - return 0; } static int mkv_write_video_projection(AVFormatContext *s, AVIOContext *pb, @@ -1290,9 +1289,8 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, uint32_t color_space = av_le2ne32(par->codec_tag); put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLORSPACE, &color_space, sizeof(color_space)); } - ret = mkv_write_video_color(pb, par, st); - if (ret < 0) - return ret; + mkv_write_video_color(pb, par, st); + ret = mkv_write_video_projection(s, pb, st); if (ret < 0) return ret; From patchwork Wed Apr 29 22:21:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 19386 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 08C3844B57C for ; Thu, 30 Apr 2020 01:22:37 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E31B968C22F; Thu, 30 Apr 2020 01:22:36 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f66.google.com (mail-wr1-f66.google.com [209.85.221.66]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id D8A0768C207 for ; Thu, 30 Apr 2020 01:22:27 +0300 (EEST) Received: by mail-wr1-f66.google.com with SMTP id g13so4446955wrb.8 for ; Wed, 29 Apr 2020 15:22:27 -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=1cfSbp+TmO1AkHTCtZPLzGypBNbhMAohFtp3UfQfG2U=; b=eB2SpXalmxPP9fEFUGAG172rwQIrwVtmTT0ojN8RqlXDvEhb+3+tQ4RuQuRla9SIvC 61YYp/O4DQalfj85ipSGFSbK8hiilfLhBK8tpeO4G08E7/2i2QyqkDSiz4cLWlTKK6P1 zMBI8D0s7fMkDwXI/i/M08jct/8Ty9veUHkYzUvJSUmVKfWeoAKPpYABInWAC5fNEWJD G56v98arJ/UZgladXfGrJJSl7f6gMvRfIEdaffw3Wt6qVO7VVvxn0H0wTWkP/5dLBFLX cTI66+YZDrKgGZ+cnXRfMCePdd9qeSRAIqM+rkgYaV30+7HQOadBWz9xzhMhYnX10YgS ms5Q== 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=1cfSbp+TmO1AkHTCtZPLzGypBNbhMAohFtp3UfQfG2U=; b=PGTcM49exHLPDm2zp4Orn4kMH1tvem53zvWVGNbVkRKUVrcet24ncbVsIzqlItAz79 tQtt1By3/i45fWobLHZlDTZm2gvSPDWTwZlDkLLIhk4GjpB3RmGSgk6ptkFL5qWOkwLE 40GSJY3KoVFsisvHwZEVYFA4bBfWWTKKybf3FoX/AEzvv2hztawkF9n0GI2qbuW0YlIQ hQzjhejjButizVRZT0VQhJEoTWzA8Ml4svq59t6LljG2dymbU9L+S49fA7bns99kA84q YMIs4s3+MnLKx+/HYqYUZ8N4j2RAqKsa81tf1Q33412g52jpVTugk13EEQVqhrSbYnNK RBzw== X-Gm-Message-State: AGi0PuY9KPyIcciCpifwDbDi7+ElrZ+s/N7qyhAPLetu2kO079D5xywC yX72vChzuxgQSPtBAeFGczTN6ShG X-Google-Smtp-Source: APiQypIl6qNunWX8BkKmUZEosuhVuQ/L8oSS8t948/QrNInMIqGfM8kYVLWwswazX+FKLcYTpzEhKg== X-Received: by 2002:adf:82cf:: with SMTP id 73mr95017wrc.411.1588198947018; Wed, 29 Apr 2020 15:22:27 -0700 (PDT) Received: from sblaptop.fritz.box (ipbcc1ab57.dynamic.kabel-deutschland.de. [188.193.171.87]) by smtp.gmail.com with ESMTPSA id x6sm1071555wrg.58.2020.04.29.15.22.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Apr 2020 15:22:25 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Thu, 30 Apr 2020 00:21:54 +0200 Message-Id: <20200429222156.29129-4-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 4/6] avformat/matroskaenc: Simplify writing buffer 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" If one already has the contents of a master elements in a buffer of known size, then writing a EBML master element is no different from writing an EBML binary element. It is overtly complicated to use start/end_ebml_master() as these functions first write an unkown-length size field of the appropriate length, then write the buffer's contents, followed by a seek to the length field to overwrite it with the real size (obtained via avio_tell() although it was already known in advance), followed by another seek to the previous position. Just use put_ebml_binary() instead. Signed-off-by: Andreas Rheinhardt --- libavformat/matroskaenc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 36c9ea1d9c..e671a572a8 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -893,9 +893,7 @@ static void mkv_write_video_color(AVIOContext *pb, const AVCodecParameters *par, colorinfo_size = avio_tell(dyn_cp); if (colorinfo_size) { - ebml_master colorinfo = start_ebml_master(pb, MATROSKA_ID_VIDEOCOLOR, colorinfo_size); - avio_write(pb, colour, colorinfo_size); - end_ebml_master(pb, colorinfo); + put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLOR, colour, colorinfo_size); } } From patchwork Wed Apr 29 22:21:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 19387 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 BEF0744B57C for ; Thu, 30 Apr 2020 01:22:37 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id A8FC668C248; Thu, 30 Apr 2020 01:22:37 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f65.google.com (mail-wm1-f65.google.com [209.85.128.65]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 7C09E68C1EB for ; Thu, 30 Apr 2020 01:22:29 +0300 (EEST) Received: by mail-wm1-f65.google.com with SMTP id r26so3810302wmh.0 for ; Wed, 29 Apr 2020 15:22:29 -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=V6iIP84atg9BOwxbmtshMptzIPzxjAB0e6P+TeyQqZg=; b=qV2MPTRsgmU7QIX86uh6/UHyTokpQHd6f3wpU0pfe/pT/ClpYEeqbDT/9P64Hachw3 +O90JUs0gFEOVWrzpKVjF/+XvJfpjXPtcqo8CA5xT3RSPhGK8GSUZUAA8vVdEP+3SX9i +6lAF4AMOSEJlK++XEUsGz2YtDyUmS+QYTTseyKpmWfRnNvOZqLpSqXQkveAd/Emkgrr WIAtZzM8cJlSzAp9F/9LVSQYxtRZxglxIjtK1AadEGQOp/kUE2lIMT+leBPQjeBJcpTB /BDXHBxEMHbLt8liGx6Qw1e8wUBB9UixPYdm5r7xDOfrAlBmhy5mcRkScdMUAdMJ4Y2l ZWKA== 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=V6iIP84atg9BOwxbmtshMptzIPzxjAB0e6P+TeyQqZg=; b=BPe74ec/9jpUt6DJqeB195eWI7qrr4UA/GgfIcgmIrz97xWJgeflyW1EyLs7eVSJVG 2peYnjHVn+vbqo9y8x/FP2BcnR/mQSfPzpd0Q4NEtkd2s710/4S2bom+p03Z2XQZlgMx cYOQIcUN03c7Yt8N3kUen9jPqpOHFH92Yfyc0ZKkSJrNbybJnW/cxK97OIKeBCZZjiNJ ggjamWt3ZKPjxYaL5yk681Wb5YZ8CtZSItTRww+zEs3SQBc6hskreL9yxEBDVspcW6eV qEdjW8dEWMjGMq5jIFXpkfgVf4kZMXeix3s3/As8o3kUqpnCr5KwncestDejoPLQ+RTi Gn3Q== X-Gm-Message-State: AGi0PuZN5+VVKTx0eiUTc3uVomN9Yd8ix2eJeeCeB7SiRUq6CC50r0ht BUpuVIvDMFY3pS6axU60DlhZFYBa X-Google-Smtp-Source: APiQypJqEX1h5g19i1g2I2ODIfMNbHcs5NAQaUBcE9/anZV/r1E2WHBPnAVCJn5wRIFiRaTzafRQBQ== X-Received: by 2002:a05:600c:24cf:: with SMTP id 15mr58976wmu.94.1588198948223; Wed, 29 Apr 2020 15:22:28 -0700 (PDT) Received: from sblaptop.fritz.box (ipbcc1ab57.dynamic.kabel-deutschland.de. [188.193.171.87]) by smtp.gmail.com with ESMTPSA id x6sm1071555wrg.58.2020.04.29.15.22.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Apr 2020 15:22:27 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Thu, 30 Apr 2020 00:21:55 +0200 Message-Id: <20200429222156.29129-5-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 5/6] avformat/matroskaenc: Check allocations implicit in dynamic buffers 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" Failures of the allocations that happen under the hood when using dynamic buffers are usually completely unchecked and the Matroska muxer is no exception to this. The API has its part in this, because there is no documented way to actually check for errors: The return value of both avio_get_dyn_buf() as well as avio_close_dyn_buf() is only documented as "the length of the byte buffer", so that using this to return errors would be an API break. Therefore this commit uses the only reliable way to check for errors with avio_get_dyn_buf(): The AVIOContext's error flag. (This is one of the advantages of avio_get_dyn_buf(): By not destroying the AVIOContext it is possible to inspect this value.) Checking whether the size or the pointer vanishes is not enough as it does not check for truncated output (the dynamic buffer API is int based and so has to truncate the buffer even when enough memory would be available; it's current actual limit is even way below INT_MAX). Signed-off-by: Andreas Rheinhardt --- libavformat/matroskaenc.c | 113 ++++++++++++++++++++++++++------------ 1 file changed, 77 insertions(+), 36 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index e671a572a8..12c22184a3 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -375,19 +375,22 @@ static int start_ebml_master_crc32(AVIOContext **dyn_cp, MatroskaMuxContext *mkv return 0; } -static void end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp, +static int end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp, MatroskaMuxContext *mkv, uint32_t id, int length_size, int keep_buffer, int add_seekentry) { uint8_t *buf, crc[4]; - int size, skip = 0; + int ret, size, skip = 0; + + size = avio_get_dyn_buf(*dyn_cp, &buf); + if ((ret = (*dyn_cp)->error) < 0) + goto fail; if (add_seekentry) mkv_add_seekhead_entry(mkv, id, avio_tell(pb)); put_ebml_id(pb, id); - size = avio_get_dyn_buf(*dyn_cp, &buf); put_ebml_length(pb, size, length_size); if (mkv->write_crc) { skip = 6; /* Skip reserved 6-byte long void element from the dynamic buffer. */ @@ -396,18 +399,20 @@ static void end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp, } avio_write(pb, buf + skip, size - skip); +fail: if (keep_buffer) { ffio_reset_dyn_buf(*dyn_cp); } else { ffio_free_dyn_buf(dyn_cp); } + return ret; } /** * Output EBML master. Keep the buffer if seekable, allowing for later updates. * Furthermore always add a SeekHead Entry for this element. */ -static void end_ebml_master_crc32_tentatively(AVIOContext *pb, +static int end_ebml_master_crc32_tentatively(AVIOContext *pb, ebml_stored_master *elem, MatroskaMuxContext *mkv, uint32_t id) { @@ -415,14 +420,19 @@ static void end_ebml_master_crc32_tentatively(AVIOContext *pb, uint8_t *buf; int size = avio_get_dyn_buf(elem->bc, &buf); + if (elem->bc->error < 0) + return elem->bc->error; + elem->pos = avio_tell(pb); mkv_add_seekhead_entry(mkv, id, elem->pos); put_ebml_id(pb, id); put_ebml_length(pb, size, 0); avio_write(pb, buf, size); + + return 0; } else - end_ebml_master_crc32(pb, &elem->bc, mkv, id, 0, 0, 1); + return end_ebml_master_crc32(pb, &elem->bc, mkv, id, 0, 0, 1); } static void put_xiph_size(AVIOContext *pb, int size) @@ -501,7 +511,10 @@ static int mkv_write_seekhead(AVIOContext *pb, MatroskaMuxContext *mkv, put_ebml_uint(dyn_cp, MATROSKA_ID_SEEKPOSITION, entry->segmentpos); end_ebml_master(dyn_cp, seekentry); } - end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_SEEKHEAD, 0, 0, 0); + ret = end_ebml_master_crc32(pb, &dyn_cp, mkv, + MATROSKA_ID_SEEKHEAD, 0, 0, 0); + if (ret < 0) + return ret; remaining = seekhead->filepos + seekhead->reserved_size - avio_tell(pb); put_ebml_void(pb, remaining); @@ -574,12 +587,14 @@ static int mkv_assemble_cues(AVStream **streams, AVIOContext *dyn_cp, end_ebml_master(cuepoint, track_positions); } while (++entry < end && entry->pts == pts); size = avio_get_dyn_buf(cuepoint, &buf); + if ((ret = cuepoint->error) < 0) + break; put_ebml_binary(dyn_cp, MATROSKA_ID_POINTENTRY, buf, size); ffio_reset_dyn_buf(cuepoint); } ffio_free_dyn_buf(&cuepoint); - return 0; + return ret; } static int put_xiph_codecpriv(AVFormatContext *s, AVIOContext *pb, @@ -800,10 +815,12 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, ff_put_wav_header(s, dyn_cp, par, FF_PUT_WAV_HEADER_FORCE_WAVEFORMATEX); } + if (ret >= 0) { codecpriv_size = avio_get_dyn_buf(dyn_cp, &codecpriv); - if (codecpriv_size) + if ((ret = dyn_cp->error) >= 0 && codecpriv_size) put_ebml_binary(pb, MATROSKA_ID_CODECPRIVATE, codecpriv, codecpriv_size); + } ffio_free_dyn_buf(&dyn_cp); return ret; } @@ -1423,10 +1440,8 @@ static int mkv_write_tracks(AVFormatContext *s) return ret; } - end_ebml_master_crc32_tentatively(pb, &mkv->track, mkv, + return end_ebml_master_crc32_tentatively(pb, &mkv->track, mkv, MATROSKA_ID_TRACKS); - - return 0; } static int mkv_write_chapters(AVFormatContext *s) @@ -1482,10 +1497,10 @@ static int mkv_write_chapters(AVFormatContext *s) end_ebml_master(dyn_cp, chapteratom); } end_ebml_master(dyn_cp, editionentry); - end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_CHAPTERS, 0, 0, 1); - mkv->wrote_chapters = 1; - return 0; + + return end_ebml_master_crc32(pb, &dyn_cp, mkv, + MATROSKA_ID_CHAPTERS, 0, 0, 1); } static int mkv_write_simpletag(AVIOContext *pb, const AVDictionaryEntry *t) @@ -1677,7 +1692,7 @@ static int mkv_write_tags(AVFormatContext *s) } if (mkv->tags.bc) { - end_ebml_master_crc32_tentatively(s->pb, &mkv->tags, mkv, + return end_ebml_master_crc32_tentatively(s->pb, &mkv->tags, mkv, MATROSKA_ID_TAGS); } return 0; @@ -1740,9 +1755,8 @@ static int mkv_write_attachments(AVFormatContext *s) put_ebml_uid(dyn_cp, MATROSKA_ID_FILEUID, track->uid); end_ebml_master(dyn_cp, attached_file); } - end_ebml_master_crc32(pb, &dyn_cp, mkv, MATROSKA_ID_ATTACHMENTS, 0, 0, 1); - - return 0; + return end_ebml_master_crc32(pb, &dyn_cp, mkv, + MATROSKA_ID_ATTACHMENTS, 0, 0, 1); } static int64_t get_metadata_duration(AVFormatContext *s) @@ -1856,7 +1870,10 @@ static int mkv_write_header(AVFormatContext *s) put_ebml_void(pb, 11); // assumes double-precision float to be written } } - end_ebml_master_crc32_tentatively(s->pb, &mkv->info, mkv, MATROSKA_ID_INFO); + ret = end_ebml_master_crc32_tentatively(s->pb, &mkv->info, + mkv, MATROSKA_ID_INFO); + if (ret < 0) + return ret; pb = s->pb; ret = mkv_write_tracks(s); @@ -2137,18 +2154,23 @@ static int mkv_write_vtt_blocks(AVFormatContext *s, AVIOContext *pb, const AVPac return pkt->duration; } -static void mkv_end_cluster(AVFormatContext *s) +static int mkv_end_cluster(AVFormatContext *s) { MatroskaMuxContext *mkv = s->priv_data; + int ret; - end_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv, - MATROSKA_ID_CLUSTER, 0, 1, 0); if (!mkv->have_video) { for (unsigned i = 0; i < s->nb_streams; i++) mkv->tracks[i].has_cue = 0; } mkv->cluster_pos = -1; + ret = end_ebml_master_crc32(s->pb, &mkv->cluster_bc, mkv, + MATROSKA_ID_CLUSTER, 0, 1, 0); + if (ret < 0) + return ret; + avio_write_marker(s->pb, AV_NOPTS_VALUE, AVIO_DATA_MARKER_FLUSH_POINT); + return 0; } static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) @@ -2216,15 +2238,16 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) if (ret < 0) return ret; ff_isom_write_av1c(dyn_cp, side_data, side_data_size); - codecpriv_size = avio_close_dyn_buf(dyn_cp, &codecpriv); - if (!codecpriv_size) { - av_free(codecpriv); - return AVERROR_INVALIDDATA; + codecpriv_size = avio_get_dyn_buf(dyn_cp, &codecpriv); + if ((ret = dyn_cp->error) < 0 || + !codecpriv_size && (ret = AVERROR_INVALIDDATA)) { + ffio_free_dyn_buf(&dyn_cp); + return ret; } avio_seek(mkv->track.bc, track->codecpriv_offset, SEEK_SET); // Do not write the OBUs as we don't have space saved for them put_ebml_binary(mkv->track.bc, MATROSKA_ID_CODECPRIVATE, codecpriv, 4); - av_free(codecpriv); + ffio_free_dyn_buf(&dyn_cp); ret = ff_alloc_extradata(par, side_data_size); if (ret < 0) return ret; @@ -2262,7 +2285,9 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) if (mkv->cluster_pos != -1) { int64_t cluster_time = ts - mkv->cluster_pts; if ((int16_t)cluster_time != cluster_time) { - mkv_end_cluster(s); + ret = mkv_end_cluster(s); + if (ret < 0) + return ret; av_log(s, AV_LOG_WARNING, "Starting new cluster due to timestamp\n"); } } @@ -2372,8 +2397,11 @@ static int mkv_write_packet(AVFormatContext *s, const AVPacket *pkt) } else start_new_cluster = 0; - if (start_new_cluster) - mkv_end_cluster(s); + if (start_new_cluster) { + ret = mkv_end_cluster(s); + if (ret < 0) + return ret; + } } if (!mkv->cluster_pos) @@ -2408,7 +2436,9 @@ static int mkv_write_flush_packet(AVFormatContext *s, AVPacket *pkt) if (!pkt) { if (mkv->cluster_pos != -1) { - mkv_end_cluster(s); + int ret = mkv_end_cluster(s); + if (ret < 0) + return ret; av_log(s, AV_LOG_DEBUG, "Flushing cluster at offset %" PRIu64 " bytes\n", avio_tell(s->pb)); @@ -2435,8 +2465,10 @@ static int mkv_write_trailer(AVFormatContext *s) } if (mkv->cluster_bc) { - end_ebml_master_crc32(pb, &mkv->cluster_bc, mkv, + ret = end_ebml_master_crc32(pb, &mkv->cluster_bc, mkv, MATROSKA_ID_CLUSTER, 0, 0, 0); + if (ret < 0) + return ret; } ret = mkv_write_chapters(s); @@ -2493,8 +2525,10 @@ static int mkv_write_trailer(AVFormatContext *s) } } } - end_ebml_master_crc32(pb, &cues, mkv, MATROSKA_ID_CUES, + ret = end_ebml_master_crc32(pb, &cues, mkv, MATROSKA_ID_CUES, length_size, 0, 1); + if (ret < 0) + return ret; if (mkv->reserve_cues_space) { if (size < mkv->reserve_cues_space) put_ebml_void(pb, mkv->reserve_cues_space - size); @@ -2511,13 +2545,18 @@ static int mkv_write_trailer(AVFormatContext *s) av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration); avio_seek(mkv->info.bc, mkv->duration_offset, SEEK_SET); put_ebml_float(mkv->info.bc, MATROSKA_ID_DURATION, mkv->duration); - end_ebml_master_crc32(pb, &mkv->info.bc, mkv, MATROSKA_ID_INFO, 0, 0, 0); + ret = end_ebml_master_crc32(pb, &mkv->info.bc, mkv, + MATROSKA_ID_INFO, 0, 0, 0); + if (ret < 0) + return ret; if (mkv->track.bc) { // write Tracks master avio_seek(pb, mkv->track.pos, SEEK_SET); - end_ebml_master_crc32(pb, &mkv->track.bc, mkv, + ret = end_ebml_master_crc32(pb, &mkv->track.bc, mkv, MATROSKA_ID_TRACKS, 0, 0, 0); + if (ret < 0) + return ret; } // update stream durations @@ -2545,8 +2584,10 @@ static int mkv_write_trailer(AVFormatContext *s) } avio_seek(pb, mkv->tags.pos, SEEK_SET); - end_ebml_master_crc32(pb, &mkv->tags.bc, mkv, + ret = end_ebml_master_crc32(pb, &mkv->tags.bc, mkv, MATROSKA_ID_TAGS, 0, 0, 0); + if (ret < 0) + return ret; } avio_seek(pb, endpos, SEEK_SET); From patchwork Sat May 2 17:16:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 19435 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 EFA8344BB45 for ; Sat, 2 May 2020 20:17:24 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id CC8FB68C33A; Sat, 2 May 2020 20:17:24 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f65.google.com (mail-wr1-f65.google.com [209.85.221.65]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id E1D3F68C33A for ; Sat, 2 May 2020 20:17:17 +0300 (EEST) Received: by mail-wr1-f65.google.com with SMTP id e16so10566519wra.7 for ; Sat, 02 May 2020 10:17:17 -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=LBSyA3NtLESXj/TwG8SSD7XMK1uIE17+qP4IavnifrY=; b=j2bRnLt/lAJdeXpiBPG6KGRwQruc8dpNsqamwiNDF2qbHEhZvuMClWS2Op87stiWjp GyY5VzX7o/gJtOSiYBHYM0/VxWGOXBfWE7hsekGlNevyUaGn280ZjSx0VvZKCaAiZOyw ljLwsAy6n4lc5g4FIBZJWFHu9t4ZSAxQmepiiRC2UVEKAaDHv7jeBD/PJwShLCGnvRMf E+NHhBGpv9De+EI1QYqUc6l4GsDdjhR/F9X/fY8JEmOSLa4kYVK7A4EoidIRizC9EyZs uhB/jKv1HhTTZRzWxK7WybXBV3Xwn6geVUHRorrXysLcUsp1VO2lncYCuzCbbM4nE6T6 m+5g== 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=LBSyA3NtLESXj/TwG8SSD7XMK1uIE17+qP4IavnifrY=; b=JYPEgf4TYYSF1FN18LmFtXQBZgF2v+hFwxOF3I+WGXYvTjucWXjIGBHKvh77MEdUdV M6+8s//BAIXer1k2jN0ck6eJfTaxtO9SDwjfwQKBWizFXBBhQ7RFcdueHu/0u9xzAQsP EwC+0UZHQGeF/9Pyj4nVsavfw8Qj60Yl2Q+WQmBwg0oh+fUMPAxz3ovrxYV5HiexJ5qg Vyz0X1wPRApW9EucA7VeNxN/t130kN6GxuZnyVGIh5D7CHFhjadQoc3Z1EFGP5mkUlFl BSwwVykleRyn33di6sARTamzXH1hq6qYYvRs02n+iFSmDKZFIe3iAuV2oW3Ir86+A5Ym S2cA== X-Gm-Message-State: AGi0PuZRTM6uYKfX/7hQoyQNN6ZNhycLzSxxkhZxrLVl3beT/OAt/KTz 7n25VY8X5XdTdjF3oc5/wRLuk7Wc X-Google-Smtp-Source: APiQypL7B/HK++hdRvcBHVpSKQSzoBFJ0kVANPKZHpsvefIA7pQvmE1YFWyAAhKLiXUd2cFXK0LR/Q== X-Received: by 2002:a05:6000:108b:: with SMTP id y11mr9245603wrw.380.1588439836894; Sat, 02 May 2020 10:17:16 -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.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 10:17:16 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Sat, 2 May 2020 19:16:53 +0200 Message-Id: <20200502171700.28991-1-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 06/13] avformat/matroskaenc: Only write Cluster if it has in fact been opened 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" Since commit 4aa0665f393847c35387a1c673e62346d0acfc95, the dynamic buffer destined for the contents of the current Cluster is no longer constantly allocated, reallocated and then freed after writing the content; instead it is reset and reused when closing a Cluster. Yet the code in mkv_write_trailer() still checked for whether a Cluster is open by checking whether the pointer to the dynamic buffer is NULL or not (instead of checking whether the position of the current Cluster is -1 or not). If a Cluster was not open, an empty Cluster would be output. One usually does not run into this issue, because unless there are errors, there are only three possibilities to not have an opened Cluster at the end of writing a packet: The first is if one sent an audio packet to the muxer. It might trigger closing and outputting the old Cluster, but because the muxer caches audio packets internally, it would not be output immediately and therefore no new Cluster would be opened. The second is an audio packet that does not contain data (such packets are sometimes sent for side-data only, e.g. by the FLAC encoder). The only difference to the first scenario is that such packets are not cached. The third is if one explicitly flushes the muxer by sending a NULL packet via av_write_frame(). If one also allows for errors, then there is also another possibility: Caching the audio packet may fail in the first scenario. If one calls av_write_trailer() after the first scenario, the cached audio packet will be output when writing the trailer, for which a Cluster is opened and everything is fine; because flushing the muxer does currently not output the cached audio packet (if one is cached), the issue also does not exist if an audio packet has been cached before flushing. The issue only exists in one of the other scenarios. Signed-off-by: Andreas Rheinhardt --- Given that this is a recent regression caused by me I will push this soon if no one objects. That the cached packet is not output on flushing looks like a bug to me. Will send a patch soon. libavformat/matroskaenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 8593c3fce1..99b549ecc4 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -2464,7 +2464,7 @@ static int mkv_write_trailer(AVFormatContext *s) } } - if (mkv->cluster_bc) { + if (mkv->cluster_pos != -1) { ret = end_ebml_master_crc32(pb, &mkv->cluster_bc, mkv, MATROSKA_ID_CLUSTER, 0, 0, 0); if (ret < 0) From patchwork Sat May 2 17:16:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 19436 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 180A344BB45 for ; Sat, 2 May 2020 20:17:54 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id F21CA68C87D; Sat, 2 May 2020 20:17:53 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f67.google.com (mail-wr1-f67.google.com [209.85.221.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 741DE68BB49 for ; Sat, 2 May 2020 20:17:47 +0300 (EEST) Received: by mail-wr1-f67.google.com with SMTP id l18so4945430wrn.6 for ; Sat, 02 May 2020 10:17:47 -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=m2afAJXouO4SO1qFdxhXh3XS8DKewaJnmMx5V/+WaxI=; b=GoVyjiMdI0et75a4nozRjr/ngnBx88urwH4/Xyr1V3gbFBgKErdtYjpOctaLSs752p k9Mmcf83ZuUXgffbOC3SojccJ25Zv6CBGZpV3TdDaszVdpc+TJX42k9FLiB3r1vt6YDG fJVhwg5xaFugryb2ORqphINm0D2IXhayMmu2GZZj7qBpFh1iE52xcbO1lUKzfRXv4t7P zxEgWhFPJSxv2S8HYBozyFq3WwI6+FGUh4Ns+Ma5PHrACbvmTPMENCW5UsVOraMvMTtq I2F/6555J6l1D//RQhD21jAnjjHSM5CTh/69qOltubTHLQfo91ebe0DWpDXKk8UYmknU Qjww== 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=m2afAJXouO4SO1qFdxhXh3XS8DKewaJnmMx5V/+WaxI=; b=Vz5aokftm7U1++autKXMxvzrSpoVTrAbBTAS4ll6oITtrxeXZS7vQWoVld9HLCNvUW pE2zZ67tPNbNP6UI4f7gz5lF2pJrj7CzmK1pd3ilUtkEjYSqyMDgAv0Qvldf95xKC17n QrUqsGiCSzF8IidAdBLwn3tMlrMgb6cbV/gPTn2pI30WV2Zv2xWt/aPgL4PIUxjU7Q48 D19w3mxkbG90dnaOTBeS5rJr90DKXDnpmOomBuvGBqc5qYhMeohqUoyGI+16jS29V9bs P2QeIK7MTKacTFQYScegXQkeuO2CFOKksEVZ1zOHfmzXCq8wrlxl+UH3cjWuj96fMq0V UjVA== X-Gm-Message-State: AGi0PuZY76kCKRkCKUkbeUOw5H2i/YSpJXwR5UI6W0aKdrA8CDFtyO2L 4tSvDVv0tqIX1iYh+k/TIMdDbbiC X-Google-Smtp-Source: APiQypIVU28n32ztJ67q8miScE2CUhwOmyXaM326VFsmr1ZiljBxtvDyRcktzIFFeEjl6Tr0L8jJAA== X-Received: by 2002:a5d:45cf:: with SMTP id b15mr9776311wrs.78.1588439866425; Sat, 02 May 2020 10:17:46 -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.45 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 10:17:45 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Sat, 2 May 2020 19:16:54 +0200 Message-Id: <20200502171700.28991-2-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 07/13] avformat/matroskaenc: Don't segfault when seekability changes 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" If the Matroska muxer's AVIOContext was unseekable when writing the header, but is seekable when writing the trailer, the code for writing the trailer presumes that a dynamic buffer exists and tries to update its content in order to overwrite data that has already been preliminarily written when writing the header, yet said buffer doesn't exist as it has been written finally and not preliminarily when writing the header (because of the unseekability it was presumed that one won't be able to update the data anyway). This commit adds a check for this and also for a similar situation involving updating extradata with new data from packet side-data. Signed-off-by: Andreas Rheinhardt --- It seems that the whole code was based around the presumption that the seekability does not change mid-stream. E.g. before add68dcca there were the way level 1 elements were written depended upon the seekability and the output would be corrupt if it changed between opening and closing. Given the lack of tickets about this it seems that this assumption holds true. Therefore this patch uses the existence of the Tracks buffer as proxy for seekability. libavformat/matroskaenc.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 99b549ecc4..1a142403fa 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -2186,7 +2186,7 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) switch (par->codec_id) { case AV_CODEC_ID_AAC: - if (side_data_size && (s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) { + if (side_data_size && mkv->track.bc) { int filler, output_sample_rate = 0; ret = get_aac_sample_rates(s, side_data, side_data_size, &track->sample_rate, &output_sample_rate); @@ -2213,7 +2213,7 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) } break; case AV_CODEC_ID_FLAC: - if (side_data_size && (s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) { + if (side_data_size && mkv->track.bc) { uint8_t *old_extradata = par->extradata; if (side_data_size != par->extradata_size) { av_log(s, AV_LOG_ERROR, "Invalid FLAC STREAMINFO metadata for output stream %d\n", @@ -2229,8 +2229,7 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) // FIXME: Remove the following once libaom starts propagating extradata during init() // See https://bugs.chromium.org/p/aomedia/issues/detail?id=2012 case AV_CODEC_ID_AV1: - if (side_data_size && (s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live && - !par->extradata_size) { + if (side_data_size && mkv->track.bc && !par->extradata_size) { AVIOContext *dyn_cp; uint8_t *codecpriv; int codecpriv_size; @@ -2541,6 +2540,7 @@ static int mkv_write_trailer(AVFormatContext *s) if (ret < 0) return ret; + if (mkv->info.bc) { // update the duration av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration); avio_seek(mkv->info.bc, mkv->duration_offset, SEEK_SET); @@ -2549,6 +2549,7 @@ static int mkv_write_trailer(AVFormatContext *s) MATROSKA_ID_INFO, 0, 0, 0); if (ret < 0) return ret; + } if (mkv->track.bc) { // write Tracks master From patchwork Sat May 2 17:16:55 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 19437 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 215AD44BB45 for ; Sat, 2 May 2020 20:17:56 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 013B468C885; Sat, 2 May 2020 20:17:56 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f49.google.com (mail-wm1-f49.google.com [209.85.128.49]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 66DCA68C3B7 for ; Sat, 2 May 2020 20:17:48 +0300 (EEST) Received: by mail-wm1-f49.google.com with SMTP id 188so3533632wmc.2 for ; Sat, 02 May 2020 10:17:48 -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=k8OOf6sW4Bp1EDT/F2wCbER1+m112jILEetUFJ70PJk=; b=AQFjCKrDH4kPEf4xFi6cBE7WXPaQTgalBBDeSnHHcjAZwVgcteE8Gq3vOuxOwg4uVs ontq7b7PdtLOGHJk0Cn0A+SoSvDpsM9mECupz5RqofJzhBx/O0NN/tA3X/3MtCeNpeuD EglJoFD1jeApKhC3VCUapEvvMo1S3yMhJMXTWnW+dUG6PMqxuh89S3WaV1crsDdCi3Z3 hlTQphu7aIR9Q/HcKMkR7bP/Bdaq1mdbt9ep1kNBnQk7KsXjEqng7Q0dg8pYyBnI+Lx/ SWwSksWUv9inpj4l+buOmblbiMeJ0ZXfZViMqLmIcLdn3NeHMufPmEXDAww+6v3ng9/y cd9Q== 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=k8OOf6sW4Bp1EDT/F2wCbER1+m112jILEetUFJ70PJk=; b=EzYtYjOs03YIdPGYs/URbt5rcVvl42LxE8AhKzXnh3oPt5tOSFYOUEwjrx9k0g9aBC v+kjCCg/GM3mumJxaDk/urk/QJaIlttDjeK5RDHs2q9BFFMthzVvNb+/8WzlvVD0eDml HCt/Wx/wMBc7LBVvXRZv5/XEsfbfEET44r2BXhgKP3oN4LKsidVye7f2UUscWLDRvlx4 y/lKYIyi4S4LA3qw6meWkR/IxMR/8iIl75rSYDZkOLKLX5FQMyQcroq8/FY9B9EwAvff iy6JdkrZ8bq4fkP6p5RIAZLoKLQr622acsVU+/kBtkhGnkxCPeBAfUYasct+ivNV0fim Moww== X-Gm-Message-State: AGi0PuaqcmeeVm5fI4T15pbrJozqPyNBLeUY6ynmjvDWLrQTL+Q5uraN 7uTpPhNBFlShSjUZsWJiVfnFIO1J X-Google-Smtp-Source: APiQypK04FvhTeKFtV8qxbvoWnTpLndiNElZCkuX0dTNt2Y1iuoiwAQFD9PNLlgJv6nYcPAbOb2e9g== X-Received: by 2002:a7b:c0cb:: with SMTP id s11mr5908579wmh.180.1588439867403; Sat, 02 May 2020 10:17:47 -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.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 10:17:46 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Sat, 2 May 2020 19:16:55 +0200 Message-Id: <20200502171700.28991-3-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 08/13] avformat/matroskaenc: Remove inconsistencies wrt seekability handling 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 behaves differently in several ways when it thinks that it is in unseekable/livestreaming mode: It does not add Cue entries because they won't be written anyway for a livestream and it writes some elements only preliminarily (with the intention to overwrite them with an updated version at the end) when non-livestreaming etc. There are two ways to set the Matroska muxer into livestreaming mode: Setting an option or by providing an unseekable AVIOContext. Yet the actual checks were not consistent: If the AVIOContext was unseekable and no AAC extradata was available when writing the header, writing the header failed; but if the AVIOContext was seekable, it didn't, because the muxer expected to get the extradata via packet side-data. Here the livestreaming option has not been checked, although one can't use the updated extradata in case it is a livestream. If the reserve_index_space option was used, space for writing Cues would be reserved when writing the header unless the AVIOContext was unseekable. Yet Cues were only written if the livestreaming option was not set and the AVIOContext was seekable (when writing the trailer), so if the AVIOContext was seekable and the livestreaming option set, the reserved space would never be used at all. If the AVIOContext was unseekable and the livestreaming option was not set, it would be attempted to update the main length field at the end. After all, it might be possible that the file is so short that it fits into the AVIOContext's buffer in which case the seek back would work. Yet this is dangerous: It might be that we are not dealing with a simple output file, but that our output gets split into chunks and that each of these chunks is actually seekable. In this case some part of the last chunk (namely the eight bytes that have the same offset as the length field had in the header) will be overwritten with what the muxer wrongly believes to be the filesize. (The livestreaming option has been added to deal with this scenario, yet its documentation ("Write files assuming it is a live stream.") doesn't make this clear at all. At least the segment muxer does not set the option for live and given that the chances of successfully seeking when the output is actually unseekable are slim, it is best to not attempt to update the length field in the unseekable case at all.) All these inconsistencies were fixed by treating the output as seekable if the livestreaming option is not set and if the AVIOContext is seekable. A macro has been used to enforce consistency and improve code readability. Signed-off-by: Andreas Rheinhardt --- I am actually not really satisfied with this: I'd really like an option that says that the output is a single file. The reason for this is that I am working on a patchset for writing attached picture streams as AttachedFile in Matroska (there are several tickets open for this), yet the corresponding packets are only available after writing the header.* My plan is to write the Attachments as soon as possible when seekable (i.e. before the first Cluster when all necessary packets already arrived; at the end otherwise) and if I knew that the output was a single file (even if unseekable) I could also write Attachments before the first Cluster. This commit will btw lead to a misleading-indentation warning. It will be fixed in the cosmetics commit. *: I have an idea to mitigate this (by using AVStream.attached_pic for muxers, too), but it won't solve this problem completely. libavformat/matroskaenc.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 1a142403fa..ccbd73cbe4 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -58,6 +58,9 @@ * Info, Tracks, Chapters, Attachments, Tags and Cues */ #define MAX_SEEKHEAD_ENTRIES 6 +#define IS_SEEKABLE(pb, mkv) (((pb)->seekable & AVIO_SEEKABLE_NORMAL) && \ + !(mkv)->is_live) + enum { DEFAULT_MODE_INFER, DEFAULT_MODE_INFER_NO_SUBS, @@ -671,9 +674,9 @@ static int put_flac_codecpriv(AVFormatContext *s, AVIOContext *pb, return 0; } -static int get_aac_sample_rates(AVFormatContext *s, const uint8_t *extradata, - int extradata_size, int *sample_rate, - int *output_sample_rate) +static int get_aac_sample_rates(AVFormatContext *s, MatroskaMuxContext *mkv, + const uint8_t *extradata, int extradata_size, + int *sample_rate, int *output_sample_rate) { MPEG4AudioConfig mp4ac; int ret; @@ -684,7 +687,7 @@ static int get_aac_sample_rates(AVFormatContext *s, const uint8_t *extradata, * first packet. * Abort however if s->pb is not seekable, as we would not be able to seek back * to write the sample rate elements once the extradata shows up, anyway. */ - if (ret < 0 && (extradata_size || !(s->pb->seekable & AVIO_SEEKABLE_NORMAL))) { + if (ret < 0 && (extradata_size || !IS_SEEKABLE(s->pb, mkv))) { av_log(s, AV_LOG_ERROR, "Error parsing AAC extradata, unable to determine samplerate.\n"); return AVERROR(EINVAL); @@ -1141,8 +1144,8 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, return 0; if (par->codec_id == AV_CODEC_ID_AAC) { - ret = get_aac_sample_rates(s, par->extradata, par->extradata_size, &sample_rate, - &output_sample_rate); + ret = get_aac_sample_rates(s, mkv, par->extradata, par->extradata_size, + &sample_rate, &output_sample_rate); if (ret < 0) return ret; } @@ -1907,11 +1910,13 @@ static int mkv_write_header(AVFormatContext *s) put_ebml_void(pb, s->metadata_header_padding); } - if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && mkv->reserve_cues_space) { + if (mkv->reserve_cues_space) { + if (IS_SEEKABLE(pb, mkv)) { mkv->cues_pos = avio_tell(pb); if (mkv->reserve_cues_space == 1) mkv->reserve_cues_space++; put_ebml_void(pb, mkv->reserve_cues_space); + } } av_init_packet(&mkv->cur_audio_pkt); @@ -1920,7 +1925,7 @@ static int mkv_write_header(AVFormatContext *s) // start a new cluster every 5 MB or 5 sec, or 32k / 1 sec for streaming or // after 4k and on a keyframe - if (pb->seekable & AVIO_SEEKABLE_NORMAL) { + if (IS_SEEKABLE(pb, mkv)) { if (mkv->cluster_time_limit < 0) mkv->cluster_time_limit = 5000; if (mkv->cluster_size_limit < 0) @@ -2188,8 +2193,8 @@ static int mkv_check_new_extra_data(AVFormatContext *s, const AVPacket *pkt) case AV_CODEC_ID_AAC: if (side_data_size && mkv->track.bc) { int filler, output_sample_rate = 0; - ret = get_aac_sample_rates(s, side_data, side_data_size, &track->sample_rate, - &output_sample_rate); + ret = get_aac_sample_rates(s, mkv, side_data, side_data_size, + &track->sample_rate, &output_sample_rate); if (ret < 0) return ret; if (!output_sample_rate) @@ -2311,7 +2316,7 @@ static int mkv_write_packet_internal(AVFormatContext *s, const AVPacket *pkt) ret = mkv_write_block(s, pb, MATROSKA_ID_SIMPLEBLOCK, pkt, keyframe); if (ret < 0) return ret; - if ((s->pb->seekable & AVIO_SEEKABLE_NORMAL) && keyframe && + if (keyframe && IS_SEEKABLE(s->pb, mkv) && (par->codec_type == AVMEDIA_TYPE_VIDEO || !mkv->have_video && !track->has_cue)) { ret = mkv_add_cuepoint(mkv, pkt->stream_index, ts, mkv->cluster_pos, relative_packet_pos, -1); @@ -2341,7 +2346,7 @@ FF_ENABLE_DEPRECATION_WARNINGS end_ebml_master(pb, blockgroup); } - if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) { + if (IS_SEEKABLE(s->pb, mkv)) { ret = mkv_add_cuepoint(mkv, pkt->stream_index, ts, mkv->cluster_pos, relative_packet_pos, duration); if (ret < 0) @@ -2451,6 +2456,7 @@ static int mkv_write_trailer(AVFormatContext *s) { MatroskaMuxContext *mkv = s->priv_data; AVIOContext *pb = s->pb; + int64_t endpos, ret64; int ret; // check if we have an audio packet cached @@ -2474,9 +2480,8 @@ static int mkv_write_trailer(AVFormatContext *s) if (ret < 0) return ret; - - if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) { - int64_t endpos, ret64; + if (!IS_SEEKABLE(pb, mkv)) + return 0; endpos = avio_tell(pb); @@ -2592,9 +2597,7 @@ static int mkv_write_trailer(AVFormatContext *s) } avio_seek(pb, endpos, SEEK_SET); - } - if (!mkv->is_live) end_ebml_master(pb, mkv->segment); return mkv->reserve_cues_space < 0 ? AVERROR(EINVAL) : 0; From patchwork Sat May 2 17:16:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 19438 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 2D40F44BB45 for ; Sat, 2 May 2020 20:17:57 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1278A68C894; Sat, 2 May 2020 20:17:57 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f67.google.com (mail-wm1-f67.google.com [209.85.128.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 867BA68C87B for ; Sat, 2 May 2020 20:17:49 +0300 (EEST) Received: by mail-wm1-f67.google.com with SMTP id u16so3757768wmc.5 for ; Sat, 02 May 2020 10:17:49 -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=eYNESwT5QdaWvA8ZigLdOLmsvfdXXDmlkW2gTFOEo+E=; b=cs0g36LUNJaSicY1agEfnEJ07WOV4PkjKouxm9AcfG1gNA//gjRQCxxE2hUCmQu5tt GRFDCVLusre8BnLm6DunJ7UBwwLdVew5qiDEMdNmaIF33fBkNpYcxnppOV4tgGpfmu7v znowxVFfmUFR1oPcswt0EjqPdzFVfc+ENSxFRe1nPBOMD6YrzIHc0l8zr9XIR8JZrbP6 Oh2V3U2+0t/KclT0KZVvNsDRzVG7DoLwS3yEBCN+b9/b0d09aWqh/BlgqwK2pcuQh5gL b2FTnnPdj4VMssS1469MOHhfmAR9oWwQyKLncVtzeO1A47FdkyEy/xMFY8p7WzeuZz0y DAQQ== 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=eYNESwT5QdaWvA8ZigLdOLmsvfdXXDmlkW2gTFOEo+E=; b=izqmqYP2ysd8DBViHTcfEUfE2DLcZOcaVEYBpuFkvh2UGGtgMcvrhk/7/V6VnrLj+a pfYZn/4g8XVFuEEy/OS9GNBgiuSAgtRmsEqiGzNO8lzSCyYMv2Pedk1SKMtyUG8Ukc7q HWncOJ3MX98a8f3oixGMas+7cUluJH1RfasPhL53YKeUFGiT2AbPP0R7jwUazqRfvFDs H+iUGnmic9wb54SLDUCtaE5hjFZ2IMaJHjOkROAOMjDTjsN0k1+j6Z0xTUThqmsEfFkl 7j7Jtsg4bkGDU8MNOitJO3yXsteNbZ8is85PHxeAgc61hJyCEZa9U5kJWx5w2YKCDOy/ BJgQ== X-Gm-Message-State: AGi0PuamQFPIIYggRuCahseJMpVK1pPDOEVeO6Ps0GxEwNCG5/vlms+G bbJTKghmrO/sgjBPVjrho60fld0h X-Google-Smtp-Source: APiQypIEQM9LvRlSTVtzpelmu1QwnR/nMnMN+apTEOvwXtGWYW7rVKguc8UWegh2eAaVX1SfWR5wVg== X-Received: by 2002:a7b:c459:: with SMTP id l25mr5332083wmi.52.1588439868594; Sat, 02 May 2020 10:17:48 -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.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 10:17:47 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Sat, 2 May 2020 19:16:56 +0200 Message-Id: <20200502171700.28991-4-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 09/13] avformat/matroskaenc: Don't reserve space for duration when unseekable 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" We won't be able to seek back to write the actual duration anyway. FATE-tests using the md5pipe command had to be updated due to this change. Signed-off-by: Andreas Rheinhardt --- This is the one and only place where is_live still differs from !(pb->seekable & AVIO_SEEKABLE_NORMAL): No duration is ever written when is_live is set. libavformat/matroskaenc.c | 2 +- tests/fate/matroska.mak | 2 +- tests/fate/wavpack.mak | 4 ++-- tests/ref/fate/binsub-mksenc | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index ccbd73cbe4..10b64e2965 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -1869,7 +1869,7 @@ static int mkv_write_header(AVFormatContext *s) int64_t scaledDuration = av_rescale(metadata_duration, 1000, AV_TIME_BASE); put_ebml_float(pb, MATROSKA_ID_DURATION, scaledDuration); av_log(s, AV_LOG_DEBUG, "Write early duration from metadata = %" PRIu64 "\n", scaledDuration); - } else { + } else if (s->pb->seekable & AVIO_SEEKABLE_NORMAL) { put_ebml_void(pb, 11); // assumes double-precision float to be written } } diff --git a/tests/fate/matroska.mak b/tests/fate/matroska.mak index 1d2921194f..b69f9792a8 100644 --- a/tests/fate/matroska.mak +++ b/tests/fate/matroska.mak @@ -12,7 +12,7 @@ fate-matroska-prores-header-insertion-bz2: CMD = framecrc -i $(TARGET_SAMPLES)/m FATE_MATROSKA-$(call DEMMUX, MATROSKA, MATROSKA) += fate-matroska-remux fate-matroska-remux: CMD = md5pipe -i $(TARGET_SAMPLES)/vp9-test-vectors/vp90-2-2pass-akiyo.webm -color_trc 4 -c:v copy -fflags +bitexact -strict -2 -f matroska fate-matroska-remux: CMP = oneline -fate-matroska-remux: REF = 8369f24de64aaa52cf57a699dcdc7d58 +fate-matroska-remux: REF = acaf96f1832264d7f2845b16dd4ab082 FATE_MATROSKA-$(call ALLYES, MATROSKA_DEMUXER VORBIS_PARSER) += fate-matroska-xiph-lacing fate-matroska-xiph-lacing: CMD = framecrc -i $(TARGET_SAMPLES)/mkv/xiph_lacing.mka -c:a copy diff --git a/tests/fate/wavpack.mak b/tests/fate/wavpack.mak index c62b3ceefd..f98eaf9a0b 100644 --- a/tests/fate/wavpack.mak +++ b/tests/fate/wavpack.mak @@ -91,12 +91,12 @@ fate-wavpack-matroskamode: CMD = md5 -i $(TARGET_SAMPLES)/wavpack/special/matros FATE_WAVPACK-$(call DEMMUX, WV, MATROSKA) += fate-wavpack-matroska_mux-mono fate-wavpack-matroska_mux-mono: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/num_channels/mono_16bit_int.wv -c copy -fflags +bitexact -f matroska fate-wavpack-matroska_mux-mono: CMP = oneline -fate-wavpack-matroska_mux-mono: REF = a378996c1bb5a54998fc804fb1ad97b1 +fate-wavpack-matroska_mux-mono: REF = 5388d452e84958d204de9974bb4e3947 FATE_WAVPACK-$(call DEMMUX, WV, MATROSKA) += fate-wavpack-matroska_mux-61 fate-wavpack-matroska_mux-61: CMD = md5pipe -i $(TARGET_SAMPLES)/wavpack/num_channels/eva_2.22_6.1_16bit-partial.wv -c copy -fflags +bitexact -f matroska fate-wavpack-matroska_mux-61: CMP = oneline -fate-wavpack-matroska_mux-61: REF = 3d708dfce5ac85df114ea91b30143708 +fate-wavpack-matroska_mux-61: REF = c28c51910fc8f3806b1ada1efc82ccae FATE_SAMPLES_AVCONV += $(FATE_WAVPACK-yes) fate-wavpack: $(FATE_WAVPACK-yes) diff --git a/tests/ref/fate/binsub-mksenc b/tests/ref/fate/binsub-mksenc index b4c08e57dd..48a7a56260 100644 --- a/tests/ref/fate/binsub-mksenc +++ b/tests/ref/fate/binsub-mksenc @@ -1 +1 @@ -3dd15fa67a1df541aa89565ceb7047cf +8f355f39124753f89ead698e66f98098 From patchwork Sat May 2 17:16:57 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 19439 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 1567444BB45 for ; Sat, 2 May 2020 20:17:58 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id F3DA968C89B; Sat, 2 May 2020 20:17:57 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm1-f67.google.com (mail-wm1-f67.google.com [209.85.128.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 856D968C882 for ; Sat, 2 May 2020 20:17:50 +0300 (EEST) Received: by mail-wm1-f67.google.com with SMTP id x4so3547072wmj.1 for ; Sat, 02 May 2020 10:17:50 -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=uDjrdozDAZxvu6n3VMag7bylAsHWpKBscBWzCEF2M8A=; b=osUgxZ+hfY/6z2JEJU+2KqIp613TqbmSSRwouqCbJozm4U5FRzs2FNGKONDJ0/Dl3p Ng+ldrazR4V0ZrIkJ2Yj3MiES5H0E84kG032g192egb6P71n6KqbNe04Ef9z9/SZ7fEF 3bT+CE2yaQ4dSSy76ZdkvFhF2ii8CJF83QMrRH9BtiCaBy7p2i6QXKiAXIlwNO+v+hRG IG+PEjkXPVqBzhMD0M6LFlhH4MbNYQ5GTm8O+opUEM3xmPvVuArE8c/7F0Bb8ThOFaqM JipbxY5X6j3+6bCVjbNMO9igIfORmWINUKK3bop2jovIxxx5ml7DCUb9zy+9tEUk3bRU lMGQ== 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=uDjrdozDAZxvu6n3VMag7bylAsHWpKBscBWzCEF2M8A=; b=Hy25O4SiBBEfM3iCl0oM42++HdtLzfJH2z4Gv25nVQhnj370Z1RokA6JIVCacSjWGs vX3rB2si38p9TZIamA1Sy3TC3Lf20jvkIueaf9lmO9BG6qwztKWjbHGsIbKF8hyRattq QbZmn69i2nCw/zGJbJIdFIMyhpHOicXOhl9ZaclqU8O7NzuNQPFpgfbehLsyCclTr1aY TjiW0EdL1Eqpi12tNNUr/Nj5XuI+WXw+70LtTvsDOVloUkHToma6FVfM6xqPNVMMDvnF eGxd0ihzZ7/X1nOqd+5OPFJabJUnX7BHEHLzs9xpaG8q0Cp8NUUnCoc39Tp4vS1HbjQF /6bw== X-Gm-Message-State: AGi0PubTkmUhj7njSWGZp0urgoA3ifHiC+QbPa9Z/bO3r7Ggezzyfm1T QmmzG26ebFtwlYlq+LWacLzk6OSo X-Google-Smtp-Source: APiQypICk+fJ7o/Y0JCewDr//T61yE1CpqRCnP2DrLaT8M2WyVTWRMxbN9uB+0xqNP/rwz9RCBVVLw== X-Received: by 2002:a1c:7c18:: with SMTP id x24mr5056238wmc.146.1588439869643; Sat, 02 May 2020 10:17:49 -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.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 10:17:49 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Sat, 2 May 2020 19:16:57 +0200 Message-Id: <20200502171700.28991-5-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 10/13] avformat/matroskaenc: Only write Cues at the front if space has been reserved 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" If the AVIOContext for output was unseekable when writing the header, no space for Cues would be reserved even if the reserve_index_space option was used (because it is reasonable to expect that one can't seek back to the beginning to write the Cues anyway). But if the AVIOContext was seekable when writing the trailer, it was presumed that space for the Cues had been reserved when the reserve_index_space option indicated so even when it was not. As a result, the beginning of the file would be overwritten. This commit fixes this: If the reserve_index_space option had been used and no space has been reserved in advance because of unseekability when writing the header, then no attempt to write Cues will be performed when writing the trailer; after all, writing them at the front is impossible and writing them at the end is probably undesired. Signed-off-by: Andreas Rheinhardt --- On git master one would get the segfault fixed in 7/13 when one runs into the issue fixed by this commit. libavformat/matroskaenc.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index 10b64e2965..e9b2be3d42 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -1916,7 +1916,8 @@ static int mkv_write_header(AVFormatContext *s) if (mkv->reserve_cues_space == 1) mkv->reserve_cues_space++; put_ebml_void(pb, mkv->reserve_cues_space); - } + } else + mkv->reserve_cues_space = -1; } av_init_packet(&mkv->cur_audio_pkt); @@ -2457,7 +2458,7 @@ static int mkv_write_trailer(AVFormatContext *s) MatroskaMuxContext *mkv = s->priv_data; AVIOContext *pb = s->pb; int64_t endpos, ret64; - int ret; + int ret, ret2 = 0; // check if we have an audio packet cached if (mkv->cur_audio_pkt.size > 0) { @@ -2485,7 +2486,7 @@ static int mkv_write_trailer(AVFormatContext *s) endpos = avio_tell(pb); - if (mkv->cues.num_entries) { + if (mkv->cues.num_entries && mkv->reserve_cues_space >= 0) { AVIOContext *cues = NULL; uint64_t size; int length_size = 0; @@ -2510,7 +2511,7 @@ static int mkv_write_trailer(AVFormatContext *s) "Insufficient space reserved for Cues: " "%d < %"PRIu64". No Cues will be output.\n", mkv->reserve_cues_space, size); - mkv->reserve_cues_space = -1; + ret2 = AVERROR(EINVAL); ffio_free_dyn_buf(&cues); goto after_cues; } else { @@ -2600,7 +2601,7 @@ static int mkv_write_trailer(AVFormatContext *s) end_ebml_master(pb, mkv->segment); - return mkv->reserve_cues_space < 0 ? AVERROR(EINVAL) : 0; + return ret2; } static int mkv_query_codec(enum AVCodecID codec_id, int std_compliance) 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; } From patchwork Sat May 2 17:16:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 19441 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 D2F7944BB45 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 B6CB268C8AB; Sat, 2 May 2020 20:17:59 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f67.google.com (mail-wr1-f67.google.com [209.85.221.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 9409C68C888 for ; Sat, 2 May 2020 20:17:52 +0300 (EEST) Received: by mail-wr1-f67.google.com with SMTP id j1so15719846wrt.1 for ; Sat, 02 May 2020 10:17:52 -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=QBW2f5k7M5Lrj6M4biK0ZXaRVOSumE7bjJI/ICDs3zM=; b=JMXEOedxQrLUYHP4FSenzW97nAjIJ8RuAdY9/HUErthSuHI8fZ3rR3dUVS2hjoB+kY QY563f/k4v0YpvuT59/IybkD5Nzrw/xVDBwh3RcoPQilBVE4pcXUpyKN+VLJ90hB+DD5 9JO0Gu5mZqcr1GPBLvURgNJM8jqdZdZYiAAb+XuC4OB73/ZBIkJEYqhexoNQdWWA5ePk jg9btQHvpT7PBGC7KlYX+kw6qe6a0sCVeq8gRnLsOtogmglC3HhCB1QsM8z8ocHlAFIO HgXipJmcwpFZ/1w8OiQ176Gxj8WPO5t1HFoT4UTdLV5HfN05F9YvhcrbsaAaZiQZLAn+ rcKA== 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=QBW2f5k7M5Lrj6M4biK0ZXaRVOSumE7bjJI/ICDs3zM=; b=PWG5i5PZt1Ucu3TUzX9h7M0g1oaSp++7tyk3vmdfgR3gqQdLBcgOgSfndpsVdkNVYa gTI/G+udcFNvRKnJtjKnj64xNdWe/7cnC+oo7WcyTFfOqYcPsMnCMd8ZulEP2foaAPmV lFmSHCKrK/+Zl96olVjf5NVefN6BjW8GUZWzTuqeuVvlhgzhBftILHPfH5de4IrrWlt0 cljHh3IDlFkhe4JD6j4R30SDpTeMIOJ6R64AS+CRnEAB3wbp+4O/Qb0IJ+GyHrtQeM+o Y9oN9+mq0AllBPtJ6W7zUh8d1GBqysUx7LP+Hm/svc4Z49bMGKmjsd4kFejt5+LPs1yo Czwg== X-Gm-Message-State: AGi0PuamOsBlp1LG62K9QNu2MKRCm/l7nu11Avu3IcdkZjTukj2P18LZ 5W8+CGFwDSuEHSfL9rSyDlV+v/3E X-Google-Smtp-Source: APiQypLXDuQZ3GJk3wX2TI+a9gaKA0kIC63OGoS6k6LixMHdUBgtyGL8iFZrS91BjaxHEPc4kxKJNg== X-Received: by 2002:a05:6000:1242:: with SMTP id j2mr9770599wrx.274.1588439871727; Sat, 02 May 2020 10:17:51 -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.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 10:17:51 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Sat, 2 May 2020 19:16:59 +0200 Message-Id: <20200502171700.28991-7-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 12/13] avformat/matroskaenc: Don't assert when writing huge files 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" EBML numbers are variable length numbers: Only seven bits of every byte are available to encode the number, the other bits encode the length of the number itself. So an eight byte EBML number can only encode numbers in the range 0..(2^56 - 1). And when using EBML numbers to encode the length of an EBML element, the EBML number corresponding to 2^56 - 1 is actually reserved to mean that the length of the corresponding element is unknown. And therefore put_ebml_length() asserted that the length it should represent is < 2^56 - 1. Yet there was nothing that actually guaranteed this to be true for the Segment (the main/root EBML element of a Matroska file that encompasses nearly the whole file). This commit changes this by checking in advance how big the length is and only updating the number if it is representable at all; if not, the unknown length element is not touched. Signed-off-by: Andreas Rheinhardt --- libavformat/matroskaenc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index dfc1563fc1..fd590597c9 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -2542,9 +2542,13 @@ static int mkv_write_trailer(AVFormatContext *s) } after_cues: + /* Lengths greater than (1ULL << 56) - 1 can't be represented + * via an EBML number, so leave the unknown length field. */ + if (endpos - mkv->segment_offset < (1ULL << 56) - 1) { 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) From patchwork Sat May 2 17:17:00 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Rheinhardt X-Patchwork-Id: 19442 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 1A47D44BB45 for ; Sat, 2 May 2020 20:18:01 +0300 (EEST) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 0200868C8AE; Sat, 2 May 2020 20:18:01 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f66.google.com (mail-wr1-f66.google.com [209.85.221.66]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 11A6B68C8A9 for ; Sat, 2 May 2020 20:17:54 +0300 (EEST) Received: by mail-wr1-f66.google.com with SMTP id x18so15702408wrq.2 for ; Sat, 02 May 2020 10:17:54 -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=ge7JObt0kYDMbXWJoJ9cuhh8ygkvWk5n1ja169NGq4Y=; b=Q0gZQlfp6O5f73+jsZ7HNIXOUtAmuZdZd1XuPsftS3vYKLlAaPqLeqpxcRxMIM8K2e 8ZeBSTyhcg4jCvguRkElbY/r3DnF4v1YoZL5+LX2J0dJQC6N4lEf+z5spQ+EStzB/JpK lyHV4tWdnRomEYVO68XRvXYUPkPc9bekmw6n5m8SOSQ9btlo+cD6T0X6+/C6yFA8Pe4f 1d6glmbT4he6+nAEYVF3kVfqi0ybVpYhNohAlscaBV3IohFgOWRor8lh8Zd6SKNfse5h Y3GP8g8P9pjlUi+0iebtA/yhEOst5ccXgCRyOWrBjbxqMc8G+ivlOb6JsbUlGzvw+aH6 YnYQ== 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=ge7JObt0kYDMbXWJoJ9cuhh8ygkvWk5n1ja169NGq4Y=; b=oqUe1Fm5icAsCWUU+oDJy8pnX3zkFy7Vc0dE+mx4QsGszAmIPcCrzFjbJ5OYFC/oCc Aq8R36q6+qnmOQjwsyqkXKp/kCPjMp/SF23ekfN5CjDOrdjSggjqDjiN/eV03pIzv/J/ Yfvj78SdTubhPsclUVOBnXWf+NARuGtynf0lrw5coW8XKVySLvcoGUhWU12UAU+cpdpz j35NihUHScjWSa5qK2Pt2doeY50MhjQjQ0BBKvqSS+MWg0WRE7NfV+vuDalJpfltIBcn ZzuDU6oDs3mcSfqLtz9GoxJno2seWqIe6M3zqhRTRcmcjpCAz3nggbUUQpJfAXkpDLvS OKRg== X-Gm-Message-State: AGi0PuZbMG3eziTVE31M7vJL/5FoYayOrhx8NelwtV9GxxgfydwNCVXj gYZPWbYjwDWMgzVt/eeEJFJf7H0E X-Google-Smtp-Source: APiQypI83tN1Ltip1xAHK4F0VGgXlgFN3xYkSzmg9knmEN2QSSUw/VeGywLjUNOBk2aG36iBo2hL4g== X-Received: by 2002:a5d:458a:: with SMTP id p10mr9748545wrq.273.1588439872773; Sat, 02 May 2020 10:17:52 -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.51 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 02 May 2020 10:17:52 -0700 (PDT) From: Andreas Rheinhardt To: ffmpeg-devel@ffmpeg.org Date: Sat, 2 May 2020 19:17:00 +0200 Message-Id: <20200502171700.28991-8-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 13/13] avformat/matroskaenc: Cosmetics 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" Mainly reindentation plus some reordering in MatroskaMuxContext; moreover, use the IS_SEEKABLE() macro troughout the code. Signed-off-by: Andreas Rheinhardt --- libavformat/matroskaenc.c | 298 +++++++++++++++++++------------------- 1 file changed, 148 insertions(+), 150 deletions(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index fd590597c9..d16d607269 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -98,7 +98,7 @@ typedef struct mkv_cuepoint { } mkv_cuepoint; typedef struct mkv_cues { - mkv_cuepoint *entries; + mkv_cuepoint *entries; int num_entries; } mkv_cues; @@ -121,42 +121,42 @@ typedef struct mkv_track { #define MODE_WEBM 0x02 typedef struct MatroskaMuxContext { - const AVClass *class; - int mode; - ebml_stored_master info; - ebml_stored_master track; - ebml_stored_master tags; - int64_t segment_offset; - AVIOContext *cluster_bc; - int64_t cluster_pos; ///< file offset of the current cluster - int64_t cluster_pts; - int64_t duration_offset; - int64_t duration; - mkv_seekhead seekhead; - mkv_cues cues; - mkv_track *tracks; - - AVPacket cur_audio_pkt; - - unsigned nb_attachments; - int have_video; - - int reserve_cues_space; - int cluster_size_limit; - int64_t cues_pos; - int64_t cluster_time_limit; - int is_dash; - int dash_track_number; - int is_live; - int write_crc; - - uint32_t chapter_id_offset; - int wrote_chapters; - - int allow_raw_vfw; - int default_mode; - - uint32_t segment_uid[4]; + const AVClass *class; + int mode; + ebml_stored_master info; + ebml_stored_master track; + ebml_stored_master tags; + int64_t segment_offset; + AVIOContext *cluster_bc; + int64_t cluster_pos; ///< file offset of the current Cluster + int64_t cluster_pts; + int64_t duration_offset; + int64_t duration; + mkv_track *tracks; + mkv_seekhead seekhead; + mkv_cues cues; + int64_t cues_pos; + + AVPacket cur_audio_pkt; + + unsigned nb_attachments; + int have_video; + + uint32_t chapter_id_offset; + int wrote_chapters; + + int reserve_cues_space; + int cluster_size_limit; + int64_t cluster_time_limit; + int write_crc; + int is_live; + + int is_dash; + int dash_track_number; + int allow_raw_vfw; + int default_mode; + + uint32_t segment_uid[4]; } MatroskaMuxContext; /** 2 bytes * 7 for EBML IDs, 7 1-byte EBML lengths, 6 1-byte uint, @@ -378,9 +378,9 @@ static int start_ebml_master_crc32(AVIOContext **dyn_cp, MatroskaMuxContext *mkv } static int end_ebml_master_crc32(AVIOContext *pb, AVIOContext **dyn_cp, - MatroskaMuxContext *mkv, uint32_t id, - int length_size, int keep_buffer, - int add_seekentry) + MatroskaMuxContext *mkv, uint32_t id, + int length_size, int keep_buffer, + int add_seekentry) { uint8_t *buf, crc[4]; int ret, size, skip = 0; @@ -415,11 +415,11 @@ fail: * Furthermore always add a SeekHead Entry for this element. */ static int end_ebml_master_crc32_tentatively(AVIOContext *pb, - ebml_stored_master *elem, - MatroskaMuxContext *mkv, uint32_t id) + ebml_stored_master *elem, + MatroskaMuxContext *mkv, uint32_t id) { - if ((pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live) { - uint8_t *buf; + if (IS_SEEKABLE(pb, mkv)) { + uint8_t *buf; int size = avio_get_dyn_buf(elem->bc, &buf); if (elem->bc->error < 0) @@ -428,9 +428,9 @@ static int end_ebml_master_crc32_tentatively(AVIOContext *pb, elem->pos = avio_tell(pb); mkv_add_seekhead_entry(mkv, id, elem->pos); - put_ebml_id(pb, id); - put_ebml_length(pb, size, 0); - avio_write(pb, buf, size); + put_ebml_id(pb, id); + put_ebml_length(pb, size, 0); + avio_write(pb, buf, size); return 0; } else @@ -818,17 +818,17 @@ static int mkv_write_codecprivate(AVFormatContext *s, AVIOContext *pb, } if (ret >= 0) { - codecpriv_size = avio_get_dyn_buf(dyn_cp, &codecpriv); + codecpriv_size = avio_get_dyn_buf(dyn_cp, &codecpriv); if ((ret = dyn_cp->error) >= 0 && codecpriv_size) - put_ebml_binary(pb, MATROSKA_ID_CODECPRIVATE, codecpriv, - codecpriv_size); + put_ebml_binary(pb, MATROSKA_ID_CODECPRIVATE, codecpriv, + codecpriv_size); } ffio_free_dyn_buf(&dyn_cp); return ret; } -static void mkv_write_video_color(AVIOContext *pb, const AVCodecParameters *par, - const AVStream *st) +static void mkv_write_video_color(AVIOContext *pb, const AVStream *st, + const AVCodecParameters *par) { /* 18 Elements with two bytes ID, one byte length field, 8 bytes payload * a master element with two bytes ID and one byte length field @@ -911,9 +911,8 @@ static void mkv_write_video_color(AVIOContext *pb, const AVCodecParameters *par, } colorinfo_size = avio_tell(dyn_cp); - if (colorinfo_size) { + if (colorinfo_size) put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLOR, colour, colorinfo_size); - } } static int mkv_write_video_projection(AVFormatContext *s, AVIOContext *pb, @@ -1306,7 +1305,7 @@ static int mkv_write_track(AVFormatContext *s, MatroskaMuxContext *mkv, uint32_t color_space = av_le2ne32(par->codec_tag); put_ebml_binary(pb, MATROSKA_ID_VIDEOCOLORSPACE, &color_space, sizeof(color_space)); } - mkv_write_video_color(pb, par, st); + mkv_write_video_color(pb, st, par); ret = mkv_write_video_projection(s, pb, st); if (ret < 0) @@ -1443,7 +1442,7 @@ static int mkv_write_tracks(AVFormatContext *s) } return end_ebml_master_crc32_tentatively(pb, &mkv->track, mkv, - MATROSKA_ID_TRACKS); + MATROSKA_ID_TRACKS); } static int mkv_write_chapters(AVFormatContext *s) @@ -1627,7 +1626,7 @@ static int mkv_write_tags(AVFormatContext *s) return ret; } - tagp = (s->pb->seekable & AVIO_SEEKABLE_NORMAL) && !mkv->is_live ? &tag : NULL; + tagp = IS_SEEKABLE(s->pb, mkv) ? &tag : NULL; for (i = 0; i < s->nb_streams; i++) { const AVStream *st = s->streams[i]; mkv_track *track = &mkv->tracks[i]; @@ -1695,7 +1694,7 @@ static int mkv_write_tags(AVFormatContext *s) if (mkv->tags.bc) { return end_ebml_master_crc32_tentatively(s->pb, &mkv->tags, mkv, - MATROSKA_ID_TAGS); + MATROSKA_ID_TAGS); } return 0; } @@ -1898,7 +1897,7 @@ static int mkv_write_header(AVFormatContext *s) if (ret < 0) return ret; - if (!(s->pb->seekable & AVIO_SEEKABLE_NORMAL) || mkv->is_live) { + if (!IS_SEEKABLE(pb, mkv)) { ret = mkv_write_seekhead(pb, mkv, 0, avio_tell(pb)); if (ret < 0) return ret; @@ -1912,10 +1911,10 @@ static int mkv_write_header(AVFormatContext *s) if (mkv->reserve_cues_space) { if (IS_SEEKABLE(pb, mkv)) { - mkv->cues_pos = avio_tell(pb); - if (mkv->reserve_cues_space == 1) - mkv->reserve_cues_space++; - put_ebml_void(pb, mkv->reserve_cues_space); + mkv->cues_pos = avio_tell(pb); + if (mkv->reserve_cues_space == 1) + mkv->reserve_cues_space++; + put_ebml_void(pb, mkv->reserve_cues_space); } else mkv->reserve_cues_space = -1; } @@ -2472,7 +2471,7 @@ static int mkv_write_trailer(AVFormatContext *s) if (mkv->cluster_pos != -1) { ret = end_ebml_master_crc32(pb, &mkv->cluster_bc, mkv, - MATROSKA_ID_CLUSTER, 0, 0, 0); + MATROSKA_ID_CLUSTER, 0, 0, 0); if (ret < 0) return ret; } @@ -2484,64 +2483,63 @@ static int mkv_write_trailer(AVFormatContext *s) if (!IS_SEEKABLE(pb, mkv)) return 0; - endpos = avio_tell(pb); + endpos = avio_tell(pb); - if (mkv->cues.num_entries && mkv->reserve_cues_space >= 0) { - AVIOContext *cues = NULL; - uint64_t size; - int length_size = 0; + if (mkv->cues.num_entries && mkv->reserve_cues_space >= 0) { + AVIOContext *cues = NULL; + uint64_t size; + int length_size = 0; - ret = start_ebml_master_crc32(&cues, mkv); - if (ret < 0) - return ret; + 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) { - ffio_free_dyn_buf(&cues); - return ret; - } + ret = mkv_assemble_cues(s->streams, cues, &mkv->cues, + mkv->tracks, s->nb_streams); + if (ret < 0) { + ffio_free_dyn_buf(&cues); + return ret; + } - if (mkv->reserve_cues_space) { - size = avio_tell(cues); - length_size = ebml_length_size(size); - size += 4 + length_size; - if (mkv->reserve_cues_space < size) { - av_log(s, AV_LOG_WARNING, - "Insufficient space reserved for Cues: " - "%d < %"PRIu64". No Cues will be output.\n", - mkv->reserve_cues_space, size); - ret2 = AVERROR(EINVAL); + if (mkv->reserve_cues_space) { + size = avio_tell(cues); + length_size = ebml_length_size(size); + size += 4 + length_size; + if (mkv->reserve_cues_space < size) { + av_log(s, AV_LOG_WARNING, + "Insufficient space reserved for Cues: " + "%d < %"PRIu64". No Cues will be output.\n", + mkv->reserve_cues_space, size); + ret2 = AVERROR(EINVAL); + goto after_cues; + } else { + if ((ret64 = avio_seek(pb, mkv->cues_pos, SEEK_SET)) < 0) { ffio_free_dyn_buf(&cues); - goto after_cues; - } else { - if ((ret64 = avio_seek(pb, mkv->cues_pos, SEEK_SET)) < 0) { - ffio_free_dyn_buf(&cues); - return ret64; - } - if (mkv->reserve_cues_space == size + 1) { - /* There is no way to reserve a single byte because - * the minimal size of an EBML Void element is 2 - * (1 byte ID, 1 byte length field). This problem - * is solved by writing the Cues' length field on - * one byte more than necessary. */ - length_size++; - size++; - } + return ret64; + } + if (mkv->reserve_cues_space == size + 1) { + /* There is no way to reserve a single byte because + * the minimal size of an EBML Void element is 2 + * (1 byte ID, 1 byte length field). This problem + * is solved by writing the Cues' length field on + * one byte more than necessary. */ + length_size++; + size++; } } - ret = end_ebml_master_crc32(pb, &cues, mkv, MATROSKA_ID_CUES, - length_size, 0, 1); - if (ret < 0) - return ret; - if (mkv->reserve_cues_space) { - if (size < mkv->reserve_cues_space) - put_ebml_void(pb, mkv->reserve_cues_space - size); - } else - endpos = avio_tell(pb); } + ret = end_ebml_master_crc32(pb, &cues, mkv, MATROSKA_ID_CUES, + length_size, 0, 1); + if (ret < 0) + return ret; + if (mkv->reserve_cues_space) { + if (size < mkv->reserve_cues_space) + put_ebml_void(pb, mkv->reserve_cues_space - size); + } else + endpos = avio_tell(pb); + } - after_cues: +after_cues: /* Lengths greater than (1ULL << 56) - 1 can't be represented * via an EBML number, so leave the unknown length field. */ if (endpos - mkv->segment_offset < (1ULL << 56) - 1) { @@ -2550,11 +2548,11 @@ static int mkv_write_trailer(AVFormatContext *s) put_ebml_length(pb, endpos - mkv->segment_offset, 8); } - ret = mkv_write_seekhead(pb, mkv, 1, mkv->info.pos); - if (ret < 0) - return ret; + ret = mkv_write_seekhead(pb, mkv, 1, mkv->info.pos); + if (ret < 0) + return ret; - if (mkv->info.bc) { + if (mkv->info.bc) { // update the duration av_log(s, AV_LOG_DEBUG, "end duration = %" PRIu64 "\n", mkv->duration); avio_seek(mkv->info.bc, mkv->duration_offset, SEEK_SET); @@ -2563,49 +2561,49 @@ static int mkv_write_trailer(AVFormatContext *s) MATROSKA_ID_INFO, 0, 0, 0); if (ret < 0) return ret; - } + } - if (mkv->track.bc) { - // write Tracks master - avio_seek(pb, mkv->track.pos, SEEK_SET); - ret = end_ebml_master_crc32(pb, &mkv->track.bc, mkv, - MATROSKA_ID_TRACKS, 0, 0, 0); - if (ret < 0) - return ret; - } + if (mkv->track.bc) { + // write Tracks master + avio_seek(pb, mkv->track.pos, SEEK_SET); + ret = end_ebml_master_crc32(pb, &mkv->track.bc, mkv, + MATROSKA_ID_TRACKS, 0, 0, 0); + if (ret < 0) + return ret; + } - // update stream durations - if (mkv->tags.bc) { - int i; - for (i = 0; i < s->nb_streams; ++i) { - const AVStream *st = s->streams[i]; - const mkv_track *track = &mkv->tracks[i]; + // update stream durations + if (mkv->tags.bc) { + int i; + for (i = 0; i < s->nb_streams; ++i) { + const AVStream *st = s->streams[i]; + const mkv_track *track = &mkv->tracks[i]; - if (track->duration_offset > 0) { - double duration_sec = track->duration * av_q2d(st->time_base); - char duration_string[20] = ""; + if (track->duration_offset > 0) { + double duration_sec = track->duration * av_q2d(st->time_base); + char duration_string[20] = ""; - av_log(s, AV_LOG_DEBUG, "stream %d end duration = %" PRIu64 "\n", i, - track->duration); + av_log(s, AV_LOG_DEBUG, "stream %d end duration = %" PRIu64 "\n", i, + track->duration); - avio_seek(mkv->tags.bc, track->duration_offset, SEEK_SET); + avio_seek(mkv->tags.bc, track->duration_offset, SEEK_SET); - snprintf(duration_string, 20, "%02d:%02d:%012.9f", - (int) duration_sec / 3600, ((int) duration_sec / 60) % 60, - fmod(duration_sec, 60)); + snprintf(duration_string, 20, "%02d:%02d:%012.9f", + (int) duration_sec / 3600, ((int) duration_sec / 60) % 60, + fmod(duration_sec, 60)); - put_ebml_binary(mkv->tags.bc, MATROSKA_ID_TAGSTRING, duration_string, 20); - } + put_ebml_binary(mkv->tags.bc, MATROSKA_ID_TAGSTRING, duration_string, 20); } - - avio_seek(pb, mkv->tags.pos, SEEK_SET); - ret = end_ebml_master_crc32(pb, &mkv->tags.bc, mkv, - MATROSKA_ID_TAGS, 0, 0, 0); - if (ret < 0) - return ret; } - avio_seek(pb, endpos, SEEK_SET); + avio_seek(pb, mkv->tags.pos, SEEK_SET); + ret = end_ebml_master_crc32(pb, &mkv->tags.bc, mkv, + MATROSKA_ID_TAGS, 0, 0, 0); + if (ret < 0) + return ret; + } + + avio_seek(pb, endpos, SEEK_SET); return ret2; }