]> git.sesse.net Git - vlc/blob - modules/demux/mkv/Ebml_parser.cpp
Added an assert in mkv.
[vlc] / modules / demux / mkv / Ebml_parser.cpp
1
2 /*****************************************************************************
3  * EbmlParser for the matroska demuxer
4  *****************************************************************************
5  * Copyright (C) 2003-2004 the VideoLAN team
6  * $Id$
7  *
8  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
9  *          Steve Lhomme <steve.lhomme@free.fr>
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
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 General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24  *****************************************************************************/
25
26 #include "Ebml_parser.hpp"
27
28 /*****************************************************************************
29  * Ebml Stream parser
30  *****************************************************************************/
31 EbmlParser::EbmlParser( EbmlStream *es, EbmlElement *el_start, demux_t *p_demux )
32 {
33     m_es = es;
34     m_got = NULL;
35     m_el[0] = el_start;
36     mi_remain_size[0] = el_start->GetSize();
37
38     for( int i = 1; i < 6; i++ )
39     {
40         m_el[i] = NULL;
41     }
42     mi_level = 1;
43     mi_user_level = 1;
44     mb_keep = false;
45     mb_dummy = var_InheritBool( p_demux, "mkv-use-dummy" );
46 }
47
48 EbmlParser::~EbmlParser( void )
49 {
50     if( !mi_level )
51     {
52         assert( !mb_keep );
53         delete m_el[1];
54         return;
55     }
56
57     for( int i = 1; i <= mi_level; i++ )
58     {
59         if( !mb_keep )
60         {
61             delete m_el[i];
62         }
63         mb_keep = false;
64     }
65 }
66
67 EbmlElement* EbmlParser::UnGet( uint64 i_block_pos, uint64 i_cluster_pos )
68 {
69     if ( mi_user_level > mi_level )
70     {
71         while ( mi_user_level != mi_level )
72         {
73             delete m_el[mi_user_level];
74             m_el[mi_user_level] = NULL;
75             mi_user_level--;
76         }
77     }
78     m_got = NULL;
79     mb_keep = false;
80     if ( m_el[1]->GetElementPosition() == i_cluster_pos )
81     {
82         m_es->I_O().setFilePointer( i_block_pos, seek_beginning );
83         return (EbmlMaster*) m_el[1];
84     }
85     else
86     {
87         // seek to the previous Cluster
88         m_es->I_O().setFilePointer( i_cluster_pos, seek_beginning );
89         mi_level--;
90         mi_user_level--;
91         delete m_el[mi_level];
92         m_el[mi_level] = NULL;
93         return NULL;
94     }
95 }
96
97 void EbmlParser::Up( void )
98 {
99     if( mi_user_level == mi_level )
100     {
101         fprintf( stderr,"MKV/Ebml Parser: Up cannot escape itself\n" );
102     }
103
104     mi_user_level--;
105 }
106
107 void EbmlParser::Down( void )
108 {
109     mi_user_level++;
110     mi_level++;
111 }
112
113 void EbmlParser::Keep( void )
114 {
115     mb_keep = true;
116 }
117
118 int EbmlParser::GetLevel( void )
119 {
120     return mi_user_level;
121 }
122
123 void EbmlParser::Reset( demux_t *p_demux )
124 {
125     while ( mi_level > 0)
126     {
127         delete m_el[mi_level];
128         m_el[mi_level] = NULL;
129         mi_level--;
130     }
131     mi_user_level = mi_level = 1;
132     // a little faster and cleaner
133     m_es->I_O().setFilePointer( static_cast<KaxSegment*>(m_el[0])->GetGlobalPosition(0) );
134     mb_dummy = var_InheritBool( p_demux, "mkv-use-dummy" );
135 }
136
137 EbmlElement *EbmlParser::Get( void )
138 {
139     int i_ulev = 0;
140
141     if( mi_user_level != mi_level )
142     {
143         return NULL;
144     }
145     if( m_got )
146     {
147         EbmlElement *ret = m_got;
148         m_got = NULL;
149
150         return ret;
151     }
152
153     if( m_el[mi_level] )
154     {
155         m_el[mi_level]->SkipData( *m_es, m_el[mi_level]->Generic().Context );
156         if( !mb_keep )
157         {
158             if( MKV_IS_ID( m_el[mi_level], KaxBlockVirtual ) )
159                 static_cast<KaxBlockVirtualWorkaround*>(m_el[mi_level])->Fix();
160             delete m_el[mi_level];
161         }
162         mb_keep = false;
163     }
164
165     m_el[mi_level] = m_es->FindNextElement( m_el[mi_level - 1]->Generic().Context, i_ulev, 0xFFFFFFFFL, mb_dummy != 0, 1 );
166 //    mi_remain_size[mi_level] = m_el[mi_level]->GetSize();
167     if( i_ulev > 0 )
168     {
169         while( i_ulev > 0 )
170         {
171             if( mi_level == 1 )
172             {
173                 mi_level = 0;
174                 return NULL;
175             }
176
177             delete m_el[mi_level - 1];
178             m_got = m_el[mi_level -1] = m_el[mi_level];
179             m_el[mi_level] = NULL;
180
181             mi_level--;
182             i_ulev--;
183         }
184         return NULL;
185     }
186     else if( m_el[mi_level] == NULL )
187     {
188         fprintf( stderr,"MKV/Ebml Parser: m_el[mi_level] == NULL\n" );
189     }
190
191     return m_el[mi_level];
192 }
193
194 bool EbmlParser::IsTopPresent( EbmlElement *el )
195 {
196     for( int i = 0; i < mi_level; i++ )
197     {
198         if( m_el[i] && m_el[i] == el )
199             return true;
200     }
201     return false;
202 }
203