MP4 reader: use track duration for frame duration for single-frame video tracks

Fixes #2747.
This commit is contained in:
Moritz Bunkus 2020-03-13 15:19:59 +01:00
parent 64b1679b23
commit 16fedc94d2
No known key found for this signature in database
GPG Key ID: 74AF00ADF2E32C85
4 changed files with 29 additions and 3 deletions

View File

@ -1,3 +1,11 @@
# Version ?
## Bug fixes
* mkvmerge: MP4 reader: fixed calculating the duration of video tracks that
only contain a single frame. Fixes #2747.
# Version 44.0.0 "Domino" 2020-03-08
## New features and enhancements

View File

@ -2104,8 +2104,20 @@ qtmp4_demuxer_c::calculate_frame_rate() {
return;
}
if (('v' == type) && time_scale && global_duration && (sample_table.size() < 2)) {
frame_rate = mtx::frame_timing::determine_frame_rate(static_cast<uint64_t>(global_duration) * 1'000'000'000ull / static_cast<uint64_t>(time_scale));
if (frame_rate)
m_use_frame_rate_for_duration = boost::rational_cast<int64_t>(int64_rational_c{1'000'000'000ll} / frame_rate);
mxdebug_if(m_debug_frame_rate,
fmt::format("calculate_frame_rate: case 2: video track with time scale {0} & duration {1} result: {2}\n",
time_scale, global_duration, frame_rate ? format_timestamp(*m_use_frame_rate_for_duration) : "<invalid>"s));
return;
}
if (sample_table.size() < 2) {
mxdebug_if(m_debug_frame_rate, fmt::format("calculate_frame_rate: case 2: sample table too small\n"));
mxdebug_if(m_debug_frame_rate, fmt::format("calculate_frame_rate: case 3: sample table too small\n"));
return;
}
@ -2126,7 +2138,7 @@ qtmp4_demuxer_c::calculate_frame_rate() {
m_use_frame_rate_for_duration = boost::rational_cast<int64_t>(int64_rational_c{1'000'000'000ll} / frame_rate);
mxdebug_if(m_debug_frame_rate,
fmt::format("calculate_frame_rate: case 3: duration {0} num_frames {1} frame_duration {2} frame_rate {3}/{4} use_frame_rate_for_duration {5}\n",
fmt::format("calculate_frame_rate: case 4: duration {0} num_frames {1} frame_duration {2} frame_rate {3}/{4} use_frame_rate_for_duration {5}\n",
duration, num_frames, duration / num_frames, frame_rate.numerator(), frame_rate.denominator(), m_use_frame_rate_for_duration ? *m_use_frame_rate_for_duration : -1));
return;
@ -2146,7 +2158,7 @@ qtmp4_demuxer_c::calculate_frame_rate() {
frame_rate.assign(static_cast<int64_t>(1000000000ll), to_nsecs(most_common.first));
mxdebug_if(m_debug_frame_rate,
fmt::format("calculate_frame_rate: case 4: duration {0} num_frames {1} frame_duration {2} most_common.num_occurances {3} most_common.duration {4} frame_rate {5}/{6}\n",
fmt::format("calculate_frame_rate: case 5: duration {0} num_frames {1} frame_duration {2} most_common.num_occurances {3} most_common.duration {4} frame_rate {5}/{6}\n",
duration, num_frames, duration / num_frames, most_common.second, to_nsecs(most_common.first), frame_rate.numerator(), frame_rate.denominator()));
}

View File

@ -535,3 +535,4 @@ T_686container_wrong_num_channels:true:passed:20200101-235713:0.009057097
T_687h264_additional_sps_pps_in_middle:3c9e0781b9b5e75be5dc3da6d59b8795:passed:20200105-163253:0.029150634
T_688opus_single_page:6ce93001a667609670ec7103450f622f:passed:20200113-193521:0.011219948
T_689mpeg_ts_mpeg_2_two_frames_only:b187d13ae7af1f6a61e7369c549cf2c4:passed:20200126-124111:0.034034657
T_690mp4_single_video_frame_duration:ff234c76e7626f78aded30b3c2ad6669:passed:20200313-151900:0.040140889

View File

@ -0,0 +1,5 @@
#!/usr/bin/ruby -w
# T_690mp4_single_video_frame_duration
describe "mkvmerge / MP4/MOV with a single video frame, calculating the frame duration"
test_merge "data/mp4/single_video_frame.mov", :args => "-A"