kax_reader_c: use kax_file_c for reading the headers

kax_file_c has built-in error resilience and will re-sync to the next
level 1 element in case of a structural error. This way a structural
error before the first cluster won't cause mkvmerge to abort the reading
process.

Fixes #1654.
This commit is contained in:
Moritz Bunkus 2016-04-09 15:48:10 +02:00
parent d64e55e630
commit f82360deb8
3 changed files with 21 additions and 40 deletions

View File

@ -1,3 +1,9 @@
2016-04-09 Moritz Bunkus <moritz@bunkus.org>
* mkvmerge: bug fix: mkvmerge will no longer abort reading a
Matroska file with a structural error right before the first
cluster. Fixes #1654.
2016-04-03 Moritz Bunkus <moritz@bunkus.org>
* mkvmerge: enhancement: added the muxing date in both local time

View File

@ -1276,11 +1276,13 @@ bool
kax_reader_c::read_headers_internal() {
// Elements for different levels
auto cluster = std::unique_ptr<KaxCluster>{};
auto cluster = std::shared_ptr<KaxCluster>{};
try {
m_es = std::shared_ptr<EbmlStream>(new EbmlStream(*m_in));
m_in_file = std::make_shared<kax_file_c>(*m_in);
m_in_file->enable_reporting(!g_identifying);
// Find the EbmlHead element. Must be the first one.
EbmlElement *l0 = m_es->FindNextID(EBML_INFO(EbmlHead), 0xFFFFFFFFFFFFFFFFLL);
if (!l0) {
@ -1309,39 +1311,33 @@ kax_reader_c::read_headers_internal() {
m_in_file->set_segment_end(*l0);
// We've got our segment, so let's find the m_tracks
int upper_lvl_el = 0;
m_tc_scale = TIMECODE_SCALE;
EbmlElement *l1 = nullptr;
m_tc_scale = TIMECODE_SCALE;
while (m_in->getFilePointer() < m_in_file->get_segment_end()) {
auto l1 = ebml_element_cptr{ m_in_file->read_next_level1_element() };
if (!l1)
l1 = m_es->FindNextElement(EBML_CONTEXT(l0), upper_lvl_el, 0xFFFFFFFFL, true, 1);
if (!l1 || (0 < upper_lvl_el)) {
delete l1;
break;
}
if (Is<KaxInfo>(l1))
if (Is<KaxInfo>(*l1))
m_deferred_l1_positions[dl1t_info].push_back(l1->GetElementPosition());
else if (Is<KaxTracks>(l1))
else if (Is<KaxTracks>(*l1))
m_deferred_l1_positions[dl1t_tracks].push_back(l1->GetElementPosition());
else if (Is<KaxAttachments>(l1))
else if (Is<KaxAttachments>(*l1))
m_deferred_l1_positions[dl1t_attachments].push_back(l1->GetElementPosition());
else if (Is<KaxChapters>(l1))
else if (Is<KaxChapters>(*l1))
m_deferred_l1_positions[dl1t_chapters].push_back(l1->GetElementPosition());
else if (Is<KaxTags>(l1))
else if (Is<KaxTags>(*l1))
m_deferred_l1_positions[dl1t_tags].push_back(l1->GetElementPosition());
else if (Is<KaxSeekHead>(l1))
else if (Is<KaxSeekHead>(*l1))
handle_seek_head(m_in.get(), l0, l1->GetElementPosition());
else if (Is<KaxCluster>(l1))
cluster.reset(static_cast<KaxCluster *>(l1));
else if (Is<KaxCluster>(*l1))
cluster = std::static_pointer_cast<KaxCluster>(l1);
else
l1->SkipData(*m_es, EBML_CONTEXT(l1));
@ -1349,31 +1345,10 @@ kax_reader_c::read_headers_internal() {
if (cluster) // we've found the first cluster, so get out
break;
if (!in_parent(l0)) {
delete l1;
if (!in_parent(l0))
break;
}
if (upper_lvl_el > 0) {
upper_lvl_el--;
if (upper_lvl_el > 0)
break;
delete l1;
l1 = nullptr;
continue;
} else if (upper_lvl_el < 0) {
upper_lvl_el++;
if (upper_lvl_el < 0)
break;
}
l1->SkipData(*m_es, EBML_CONTEXT(l1));
delete l1;
l1 = m_es->FindNextElement(EBML_CONTEXT(l0), upper_lvl_el, 0xFFFFFFFFL, true);
if (!l1)
break;
} // while (l1)

View File

@ -294,7 +294,7 @@ T_445teletext_subs_missing_second_line:ffbf578cd2806634b76d8e4322600c56:passed:2
T_446mkvinfo_output:d79a79c6c267d83604fb5dedfb361220-05d21f5e324d5b02a5f4bc1a44c58e13-a1a990a98a530744fe2f18d2dedcb116-bea802377f7e6f09efdb90a2e0ed11c9:passed:20141216-165433:2.799686224
T_447mkvinfo_rounded_timecodes:1af5a15e4e84818e9f85221fbc621b00-2a3771b863ced8cf1c624a5df5eafadb-7a77f3e6264e1881e42980bbc85a9e1a:passed:20141216-172642:1.712081143
T_448mpeg_ts_with_hevc:6733a551eacab4145ed267bea8a4d75c:passed:20141216-181650:1.133097273
T_449segfaults_assertions:error-error-04aa38adf31451c85a19f490ca040dd8-e5484c528a96c5f3fd678ea6bd99a8f2-d0c5f7db319baa4adbd3b965f2c505d5-d560ddb71dfdc430be462588ec38e789-error-error-91eca98ea8df1f307644d5d17d8f0f95-36602f6d1d981cd429f54a6a39b023d8-91eca98ea8df1f307644d5d17d8f0f95-e5484c528a96c5f3fd678ea6bd99a8f2-e5484c528a96c5f3fd678ea6bd99a8f2-f89d13bdea53445e67c78c042f7f783e-565d2ce6866560056a2e929279f88e8e-f89d13bdea53445e67c78c042f7f783e:passed:20141219-195127:0.830949441
T_449segfaults_assertions:error-error-06096bf8b416ae2c869f6bc32e88213a-e5484c528a96c5f3fd678ea6bd99a8f2-d0c5f7db319baa4adbd3b965f2c505d5-d560ddb71dfdc430be462588ec38e789-error-error-91eca98ea8df1f307644d5d17d8f0f95-36602f6d1d981cd429f54a6a39b023d8-91eca98ea8df1f307644d5d17d8f0f95-e5484c528a96c5f3fd678ea6bd99a8f2-e5484c528a96c5f3fd678ea6bd99a8f2-f89d13bdea53445e67c78c042f7f783e-565d2ce6866560056a2e929279f88e8e-f89d13bdea53445e67c78c042f7f783e:passed:20141219-195127:0.830949441
T_450aac_loas_latm_in_mpeg_ts:2e174e28aecb0f318fbfd8e9647dbd3c:passed:20141229-210738:0.515183095
T_451aac_loas_latm_raw:5a2db12f6eea0bcd37a5d524d8c4c91c:passed:20141230-155351:0.589778873
T_452mkvinfo_track_statistics_frame_order:cb9a860b00fd306fe85e2ac3ee698c17-d49ee464e7ea3eefbbc3e3b4707a308a:passed:20141230-182428:1.579605124