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