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