From 80b8135bd5ba2dc351b381c7216d89eb3f725e47 Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Fri, 1 May 2020 08:46:38 +0200 Subject: [PATCH] Matroska reader: fix tag chapter UID targets when regenerating chapter UIDs Fixes #2804. --- NEWS.md | 3 +++ src/common/chapters/chapters.cpp | 21 +++++++++++++++---- src/common/chapters/chapters.h | 2 +- src/input/r_matroska.cpp | 8 +++---- tests/results.txt | 1 + ...fix_tags_when_regenerating_chapter_uids.rb | 5 +++++ 6 files changed, 31 insertions(+), 9 deletions(-) create mode 100755 tests/test-694fix_tags_when_regenerating_chapter_uids.rb diff --git a/NEWS.md b/NEWS.md index df0a52ce1..4fbe17678 100644 --- a/NEWS.md +++ b/NEWS.md @@ -39,6 +39,9 @@ frame). Fixes #2790. * mkvmerge: MP4 reader: fixed a crash that could potentially happen while trying to identify H.265/HEVC tracks. +* mkvmerge: when regenerating UIDs for chapters read from Matroska files + mkvmerge will now fix referencing tag chapter UID targets to have the same + values. Fixes #2804. # Version 45.0.0 "Heaven in Pennies" 2020-04-04 diff --git a/src/common/chapters/chapters.cpp b/src/common/chapters/chapters.cpp index 3bd760db5..2f3e41286 100644 --- a/src/common/chapters/chapters.cpp +++ b/src/common/chapters/chapters.cpp @@ -1063,8 +1063,9 @@ align_uids(KaxChapters &reference, } } -void -regenerate_uids(EbmlMaster &master) { +static void +regenerate_uids_worker(EbmlMaster &master, + std::unordered_map &new_chapter_uids) { for (int idx = 0, end = master.ListSize(); end > idx; ++idx) { auto element = master[idx]; auto edition_uid = dynamic_cast(element); @@ -1077,16 +1078,28 @@ regenerate_uids(EbmlMaster &master) { auto chapter_uid = dynamic_cast(element); if (chapter_uid) { - chapter_uid->SetValue(create_unique_number(UNIQUE_CHAPTER_IDS)); + new_chapter_uids[chapter_uid->GetValue()] = create_unique_number(UNIQUE_CHAPTER_IDS); + chapter_uid->SetValue(new_chapter_uids[chapter_uid->GetValue()]); continue; } auto sub_master = dynamic_cast(master[idx]); if (sub_master) - regenerate_uids(*sub_master); + regenerate_uids_worker(*sub_master, new_chapter_uids); } } +void +regenerate_uids(EbmlMaster &master, + EbmlMaster *tags) { + std::unordered_map new_chapter_uids; + + regenerate_uids_worker(master, new_chapter_uids); + + if (tags) + change_values(*tags, new_chapter_uids); +} + std::string format_name_template(std::string const &name_template, int chapter_number, diff --git a/src/common/chapters/chapters.h b/src/common/chapters/chapters.h index 877ac906c..6ad232054 100644 --- a/src/common/chapters/chapters.h +++ b/src/common/chapters/chapters.h @@ -88,7 +88,7 @@ void move_by_edition(libmatroska::KaxChapters &dst, libmatroska::KaxChapters &sr void adjust_timestamps(libebml::EbmlMaster &master, int64_t offset, int64_t numerator = 1, int64_t denominator = 1); void merge_entries(libebml::EbmlMaster &master); int count_atoms(libebml::EbmlMaster &master); -void regenerate_uids(libebml::EbmlMaster &master); +void regenerate_uids(libebml::EbmlMaster &master, libebml::EbmlMaster *tags = nullptr); void align_uids(libmatroska::KaxChapters *chapters); void align_uids(libmatroska::KaxChapters &reference, libmatroska::KaxChapters &modify); diff --git a/src/input/r_matroska.cpp b/src/input/r_matroska.cpp index 1e4a4f4b3..c9ebb7ea3 100644 --- a/src/input/r_matroska.cpp +++ b/src/input/r_matroska.cpp @@ -892,7 +892,7 @@ kax_reader_c::handle_chapters(mm_io_c *io, delete element_found; if (m_regenerate_chapter_uids) - mtx::chapters::regenerate_uids(*tmp_chapters); + mtx::chapters::regenerate_uids(*tmp_chapters, m_tags.get()); if (!m_chapters) m_chapters = mtx::chapters::kax_cptr{new KaxChapters}; @@ -1470,13 +1470,13 @@ kax_reader_c::read_deferred_level1_elements(KaxSegment &segment) { for (auto position : m_deferred_l1_positions[dl1t_attachments]) handle_attachments(m_in.get(), &segment, position); + for (auto position : m_deferred_l1_positions[dl1t_tags]) + handle_tags(m_in.get(), &segment, position); + if (!m_ti.m_no_chapters) for (auto position : m_deferred_l1_positions[dl1t_chapters]) handle_chapters(m_in.get(), &segment, position); - for (auto position : m_deferred_l1_positions[dl1t_tags]) - handle_tags(m_in.get(), &segment, position); - handle_track_statistics_tags(); if (!m_ti.m_no_global_tags) diff --git a/tests/results.txt b/tests/results.txt index 9d552d538..0b3e36828 100644 --- a/tests/results.txt +++ b/tests/results.txt @@ -539,3 +539,4 @@ T_690mp4_single_video_frame_duration:ff234c76e7626f78aded30b3c2ad6669:passed:202 T_691hevc_in_mp4_no_ctts_atom_no_sei_nalus:c387b9839708d0e9e8fe1595f42b873d:passed:20200412-163012:0.114639239 T_692splitting_chapter_name_in_file_name:f90456eacc7f481da6c37f3e0fc897ff:passed:20200425-145924:0.063961157 T_693keeping_source_id_tags:d3e6334130baa038d7108fe94bc4e7fe:passed:20200426-123650:0.067781165 +T_694fix_tags_when_regenerating_chapter_uids:6a126f4bc74051802aac90369addec15:passed:20200501-084512:0.046681713 diff --git a/tests/test-694fix_tags_when_regenerating_chapter_uids.rb b/tests/test-694fix_tags_when_regenerating_chapter_uids.rb new file mode 100755 index 000000000..473bb3e3e --- /dev/null +++ b/tests/test-694fix_tags_when_regenerating_chapter_uids.rb @@ -0,0 +1,5 @@ +#!/usr/bin/ruby -w + +# T_694fix_tags_when_regenerating_chapter_uids +describe "mkvmerge / regenerate chapter UIDs but fix tag chapter UIDs in the process" +test_merge "data/mkv/chapters_tags_max_size_field_size.mkv"