doc type version handler: create EBML Void inside EBML Head instead of after it

When the Matroska version numbers stored in the EBML Head element are
updated, the updated EBML Head element might be smaller than the
existing one. In that case the programs used to shrink the EBML Head &
write a small EBML Void element between the updated EBML Head & the
following element, usually a Matroska Segment element.

This isn't widely supported by programs including MKVToolNix itself,
causing them to declare such files as invalid.

The programs will now create the EBML Void element inside the EBML
Head element, making them a level 1 element instead of a level 0
element.

Affects mkvpropedit, MKVToolNix GUI's chapter & header editors.

Fixes #3355.
This commit is contained in:
Moritz Bunkus 2022-11-02 18:11:00 +01:00
parent 3c71f1d2e7
commit 375de02b36
No known key found for this signature in database
GPG Key ID: 74AF00ADF2E32C85
4 changed files with 34 additions and 6 deletions

View File

@ -26,6 +26,15 @@
those elements, even if they're found in the file to be modified. The
programs will no longer abort with error messages such as `assertion "false"
failed`. Fixes #3416.
* mkvpropedit, MKVToolNix GUI's chapter & header editors: when the Matroska
version numbers stored in the EBML Head element are updated, the updated
EBML Head element might be smaller than the existing one. In that case the
programs used to shrink the EBML Head & write a small EBML Void element
between the updated EBML Head & the following element, usually a Matroska
Segment element. This isn't widely supported by programs including
MKVToolNix itself, causing them to declare such files as invalid. The
programs will now create the EBML Void element inside the EBML Head element,
making them a level 1 element instead of a level 0 element. Fixes #3355.
# Version 71.1.0 "Fortitude" 2022-10-09

View File

@ -156,15 +156,18 @@ doc_type_version_handler_c::do_update_ebml_head(mm_io_c &file) {
if (diff == 1)
head->SetSizeLength(head->GetSizeLength() + 1);
else if (diff > 1) {
auto v = new EbmlVoid;
v->SetSize(diff - 2);
head->PushElement(*v);
new_size = head->UpdateSize(true);
mxdebug_if(p->debug, fmt::format("do_update_ebml_head: diff > 1 case; new size now {0}\n", new_size));
}
file.setFilePointer(head->GetElementPosition());
head->Render(*stream, true);
if (diff > 1) {
EbmlVoid v;
v.SetSize(diff - 2);
v.Render(*stream);
}
} catch (mtx::mm_io::exception &) {
return update_result_e::err_read_or_write_failure;
}

View File

@ -592,3 +592,4 @@ T_0744hevc_first_unspec_nalus_after_one_mb_of_data:8083c1cd24908eba1f86fec60e307
T_0745av1_single_frame:294681d11be5149ba29728a1e37a00bc:passed:20220730-122150:0.044258962
T_0746ogg_unknown_track_and_kate_missing_headers:43cb49944b1552ba9df35f2e1ed303d3:passed:20220904-153425:0.031062254
T_0747reversed_attachment_selection:ok-67de61ddef39f3a39fbf68136783b63b-ok-b5bc906a30ca7b969571d29b235cf80f-ok:passed:20221101-125728:0.367793332
T_0748doc_type_version_handler_create_void_in_ebml_head:4692b2494f3ab58b5e9c09e1ea9ba8c2-429b083f5497fd6085e80c24b660cae5:passed:20221102-180257:0.230079273

View File

@ -0,0 +1,15 @@
#!/usr/bin/ruby -w
# T_748doc_type_version_handler_create_void_in_ebml_head
describe "mkvpropedit / doc type version handler should create void inside EBLM Head, not on top level"
work = "#{tmp}.work"
test "propedit" do
cp "data/mkv/bug3355.mkv", work
propedit work, "--tags track:1:data/tags/bug3355.xml --edit info --set title=Test"
hash_file work
end
test_identify work