]> git.sesse.net Git - vlc/blobdiff - modules/demux/mkv/Ebml_parser.cpp
Regression fix for non-SPU tracks in MKV containers.
[vlc] / modules / demux / mkv / Ebml_parser.cpp
index 2283e921b172f4b67b006cfbdbfa0ad4b08f0e7d..6890f418d7cad14aa151e393a2b8a33d4b9b06f2 100644 (file)
@@ -121,6 +121,11 @@ void EbmlParser::Keep( void )
     mb_keep = true;
 }
 
+void EbmlParser::Unkeep()
+{
+    mb_keep = false;
+}
+
 int EbmlParser::GetLevel( void ) const
 {
     return mi_user_level;
@@ -164,11 +169,11 @@ EbmlElement *EbmlParser::Get( int n_call )
         m_el[mi_level]->SkipData( *m_es, EBML_CONTEXT(m_el[mi_level]) );
 
     }
-    vlc_stream_io_callback & io_stream = (vlc_stream_io_callback &) m_es->I_O();
-    uint64 i_size = io_stream.toRead();
+
+    /* Ignore unknown level 0 or 1 elements */
     m_el[mi_level] = m_es->FindNextElement( EBML_CONTEXT(m_el[mi_level - 1]),
-                                            i_ulev, i_size, true, 1 );
-//    mi_remain_size[mi_level] = m_el[mi_level]->GetSize();
+                                            i_ulev, UINT64_MAX,
+                                            (  mb_dummy | (mi_level > 1) ), 1 );
     if( i_ulev > 0 )
     {
         if( p_prev )
@@ -214,7 +219,8 @@ EbmlElement *EbmlParser::Get( int n_call )
         }
 
         if( p_prev && p_prev->IsFiniteSize() &&
-            p_prev->GetEndPosition() != m_el[mi_level]->GetElementPosition())
+            p_prev->GetEndPosition() != m_el[mi_level]->GetElementPosition() &&
+            mi_level > 1 )
         {
             msg_Err( p_demux, "Dummy Element at unexpected position... corrupted file?" );
             b_bad_position = true;
@@ -225,13 +231,29 @@ EbmlElement *EbmlParser::Get( int n_call )
               m_el[mi_level]->GetEndPosition() <= m_el[mi_level-1]->GetEndPosition() ) )
         {
             /* The element fits inside its upper element */
-            msg_Warn( p_demux, "Dummy element found... skipping it" );
+            msg_Warn( p_demux, "Dummy element found %"PRIu64"... skipping it",
+                      m_el[mi_level]->GetElementPosition() );
             return Get( ++n_call );
         }
         else
         {
             /* Too large, misplaced or 10 successive dummy elements */
-            msg_Err( p_demux, "Dummy element too large or misplaced... skipping to next upper element" );
+            msg_Err( p_demux,
+                     "Dummy element too large or misplaced at %"PRIu64"... skipping to next upper element",
+                     m_el[mi_level]->GetElementPosition() );
+
+            if( mi_level >= 1 &&
+                m_el[mi_level]->GetElementPosition() >= m_el[mi_level-1]->GetEndPosition() )
+            {
+                msg_Err(p_demux, "This element is outside its known parent... upping level");
+                delete m_el[mi_level - 1];
+                m_got = m_el[mi_level -1] = m_el[mi_level];
+                m_el[mi_level] = NULL;
+
+                mi_level--;
+                return NULL;
+            }
+
             delete m_el[mi_level];
             m_el[mi_level] = NULL;
             m_el[mi_level - 1]->SkipData( *m_es, EBML_CONTEXT(m_el[mi_level - 1]) );