/src/vlc/modules/demux/mkv/matroska_segment.cpp
Line | Count | Source |
1 | | /***************************************************************************** |
2 | | * matroska_segment.cpp : matroska demuxer |
3 | | ***************************************************************************** |
4 | | * Copyright (C) 2003-2010 VLC authors and VideoLAN |
5 | | * |
6 | | * Authors: Laurent Aimar <fenrir@via.ecp.fr> |
7 | | * Steve Lhomme <steve.lhomme@free.fr> |
8 | | * |
9 | | * This program is free software; you can redistribute it and/or modify it |
10 | | * under the terms of the GNU Lesser General Public License as published by |
11 | | * the Free Software Foundation; either version 2.1 of the License, or |
12 | | * (at your option) any later version. |
13 | | * |
14 | | * This program is distributed in the hope that it will be useful, |
15 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | | * GNU Lesser General Public License for more details. |
18 | | * |
19 | | * You should have received a copy of the GNU Lesser General Public License |
20 | | * along with this program; if not, write to the Free Software Foundation, |
21 | | * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. |
22 | | *****************************************************************************/ |
23 | | |
24 | | #include "matroska_segment.hpp" |
25 | | #include "chapters.hpp" |
26 | | #include "demux.hpp" |
27 | | #include "util.hpp" |
28 | | #include "Ebml_dispatcher.hpp" |
29 | | |
30 | | #include <vlc_arrays.h> |
31 | | |
32 | | #include <new> |
33 | | #include <iterator> |
34 | | #include <limits> |
35 | | |
36 | | namespace mkv { |
37 | | |
38 | | matroska_segment_c::matroska_segment_c( demux_sys_t & demuxer, matroska_iostream_c & estream, KaxSegment *p_seg ) |
39 | 1.71k | :segment(p_seg) |
40 | 1.71k | ,es(estream) |
41 | 1.71k | ,i_timescale(MKVD_TIMECODESCALE) |
42 | 1.71k | ,i_duration(-1) |
43 | 1.71k | ,i_mk_start_time(0) |
44 | 1.71k | ,i_seekhead_count(0) |
45 | 1.71k | ,i_seekhead_position(-1) |
46 | 1.71k | ,i_cues_position(-1) |
47 | 1.71k | ,i_tracks_position(-1) |
48 | 1.71k | ,i_info_position(-1) |
49 | 1.71k | ,i_chapters_position(-1) |
50 | 1.71k | ,i_attachments_position(-1) |
51 | 1.71k | ,cluster(NULL) |
52 | 1.71k | ,i_block_pos(0) |
53 | 1.71k | ,p_segment_uid(NULL) |
54 | 1.71k | ,p_prev_segment_uid(NULL) |
55 | 1.71k | ,p_next_segment_uid(NULL) |
56 | 1.71k | ,b_cues(false) |
57 | 1.71k | ,psz_muxing_application(NULL) |
58 | 1.71k | ,psz_writing_application(NULL) |
59 | 1.71k | ,psz_title(NULL) |
60 | 1.71k | ,i_default_edition(0) |
61 | 1.71k | ,sys(demuxer) |
62 | 1.71k | ,ep( EbmlParser(&estream, p_seg, &demuxer.demuxer )) |
63 | 1.71k | ,b_preloaded(false) |
64 | 1.71k | ,b_ref_external_segments(false) |
65 | 1.71k | { |
66 | 1.71k | } |
67 | | |
68 | | matroska_segment_c::~matroska_segment_c() |
69 | 1.71k | { |
70 | 1.71k | free( psz_writing_application ); |
71 | 1.71k | free( psz_muxing_application ); |
72 | 1.71k | free( psz_title ); |
73 | | |
74 | 1.71k | delete segment; |
75 | 1.71k | delete p_segment_uid; |
76 | 1.71k | delete p_prev_segment_uid; |
77 | 1.71k | delete p_next_segment_uid; |
78 | | |
79 | 1.71k | vlc_delete_all( stored_editions ); |
80 | 1.71k | vlc_delete_all( translations ); |
81 | 1.71k | vlc_delete_all( families ); |
82 | 1.71k | } |
83 | | |
84 | | |
85 | | /***************************************************************************** |
86 | | * Tools * |
87 | | ***************************************************************************** |
88 | | * * LoadCues : load the cues element and update index |
89 | | * * LoadTags : load ... the tags element |
90 | | * * InformationCreate : create all information, load tags if present |
91 | | *****************************************************************************/ |
92 | | void matroska_segment_c::LoadCues( KaxCues *cues ) |
93 | 150 | { |
94 | 150 | EbmlElement *el; |
95 | | |
96 | 150 | if( b_cues ) |
97 | 0 | { |
98 | 0 | msg_Warn( &sys.demuxer, "There can be only 1 Cues per section." ); |
99 | 0 | return; |
100 | 0 | } |
101 | | |
102 | 150 | EbmlParser eparser (&es, cues, &sys.demuxer ); |
103 | 12.4k | while( ( el = eparser.Get() ) != NULL ) |
104 | 12.2k | { |
105 | 12.2k | if( MKV_IS_ID( el, KaxCuePoint ) ) |
106 | 12.1k | { |
107 | 12.1k | uint64_t cue_position = -1; |
108 | 12.1k | vlc_tick_t cue_mk_time = -1; |
109 | | |
110 | 12.1k | unsigned int track_id = 0; |
111 | 12.1k | bool b_invalid_cue = false; |
112 | | |
113 | 12.1k | eparser.Down(); |
114 | 36.2k | while( ( el = eparser.Get() ) != NULL ) |
115 | 24.1k | { |
116 | 24.1k | if ( MKV_CHECKED_PTR_DECL( cuetime, KaxCueTime, el ) ) |
117 | 12.0k | { |
118 | 12.0k | try |
119 | 12.0k | { |
120 | 12.0k | if( unlikely( !cuetime->ValidateSize() ) ) |
121 | 0 | { |
122 | 0 | msg_Err( &sys.demuxer, "CueTime size too big"); |
123 | 0 | b_invalid_cue = true; |
124 | 0 | break; |
125 | 0 | } |
126 | 12.0k | cuetime->ReadData( es.I_O() ); |
127 | 12.0k | } |
128 | 12.0k | catch(...) |
129 | 12.0k | { |
130 | 0 | msg_Err( &sys.demuxer, "Error while reading CueTime" ); |
131 | 0 | b_invalid_cue = true; |
132 | 0 | break; |
133 | 0 | } |
134 | 12.0k | cue_mk_time = VLC_TICK_FROM_NS(static_cast<uint64_t>( *cuetime ) * i_timescale); |
135 | 12.0k | } |
136 | 12.0k | else if( MKV_IS_ID( el, KaxCueTrackPositions ) ) |
137 | 12.0k | { |
138 | 12.0k | eparser.Down(); |
139 | 12.0k | try |
140 | 12.0k | { |
141 | 46.7k | while( ( el = eparser.Get() ) != NULL ) |
142 | 34.6k | { |
143 | 34.6k | if( unlikely( !el->ValidateSize() ) ) |
144 | 0 | { |
145 | 0 | eparser.Up(); |
146 | 0 | msg_Err( &sys.demuxer, "Error %s too big, aborting", EBML_NAME(el) ); |
147 | 0 | b_invalid_cue = true; |
148 | 0 | break; |
149 | 0 | } |
150 | | |
151 | 34.6k | if( MKV_CHECKED_PTR_DECL ( kct_ptr, KaxCueTrack, el ) ) |
152 | 12.0k | { |
153 | 12.0k | kct_ptr->ReadData( es.I_O() ); |
154 | 12.0k | track_id = static_cast<uint16_t>( *kct_ptr ); |
155 | 12.0k | } |
156 | 22.6k | else if( MKV_CHECKED_PTR_DECL ( kccp_ptr, KaxCueClusterPosition, el ) ) |
157 | 12.0k | { |
158 | 12.0k | kccp_ptr->ReadData( es.I_O() ); |
159 | 12.0k | cue_position = segment->GetGlobalPosition( static_cast<uint64_t>( *kccp_ptr ) ); |
160 | | |
161 | 12.0k | _seeker.add_cluster_position( cue_position ); |
162 | 12.0k | } |
163 | 10.6k | else if( MKV_CHECKED_PTR_DECL ( kcbn_ptr, KaxCueBlockNumber, el ) ) |
164 | 10.3k | { |
165 | 10.3k | VLC_UNUSED( kcbn_ptr ); |
166 | 10.3k | } |
167 | 230 | #if LIBMATROSKA_VERSION >= 0x010401 |
168 | 230 | else if( MKV_CHECKED_PTR_DECL( cuerelative, KaxCueRelativePosition, el ) ) |
169 | 215 | { |
170 | | // IGNORE |
171 | 215 | cuerelative->ReadData( es.I_O() ); |
172 | 215 | } |
173 | 15 | else if( MKV_CHECKED_PTR_DECL( cueblock, KaxCueBlockNumber, el ) ) |
174 | 0 | { |
175 | | // IGNORE |
176 | 0 | cueblock->ReadData( es.I_O() ); |
177 | 0 | } |
178 | 15 | else if( MKV_CHECKED_PTR_DECL( cueref, KaxCueReference, el ) ) |
179 | 0 | { |
180 | | // IGNORE |
181 | 0 | cueref->ReadData( es.I_O(), SCOPE_ALL_DATA ); |
182 | 0 | } |
183 | 15 | else if( MKV_CHECKED_PTR_DECL( cueduration, KaxCueDuration, el ) ) |
184 | 8 | { |
185 | | /* For future use */ |
186 | 8 | cueduration->ReadData( es.I_O() ); |
187 | 8 | } |
188 | 7 | #endif |
189 | 7 | else |
190 | 7 | { |
191 | 7 | msg_Dbg( &sys.demuxer, " * Unknown (%s)", EBML_NAME(el) ); |
192 | 7 | } |
193 | 34.6k | } |
194 | 12.0k | } |
195 | 12.0k | catch(...) |
196 | 12.0k | { |
197 | 1 | eparser.Up(); |
198 | 1 | msg_Err( &sys.demuxer, "Error while reading %s", EBML_NAME(el) ); |
199 | 1 | b_invalid_cue = true; |
200 | 1 | break; |
201 | 1 | } |
202 | 12.0k | eparser.Up(); |
203 | 12.0k | } |
204 | 3 | else |
205 | 3 | { |
206 | 3 | msg_Dbg( &sys.demuxer, " * Unknown (%s)", EBML_NAME(el) ); |
207 | 3 | } |
208 | 24.1k | } |
209 | 12.1k | eparser.Up(); |
210 | | |
211 | 12.1k | if( track_id != 0 && cue_mk_time != -1 && cue_position != static_cast<uint64_t>( -1 ) ) { |
212 | | |
213 | 11.9k | SegmentSeeker::Seekpoint::TrustLevel level = SegmentSeeker::Seekpoint::DISABLED; |
214 | | |
215 | 11.9k | if( ! b_invalid_cue && tracks.find( track_id ) != tracks.end() ) |
216 | 10.6k | { |
217 | 10.6k | level = sys.trust_cues ? |
218 | 0 | SegmentSeeker::Seekpoint::TRUSTED : |
219 | 10.6k | SegmentSeeker::Seekpoint::QUESTIONABLE; |
220 | 10.6k | } |
221 | | |
222 | 11.9k | _seeker.add_seekpoint( track_id, |
223 | 11.9k | SegmentSeeker::Seekpoint( cue_position, cue_mk_time, level ) ); |
224 | 11.9k | } |
225 | 12.1k | } |
226 | 173 | else |
227 | 173 | { |
228 | 173 | msg_Dbg( &sys.demuxer, " * Unknown (%s)", EBML_NAME(el) ); |
229 | 173 | } |
230 | 12.2k | } |
231 | 150 | b_cues = true; |
232 | 150 | msg_Dbg( &sys.demuxer, "| - loading cues done." ); |
233 | 150 | } |
234 | | |
235 | | |
236 | | static const struct { |
237 | | vlc_meta_type_t type; |
238 | | const char *key; |
239 | | int target_type; /* 0 is valid for all target_type */ |
240 | | } metadata_map[] = { |
241 | | {vlc_meta_ShowName, "TITLE", 70}, |
242 | | {vlc_meta_Album, "TITLE", 50}, |
243 | | {vlc_meta_Title, "TITLE", 30}, |
244 | | {vlc_meta_DiscNumber, "PART_NUMBER", 60}, |
245 | | {vlc_meta_Season, "PART_NUMBER", 60}, |
246 | | {vlc_meta_Episode, "PART_NUMBER", 50}, |
247 | | {vlc_meta_TrackNumber, "PART_NUMBER", 30}, |
248 | | {vlc_meta_DiscTotal, "TOTAL_PARTS", 70}, |
249 | | {vlc_meta_TrackTotal, "TOTAL_PARTS", 30}, |
250 | | {vlc_meta_Setting, "ENCODER_SETTINGS", 0}, |
251 | | /* TODO read TagLanguage {vlc_meta_Language} */ |
252 | | /* TODO read tags targeting attachments {vlc_meta_ArtworkURL, */ |
253 | | {vlc_meta_AlbumArtist, "ARTIST", 50}, |
254 | | {vlc_meta_Artist, "ARTIST", 0}, |
255 | | {vlc_meta_Director, "DIRECTOR", 0}, |
256 | | {vlc_meta_Actors, "ACTOR", 0}, |
257 | | {vlc_meta_Genre, "GENRE", 0}, |
258 | | {vlc_meta_Copyright, "COPYRIGHT", 0}, |
259 | | {vlc_meta_Description, "DESCRIPTION", 0}, |
260 | | {vlc_meta_Description, "COMMENT", 0}, |
261 | | {vlc_meta_Rating, "RATING", 0}, |
262 | | {vlc_meta_Date, "DATE_RELEASED", 0}, |
263 | | {vlc_meta_Date, "DATE_RELEASE", 0}, |
264 | | {vlc_meta_Date, "DATE_RECORDED", 0}, |
265 | | {vlc_meta_URL, "URL", 0}, |
266 | | {vlc_meta_Publisher, "PUBLISHER", 0}, |
267 | | {vlc_meta_EncodedBy, "ENCODED_BY", 0}, |
268 | | {vlc_meta_Album, "ALBUM", 0}, /* invalid tag */ |
269 | | {vlc_meta_Title, NULL, 0}, |
270 | | }; |
271 | | |
272 | | bool matroska_segment_c::ParseSimpleTags( SimpleTag* pout_simple, KaxTagSimple *tag, int target_type ) |
273 | 535 | { |
274 | 535 | msg_Dbg( &sys.demuxer, "| + Simple Tag "); |
275 | 535 | struct SimpleTagHandlerPayload |
276 | 535 | { |
277 | 535 | matroska_segment_c * const obj; |
278 | 535 | EbmlParser * const ep; |
279 | 535 | demux_sys_t & sys; |
280 | 535 | SimpleTag & out; |
281 | 535 | int target_type; |
282 | 535 | } payload = { this, &ep, sys, *pout_simple, 50 }; |
283 | 535 | MKV_SWITCH_CREATE( EbmlTypeDispatcher, SimpleTagHandler, SimpleTagHandlerPayload ) |
284 | 535 | { |
285 | 535 | MKV_SWITCH_INIT(); |
286 | 535 | E_CASE( KaxTagName, entry ) |
287 | 535 | { |
288 | 467 | vars.out.tag_name = UTFstring( entry ).GetUTF8().c_str(); |
289 | 467 | } |
290 | 535 | E_CASE( KaxTagString, entry ) |
291 | 535 | { |
292 | 464 | vars.out.value = UTFstring( entry ).GetUTF8().c_str(); |
293 | 464 | } |
294 | 535 | E_CASE( KaxTagLangue, entry ) |
295 | 535 | { |
296 | 44 | vars.out.lang = entry.GetValue(); |
297 | 44 | } |
298 | 535 | E_CASE( KaxTagDefault, unused ) |
299 | 535 | { |
300 | 0 | VLC_UNUSED(unused); |
301 | 0 | VLC_UNUSED(vars); |
302 | 0 | } |
303 | 535 | E_CASE( KaxTagSimple, simple ) |
304 | 535 | { |
305 | 0 | SimpleTag st; // ParseSimpleTags will write to this variable |
306 | | // the SimpleTag is valid if ParseSimpleTags returns `true` |
307 | |
|
308 | 0 | if (vars.obj->ParseSimpleTags( &st, &simple, vars.target_type )) |
309 | 0 | vars.out.sub_tags.push_back( std::move(st) ); |
310 | 0 | } |
311 | 535 | }; |
312 | 535 | SimpleTagHandler::Dispatcher().iterate( tag->begin(), tag->end(), &payload ); |
313 | | |
314 | 535 | if( pout_simple->tag_name.empty() ) |
315 | 68 | { |
316 | 68 | msg_Warn( &sys.demuxer, "Invalid MKV SimpleTag found."); |
317 | 68 | return false; |
318 | 68 | } |
319 | 467 | if( !sys.meta ) |
320 | 111 | sys.meta = vlc_meta_New(); |
321 | 10.6k | for( int i = 0; metadata_map[i].key; i++ ) |
322 | 10.3k | { |
323 | 10.3k | if( pout_simple->tag_name == metadata_map[i].key && |
324 | 187 | (metadata_map[i].target_type == 0 || target_type == metadata_map[i].target_type ) ) |
325 | 138 | { |
326 | 138 | vlc_meta_Set( sys.meta, metadata_map[i].type, pout_simple->value.c_str () ); |
327 | 138 | msg_Dbg( &sys.demuxer, "| | + Meta %s: %s", pout_simple->tag_name.c_str (), pout_simple->value.c_str ()); |
328 | 138 | goto done; |
329 | 138 | } |
330 | 10.3k | } |
331 | 329 | msg_Dbg( &sys.demuxer, "| | + Meta %s: %s", pout_simple->tag_name.c_str (), pout_simple->value.c_str ()); |
332 | 329 | vlc_meta_SetExtra( sys.meta, pout_simple->tag_name.c_str (), pout_simple->value.c_str ()); |
333 | 467 | done: |
334 | 467 | return true; |
335 | 329 | } |
336 | | |
337 | | void matroska_segment_c::LoadTags( KaxTags *tags_ ) |
338 | 1.10k | { |
339 | 1.10k | if ( !ReadMaster( *tags_ ) ) |
340 | 52 | return; |
341 | | |
342 | 1.04k | struct TagsHandlerPayload |
343 | 1.04k | { |
344 | 1.04k | matroska_segment_c * const obj; |
345 | 1.04k | EbmlParser * const ep; |
346 | 1.04k | demux_sys_t & sys; |
347 | 1.04k | int target_type; |
348 | 1.04k | } payload = { this, &ep, sys, 50 }; |
349 | 1.04k | MKV_SWITCH_CREATE( EbmlTypeDispatcher, KaxTagsHandler, TagsHandlerPayload ) |
350 | 1.04k | { |
351 | 1.04k | MKV_SWITCH_INIT(); |
352 | 1.04k | E_CASE( KaxTag, entry ) |
353 | 1.04k | { |
354 | 332 | msg_Dbg( &vars.sys.demuxer, "+ Tag" ); |
355 | 332 | Tag tag; |
356 | 332 | struct TagHandlerPayload |
357 | 332 | { |
358 | 332 | matroska_segment_c * const obj; |
359 | 332 | EbmlParser * const ep; |
360 | 332 | demux_sys_t & sys; |
361 | 332 | Tag & tag; |
362 | 332 | int target_type; |
363 | 332 | } payload = { vars.obj, vars.ep, vars.sys, tag, 50 }; |
364 | 332 | MKV_SWITCH_CREATE( EbmlTypeDispatcher, TagHandler, TagHandlerPayload ) |
365 | 332 | { |
366 | 332 | MKV_SWITCH_INIT(); |
367 | 332 | E_CASE( KaxTagTargets, targets ) |
368 | 332 | { |
369 | 316 | msg_Dbg( &vars.sys.demuxer, "| + Targets" ); |
370 | | |
371 | 316 | MKV_SWITCH_CREATE( EbmlTypeDispatcher, TargetsHandler, TagHandlerPayload ) |
372 | 316 | { |
373 | 316 | MKV_SWITCH_INIT(); |
374 | 316 | E_CASE( KaxTagTargetTypeValue, entry ) |
375 | 316 | { |
376 | 11 | vars.target_type = static_cast<uint32_t>( entry ); |
377 | 11 | msg_Dbg( &vars.sys.demuxer, "| | + TargetTypeValue: %u", vars.target_type); |
378 | 11 | } |
379 | 316 | E_CASE( KaxTagTrackUID, entry ) |
380 | 316 | { |
381 | 168 | vars.tag.i_tag_type = TRACK_UID; |
382 | 168 | vars.tag.i_uid = static_cast<uint64_t>( entry ); |
383 | 168 | msg_Dbg( &vars.sys.demuxer, "| | + TrackUID: %" PRIu64, vars.tag.i_uid); |
384 | 168 | } |
385 | 316 | E_CASE( KaxTagEditionUID, entry ) |
386 | 316 | { |
387 | 1 | vars.tag.i_tag_type = EDITION_UID; |
388 | 1 | vars.tag.i_uid = static_cast<uint64_t>( entry ); |
389 | 1 | msg_Dbg( &vars.sys.demuxer, "| | + EditionUID: %" PRIu64, vars.tag.i_uid); |
390 | 1 | } |
391 | 316 | E_CASE( KaxTagChapterUID, entry ) |
392 | 316 | { |
393 | 2 | vars.tag.i_tag_type = CHAPTER_UID; |
394 | 2 | vars.tag.i_uid = static_cast<uint64_t>( entry ); |
395 | 2 | msg_Dbg( &vars.sys.demuxer, "| | + ChapterUID: %" PRIu64, vars.tag.i_uid); |
396 | 2 | } |
397 | 316 | E_CASE( KaxTagAttachmentUID, entry ) |
398 | 316 | { |
399 | 0 | vars.tag.i_tag_type = ATTACHMENT_UID; |
400 | 0 | vars.tag.i_uid = static_cast<uint64_t>( entry ); |
401 | 0 | msg_Dbg( &vars.sys.demuxer, "| | + AttachmentUID: %" PRIu64, vars.tag.i_uid); |
402 | 0 | } |
403 | 316 | E_CASE( KaxTagTargetType, entry ) |
404 | 316 | { |
405 | 8 | msg_Dbg( &vars.sys.demuxer, "| | + TargetType: %s", entry.GetValue().c_str()); |
406 | 8 | } |
407 | 316 | E_CASE_DEFAULT( el ) |
408 | 316 | { |
409 | 0 | msg_Dbg( &vars.sys.demuxer, "| | + Unknown (%s)", EBML_NAME(&el) ); |
410 | 0 | } |
411 | 316 | }; |
412 | | |
413 | 316 | TargetsHandler::Dispatcher().iterate( targets.begin(), targets.end(), &vars ); |
414 | 316 | } |
415 | 332 | E_CASE( KaxTagSimple, entry ) |
416 | 535 | { |
417 | 535 | SimpleTag simple; |
418 | | |
419 | 535 | if (vars.obj->ParseSimpleTags( &simple, &entry, vars.target_type )) |
420 | 467 | vars.tag.simple_tags.push_back( std::move(simple) ); |
421 | 535 | } |
422 | 332 | E_CASE_DEFAULT( el ) |
423 | 343 | { |
424 | 343 | msg_Dbg( &vars.sys.demuxer, "| | + Unknown (%s)", EBML_NAME(&el) ); |
425 | 343 | } |
426 | 332 | }; |
427 | | |
428 | 332 | TagHandler::Dispatcher().iterate( entry.begin(), entry.end(), &payload ); |
429 | 332 | vars.obj->tags.push_back(std::move(tag)); |
430 | 332 | } |
431 | 1.04k | E_CASE_DEFAULT( el ) |
432 | 5.43k | { |
433 | 5.43k | msg_Dbg( &vars.sys.demuxer, "| + LoadTag Unknown (%s)", EBML_NAME(&el) ); |
434 | 5.43k | } |
435 | 1.04k | }; |
436 | | |
437 | 1.04k | KaxTagsHandler::Dispatcher().iterate( tags_->begin(), tags_->end(), &payload ); |
438 | 1.04k | msg_Dbg( &sys.demuxer, "loading tags done." ); |
439 | 1.04k | } |
440 | | |
441 | | /***************************************************************************** |
442 | | * InformationCreate: |
443 | | *****************************************************************************/ |
444 | | void matroska_segment_c::InformationCreate( ) |
445 | 1.63k | { |
446 | 1.63k | if( !sys.meta ) |
447 | 1.51k | sys.meta = vlc_meta_New(); |
448 | | |
449 | 1.63k | if( psz_title ) |
450 | 120 | { |
451 | 120 | vlc_meta_SetTitle( sys.meta, psz_title ); |
452 | 120 | } |
453 | 1.63k | } |
454 | | |
455 | | |
456 | | /***************************************************************************** |
457 | | * Misc |
458 | | *****************************************************************************/ |
459 | | |
460 | | bool matroska_segment_c::PreloadClusters(uint64_t i_cluster_pos) |
461 | 0 | { |
462 | 0 | struct ClusterHandlerPayload |
463 | 0 | { |
464 | 0 | matroska_segment_c * const obj; |
465 | 0 | bool stop_parsing; |
466 | |
|
467 | 0 | } payload = { this, false }; |
468 | |
|
469 | 0 | MKV_SWITCH_CREATE(EbmlTypeDispatcher, ClusterHandler, ClusterHandlerPayload ) |
470 | 0 | { |
471 | 0 | MKV_SWITCH_INIT(); |
472 | |
|
473 | 0 | E_CASE( KaxCluster, kcluster ) |
474 | 0 | { |
475 | 0 | vars.obj->ParseCluster( &kcluster, false ); |
476 | 0 | } |
477 | |
|
478 | 0 | E_CASE_DEFAULT( el ) |
479 | 0 | { |
480 | 0 | VLC_UNUSED( el ); |
481 | 0 | vars.stop_parsing = true; |
482 | 0 | } |
483 | 0 | }; |
484 | |
|
485 | 0 | { |
486 | 0 | es.I_O().setFilePointer( i_cluster_pos ); |
487 | |
|
488 | 0 | while (payload.stop_parsing == false) |
489 | 0 | { |
490 | 0 | EbmlParser parser ( &es, segment, &sys.demuxer ); |
491 | 0 | EbmlElement* el = parser.Get(); |
492 | |
|
493 | 0 | if( el == NULL ) |
494 | 0 | break; |
495 | | |
496 | 0 | ClusterHandler::Dispatcher().send( el, &payload ); |
497 | 0 | } |
498 | 0 | } |
499 | |
|
500 | 0 | return true; |
501 | 0 | } |
502 | | |
503 | | bool matroska_segment_c::PreloadFamily( const matroska_segment_c & of_segment ) |
504 | 0 | { |
505 | 0 | if ( b_preloaded ) |
506 | 0 | return false; |
507 | | |
508 | 0 | if ( SameFamily( of_segment ) ) |
509 | 0 | return Preload( ); |
510 | | |
511 | 0 | return false; |
512 | 0 | } |
513 | | |
514 | | bool matroska_segment_c::CompareSegmentUIDs( const matroska_segment_c * p_item_a, const matroska_segment_c * p_item_b ) |
515 | 0 | { |
516 | 0 | EbmlBinary *p_tmp; |
517 | |
|
518 | 0 | if ( p_item_a == NULL || p_item_b == NULL ) |
519 | 0 | return false; |
520 | | |
521 | 0 | p_tmp = static_cast<EbmlBinary *>( p_item_a->p_segment_uid ); |
522 | 0 | if ( !p_tmp ) |
523 | 0 | return false; |
524 | 0 | if ( p_item_b->p_prev_segment_uid != NULL |
525 | 0 | && *p_tmp == *p_item_b->p_prev_segment_uid ) |
526 | 0 | return true; |
527 | | |
528 | 0 | p_tmp = static_cast<EbmlBinary *>( p_item_a->p_next_segment_uid ); |
529 | 0 | if ( !p_tmp ) |
530 | 0 | return false; |
531 | | |
532 | 0 | if ( p_item_b->p_segment_uid != NULL |
533 | 0 | && *p_tmp == *p_item_b->p_segment_uid ) |
534 | 0 | return true; |
535 | | |
536 | 0 | if ( p_item_b->p_prev_segment_uid != NULL |
537 | 0 | && *p_tmp == *p_item_b->p_prev_segment_uid ) |
538 | 0 | return true; |
539 | | |
540 | 0 | return false; |
541 | 0 | } |
542 | | |
543 | | bool matroska_segment_c::SameFamily( const matroska_segment_c & of_segment ) const |
544 | 0 | { |
545 | 0 | for (size_t i=0; i<families.size(); i++) |
546 | 0 | { |
547 | 0 | for (size_t j=0; j<of_segment.families.size(); j++) |
548 | 0 | { |
549 | 0 | if ( *(families[i]) == *(of_segment.families[j]) ) |
550 | 0 | return true; |
551 | 0 | } |
552 | 0 | } |
553 | 0 | return false; |
554 | 0 | } |
555 | | |
556 | | bool matroska_segment_c::Preload( ) |
557 | 4.27k | { |
558 | 4.27k | if ( b_preloaded ) |
559 | 2.55k | return false; |
560 | | |
561 | 1.71k | EbmlElement *el = NULL; |
562 | | |
563 | 1.71k | ep.Reset( &sys.demuxer ); |
564 | | |
565 | 14.1k | while( ( el = ep.Get() ) != NULL ) |
566 | 14.0k | { |
567 | 14.0k | if( MKV_IS_ID( el, KaxSeekHead ) ) |
568 | 1.54k | { |
569 | | /* Multiple allowed */ |
570 | | /* We bail at 10, to prevent possible recursion */ |
571 | 1.54k | msg_Dbg( &sys.demuxer, "| + Seek head" ); |
572 | 1.54k | if( i_seekhead_count < 10 ) |
573 | 1.22k | { |
574 | 1.22k | i_seekhead_position = el->GetElementPosition(); |
575 | 1.22k | ParseSeekHead( static_cast<KaxSeekHead*>( el ) ); |
576 | 1.22k | } |
577 | 1.54k | } |
578 | 12.4k | else if( MKV_IS_ID( el, KaxInfo ) ) |
579 | 1.67k | { |
580 | | /* Multiple allowed, mandatory */ |
581 | 1.67k | msg_Dbg( &sys.demuxer, "| + Information" ); |
582 | 1.67k | if( i_info_position < 0 ) |
583 | 781 | { |
584 | 781 | ParseInfo( static_cast<KaxInfo*>( el ) ); |
585 | 781 | i_info_position = el->GetElementPosition(); |
586 | 781 | } |
587 | 1.67k | } |
588 | 10.7k | else if( MKV_CHECKED_PTR_DECL ( kt_ptr, KaxTracks, el ) ) |
589 | 2.33k | { |
590 | | /* Multiple allowed */ |
591 | 2.33k | msg_Dbg( &sys.demuxer, "| + Tracks" ); |
592 | 2.33k | if( i_tracks_position < 0 ) |
593 | 1.21k | { |
594 | 1.21k | ParseTracks( kt_ptr ); |
595 | 1.21k | } |
596 | 2.33k | if ( tracks.size() == 0 ) |
597 | 49 | { |
598 | 49 | msg_Err( &sys.demuxer, "No tracks supported" ); |
599 | 49 | } |
600 | 2.33k | i_tracks_position = el->GetElementPosition(); |
601 | 2.33k | } |
602 | 8.45k | else if( MKV_CHECKED_PTR_DECL ( cues, KaxCues, el ) ) |
603 | 795 | { |
604 | 795 | msg_Dbg( &sys.demuxer, "| + Cues" ); |
605 | 795 | if( i_cues_position < 0 ) |
606 | 114 | { |
607 | 114 | LoadCues( cues ); |
608 | 114 | i_cues_position = el->GetElementPosition(); |
609 | 114 | } |
610 | 795 | } |
611 | 7.66k | else if( MKV_CHECKED_PTR_DECL ( cluster_, KaxCluster, el ) ) |
612 | 1.66k | { |
613 | 1.66k | if( sys.b_seekable && |
614 | 1.66k | var_InheritBool( &sys.demuxer, "mkv-preload-clusters" ) ) |
615 | 0 | { |
616 | 0 | PreloadClusters ( cluster_->GetElementPosition() ); |
617 | 0 | es.I_O().setFilePointer( cluster_->GetElementPosition() ); |
618 | 0 | } |
619 | 1.66k | msg_Dbg( &sys.demuxer, "| + Cluster" ); |
620 | | |
621 | | |
622 | 1.66k | if (EnsureDuration(*cluster_)) |
623 | 1.62k | { |
624 | 1.62k | cluster = cluster_; |
625 | | |
626 | | // add first cluster as trusted seekpoint for all tracks |
627 | 1.62k | for( tracks_map_t::const_iterator it = tracks.begin(); |
628 | 4.49k | it != tracks.end(); ++it ) |
629 | 2.86k | { |
630 | 2.86k | _seeker.add_seekpoint( it->first, |
631 | 2.86k | SegmentSeeker::Seekpoint( cluster->GetElementPosition(), -1, |
632 | 2.86k | SegmentSeeker::Seekpoint::TrustLevel::QUESTIONABLE ) ); |
633 | 2.86k | } |
634 | | |
635 | | /* stop pre-parsing the stream */ |
636 | 1.62k | break; |
637 | 1.62k | } |
638 | 1.66k | } |
639 | 5.99k | else if( MKV_CHECKED_PTR_DECL ( ka_ptr, KaxAttachments, el ) ) |
640 | 475 | { |
641 | 475 | msg_Dbg( &sys.demuxer, "| + Attachments" ); |
642 | 475 | if( i_attachments_position < 0 ) |
643 | 43 | { |
644 | 43 | ParseAttachments( ka_ptr ); |
645 | 43 | i_attachments_position = el->GetElementPosition(); |
646 | 43 | } |
647 | 475 | } |
648 | 5.52k | else if( MKV_CHECKED_PTR_DECL ( chapters, KaxChapters, el ) ) |
649 | 842 | { |
650 | 842 | msg_Dbg( &sys.demuxer, "| + Chapters" ); |
651 | 842 | if( i_chapters_position < 0 ) |
652 | 261 | { |
653 | 261 | ParseChapters( chapters ); |
654 | 261 | i_chapters_position = el->GetElementPosition(); |
655 | 261 | } |
656 | 842 | } |
657 | 4.68k | else if( MKV_CHECKED_PTR_DECL ( tags_, KaxTags, el ) ) |
658 | 1.29k | { |
659 | 1.29k | msg_Dbg( &sys.demuxer, "| + Tags" ); |
660 | 1.29k | if(tags.empty ()) |
661 | 1.04k | { |
662 | 1.04k | LoadTags( tags_ ); |
663 | 1.04k | } |
664 | 1.29k | } |
665 | 3.39k | else if( MKV_IS_ID ( el, EbmlVoid ) ) |
666 | 3.39k | msg_Dbg( &sys.demuxer, "| + Void" ); |
667 | 1.01k | else |
668 | 1.01k | msg_Dbg( &sys.demuxer, "| + Preload Unknown (%s)", EBML_NAME(el) ); |
669 | 14.0k | } |
670 | | |
671 | 1.71k | ComputeTrackPriority(); |
672 | | |
673 | 1.71k | b_preloaded = true; |
674 | | |
675 | 1.71k | return true; |
676 | 4.27k | } |
677 | | |
678 | | /* Here we try to load elements that were found in Seek Heads, but not yet parsed */ |
679 | | bool matroska_segment_c::LoadSeekHeadItem( const EbmlCallbacks & ClassInfos, int64_t i_element_position ) |
680 | 3.34k | { |
681 | 3.34k | int64_t i_sav_position = static_cast<int64_t>( es.I_O().getFilePointer() ); |
682 | 3.34k | EbmlElement *el; |
683 | | |
684 | 3.34k | es.I_O().setFilePointer( i_element_position, seek_beginning ); |
685 | 3.34k | el = es.FindNextID( ClassInfos, 0xFFFFFFFFL); |
686 | | |
687 | 3.34k | if( el == nullptr || el->IsDummy() ) |
688 | 2.22k | { |
689 | 2.22k | msg_Err( &sys.demuxer, "cannot load some cues/chapters/tags etc. (broken seekhead or file)" ); |
690 | 2.22k | es.I_O().setFilePointer( i_sav_position, seek_beginning ); |
691 | 2.22k | delete el; |
692 | 2.22k | return false; |
693 | 2.22k | } |
694 | | |
695 | 1.12k | if( MKV_CHECKED_PTR_DECL ( ksh_ptr, KaxSeekHead, el ) ) |
696 | 0 | { |
697 | | /* Multiple allowed */ |
698 | 0 | msg_Dbg( &sys.demuxer, "| + Seek head" ); |
699 | 0 | if( i_seekhead_count < 10 ) |
700 | 0 | { |
701 | 0 | if ( i_seekhead_position != i_element_position ) |
702 | 0 | { |
703 | 0 | i_seekhead_position = i_element_position; |
704 | 0 | ParseSeekHead( ksh_ptr ); |
705 | 0 | } |
706 | 0 | } |
707 | 0 | } |
708 | 1.12k | else if( MKV_CHECKED_PTR_DECL ( ki_ptr, KaxInfo, el ) ) // FIXME |
709 | 503 | { |
710 | | /* Multiple allowed, mandatory */ |
711 | 503 | msg_Dbg( &sys.demuxer, "| + Information" ); |
712 | 503 | if( i_info_position < 0 ) |
713 | 502 | { |
714 | 502 | ParseInfo( ki_ptr ); |
715 | 502 | i_info_position = i_element_position; |
716 | 502 | } |
717 | 503 | } |
718 | 625 | else if( MKV_CHECKED_PTR_DECL ( kt_ptr, KaxTracks, el ) ) // FIXME |
719 | 486 | { |
720 | | /* Multiple allowed */ |
721 | 486 | msg_Dbg( &sys.demuxer, "| + Tracks" ); |
722 | 486 | if( i_tracks_position < 0 ) |
723 | 468 | ParseTracks( kt_ptr ); |
724 | 486 | if ( tracks.size() == 0 ) |
725 | 1 | { |
726 | 1 | msg_Err( &sys.demuxer, "No tracks supported" ); |
727 | 1 | delete el; |
728 | 1 | es.I_O().setFilePointer( i_sav_position, seek_beginning ); |
729 | 1 | return false; |
730 | 1 | } |
731 | 485 | i_tracks_position = i_element_position; |
732 | 485 | } |
733 | 139 | else if( MKV_CHECKED_PTR_DECL ( kc_ptr, KaxCues, el ) ) |
734 | 36 | { |
735 | 36 | msg_Dbg( &sys.demuxer, "| + Cues" ); |
736 | 36 | if( i_cues_position < 0 ) |
737 | 36 | { |
738 | 36 | LoadCues( kc_ptr ); |
739 | 36 | i_cues_position = i_element_position; |
740 | 36 | } |
741 | 36 | } |
742 | 103 | else if( MKV_CHECKED_PTR_DECL ( ka_ptr, KaxAttachments, el ) ) |
743 | 16 | { |
744 | 16 | msg_Dbg( &sys.demuxer, "| + Attachments" ); |
745 | 16 | if( i_attachments_position < 0 ) |
746 | 16 | { |
747 | 16 | ParseAttachments( ka_ptr ); |
748 | 16 | i_attachments_position = i_element_position; |
749 | 16 | } |
750 | 16 | } |
751 | 87 | else if( MKV_CHECKED_PTR_DECL ( chapters, KaxChapters, el ) ) |
752 | 30 | { |
753 | 30 | msg_Dbg( &sys.demuxer, "| + Chapters" ); |
754 | 30 | if( i_chapters_position < 0 ) |
755 | 30 | { |
756 | 30 | ParseChapters( chapters ); |
757 | 30 | i_chapters_position = i_element_position; |
758 | 30 | } |
759 | 30 | } |
760 | 57 | else if( MKV_CHECKED_PTR_DECL ( tags_, KaxTags, el ) ) |
761 | 57 | { |
762 | 57 | msg_Dbg( &sys.demuxer, "| + Tags" ); |
763 | 57 | if(tags.empty ()) |
764 | 57 | { |
765 | 57 | LoadTags( tags_ ); |
766 | 57 | } |
767 | 57 | } |
768 | 0 | else |
769 | 0 | { |
770 | 0 | msg_Dbg( &sys.demuxer, "| + LoadSeekHeadItem Unknown (%s)", EBML_NAME(el) ); |
771 | 0 | } |
772 | 1.12k | delete el; |
773 | | |
774 | 1.12k | es.I_O().setFilePointer( i_sav_position, seek_beginning ); |
775 | 1.12k | return true; |
776 | 1.12k | } |
777 | | |
778 | | bool matroska_segment_c::Seek( demux_t &demuxer, vlc_tick_t i_absolute_mk_date, vlc_tick_t i_mk_time_offset, bool b_accurate ) |
779 | 1.76k | { |
780 | 1.76k | SegmentSeeker::tracks_seekpoint_t seekpoints; |
781 | | |
782 | 1.76k | SegmentSeeker::fptr_t i_seek_position = std::numeric_limits<SegmentSeeker::fptr_t>::max(); |
783 | 1.76k | vlc_tick_t i_mk_seek_time = -1; |
784 | 1.76k | vlc_tick_t i_mk_date = i_absolute_mk_date - i_mk_time_offset; |
785 | 1.76k | SegmentSeeker::track_ids_t selected_tracks; |
786 | 1.76k | SegmentSeeker::track_ids_t priority; |
787 | | |
788 | | // reset information for all tracks // |
789 | | |
790 | 4.90k | for( tracks_map_t::iterator it = tracks.begin(); it != tracks.end(); ++it ) |
791 | 3.13k | { |
792 | 3.13k | mkv_track_t &track = *it->second; |
793 | | |
794 | 3.13k | track.i_skip_until_fpos = std::numeric_limits<uint64_t>::max(); |
795 | 3.13k | if( track.i_last_dts != VLC_TICK_INVALID ) |
796 | 146 | track.b_discontinuity = true; |
797 | 3.13k | track.i_last_dts = VLC_TICK_INVALID; |
798 | | |
799 | 3.13k | bool selected; |
800 | 3.13k | if (track.p_es == NULL) |
801 | 127 | selected = false; |
802 | 3.01k | else |
803 | 3.01k | es_out_Control( demuxer.out, ES_OUT_GET_ES_STATE, track.p_es, &selected ); |
804 | 3.13k | if ( selected ) |
805 | 3.01k | selected_tracks.push_back( track.i_number ); |
806 | 3.13k | } |
807 | | |
808 | 1.76k | if ( selected_tracks.empty() ) |
809 | 37 | { |
810 | 37 | selected_tracks = priority_tracks; |
811 | 37 | priority = priority_tracks; |
812 | 37 | } |
813 | 1.72k | else |
814 | 1.72k | { |
815 | 1.72k | std::set_intersection(priority_tracks.begin(),priority_tracks.end(), |
816 | 1.72k | selected_tracks.begin(),selected_tracks.end(), |
817 | 1.72k | std::back_inserter(priority)); |
818 | 1.72k | if (priority.empty()) // no video selected ? |
819 | 19 | priority = selected_tracks; |
820 | 1.72k | } |
821 | | |
822 | | // find appropriate seekpoints // |
823 | | |
824 | 1.76k | try { |
825 | 1.76k | seekpoints = _seeker.get_seekpoints( *this, i_mk_date, priority, selected_tracks ); |
826 | 1.76k | } |
827 | 1.76k | catch( std::exception const& e ) |
828 | 1.76k | { |
829 | 0 | msg_Err( &sys.demuxer, "error during seek: \"%s\", aborting!", e.what() ); |
830 | 0 | return false; |
831 | 0 | } |
832 | | |
833 | | // initialize seek information in order to set up playback // |
834 | | |
835 | 4.75k | for( SegmentSeeker::tracks_seekpoint_t::const_iterator it = seekpoints.begin(); it != seekpoints.end(); ++it ) |
836 | 2.99k | { |
837 | 2.99k | tracks_map_t::iterator trackit = tracks.find( it->first ); |
838 | 2.99k | if ( trackit == tracks.end() ) |
839 | 0 | continue; // there were blocks with unknown tracks |
840 | | |
841 | 2.99k | if( i_seek_position > it->second.fpos ) |
842 | 1.95k | { |
843 | 1.95k | i_seek_position = it->second.fpos; |
844 | 1.95k | i_mk_seek_time = it->second.pts; |
845 | 1.95k | } |
846 | | |
847 | | // blocks that will be not be read until this fpos |
848 | 2.99k | if ( b_accurate ) |
849 | 2.99k | trackit->second->i_skip_until_fpos = it->second.fpos; |
850 | 0 | else |
851 | 0 | trackit->second->i_skip_until_fpos = std::numeric_limits<uint64_t>::max(); |
852 | 2.99k | if (it->second.pts != -1) |
853 | 1.12k | trackit->second->i_last_dts = it->second.pts + i_mk_time_offset; |
854 | | |
855 | 2.99k | msg_Dbg( &sys.demuxer, "seek: preroll{ track: %u, pts: %" PRId64 ", fpos: %" PRIu64 " skip: %" PRIu64 "} ", |
856 | 2.99k | it->first, it->second.pts, it->second.fpos, trackit->second->i_skip_until_fpos ); |
857 | 2.99k | } |
858 | | |
859 | 1.76k | if ( i_seek_position == std::numeric_limits<SegmentSeeker::fptr_t>::max() ) |
860 | 33 | return false; |
861 | | |
862 | | // propagate seek information // |
863 | | |
864 | 1.73k | sys.i_pcr = VLC_TICK_INVALID; |
865 | 1.73k | sys.i_pts = VLC_TICK_0 + i_mk_seek_time + i_mk_time_offset; |
866 | 1.73k | if (b_accurate) |
867 | 1.73k | sys.i_start_pts = VLC_TICK_0 + i_absolute_mk_date; |
868 | 0 | else |
869 | 0 | sys.i_start_pts = sys.i_pts; |
870 | | |
871 | | // make the jump // |
872 | | |
873 | 1.73k | _seeker.mkv_jump_to( *this, i_seek_position ); |
874 | | |
875 | | // debug diagnostics // |
876 | | |
877 | 1.73k | msg_Dbg( &sys.demuxer, "seek: preroll{ req: %" PRId64 ", start-pts: %" PRId64 ", start-fpos: %" PRIu64 "} ", |
878 | 1.73k | sys.i_start_pts, sys.i_pts, i_seek_position ); |
879 | | |
880 | | // blocks that will be read and decoded but discarded until this pts |
881 | 1.73k | es_out_Control( sys.demuxer.out, ES_OUT_SET_NEXT_DISPLAY_TIME, sys.i_start_pts ); |
882 | 1.73k | return true; |
883 | 1.76k | } |
884 | | |
885 | | |
886 | | mkv_track_t * matroska_segment_c::FindTrackByBlock( |
887 | | const KaxBlock *p_block, const KaxSimpleBlock *p_simpleblock ) |
888 | 238k | { |
889 | 238k | tracks_map_t::iterator track_it; |
890 | | |
891 | 238k | if (p_block != NULL) |
892 | 122k | track_it = tracks.find( p_block->TrackNum() ); |
893 | 115k | else if( p_simpleblock != NULL) |
894 | 115k | track_it = tracks.find( p_simpleblock->TrackNum() ); |
895 | 0 | else |
896 | 0 | track_it = tracks.end(); |
897 | | |
898 | 238k | if (track_it == tracks.end()) |
899 | 5.10k | return NULL; |
900 | | |
901 | 232k | return track_it->second.get(); |
902 | 238k | } |
903 | | |
904 | | void matroska_segment_c::ComputeTrackPriority() |
905 | 1.71k | { |
906 | 1.71k | bool b_has_default_video = false; |
907 | 1.71k | bool b_has_default_audio = false; |
908 | | /* check for default */ |
909 | 4.87k | for( tracks_map_t::const_iterator it = tracks.begin(); it != tracks.end(); |
910 | 3.15k | ++it ) |
911 | 3.15k | { |
912 | 3.15k | mkv_track_t &track = *it->second; |
913 | | |
914 | 3.15k | bool flag = track.b_enabled && ( track.b_default || track.b_forced ); |
915 | | |
916 | 3.15k | switch( track.fmt.i_cat ) |
917 | 3.15k | { |
918 | 1.28k | case VIDEO_ES: b_has_default_video |= flag; break; |
919 | 1.14k | case AUDIO_ES: b_has_default_audio |= flag; break; |
920 | 724 | default: break; // ignore |
921 | 3.15k | } |
922 | 3.15k | } |
923 | | |
924 | 4.87k | for( tracks_map_t::iterator it = tracks.begin(); it != tracks.end(); ++it ) |
925 | 3.15k | { |
926 | 3.15k | tracks_map_t::key_type track_id = it->first; |
927 | 3.15k | mkv_track_t & track = *it->second; |
928 | | |
929 | 3.15k | if( unlikely( track.fmt.i_cat == UNKNOWN_ES || track.codec.empty() ) ) |
930 | 160 | { |
931 | 160 | msg_Warn( &sys.demuxer, "invalid track[%d]", static_cast<int>( track_id ) ); |
932 | 160 | track.p_es = NULL; |
933 | 160 | continue; |
934 | 160 | } |
935 | 2.99k | else if( unlikely( !b_has_default_video && track.fmt.i_cat == VIDEO_ES ) ) |
936 | 56 | { |
937 | 56 | track.b_default = true; |
938 | 56 | b_has_default_video = true; |
939 | 56 | } |
940 | 2.93k | else if( unlikely( !b_has_default_audio && track.fmt.i_cat == AUDIO_ES ) ) |
941 | 18 | { |
942 | 18 | track.b_default = true; |
943 | 18 | b_has_default_audio = true; |
944 | 18 | } |
945 | 2.99k | if( unlikely( !track.b_enabled ) ) |
946 | 0 | track.fmt.i_priority = ES_PRIORITY_NOT_SELECTABLE; |
947 | 2.99k | else if( track.b_forced ) |
948 | 1 | track.fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + 2; |
949 | 2.99k | else if( track.b_default ) |
950 | 2.52k | track.fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN + 1; |
951 | 471 | else |
952 | 471 | track.fmt.i_priority = ES_PRIORITY_SELECTABLE_MIN; |
953 | | |
954 | | /* Avoid multivideo tracks when unnecessary */ |
955 | 2.99k | if( track.fmt.i_cat == VIDEO_ES ) |
956 | 1.26k | track.fmt.i_priority--; |
957 | 2.99k | } |
958 | | |
959 | | // find track(s) with highest priority // |
960 | 1.71k | { |
961 | 1.71k | int score = -1; |
962 | 1.71k | int es_type = -1; |
963 | | |
964 | 4.87k | for( tracks_map_t::const_iterator it = this->tracks.begin(); it != this->tracks.end(); ++it ) |
965 | 3.15k | { |
966 | 3.15k | int track_score = -1; |
967 | | |
968 | 3.15k | switch( it->second->fmt.i_cat ) |
969 | 3.15k | { |
970 | 1.28k | case VIDEO_ES: ++track_score; |
971 | | /* fallthrough */ |
972 | 2.43k | case AUDIO_ES: ++track_score; |
973 | | /* fallthrough */ |
974 | 3.03k | case SPU_ES: ++track_score; |
975 | | /* fallthrough */ |
976 | 3.15k | default: |
977 | 3.15k | if( score < track_score ) |
978 | 1.75k | { |
979 | 1.75k | es_type = it->second->fmt.i_cat; |
980 | 1.75k | score = track_score; |
981 | 1.75k | } |
982 | 3.15k | } |
983 | 3.15k | } |
984 | | |
985 | 4.87k | for( tracks_map_t::const_iterator it = this->tracks.begin(); it != this->tracks.end(); ++it ) |
986 | 3.15k | { |
987 | 3.15k | if( it->second->fmt.i_cat == es_type ) |
988 | 1.78k | priority_tracks.push_back( it->first ); |
989 | 3.15k | } |
990 | 1.71k | } |
991 | 1.71k | } |
992 | | |
993 | | bool matroska_segment_c::EnsureDuration(KaxCluster & fromCluster) |
994 | 1.66k | { |
995 | 1.66k | if ( i_duration > 0 ) |
996 | 545 | return true; |
997 | | |
998 | 1.12k | i_duration = -1; |
999 | | |
1000 | 1.12k | if( !sys.b_fastseekable ) |
1001 | 0 | { |
1002 | 0 | msg_Warn( &sys.demuxer, "could not look for the segment duration" ); |
1003 | 0 | return true; |
1004 | 0 | } |
1005 | | |
1006 | 1.12k | uint64_t i_current_position = es.I_O().getFilePointer(); |
1007 | 1.12k | uint64_t i_last_cluster_pos = fromCluster.GetElementPosition(); |
1008 | | |
1009 | | // find the last Cluster from the Cues |
1010 | | |
1011 | 1.12k | if ( b_cues && _seeker._cluster_positions.size() ) |
1012 | 42 | i_last_cluster_pos = *_seeker._cluster_positions.rbegin(); |
1013 | 1.07k | else if( !fromCluster.IsFiniteSize() ) |
1014 | 433 | { |
1015 | | // make sure our first Cluster has a timestamp |
1016 | 433 | return ParseCluster( &fromCluster, false, SCOPE_PARTIAL_DATA ); |
1017 | 433 | } |
1018 | | |
1019 | 688 | es.I_O().setFilePointer( i_last_cluster_pos, seek_beginning ); |
1020 | | |
1021 | 688 | EbmlParser eparser ( &es, segment, &sys.demuxer ); |
1022 | | |
1023 | | // locate the definitely last cluster in the stream |
1024 | | |
1025 | 8.65k | while( EbmlElement* el = eparser.Get() ) |
1026 | 8.02k | { |
1027 | 8.02k | if( !el->IsFiniteSize() && el->GetElementPosition() != i_last_cluster_pos ) |
1028 | 20 | { |
1029 | 20 | es.I_O().setFilePointer( i_current_position, seek_beginning ); |
1030 | 20 | return true; |
1031 | 20 | } |
1032 | | |
1033 | 8.00k | if( MKV_IS_ID( el, KaxCluster ) ) |
1034 | 5.78k | { |
1035 | 5.78k | i_last_cluster_pos = el->GetElementPosition(); |
1036 | 5.78k | if ( i_last_cluster_pos == fromCluster.GetElementPosition() ) |
1037 | 650 | { |
1038 | | // make sure our first Cluster has a timestamp |
1039 | 650 | if (!ParseCluster( &fromCluster, true, SCOPE_PARTIAL_DATA )) |
1040 | 38 | return false; |
1041 | 650 | } |
1042 | 5.78k | } |
1043 | 8.00k | } |
1044 | | |
1045 | | // find the last timecode in the Cluster |
1046 | | |
1047 | 630 | eparser.Reset( &sys.demuxer ); |
1048 | 630 | es.I_O().setFilePointer( i_last_cluster_pos, seek_beginning ); |
1049 | | |
1050 | 630 | EbmlElement* el = eparser.Get(); |
1051 | 630 | MKV_CHECKED_PTR_DECL( p_last_cluster, KaxCluster, el ); |
1052 | | |
1053 | 630 | if( p_last_cluster && |
1054 | 594 | ParseCluster( p_last_cluster, false, SCOPE_PARTIAL_DATA ) ) |
1055 | 586 | { |
1056 | | // use the last block + duration |
1057 | 586 | uint64_t i_last_timecode = p_last_cluster->GlobalTimestamp(); |
1058 | 586 | for (auto l : *p_last_cluster) |
1059 | 11.4k | { |
1060 | 11.4k | if( MKV_CHECKED_PTR_DECL ( simpleblock, KaxSimpleBlock, l ) ) |
1061 | 2.66k | { |
1062 | 2.66k | simpleblock->SetParent( *p_last_cluster ); |
1063 | 2.66k | i_last_timecode = std::max(i_last_timecode, simpleblock->GlobalTimestamp()); |
1064 | 2.66k | } |
1065 | 8.76k | else if( MKV_CHECKED_PTR_DECL_CONST ( group, KaxBlockGroup, l ) ) |
1066 | 1.59k | { |
1067 | 1.59k | uint64_t i_group_timecode = 0; |
1068 | 1.59k | for (auto g : *group) |
1069 | 3.24k | { |
1070 | 3.24k | if( MKV_CHECKED_PTR_DECL ( block, KaxBlock, g ) ) |
1071 | 1.50k | { |
1072 | 1.50k | block->SetParent( *p_last_cluster ); |
1073 | 1.50k | i_group_timecode += block->GlobalTimestamp(); |
1074 | 1.50k | } |
1075 | 1.74k | else if( MKV_CHECKED_PTR_DECL_CONST ( kbd_ptr, KaxBlockDuration, g ) ) |
1076 | 176 | { |
1077 | 176 | i_group_timecode += static_cast<uint64_t>( *kbd_ptr ); |
1078 | 176 | } |
1079 | 3.24k | } |
1080 | 1.59k | i_last_timecode = std::max(i_last_timecode, i_group_timecode); |
1081 | 1.59k | } |
1082 | 11.4k | } |
1083 | | |
1084 | 586 | i_duration = VLC_TICK_FROM_NS( i_last_timecode - fromCluster.GlobalTimestamp() ); |
1085 | 586 | msg_Dbg( &sys.demuxer, " extracted Duration=%" PRId64, SEC_FROM_VLC_TICK(i_duration) ); |
1086 | 586 | } |
1087 | | |
1088 | | // get back to the reading position we were at before looking for a duration |
1089 | 630 | es.I_O().setFilePointer( i_current_position, seek_beginning ); |
1090 | 630 | return true; |
1091 | 688 | } |
1092 | | |
1093 | | bool matroska_segment_c::ESCreate() |
1094 | 1.63k | { |
1095 | | /* add all es */ |
1096 | 1.63k | msg_Dbg( &sys.demuxer, "found %d es", static_cast<int>( tracks.size() ) ); |
1097 | | |
1098 | 1.63k | mkv_track_t *default_tracks[ES_CATEGORY_COUNT] = {}; |
1099 | 4.51k | for( tracks_map_t::iterator it = tracks.begin(); it != tracks.end(); ++it ) |
1100 | 2.88k | { |
1101 | 2.88k | tracks_map_t::key_type track_id = it->first; |
1102 | 2.88k | mkv_track_t & track = *it->second; |
1103 | | |
1104 | 2.88k | if( unlikely( track.fmt.i_cat == UNKNOWN_ES || track.codec.empty() ) ) |
1105 | 118 | { |
1106 | 118 | msg_Warn( &sys.demuxer, "invalid track[%d]", static_cast<int>( track_id ) ); |
1107 | 118 | track.p_es = NULL; |
1108 | 118 | continue; |
1109 | 118 | } |
1110 | 2.76k | track.fmt.i_id = static_cast<int>( track_id ); |
1111 | | |
1112 | 2.76k | if( !track.p_es ) |
1113 | 2.76k | { |
1114 | 2.76k | track.p_es = es_out_Add( sys.demuxer.out, &track.fmt ); |
1115 | | |
1116 | 2.76k | if( track.p_es && |
1117 | 2.76k | !sys.ev.AddTrack( track ) ) |
1118 | 1.22k | { |
1119 | 1.22k | msg_Warn( &sys.demuxer, "Could not register events, interactive menus will not work"); |
1120 | 1.22k | } |
1121 | 2.76k | } |
1122 | | |
1123 | | /* Turn on a subtitles track if it has been flagged as default - |
1124 | | * but only do this if no subtitles track has already been engaged, |
1125 | | * either by an earlier 'default track' (??) or by default |
1126 | | * language choice behaviour. |
1127 | | */ |
1128 | 2.76k | if( track.b_default || track.b_forced ) |
1129 | 2.42k | { |
1130 | 2.42k | mkv_track_t *&default_track = default_tracks[track.fmt.i_cat]; |
1131 | 2.42k | if( !default_track || track.b_default ) |
1132 | 2.42k | default_track = &track; |
1133 | 2.42k | } |
1134 | 2.76k | } |
1135 | | |
1136 | 1.63k | for( mkv_track_t *track : default_tracks ) |
1137 | 8.15k | { |
1138 | 8.15k | if( track ) |
1139 | 2.40k | es_out_Control( sys.demuxer.out, ES_OUT_SET_ES_DEFAULT, track->p_es ); |
1140 | 8.15k | } |
1141 | | |
1142 | 1.63k | return true; |
1143 | 1.63k | } |
1144 | | |
1145 | | void matroska_segment_c::ESDestroy( ) |
1146 | 1.63k | { |
1147 | 1.63k | sys.ev.AbortThread(); |
1148 | | |
1149 | 4.51k | for( tracks_map_t::iterator it = tracks.begin(); it != tracks.end(); ++it ) |
1150 | 2.88k | { |
1151 | 2.88k | mkv_track_t & track = *it->second; |
1152 | | |
1153 | 2.88k | if( track.p_es != NULL ) |
1154 | 2.76k | { |
1155 | 2.76k | es_out_Del( sys.demuxer.out, track.p_es ); |
1156 | 2.76k | sys.ev.DelTrack( track ); |
1157 | 2.76k | track.p_es = NULL; |
1158 | 2.76k | } |
1159 | 2.88k | } |
1160 | 1.63k | } |
1161 | | |
1162 | | int matroska_segment_c::BlockGet( KaxBlock * & pp_block, KaxSimpleBlock * & pp_simpleblock, |
1163 | | KaxBlockAdditions * & pp_additions, |
1164 | | bool *pb_key_picture, bool *pb_discardable_picture, |
1165 | | int64_t *pi_duration ) |
1166 | 66.3k | { |
1167 | 66.3k | pp_simpleblock = NULL; |
1168 | 66.3k | pp_block = NULL; |
1169 | 66.3k | pp_additions = NULL; |
1170 | | |
1171 | 66.3k | *pb_key_picture = true; |
1172 | 66.3k | *pb_discardable_picture = false; |
1173 | 66.3k | *pi_duration = 0; |
1174 | | |
1175 | 66.3k | struct BlockPayload { |
1176 | 66.3k | matroska_segment_c * const obj; |
1177 | 66.3k | EbmlParser * const ep; |
1178 | 66.3k | demux_t * const p_demuxer; |
1179 | 66.3k | KaxBlock *& block; |
1180 | 66.3k | KaxSimpleBlock *& simpleblock; |
1181 | 66.3k | KaxBlockAdditions *& additions; |
1182 | | |
1183 | 66.3k | int64_t & i_duration; |
1184 | 66.3k | bool & b_key_picture; |
1185 | 66.3k | bool & b_discardable_picture; |
1186 | 66.3k | bool b_cluster_timecode; |
1187 | | |
1188 | 66.3k | } payload = { |
1189 | 66.3k | this, &ep, &sys.demuxer, pp_block, pp_simpleblock, pp_additions, |
1190 | 66.3k | *pi_duration, *pb_key_picture, *pb_discardable_picture, true |
1191 | 66.3k | }; |
1192 | | |
1193 | 66.3k | MKV_SWITCH_CREATE( EbmlTypeDispatcher, BlockGetHandler_l1, BlockPayload ) |
1194 | 66.3k | { |
1195 | 66.3k | MKV_SWITCH_INIT(); |
1196 | | |
1197 | 66.3k | E_CASE( KaxCluster, kcluster ) |
1198 | 66.3k | { |
1199 | 24.1k | vars.obj->cluster = &kcluster; |
1200 | 24.1k | vars.b_cluster_timecode = false; |
1201 | 24.1k | vars.ep->Down (); |
1202 | 24.1k | } |
1203 | 66.3k | E_CASE( KaxCues, kcue ) |
1204 | 66.3k | { |
1205 | 67 | VLC_UNUSED( kcue ); |
1206 | 67 | msg_Warn( vars.p_demuxer, "find KaxCues FIXME" ); |
1207 | 67 | } |
1208 | 66.3k | E_CASE_DEFAULT(element) |
1209 | 66.3k | { |
1210 | 26.8k | msg_Dbg( vars.p_demuxer, "Unknown (%s)", EBML_NAME(&element) ); |
1211 | 26.8k | } |
1212 | 66.3k | }; |
1213 | | |
1214 | 66.3k | MKV_SWITCH_CREATE( EbmlTypeDispatcher, BlockGetHandler_l2, BlockPayload ) |
1215 | 66.3k | { |
1216 | 66.3k | MKV_SWITCH_INIT(); |
1217 | | |
1218 | 66.3k | E_CASE( KaxClusterTimestamp, ktimecode ) |
1219 | 66.3k | { |
1220 | 24.8k | ktimecode.ReadData( vars.obj->es.I_O(), SCOPE_ALL_DATA ); |
1221 | 24.8k | vars.obj->cluster->InitTimestamp( static_cast<uint64_t>( ktimecode ), vars.obj->i_timescale ); |
1222 | 24.8k | vars.obj->_seeker.add_cluster( vars.obj->cluster ); |
1223 | 24.8k | vars.b_cluster_timecode = true; |
1224 | 24.8k | } |
1225 | 66.3k | E_CASE( KaxClusterSilentTracks, ksilent ) |
1226 | 66.3k | { |
1227 | 8 | vars.ep->Down (); |
1228 | | |
1229 | 8 | VLC_UNUSED( ksilent ); |
1230 | 8 | } |
1231 | 66.3k | E_CASE( KaxBlockGroup, kbgroup ) |
1232 | 66.3k | { |
1233 | 37.4k | vars.obj->i_block_pos = kbgroup.GetElementPosition(); |
1234 | 37.4k | vars.ep->Down (); |
1235 | 37.4k | } |
1236 | 66.3k | E_CASE( KaxSimpleBlock, ksblock ) |
1237 | 66.3k | { |
1238 | 35.7k | if( vars.b_cluster_timecode == false ) |
1239 | 115 | { |
1240 | 115 | msg_Warn( vars.p_demuxer, "ignoring SimpleBlock prior to mandatory Timecode" ); |
1241 | 115 | return; |
1242 | 115 | } |
1243 | | |
1244 | 35.6k | filepos_t read = 0; |
1245 | 35.6k | try { |
1246 | 35.6k | read = ksblock.ReadData( vars.obj->es.I_O() ); |
1247 | 35.6k | } catch(...) { |
1248 | 0 | } |
1249 | 35.6k | if (read == 0 && ksblock.GetSize() != 0) { |
1250 | 1.54k | msg_Err( vars.p_demuxer,"Error while reading %s", EBML_NAME(&ksblock) ); |
1251 | 1.54k | ksblock.ReleaseFrames(); |
1252 | 1.54k | return; |
1253 | 1.54k | } |
1254 | 34.1k | vars.simpleblock = &ksblock; |
1255 | 34.1k | vars.simpleblock->SetParent( *vars.obj->cluster ); |
1256 | | |
1257 | 34.1k | if( ksblock.IsKeyframe() ) |
1258 | 17.1k | { |
1259 | 17.1k | bool const b_valid_track = vars.obj->FindTrackByBlock( NULL, &ksblock ) != NULL; |
1260 | 17.1k | if (b_valid_track) |
1261 | 16.3k | vars.obj->_seeker.add_seekpoint( ksblock.TrackNum(), |
1262 | 16.3k | SegmentSeeker::Seekpoint( ksblock.GetElementPosition(), VLC_TICK_FROM_NS(ksblock.GlobalTimestamp()) ) ); |
1263 | 17.1k | } |
1264 | 34.1k | } |
1265 | 66.3k | }; |
1266 | | |
1267 | 66.3k | MKV_SWITCH_CREATE( EbmlTypeDispatcher, BlockGetHandler_l3, BlockPayload ) |
1268 | 66.3k | { |
1269 | 66.3k | MKV_SWITCH_INIT(); |
1270 | | |
1271 | 66.3k | E_CASE( KaxBlock, kblock ) |
1272 | 66.3k | { |
1273 | 32.9k | filepos_t read = 0; |
1274 | 32.9k | try { |
1275 | 32.9k | read = kblock.ReadData( vars.obj->es.I_O() ); |
1276 | 32.9k | } catch(...) { |
1277 | 0 | } |
1278 | 32.9k | if (unlikely(read == 0) && kblock.GetSize() != 0) { |
1279 | 122 | msg_Err( vars.p_demuxer,"Error while reading %s", EBML_NAME(&kblock) ); |
1280 | 122 | kblock.ReleaseFrames(); |
1281 | 122 | return; |
1282 | 122 | } |
1283 | 32.8k | vars.block = &kblock; |
1284 | 32.8k | vars.block->SetParent( *vars.obj->cluster ); |
1285 | | |
1286 | 32.8k | const mkv_track_t *p_track = vars.obj->FindTrackByBlock( &kblock, NULL ); |
1287 | 32.8k | if( p_track != NULL && p_track->fmt.i_cat == SPU_ES ) |
1288 | 785 | { |
1289 | 785 | vars.obj->_seeker.add_seekpoint( kblock.TrackNum(), |
1290 | 785 | SegmentSeeker::Seekpoint( kblock.GetElementPosition(), VLC_TICK_FROM_NS(kblock.GlobalTimestamp()) ) ); |
1291 | 785 | } |
1292 | | |
1293 | 32.8k | vars.ep->Keep (); |
1294 | 32.8k | } |
1295 | 66.3k | E_CASE( KaxBlockAdditions, kadditions ) |
1296 | 66.3k | { |
1297 | 2.81k | if ( vars.obj->ReadMaster( kadditions ) ) |
1298 | 2.81k | { |
1299 | 2.81k | vars.additions = &kadditions; |
1300 | 2.81k | vars.ep->Keep (); |
1301 | 2.81k | } |
1302 | 2.81k | } |
1303 | 66.3k | E_CASE( KaxBlockDuration, kduration ) |
1304 | 66.3k | { |
1305 | 6.68k | kduration.ReadData( vars.obj->es.I_O() ); |
1306 | 6.68k | vars.i_duration = static_cast<uint64_t>( kduration ); |
1307 | 6.68k | } |
1308 | 66.3k | E_CASE( KaxReferenceBlock, kreference ) |
1309 | 66.3k | { |
1310 | 8.58k | kreference.ReadData( vars.obj->es.I_O() ); |
1311 | | |
1312 | 8.58k | if( vars.b_key_picture ) |
1313 | 8.11k | vars.b_key_picture = false; |
1314 | 472 | else if( static_cast<int64_t>( kreference ) ) |
1315 | 470 | vars.b_discardable_picture = true; |
1316 | 8.58k | } |
1317 | 66.3k | E_CASE( KaxClusterSilentTrackNumber, kstrackn ) |
1318 | 66.3k | { |
1319 | 0 | VLC_UNUSED( kstrackn ); |
1320 | 0 | VLC_UNUSED( vars ); |
1321 | 0 | } |
1322 | 66.3k | #if LIBMATROSKA_VERSION >= 0x010401 |
1323 | 66.3k | E_CASE( KaxDiscardPadding, kdiscardp ) |
1324 | 66.3k | { |
1325 | 2 | kdiscardp.ReadData( vars.obj->es.I_O() ); |
1326 | 2 | int64_t i_duration = static_cast<int64_t>( kdiscardp ); |
1327 | | |
1328 | 2 | if( vars.i_duration < i_duration ) |
1329 | 0 | vars.i_duration = 0; |
1330 | 2 | else |
1331 | 2 | vars.i_duration -= i_duration; |
1332 | 2 | } |
1333 | 66.3k | #endif |
1334 | 66.3k | E_CASE_DEFAULT( element ) |
1335 | 66.3k | { |
1336 | 111 | VLC_UNUSED(element); |
1337 | | |
1338 | 111 | msg_Warn( vars.p_demuxer, "unknown element at { fpos: %" PRId64 ", '%s' }", |
1339 | 111 | element.GetElementPosition(), EBML_NAME( &element ) ); |
1340 | 111 | } |
1341 | 66.3k | }; |
1342 | | |
1343 | 66.3k | static EbmlTypeDispatcher const * const dispatchers[] = { |
1344 | 66.3k | &BlockGetHandler_l1::Dispatcher(), |
1345 | 66.3k | &BlockGetHandler_l2::Dispatcher(), |
1346 | 66.3k | &BlockGetHandler_l3::Dispatcher() |
1347 | 66.3k | }; |
1348 | | |
1349 | 66.3k | for( ;; ) |
1350 | 335k | { |
1351 | 335k | EbmlElement *el = NULL; |
1352 | 335k | int i_level; |
1353 | | |
1354 | 335k | if( pp_simpleblock != NULL || ((el = ep.Get()) == NULL && pp_block != NULL) ) |
1355 | 66.9k | { |
1356 | | /* Check blocks validity to protect against broken files */ |
1357 | 66.9k | const mkv_track_t *p_track = FindTrackByBlock( pp_block , pp_simpleblock ); |
1358 | 66.9k | if( p_track == NULL ) |
1359 | 2.62k | { |
1360 | 2.62k | ep.Unkeep(); |
1361 | 2.62k | pp_simpleblock = NULL; |
1362 | 2.62k | pp_block = NULL; |
1363 | 2.62k | continue; |
1364 | 2.62k | } |
1365 | 64.3k | if( pp_simpleblock != NULL ) |
1366 | 33.1k | { |
1367 | 33.1k | *pb_key_picture = pp_simpleblock->IsKeyframe(); |
1368 | 33.1k | *pb_discardable_picture = pp_simpleblock->IsDiscardable(); |
1369 | 33.1k | } |
1370 | | /* We have block group let's check if the picture is a keyframe */ |
1371 | 31.1k | else if( *pb_key_picture ) |
1372 | 23.0k | { |
1373 | 23.0k | if( p_track->fmt.i_codec == VLC_CODEC_THEORA ) |
1374 | 1.00k | { |
1375 | 1.00k | DataBuffer * p_data = &pp_block->GetBuffer(0); |
1376 | 1.00k | const uint8_t * p_buff = p_data->Buffer(); |
1377 | | /* if the second bit of a Theora frame is 1 |
1378 | | it's not a keyframe */ |
1379 | 1.00k | if( p_data->Size() && p_buff ) |
1380 | 1.00k | { |
1381 | 1.00k | if( p_buff[0] & 0x40 ) |
1382 | 854 | *pb_key_picture = false; |
1383 | 1.00k | } |
1384 | 2 | else |
1385 | 2 | *pb_key_picture = false; |
1386 | 1.00k | } |
1387 | 23.0k | } |
1388 | | |
1389 | 64.3k | return VLC_SUCCESS; |
1390 | 66.9k | } |
1391 | | |
1392 | 268k | i_level = ep.GetLevel(); |
1393 | | |
1394 | 268k | if( el == NULL ) |
1395 | 64.6k | { |
1396 | 64.6k | if( i_level > 1 ) |
1397 | 62.6k | { |
1398 | 62.6k | ep.Up(); |
1399 | 62.6k | continue; |
1400 | 62.6k | } |
1401 | 1.98k | msg_Warn( &sys.demuxer, "EOF" ); |
1402 | 1.98k | return VLC_EGENERIC; |
1403 | 64.6k | } |
1404 | | |
1405 | | /* Verify that we are still inside our cluster |
1406 | | * It can happens with broken files and when seeking |
1407 | | * without index */ |
1408 | 203k | if( i_level > 1 ) |
1409 | 152k | { |
1410 | 152k | if( cluster && !ep.IsTopPresent( cluster ) ) |
1411 | 0 | { |
1412 | 0 | msg_Warn( &sys.demuxer, "Unexpected escape from current cluster" ); |
1413 | 0 | cluster = NULL; |
1414 | 0 | } |
1415 | 152k | if( !cluster ) |
1416 | 0 | continue; |
1417 | 152k | } |
1418 | | |
1419 | | /* do parsing */ |
1420 | | |
1421 | 203k | try { |
1422 | 203k | switch( i_level ) |
1423 | 203k | { |
1424 | 101k | case 2: |
1425 | | /* fallthrough */ |
1426 | 152k | case 3: |
1427 | 152k | if( unlikely( !el->ValidateSize() || ( el->IsFiniteSize() && el->GetSize() >= SIZE_MAX ) ) ) |
1428 | 0 | { |
1429 | 0 | msg_Err( &sys.demuxer, "Error while reading %s... upping level", EBML_NAME(el)); |
1430 | 0 | ep.Up(); |
1431 | |
|
1432 | 0 | if ( i_level == 2 ) |
1433 | 0 | break; |
1434 | | |
1435 | 0 | ep.Unkeep(); |
1436 | 0 | pp_simpleblock = NULL; |
1437 | 0 | pp_block = NULL; |
1438 | |
|
1439 | 0 | break; |
1440 | 0 | } |
1441 | | /* fallthrough */ |
1442 | 203k | case 1: |
1443 | 203k | { |
1444 | 203k | EbmlTypeDispatcher const * dispatcher = dispatchers[i_level - 1]; |
1445 | 203k | dispatcher->send( el, &payload ); |
1446 | 203k | } |
1447 | 203k | break; |
1448 | | |
1449 | 0 | default: |
1450 | 0 | msg_Err( &sys.demuxer, "invalid level = %d", i_level ); |
1451 | 0 | return VLC_EGENERIC; |
1452 | 203k | } |
1453 | 203k | } |
1454 | 203k | catch (int ret_code) |
1455 | 203k | { |
1456 | 0 | return ret_code; |
1457 | 0 | } |
1458 | 203k | catch (...) |
1459 | 203k | { |
1460 | 6 | msg_Err( &sys.demuxer, "Error while reading %s... upping level", EBML_NAME(el)); |
1461 | 6 | ep.Up(); |
1462 | 6 | ep.Unkeep(); |
1463 | 6 | pp_simpleblock = NULL; |
1464 | | pp_block = NULL; |
1465 | 6 | } |
1466 | 203k | } |
1467 | 66.3k | } |
1468 | | |
1469 | | } // namespace |