From 12a82f9c997927e0f6a9f58e80351e6d3069f67f Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Fri, 5 Sep 2014 18:32:28 +0200 Subject: [PATCH] QT/MP4 reader: fix edit list handling for its duration field The duration is expressed in the file's time scale while the position is expressed in the track's time scale. Fixes #1059. --- ChangeLog | 5 +++++ src/input/r_qtmp4.cpp | 21 +++++++++++-------- tests/results.txt | 5 +++-- ...it_list_duration_uses_global_time_scale.rb | 4 ++++ 4 files changed, 24 insertions(+), 11 deletions(-) create mode 100755 tests/test-435mp4_edit_list_duration_uses_global_time_scale.rb diff --git a/ChangeLog b/ChangeLog index 167450365..5f08f483c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2014-09-05 Moritz Bunkus + + * mkvmerge: bug fix: Fixed handling certain edit list types in MP4 + files that are used for positive track delays. Fixes #1059. + 2014-08-09 Moritz Bunkus * source: Fixed compilation with Boost 1.56.0 which changed the diff --git a/src/input/r_qtmp4.cpp b/src/input/r_qtmp4.cpp index a79cfa1cb..923658102 100644 --- a/src/input/r_qtmp4.cpp +++ b/src/input/r_qtmp4.cpp @@ -1888,8 +1888,9 @@ qtmp4_demuxer_c::update_editlist_table(int64_t global_time_scale) { if (editlist_table.empty()) return; - int simple_editlist_type = 0; - int64_t offset_to_apply = 0; + auto simple_editlist_type = 0u; + int64_t raw_offset = 0; + auto offset_in_global_time_scale = false; if ((editlist_table.size() == 1) && (0 == editlist_table[0].pos)) { mxdebug_if(m_debug_editlists, boost::format("Track ID %1%: Edit list analysis: type 1: one entry, zero time\n") % id); @@ -1899,13 +1900,16 @@ qtmp4_demuxer_c::update_editlist_table(int64_t global_time_scale) { mxdebug_if(m_debug_editlists, boost::format("Track ID %1%: Edit list analysis: type 2: one entry, positive time, %2%\n") % id % (frame_offset_table.empty() ? "no frame offset table" : frame_offset_table[0] == editlist_table[0].pos ? "same as first frame offset" : "different from first frame offset")); - simple_editlist_type = 2; - offset_to_apply = -editlist_table[0].pos + (frame_offset_table.empty() ? 0 : frame_offset_table[0]); + simple_editlist_type = 2; + raw_offset = editlist_table[0].pos; + constant_editlist_offset_ns = (-editlist_table[0].pos + (frame_offset_table.empty() ? 0 : frame_offset_table[0])) * 1000000000ll / time_scale; } else if ((editlist_table.size() == 2) && (-1 == editlist_table[0].pos) && (0 == editlist_table[1].pos)) { mxdebug_if(m_debug_editlists, boost::format("Track ID %1%: Edit list analysis: type 3: two entries; first with time == -1, second zero time\n") % id); - simple_editlist_type = 3; - offset_to_apply = editlist_table[0].duration - (frame_offset_table.empty() ? 0 : frame_offset_table[0]); + simple_editlist_type = 3; + raw_offset = editlist_table[0].duration; + constant_editlist_offset_ns = (editlist_table[0].duration * 1000000000ll / global_time_scale) - ((frame_offset_table.empty() ? 0 : frame_offset_table[0]) * 1000000000ll / time_scale); + offset_in_global_time_scale = true; } else if (m_debug_editlists) { std::stringstream output; @@ -1915,12 +1919,11 @@ qtmp4_demuxer_c::update_editlist_table(int64_t global_time_scale) { } if (simple_editlist_type) { - constant_editlist_offset_ns = offset_to_apply * 1000000000ll / time_scale; editlist_table.clear(); mxdebug_if(m_debug_editlists, - boost::format("Track ID %1%: Simple edit list type detected. Offset in track's time scale: %2%; as a timecode: %3%; track scale %4%\n") - % id % offset_to_apply % format_timecode(constant_editlist_offset_ns) % time_scale); + boost::format("Track ID %1%: Simple edit list type detected. Offset in %5%'s time scale: %2%; as a timecode: %3%; time scale %4%\n") + % id % raw_offset % format_timecode(constant_editlist_offset_ns) % (offset_in_global_time_scale ? global_time_scale : time_scale) % (offset_in_global_time_scale ? "file" : "track")); return; } diff --git a/tests/results.txt b/tests/results.txt index 8bca29884..3461d54f8 100644 --- a/tests/results.txt +++ b/tests/results.txt @@ -209,8 +209,8 @@ T_360X_chapters_hex_format:87a60c81c05fb0a153a2e041485ae2cb-3853793b0d88fc10efad T_361file_concatenation:427fc997022d6940b27f1ecdc94d77ce-44a61a38ad7cd4dff63cf391a67fb6af-44a61a38ad7cd4dff63cf391a67fb6af-30ff14be9bcf252e33a607a19da0dc19-30ff14be9bcf252e33a607a19da0dc19-30ff14be9bcf252e33a607a19da0dc19-96a0ceb37fbec40ee2b112a2d533bdb0-5964d7e75075cfb17d2647ae084ee5d6-740607972d7bb60c595835efdb9d880d-740607972d7bb60c595835efdb9d880d-740607972d7bb60c595835efdb9d880d-740607972d7bb60c595835efdb9d880d-09ffbb6cd3ce4f4947f1f2e782be6cdd-d7039c2d63d417c29d4ba7bf623563e5-80e456901895bd509cc8f2f6ed10d587-80e456901895bd509cc8f2f6ed10d587:passed:20120406-144928:18.646532342 T_362xtr_avc:abc9dd7b4579a2e14783271d1d64d486-49ae33bdb1e43de90886bc2ac6410c35:passed:20120416-153515:1.811589633 T_363srt_colon_decimal_separator:d75be97f27797c8b3fc62e5d39a8d7ea:passed:20120520-180625:0.032379535 -T_364qtmp4_track_with_empty_chunkmap_table:802219cda79837dd71f6640ae530d633:passed:20120605-223925:0.168392001 -T_365qtmp4_constant_sample_size:3d572fbc411f3ec5a53d7eed8668d7ce-4ba44dddb6beaab3415910dc6160b79a:passed:20120605-230823:0.675175697 +T_364qtmp4_track_with_empty_chunkmap_table:f7837ed142ed9a5cca5d2fbc5788d597:passed:20120605-223925:0.168392001 +T_365qtmp4_constant_sample_size:3d572fbc411f3ec5a53d7eed8668d7ce-eba0b6ddc51c05e4a97f39a3bb350b01:passed:20120605-230823:0.675175697 T_366srt_with_space_in_timecode_arrow:ad8e2cdf5de8ba4b845ac4894ef7296b:passed:20120801-132204:0.121731174 T_367vob_80ms_delay_by_b_frames:2a85681425d9111d6106abfbf5ced906-75d4a446c1e564466db16d5b5b4cc144:passed:20120801-182507:0.106468603 T_368alac:ef55ca2ffd57f92348ebc9ebff011c10-c150a9b2183810011fa20961cf7de72f-a4cdc118b8e884218dc2bd8191b28b46-1f07d381ad4911f3b7a93b92e439f238:passed:20120805-160128:0.596006157 @@ -280,3 +280,4 @@ T_431ssa_comments_exclamation_mark:3caa9ad1716134cc1f3e229b88ff94ea:passed:20140 T_432concatenate_two_ac3_files:4f4b7c58d4557d52849866e1a3ad1b05:passed:20140727-124637:0.15390456 T_433matroska_no_track_uid:32eaa074a254eab81b90bd97be50c425:passed:20140809-211544:0.043556355 T_434mkvpropedit_no_track_uid:99631d7c0f79faf45a37696dae506b21-0c411b1fc48d546f9fbeb6185e43f74f:passed:20140809-213018:0.046441804 +T_435mp4_edit_list_duration_uses_global_time_scale:eba0b6ddc51c05e4a97f39a3bb350b01:passed:20140905-183027:0.096674624 diff --git a/tests/test-435mp4_edit_list_duration_uses_global_time_scale.rb b/tests/test-435mp4_edit_list_duration_uses_global_time_scale.rb new file mode 100755 index 000000000..13e4bd617 --- /dev/null +++ b/tests/test-435mp4_edit_list_duration_uses_global_time_scale.rb @@ -0,0 +1,4 @@ +#!/usr/bin/ruby -w + +describe "mkvmerge / QuickTime/MP4 files with edit lists whose duration must be used with global time scale" +test_merge "data/mp4/fixed_sample_size2.mp4", :exit_code => :warning