1 | /* |
2 | Copyright (c) 2012, Broadcom Europe Ltd |
3 | All rights reserved. |
4 | |
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the following conditions are met: |
7 | * Redistributions of source code must retain the above copyright |
8 | notice, this list of conditions and the following disclaimer. |
9 | * Redistributions in binary form must reproduce the above copyright |
10 | notice, this list of conditions and the following disclaimer in the |
11 | documentation and/or other materials provided with the distribution. |
12 | * Neither the name of the copyright holder nor the |
13 | names of its contributors may be used to endorse or promote products |
14 | derived from this software without specific prior written permission. |
15 | |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY |
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ |
27 | #include <stdlib.h> |
28 | #include <string.h> |
29 | |
30 | //#define ENABLE_MKV_EXTRA_LOGGING |
31 | #define CONTAINER_IS_BIG_ENDIAN |
32 | #define CONTAINER_HELPER_LOG_INDENT(a) (a)->priv->module->element_level |
33 | #include "containers/core/containers_private.h" |
34 | #include "containers/core/containers_io_helpers.h" |
35 | #include "containers/core/containers_utils.h" |
36 | #include "containers/core/containers_logging.h" |
37 | |
38 | /****************************************************************************** |
39 | Defines. |
40 | ******************************************************************************/ |
41 | #define MKV_TRACKS_MAX 16 |
42 | #define MKV_CODECID_MAX 32 |
43 | #define MKV_MAX_LACING_NUM 64 |
44 | |
45 | #define MKV_MAX_ENCODINGS 1 |
46 | #define MKV_MAX_ENCODING_DATA 256 |
47 | |
48 | #define MKV_MAX_ELEMENT_LEVEL 8 |
49 | #define MKV_MAX_CONSECUTIVE_UNKNOWN_ELEMENTS 5 |
50 | #define MKV_MAX_ELEMENT_SIZE (1<<29) /* Does not apply to the data element */ |
51 | #define MKV_MAX_STRING_SIZE 256 |
52 | #define 2 |
53 | |
54 | #define MKV_MAX_READER_STATE_LEVEL 4 |
55 | |
56 | #define MKV_SKIP_U8(ctx,n) (size -= 1, SKIP_U8(ctx,n)) |
57 | #define MKV_SKIP_U16(ctx,n) (size -= 2, SKIP_U16(ctx,n)) |
58 | #define MKV_SKIP_U24(ctx,n) (size -= 3, SKIP_U24(ctx,n)) |
59 | #define MKV_SKIP_U32(ctx,n) (size -= 4, SKIP_U32(ctx,n)) |
60 | #define MKV_SKIP_U64(ctx,n) (size -= 8, SKIP_U64(ctx,n)) |
61 | #define MKV_READ_U8(ctx,n) (size -= 1, READ_U8(ctx,n)) |
62 | #define MKV_READ_U16(ctx,n) (size -= 2, READ_U16(ctx,n)) |
63 | #define MKV_READ_U24(ctx,n) (size -= 3, READ_U24(ctx,n)) |
64 | #define MKV_READ_U32(ctx,n) (size -= 4, READ_U32(ctx,n)) |
65 | #define MKV_READ_U64(ctx,n) (size -= 8, READ_U64(ctx,n)) |
66 | #define MKV_READ_BYTES(ctx,buffer,sz) (size -= sz, READ_BYTES(ctx,buffer,sz)) |
67 | #define MKV_SKIP_BYTES(ctx,sz) (size -= sz, SKIP_BYTES(ctx,sz)) |
68 | |
69 | #define CHECK_POINT(a) do { \ |
70 | /*if(size < 0 && size != INT64_C(-1)) return VC_CONTAINER_ERROR_CORRUPTED;*/ \ |
71 | if(STREAM_STATUS(p_ctx)) return STREAM_STATUS(p_ctx); } while(0) |
72 | |
73 | static uint32_t mkv_io_read_id(VC_CONTAINER_IO_T *io, int64_t *size) |
74 | { |
75 | uint32_t value, mask; |
76 | |
77 | value = vc_container_io_read_uint8(io); (*size)--; |
78 | for(mask = 0x80; mask; mask <<= 7) |
79 | { |
80 | if(value & mask) return value; |
81 | value = (value << 8) | vc_container_io_read_uint8(io); (*size)--; |
82 | } |
83 | return 0; |
84 | } |
85 | |
86 | static int64_t mkv_io_read_uint(VC_CONTAINER_IO_T *io, int64_t *size) |
87 | { |
88 | uint64_t value, mask; |
89 | |
90 | value = vc_container_io_read_uint8(io); (*size)--; |
91 | if(value == 0xFF) return -1; |
92 | |
93 | for(mask = 0x80; mask; mask <<= 7) |
94 | { |
95 | if(value & mask) return value & ~mask; |
96 | value = (value << 8) | vc_container_io_read_uint8(io); (*size)--; |
97 | } |
98 | return 0; |
99 | } |
100 | |
101 | static int64_t mkv_io_read_sint(VC_CONTAINER_IO_T *io, int64_t *size) |
102 | { |
103 | int64_t value, count = io->offset; |
104 | value = mkv_io_read_uint(io, size); |
105 | count = io->offset - count; |
106 | |
107 | switch(count) |
108 | { |
109 | case 1: value -= 0x3F; break; |
110 | case 2: value -= 0x1FFF; break; |
111 | case 3: value -= 0xFFFFF; break; |
112 | case 4: value -= 0x7FFFFFF; break; |
113 | default: break; |
114 | } |
115 | return value; |
116 | } |
117 | |
118 | #define MKV_READ_ID(ctx, n) mkv_io_read_id((ctx)->priv->io, &size) |
119 | #define MKV_READ_UINT(ctx, n) mkv_io_read_uint((ctx)->priv->io, &size) |
120 | #define MKV_READ_SINT(ctx, n) mkv_io_read_sint((ctx)->priv->io, &size) |
121 | |
122 | /****************************************************************************** |
123 | Type definitions. |
124 | ******************************************************************************/ |
125 | |
126 | typedef enum |
127 | { |
128 | MKV_ELEMENT_ID_UNKNOWN = 0, |
129 | |
130 | /* EBML Basics */ |
131 | MKV_ELEMENT_ID_EBML = 0x1A45DFA3, |
132 | MKV_ELEMENT_ID_EBML_VERSION = 0x4286, |
133 | MKV_ELEMENT_ID_EBML_READ_VERSION = 0x42F7, |
134 | MKV_ELEMENT_ID_EBML_MAX_ID_LENGTH = 0x42F2, |
135 | MKV_ELEMENT_ID_EBML_MAX_SIZE_LENGTH = 0x42F3, |
136 | MKV_ELEMENT_ID_DOCTYPE = 0x4282, |
137 | MKV_ELEMENT_ID_DOCTYPE_VERSION = 0x4287, |
138 | MKV_ELEMENT_ID_DOCTYPE_READ_VERSION = 0x4285, |
139 | |
140 | /* Global Elements */ |
141 | MKV_ELEMENT_ID_CRC32 = 0xBF, |
142 | MKV_ELEMENT_ID_VOID = 0xEC, |
143 | |
144 | /* Segment */ |
145 | MKV_ELEMENT_ID_SEGMENT = 0x18538067, |
146 | |
147 | /* Meta Seek Information */ |
148 | MKV_ELEMENT_ID_SEEK_HEAD = 0x114D9B74, |
149 | MKV_ELEMENT_ID_SEEK = 0x4DBB, |
150 | MKV_ELEMENT_ID_SEEK_ID = 0x53AB, |
151 | MKV_ELEMENT_ID_SEEK_POSITION = 0x53AC, |
152 | |
153 | /* Segment Information */ |
154 | MKV_ELEMENT_ID_INFO = 0x1549A966, |
155 | MKV_ELEMENT_ID_SEGMENT_UID = 0x73A4, |
156 | MKV_ELEMENT_ID_SEGMENT_FILENAME = 0x7384, |
157 | MKV_ELEMENT_ID_PREV_UID = 0x3CB923, |
158 | MKV_ELEMENT_ID_PREV_FILENAME = 0x3C83AB, |
159 | MKV_ELEMENT_ID_NEXT_UID = 0x3EB923, |
160 | MKV_ELEMENT_ID_NEXT_FILENAME = 0x3E83BB, |
161 | MKV_ELEMENT_ID_SEGMENT_FAMILY = 0x4444, |
162 | MKV_ELEMENT_ID_CHAPTER_TRANSLATE = 0x6924, |
163 | MKV_ELEMENT_ID_CHAPTER_TRANSLATE_EDITION_UID = 0x69FC, |
164 | MKV_ELEMENT_ID_CHAPTER_TRANSLATE_CODEC = 0x69BF, |
165 | MKV_ELEMENT_ID_CHAPTER_TRANSLATE_ID = 0x69A5, |
166 | MKV_ELEMENT_ID_TIMECODE_SCALE = 0x2AD7B1, |
167 | MKV_ELEMENT_ID_DURATION = 0x4489, |
168 | MKV_ELEMENT_ID_DATE_UTC = 0x4461, |
169 | MKV_ELEMENT_ID_TITLE = 0x7BA9, |
170 | MKV_ELEMENT_ID_MUXING_APP = 0x4D80, |
171 | MKV_ELEMENT_ID_WRITING_APP = 0x5741, |
172 | |
173 | /* Cluster */ |
174 | MKV_ELEMENT_ID_CLUSTER = 0x1F43B675, |
175 | MKV_ELEMENT_ID_TIMECODE = 0xE7, |
176 | MKV_ELEMENT_ID_SILENT_TRACKS = 0x5854, |
177 | MKV_ELEMENT_ID_SILENT_TRACK_NUMBER = 0x58D7, |
178 | MKV_ELEMENT_ID_POSITION = 0xA7, |
179 | MKV_ELEMENT_ID_PREV_SIZE = 0xAB, |
180 | MKV_ELEMENT_ID_BLOCKGROUP = 0xA0, |
181 | MKV_ELEMENT_ID_BLOCK = 0xA1, |
182 | MKV_ELEMENT_ID_BLOCK_ADDITIONS = 0x75A1, |
183 | MKV_ELEMENT_ID_BLOCK_MORE = 0xA6, |
184 | MKV_ELEMENT_ID_BLOCK_ADD_ID = 0xEE, |
185 | MKV_ELEMENT_ID_BLOCK_ADDITIONAL = 0xA5, |
186 | MKV_ELEMENT_ID_BLOCK_DURATION = 0x9B, |
187 | MKV_ELEMENT_ID_REFERENCE_PRIORITY = 0xFA, |
188 | MKV_ELEMENT_ID_REFERENCE_BLOCK = 0xFB, |
189 | MKV_ELEMENT_ID_CODEC_STATE = 0xA4, |
190 | MKV_ELEMENT_ID_SLICES = 0x8E, |
191 | MKV_ELEMENT_ID_TIME_SLICE = 0xE8, |
192 | MKV_ELEMENT_ID_LACE_NUMBER = 0xCC, |
193 | MKV_ELEMENT_ID_SIMPLE_BLOCK = 0xA3, |
194 | |
195 | /* Track */ |
196 | MKV_ELEMENT_ID_TRACKS = 0x1654AE6B, |
197 | MKV_ELEMENT_ID_TRACK_ENTRY = 0xAE, |
198 | MKV_ELEMENT_ID_TRACK_NUMBER = 0xD7, |
199 | MKV_ELEMENT_ID_TRACK_UID = 0x73C5, |
200 | MKV_ELEMENT_ID_TRACK_TYPE = 0x83, |
201 | MKV_ELEMENT_ID_FLAG_ENABLED = 0xB9, |
202 | MKV_ELEMENT_ID_FLAG_DEFAULT = 0x88, |
203 | MKV_ELEMENT_ID_FLAG_FORCED = 0x55AA, |
204 | MKV_ELEMENT_ID_FLAG_LACING = 0x9C, |
205 | MKV_ELEMENT_ID_MIN_CACHE = 0x6DE7, |
206 | MKV_ELEMENT_ID_MAX_CACHE = 0x6DF8, |
207 | MKV_ELEMENT_ID_DEFAULT_DURATION = 0x23E383, |
208 | MKV_ELEMENT_ID_TRACK_TIMECODE_SCALE = 0x23314F, |
209 | MKV_ELEMENT_ID_MAX_BLOCK_ADDITION_ID = 0x55EE, |
210 | MKV_ELEMENT_ID_NAME = 0x536E, |
211 | MKV_ELEMENT_ID_LANGUAGE = 0x22B59C, |
212 | MKV_ELEMENT_ID_TRACK_CODEC_ID = 0x86, |
213 | MKV_ELEMENT_ID_TRACK_CODEC_PRIVATE = 0x63A2, |
214 | MKV_ELEMENT_ID_TRACK_CODEC_NAME = 0x258688, |
215 | MKV_ELEMENT_ID_ATTACHMENT_LINK = 0x7446, |
216 | MKV_ELEMENT_ID_CODEC_DECODE_ALL = 0xAA, |
217 | MKV_ELEMENT_ID_TRACK_OVERLAY = 0x6FAB, |
218 | MKV_ELEMENT_ID_TRACK_TRANSLATE = 0x6624, |
219 | MKV_ELEMENT_ID_TRACK_TRANSLATE_EDITION_UID = 0x66FC, |
220 | MKV_ELEMENT_ID_TRACK_TRANSLATE_CODEC = 0x66BF, |
221 | MKV_ELEMENT_ID_TRACK_TRANSLATE_TRACK_ID = 0x66A5, |
222 | |
223 | /* Video */ |
224 | MKV_ELEMENT_ID_VIDEO = 0xE0, |
225 | MKV_ELEMENT_ID_FLAG_INTERLACED = 0x9A, |
226 | MKV_ELEMENT_ID_STEREO_MODE = 0x53B8, |
227 | MKV_ELEMENT_ID_PIXEL_WIDTH = 0xB0, |
228 | MKV_ELEMENT_ID_PIXEL_HEIGHT = 0xBA, |
229 | MKV_ELEMENT_ID_PIXEL_CROP_BOTTOM = 0x54AA, |
230 | MKV_ELEMENT_ID_PIXEL_CROP_TOP = 0x54BB, |
231 | MKV_ELEMENT_ID_PIXEL_CROP_LEFT = 0x54CC, |
232 | MKV_ELEMENT_ID_PIXEL_CROP_RIGHT = 0x54DD, |
233 | MKV_ELEMENT_ID_DISPLAY_WIDTH = 0x54B0, |
234 | MKV_ELEMENT_ID_DISPLAY_HEIGHT = 0x54BA, |
235 | MKV_ELEMENT_ID_DISPLAY_UNIT = 0x54B2, |
236 | MKV_ELEMENT_ID_ASPECT_RATIO_TYPE = 0x54B3, |
237 | MKV_ELEMENT_ID_COLOUR_SPACE = 0x2EB524, |
238 | MKV_ELEMENT_ID_FRAME_RATE = 0x2383E3, |
239 | |
240 | /* Audio */ |
241 | MKV_ELEMENT_ID_AUDIO = 0xE1, |
242 | MKV_ELEMENT_ID_SAMPLING_FREQUENCY = 0xB5, |
243 | MKV_ELEMENT_ID_OUTPUT_SAMPLING_FREQUENCY = 0x78B5, |
244 | MKV_ELEMENT_ID_CHANNELS = 0x9F, |
245 | MKV_ELEMENT_ID_BIT_DEPTH = 0x6264, |
246 | |
247 | /* Content Encoding */ |
248 | MKV_ELEMENT_ID_CONTENT_ENCODINGS = 0x6D80, |
249 | MKV_ELEMENT_ID_CONTENT_ENCODING = 0x6240, |
250 | MKV_ELEMENT_ID_CONTENT_ENCODING_ORDER = 0x5031, |
251 | MKV_ELEMENT_ID_CONTENT_ENCODING_SCOPE = 0x5032, |
252 | MKV_ELEMENT_ID_CONTENT_ENCODING_TYPE = 0x5033, |
253 | MKV_ELEMENT_ID_CONTENT_COMPRESSION = 0x5034, |
254 | MKV_ELEMENT_ID_CONTENT_COMPRESSION_ALGO = 0x4254, |
255 | MKV_ELEMENT_ID_CONTENT_COMPRESSION_SETTINGS = 0x4255, |
256 | MKV_ELEMENT_ID_CONTENT_ENCRYPTION = 0x5035, |
257 | MKV_ELEMENT_ID_CONTENT_ENCRYPTION_ALGO = 0x47E1, |
258 | MKV_ELEMENT_ID_CONTENT_ENCRYPTION_KEY_ID = 0x47E2, |
259 | MKV_ELEMENT_ID_CONTENT_SIGNATURE = 0x47E3, |
260 | MKV_ELEMENT_ID_CONTENT_SIGNATURE_KEY_ID = 0x47E4, |
261 | MKV_ELEMENT_ID_CONTENT_SIGNATURE_ALGO = 0x47E5, |
262 | MKV_ELEMENT_ID_CONTENT_SIGNATURE_HASH_ALGO = 0x47E6, |
263 | |
264 | /* Cueing Data */ |
265 | MKV_ELEMENT_ID_CUES = 0x1C53BB6B, |
266 | MKV_ELEMENT_ID_CUE_POINT = 0xBB, |
267 | MKV_ELEMENT_ID_CUE_TIME = 0xB3, |
268 | MKV_ELEMENT_ID_CUE_TRACK_POSITIONS = 0xB7, |
269 | MKV_ELEMENT_ID_CUE_TRACK = 0xF7, |
270 | MKV_ELEMENT_ID_CUE_CLUSTER_POSITION = 0xF1, |
271 | MKV_ELEMENT_ID_CUE_BLOCK_NUMBER = 0x5378, |
272 | |
273 | /* Attachments */ |
274 | MKV_ELEMENT_ID_ATTACHMENTS = 0x1941A469, |
275 | |
276 | /* Chapters */ |
277 | MKV_ELEMENT_ID_CHAPTERS = 0x1043A770, |
278 | |
279 | /* Tagging */ |
280 | MKV_ELEMENT_ID_TAGS = 0x1254C367, |
281 | MKV_ELEMENT_ID_TAG = 0x7373, |
282 | MKV_ELEMENT_ID_TAG_TARGETS = 0x63C0, |
283 | MKV_ELEMENT_ID_TAG_TARGET_TYPE_VALUE = 0x68CA, |
284 | MKV_ELEMENT_ID_TAG_TARGET_TYPE = 0x63CA, |
285 | MKV_ELEMENT_ID_TAG_TRACK_UID = 0x63C5, |
286 | MKV_ELEMENT_ID_TAG_EDITION_UID = 0x63C9, |
287 | MKV_ELEMENT_ID_TAG_CHAPTER_UID = 0x63C4, |
288 | MKV_ELEMENT_ID_TAG_ATTACHMENT_UID = 0x63C6, |
289 | MKV_ELEMENT_ID_TAG_SIMPLE_TAG = 0x67C8, |
290 | MKV_ELEMENT_ID_TAG_NAME = 0x45A3, |
291 | MKV_ELEMENT_ID_TAG_LANGUAGE = 0x447A, |
292 | MKV_ELEMENT_ID_TAG_DEFAULT = 0x4484, |
293 | MKV_ELEMENT_ID_TAG_STRING = 0x4487, |
294 | MKV_ELEMENT_ID_TAG_BINARY = 0x4485, |
295 | |
296 | MKV_ELEMENT_ID_INVALID = 0xFFFFFFFF |
297 | } MKV_ELEMENT_ID_T; |
298 | |
299 | /** Context for our reader |
300 | */ |
301 | |
302 | typedef struct |
303 | { |
304 | unsigned int track; |
305 | unsigned int flags; |
306 | int64_t pts; |
307 | int64_t cluster_timecode; |
308 | int64_t prev_cluster_size; /* Size of the previous cluster if available */ |
309 | int64_t frame_duration; |
310 | |
311 | int level; |
312 | struct { |
313 | int64_t offset; |
314 | int64_t data_start; |
315 | int64_t data_offset; |
316 | int64_t size; |
317 | MKV_ELEMENT_ID_T id; |
318 | } levels[MKV_MAX_READER_STATE_LEVEL]; |
319 | |
320 | bool eos; |
321 | bool corrupted; |
322 | bool seen_ref_block; |
323 | |
324 | uint32_t lacing_num_frames; |
325 | uint32_t lacing_size; |
326 | uint16_t lacing_sizes[MKV_MAX_LACING_NUM]; |
327 | uint32_t lacing_current_size; |
328 | |
329 | /* For header stripping compression */ |
330 | uint32_t ; |
331 | uint8_t *; |
332 | uint32_t ; |
333 | } MKV_READER_STATE_T; |
334 | |
335 | typedef struct |
336 | { |
337 | const MKV_ELEMENT_ID_T id; |
338 | const MKV_ELEMENT_ID_T parent_id; |
339 | const char *psz_name; |
340 | VC_CONTAINER_STATUS_T (*pf_func)(VC_CONTAINER_T *, MKV_ELEMENT_ID_T, int64_t); |
341 | |
342 | } MKV_ELEMENT_T; |
343 | |
344 | typedef struct VC_CONTAINER_TRACK_MODULE_T |
345 | { |
346 | MKV_READER_STATE_T *state; |
347 | MKV_READER_STATE_T track_state; |
348 | |
349 | /* Information extracted from the track entry */ |
350 | uint32_t number; |
351 | uint32_t type; |
352 | int64_t timecode_scale; |
353 | uint32_t duration; |
354 | int64_t frame_duration; |
355 | char codecid[MKV_CODECID_MAX]; |
356 | |
357 | union { |
358 | /* video specific */ |
359 | struct { |
360 | unsigned int interlaced:1; |
361 | unsigned int stereo_mode:2; |
362 | uint32_t pixel_width; |
363 | uint32_t pixel_height; |
364 | uint32_t pixel_crop_bottom; |
365 | uint32_t pixel_crop_top; |
366 | uint32_t pixel_crop_left; |
367 | uint32_t pixel_crop_right; |
368 | uint32_t display_width; |
369 | uint32_t display_height; |
370 | uint32_t display_unit; |
371 | uint32_t aspect_ratio_type; |
372 | float frame_rate; |
373 | } video; |
374 | |
375 | /* audio specific */ |
376 | struct { |
377 | uint32_t sampling_frequency; |
378 | uint32_t output_sampling_frequency; |
379 | uint32_t channels; |
380 | uint32_t bit_depth; |
381 | } audio; |
382 | } es_type; |
383 | |
384 | /* content encoding (i.e. lossless compression and encryption) */ |
385 | unsigned int encodings_num; |
386 | struct { |
387 | enum { |
388 | MKV_CONTENT_ENCODING_COMPRESSION_ZLIB, |
389 | , |
390 | MKV_CONTENT_ENCODING_ENCRYPTION, |
391 | MKV_CONTENT_ENCODING_UNKNOWN |
392 | } type; |
393 | unsigned int data_size; |
394 | uint8_t *data; |
395 | } encodings[MKV_MAX_ENCODINGS]; |
396 | |
397 | } VC_CONTAINER_TRACK_MODULE_T; |
398 | |
399 | typedef struct VC_CONTAINER_MODULE_T |
400 | { |
401 | MKV_ELEMENT_T *elements_list; |
402 | int element_level; |
403 | MKV_ELEMENT_ID_T parent_id; |
404 | |
405 | uint64_t element_offset; /**< Offset to the start of the current element */ |
406 | |
407 | uint64_t segment_offset; /**< Offset to the start of the data packets */ |
408 | int64_t segment_size; |
409 | |
410 | int tracks_num; |
411 | VC_CONTAINER_TRACK_T *tracks[MKV_TRACKS_MAX]; |
412 | |
413 | MKV_READER_STATE_T state; |
414 | int64_t timecode_scale; |
415 | float duration; |
416 | |
417 | uint64_t cluster_offset; /**< Offset to the first cluster */ |
418 | uint64_t cues_offset; /**< Offset to the start of the seeking cues */ |
419 | uint64_t tags_offset; /**< Offset to the start of the tags */ |
420 | |
421 | /* |
422 | * Variables only used during parsing of the header |
423 | */ |
424 | |
425 | VC_CONTAINER_TRACK_T *parsing; /**< Current track being parsed */ |
426 | bool is_doctype_valid; |
427 | |
428 | MKV_ELEMENT_ID_T seekhead_elem_id; |
429 | int64_t seekhead_elem_offset; |
430 | |
431 | /* Cues */ |
432 | unsigned int cue_track; |
433 | int64_t cue_timecode; |
434 | uint64_t cue_cluster_offset; |
435 | unsigned int cue_block; |
436 | |
437 | } VC_CONTAINER_MODULE_T; |
438 | |
439 | /****************************************************************************** |
440 | Function prototypes |
441 | ******************************************************************************/ |
442 | VC_CONTAINER_STATUS_T mkv_reader_open( VC_CONTAINER_T * ); |
443 | |
444 | /****************************************************************************** |
445 | Prototypes for local functions |
446 | ******************************************************************************/ |
447 | static VC_CONTAINER_STATUS_T mkv_read_element( VC_CONTAINER_T *p_ctx, int64_t size, MKV_ELEMENT_ID_T parent_id ); |
448 | static VC_CONTAINER_STATUS_T mkv_read_elements( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ); |
449 | static VC_CONTAINER_STATUS_T mkv_read_element_data_uint( VC_CONTAINER_T *p_ctx, int64_t size, uint64_t *value ); |
450 | static VC_CONTAINER_STATUS_T mkv_read_element_data_float( VC_CONTAINER_T *p_ctx, int64_t size, double *value ); |
451 | static VC_CONTAINER_STATUS_T mkv_read_element_ebml( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ); |
452 | static VC_CONTAINER_STATUS_T mkv_read_subelements_ebml( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ); |
453 | static VC_CONTAINER_STATUS_T mkv_read_element_segment( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ); |
454 | static VC_CONTAINER_STATUS_T mkv_read_element_track_entry( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ); |
455 | static VC_CONTAINER_STATUS_T mkv_read_subelements_track_entry( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ); |
456 | static VC_CONTAINER_STATUS_T mkv_read_subelements_video( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ); |
457 | static VC_CONTAINER_STATUS_T mkv_read_subelements_audio( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ); |
458 | static VC_CONTAINER_STATUS_T mkv_read_subelements_info( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ); |
459 | static VC_CONTAINER_STATUS_T mkv_read_element_encoding( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ); |
460 | static VC_CONTAINER_STATUS_T mkv_read_subelements_encoding( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ); |
461 | static VC_CONTAINER_STATUS_T mkv_read_subelements_compression( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ); |
462 | static VC_CONTAINER_STATUS_T mkv_read_subelements_seek_head( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ); |
463 | static VC_CONTAINER_STATUS_T mkv_read_element_cues( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ); |
464 | static VC_CONTAINER_STATUS_T mkv_read_subelements_cue_point( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ); |
465 | |
466 | static VC_CONTAINER_STATUS_T mkv_read_subelements_cluster( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ); |
467 | |
468 | /****************************************************************************** |
469 | List of element IDs and their associated processing functions |
470 | ******************************************************************************/ |
471 | MKV_ELEMENT_T mkv_elements_list[] = |
472 | { |
473 | /* EBML Basics */ |
474 | {MKV_ELEMENT_ID_EBML, MKV_ELEMENT_ID_UNKNOWN, "EBML" , mkv_read_element_ebml}, |
475 | {MKV_ELEMENT_ID_EBML_VERSION, MKV_ELEMENT_ID_EBML, "EBMLVersion" , mkv_read_subelements_ebml}, |
476 | {MKV_ELEMENT_ID_EBML_READ_VERSION, MKV_ELEMENT_ID_EBML, "EBMLReadVersion" , mkv_read_subelements_ebml}, |
477 | {MKV_ELEMENT_ID_EBML_MAX_ID_LENGTH, MKV_ELEMENT_ID_EBML, "EBMLMaxIDLength" , mkv_read_subelements_ebml}, |
478 | {MKV_ELEMENT_ID_EBML_MAX_SIZE_LENGTH, MKV_ELEMENT_ID_EBML, "EBMLMaxSizeLength" , mkv_read_subelements_ebml}, |
479 | {MKV_ELEMENT_ID_DOCTYPE, MKV_ELEMENT_ID_EBML, "DocType" , mkv_read_subelements_ebml}, |
480 | {MKV_ELEMENT_ID_DOCTYPE_VERSION, MKV_ELEMENT_ID_EBML, "DocTypeVersion" , mkv_read_subelements_ebml}, |
481 | {MKV_ELEMENT_ID_DOCTYPE_READ_VERSION, MKV_ELEMENT_ID_EBML, "DocTypeReadVersion" , mkv_read_subelements_ebml}, |
482 | |
483 | /* Global Elements */ |
484 | {MKV_ELEMENT_ID_CRC32, MKV_ELEMENT_ID_INVALID, "CRC-32" , 0}, |
485 | {MKV_ELEMENT_ID_VOID, MKV_ELEMENT_ID_INVALID, "Void" , 0}, |
486 | |
487 | /* Segment */ |
488 | {MKV_ELEMENT_ID_SEGMENT, MKV_ELEMENT_ID_UNKNOWN, "Segment" , mkv_read_element_segment}, |
489 | |
490 | /* Meta Seek Information */ |
491 | {MKV_ELEMENT_ID_SEEK_HEAD, MKV_ELEMENT_ID_SEGMENT, "SeekHead" , mkv_read_elements}, |
492 | {MKV_ELEMENT_ID_SEEK, MKV_ELEMENT_ID_SEEK_HEAD, "Seek" , mkv_read_subelements_seek_head}, |
493 | {MKV_ELEMENT_ID_SEEK_ID, MKV_ELEMENT_ID_SEEK, "SeekID" , mkv_read_subelements_seek_head}, |
494 | {MKV_ELEMENT_ID_SEEK_POSITION, MKV_ELEMENT_ID_SEEK, "SeekPosition" , mkv_read_subelements_seek_head}, |
495 | |
496 | /* Segment Information */ |
497 | {MKV_ELEMENT_ID_INFO, MKV_ELEMENT_ID_SEGMENT, "Info" , mkv_read_elements}, |
498 | {MKV_ELEMENT_ID_SEGMENT_UID, MKV_ELEMENT_ID_INFO, "SegmentUID" , 0}, |
499 | {MKV_ELEMENT_ID_SEGMENT_FILENAME, MKV_ELEMENT_ID_INFO, "SegmentFilename" , 0}, |
500 | {MKV_ELEMENT_ID_PREV_UID, MKV_ELEMENT_ID_INFO, "PrevUID" , 0}, |
501 | {MKV_ELEMENT_ID_PREV_FILENAME, MKV_ELEMENT_ID_INFO, "PrevFilename" , 0}, |
502 | {MKV_ELEMENT_ID_NEXT_UID, MKV_ELEMENT_ID_INFO, "NextUID" , 0}, |
503 | {MKV_ELEMENT_ID_NEXT_FILENAME, MKV_ELEMENT_ID_INFO, "NextFilename" , 0}, |
504 | {MKV_ELEMENT_ID_SEGMENT_FAMILY, MKV_ELEMENT_ID_INFO, "SegmentFamily" , 0}, |
505 | {MKV_ELEMENT_ID_CHAPTER_TRANSLATE, MKV_ELEMENT_ID_INFO, "ChapterTranslate" , 0}, |
506 | {MKV_ELEMENT_ID_CHAPTER_TRANSLATE_EDITION_UID, MKV_ELEMENT_ID_INFO, "ChapterTranslateEditionUID" , 0}, |
507 | {MKV_ELEMENT_ID_CHAPTER_TRANSLATE_CODEC, MKV_ELEMENT_ID_INFO, "ChapterTranslateCodec" , 0}, |
508 | {MKV_ELEMENT_ID_CHAPTER_TRANSLATE_ID, MKV_ELEMENT_ID_INFO, "ChapterTranslateID" , 0}, |
509 | {MKV_ELEMENT_ID_TIMECODE_SCALE, MKV_ELEMENT_ID_INFO, "TimecodeScale" , mkv_read_subelements_info}, |
510 | {MKV_ELEMENT_ID_DURATION, MKV_ELEMENT_ID_INFO, "Duration" , mkv_read_subelements_info}, |
511 | {MKV_ELEMENT_ID_DATE_UTC, MKV_ELEMENT_ID_INFO, "DateUTC" , 0}, |
512 | {MKV_ELEMENT_ID_TITLE, MKV_ELEMENT_ID_INFO, "Title" , mkv_read_subelements_info}, |
513 | {MKV_ELEMENT_ID_MUXING_APP, MKV_ELEMENT_ID_INFO, "MuxingApp" , mkv_read_subelements_info}, |
514 | {MKV_ELEMENT_ID_WRITING_APP, MKV_ELEMENT_ID_INFO, "WritingApp" , mkv_read_subelements_info}, |
515 | |
516 | /* Cluster */ |
517 | {MKV_ELEMENT_ID_CLUSTER, MKV_ELEMENT_ID_SEGMENT, "Cluster" , 0}, |
518 | {MKV_ELEMENT_ID_TIMECODE, MKV_ELEMENT_ID_CLUSTER, "Timecode" , 0}, |
519 | {MKV_ELEMENT_ID_SILENT_TRACKS, MKV_ELEMENT_ID_CLUSTER, "SilentTracks" , 0}, |
520 | {MKV_ELEMENT_ID_SILENT_TRACK_NUMBER, MKV_ELEMENT_ID_CLUSTER, "SilentTrackNumber" , 0}, |
521 | {MKV_ELEMENT_ID_POSITION, MKV_ELEMENT_ID_CLUSTER, "Position" , 0}, |
522 | {MKV_ELEMENT_ID_PREV_SIZE, MKV_ELEMENT_ID_CLUSTER, "PrevSize" , 0}, |
523 | {MKV_ELEMENT_ID_BLOCKGROUP, MKV_ELEMENT_ID_CLUSTER, "BlockGroup" , 0}, |
524 | {MKV_ELEMENT_ID_BLOCK, MKV_ELEMENT_ID_BLOCKGROUP, "Block" , 0}, |
525 | {MKV_ELEMENT_ID_BLOCK_ADDITIONS, MKV_ELEMENT_ID_BLOCKGROUP, "BlockAdditions" , 0}, |
526 | {MKV_ELEMENT_ID_BLOCK_MORE, MKV_ELEMENT_ID_BLOCK_ADDITIONS, "BlockMore" , 0}, |
527 | {MKV_ELEMENT_ID_BLOCK_ADD_ID, MKV_ELEMENT_ID_BLOCK_MORE, "BlockAddId" , 0}, |
528 | {MKV_ELEMENT_ID_BLOCK_ADDITIONAL, MKV_ELEMENT_ID_BLOCK_MORE, "BlockAdditional" , 0}, |
529 | {MKV_ELEMENT_ID_BLOCK_DURATION, MKV_ELEMENT_ID_BLOCKGROUP, "BlockDuration" , 0}, |
530 | {MKV_ELEMENT_ID_REFERENCE_PRIORITY, MKV_ELEMENT_ID_BLOCKGROUP, "ReferencePriority" , 0}, |
531 | {MKV_ELEMENT_ID_REFERENCE_BLOCK, MKV_ELEMENT_ID_BLOCKGROUP, "ReferenceBlock" , 0}, |
532 | {MKV_ELEMENT_ID_CODEC_STATE, MKV_ELEMENT_ID_BLOCKGROUP, "CodecState" , 0}, |
533 | {MKV_ELEMENT_ID_SLICES, MKV_ELEMENT_ID_BLOCKGROUP, "Slices" , 0}, |
534 | {MKV_ELEMENT_ID_TIME_SLICE, MKV_ELEMENT_ID_SLICES, "TimeSlice" , 0}, |
535 | {MKV_ELEMENT_ID_LACE_NUMBER, MKV_ELEMENT_ID_TIME_SLICE, "LaceNumber" , 0}, |
536 | {MKV_ELEMENT_ID_SIMPLE_BLOCK, MKV_ELEMENT_ID_CLUSTER, "SimpleBlock" , 0}, |
537 | |
538 | /* Track */ |
539 | {MKV_ELEMENT_ID_TRACKS, MKV_ELEMENT_ID_SEGMENT, "Tracks" , mkv_read_elements}, |
540 | {MKV_ELEMENT_ID_TRACK_ENTRY, MKV_ELEMENT_ID_TRACKS, "TrackEntry" , mkv_read_element_track_entry}, |
541 | {MKV_ELEMENT_ID_TRACK_NUMBER, MKV_ELEMENT_ID_TRACK_ENTRY, "TrackNumber" , mkv_read_subelements_track_entry}, |
542 | {MKV_ELEMENT_ID_TRACK_UID, MKV_ELEMENT_ID_TRACK_ENTRY, "TrackUID" , mkv_read_subelements_track_entry}, |
543 | {MKV_ELEMENT_ID_TRACK_TYPE, MKV_ELEMENT_ID_TRACK_ENTRY, "TrackType" , mkv_read_subelements_track_entry}, |
544 | {MKV_ELEMENT_ID_FLAG_ENABLED, MKV_ELEMENT_ID_TRACK_ENTRY, "FlagEnabled" , mkv_read_subelements_track_entry}, |
545 | {MKV_ELEMENT_ID_FLAG_DEFAULT, MKV_ELEMENT_ID_TRACK_ENTRY, "FlagDefault" , mkv_read_subelements_track_entry}, |
546 | {MKV_ELEMENT_ID_FLAG_FORCED, MKV_ELEMENT_ID_TRACK_ENTRY, "FlagForced" , mkv_read_subelements_track_entry}, |
547 | {MKV_ELEMENT_ID_FLAG_LACING, MKV_ELEMENT_ID_TRACK_ENTRY, "FlagLacing" , mkv_read_subelements_track_entry}, |
548 | {MKV_ELEMENT_ID_MIN_CACHE, MKV_ELEMENT_ID_TRACK_ENTRY, "MinCache" , 0}, |
549 | {MKV_ELEMENT_ID_MAX_CACHE, MKV_ELEMENT_ID_TRACK_ENTRY, "MaxCache" , 0}, |
550 | {MKV_ELEMENT_ID_DEFAULT_DURATION, MKV_ELEMENT_ID_TRACK_ENTRY, "DefaultDuration" , mkv_read_subelements_track_entry}, |
551 | {MKV_ELEMENT_ID_TRACK_TIMECODE_SCALE, MKV_ELEMENT_ID_TRACK_ENTRY, "TrackTimecodeScale" , mkv_read_subelements_track_entry}, |
552 | {MKV_ELEMENT_ID_MAX_BLOCK_ADDITION_ID, MKV_ELEMENT_ID_TRACK_ENTRY, "MaxBlockAdditionID" , 0}, |
553 | {MKV_ELEMENT_ID_NAME, MKV_ELEMENT_ID_TRACK_ENTRY, "Name" , mkv_read_subelements_track_entry}, |
554 | {MKV_ELEMENT_ID_LANGUAGE, MKV_ELEMENT_ID_TRACK_ENTRY, "Language" , mkv_read_subelements_track_entry}, |
555 | {MKV_ELEMENT_ID_TRACK_CODEC_ID, MKV_ELEMENT_ID_TRACK_ENTRY, "CodecID" , mkv_read_subelements_track_entry}, |
556 | {MKV_ELEMENT_ID_TRACK_CODEC_PRIVATE, MKV_ELEMENT_ID_TRACK_ENTRY, "CodecPrivate" , mkv_read_subelements_track_entry}, |
557 | {MKV_ELEMENT_ID_TRACK_CODEC_NAME, MKV_ELEMENT_ID_TRACK_ENTRY, "CodecName" , mkv_read_subelements_track_entry}, |
558 | {MKV_ELEMENT_ID_ATTACHMENT_LINK, MKV_ELEMENT_ID_TRACK_ENTRY, "AttachmentLink" , 0}, |
559 | {MKV_ELEMENT_ID_CODEC_DECODE_ALL, MKV_ELEMENT_ID_TRACK_ENTRY, "DecodeAll" , 0}, |
560 | {MKV_ELEMENT_ID_TRACK_OVERLAY, MKV_ELEMENT_ID_TRACK_ENTRY, "TrackOverlay" , 0}, |
561 | {MKV_ELEMENT_ID_TRACK_TRANSLATE, MKV_ELEMENT_ID_TRACK_ENTRY, "TrackTranslate" , 0}, |
562 | {MKV_ELEMENT_ID_TRACK_TRANSLATE_EDITION_UID, MKV_ELEMENT_ID_TRACK_TRANSLATE, "TrackTranslateEditionUID" , 0}, |
563 | {MKV_ELEMENT_ID_TRACK_TRANSLATE_CODEC, MKV_ELEMENT_ID_TRACK_TRANSLATE, "TrackTranslateCodec" , 0}, |
564 | {MKV_ELEMENT_ID_TRACK_TRANSLATE_TRACK_ID, MKV_ELEMENT_ID_TRACK_TRANSLATE, "TrackTranslateTrackID" , 0}, |
565 | |
566 | /* Video */ |
567 | {MKV_ELEMENT_ID_VIDEO, MKV_ELEMENT_ID_TRACK_ENTRY, "Video" , mkv_read_elements}, |
568 | {MKV_ELEMENT_ID_FLAG_INTERLACED, MKV_ELEMENT_ID_VIDEO, "FlagInterlaced" , mkv_read_subelements_video}, |
569 | {MKV_ELEMENT_ID_STEREO_MODE, MKV_ELEMENT_ID_VIDEO, "StereoMode" , mkv_read_subelements_video}, |
570 | {MKV_ELEMENT_ID_PIXEL_WIDTH, MKV_ELEMENT_ID_VIDEO, "PixelWidth" , mkv_read_subelements_video}, |
571 | {MKV_ELEMENT_ID_PIXEL_HEIGHT, MKV_ELEMENT_ID_VIDEO, "PixelHeight" , mkv_read_subelements_video}, |
572 | {MKV_ELEMENT_ID_PIXEL_CROP_BOTTOM, MKV_ELEMENT_ID_VIDEO, "PixelCropBottom" , mkv_read_subelements_video}, |
573 | {MKV_ELEMENT_ID_PIXEL_CROP_TOP, MKV_ELEMENT_ID_VIDEO, "PixelCropTop" , mkv_read_subelements_video}, |
574 | {MKV_ELEMENT_ID_PIXEL_CROP_LEFT, MKV_ELEMENT_ID_VIDEO, "PixelCropLeft" , mkv_read_subelements_video}, |
575 | {MKV_ELEMENT_ID_PIXEL_CROP_RIGHT, MKV_ELEMENT_ID_VIDEO, "PixelCropRight" , mkv_read_subelements_video}, |
576 | {MKV_ELEMENT_ID_DISPLAY_WIDTH, MKV_ELEMENT_ID_VIDEO, "DisplayWidth" , mkv_read_subelements_video}, |
577 | {MKV_ELEMENT_ID_DISPLAY_HEIGHT, MKV_ELEMENT_ID_VIDEO, "DisplayHeight" , mkv_read_subelements_video}, |
578 | {MKV_ELEMENT_ID_DISPLAY_UNIT, MKV_ELEMENT_ID_VIDEO, "DisplayUnit" , mkv_read_subelements_video}, |
579 | {MKV_ELEMENT_ID_ASPECT_RATIO_TYPE, MKV_ELEMENT_ID_VIDEO, "AspectRatioType" , mkv_read_subelements_video}, |
580 | {MKV_ELEMENT_ID_COLOUR_SPACE, MKV_ELEMENT_ID_VIDEO, "ColourSpace" , mkv_read_subelements_video}, |
581 | {MKV_ELEMENT_ID_FRAME_RATE, MKV_ELEMENT_ID_VIDEO, "FrameRate" , mkv_read_subelements_video}, |
582 | |
583 | /* Audio */ |
584 | {MKV_ELEMENT_ID_AUDIO, MKV_ELEMENT_ID_TRACK_ENTRY, "Audio" , mkv_read_elements}, |
585 | {MKV_ELEMENT_ID_SAMPLING_FREQUENCY, MKV_ELEMENT_ID_AUDIO, "SamplingFrequency" , mkv_read_subelements_audio}, |
586 | {MKV_ELEMENT_ID_OUTPUT_SAMPLING_FREQUENCY, MKV_ELEMENT_ID_AUDIO, "OutputSamplingFrequency" , mkv_read_subelements_audio}, |
587 | {MKV_ELEMENT_ID_CHANNELS, MKV_ELEMENT_ID_AUDIO, "Channels" , mkv_read_subelements_audio}, |
588 | {MKV_ELEMENT_ID_BIT_DEPTH, MKV_ELEMENT_ID_AUDIO, "BitDepth" , mkv_read_subelements_audio}, |
589 | |
590 | /* Content Encoding */ |
591 | {MKV_ELEMENT_ID_CONTENT_ENCODINGS, MKV_ELEMENT_ID_TRACK_ENTRY, "ContentEncodings" , mkv_read_elements}, |
592 | {MKV_ELEMENT_ID_CONTENT_ENCODING, MKV_ELEMENT_ID_CONTENT_ENCODINGS, "ContentEncoding" , mkv_read_element_encoding}, |
593 | {MKV_ELEMENT_ID_CONTENT_ENCODING_ORDER, MKV_ELEMENT_ID_CONTENT_ENCODING, "ContentEncodingOrder" , mkv_read_subelements_encoding}, |
594 | {MKV_ELEMENT_ID_CONTENT_ENCODING_SCOPE, MKV_ELEMENT_ID_CONTENT_ENCODING, "ContentEncodingScope" , mkv_read_subelements_encoding}, |
595 | {MKV_ELEMENT_ID_CONTENT_ENCODING_TYPE, MKV_ELEMENT_ID_CONTENT_ENCODING, "ContentEncodingType" , mkv_read_subelements_encoding}, |
596 | {MKV_ELEMENT_ID_CONTENT_COMPRESSION, MKV_ELEMENT_ID_CONTENT_ENCODING, "ContentCompression" , mkv_read_elements}, |
597 | {MKV_ELEMENT_ID_CONTENT_COMPRESSION_ALGO, MKV_ELEMENT_ID_CONTENT_COMPRESSION, "ContentCompAlgo" , mkv_read_subelements_compression}, |
598 | {MKV_ELEMENT_ID_CONTENT_COMPRESSION_SETTINGS, MKV_ELEMENT_ID_CONTENT_COMPRESSION, "ContentCompSettings" , mkv_read_subelements_compression}, |
599 | {MKV_ELEMENT_ID_CONTENT_ENCRYPTION, MKV_ELEMENT_ID_CONTENT_ENCODING, "ContentEncryption" , mkv_read_elements}, |
600 | {MKV_ELEMENT_ID_CONTENT_ENCRYPTION_ALGO, MKV_ELEMENT_ID_CONTENT_ENCRYPTION, "ContentEncAlgo" , 0}, |
601 | {MKV_ELEMENT_ID_CONTENT_ENCRYPTION_KEY_ID, MKV_ELEMENT_ID_CONTENT_ENCRYPTION, "ContentEncKeyID" , 0}, |
602 | {MKV_ELEMENT_ID_CONTENT_SIGNATURE, MKV_ELEMENT_ID_CONTENT_ENCRYPTION, "ContentSignature" , 0}, |
603 | {MKV_ELEMENT_ID_CONTENT_SIGNATURE_KEY_ID, MKV_ELEMENT_ID_CONTENT_ENCRYPTION, "ContentSigKeyID" , 0}, |
604 | {MKV_ELEMENT_ID_CONTENT_SIGNATURE_ALGO, MKV_ELEMENT_ID_CONTENT_ENCRYPTION, "ContentSigAlgo" , 0}, |
605 | {MKV_ELEMENT_ID_CONTENT_SIGNATURE_HASH_ALGO, MKV_ELEMENT_ID_CONTENT_ENCRYPTION, "ContentSigHashAlgo" , 0}, |
606 | |
607 | /* Cueing data */ |
608 | {MKV_ELEMENT_ID_CUES, MKV_ELEMENT_ID_SEGMENT, "Cues" , mkv_read_element_cues}, |
609 | {MKV_ELEMENT_ID_CUE_POINT, MKV_ELEMENT_ID_CUES, "Cue Point" , mkv_read_elements}, |
610 | {MKV_ELEMENT_ID_CUE_TIME, MKV_ELEMENT_ID_CUE_POINT, "Cue Time" , 0}, |
611 | {MKV_ELEMENT_ID_CUE_TRACK_POSITIONS, MKV_ELEMENT_ID_CUE_POINT, "Cue Track Positions" , mkv_read_elements}, |
612 | {MKV_ELEMENT_ID_CUE_TRACK, MKV_ELEMENT_ID_CUE_TRACK_POSITIONS, "Cue Track" , 0}, |
613 | {MKV_ELEMENT_ID_CUE_CLUSTER_POSITION, MKV_ELEMENT_ID_CUE_TRACK_POSITIONS, "Cue Cluster Position" , 0}, |
614 | {MKV_ELEMENT_ID_CUE_BLOCK_NUMBER, MKV_ELEMENT_ID_CUE_TRACK_POSITIONS, "Cue Block Number" , 0}, |
615 | |
616 | /* Attachments */ |
617 | {MKV_ELEMENT_ID_ATTACHMENTS, MKV_ELEMENT_ID_SEGMENT, "Attachments" , 0}, |
618 | |
619 | /* Chapters */ |
620 | {MKV_ELEMENT_ID_CHAPTERS, MKV_ELEMENT_ID_SEGMENT, "Chapters" , 0}, |
621 | |
622 | /* Tagging */ |
623 | {MKV_ELEMENT_ID_TAGS, MKV_ELEMENT_ID_SEGMENT, "Tags" , mkv_read_elements}, |
624 | {MKV_ELEMENT_ID_TAG, MKV_ELEMENT_ID_TAGS, "Tag" , mkv_read_elements}, |
625 | {MKV_ELEMENT_ID_TAG_TARGETS, MKV_ELEMENT_ID_TAG, "Tag Targets" , mkv_read_elements}, |
626 | {MKV_ELEMENT_ID_TAG_TARGET_TYPE_VALUE, MKV_ELEMENT_ID_TAG_TARGETS, "Tag Target Type Value" , 0}, |
627 | {MKV_ELEMENT_ID_TAG_TARGET_TYPE, MKV_ELEMENT_ID_TAG_TARGETS, "Tag Target Type" , 0}, |
628 | {MKV_ELEMENT_ID_TAG_TRACK_UID, MKV_ELEMENT_ID_TAG_TARGETS, "Tag Track UID" , 0}, |
629 | {MKV_ELEMENT_ID_TAG_EDITION_UID, MKV_ELEMENT_ID_TAG_TARGETS, "Tag Edition UID" , 0}, |
630 | {MKV_ELEMENT_ID_TAG_CHAPTER_UID, MKV_ELEMENT_ID_TAG_TARGETS, "Tag Chapter UID" , 0}, |
631 | {MKV_ELEMENT_ID_TAG_ATTACHMENT_UID, MKV_ELEMENT_ID_TAG_TARGETS, "Tag Attachment UID" , 0}, |
632 | {MKV_ELEMENT_ID_TAG_SIMPLE_TAG, MKV_ELEMENT_ID_TAG, "Simple Tag" , mkv_read_elements}, |
633 | {MKV_ELEMENT_ID_TAG_NAME, MKV_ELEMENT_ID_TAG_SIMPLE_TAG, "Tag Name" , 0}, |
634 | {MKV_ELEMENT_ID_TAG_LANGUAGE, MKV_ELEMENT_ID_TAG_SIMPLE_TAG, "Tag Language" , 0}, |
635 | {MKV_ELEMENT_ID_TAG_DEFAULT, MKV_ELEMENT_ID_TAG_SIMPLE_TAG, "Tag Default" , 0}, |
636 | {MKV_ELEMENT_ID_TAG_STRING, MKV_ELEMENT_ID_TAG_SIMPLE_TAG, "Tag String" , 0}, |
637 | {MKV_ELEMENT_ID_TAG_BINARY, MKV_ELEMENT_ID_TAG_SIMPLE_TAG, "Tag Binary" , 0}, |
638 | |
639 | {MKV_ELEMENT_ID_UNKNOWN, MKV_ELEMENT_ID_INVALID, "unknown" , 0} |
640 | }; |
641 | |
642 | MKV_ELEMENT_T mkv_cluster_elements_list[] = |
643 | { |
644 | /* Cluster */ |
645 | {MKV_ELEMENT_ID_CLUSTER, MKV_ELEMENT_ID_SEGMENT, "Cluster" , 0}, |
646 | {MKV_ELEMENT_ID_TIMECODE, MKV_ELEMENT_ID_CLUSTER, "Timecode" , mkv_read_subelements_cluster}, |
647 | {MKV_ELEMENT_ID_SILENT_TRACKS, MKV_ELEMENT_ID_CLUSTER, "SilentTracks" , 0}, |
648 | {MKV_ELEMENT_ID_SILENT_TRACK_NUMBER, MKV_ELEMENT_ID_CLUSTER, "SilentTrackNumber" , 0}, |
649 | {MKV_ELEMENT_ID_POSITION, MKV_ELEMENT_ID_CLUSTER, "Position" , 0}, |
650 | {MKV_ELEMENT_ID_PREV_SIZE, MKV_ELEMENT_ID_CLUSTER, "PrevSize" , 0}, |
651 | {MKV_ELEMENT_ID_BLOCKGROUP, MKV_ELEMENT_ID_CLUSTER, "BlockGroup" , 0}, |
652 | {MKV_ELEMENT_ID_BLOCK, MKV_ELEMENT_ID_BLOCKGROUP, "Block" , 0}, |
653 | {MKV_ELEMENT_ID_BLOCK_ADDITIONS, MKV_ELEMENT_ID_BLOCKGROUP, "BlockAdditions" , 0}, |
654 | {MKV_ELEMENT_ID_BLOCK_MORE, MKV_ELEMENT_ID_BLOCK_ADDITIONS, "BlockMore" , 0}, |
655 | {MKV_ELEMENT_ID_BLOCK_ADD_ID, MKV_ELEMENT_ID_BLOCK_MORE, "BlockAddId" , 0}, |
656 | {MKV_ELEMENT_ID_BLOCK_ADDITIONAL, MKV_ELEMENT_ID_BLOCK_MORE, "BlockAdditional" , 0}, |
657 | {MKV_ELEMENT_ID_BLOCK_DURATION, MKV_ELEMENT_ID_BLOCKGROUP, "BlockDuration" , mkv_read_subelements_cluster}, |
658 | {MKV_ELEMENT_ID_REFERENCE_PRIORITY, MKV_ELEMENT_ID_BLOCKGROUP, "ReferencePriority" , 0}, |
659 | {MKV_ELEMENT_ID_REFERENCE_BLOCK, MKV_ELEMENT_ID_BLOCKGROUP, "ReferenceBlock" , 0}, |
660 | {MKV_ELEMENT_ID_CODEC_STATE, MKV_ELEMENT_ID_BLOCKGROUP, "CodecState" , 0}, |
661 | {MKV_ELEMENT_ID_SLICES, MKV_ELEMENT_ID_BLOCKGROUP, "Slices" , 0}, |
662 | {MKV_ELEMENT_ID_TIME_SLICE, MKV_ELEMENT_ID_SLICES, "TimeSlice" , 0}, |
663 | {MKV_ELEMENT_ID_LACE_NUMBER, MKV_ELEMENT_ID_TIME_SLICE, "LaceNumber" , 0}, |
664 | {MKV_ELEMENT_ID_SIMPLE_BLOCK, MKV_ELEMENT_ID_CLUSTER, "SimpleBlock" , 0}, |
665 | |
666 | /* Global Elements */ |
667 | {MKV_ELEMENT_ID_CRC32, MKV_ELEMENT_ID_INVALID, "CRC-32" , 0}, |
668 | {MKV_ELEMENT_ID_VOID, MKV_ELEMENT_ID_INVALID, "Void" , 0}, |
669 | |
670 | {MKV_ELEMENT_ID_UNKNOWN, MKV_ELEMENT_ID_INVALID, "unknown" , 0} |
671 | }; |
672 | |
673 | MKV_ELEMENT_T mkv_cue_elements_list[] = |
674 | { |
675 | /* Cueing data */ |
676 | {MKV_ELEMENT_ID_CUES, MKV_ELEMENT_ID_SEGMENT, "Cues" , 0}, |
677 | {MKV_ELEMENT_ID_CUE_POINT, MKV_ELEMENT_ID_CUES, "Cue Point" , mkv_read_elements}, |
678 | {MKV_ELEMENT_ID_CUE_TIME, MKV_ELEMENT_ID_CUE_POINT, "Cue Time" , mkv_read_subelements_cue_point}, |
679 | {MKV_ELEMENT_ID_CUE_TRACK_POSITIONS, MKV_ELEMENT_ID_CUE_POINT, "Cue Track Positions" , mkv_read_elements}, |
680 | {MKV_ELEMENT_ID_CUE_TRACK, MKV_ELEMENT_ID_CUE_TRACK_POSITIONS, "Cue Track" , mkv_read_subelements_cue_point}, |
681 | {MKV_ELEMENT_ID_CUE_CLUSTER_POSITION, MKV_ELEMENT_ID_CUE_TRACK_POSITIONS, "Cue Cluster Position" , mkv_read_subelements_cue_point}, |
682 | {MKV_ELEMENT_ID_CUE_BLOCK_NUMBER, MKV_ELEMENT_ID_CUE_TRACK_POSITIONS, "Cue Block Number" , mkv_read_subelements_cue_point}, |
683 | |
684 | /* Global Elements */ |
685 | {MKV_ELEMENT_ID_CRC32, MKV_ELEMENT_ID_INVALID, "CRC-32" , 0}, |
686 | {MKV_ELEMENT_ID_VOID, MKV_ELEMENT_ID_INVALID, "Void" , 0}, |
687 | |
688 | {MKV_ELEMENT_ID_UNKNOWN, MKV_ELEMENT_ID_INVALID, "unknown" , 0} |
689 | }; |
690 | |
691 | /****************************************************************************** |
692 | List of codec mapping |
693 | ******************************************************************************/ |
694 | static const struct { |
695 | VC_CONTAINER_FOURCC_T fourcc; |
696 | const char *codecid; |
697 | VC_CONTAINER_FOURCC_T variant; |
698 | } codecid_to_fourcc_table[] = |
699 | { |
700 | /* Video */ |
701 | {VC_CONTAINER_CODEC_MP1V, "V_MPEG1" , 0}, |
702 | {VC_CONTAINER_CODEC_MP2V, "V_MPEG2" , 0}, |
703 | {VC_CONTAINER_CODEC_MP4V, "V_MPEG4/ISO/ASP" , 0}, |
704 | {VC_CONTAINER_CODEC_MP4V, "V_MPEG4/ISO/SP" , 0}, |
705 | {VC_CONTAINER_CODEC_MP4V, "V_MPEG4/ISO/AP" , 0}, |
706 | {VC_CONTAINER_CODEC_DIV3, "V_MPEG4/MS/V3" , 0}, |
707 | {VC_CONTAINER_CODEC_H264, "V_MPEG4/ISO/AVC" , VC_CONTAINER_VARIANT_H264_AVC1}, |
708 | {VC_CONTAINER_CODEC_MJPEG, "V_MJPEG" , 0}, |
709 | {VC_CONTAINER_CODEC_RV10, "V_REAL/RV10" , 0}, |
710 | {VC_CONTAINER_CODEC_RV20, "V_REAL/RV20" , 0}, |
711 | {VC_CONTAINER_CODEC_RV30, "V_REAL/RV30" , 0}, |
712 | {VC_CONTAINER_CODEC_RV40, "V_REAL/RV40" , 0}, |
713 | {VC_CONTAINER_CODEC_THEORA, "V_THEORA" , 0}, |
714 | {VC_CONTAINER_CODEC_DIRAC, "V_DIRAC" , 0}, |
715 | {VC_CONTAINER_CODEC_VP8, "V_VP8" , 0}, |
716 | |
717 | /* Audio */ |
718 | {VC_CONTAINER_CODEC_MPGA, "A_MPEG/L3" , VC_CONTAINER_VARIANT_MPGA_L3}, |
719 | {VC_CONTAINER_CODEC_MPGA, "A_MPEG/L2" , VC_CONTAINER_VARIANT_MPGA_L2}, |
720 | {VC_CONTAINER_CODEC_MPGA, "A_MPEG/L1" , VC_CONTAINER_VARIANT_MPGA_L1}, |
721 | {VC_CONTAINER_CODEC_MP4A, "A_AAC" , 0}, |
722 | {VC_CONTAINER_CODEC_MP4A, "A_AAC/MPEG2/MAIN" , 0}, |
723 | {VC_CONTAINER_CODEC_MP4A, "A_AAC/MPEG2/LC" , 0}, |
724 | {VC_CONTAINER_CODEC_MP4A, "A_AAC/MPEG2/SSR" , 0}, |
725 | {VC_CONTAINER_CODEC_MP4A, "A_AAC/MPEG2/LC/SBR" , 0}, |
726 | {VC_CONTAINER_CODEC_MP4A, "A_AAC/MPEG4/MAIN" , 0}, |
727 | {VC_CONTAINER_CODEC_MP4A, "A_AAC/MPEG4/LC" , 0}, |
728 | {VC_CONTAINER_CODEC_MP4A, "A_AAC/MPEG4/SSR" , 0}, |
729 | {VC_CONTAINER_CODEC_MP4A, "A_AAC/MPEG4/LC/SBR" , 0}, |
730 | {VC_CONTAINER_CODEC_AC3, "A_AC3" , 0}, |
731 | {VC_CONTAINER_CODEC_EAC3, "A_EAC3" , 0}, |
732 | {VC_CONTAINER_CODEC_DTS, "A_DTS" , 0}, |
733 | {VC_CONTAINER_CODEC_MLP, "A_MLP" , 0}, |
734 | {0, "A_TRUEHD" , 0}, |
735 | {VC_CONTAINER_CODEC_VORBIS, "A_VORBIS" , 0}, |
736 | {VC_CONTAINER_CODEC_FLAC, "A_FLAC" , 0}, |
737 | {VC_CONTAINER_CODEC_PCM_SIGNED_LE, "A_PCM/INT/LIT" , 0}, |
738 | {VC_CONTAINER_CODEC_PCM_SIGNED_BE, "A_PCM/INT/BIG" , 0}, |
739 | {VC_CONTAINER_CODEC_PCM_FLOAT_LE, "A_PCM/FLOAT/IEEE" , 0}, |
740 | {0, "A_REAL/xyzt" , 0}, |
741 | {0, "A_REAL/14_4" , 0}, |
742 | |
743 | /* Text */ |
744 | {VC_CONTAINER_CODEC_TEXT, "S_TEXT/ASCII" , 0}, |
745 | {VC_CONTAINER_CODEC_TEXT, "S_TEXT/UTF8" , 0}, |
746 | {VC_CONTAINER_CODEC_SSA, "S_TEXT/ASS" , 0}, |
747 | {VC_CONTAINER_CODEC_SSA, "S_TEXT/SSA" , 0}, |
748 | {VC_CONTAINER_CODEC_SSA, "S_ASS" , 0}, |
749 | {VC_CONTAINER_CODEC_SSA, "S_SSA" , 0}, |
750 | {VC_CONTAINER_CODEC_USF, "S_TEXT/USF" , 0}, |
751 | {VC_CONTAINER_CODEC_VOBSUB, "S_VOBSUB" , 0}, |
752 | |
753 | {0, 0} |
754 | }; |
755 | |
756 | /****************************************************************************** |
757 | Local Functions |
758 | ******************************************************************************/ |
759 | |
760 | static VC_CONTAINER_FOURCC_T mkv_codecid_to_fourcc(const char *codecid, |
761 | VC_CONTAINER_FOURCC_T *variant) |
762 | { |
763 | unsigned int i; |
764 | for(i = 0; codecid_to_fourcc_table[i].codecid; i++) |
765 | if(!strcmp(codecid_to_fourcc_table[i].codecid, codecid)) break; |
766 | if (variant) *variant = codecid_to_fourcc_table[i].variant; |
767 | return codecid_to_fourcc_table[i].fourcc; |
768 | } |
769 | |
770 | #if 0 |
771 | /** Find the track associated with an MKV track number */ |
772 | static VC_CONTAINER_TRACK_T *mkv_reader_find_track( VC_CONTAINER_T *p_ctx, unsigned int mkv_track_num) |
773 | { |
774 | VC_CONTAINER_TRACK_T *p_track = 0; |
775 | unsigned int i; |
776 | |
777 | for(i = 0; i < p_ctx->tracks_num; i++) |
778 | if(p_ctx->tracks[i]->priv->module->number == mkv_track_num) break; |
779 | |
780 | if(i < p_ctx->tracks_num) /* We found it */ |
781 | p_track = p_ctx->tracks[i]; |
782 | |
783 | return p_track; |
784 | } |
785 | #endif |
786 | |
787 | /** Base function used to read an MKV/EBML element header. |
788 | * This will read the element header do lots of sanity checking and return the element id |
789 | * and the size of the data contained in the element */ |
790 | static VC_CONTAINER_STATUS_T (VC_CONTAINER_T *p_ctx, int64_t size, |
791 | MKV_ELEMENT_ID_T *id, int64_t *element_size, MKV_ELEMENT_ID_T parent_id, |
792 | MKV_ELEMENT_T **elem) |
793 | { |
794 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
795 | MKV_ELEMENT_T *element; |
796 | |
797 | module->element_offset = STREAM_POSITION(p_ctx); |
798 | |
799 | *id = MKV_READ_ID(p_ctx, "Element ID" ); |
800 | CHECK_POINT(p_ctx); |
801 | if(!*id) |
802 | { |
803 | LOG_DEBUG(p_ctx, "invalid element id %i" , *id); |
804 | return VC_CONTAINER_ERROR_CORRUPTED; |
805 | } |
806 | |
807 | if(elem) element = *elem; |
808 | else element = mkv_elements_list; |
809 | |
810 | /* Find out which Element we are dealing with */ |
811 | while(element->id && *id != element->id) element++; |
812 | |
813 | *element_size = MKV_READ_UINT(p_ctx, "Element Size" ); |
814 | CHECK_POINT(p_ctx); |
815 | LOG_FORMAT(p_ctx, "- Element %s (ID 0x%x), Size: %" PRIi64", Offset: %" PRIi64, |
816 | element->psz_name, *id, *element_size, module->element_offset); |
817 | |
818 | /* Sanity check the element size */ |
819 | if(*element_size + 1 < 0 /* Shouldn't ever get that big */ || |
820 | /* Only the segment / cluster elements can really be massive */ |
821 | (*id != MKV_ELEMENT_ID_SEGMENT && *id != MKV_ELEMENT_ID_CLUSTER && |
822 | *element_size > MKV_MAX_ELEMENT_SIZE)) |
823 | { |
824 | LOG_DEBUG(p_ctx, "element %s has an invalid size (%" PRIi64")" , |
825 | element->psz_name, *element_size); |
826 | return VC_CONTAINER_ERROR_CORRUPTED; |
827 | } |
828 | if(size >= 0 && *element_size > size) |
829 | { |
830 | LOG_DEBUG(p_ctx, "element %s is bigger than it should (%" PRIi64" > %" PRIi64")" , |
831 | element->psz_name, *element_size, size); |
832 | return VC_CONTAINER_ERROR_CORRUPTED; |
833 | } |
834 | |
835 | /* Sanity check that the element has the right parent */ |
836 | if(element->id && element->parent_id != MKV_ELEMENT_ID_INVALID && |
837 | parent_id != MKV_ELEMENT_ID_INVALID && parent_id != element->parent_id) |
838 | { |
839 | LOG_FORMAT(p_ctx, "Ignoring mis-placed element %s (ID 0x%x)" , element->psz_name, *id); |
840 | while(element->id != MKV_ELEMENT_ID_UNKNOWN) element++; |
841 | } |
842 | |
843 | /* Sanity check that the element isn't too deeply nested */ |
844 | if(module->element_level >= MKV_MAX_ELEMENT_LEVEL) |
845 | { |
846 | LOG_DEBUG(p_ctx, "element %s is too deep. skipping" , element->psz_name); |
847 | while(element->id != MKV_ELEMENT_ID_UNKNOWN) element++; |
848 | } |
849 | |
850 | if(elem) *elem = element; |
851 | return STREAM_STATUS(p_ctx); |
852 | } |
853 | |
854 | static VC_CONTAINER_STATUS_T mkv_read_element_data(VC_CONTAINER_T *p_ctx, |
855 | MKV_ELEMENT_T *element, int64_t element_size, int64_t size) |
856 | { |
857 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
858 | int64_t offset; |
859 | |
860 | offset = STREAM_POSITION(p_ctx); |
861 | if (size < 0) size = element_size; |
862 | if (size < 0) size = INT64_C(1) << 62; |
863 | |
864 | /* Call the element specific parsing function */ |
865 | if(element->pf_func) |
866 | status = element->pf_func(p_ctx, element->id, element_size < 0 ? size : element_size); |
867 | |
868 | if(status != VC_CONTAINER_SUCCESS) |
869 | LOG_DEBUG(p_ctx, "element %s appears to be corrupted (%i)" , element->psz_name, status); |
870 | |
871 | if(element_size < 0) return STREAM_STATUS(p_ctx); /* Unknown size */ |
872 | |
873 | /* Skip the rest of the element */ |
874 | element_size -= (STREAM_POSITION(p_ctx) - offset); |
875 | if(element_size < 0) /* Check for overruns */ |
876 | { |
877 | /* Things have gone really bad here and we ended up reading past the end of the |
878 | * element. We could maybe try to be clever and recover by seeking back to the end |
879 | * of the element. However if we get there, the file is clearly corrupted so there's |
880 | * no guarantee it would work anyway. */ |
881 | LOG_DEBUG(p_ctx, "%" PRIi64" bytes overrun past the end of element %s" , |
882 | -element_size, element->psz_name); |
883 | return VC_CONTAINER_ERROR_CORRUPTED; |
884 | } |
885 | |
886 | if(element_size) |
887 | LOG_FORMAT(p_ctx, "%" PRIi64" bytes left unread in element %s" , element_size, element->psz_name); |
888 | |
889 | if(element_size < MKV_MAX_ELEMENT_SIZE) SKIP_BYTES(p_ctx, element_size); |
890 | else SEEK(p_ctx, STREAM_POSITION(p_ctx) + element_size); |
891 | |
892 | return STREAM_STATUS(p_ctx); |
893 | } |
894 | |
895 | /** Base function used to read an MKV/EBML element. |
896 | * This will read the element header do lots of sanity checking and pass on the rest |
897 | * of the reading to the element specific reading function */ |
898 | static VC_CONTAINER_STATUS_T mkv_read_element(VC_CONTAINER_T *p_ctx, |
899 | int64_t size, MKV_ELEMENT_ID_T parent_id) |
900 | { |
901 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
902 | MKV_ELEMENT_T *element = p_ctx->priv->module->elements_list; |
903 | int64_t element_size; |
904 | MKV_ELEMENT_ID_T id; |
905 | |
906 | status = mkv_read_element_header(p_ctx, size, &id, &element_size, parent_id, &element); |
907 | if(status != VC_CONTAINER_SUCCESS) return status; |
908 | return mkv_read_element_data(p_ctx, element, element_size, size); |
909 | } |
910 | |
911 | /** Reads an unsigned integer element */ |
912 | static VC_CONTAINER_STATUS_T mkv_read_element_data_uint(VC_CONTAINER_T *p_ctx, |
913 | int64_t size, uint64_t *value) |
914 | { |
915 | switch(size) |
916 | { |
917 | case 1: *value = READ_U8(p_ctx, "u8-integer" ); break; |
918 | case 2: *value = READ_U16(p_ctx, "u16-integer" ); break; |
919 | case 3: *value = READ_U24(p_ctx, "u24-integer" ); break; |
920 | case 4: *value = READ_U32(p_ctx, "u32-integer" ); break; |
921 | case 5: *value = READ_U40(p_ctx, "u40-integer" ); break; |
922 | case 6: *value = READ_U48(p_ctx, "u48-integer" ); break; |
923 | case 7: *value = READ_U56(p_ctx, "u56-integer" ); break; |
924 | case 8: *value = READ_U64(p_ctx, "u64-integer" ); break; |
925 | default: return VC_CONTAINER_ERROR_CORRUPTED; |
926 | } |
927 | return STREAM_STATUS(p_ctx); |
928 | } |
929 | |
930 | /** Reads a float element */ |
931 | static VC_CONTAINER_STATUS_T mkv_read_element_data_float(VC_CONTAINER_T *p_ctx, |
932 | int64_t size, double *value) |
933 | { |
934 | union { |
935 | uint32_t u32; |
936 | uint64_t u64; |
937 | float f; |
938 | double d; |
939 | } u; |
940 | |
941 | switch(size) |
942 | { |
943 | case 4: u.u32 = READ_U32(p_ctx, "f32-float" ); *value = u.f; break; |
944 | case 8: u.u64 = READ_U64(p_ctx, "f64-float" ); *value = u.d; break; |
945 | default: return VC_CONTAINER_ERROR_CORRUPTED; |
946 | } |
947 | LOG_FORMAT(p_ctx, "float: %f" , *value); |
948 | return STREAM_STATUS(p_ctx); |
949 | } |
950 | |
951 | /** Reads an MKV EBML element */ |
952 | static VC_CONTAINER_STATUS_T mkv_read_element_ebml(VC_CONTAINER_T *p_ctx, |
953 | MKV_ELEMENT_ID_T id, int64_t size) |
954 | { |
955 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
956 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
957 | int64_t offset = STREAM_POSITION(p_ctx); |
958 | |
959 | /* Read contained elements */ |
960 | module->element_level++; |
961 | while(status == VC_CONTAINER_SUCCESS && size >= MKV_ELEMENT_MIN_HEADER_SIZE) |
962 | { |
963 | offset = STREAM_POSITION(p_ctx); |
964 | status = mkv_read_element(p_ctx, size, id); |
965 | size -= (STREAM_POSITION(p_ctx) - offset); |
966 | } |
967 | module->element_level--; |
968 | return status; |
969 | } |
970 | |
971 | /** Reads the MKV EBML sub-element */ |
972 | static VC_CONTAINER_STATUS_T mkv_read_subelements_ebml( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ) |
973 | { |
974 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
975 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
976 | uint64_t value; |
977 | |
978 | /* Deal with DocType first since it's a special case */ |
979 | if(id == MKV_ELEMENT_ID_DOCTYPE) |
980 | { |
981 | char doctype[] = "matroska doctype" ; |
982 | |
983 | /* Check we've got the right doctype string for matroska */ |
984 | if(size <= 0) goto unknown_doctype; |
985 | if(size > (int)sizeof(doctype)) goto unknown_doctype; |
986 | if((int)READ_STRING(p_ctx, doctype, size, "string" ) != size) return STREAM_STATUS(p_ctx); |
987 | if((size != sizeof("matroska" )-1 || strncmp(doctype, "matroska" , (int)size)) && |
988 | (size != sizeof("webm" )-1 || strncmp(doctype, "webm" , (int)size))) |
989 | goto unknown_doctype; |
990 | |
991 | module->is_doctype_valid = true; |
992 | return VC_CONTAINER_SUCCESS; |
993 | |
994 | unknown_doctype: |
995 | LOG_DEBUG(p_ctx, "invalid doctype" ); |
996 | return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED; |
997 | } |
998 | |
999 | /* The rest are just unsigned integers */ |
1000 | status = mkv_read_element_data_uint(p_ctx, size, &value); |
1001 | if(status != VC_CONTAINER_SUCCESS) return status; |
1002 | |
1003 | switch(id) |
1004 | { |
1005 | case MKV_ELEMENT_ID_EBML_VERSION: |
1006 | case MKV_ELEMENT_ID_EBML_READ_VERSION: |
1007 | if(value != 1) return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED; |
1008 | break; |
1009 | case MKV_ELEMENT_ID_EBML_MAX_ID_LENGTH: |
1010 | if(value > 4) return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED; |
1011 | break; |
1012 | case MKV_ELEMENT_ID_EBML_MAX_SIZE_LENGTH: |
1013 | if(value > 8) return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED; |
1014 | break; |
1015 | case MKV_ELEMENT_ID_DOCTYPE_VERSION: |
1016 | case MKV_ELEMENT_ID_DOCTYPE_READ_VERSION: |
1017 | default: break; |
1018 | } |
1019 | |
1020 | return STREAM_STATUS(p_ctx); |
1021 | } |
1022 | |
1023 | static VC_CONTAINER_STATUS_T mkv_read_elements( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ) |
1024 | { |
1025 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
1026 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
1027 | int64_t offset = STREAM_POSITION(p_ctx); |
1028 | bool unknown_size = size < 0; |
1029 | |
1030 | /* Read contained elements */ |
1031 | module->element_level++; |
1032 | while(status == VC_CONTAINER_SUCCESS && |
1033 | (unknown_size || size >= MKV_ELEMENT_MIN_HEADER_SIZE)) |
1034 | { |
1035 | offset = STREAM_POSITION(p_ctx); |
1036 | status = mkv_read_element(p_ctx, size, id); |
1037 | if(!unknown_size) size -= (STREAM_POSITION(p_ctx) - offset); |
1038 | } |
1039 | module->element_level--; |
1040 | return status; |
1041 | } |
1042 | |
1043 | static VC_CONTAINER_STATUS_T mkv_read_element_segment( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ) |
1044 | { |
1045 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
1046 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
1047 | int64_t offset = STREAM_POSITION(p_ctx); |
1048 | bool unknown_size = size < 0; |
1049 | |
1050 | /* Read contained elements */ |
1051 | /* Initialise state used by reader */ |
1052 | module->state.level = 0; |
1053 | module->state.levels[0].offset = STREAM_POSITION(p_ctx); |
1054 | module->state.levels[0].size = size; |
1055 | module->state.levels[0].id = MKV_ELEMENT_ID_SEGMENT; |
1056 | module->state.levels[0].data_start = 0; |
1057 | module->state.levels[0].data_offset = 0; |
1058 | module->timecode_scale = 1000000; |
1059 | module->duration = 0.0; |
1060 | module->segment_offset = STREAM_POSITION(p_ctx); |
1061 | module->segment_size = size; |
1062 | |
1063 | /* Read contained elements until we have all the information we need to start |
1064 | * playing the stream */ |
1065 | module->element_level++; |
1066 | while(status == VC_CONTAINER_SUCCESS && |
1067 | (unknown_size || size >= MKV_ELEMENT_MIN_HEADER_SIZE)) |
1068 | { |
1069 | MKV_ELEMENT_T *child = mkv_elements_list; |
1070 | MKV_ELEMENT_ID_T child_id; |
1071 | int64_t child_size; |
1072 | |
1073 | offset = STREAM_POSITION(p_ctx); |
1074 | |
1075 | status = mkv_read_element_header(p_ctx, size, &child_id, &child_size, id, &child); |
1076 | if(status != VC_CONTAINER_SUCCESS) break; |
1077 | |
1078 | if(child_id == MKV_ELEMENT_ID_CLUSTER) |
1079 | { |
1080 | /* We found the start of the data */ |
1081 | module->cluster_offset = module->element_offset; |
1082 | module->state.level = 1; |
1083 | module->state.levels[1].offset = STREAM_POSITION(p_ctx); |
1084 | module->state.levels[1].size = child_size; |
1085 | module->state.levels[1].id = MKV_ELEMENT_ID_CLUSTER; |
1086 | module->state.levels[1].data_start = 0; |
1087 | module->state.levels[1].data_offset = 0; |
1088 | break; |
1089 | } |
1090 | |
1091 | status = mkv_read_element_data(p_ctx, child, child_size, size); |
1092 | if(!unknown_size) size -= (STREAM_POSITION(p_ctx) - offset); |
1093 | } |
1094 | |
1095 | module->element_level--; |
1096 | return status; |
1097 | } |
1098 | |
1099 | static VC_CONTAINER_STATUS_T mkv_read_element_track_entry( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ) |
1100 | { |
1101 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
1102 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
1103 | VC_CONTAINER_ES_TYPE_T es_type = VC_CONTAINER_ES_TYPE_UNKNOWN; |
1104 | VC_CONTAINER_TRACK_MODULE_T *track_module; |
1105 | VC_CONTAINER_TRACK_T *track; |
1106 | VC_CONTAINER_FOURCC_T fourcc = 0, variant = 0; |
1107 | unsigned int i, = 0, = 0, is_wf = 0, is_bmih = 0; |
1108 | |
1109 | /* Allocate and initialise track data */ |
1110 | if(p_ctx->tracks_num >= MKV_TRACKS_MAX) return VC_CONTAINER_ERROR_OUT_OF_RESOURCES; |
1111 | p_ctx->tracks[p_ctx->tracks_num] = track = |
1112 | vc_container_allocate_track(p_ctx, sizeof(*p_ctx->tracks[0]->priv->module)); |
1113 | if(!track) return VC_CONTAINER_ERROR_OUT_OF_MEMORY; |
1114 | |
1115 | module->parsing = track; |
1116 | track_module = track->priv->module; |
1117 | track->is_enabled = true; |
1118 | track->format->flags |= VC_CONTAINER_ES_FORMAT_FLAG_FRAMED; |
1119 | track_module->timecode_scale = 1.0; |
1120 | track_module->es_type.video.frame_rate = 0; |
1121 | |
1122 | status = mkv_read_elements( p_ctx, id, size ); |
1123 | if(status != VC_CONTAINER_SUCCESS) goto error; |
1124 | |
1125 | /* Sanity check the data we got from the track entry */ |
1126 | if(!track_module->number || !track_module->type) |
1127 | { status = VC_CONTAINER_ERROR_FORMAT_INVALID; goto error; } |
1128 | |
1129 | /* Check the encodings for the track are supported */ |
1130 | if(track_module->encodings_num > MKV_MAX_ENCODINGS) |
1131 | { status = VC_CONTAINER_ERROR_TRACK_FORMAT_NOT_SUPPORTED; goto error; } |
1132 | for(i = 0; i < track_module->encodings_num; i++) |
1133 | { |
1134 | if(track_module->encodings[i].type != MKV_CONTENT_ENCODING_COMPRESSION_HEADER || |
1135 | !track_module->encodings[i].data_size) |
1136 | { status = VC_CONTAINER_ERROR_TRACK_FORMAT_NOT_SUPPORTED; goto error; } |
1137 | } |
1138 | |
1139 | /* Find out the track type */ |
1140 | if(track_module->type == 0x1) |
1141 | es_type = VC_CONTAINER_ES_TYPE_VIDEO; |
1142 | else if(track_module->type == 0x2) |
1143 | es_type = VC_CONTAINER_ES_TYPE_AUDIO; |
1144 | else if(track_module->type == 0x11) |
1145 | es_type = VC_CONTAINER_ES_TYPE_SUBPICTURE; |
1146 | |
1147 | if(es_type == VC_CONTAINER_ES_TYPE_UNKNOWN) |
1148 | { status = VC_CONTAINER_ERROR_TRACK_FORMAT_NOT_SUPPORTED; goto error; } |
1149 | |
1150 | if(!strcmp(track_module->codecid, "V_MS/VFW/FOURCC" )) |
1151 | { |
1152 | if(vc_container_bitmapinfoheader_to_es_format(track->format->extradata, |
1153 | track->format->extradata_size, &extra_offset, &extra_size, |
1154 | track->format) == VC_CONTAINER_SUCCESS) |
1155 | { |
1156 | fourcc = track->format->codec; |
1157 | is_bmih = 1; |
1158 | } |
1159 | track->format->extradata += extra_offset; |
1160 | track->format->extradata_size = extra_size; |
1161 | } |
1162 | else if(!strcmp(track_module->codecid, "A_MS/ACM" )) |
1163 | { |
1164 | if(vc_container_waveformatex_to_es_format(track->format->extradata, |
1165 | track->format->extradata_size, &extra_offset, &extra_size, |
1166 | track->format) == VC_CONTAINER_SUCCESS) |
1167 | { |
1168 | fourcc = track->format->codec; |
1169 | is_wf = 1; |
1170 | } |
1171 | track->format->extradata += extra_offset; |
1172 | track->format->extradata_size = extra_size; |
1173 | } |
1174 | else if((!strncmp(track_module->codecid, "A_AAC/MPEG2/" , sizeof("A_AAC/MPEG2/" )-1) || |
1175 | !strncmp(track_module->codecid, "A_AAC/MPEG4/" , sizeof("A_AAC/MPEG4/" )-1)) && |
1176 | !track->format->extradata_size) |
1177 | { |
1178 | static const unsigned int sample_rates[16] = |
1179 | {96000, 88200, 64000, 48000, 44100, 32000, 24000, 22050, 16000, 12000, 11025, 8000, 7350}; |
1180 | unsigned int samplerate, samplerate_idx, profile, sbr = 0; |
1181 | uint8_t *; |
1182 | |
1183 | fourcc = mkv_codecid_to_fourcc(track_module->codecid, &variant); |
1184 | |
1185 | /* Create extra data */ |
1186 | if( !strcmp( &track_module->codecid[12], "MAIN" ) ) profile = 0; |
1187 | else if( !strcmp( &track_module->codecid[12], "LC" ) ) profile = 1; |
1188 | else if( !strcmp( &track_module->codecid[12], "SSR" ) ) profile = 2; |
1189 | else if( !strcmp( &track_module->codecid[12], "LC/SBR" ) ) { profile = 1; sbr = 1; } |
1190 | else profile = 3; |
1191 | |
1192 | samplerate = track_module->es_type.audio.sampling_frequency; |
1193 | for( samplerate_idx = 0; samplerate_idx < 13; samplerate_idx++ ) |
1194 | if( sample_rates[samplerate_idx] == samplerate ) break; |
1195 | |
1196 | status = vc_container_track_allocate_extradata(p_ctx, track, sbr ? 5 : 2); |
1197 | if(status != VC_CONTAINER_SUCCESS) goto error; |
1198 | track->format->extradata_size = sbr ? 5 : 2; |
1199 | extra = track->format->extradata; |
1200 | |
1201 | extra[0] = ((profile + 1) << 3) | ((samplerate_idx & 0xe) >> 1); |
1202 | extra[1] = ((samplerate_idx & 0x1) << 7) | (track_module->es_type.audio.channels << 3); |
1203 | |
1204 | if(sbr) |
1205 | { |
1206 | unsigned int sync_extension_type = 0x2B7; |
1207 | samplerate = track_module->es_type.audio.output_sampling_frequency; |
1208 | for(samplerate_idx = 0; samplerate_idx < 13; samplerate_idx++) |
1209 | if(sample_rates[samplerate_idx] == samplerate) break; |
1210 | extra[2] = (sync_extension_type >> 3) & 0xFF; |
1211 | extra[3] = ((sync_extension_type & 0x7) << 5) | 5; |
1212 | extra[4] = (1 << 7) | (samplerate_idx << 3); |
1213 | } |
1214 | } |
1215 | else fourcc = mkv_codecid_to_fourcc(track_module->codecid, &variant); |
1216 | |
1217 | if(!fourcc) |
1218 | { |
1219 | LOG_DEBUG(p_ctx, "codec id %s is not supported" , track_module->codecid); |
1220 | } |
1221 | |
1222 | LOG_DEBUG(p_ctx, "found track %4.4s" , (char *)&fourcc); |
1223 | track->format->codec = fourcc; |
1224 | track->format->codec_variant = variant; |
1225 | track->format->es_type = es_type; |
1226 | |
1227 | switch(es_type) |
1228 | { |
1229 | case VC_CONTAINER_ES_TYPE_VIDEO: |
1230 | if(!is_bmih) |
1231 | { |
1232 | track->format->type->video.width = track_module->es_type.video.pixel_width; |
1233 | track->format->type->video.height = track_module->es_type.video.pixel_height; |
1234 | } |
1235 | track->format->type->video.visible_width = track->format->type->video.width; |
1236 | track->format->type->video.visible_height = track->format->type->video.height; |
1237 | if(track_module->es_type.video.pixel_crop_left < track->format->type->video.visible_width && |
1238 | track_module->es_type.video.pixel_crop_top < track->format->type->video.visible_height) |
1239 | { |
1240 | track->format->type->video.x_offset = track_module->es_type.video.pixel_crop_left; |
1241 | track->format->type->video.y_offset = track_module->es_type.video.pixel_crop_right; |
1242 | track->format->type->video.visible_width -= track->format->type->video.x_offset; |
1243 | track->format->type->video.visible_height -= track->format->type->video.y_offset; |
1244 | } |
1245 | if(track_module->es_type.video.pixel_crop_right < track->format->type->video.visible_width && |
1246 | track_module->es_type.video.pixel_crop_bottom < track->format->type->video.visible_height) |
1247 | { |
1248 | track->format->type->video.visible_width -= track_module->es_type.video.pixel_crop_right; |
1249 | track->format->type->video.visible_height -= track_module->es_type.video.pixel_crop_bottom; |
1250 | } |
1251 | if(track_module->es_type.video.frame_rate) |
1252 | { |
1253 | track->format->type->video.frame_rate_den = 100; |
1254 | track->format->type->video.frame_rate_num = 100 * track_module->es_type.video.frame_rate; |
1255 | } |
1256 | if(track_module->es_type.video.display_width && track_module->es_type.video.display_height) |
1257 | { |
1258 | track->format->type->video.par_num = track_module->es_type.video.display_width * |
1259 | track->format->type->video.visible_height; |
1260 | track->format->type->video.par_den = track_module->es_type.video.display_height * |
1261 | track->format->type->video.visible_width; |
1262 | vc_container_maths_rational_simplify(&track->format->type->video.par_num, |
1263 | &track->format->type->video.par_den); |
1264 | } |
1265 | break; |
1266 | case VC_CONTAINER_ES_TYPE_AUDIO: |
1267 | if(is_wf) break; |
1268 | track->format->type->audio.sample_rate = track_module->es_type.audio.sampling_frequency; |
1269 | if(track_module->es_type.audio.output_sampling_frequency) |
1270 | track->format->type->audio.sample_rate = track_module->es_type.audio.output_sampling_frequency; |
1271 | track->format->type->audio.channels = track_module->es_type.audio.channels; |
1272 | track->format->type->audio.bits_per_sample = track_module->es_type.audio.bit_depth; |
1273 | break; |
1274 | default: |
1275 | case VC_CONTAINER_ES_TYPE_SUBPICTURE: |
1276 | track->format->type->subpicture.encoding = VC_CONTAINER_CHAR_ENCODING_UTF8; |
1277 | if(!strcmp(track_module->codecid, "S_TEXT/ASCII" )) |
1278 | track->format->type->subpicture.encoding = VC_CONTAINER_CHAR_ENCODING_UNKNOWN; |
1279 | } |
1280 | |
1281 | track->is_enabled = true; |
1282 | |
1283 | p_ctx->tracks_num++; |
1284 | return VC_CONTAINER_SUCCESS; |
1285 | |
1286 | error: |
1287 | for(i = 0; i < MKV_MAX_ENCODINGS; i++) free(track_module->encodings[i].data); |
1288 | vc_container_free_track(p_ctx, track); |
1289 | return status; |
1290 | } |
1291 | |
1292 | static VC_CONTAINER_STATUS_T mkv_read_subelements_track_entry( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ) |
1293 | { |
1294 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
1295 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
1296 | VC_CONTAINER_TRACK_T *track = module->parsing; |
1297 | VC_CONTAINER_TRACK_MODULE_T *track_module = track->priv->module; |
1298 | uint64_t value; |
1299 | |
1300 | /* Deal with string elements */ |
1301 | if( id == MKV_ELEMENT_ID_NAME || |
1302 | id == MKV_ELEMENT_ID_LANGUAGE || |
1303 | id == MKV_ELEMENT_ID_TRACK_CODEC_ID || |
1304 | id == MKV_ELEMENT_ID_TRACK_CODEC_NAME ) |
1305 | { |
1306 | char stringbuf[MKV_MAX_STRING_SIZE+1]; |
1307 | |
1308 | if(size > MKV_MAX_STRING_SIZE) |
1309 | { |
1310 | LOG_DEBUG(p_ctx, "string truncated (%i>%i)" , (int)size, MKV_MAX_STRING_SIZE); |
1311 | size = MKV_MAX_STRING_SIZE; |
1312 | } |
1313 | if(READ_BYTES(p_ctx, stringbuf, size) != (size_t)size) |
1314 | { |
1315 | //XXX do sane thing |
1316 | return STREAM_STATUS(p_ctx); |
1317 | } |
1318 | stringbuf[size] = 0; /* null terminate */ |
1319 | |
1320 | LOG_FORMAT(p_ctx, "%s" , stringbuf); |
1321 | |
1322 | if(id == MKV_ELEMENT_ID_TRACK_CODEC_ID) |
1323 | strncpy(track_module->codecid, stringbuf, MKV_CODECID_MAX-1); |
1324 | |
1325 | return VC_CONTAINER_SUCCESS; |
1326 | } |
1327 | |
1328 | /* Deal with codec private data */ |
1329 | if( id == MKV_ELEMENT_ID_TRACK_CODEC_PRIVATE ) |
1330 | { |
1331 | status = vc_container_track_allocate_extradata(p_ctx, track, (unsigned int)size); |
1332 | if(status != VC_CONTAINER_SUCCESS) return status; |
1333 | track->format->extradata_size = READ_BYTES(p_ctx, track->format->extradata, size); |
1334 | return STREAM_STATUS(p_ctx); |
1335 | } |
1336 | |
1337 | /* The rest are just unsigned integers */ |
1338 | status = mkv_read_element_data_uint(p_ctx, size, &value); |
1339 | if(status != VC_CONTAINER_SUCCESS) return status; |
1340 | |
1341 | switch(id) |
1342 | { |
1343 | case MKV_ELEMENT_ID_TRACK_NUMBER: |
1344 | track_module->number = value; break; |
1345 | case MKV_ELEMENT_ID_TRACK_TYPE: |
1346 | track_module->type = value; break; |
1347 | case MKV_ELEMENT_ID_DEFAULT_DURATION: |
1348 | track_module->frame_duration = value; break; |
1349 | default: break; |
1350 | } |
1351 | |
1352 | return status; |
1353 | } |
1354 | |
1355 | static VC_CONTAINER_STATUS_T mkv_read_subelements_video( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ) |
1356 | { |
1357 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
1358 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
1359 | VC_CONTAINER_TRACK_MODULE_T *track_module = module->parsing->priv->module; |
1360 | uint64_t value; |
1361 | |
1362 | /* Deal with floating point values first */ |
1363 | if(id == MKV_ELEMENT_ID_FRAME_RATE) |
1364 | { |
1365 | double fvalue; |
1366 | status = mkv_read_element_data_float(p_ctx, size, &fvalue); |
1367 | if(status != VC_CONTAINER_SUCCESS) return status; |
1368 | track_module->es_type.video.frame_rate = fvalue; |
1369 | return status; |
1370 | } |
1371 | |
1372 | /* The rest are just unsigned integers */ |
1373 | status = mkv_read_element_data_uint(p_ctx, size, &value); |
1374 | if(status != VC_CONTAINER_SUCCESS) return status; |
1375 | |
1376 | switch(id) |
1377 | { |
1378 | case MKV_ELEMENT_ID_PIXEL_WIDTH: track_module->es_type.video.pixel_width = value; break; |
1379 | case MKV_ELEMENT_ID_PIXEL_HEIGHT: track_module->es_type.video.pixel_height = value; break; |
1380 | case MKV_ELEMENT_ID_PIXEL_CROP_BOTTOM: track_module->es_type.video.pixel_crop_bottom = value; break; |
1381 | case MKV_ELEMENT_ID_PIXEL_CROP_TOP: track_module->es_type.video.pixel_crop_top = value; break; |
1382 | case MKV_ELEMENT_ID_PIXEL_CROP_LEFT: track_module->es_type.video.pixel_crop_left = value; break; |
1383 | case MKV_ELEMENT_ID_PIXEL_CROP_RIGHT: track_module->es_type.video.pixel_crop_right = value; break; |
1384 | case MKV_ELEMENT_ID_DISPLAY_WIDTH: track_module->es_type.video.display_width = value; break; |
1385 | case MKV_ELEMENT_ID_DISPLAY_HEIGHT: track_module->es_type.video.display_height = value; break; |
1386 | case MKV_ELEMENT_ID_DISPLAY_UNIT: track_module->es_type.video.display_unit = value; break; |
1387 | case MKV_ELEMENT_ID_ASPECT_RATIO_TYPE: track_module->es_type.video.aspect_ratio_type = value; break; |
1388 | default: break; |
1389 | } |
1390 | |
1391 | return status; |
1392 | } |
1393 | |
1394 | static VC_CONTAINER_STATUS_T mkv_read_subelements_audio( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ) |
1395 | { |
1396 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
1397 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
1398 | VC_CONTAINER_TRACK_MODULE_T *track_module = module->parsing->priv->module; |
1399 | uint64_t value; |
1400 | |
1401 | /* Deal with floating point values first */ |
1402 | if(id == MKV_ELEMENT_ID_SAMPLING_FREQUENCY || |
1403 | id == MKV_ELEMENT_ID_OUTPUT_SAMPLING_FREQUENCY) |
1404 | { |
1405 | double fvalue; |
1406 | status = mkv_read_element_data_float(p_ctx, size, &fvalue); |
1407 | if(status != VC_CONTAINER_SUCCESS) return status; |
1408 | |
1409 | if(id == MKV_ELEMENT_ID_SAMPLING_FREQUENCY) |
1410 | track_module->es_type.audio.sampling_frequency = fvalue; |
1411 | |
1412 | if(id == MKV_ELEMENT_ID_OUTPUT_SAMPLING_FREQUENCY) |
1413 | track_module->es_type.audio.output_sampling_frequency = fvalue; |
1414 | |
1415 | return status; |
1416 | } |
1417 | |
1418 | /* The rest are just unsigned integers */ |
1419 | status = mkv_read_element_data_uint(p_ctx, size, &value); |
1420 | if(status != VC_CONTAINER_SUCCESS) return status; |
1421 | |
1422 | switch(id) |
1423 | { |
1424 | case MKV_ELEMENT_ID_CHANNELS: track_module->es_type.audio.channels = value; break; |
1425 | case MKV_ELEMENT_ID_BIT_DEPTH: track_module->es_type.audio.bit_depth = value; break; |
1426 | default: break; |
1427 | } |
1428 | |
1429 | return status; |
1430 | } |
1431 | |
1432 | static VC_CONTAINER_STATUS_T mkv_read_element_encoding( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ) |
1433 | { |
1434 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
1435 | VC_CONTAINER_TRACK_MODULE_T *track_module = module->parsing->priv->module; |
1436 | VC_CONTAINER_STATUS_T status; |
1437 | status = mkv_read_elements(p_ctx, id, size); |
1438 | track_module->encodings_num++; |
1439 | return status; |
1440 | } |
1441 | |
1442 | static VC_CONTAINER_STATUS_T mkv_read_subelements_encoding( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ) |
1443 | { |
1444 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
1445 | VC_CONTAINER_TRACK_MODULE_T *track_module = module->parsing->priv->module; |
1446 | VC_CONTAINER_STATUS_T status; |
1447 | uint64_t value; |
1448 | |
1449 | /* These are just unsigned integers */ |
1450 | status = mkv_read_element_data_uint(p_ctx, size, &value); |
1451 | if(status != VC_CONTAINER_SUCCESS) return status; |
1452 | |
1453 | if(track_module->encodings_num >= MKV_MAX_ENCODINGS) return VC_CONTAINER_ERROR_OUT_OF_RESOURCES; |
1454 | |
1455 | switch(id) |
1456 | { |
1457 | case MKV_ELEMENT_ID_CONTENT_ENCODING_TYPE: |
1458 | if(value == 0) track_module->encodings[track_module->encodings_num].type = MKV_CONTENT_ENCODING_COMPRESSION_ZLIB; |
1459 | if(value == 1) track_module->encodings[track_module->encodings_num].type = MKV_CONTENT_ENCODING_ENCRYPTION; |
1460 | else track_module->encodings[track_module->encodings_num].type = MKV_CONTENT_ENCODING_UNKNOWN; |
1461 | break; |
1462 | default: break; |
1463 | } |
1464 | |
1465 | return status; |
1466 | } |
1467 | |
1468 | static VC_CONTAINER_STATUS_T mkv_read_subelements_compression( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ) |
1469 | { |
1470 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
1471 | VC_CONTAINER_TRACK_MODULE_T *track_module = module->parsing->priv->module; |
1472 | VC_CONTAINER_STATUS_T status; |
1473 | uint64_t value; |
1474 | uint8_t *data; |
1475 | |
1476 | if(id == MKV_ELEMENT_ID_CONTENT_COMPRESSION_ALGO) |
1477 | { |
1478 | status = mkv_read_element_data_uint(p_ctx, size, &value); |
1479 | if(status != VC_CONTAINER_SUCCESS) return status; |
1480 | |
1481 | if(value == 0) track_module->encodings[track_module->encodings_num].type = MKV_CONTENT_ENCODING_COMPRESSION_ZLIB; |
1482 | if(value == 3) track_module->encodings[track_module->encodings_num].type = MKV_CONTENT_ENCODING_COMPRESSION_HEADER; |
1483 | else track_module->encodings[track_module->encodings_num].type = MKV_CONTENT_ENCODING_UNKNOWN; |
1484 | return status; |
1485 | } |
1486 | |
1487 | if(id == MKV_ELEMENT_ID_CONTENT_COMPRESSION_SETTINGS) |
1488 | { |
1489 | if(track_module->encodings[track_module->encodings_num].type == MKV_CONTENT_ENCODING_COMPRESSION_HEADER) |
1490 | { |
1491 | if(size > MKV_MAX_ENCODING_DATA) return VC_CONTAINER_ERROR_OUT_OF_RESOURCES; |
1492 | |
1493 | data = malloc((int)size); |
1494 | if(!data) return VC_CONTAINER_ERROR_OUT_OF_MEMORY; |
1495 | |
1496 | track_module->encodings[track_module->encodings_num].data = data; |
1497 | track_module->encodings[track_module->encodings_num].data_size = READ_BYTES(p_ctx, data, size); |
1498 | if(track_module->encodings[track_module->encodings_num].data_size != size) |
1499 | track_module->encodings[track_module->encodings_num].data_size = 0; |
1500 | return STREAM_STATUS(p_ctx); |
1501 | } |
1502 | else |
1503 | { |
1504 | SKIP_BYTES(p_ctx, size); |
1505 | } |
1506 | return STREAM_STATUS(p_ctx); |
1507 | } |
1508 | |
1509 | return VC_CONTAINER_SUCCESS; |
1510 | } |
1511 | |
1512 | static VC_CONTAINER_STATUS_T mkv_read_subelements_info( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ) |
1513 | { |
1514 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
1515 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
1516 | uint64_t value; |
1517 | double fvalue; |
1518 | |
1519 | switch(id) |
1520 | { |
1521 | case MKV_ELEMENT_ID_TIMECODE_SCALE: |
1522 | status = mkv_read_element_data_uint(p_ctx, size, &value); |
1523 | if(status != VC_CONTAINER_SUCCESS) break; |
1524 | module->timecode_scale = value; |
1525 | break; |
1526 | case MKV_ELEMENT_ID_DURATION: |
1527 | status = mkv_read_element_data_float(p_ctx, size, &fvalue); |
1528 | if(status != VC_CONTAINER_SUCCESS) break; |
1529 | module->duration = fvalue; |
1530 | break; |
1531 | case MKV_ELEMENT_ID_TITLE: |
1532 | case MKV_ELEMENT_ID_MUXING_APP: |
1533 | case MKV_ELEMENT_ID_WRITING_APP: |
1534 | SKIP_STRING(p_ctx, size, "string" ); |
1535 | break; |
1536 | |
1537 | default: break; |
1538 | } |
1539 | |
1540 | return status; |
1541 | } |
1542 | |
1543 | static VC_CONTAINER_STATUS_T mkv_read_subelements_seek_head( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ) |
1544 | { |
1545 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
1546 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
1547 | uint64_t value; |
1548 | |
1549 | if(id == MKV_ELEMENT_ID_SEEK) |
1550 | { |
1551 | module->seekhead_elem_id = MKV_ELEMENT_ID_UNKNOWN; |
1552 | module->seekhead_elem_offset = -1; |
1553 | status = mkv_read_elements(p_ctx, id, size); |
1554 | if(status == VC_CONTAINER_SUCCESS && !module->cues_offset && |
1555 | module->seekhead_elem_id == MKV_ELEMENT_ID_CUES && module->seekhead_elem_offset) |
1556 | module->cues_offset = module->seekhead_elem_offset; |
1557 | if(status == VC_CONTAINER_SUCCESS && !module->tags_offset && |
1558 | module->seekhead_elem_id == MKV_ELEMENT_ID_TAGS && module->seekhead_elem_offset) |
1559 | module->tags_offset = module->seekhead_elem_offset; |
1560 | return status; |
1561 | } |
1562 | |
1563 | if(id == MKV_ELEMENT_ID_SEEK_ID) |
1564 | { |
1565 | MKV_ELEMENT_T *element = mkv_elements_list; |
1566 | id = MKV_READ_ID(p_ctx, "Element ID" ); |
1567 | module->seekhead_elem_id = id; |
1568 | |
1569 | /* Find out which Element we are dealing with */ |
1570 | while(element->id && id != element->id) element++; |
1571 | LOG_FORMAT(p_ctx, "element: %s (ID 0x%x)" , element->psz_name, id); |
1572 | } |
1573 | else if(id == MKV_ELEMENT_ID_SEEK_POSITION) |
1574 | { |
1575 | status = mkv_read_element_data_uint(p_ctx, size, &value); |
1576 | if(status != VC_CONTAINER_SUCCESS) return status; |
1577 | LOG_FORMAT(p_ctx, "offset: %" PRIi64, value + module->segment_offset); |
1578 | module->seekhead_elem_offset = value + module->segment_offset; |
1579 | } |
1580 | |
1581 | return status; |
1582 | } |
1583 | |
1584 | static VC_CONTAINER_STATUS_T mkv_read_element_cues( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ) |
1585 | { |
1586 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
1587 | VC_CONTAINER_PARAM_UNUSED(id); |
1588 | VC_CONTAINER_PARAM_UNUSED(size); |
1589 | module->cues_offset = module->element_offset; |
1590 | return VC_CONTAINER_SUCCESS; |
1591 | } |
1592 | |
1593 | static VC_CONTAINER_STATUS_T mkv_read_subelements_cue_point( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ) |
1594 | { |
1595 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
1596 | VC_CONTAINER_STATUS_T status; |
1597 | uint64_t value; |
1598 | |
1599 | /* All the values are unsigned integers */ |
1600 | status = mkv_read_element_data_uint(p_ctx, size, &value); |
1601 | if(status != VC_CONTAINER_SUCCESS) return status; |
1602 | |
1603 | switch(id) |
1604 | { |
1605 | case MKV_ELEMENT_ID_CUE_TIME: |
1606 | module->cue_timecode = value; break; |
1607 | case MKV_ELEMENT_ID_CUE_TRACK: |
1608 | module->cue_track = value; break; |
1609 | case MKV_ELEMENT_ID_CUE_CLUSTER_POSITION: |
1610 | module->cue_cluster_offset = value; break; |
1611 | case MKV_ELEMENT_ID_CUE_BLOCK_NUMBER: |
1612 | module->cue_block = value; break; |
1613 | default: break; |
1614 | } |
1615 | |
1616 | return status; |
1617 | } |
1618 | |
1619 | static VC_CONTAINER_STATUS_T mkv_read_subelements_cluster( VC_CONTAINER_T *p_ctx, MKV_ELEMENT_ID_T id, int64_t size ) |
1620 | { |
1621 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
1622 | VC_CONTAINER_STATUS_T status; |
1623 | uint64_t value; |
1624 | |
1625 | /* The rest are just unsigned integers */ |
1626 | status = mkv_read_element_data_uint(p_ctx, size, &value); |
1627 | if(status != VC_CONTAINER_SUCCESS) return status; |
1628 | |
1629 | switch(id) |
1630 | { |
1631 | //XXX |
1632 | case MKV_ELEMENT_ID_TIMECODE: module->state.cluster_timecode = value; break; |
1633 | case MKV_ELEMENT_ID_BLOCK_DURATION: module->state.frame_duration = value; break; |
1634 | default: break; |
1635 | } |
1636 | |
1637 | return status; |
1638 | } |
1639 | |
1640 | /*******************************/ |
1641 | |
1642 | static VC_CONTAINER_STATUS_T mkv_skip_element(VC_CONTAINER_T *p_ctx, |
1643 | MKV_READER_STATE_T *state) |
1644 | { |
1645 | /* Skip any trailing data from the current element */ |
1646 | int64_t skip = state->levels[state->level].offset + |
1647 | state->levels[state->level].size - STREAM_POSITION(p_ctx); |
1648 | |
1649 | if(skip < 0) /* Check for overruns */ |
1650 | { |
1651 | /* Things have gone really bad here and we ended up reading past the end of the |
1652 | * element. We could maybe try to be clever and recover by seeking back to the end |
1653 | * of the element. However if we get there, the file is clearly corrupted so there's |
1654 | * no guarantee it would work anyway. */ |
1655 | LOG_DEBUG(p_ctx, "%" PRIi64" bytes overrun past the end of the element" , -skip); |
1656 | return VC_CONTAINER_ERROR_CORRUPTED; |
1657 | } |
1658 | |
1659 | if(skip) |
1660 | LOG_FORMAT(p_ctx, "%" PRIi64" bytes left unread at the end of element" , skip); |
1661 | |
1662 | state->level--; |
1663 | |
1664 | if (skip >= MKV_MAX_ELEMENT_SIZE) |
1665 | return SEEK(p_ctx, STREAM_POSITION(p_ctx) + skip); |
1666 | SKIP_BYTES(p_ctx, skip); |
1667 | return STREAM_STATUS(p_ctx); |
1668 | } |
1669 | |
1670 | static VC_CONTAINER_STATUS_T mkv_find_next_element(VC_CONTAINER_T *p_ctx, |
1671 | MKV_READER_STATE_T *state, MKV_ELEMENT_ID_T element_id) |
1672 | { |
1673 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
1674 | int64_t element_size, element_offset; |
1675 | MKV_ELEMENT_ID_T id; |
1676 | |
1677 | /* Skip all elements until we find the next requested element */ |
1678 | do |
1679 | { |
1680 | MKV_ELEMENT_T *element = mkv_cluster_elements_list; |
1681 | |
1682 | /* Check whether we've reach the end of the parent element */ |
1683 | if(STREAM_POSITION(p_ctx) >= state->levels[state->level].offset + |
1684 | state->levels[state->level].size) |
1685 | return VC_CONTAINER_ERROR_NOT_FOUND; |
1686 | |
1687 | status = mkv_read_element_header(p_ctx, INT64_C(1) << 30, &id, |
1688 | &element_size, state->levels[state->level].id, &element); |
1689 | element_offset = STREAM_POSITION(p_ctx); |
1690 | if(status != VC_CONTAINER_SUCCESS) return status; |
1691 | if(id == element_id) break; |
1692 | if(element_id == MKV_ELEMENT_ID_BLOCKGROUP && id == MKV_ELEMENT_ID_SIMPLE_BLOCK) break; |
1693 | |
1694 | if(element_id == MKV_ELEMENT_ID_BLOCK && id == MKV_ELEMENT_ID_REFERENCE_BLOCK) |
1695 | state->seen_ref_block = 1; |
1696 | |
1697 | /* Check whether we've reached the end of the parent element */ |
1698 | if(STREAM_POSITION(p_ctx) + element_size >= state->levels[state->level].offset + |
1699 | state->levels[state->level].size) |
1700 | return VC_CONTAINER_ERROR_NOT_FOUND; |
1701 | |
1702 | status = mkv_read_element_data(p_ctx, element, element_size, INT64_C(1) << 30); |
1703 | #if 0 |
1704 | if(element_size < MKV_MAX_ELEMENT_SIZE) SKIP_BYTES(p_ctx, element_size); |
1705 | else SEEK(p_ctx, STREAM_POSITION(p_ctx) + element_size); |
1706 | #endif |
1707 | } while (status == VC_CONTAINER_SUCCESS && STREAM_STATUS(p_ctx) == VC_CONTAINER_SUCCESS); |
1708 | |
1709 | if(STREAM_STATUS(p_ctx) != VC_CONTAINER_SUCCESS) |
1710 | return STREAM_STATUS(p_ctx); |
1711 | |
1712 | state->level++; |
1713 | state->levels[state->level].offset = element_offset; |
1714 | state->levels[state->level].size = element_size; |
1715 | state->levels[state->level].id = id; |
1716 | return VC_CONTAINER_SUCCESS; |
1717 | } |
1718 | |
1719 | static VC_CONTAINER_STATUS_T mkv_find_next_segment(VC_CONTAINER_T *p_ctx, |
1720 | MKV_READER_STATE_T *state) |
1721 | { |
1722 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
1723 | int64_t element_size, element_offset; |
1724 | MKV_ELEMENT_ID_T id; |
1725 | |
1726 | /* Skip all elements until we find the next segment */ |
1727 | do |
1728 | { |
1729 | MKV_ELEMENT_T *element = mkv_cluster_elements_list; |
1730 | |
1731 | status = mkv_read_element_header(p_ctx, INT64_C(-1), &id, |
1732 | &element_size, MKV_ELEMENT_ID_INVALID, &element); |
1733 | |
1734 | element_offset = STREAM_POSITION(p_ctx); |
1735 | if(status != VC_CONTAINER_SUCCESS) return status; |
1736 | if(id == MKV_ELEMENT_ID_SEGMENT) break; |
1737 | |
1738 | status = mkv_read_element_data(p_ctx, element, element_size, INT64_C(-1)); |
1739 | } while (status == VC_CONTAINER_SUCCESS && STREAM_STATUS(p_ctx) == VC_CONTAINER_SUCCESS); |
1740 | |
1741 | if(STREAM_STATUS(p_ctx) != VC_CONTAINER_SUCCESS) |
1742 | return STREAM_STATUS(p_ctx); |
1743 | |
1744 | state->level++; |
1745 | state->levels[state->level].offset = element_offset; |
1746 | state->levels[state->level].size = element_size; |
1747 | state->levels[state->level].id = id; |
1748 | return VC_CONTAINER_SUCCESS; |
1749 | } |
1750 | |
1751 | static VC_CONTAINER_STATUS_T mkv_find_next_block(VC_CONTAINER_T *p_ctx, MKV_READER_STATE_T *state) |
1752 | { |
1753 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_ERROR_NOT_FOUND; |
1754 | |
1755 | do |
1756 | { |
1757 | if(state->level < 0) |
1758 | { |
1759 | #ifdef ENABLE_MKV_EXTRA_LOGGING |
1760 | LOG_DEBUG(p_ctx, "find segment" ); |
1761 | #endif |
1762 | status = mkv_find_next_segment(p_ctx, state); |
1763 | if(status == VC_CONTAINER_SUCCESS) |
1764 | { |
1765 | LOG_ERROR(p_ctx, "multi-segment files not supported" ); |
1766 | status = VC_CONTAINER_ERROR_EOS; |
1767 | break; |
1768 | } |
1769 | } |
1770 | if(state->levels[state->level].id == MKV_ELEMENT_ID_BLOCK || |
1771 | state->levels[state->level].id == MKV_ELEMENT_ID_SIMPLE_BLOCK) |
1772 | { |
1773 | status = mkv_skip_element(p_ctx, state); |
1774 | } |
1775 | if(state->levels[state->level].id == MKV_ELEMENT_ID_BLOCKGROUP) |
1776 | { |
1777 | #ifdef ENABLE_MKV_EXTRA_LOGGING |
1778 | LOG_DEBUG(p_ctx, "find block" ); |
1779 | #endif |
1780 | state->seen_ref_block = 0; |
1781 | state->frame_duration = 0; |
1782 | status = mkv_find_next_element(p_ctx, state, MKV_ELEMENT_ID_BLOCK); |
1783 | if(status == VC_CONTAINER_SUCCESS) break; |
1784 | |
1785 | if(status == VC_CONTAINER_ERROR_NOT_FOUND) |
1786 | status = mkv_skip_element(p_ctx, state); |
1787 | } |
1788 | if(state->levels[state->level].id == MKV_ELEMENT_ID_CLUSTER) |
1789 | { |
1790 | #ifdef ENABLE_MKV_EXTRA_LOGGING |
1791 | LOG_DEBUG(p_ctx, "find blockgroup or simpleblock" ); |
1792 | #endif |
1793 | state->frame_duration = 0; |
1794 | status = mkv_find_next_element(p_ctx, state, MKV_ELEMENT_ID_BLOCKGROUP); |
1795 | if(status == VC_CONTAINER_SUCCESS && |
1796 | state->levels[state->level].id == MKV_ELEMENT_ID_SIMPLE_BLOCK) break; |
1797 | if(status == VC_CONTAINER_ERROR_NOT_FOUND) |
1798 | status = mkv_skip_element(p_ctx, state); |
1799 | } |
1800 | if(state->levels[state->level].id == MKV_ELEMENT_ID_SEGMENT) |
1801 | { |
1802 | #ifdef ENABLE_MKV_EXTRA_LOGGING |
1803 | LOG_DEBUG(p_ctx, "find cluster" ); |
1804 | #endif |
1805 | status = mkv_find_next_element(p_ctx, state, MKV_ELEMENT_ID_CLUSTER); |
1806 | if(status == VC_CONTAINER_ERROR_NOT_FOUND) |
1807 | status = mkv_skip_element(p_ctx, state); |
1808 | } |
1809 | |
1810 | } while(status == VC_CONTAINER_SUCCESS && STREAM_STATUS(p_ctx) == VC_CONTAINER_SUCCESS); |
1811 | |
1812 | return status == VC_CONTAINER_SUCCESS ? STREAM_STATUS(p_ctx) : status; |
1813 | } |
1814 | |
1815 | static VC_CONTAINER_STATUS_T (VC_CONTAINER_T *p_ctx, |
1816 | MKV_READER_STATE_T *state, uint32_t *pi_track, uint32_t *pi_length) |
1817 | { |
1818 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
1819 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
1820 | VC_CONTAINER_TRACK_MODULE_T *track_module = 0; |
1821 | unsigned int i, track, flags, is_first_lace = 0; |
1822 | int64_t size, pts; |
1823 | |
1824 | if ((state->levels[state->level].id == MKV_ELEMENT_ID_BLOCK || |
1825 | state->levels[state->level].id == MKV_ELEMENT_ID_SIMPLE_BLOCK) && |
1826 | state->levels[state->level].data_start + state->levels[state->level].data_offset < |
1827 | state->levels[state->level].size) |
1828 | goto end; |
1829 | |
1830 | status = mkv_find_next_block(p_ctx, state); |
1831 | if (status != VC_CONTAINER_SUCCESS) return status; |
1832 | |
1833 | /* We have a block */ |
1834 | size = state->levels[state->level].size; |
1835 | track = MKV_READ_UINT(p_ctx, "Track Number" ); LOG_FORMAT(p_ctx, "Track Number: %u" , track); |
1836 | pts = (int16_t)MKV_READ_U16(p_ctx, "Timecode" ); |
1837 | flags = MKV_READ_U8(p_ctx, "Flags" ); |
1838 | if(state->levels[state->level].id == MKV_ELEMENT_ID_BLOCK) flags &= 0x0F; |
1839 | |
1840 | //TODO improve sanity checking |
1841 | /* Sanity checking */ |
1842 | if(size < 0) return VC_CONTAINER_ERROR_CORRUPTED; |
1843 | if(STREAM_STATUS(p_ctx)) return STREAM_STATUS(p_ctx); |
1844 | |
1845 | for (i = 0; i < p_ctx->tracks_num; i++) |
1846 | if (p_ctx->tracks[i]->priv->module->number == track) |
1847 | { track_module = p_ctx->tracks[i]->priv->module; break; } |
1848 | |
1849 | /* Finding out if we have a keyframe when dealing with an MKV_ELEMENT_ID_BLOCK is tricky */ |
1850 | if(state->levels[state->level].id == MKV_ELEMENT_ID_BLOCK && |
1851 | i < p_ctx->tracks_num && p_ctx->tracks[i]->format->es_type == VC_CONTAINER_ES_TYPE_VIDEO) |
1852 | { |
1853 | /* The absence of a ReferenceBlock element tells us if we are a keyframe or not. |
1854 | * The problem we have is that this element can appear before as well as after the block element. |
1855 | * To avoid seeking to look for this element, we do some guess work. */ |
1856 | if(!state->seen_ref_block && state->level && |
1857 | state->levels[state->level].offset + state->levels[state->level].size >= |
1858 | state->levels[state->level-1].offset + state->levels[state->level-1].size) |
1859 | flags |= 0x80; |
1860 | } |
1861 | |
1862 | /* Take care of the lacing */ |
1863 | state->lacing_num_frames = 0; |
1864 | if(i < p_ctx->tracks_num && (flags & 0x06)) |
1865 | { |
1866 | unsigned int i, value = 0; |
1867 | int32_t fs = 0; |
1868 | |
1869 | state->lacing_num_frames = MKV_READ_U8(p_ctx, "Lacing Head" ); |
1870 | state->lacing_size = 0; |
1871 | switch((flags & 0x06)>>1) |
1872 | { |
1873 | case 1: /* Xiph lacing */ |
1874 | for(i = 0; i < state->lacing_num_frames; i++, fs = 0) |
1875 | { |
1876 | do { |
1877 | value = vc_container_io_read_uint8(p_ctx->priv->io); |
1878 | fs += value; size--; |
1879 | } while(value == 255); |
1880 | LOG_FORMAT(p_ctx, "Frame Size: %i" , (int)fs); |
1881 | if(state->lacing_num_frames > MKV_MAX_LACING_NUM) continue; |
1882 | state->lacing_sizes[state->lacing_num_frames-(i+1)] = fs; |
1883 | } |
1884 | break; |
1885 | case 3: /* EBML lacing */ |
1886 | for(i = 0; i < state->lacing_num_frames; i++) |
1887 | { |
1888 | if(!i) fs = MKV_READ_UINT(p_ctx, "Frame Size" ); |
1889 | else fs += MKV_READ_SINT(p_ctx, "Frame Size" ); |
1890 | LOG_FORMAT(p_ctx, "Frame Size: %i" , (int)fs); |
1891 | if(state->lacing_num_frames > MKV_MAX_LACING_NUM) continue; |
1892 | state->lacing_sizes[state->lacing_num_frames-(i+1)] = fs; |
1893 | } |
1894 | break; |
1895 | default: /* Fixed-size lacing */ |
1896 | state->lacing_size = size / (state->lacing_num_frames+1); |
1897 | break; |
1898 | } |
1899 | |
1900 | /* There is a max number of laced frames we can support but after we can still give back |
1901 | * all the other frames in 1 packet */ |
1902 | if(state->lacing_num_frames > MKV_MAX_LACING_NUM) |
1903 | state->lacing_num_frames = MKV_MAX_LACING_NUM; |
1904 | |
1905 | /* Sanity check the size of the frames */ |
1906 | if(size < 0) return VC_CONTAINER_ERROR_CORRUPTED; |
1907 | if(STREAM_STATUS(p_ctx)) return STREAM_STATUS(p_ctx); |
1908 | state->lacing_current_size = state->lacing_size; |
1909 | if(!state->lacing_size) |
1910 | { |
1911 | int64_t frames_size = 0; |
1912 | for(i = state->lacing_num_frames; i > 0; i--) |
1913 | { |
1914 | if(frames_size + state->lacing_sizes[i-1] > size) /* return error ? */ |
1915 | state->lacing_sizes[i-1] = size - frames_size; |
1916 | frames_size += state->lacing_sizes[i-1]; |
1917 | } |
1918 | } |
1919 | state->lacing_current_size = 0; |
1920 | state->lacing_num_frames++; /* Will be decremented further down */ |
1921 | is_first_lace = 1; |
1922 | } |
1923 | |
1924 | state->track = i; |
1925 | state->pts = (state->cluster_timecode + pts) * module->timecode_scale; |
1926 | if(track_module) state->pts *= track_module->timecode_scale; |
1927 | state->pts /= 1000; |
1928 | state->flags = flags; |
1929 | |
1930 | state->frame_duration = state->frame_duration * module->timecode_scale / 1000; |
1931 | if(state->lacing_num_frames) state->frame_duration /= state->lacing_num_frames; |
1932 | if(!state->frame_duration && track_module) |
1933 | state->frame_duration = track_module->frame_duration / 1000; |
1934 | |
1935 | state->levels[state->level].data_start = STREAM_POSITION(p_ctx) - |
1936 | state->levels[state->level].offset; |
1937 | state->levels[state->level].data_offset = 0; |
1938 | |
1939 | /* Deal with header stripping compression */ |
1940 | state->header_size = 0; |
1941 | if(track_module && track_module->encodings_num) |
1942 | { |
1943 | state->header_size = track_module->encodings[0].data_size; |
1944 | state->header_data = track_module->encodings[0].data; |
1945 | } |
1946 | state->header_size_backup = state->header_size; |
1947 | |
1948 | end: |
1949 | *pi_length = state->levels[state->level].size - state->levels[state->level].data_start - |
1950 | state->levels[state->level].data_offset + state->header_size; |
1951 | *pi_track = state->track; |
1952 | |
1953 | /* Special case for lacing */ |
1954 | if(state->lacing_num_frames && |
1955 | state->levels[state->level].data_offset >= state->lacing_current_size) |
1956 | { |
1957 | /* We need to switch to the next lace */ |
1958 | if(--state->lacing_num_frames) |
1959 | { |
1960 | unsigned int lace_size = state->lacing_size; |
1961 | if(!state->lacing_size) lace_size = state->lacing_sizes[state->lacing_num_frames-1]; |
1962 | state->lacing_current_size = lace_size; |
1963 | } |
1964 | state->levels[state->level].data_start += state->levels[state->level].data_offset; |
1965 | state->levels[state->level].data_offset = 0; |
1966 | if(!is_first_lace && state->frame_duration) |
1967 | state->pts += state->frame_duration; |
1968 | else if(!is_first_lace) |
1969 | state->pts = VC_CONTAINER_TIME_UNKNOWN; |
1970 | |
1971 | /* Deal with header stripping compression */ |
1972 | state->header_data -= (state->header_size_backup - state->header_size); |
1973 | state->header_size = state->header_size_backup; |
1974 | } |
1975 | if(state->lacing_num_frames) |
1976 | *pi_length = state->lacing_current_size - state->levels[state->level].data_offset + state->header_size; |
1977 | |
1978 | return status == VC_CONTAINER_SUCCESS ? STREAM_STATUS(p_ctx) : status; |
1979 | } |
1980 | |
1981 | static VC_CONTAINER_STATUS_T mkv_read_frame_data(VC_CONTAINER_T *p_ctx, |
1982 | MKV_READER_STATE_T *state, uint8_t *p_data, uint32_t *pi_length) |
1983 | { |
1984 | uint64_t size; |
1985 | uint32_t ; |
1986 | |
1987 | size = state->levels[state->level].size - state->levels[state->level].data_start - |
1988 | state->levels[state->level].data_offset; |
1989 | |
1990 | /* Special case for lacing */ |
1991 | if(state->lacing_num_frames) |
1992 | { |
1993 | size = state->lacing_current_size - state->levels[state->level].data_offset; |
1994 | |
1995 | if(!p_data) |
1996 | { |
1997 | size = SKIP_BYTES(p_ctx, size); |
1998 | state->levels[state->level].data_offset += size; |
1999 | return STREAM_STATUS(p_ctx); |
2000 | } |
2001 | } |
2002 | |
2003 | size += state->header_size; |
2004 | |
2005 | if(!p_data) return mkv_skip_element(p_ctx, state); |
2006 | if(size > *pi_length) size = *pi_length; |
2007 | |
2008 | header_size = state->header_size; |
2009 | if(header_size) |
2010 | { |
2011 | if(header_size > size) header_size = size; |
2012 | memcpy(p_data, state->header_data, header_size); |
2013 | state->header_size -= header_size; |
2014 | state->header_data += header_size; |
2015 | size -= header_size; |
2016 | } |
2017 | |
2018 | size = READ_BYTES(p_ctx, p_data + header_size, size); |
2019 | state->levels[state->level].data_offset += size; |
2020 | *pi_length = size + header_size; |
2021 | |
2022 | return STREAM_STATUS(p_ctx); |
2023 | } |
2024 | |
2025 | /***************************************************************************** |
2026 | Functions exported as part of the Container Module API |
2027 | *****************************************************************************/ |
2028 | |
2029 | static VC_CONTAINER_STATUS_T mkv_reader_read(VC_CONTAINER_T *p_ctx, |
2030 | VC_CONTAINER_PACKET_T *p_packet, uint32_t flags) |
2031 | { |
2032 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
2033 | VC_CONTAINER_TRACK_T *p_track = 0; |
2034 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
2035 | uint32_t buffer_size = 0, track = 0, data_size; |
2036 | MKV_READER_STATE_T *state = &module->state; |
2037 | |
2038 | /* If a specific track has been selected, we need to use the track packet state */ |
2039 | if(flags & VC_CONTAINER_READ_FLAG_FORCE_TRACK) |
2040 | { |
2041 | p_track = p_ctx->tracks[p_packet->track]; |
2042 | state = p_track->priv->module->state; |
2043 | } |
2044 | |
2045 | /**/ |
2046 | if(state->eos) return VC_CONTAINER_ERROR_EOS; |
2047 | if(state->corrupted) return VC_CONTAINER_ERROR_CORRUPTED; |
2048 | |
2049 | /* Look at the next frame header */ |
2050 | status = mkv_read_next_frame_header(p_ctx, state, &track, &data_size); |
2051 | if(status == VC_CONTAINER_ERROR_EOS) state->eos = true; |
2052 | if(status == VC_CONTAINER_ERROR_CORRUPTED) state->corrupted = true; |
2053 | if(status != VC_CONTAINER_SUCCESS) return status; |
2054 | |
2055 | if(track >= p_ctx->tracks_num || !p_ctx->tracks[track]->is_enabled) |
2056 | { |
2057 | /* Skip frame */ |
2058 | status = mkv_read_frame_data(p_ctx, state, 0, &data_size); |
2059 | if (status != VC_CONTAINER_SUCCESS) return status; |
2060 | return VC_CONTAINER_ERROR_CONTINUE; |
2061 | } |
2062 | |
2063 | if((flags & VC_CONTAINER_READ_FLAG_SKIP) && !(flags & VC_CONTAINER_READ_FLAG_INFO)) /* Skip packet */ |
2064 | return mkv_read_frame_data(p_ctx, state, 0, &data_size); |
2065 | |
2066 | p_packet->dts = p_packet->pts = state->pts; |
2067 | p_packet->flags = 0; |
2068 | if(state->flags & 0x80) p_packet->flags |= VC_CONTAINER_PACKET_FLAG_KEYFRAME; |
2069 | if(!state->levels[state->level].data_offset) p_packet->flags |= VC_CONTAINER_PACKET_FLAG_FRAME_START; |
2070 | p_packet->flags |= VC_CONTAINER_PACKET_FLAG_FRAME_END; |
2071 | p_packet->size = data_size; |
2072 | p_packet->track = track; |
2073 | |
2074 | if(flags & VC_CONTAINER_READ_FLAG_SKIP) |
2075 | return mkv_read_frame_data(p_ctx, state, 0, &data_size ); |
2076 | else if(flags & VC_CONTAINER_READ_FLAG_INFO) |
2077 | return VC_CONTAINER_SUCCESS; |
2078 | |
2079 | /* Read the frame data */ |
2080 | buffer_size = p_packet->buffer_size; |
2081 | status = mkv_read_frame_data(p_ctx, state, p_packet->data, &buffer_size); |
2082 | if(status != VC_CONTAINER_SUCCESS) |
2083 | { |
2084 | /* FIXME */ |
2085 | return status; |
2086 | } |
2087 | |
2088 | p_packet->size = buffer_size; |
2089 | if(buffer_size != data_size) |
2090 | p_packet->flags &= ~VC_CONTAINER_PACKET_FLAG_FRAME_END; |
2091 | |
2092 | return status; |
2093 | } |
2094 | |
2095 | /*****************************************************************************/ |
2096 | static VC_CONTAINER_STATUS_T mkv_reader_seek(VC_CONTAINER_T *p_ctx, |
2097 | int64_t *p_offset, VC_CONTAINER_SEEK_MODE_T mode, VC_CONTAINER_SEEK_FLAGS_T flags) |
2098 | { |
2099 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_SUCCESS; |
2100 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
2101 | MKV_READER_STATE_T *state = &module->state; |
2102 | uint64_t offset = 0, prev_offset = 0, position = STREAM_POSITION(p_ctx); |
2103 | int64_t time_offset = 0, prev_time_offset = 0; |
2104 | unsigned int i, video_track; |
2105 | MKV_ELEMENT_T *element = mkv_cue_elements_list; |
2106 | int64_t size, element_size; |
2107 | MKV_ELEMENT_ID_T id; |
2108 | VC_CONTAINER_PARAM_UNUSED(mode); |
2109 | VC_CONTAINER_PARAM_UNUSED(flags); |
2110 | |
2111 | /* Find out if we have a video track */ |
2112 | for(video_track = 0; video_track < p_ctx->tracks_num; video_track++) |
2113 | if(p_ctx->tracks[video_track]->is_enabled && |
2114 | p_ctx->tracks[video_track]->format->es_type == VC_CONTAINER_ES_TYPE_VIDEO) break; |
2115 | |
2116 | if(!*p_offset) goto end; /* Nothing much to do */ |
2117 | if(!module->cues_offset) {status = VC_CONTAINER_ERROR_UNSUPPORTED_OPERATION; goto error;} |
2118 | |
2119 | /* We need to do a search in the cue list */ |
2120 | status = SEEK(p_ctx, module->cues_offset); |
2121 | if(status != VC_CONTAINER_SUCCESS) goto error; |
2122 | |
2123 | /* First read the header of the cues element */ |
2124 | status = mkv_read_element_header(p_ctx, INT64_C(-1) /* TODO */, &id, &element_size, |
2125 | MKV_ELEMENT_ID_SEGMENT, &element); |
2126 | if(status != VC_CONTAINER_SUCCESS || id != MKV_ELEMENT_ID_CUES) goto error; |
2127 | size = element_size; |
2128 | |
2129 | module->elements_list = mkv_cue_elements_list; |
2130 | do |
2131 | { |
2132 | MKV_ELEMENT_T *element = mkv_cue_elements_list; |
2133 | int64_t element_offset = STREAM_POSITION(p_ctx); |
2134 | |
2135 | /* Exit condition for when we've scanned the whole cues list */ |
2136 | if(size <= 0) |
2137 | { |
2138 | if(!(flags & VC_CONTAINER_SEEK_FLAG_FORWARD)) |
2139 | break; /* Just use the last valid entry in that case */ |
2140 | status = VC_CONTAINER_ERROR_EOS; |
2141 | goto error; |
2142 | } |
2143 | |
2144 | status = mkv_read_element_header(p_ctx, size, &id, &element_size, |
2145 | MKV_ELEMENT_ID_CUES, &element); |
2146 | size -= STREAM_POSITION(p_ctx) - element_offset; |
2147 | if(status == VC_CONTAINER_SUCCESS && element->id != MKV_ELEMENT_ID_UNKNOWN) |
2148 | status = mkv_read_element_data(p_ctx, element, element_size, size); |
2149 | |
2150 | if(status != VC_CONTAINER_SUCCESS || element->id == MKV_ELEMENT_ID_UNKNOWN) |
2151 | { |
2152 | if(!(flags & VC_CONTAINER_SEEK_FLAG_FORWARD)) |
2153 | break; /* Just use the last valid entry in that case */ |
2154 | goto error; |
2155 | } |
2156 | |
2157 | size -= element_size; |
2158 | if(id != MKV_ELEMENT_ID_CUE_POINT) continue; |
2159 | |
2160 | /* Ignore cue points which don't belong to the track we want */ |
2161 | if(video_track != p_ctx->tracks_num && |
2162 | p_ctx->tracks[video_track]->priv->module->number != module->cue_track) continue; |
2163 | |
2164 | time_offset = module->cue_timecode * module->timecode_scale / 1000; |
2165 | offset = module->cue_cluster_offset; |
2166 | LOG_DEBUG(p_ctx, "INDEX: %" PRIi64, time_offset); |
2167 | if( time_offset > *p_offset ) |
2168 | { |
2169 | if(!(flags & VC_CONTAINER_SEEK_FLAG_FORWARD)) |
2170 | { |
2171 | time_offset = prev_time_offset; |
2172 | offset = prev_offset; |
2173 | } |
2174 | break; |
2175 | } |
2176 | prev_time_offset = time_offset; |
2177 | prev_offset = offset; |
2178 | } while( 1 ); |
2179 | module->elements_list = mkv_elements_list; |
2180 | *p_offset = time_offset; |
2181 | |
2182 | end: |
2183 | /* Try seeking to the requested position */ |
2184 | status = SEEK(p_ctx, module->segment_offset + offset); |
2185 | if(status != VC_CONTAINER_SUCCESS && status != VC_CONTAINER_ERROR_EOS) goto error; |
2186 | |
2187 | /* Reinitialise the state */ |
2188 | memset(state, 0, sizeof(*state)); |
2189 | state->levels[0].offset = module->segment_offset; |
2190 | state->levels[0].size = module->segment_size; |
2191 | state->levels[0].id = MKV_ELEMENT_ID_SEGMENT; |
2192 | if(status == VC_CONTAINER_ERROR_EOS) state->eos = true; |
2193 | for(i = 0; i < p_ctx->tracks_num; i++) |
2194 | { |
2195 | VC_CONTAINER_TRACK_T *p_track = p_ctx->tracks[i]; |
2196 | p_track->priv->module->state = state; |
2197 | } |
2198 | |
2199 | /* If we have a video track, we skip frames until the next keyframe */ |
2200 | for(i = 0; video_track != p_ctx->tracks_num && i < 200 /* limit search */; ) |
2201 | { |
2202 | uint32_t track, data_size; |
2203 | status = mkv_read_next_frame_header(p_ctx, state, &track, &data_size); |
2204 | if(status != VC_CONTAINER_SUCCESS) break; //FIXME |
2205 | if(track == video_track) i++; |
2206 | if(track == video_track && (state->flags & 0x80) && |
2207 | state->pts >= time_offset) break; |
2208 | |
2209 | /* Skip frame */ |
2210 | status = mkv_read_frame_data(p_ctx, state, 0, &data_size); |
2211 | } |
2212 | |
2213 | return VC_CONTAINER_SUCCESS; |
2214 | |
2215 | error: |
2216 | /* Reset everything as it was before the seek */ |
2217 | SEEK(p_ctx, position); |
2218 | if(status == VC_CONTAINER_SUCCESS) status = VC_CONTAINER_ERROR_FAILED; |
2219 | return status; |
2220 | } |
2221 | |
2222 | /*****************************************************************************/ |
2223 | static VC_CONTAINER_STATUS_T mkv_reader_close(VC_CONTAINER_T *p_ctx) |
2224 | { |
2225 | VC_CONTAINER_MODULE_T *module = p_ctx->priv->module; |
2226 | unsigned int i, j; |
2227 | |
2228 | for(i = 0; i < p_ctx->tracks_num; i++) |
2229 | { |
2230 | for(j = 0; j < MKV_MAX_ENCODINGS; j++) |
2231 | free(p_ctx->tracks[i]->priv->module->encodings[j].data); |
2232 | vc_container_free_track(p_ctx, p_ctx->tracks[i]); |
2233 | } |
2234 | free(module); |
2235 | return VC_CONTAINER_SUCCESS; |
2236 | } |
2237 | |
2238 | /*****************************************************************************/ |
2239 | VC_CONTAINER_STATUS_T mkv_reader_open(VC_CONTAINER_T *p_ctx) |
2240 | { |
2241 | VC_CONTAINER_MODULE_T *module = 0; |
2242 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_ERROR_FORMAT_INVALID; |
2243 | uint8_t buffer[4]; |
2244 | |
2245 | // Can start with ASCII strings ???? |
2246 | |
2247 | /* Check for an EBML element */ |
2248 | if(PEEK_BYTES(p_ctx, buffer, 4) < 4 || |
2249 | buffer[0] != 0x1A || buffer[1] != 0x45 || buffer[2] != 0xDF || buffer[3] != 0xA3) |
2250 | return VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED; |
2251 | |
2252 | /* |
2253 | * We are dealing with an MKV file |
2254 | */ |
2255 | |
2256 | /* Allocate our context */ |
2257 | module = malloc(sizeof(*module)); |
2258 | if(!module) {status = VC_CONTAINER_ERROR_OUT_OF_MEMORY; goto error;} |
2259 | memset(module, 0, sizeof(*module)); |
2260 | p_ctx->priv->module = module; |
2261 | p_ctx->tracks = module->tracks; |
2262 | module->elements_list = mkv_elements_list; |
2263 | |
2264 | /* Read and sanity check the EBML header */ |
2265 | status = mkv_read_element(p_ctx, INT64_C(-1), MKV_ELEMENT_ID_UNKNOWN); |
2266 | if(status != VC_CONTAINER_SUCCESS) goto error; |
2267 | if(!module->is_doctype_valid) {status = VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED; goto error;} |
2268 | |
2269 | /* Read the other elements until we find the start of the data */ |
2270 | do |
2271 | { |
2272 | status = mkv_read_element(p_ctx, INT64_C(-1), MKV_ELEMENT_ID_UNKNOWN); |
2273 | if(status != VC_CONTAINER_SUCCESS) break; |
2274 | |
2275 | if(module->cluster_offset) break; |
2276 | } while(1); |
2277 | |
2278 | /* Bail out if we didn't find a track */ |
2279 | if(!p_ctx->tracks_num) |
2280 | { |
2281 | status = VC_CONTAINER_ERROR_NO_TRACK_AVAILABLE; |
2282 | goto error; |
2283 | } |
2284 | |
2285 | /* |
2286 | * We now have all the information we really need to start playing the stream |
2287 | */ |
2288 | |
2289 | p_ctx->priv->pf_close = mkv_reader_close; |
2290 | p_ctx->priv->pf_read = mkv_reader_read; |
2291 | p_ctx->priv->pf_seek = mkv_reader_seek; |
2292 | p_ctx->duration = module->duration / 1000 * module->timecode_scale; |
2293 | |
2294 | /* Check if we're done */ |
2295 | if(!STREAM_SEEKABLE(p_ctx)) |
2296 | return VC_CONTAINER_SUCCESS; |
2297 | |
2298 | if(module->cues_offset && (int64_t)module->cues_offset < p_ctx->size) |
2299 | p_ctx->capabilities |= VC_CONTAINER_CAPS_CAN_SEEK; |
2300 | |
2301 | if(module->tags_offset) |
2302 | { |
2303 | status = SEEK(p_ctx, module->tags_offset); |
2304 | if(status == VC_CONTAINER_SUCCESS) |
2305 | status = mkv_read_element(p_ctx, INT64_C(-1) /*FIXME*/, MKV_ELEMENT_ID_SEGMENT); |
2306 | } |
2307 | |
2308 | /* Seek back to the start of the data */ |
2309 | return SEEK(p_ctx, module->state.levels[1].offset); |
2310 | |
2311 | error: |
2312 | LOG_DEBUG(p_ctx, "mkv: error opening stream (%i)" , status); |
2313 | if(module) mkv_reader_close(p_ctx); |
2314 | return status; |
2315 | } |
2316 | |
2317 | /******************************************************************************** |
2318 | Entrypoint function |
2319 | ********************************************************************************/ |
2320 | |
2321 | #if !defined(ENABLE_CONTAINERS_STANDALONE) && defined(__HIGHC__) |
2322 | # pragma weak reader_open mkv_reader_open |
2323 | #endif |
2324 | |