]> git.sesse.net Git - vlc/blob - modules/demux/mkv/Ebml_parser.cpp
var_InheritInteger -> var_InheritBool
[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     for( int i = 1; i < mi_level; i++ )
51     {
52         if( !mb_keep )
53         {
54             delete m_el[i];
55         }
56         mb_keep = false;
57     }
58 }
59
60 EbmlElement* EbmlParser::UnGet( uint64 i_block_pos, uint64 i_cluster_pos )
61 {
62     if ( mi_user_level > mi_level )
63     {
64         while ( mi_user_level != mi_level )
65         {
66             delete m_el[mi_user_level];
67             m_el[mi_user_level] = NULL;
68             mi_user_level--;
69         }
70     }
71     m_got = NULL;
72     mb_keep = false;
73     if ( m_el[1]->GetElementPosition() == i_cluster_pos )
74     {
75         m_es->I_O().setFilePointer( i_block_pos, seek_beginning );
76         return (EbmlMaster*) m_el[1];
77     }
78     else
79     {
80         // seek to the previous Cluster
81         m_es->I_O().setFilePointer( i_cluster_pos, seek_beginning );
82         mi_level--;
83         mi_user_level--;
84         delete m_el[mi_level];
85         m_el[mi_level] = NULL;
86         return NULL;
87     }
88 }
89
90 void EbmlParser::Up( void )
91 {
92     if( mi_user_level == mi_level )
93     {
94         fprintf( stderr,"MKV/Ebml Parser: Up cannot escape itself\n" );
95     }
96
97     mi_user_level--;
98 }
99
100 void EbmlParser::Down( void )
101 {
102     mi_user_level++;
103     mi_level++;
104 }
105
106 void EbmlParser::Keep( void )
107 {
108     mb_keep = true;
109 }
110
111 int EbmlParser::GetLevel( void )
112 {
113     return mi_user_level;
114 }
115
116 void EbmlParser::Reset( demux_t *p_demux )
117 {
118     while ( mi_level > 0)
119     {
120         delete m_el[mi_level];
121         m_el[mi_level] = NULL;
122         mi_level--;
123     }
124     mi_user_level = mi_level = 1;
125     // a little faster and cleaner
126     m_es->I_O().setFilePointer( static_cast<KaxSegment*>(m_el[0])->GetGlobalPosition(0) );
127     mb_dummy = var_InheritBool( p_demux, "mkv-use-dummy" );
128 }
129
130 EbmlElement *EbmlParser::Get( void )
131 {
132     int i_ulev = 0;
133
134     if( mi_user_level != mi_level )
135     {
136         return NULL;
137     }
138     if( m_got )
139     {
140         EbmlElement *ret = m_got;
141         m_got = NULL;
142
143         return ret;
144     }
145
146     if( m_el[mi_level] )
147     {
148         m_el[mi_level]->SkipData( *m_es, m_el[mi_level]->Generic().Context );
149         if( !mb_keep )
150         {
151             if( MKV_IS_ID( m_el[mi_level], KaxBlockVirtual ) )
152                 static_cast<KaxBlockVirtualWorkaround*>(m_el[mi_level])->Fix();
153             delete m_el[mi_level];
154         }
155         mb_keep = false;
156     }
157
158     m_el[mi_level] = m_es->FindNextElement( m_el[mi_level - 1]->Generic().Context, i_ulev, 0xFFFFFFFFL, mb_dummy != 0, 1 );
159 //    mi_remain_size[mi_level] = m_el[mi_level]->GetSize();
160     if( i_ulev > 0 )
161     {
162         while( i_ulev > 0 )
163         {
164             if( mi_level == 1 )
165             {
166                 mi_level = 0;
167                 return NULL;
168             }
169
170             delete m_el[mi_level - 1];
171             m_got = m_el[mi_level -1] = m_el[mi_level];
172             m_el[mi_level] = NULL;
173
174             mi_level--;
175             i_ulev--;
176         }
177         return NULL;
178     }
179     else if( m_el[mi_level] == NULL )
180     {
181         fprintf( stderr,"MKV/Ebml Parser: m_el[mi_level] == NULL\n" );
182     }
183
184     return m_el[mi_level];
185 }
186
187 bool EbmlParser::IsTopPresent( EbmlElement *el )
188 {
189     for( int i = 0; i < mi_level; i++ )
190     {
191         if( m_el[i] && m_el[i] == el )
192             return true;
193     }
194     return false;
195 }
196