From def48b26062152e4a0c1def579370c3ea751c894 Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Tue, 4 Jul 2017 20:29:17 +0200 Subject: [PATCH] AVC/h.264 parser: flush queued frames on SPS/PPS changes Whenever a sequence parameter set or picture parameter set changes (meaning an SPS with the same ID as an earlier SPS but with different content is found), all frames queued for order & timestamp calculation must be flushed. Otherwise frame order calculation will be based on wrong values for some frames and on correct values for other frames. Fixes #2028. --- NEWS.md | 3 +++ src/common/mpeg4_p10.cpp | 5 +++++ tests/results.txt | 3 ++- ...h264_changing_sps_pps_wrong_frame_order_and_timestamps.rb | 5 +++++ 4 files changed, 15 insertions(+), 1 deletion(-) create mode 100755 tests/test-605h264_changing_sps_pps_wrong_frame_order_and_timestamps.rb diff --git a/NEWS.md b/NEWS.md index cba173a4b..377b84e07 100644 --- a/NEWS.md +++ b/NEWS.md @@ -7,6 +7,9 @@ * MKVToolNix GUI: multiplex tool: implemented a workaround for a crash that could occur during drag & drop if at least one of the columns is hidden. Fixes #2009. +* mkvmerge: AVC/h.264 parser: fixed wrong frame order & timestamp calculation + in certain situations when SPS (sequence parameter sets) or PPS (picture + parameter sets) change mid-sream. Fixes #2028. # Version 13.0.0 "The Juggler" 2017-06-25 diff --git a/src/common/mpeg4_p10.cpp b/src/common/mpeg4_p10.cpp index 29b855041..dd6df6851 100644 --- a/src/common/mpeg4_p10.cpp +++ b/src/common/mpeg4_p10.cpp @@ -1197,6 +1197,8 @@ mpeg4::p10::avc_es_parser_c::handle_sps_nalu(memory_cptr const &nalu) { } else if (m_sps_info_list[i].checksum != sps_info.checksum) { mxdebug_if(m_debug_sps_pps_changes, boost::format("mpeg4::p10: SPS ID %|1$04x| changed; checksum old %|2$04x| new %|3$04x|\n") % sps_info.id % m_sps_info_list[i].checksum % sps_info.checksum); + cleanup(); + m_sps_info_list[i] = sps_info; m_sps_list[i] = parsed_nalu; m_avcc_changed = true; @@ -1247,6 +1249,9 @@ mpeg4::p10::avc_es_parser_c::handle_pps_nalu(memory_cptr const &nalu) { } else if (m_pps_info_list[i].checksum != pps_info.checksum) { mxdebug_if(m_debug_sps_pps_changes, boost::format("mpeg4::p10: PPS ID %|1$04x| changed; checksum old %|2$04x| new %|3$04x|\n") % pps_info.id % m_pps_info_list[i].checksum % pps_info.checksum); + if (m_pps_info_list[i].sps_id != pps_info.sps_id) + cleanup(); + m_pps_info_list[i] = pps_info; m_pps_list[i] = nalu; m_avcc_changed = true; diff --git a/tests/results.txt b/tests/results.txt index 3726df9e2..77710ccc9 100644 --- a/tests/results.txt +++ b/tests/results.txt @@ -78,7 +78,7 @@ T_228h264_no_idr_slices:320e3ea079952e80e1110c3b1aac2dac:passed:20070426-103130: T_229rav3_in_rm:3db8200918c4d94c59a1aeb15c0409f1:passed:20070619-220659:0.054850494 T_230h264_nalu_size_len_change:47e6449dbc974aaad4755bcab8f8be3f-993026f0388f0b1e6ea8be8c2ec55b37:passed:20070622-103843:0.273132819 T_231X_ac3_header_removal:6ca341797c5f93e273c8502f4d6f4fba:passed:20070623-111240:0.172661551 -T_232h264_changing_sps_pps:943f7ef3ef518ac5cf03829e4748ed49:passed:20070815-211934:4.982966207 +T_232h264_changing_sps_pps:bdc21768407975be6275dc3abeb2bcae:passed:20070815-211934:4.982966207 T_233srt_with_coordinates:0de6cfc206a5889a5bd7afc8ddd9bdb8:passed:20070819-203105:0.279280932 T_234avi_aac_codecid_0x706d:5d6ff6aca9c26ed9cf51bb1aaa32b10e:passed:20080223-174500:1.065188599 T_235wav_fmt_chunk_length:4a02ad008c2b504e3b9d702dabccfb4d:passed:20080226-134540:0.199256803 @@ -450,3 +450,4 @@ T_601mp4_mpeg2_via_esds:5cadaf9b8dd86a51052182ed341a4bc0:passed:20170618-150319: T_602vob_with_garbage_at_start:c34788ceb7d96fe4ea073c6227026bea:passed:20170619-185256:0.236132323 T_603mpeg_ps_ac3_not_enough_data_in_first_packet:1+189+128+AC_3/E_AC_3-2+189+129+AC_3/E_AC_3-3+189+130+AC_3/E_AC_3-4+189+131+AC_3/E_AC_3-5+189+132+AC_3/E_AC_3-6+189+133+AC_3/E_AC_3-7+189+134+AC_3/E_AC_3:passed:20170624-092201:0.028142136 T_604append_only_one_video_track_with_codec_private:ec52119afb52345809a1c5c1a43b6fe0:passed:20170624-105837:0.144927484 +T_605h264_changing_sps_pps_wrong_frame_order_and_timestamps:1af409bd8266567525c54a0799de44cc:passed:20170704-211727:0.912982996 diff --git a/tests/test-605h264_changing_sps_pps_wrong_frame_order_and_timestamps.rb b/tests/test-605h264_changing_sps_pps_wrong_frame_order_and_timestamps.rb new file mode 100755 index 000000000..fab0767ed --- /dev/null +++ b/tests/test-605h264_changing_sps_pps_wrong_frame_order_and_timestamps.rb @@ -0,0 +1,5 @@ +#!/usr/bin/ruby -w + +# T_605h264_changing_sps_pps_wrong_frame_order_and_timestamps +describe "mkvmerge / AVC/h.264 wrong frame order & timestamps due to changing SPS/PPS" +test_merge "data/h264/changing-sps-pps2.h264"