2 /*****************************************************************************
3 * EbmlParser for the matroska demuxer
4 *****************************************************************************
5 * Copyright (C) 2003-2004 VLC authors and VideoLAN
8 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
9 * Steve Lhomme <steve.lhomme@free.fr>
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
26 #include "Ebml_parser.hpp"
27 #include "stream_io_callback.hpp"
29 /*****************************************************************************
31 *****************************************************************************/
32 EbmlParser::EbmlParser( EbmlStream
*es
, EbmlElement
*el_start
, demux_t
*p_demux
,
40 mb_dummy( b_with_dummy
)
42 memset( m_el
, 0, sizeof( *m_el
) * M_EL_MAXSIZE
);
46 EbmlParser::~EbmlParser( void )
55 for( int i
= 1; i
<= mi_level
; i
++ )
65 void EbmlParser::reconstruct( EbmlStream
* es
, EbmlElement
* el_start
, demux_t
* p_demux
)
67 this->reconstruct( es
, el_start
, p_demux
, var_InheritBool( p_demux
, "mkv-use-dummy" ) );
70 void EbmlParser::reconstruct( EbmlStream
* es
, EbmlElement
* el_start
, demux_t
* p_demux
,
75 new( static_cast<void*>( this ) ) EbmlParser(
76 es
, el_start
, p_demux
, b_with_dummy
80 void EbmlParser::Up( void )
82 if( mi_user_level
== mi_level
&& m_el
[mi_level
] )
84 msg_Warn( p_demux
, "MKV/Ebml Parser: Up cannot escape itself" );
90 void EbmlParser::Down( void )
96 void EbmlParser::Keep( void )
101 void EbmlParser::Unkeep()
106 int EbmlParser::GetLevel( void ) const
108 return mi_user_level
;
111 void EbmlParser::Reset( demux_t
*p_demux
)
113 while ( mi_level
> 0)
115 delete m_el
[mi_level
];
116 m_el
[mi_level
] = NULL
;
119 this->p_demux
= p_demux
;
120 mi_user_level
= mi_level
= 1;
121 // a little faster and cleaner
122 m_es
->I_O().setFilePointer( static_cast<KaxSegment
*>(m_el
[0])->GetGlobalPosition(0) );
126 static const EbmlSemanticContext
& GetEbmlNoGlobal_Context();
127 static const EbmlSemanticContext EbmlNoGlobal_Context
= EbmlSemanticContext(0, NULL
, NULL
, *GetEbmlNoGlobal_Context
, NULL
);
128 static const EbmlSemanticContext
& GetEbmlNoGlobal_Context()
130 return EbmlNoGlobal_Context
;
133 // the Segment Context should not allow Void or CRC32 elements to avoid lookup false alarm
134 const EbmlSemanticContext Context_KaxSegmentVLC
= EbmlSemanticContext(KaxSegment_Context
.GetSize(),
135 KaxSegment_Context
.MyTable
,
136 KaxSegment_Context
.Parent(),
137 GetEbmlNoGlobal_Context
,
138 KaxSegment_Context
.GetMaster());
140 EbmlElement
*EbmlParser::Get( int n_call
)
143 EbmlElement
*p_prev
= NULL
;
145 if( mi_user_level
!= mi_level
)
151 EbmlElement
*ret
= m_got
;
157 p_prev
= m_el
[mi_level
];
159 p_prev
->SkipData( *m_es
, EBML_CONTEXT(p_prev
) );
161 // If the parent is a segment, use the segment context when creating children
162 // (to prolong their lifetime), otherwise just continue as normal
163 EbmlSemanticContext e_context
=
164 EBML_CTX_MASTER( EBML_CONTEXT(m_el
[mi_level
- 1]) ) == EBML_CTX_MASTER( Context_KaxSegmentVLC
)
165 ? Context_KaxSegmentVLC
166 : EBML_CONTEXT(m_el
[mi_level
- 1]);
168 /* Ignore unknown level 0 or 1 elements */
169 m_el
[mi_level
] = m_es
->FindNextElement( e_context
,
171 ( mb_dummy
| (mi_level
> 1) ), 1 );
178 if( MKV_IS_ID( p_prev
, KaxBlockVirtual
) )
179 static_cast<KaxBlockVirtualWorkaround
*>(p_prev
)->Fix(); // !! WARNING : TODO !! this is undefined-behavior
192 delete m_el
[mi_level
- 1];
193 m_got
= m_el
[mi_level
-1] = m_el
[mi_level
];
194 m_el
[mi_level
] = NULL
;
201 else if( m_el
[mi_level
] == NULL
)
203 msg_Dbg( p_demux
,"MKV/Ebml Parser: m_el[mi_level] == NULL" );
205 else if( m_el
[mi_level
]->IsDummy() && !mb_dummy
)
207 bool b_bad_position
= false;
208 /* We got a dummy element but don't want those...
209 * perform a sanity check */
212 msg_Err(p_demux
, "Got invalid lvl 0 element... Aborting");
217 p_prev
&& p_prev
->IsFiniteSize() &&
218 p_prev
->GetEndPosition() != m_el
[mi_level
]->GetElementPosition() )
220 msg_Err( p_demux
, "Dummy Element at unexpected position... corrupted file?" );
221 b_bad_position
= true;
224 if( n_call
< M_EL_MAXSIZE
&& !b_bad_position
&& m_el
[mi_level
]->IsFiniteSize() &&
225 ( !m_el
[mi_level
-1]->IsFiniteSize() ||
226 m_el
[mi_level
]->GetEndPosition() <= m_el
[mi_level
-1]->GetEndPosition() ) )
228 /* The element fits inside its upper element */
229 msg_Warn( p_demux
, "Dummy element found %" PRIu64
"... skipping it",
230 m_el
[mi_level
]->GetElementPosition() );
231 return Get( ++n_call
);
235 /* Too large, misplaced or M_EL_MAXSIZE successive dummy elements */
237 "Dummy element too large or misplaced at %" PRIu64
"... skipping to next upper element",
238 m_el
[mi_level
]->GetElementPosition() );
241 m_el
[mi_level
]->GetElementPosition() >= m_el
[mi_level
-1]->GetEndPosition() )
243 msg_Err(p_demux
, "This element is outside its known parent... upping level");
244 delete m_el
[mi_level
- 1];
245 m_got
= m_el
[mi_level
-1] = m_el
[mi_level
];
246 m_el
[mi_level
] = NULL
;
252 delete m_el
[mi_level
];
255 m_el
[mi_level
] = NULL
;
256 m_el
[mi_level
- 1]->SkipData( *m_es
, EBML_CONTEXT(m_el
[mi_level
- 1]) );
265 if( MKV_IS_ID( p_prev
, KaxBlockVirtual
) )
266 static_cast<KaxBlockVirtualWorkaround
*>(p_prev
)->Fix();
271 return m_el
[mi_level
];
274 bool EbmlParser::IsTopPresent( EbmlElement
*el
) const
276 for( int i
= 0; i
< mi_level
; i
++ )
278 if( m_el
[i
] && m_el
[i
] == el
)