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