Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Matroska file demuxer | ||
3 | * Copyright (c) 2003-2008 The FFmpeg Project | ||
4 | * | ||
5 | * This file is part of FFmpeg. | ||
6 | * | ||
7 | * FFmpeg is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU Lesser General Public | ||
9 | * License as published by the Free Software Foundation; either | ||
10 | * version 2.1 of the License, or (at your option) any later version. | ||
11 | * | ||
12 | * FFmpeg is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
15 | * Lesser General Public License for more details. | ||
16 | * | ||
17 | * You should have received a copy of the GNU Lesser General Public | ||
18 | * License along with FFmpeg; if not, write to the Free Software | ||
19 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
20 | */ | ||
21 | |||
22 | /** | ||
23 | * @file | ||
24 | * Matroska file demuxer | ||
25 | * @author Ronald Bultje <rbultje@ronald.bitfreak.net> | ||
26 | * @author with a little help from Moritz Bunkus <moritz@bunkus.org> | ||
27 | * @author totally reworked by Aurelien Jacobs <aurel@gnuage.org> | ||
28 | * @see specs available on the Matroska project page: http://www.matroska.org/ | ||
29 | */ | ||
30 | |||
31 | #include "config.h" | ||
32 | #include "config_components.h" | ||
33 | |||
34 | #include <inttypes.h> | ||
35 | #include <stdio.h> | ||
36 | |||
37 | #include "libavutil/avstring.h" | ||
38 | #include "libavutil/base64.h" | ||
39 | #include "libavutil/bprint.h" | ||
40 | #include "libavutil/dict.h" | ||
41 | #include "libavutil/display.h" | ||
42 | #include "libavutil/hdr_dynamic_metadata.h" | ||
43 | #include "libavutil/intfloat.h" | ||
44 | #include "libavutil/intreadwrite.h" | ||
45 | #include "libavutil/lzo.h" | ||
46 | #include "libavutil/mastering_display_metadata.h" | ||
47 | #include "libavutil/mathematics.h" | ||
48 | #include "libavutil/mem.h" | ||
49 | #include "libavutil/opt.h" | ||
50 | #include "libavutil/pixdesc.h" | ||
51 | #include "libavutil/time_internal.h" | ||
52 | #include "libavutil/spherical.h" | ||
53 | |||
54 | #include "libavcodec/bytestream.h" | ||
55 | #include "libavcodec/defs.h" | ||
56 | #include "libavcodec/flac.h" | ||
57 | #include "libavcodec/itut35.h" | ||
58 | #include "libavcodec/mpeg4audio.h" | ||
59 | #include "libavcodec/packet_internal.h" | ||
60 | |||
61 | #include "avformat.h" | ||
62 | #include "avio_internal.h" | ||
63 | #include "demux.h" | ||
64 | #include "dovi_isom.h" | ||
65 | #include "internal.h" | ||
66 | #include "isom.h" | ||
67 | #include "matroska.h" | ||
68 | #include "oggdec.h" | ||
69 | /* For ff_codec_get_id(). */ | ||
70 | #include "riff.h" | ||
71 | #include "rmsipr.h" | ||
72 | |||
73 | #if CONFIG_BZLIB | ||
74 | #include <bzlib.h> | ||
75 | #endif | ||
76 | #if CONFIG_ZLIB | ||
77 | #include <zlib.h> | ||
78 | #endif | ||
79 | |||
80 | #include "qtpalette.h" | ||
81 | |||
82 | #define EBML_UNKNOWN_LENGTH UINT64_MAX /* EBML unknown length, in uint64_t */ | ||
83 | #define NEEDS_CHECKING 2 /* Indicates that some error checks | ||
84 | * still need to be performed */ | ||
85 | #define LEVEL_ENDED 3 /* return value of ebml_parse when the | ||
86 | * syntax level used for parsing ended. */ | ||
87 | #define SKIP_THRESHOLD 1024 * 1024 /* In non-seekable mode, if more than SKIP_THRESHOLD | ||
88 | * of unkown, potentially damaged data is encountered, | ||
89 | * it is considered an error. */ | ||
90 | #define UNKNOWN_EQUIV 50 * 1024 /* An unknown element is considered equivalent | ||
91 | * to this many bytes of unknown data for the | ||
92 | * SKIP_THRESHOLD check. */ | ||
93 | |||
94 | typedef enum { | ||
95 | EBML_NONE, | ||
96 | EBML_UINT, | ||
97 | EBML_SINT, | ||
98 | EBML_FLOAT, | ||
99 | EBML_STR, | ||
100 | EBML_UTF8, | ||
101 | EBML_BIN, | ||
102 | EBML_NEST, | ||
103 | EBML_LEVEL1, | ||
104 | EBML_STOP, | ||
105 | EBML_TYPE_COUNT | ||
106 | } EbmlType; | ||
107 | |||
108 | typedef struct CountedElement { | ||
109 | union { | ||
110 | uint64_t u; | ||
111 | int64_t i; | ||
112 | double f; | ||
113 | char *s; | ||
114 | } el; | ||
115 | unsigned count; | ||
116 | } CountedElement; | ||
117 | |||
118 | typedef const struct EbmlSyntax { | ||
119 | uint32_t id; | ||
120 | uint8_t type; | ||
121 | uint8_t is_counted; | ||
122 | size_t list_elem_size; | ||
123 | size_t data_offset; | ||
124 | union { | ||
125 | int64_t i; | ||
126 | uint64_t u; | ||
127 | double f; | ||
128 | const char *s; | ||
129 | const struct EbmlSyntax *n; | ||
130 | } def; | ||
131 | } EbmlSyntax; | ||
132 | |||
133 | typedef struct EbmlList { | ||
134 | int nb_elem; | ||
135 | unsigned int alloc_elem_size; | ||
136 | void *elem; | ||
137 | } EbmlList; | ||
138 | |||
139 | typedef struct EbmlBin { | ||
140 | int size; | ||
141 | AVBufferRef *buf; | ||
142 | uint8_t *data; | ||
143 | int64_t pos; | ||
144 | } EbmlBin; | ||
145 | |||
146 | typedef struct Ebml { | ||
147 | uint64_t version; | ||
148 | uint64_t max_size; | ||
149 | uint64_t id_length; | ||
150 | char *doctype; | ||
151 | uint64_t doctype_version; | ||
152 | } Ebml; | ||
153 | |||
154 | typedef struct MatroskaTrackCompression { | ||
155 | uint64_t algo; | ||
156 | EbmlBin settings; | ||
157 | } MatroskaTrackCompression; | ||
158 | |||
159 | typedef struct MatroskaTrackEncryption { | ||
160 | uint64_t algo; | ||
161 | EbmlBin key_id; | ||
162 | } MatroskaTrackEncryption; | ||
163 | |||
164 | typedef struct MatroskaTrackEncoding { | ||
165 | uint64_t scope; | ||
166 | uint64_t type; | ||
167 | MatroskaTrackCompression compression; | ||
168 | MatroskaTrackEncryption encryption; | ||
169 | } MatroskaTrackEncoding; | ||
170 | |||
171 | typedef struct MatroskaMasteringMeta { | ||
172 | double r_x; | ||
173 | double r_y; | ||
174 | double g_x; | ||
175 | double g_y; | ||
176 | double b_x; | ||
177 | double b_y; | ||
178 | double white_x; | ||
179 | double white_y; | ||
180 | double max_luminance; | ||
181 | CountedElement min_luminance; | ||
182 | } MatroskaMasteringMeta; | ||
183 | |||
184 | typedef struct MatroskaTrackVideoColor { | ||
185 | uint64_t matrix_coefficients; | ||
186 | uint64_t bits_per_channel; | ||
187 | uint64_t chroma_sub_horz; | ||
188 | uint64_t chroma_sub_vert; | ||
189 | uint64_t cb_sub_horz; | ||
190 | uint64_t cb_sub_vert; | ||
191 | uint64_t chroma_siting_horz; | ||
192 | uint64_t chroma_siting_vert; | ||
193 | uint64_t range; | ||
194 | uint64_t transfer_characteristics; | ||
195 | uint64_t primaries; | ||
196 | uint64_t max_cll; | ||
197 | uint64_t max_fall; | ||
198 | MatroskaMasteringMeta mastering_meta; | ||
199 | } MatroskaTrackVideoColor; | ||
200 | |||
201 | typedef struct MatroskaTrackVideoProjection { | ||
202 | uint64_t type; | ||
203 | EbmlBin private; | ||
204 | double yaw; | ||
205 | double pitch; | ||
206 | double roll; | ||
207 | } MatroskaTrackVideoProjection; | ||
208 | |||
209 | typedef struct MatroskaTrackVideo { | ||
210 | double frame_rate; | ||
211 | uint64_t display_width; | ||
212 | uint64_t display_height; | ||
213 | uint64_t pixel_width; | ||
214 | uint64_t pixel_height; | ||
215 | uint64_t cropped_width; | ||
216 | uint64_t cropped_height; | ||
217 | EbmlBin color_space; | ||
218 | uint64_t pixel_cropt; | ||
219 | uint64_t pixel_cropl; | ||
220 | uint64_t pixel_cropb; | ||
221 | uint64_t pixel_cropr; | ||
222 | uint64_t display_unit; | ||
223 | uint64_t interlaced; | ||
224 | uint64_t field_order; | ||
225 | uint64_t stereo_mode; | ||
226 | uint64_t alpha_mode; | ||
227 | EbmlList color; | ||
228 | MatroskaTrackVideoProjection projection; | ||
229 | } MatroskaTrackVideo; | ||
230 | |||
231 | typedef struct MatroskaTrackAudio { | ||
232 | double samplerate; | ||
233 | double out_samplerate; | ||
234 | uint64_t bitdepth; | ||
235 | uint64_t channels; | ||
236 | |||
237 | /* real audio header (extracted from extradata) */ | ||
238 | int coded_framesize; | ||
239 | int sub_packet_h; | ||
240 | int frame_size; | ||
241 | int sub_packet_size; | ||
242 | int sub_packet_cnt; | ||
243 | int pkt_cnt; | ||
244 | uint64_t buf_timecode; | ||
245 | uint8_t *buf; | ||
246 | } MatroskaTrackAudio; | ||
247 | |||
248 | typedef struct MatroskaTrackPlane { | ||
249 | uint64_t uid; | ||
250 | uint64_t type; | ||
251 | } MatroskaTrackPlane; | ||
252 | |||
253 | typedef struct MatroskaTrackOperation { | ||
254 | EbmlList combine_planes; | ||
255 | } MatroskaTrackOperation; | ||
256 | |||
257 | typedef struct MatroskaBlockAdditionMapping { | ||
258 | uint64_t value; | ||
259 | char *name; | ||
260 | uint64_t type; | ||
261 | EbmlBin extradata; | ||
262 | } MatroskaBlockAdditionMapping; | ||
263 | |||
264 | typedef struct MatroskaTrack { | ||
265 | uint64_t num; | ||
266 | uint64_t uid; | ||
267 | uint64_t type; | ||
268 | char *name; | ||
269 | char *codec_id; | ||
270 | EbmlBin codec_priv; | ||
271 | char *language; | ||
272 | double time_scale; | ||
273 | uint64_t default_duration; | ||
274 | uint64_t flag_default; | ||
275 | uint64_t flag_forced; | ||
276 | uint64_t flag_comment; | ||
277 | uint64_t flag_hearingimpaired; | ||
278 | uint64_t flag_visualimpaired; | ||
279 | uint64_t flag_textdescriptions; | ||
280 | CountedElement flag_original; | ||
281 | uint64_t seek_preroll; | ||
282 | MatroskaTrackVideo video; | ||
283 | MatroskaTrackAudio audio; | ||
284 | MatroskaTrackOperation operation; | ||
285 | EbmlList encodings; | ||
286 | uint64_t codec_delay; | ||
287 | uint64_t codec_delay_in_track_tb; | ||
288 | |||
289 | AVStream *stream; | ||
290 | int64_t end_timecode; | ||
291 | int ms_compat; | ||
292 | int needs_decoding; | ||
293 | uint64_t max_block_additional_id; | ||
294 | EbmlList block_addition_mappings; | ||
295 | |||
296 | uint32_t palette[AVPALETTE_COUNT]; | ||
297 | int has_palette; | ||
298 | } MatroskaTrack; | ||
299 | |||
300 | typedef struct MatroskaAttachment { | ||
301 | uint64_t uid; | ||
302 | char *filename; | ||
303 | char *description; | ||
304 | char *mime; | ||
305 | EbmlBin bin; | ||
306 | |||
307 | AVStream *stream; | ||
308 | } MatroskaAttachment; | ||
309 | |||
310 | typedef struct MatroskaChapter { | ||
311 | uint64_t start; | ||
312 | uint64_t end; | ||
313 | uint64_t uid; | ||
314 | char *title; | ||
315 | |||
316 | AVChapter *chapter; | ||
317 | } MatroskaChapter; | ||
318 | |||
319 | typedef struct MatroskaIndexPos { | ||
320 | uint64_t track; | ||
321 | uint64_t pos; | ||
322 | } MatroskaIndexPos; | ||
323 | |||
324 | typedef struct MatroskaIndex { | ||
325 | uint64_t time; | ||
326 | EbmlList pos; | ||
327 | } MatroskaIndex; | ||
328 | |||
329 | typedef struct MatroskaTag { | ||
330 | char *name; | ||
331 | char *string; | ||
332 | char *lang; | ||
333 | uint64_t def; | ||
334 | EbmlList sub; | ||
335 | } MatroskaTag; | ||
336 | |||
337 | typedef struct MatroskaTagTarget { | ||
338 | char *type; | ||
339 | uint64_t typevalue; | ||
340 | uint64_t trackuid; | ||
341 | uint64_t chapteruid; | ||
342 | uint64_t attachuid; | ||
343 | } MatroskaTagTarget; | ||
344 | |||
345 | typedef struct MatroskaTags { | ||
346 | MatroskaTagTarget target; | ||
347 | EbmlList tag; | ||
348 | } MatroskaTags; | ||
349 | |||
350 | typedef struct MatroskaSeekhead { | ||
351 | uint64_t id; | ||
352 | uint64_t pos; | ||
353 | } MatroskaSeekhead; | ||
354 | |||
355 | typedef struct MatroskaLevel { | ||
356 | uint64_t start; | ||
357 | uint64_t length; | ||
358 | } MatroskaLevel; | ||
359 | |||
360 | typedef struct MatroskaBlockMore { | ||
361 | uint64_t additional_id; | ||
362 | EbmlBin additional; | ||
363 | } MatroskaBlockMore; | ||
364 | |||
365 | typedef struct MatroskaBlock { | ||
366 | uint64_t duration; | ||
367 | CountedElement reference; | ||
368 | uint64_t non_simple; | ||
369 | EbmlBin bin; | ||
370 | EbmlList blockmore; | ||
371 | int64_t discard_padding; | ||
372 | } MatroskaBlock; | ||
373 | |||
374 | typedef struct MatroskaCluster { | ||
375 | MatroskaBlock block; | ||
376 | uint64_t timecode; | ||
377 | int64_t pos; | ||
378 | } MatroskaCluster; | ||
379 | |||
380 | typedef struct MatroskaLevel1Element { | ||
381 | int64_t pos; | ||
382 | uint32_t id; | ||
383 | int parsed; | ||
384 | } MatroskaLevel1Element; | ||
385 | |||
386 | typedef struct MatroskaDemuxContext { | ||
387 | const AVClass *class; | ||
388 | AVFormatContext *ctx; | ||
389 | |||
390 | /* EBML stuff */ | ||
391 | MatroskaLevel levels[EBML_MAX_DEPTH]; | ||
392 | int num_levels; | ||
393 | uint32_t current_id; | ||
394 | int64_t resync_pos; | ||
395 | int unknown_count; | ||
396 | |||
397 | uint64_t time_scale; | ||
398 | double duration; | ||
399 | char *title; | ||
400 | char *muxingapp; | ||
401 | EbmlBin date_utc; | ||
402 | EbmlList tracks; | ||
403 | EbmlList attachments; | ||
404 | EbmlList chapters; | ||
405 | EbmlList index; | ||
406 | EbmlList tags; | ||
407 | EbmlList seekhead; | ||
408 | |||
409 | /* byte position of the segment inside the stream */ | ||
410 | int64_t segment_start; | ||
411 | |||
412 | /* This packet coincides with FFFormatContext.parse_pkt | ||
413 | * and is not owned by us. */ | ||
414 | AVPacket *pkt; | ||
415 | |||
416 | /* the packet queue */ | ||
417 | PacketList queue; | ||
418 | |||
419 | int done; | ||
420 | |||
421 | /* What to skip before effectively reading a packet. */ | ||
422 | int skip_to_keyframe; | ||
423 | uint64_t skip_to_timecode; | ||
424 | |||
425 | /* File has a CUES element, but we defer parsing until it is needed. */ | ||
426 | int cues_parsing_deferred; | ||
427 | |||
428 | /* Level1 elements and whether they were read yet */ | ||
429 | MatroskaLevel1Element level1_elems[64]; | ||
430 | int num_level1_elems; | ||
431 | |||
432 | MatroskaCluster current_cluster; | ||
433 | |||
434 | int is_webm; | ||
435 | |||
436 | /* WebM DASH Manifest live flag */ | ||
437 | int is_live; | ||
438 | |||
439 | /* Bandwidth value for WebM DASH Manifest */ | ||
440 | int bandwidth; | ||
441 | } MatroskaDemuxContext; | ||
442 | |||
443 | #define CHILD_OF(parent) { .def = { .n = parent } } | ||
444 | |||
445 | // The following forward declarations need their size because | ||
446 | // a tentative definition with internal linkage must not be an | ||
447 | // incomplete type (6.7.2 in C90, 6.9.2 in C99). | ||
448 | // Removing the sizes breaks MSVC. | ||
449 | static EbmlSyntax ebml_syntax[3], matroska_segment[9], matroska_track_video_color[15], matroska_track_video[19], | ||
450 | matroska_track[33], matroska_track_encoding[6], matroska_track_encodings[2], | ||
451 | matroska_track_combine_planes[2], matroska_track_operation[2], matroska_block_addition_mapping[5], matroska_tracks[2], | ||
452 | matroska_attachments[2], matroska_chapter_entry[9], matroska_chapter[6], matroska_chapters[2], | ||
453 | matroska_index_entry[3], matroska_index[2], matroska_tag[3], matroska_tags[2], matroska_seekhead[2], | ||
454 | matroska_blockadditions[2], matroska_blockgroup[8], matroska_cluster_parsing[8]; | ||
455 | |||
456 | static EbmlSyntax ebml_header[] = { | ||
457 | { EBML_ID_EBMLREADVERSION, EBML_UINT, 0, 0, offsetof(Ebml, version), { .u = EBML_VERSION } }, | ||
458 | { EBML_ID_EBMLMAXSIZELENGTH, EBML_UINT, 0, 0, offsetof(Ebml, max_size), { .u = 8 } }, | ||
459 | { EBML_ID_EBMLMAXIDLENGTH, EBML_UINT, 0, 0, offsetof(Ebml, id_length), { .u = 4 } }, | ||
460 | { EBML_ID_DOCTYPE, EBML_STR, 0, 0, offsetof(Ebml, doctype), { .s = "(none)" } }, | ||
461 | { EBML_ID_DOCTYPEREADVERSION, EBML_UINT, 0, 0, offsetof(Ebml, doctype_version), { .u = 1 } }, | ||
462 | { EBML_ID_EBMLVERSION, EBML_NONE }, | ||
463 | { EBML_ID_DOCTYPEVERSION, EBML_NONE }, | ||
464 | CHILD_OF(ebml_syntax) | ||
465 | }; | ||
466 | |||
467 | static EbmlSyntax ebml_syntax[] = { | ||
468 | { EBML_ID_HEADER, EBML_NEST, 0, 0, 0, { .n = ebml_header } }, | ||
469 | { MATROSKA_ID_SEGMENT, EBML_STOP }, | ||
470 | { 0 } | ||
471 | }; | ||
472 | |||
473 | static EbmlSyntax matroska_info[] = { | ||
474 | { MATROSKA_ID_TIMECODESCALE, EBML_UINT, 0, 0, offsetof(MatroskaDemuxContext, time_scale), { .u = 1000000 } }, | ||
475 | { MATROSKA_ID_DURATION, EBML_FLOAT, 0, 0, offsetof(MatroskaDemuxContext, duration) }, | ||
476 | { MATROSKA_ID_TITLE, EBML_UTF8, 0, 0, offsetof(MatroskaDemuxContext, title) }, | ||
477 | { MATROSKA_ID_WRITINGAPP, EBML_NONE }, | ||
478 | { MATROSKA_ID_MUXINGAPP, EBML_UTF8, 0, 0, offsetof(MatroskaDemuxContext, muxingapp) }, | ||
479 | { MATROSKA_ID_DATEUTC, EBML_BIN, 0, 0, offsetof(MatroskaDemuxContext, date_utc) }, | ||
480 | { MATROSKA_ID_SEGMENTUID, EBML_NONE }, | ||
481 | CHILD_OF(matroska_segment) | ||
482 | }; | ||
483 | |||
484 | static EbmlSyntax matroska_mastering_meta[] = { | ||
485 | { MATROSKA_ID_VIDEOCOLOR_RX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, r_x) }, | ||
486 | { MATROSKA_ID_VIDEOCOLOR_RY, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, r_y) }, | ||
487 | { MATROSKA_ID_VIDEOCOLOR_GX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, g_x) }, | ||
488 | { MATROSKA_ID_VIDEOCOLOR_GY, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, g_y) }, | ||
489 | { MATROSKA_ID_VIDEOCOLOR_BX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, b_x) }, | ||
490 | { MATROSKA_ID_VIDEOCOLOR_BY, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, b_y) }, | ||
491 | { MATROSKA_ID_VIDEOCOLOR_WHITEX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, white_x) }, | ||
492 | { MATROSKA_ID_VIDEOCOLOR_WHITEY, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, white_y) }, | ||
493 | { MATROSKA_ID_VIDEOCOLOR_LUMINANCEMIN, EBML_FLOAT, 1, 0, offsetof(MatroskaMasteringMeta, min_luminance) }, | ||
494 | { MATROSKA_ID_VIDEOCOLOR_LUMINANCEMAX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, max_luminance) }, | ||
495 | CHILD_OF(matroska_track_video_color) | ||
496 | }; | ||
497 | |||
498 | static EbmlSyntax matroska_track_video_color[] = { | ||
499 | { MATROSKA_ID_VIDEOCOLORMATRIXCOEFF, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, matrix_coefficients), { .u = AVCOL_SPC_UNSPECIFIED } }, | ||
500 | { MATROSKA_ID_VIDEOCOLORBITSPERCHANNEL, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, bits_per_channel), { .u = 0 } }, | ||
501 | { MATROSKA_ID_VIDEOCOLORCHROMASUBHORZ, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, chroma_sub_horz) }, | ||
502 | { MATROSKA_ID_VIDEOCOLORCHROMASUBVERT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, chroma_sub_vert) }, | ||
503 | { MATROSKA_ID_VIDEOCOLORCBSUBHORZ, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, cb_sub_horz) }, | ||
504 | { MATROSKA_ID_VIDEOCOLORCBSUBVERT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, cb_sub_vert) }, | ||
505 | { MATROSKA_ID_VIDEOCOLORCHROMASITINGHORZ, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, chroma_siting_horz), { .u = MATROSKA_COLOUR_CHROMASITINGHORZ_UNDETERMINED } }, | ||
506 | { MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, chroma_siting_vert), { .u = MATROSKA_COLOUR_CHROMASITINGVERT_UNDETERMINED } }, | ||
507 | { MATROSKA_ID_VIDEOCOLORRANGE, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, range), { .u = AVCOL_RANGE_UNSPECIFIED } }, | ||
508 | { MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, transfer_characteristics), { .u = AVCOL_TRC_UNSPECIFIED } }, | ||
509 | { MATROSKA_ID_VIDEOCOLORPRIMARIES, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, primaries), { .u = AVCOL_PRI_UNSPECIFIED } }, | ||
510 | { MATROSKA_ID_VIDEOCOLORMAXCLL, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, max_cll) }, | ||
511 | { MATROSKA_ID_VIDEOCOLORMAXFALL, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, max_fall) }, | ||
512 | { MATROSKA_ID_VIDEOCOLORMASTERINGMETA, EBML_NEST, 0, 0, offsetof(MatroskaTrackVideoColor, mastering_meta), { .n = matroska_mastering_meta } }, | ||
513 | CHILD_OF(matroska_track_video) | ||
514 | }; | ||
515 | |||
516 | static EbmlSyntax matroska_track_video_projection[] = { | ||
517 | { MATROSKA_ID_VIDEOPROJECTIONTYPE, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoProjection, type), { .u = MATROSKA_VIDEO_PROJECTION_TYPE_RECTANGULAR } }, | ||
518 | { MATROSKA_ID_VIDEOPROJECTIONPRIVATE, EBML_BIN, 0, 0, offsetof(MatroskaTrackVideoProjection, private) }, | ||
519 | { MATROSKA_ID_VIDEOPROJECTIONPOSEYAW, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackVideoProjection, yaw), { .f = 0.0 } }, | ||
520 | { MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackVideoProjection, pitch), { .f = 0.0 } }, | ||
521 | { MATROSKA_ID_VIDEOPROJECTIONPOSEROLL, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackVideoProjection, roll), { .f = 0.0 } }, | ||
522 | CHILD_OF(matroska_track_video) | ||
523 | }; | ||
524 | |||
525 | static EbmlSyntax matroska_track_video[] = { | ||
526 | { MATROSKA_ID_VIDEOFRAMERATE, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackVideo, frame_rate) }, | ||
527 | { MATROSKA_ID_VIDEODISPLAYWIDTH, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, display_width), { .u=-1 } }, | ||
528 | { MATROSKA_ID_VIDEODISPLAYHEIGHT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, display_height), { .u=-1 } }, | ||
529 | { MATROSKA_ID_VIDEOPIXELWIDTH, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, pixel_width) }, | ||
530 | { MATROSKA_ID_VIDEOPIXELHEIGHT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, pixel_height) }, | ||
531 | { MATROSKA_ID_VIDEOCOLORSPACE, EBML_BIN, 0, 0, offsetof(MatroskaTrackVideo, color_space) }, | ||
532 | { MATROSKA_ID_VIDEOALPHAMODE, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, alpha_mode), { .u = 0 } }, | ||
533 | { MATROSKA_ID_VIDEOCOLOR, EBML_NEST, 0, sizeof(MatroskaTrackVideoColor), offsetof(MatroskaTrackVideo, color), { .n = matroska_track_video_color } }, | ||
534 | { MATROSKA_ID_VIDEOPROJECTION, EBML_NEST, 0, 0, offsetof(MatroskaTrackVideo, projection), { .n = matroska_track_video_projection } }, | ||
535 | { MATROSKA_ID_VIDEOPIXELCROPB, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, pixel_cropb), {.u = 0 } }, | ||
536 | { MATROSKA_ID_VIDEOPIXELCROPT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, pixel_cropt), {.u = 0 } }, | ||
537 | { MATROSKA_ID_VIDEOPIXELCROPL, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, pixel_cropl), {.u = 0 } }, | ||
538 | { MATROSKA_ID_VIDEOPIXELCROPR, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, pixel_cropr), {.u = 0 } }, | ||
539 | { MATROSKA_ID_VIDEODISPLAYUNIT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, display_unit), { .u= MATROSKA_VIDEO_DISPLAYUNIT_PIXELS } }, | ||
540 | { MATROSKA_ID_VIDEOFLAGINTERLACED, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, interlaced), { .u = MATROSKA_VIDEO_INTERLACE_FLAG_UNDETERMINED } }, | ||
541 | { MATROSKA_ID_VIDEOFIELDORDER, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, field_order), { .u = MATROSKA_VIDEO_FIELDORDER_UNDETERMINED } }, | ||
542 | { MATROSKA_ID_VIDEOSTEREOMODE, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, stereo_mode), { .u = MATROSKA_VIDEO_STEREOMODE_TYPE_NB } }, | ||
543 | { MATROSKA_ID_VIDEOASPECTRATIO, EBML_NONE }, | ||
544 | CHILD_OF(matroska_track) | ||
545 | }; | ||
546 | |||
547 | static EbmlSyntax matroska_track_audio[] = { | ||
548 | { MATROSKA_ID_AUDIOSAMPLINGFREQ, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackAudio, samplerate), { .f = 8000.0 } }, | ||
549 | { MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackAudio, out_samplerate) }, | ||
550 | { MATROSKA_ID_AUDIOBITDEPTH, EBML_UINT, 0, 0, offsetof(MatroskaTrackAudio, bitdepth) }, | ||
551 | { MATROSKA_ID_AUDIOCHANNELS, EBML_UINT, 0, 0, offsetof(MatroskaTrackAudio, channels), { .u = 1 } }, | ||
552 | CHILD_OF(matroska_track) | ||
553 | }; | ||
554 | |||
555 | static EbmlSyntax matroska_track_encoding_compression[] = { | ||
556 | { MATROSKA_ID_ENCODINGCOMPALGO, EBML_UINT, 0, 0, offsetof(MatroskaTrackCompression, algo), { .u = MATROSKA_TRACK_ENCODING_COMP_ZLIB } }, | ||
557 | { MATROSKA_ID_ENCODINGCOMPSETTINGS, EBML_BIN, 0, 0, offsetof(MatroskaTrackCompression, settings) }, | ||
558 | CHILD_OF(matroska_track_encoding) | ||
559 | }; | ||
560 | |||
561 | static EbmlSyntax matroska_track_encoding_encryption[] = { | ||
562 | { MATROSKA_ID_ENCODINGENCALGO, EBML_UINT, 0, 0, offsetof(MatroskaTrackEncryption,algo), {.u = 0} }, | ||
563 | { MATROSKA_ID_ENCODINGENCKEYID, EBML_BIN, 0, 0, offsetof(MatroskaTrackEncryption,key_id) }, | ||
564 | { MATROSKA_ID_ENCODINGENCAESSETTINGS, EBML_NONE }, | ||
565 | { MATROSKA_ID_ENCODINGSIGALGO, EBML_NONE }, | ||
566 | { MATROSKA_ID_ENCODINGSIGHASHALGO, EBML_NONE }, | ||
567 | { MATROSKA_ID_ENCODINGSIGKEYID, EBML_NONE }, | ||
568 | { MATROSKA_ID_ENCODINGSIGNATURE, EBML_NONE }, | ||
569 | CHILD_OF(matroska_track_encoding) | ||
570 | }; | ||
571 | static EbmlSyntax matroska_track_encoding[] = { | ||
572 | { MATROSKA_ID_ENCODINGSCOPE, EBML_UINT, 0, 0, offsetof(MatroskaTrackEncoding, scope), { .u = 1 } }, | ||
573 | { MATROSKA_ID_ENCODINGTYPE, EBML_UINT, 0, 0, offsetof(MatroskaTrackEncoding, type), { .u = 0 } }, | ||
574 | { MATROSKA_ID_ENCODINGCOMPRESSION, EBML_NEST, 0, 0, offsetof(MatroskaTrackEncoding, compression), { .n = matroska_track_encoding_compression } }, | ||
575 | { MATROSKA_ID_ENCODINGENCRYPTION, EBML_NEST, 0, 0, offsetof(MatroskaTrackEncoding, encryption), { .n = matroska_track_encoding_encryption } }, | ||
576 | { MATROSKA_ID_ENCODINGORDER, EBML_NONE }, | ||
577 | CHILD_OF(matroska_track_encodings) | ||
578 | }; | ||
579 | |||
580 | static EbmlSyntax matroska_track_encodings[] = { | ||
581 | { MATROSKA_ID_TRACKCONTENTENCODING, EBML_NEST, 0, sizeof(MatroskaTrackEncoding), offsetof(MatroskaTrack, encodings), { .n = matroska_track_encoding } }, | ||
582 | CHILD_OF(matroska_track) | ||
583 | }; | ||
584 | |||
585 | static EbmlSyntax matroska_track_plane[] = { | ||
586 | { MATROSKA_ID_TRACKPLANEUID, EBML_UINT, 0, 0, offsetof(MatroskaTrackPlane,uid) }, | ||
587 | { MATROSKA_ID_TRACKPLANETYPE, EBML_UINT, 0, 0, offsetof(MatroskaTrackPlane,type) }, | ||
588 | CHILD_OF(matroska_track_combine_planes) | ||
589 | }; | ||
590 | |||
591 | static EbmlSyntax matroska_track_combine_planes[] = { | ||
592 | { MATROSKA_ID_TRACKPLANE, EBML_NEST, 0, sizeof(MatroskaTrackPlane), offsetof(MatroskaTrackOperation,combine_planes), {.n = matroska_track_plane} }, | ||
593 | CHILD_OF(matroska_track_operation) | ||
594 | }; | ||
595 | |||
596 | static EbmlSyntax matroska_track_operation[] = { | ||
597 | { MATROSKA_ID_TRACKCOMBINEPLANES, EBML_NEST, 0, 0, 0, {.n = matroska_track_combine_planes} }, | ||
598 | CHILD_OF(matroska_track) | ||
599 | }; | ||
600 | |||
601 | static EbmlSyntax matroska_block_addition_mapping[] = { | ||
602 | { MATROSKA_ID_BLKADDIDVALUE, EBML_UINT, 0, 0, offsetof(MatroskaBlockAdditionMapping, value) }, | ||
603 | { MATROSKA_ID_BLKADDIDNAME, EBML_STR, 0, 0, offsetof(MatroskaBlockAdditionMapping, name) }, | ||
604 | { MATROSKA_ID_BLKADDIDTYPE, EBML_UINT, 0, 0, offsetof(MatroskaBlockAdditionMapping, type), { .u = MATROSKA_BLOCK_ADD_ID_TYPE_DEFAULT } }, | ||
605 | { MATROSKA_ID_BLKADDIDEXTRADATA, EBML_BIN, 0, 0, offsetof(MatroskaBlockAdditionMapping, extradata) }, | ||
606 | CHILD_OF(matroska_track) | ||
607 | }; | ||
608 | |||
609 | static EbmlSyntax matroska_track[] = { | ||
610 | { MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, 0, offsetof(MatroskaTrack, num) }, | ||
611 | { MATROSKA_ID_TRACKNAME, EBML_UTF8, 0, 0, offsetof(MatroskaTrack, name) }, | ||
612 | { MATROSKA_ID_TRACKUID, EBML_UINT, 0, 0, offsetof(MatroskaTrack, uid) }, | ||
613 | { MATROSKA_ID_TRACKTYPE, EBML_UINT, 0, 0, offsetof(MatroskaTrack, type) }, | ||
614 | { MATROSKA_ID_CODECID, EBML_STR, 0, 0, offsetof(MatroskaTrack, codec_id) }, | ||
615 | { MATROSKA_ID_CODECPRIVATE, EBML_BIN, 0, 0, offsetof(MatroskaTrack, codec_priv) }, | ||
616 | { MATROSKA_ID_CODECDELAY, EBML_UINT, 0, 0, offsetof(MatroskaTrack, codec_delay), { .u = 0 } }, | ||
617 | { MATROSKA_ID_TRACKLANGUAGE, EBML_STR, 0, 0, offsetof(MatroskaTrack, language), { .s = "eng" } }, | ||
618 | { MATROSKA_ID_TRACKDEFAULTDURATION, EBML_UINT, 0, 0, offsetof(MatroskaTrack, default_duration) }, | ||
619 | { MATROSKA_ID_TRACKTIMECODESCALE, EBML_FLOAT, 0, 0, offsetof(MatroskaTrack, time_scale), { .f = 1.0 } }, | ||
620 | { MATROSKA_ID_TRACKFLAGCOMMENTARY, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_comment), { .u = 0 } }, | ||
621 | { MATROSKA_ID_TRACKFLAGDEFAULT, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_default), { .u = 1 } }, | ||
622 | { MATROSKA_ID_TRACKFLAGFORCED, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_forced), { .u = 0 } }, | ||
623 | { MATROSKA_ID_TRACKFLAGHEARINGIMPAIRED, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_hearingimpaired), { .u = 0 } }, | ||
624 | { MATROSKA_ID_TRACKFLAGVISUALIMPAIRED, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_visualimpaired), { .u = 0 } }, | ||
625 | { MATROSKA_ID_TRACKFLAGTEXTDESCRIPTIONS, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_textdescriptions), { .u = 0 } }, | ||
626 | { MATROSKA_ID_TRACKFLAGORIGINAL, EBML_UINT, 1, 0, offsetof(MatroskaTrack, flag_original), {.u = 0 } }, | ||
627 | { MATROSKA_ID_TRACKVIDEO, EBML_NEST, 0, 0, offsetof(MatroskaTrack, video), { .n = matroska_track_video } }, | ||
628 | { MATROSKA_ID_TRACKAUDIO, EBML_NEST, 0, 0, offsetof(MatroskaTrack, audio), { .n = matroska_track_audio } }, | ||
629 | { MATROSKA_ID_TRACKOPERATION, EBML_NEST, 0, 0, offsetof(MatroskaTrack, operation), { .n = matroska_track_operation } }, | ||
630 | { MATROSKA_ID_TRACKCONTENTENCODINGS, EBML_NEST, 0, 0, 0, { .n = matroska_track_encodings } }, | ||
631 | { MATROSKA_ID_TRACKMAXBLKADDID, EBML_UINT, 0, 0, offsetof(MatroskaTrack, max_block_additional_id), { .u = 0 } }, | ||
632 | { MATROSKA_ID_TRACKBLKADDMAPPING, EBML_NEST, 0, sizeof(MatroskaBlockAdditionMapping), offsetof(MatroskaTrack, block_addition_mappings), { .n = matroska_block_addition_mapping } }, | ||
633 | { MATROSKA_ID_SEEKPREROLL, EBML_UINT, 0, 0, offsetof(MatroskaTrack, seek_preroll), { .u = 0 } }, | ||
634 | { MATROSKA_ID_TRACKFLAGENABLED, EBML_NONE }, | ||
635 | { MATROSKA_ID_TRACKFLAGLACING, EBML_NONE }, | ||
636 | { MATROSKA_ID_CODECNAME, EBML_NONE }, | ||
637 | { MATROSKA_ID_CODECDECODEALL, EBML_NONE }, | ||
638 | { MATROSKA_ID_CODECINFOURL, EBML_NONE }, | ||
639 | { MATROSKA_ID_CODECDOWNLOADURL, EBML_NONE }, | ||
640 | { MATROSKA_ID_TRACKMINCACHE, EBML_NONE }, | ||
641 | { MATROSKA_ID_TRACKMAXCACHE, EBML_NONE }, | ||
642 | CHILD_OF(matroska_tracks) | ||
643 | }; | ||
644 | |||
645 | static EbmlSyntax matroska_tracks[] = { | ||
646 | { MATROSKA_ID_TRACKENTRY, EBML_NEST, 0, sizeof(MatroskaTrack), offsetof(MatroskaDemuxContext, tracks), { .n = matroska_track } }, | ||
647 | CHILD_OF(matroska_segment) | ||
648 | }; | ||
649 | |||
650 | static EbmlSyntax matroska_attachment[] = { | ||
651 | { MATROSKA_ID_FILEUID, EBML_UINT, 0, 0, offsetof(MatroskaAttachment, uid) }, | ||
652 | { MATROSKA_ID_FILENAME, EBML_UTF8, 0, 0, offsetof(MatroskaAttachment, filename) }, | ||
653 | { MATROSKA_ID_FILEMIMETYPE, EBML_STR, 0, 0, offsetof(MatroskaAttachment, mime) }, | ||
654 | { MATROSKA_ID_FILEDATA, EBML_BIN, 0, 0, offsetof(MatroskaAttachment, bin) }, | ||
655 | { MATROSKA_ID_FILEDESC, EBML_UTF8, 0, 0, offsetof(MatroskaAttachment, description) }, | ||
656 | CHILD_OF(matroska_attachments) | ||
657 | }; | ||
658 | |||
659 | static EbmlSyntax matroska_attachments[] = { | ||
660 | { MATROSKA_ID_ATTACHEDFILE, EBML_NEST, 0, sizeof(MatroskaAttachment), offsetof(MatroskaDemuxContext, attachments), { .n = matroska_attachment } }, | ||
661 | CHILD_OF(matroska_segment) | ||
662 | }; | ||
663 | |||
664 | static EbmlSyntax matroska_chapter_display[] = { | ||
665 | { MATROSKA_ID_CHAPSTRING, EBML_UTF8, 0, 0, offsetof(MatroskaChapter, title) }, | ||
666 | { MATROSKA_ID_CHAPLANG, EBML_NONE }, | ||
667 | { MATROSKA_ID_CHAPCOUNTRY, EBML_NONE }, | ||
668 | CHILD_OF(matroska_chapter_entry) | ||
669 | }; | ||
670 | |||
671 | static EbmlSyntax matroska_chapter_entry[] = { | ||
672 | { MATROSKA_ID_CHAPTERTIMESTART, EBML_UINT, 0, 0, offsetof(MatroskaChapter, start), { .u = AV_NOPTS_VALUE } }, | ||
673 | { MATROSKA_ID_CHAPTERTIMEEND, EBML_UINT, 0, 0, offsetof(MatroskaChapter, end), { .u = AV_NOPTS_VALUE } }, | ||
674 | { MATROSKA_ID_CHAPTERUID, EBML_UINT, 0, 0, offsetof(MatroskaChapter, uid) }, | ||
675 | { MATROSKA_ID_CHAPTERDISPLAY, EBML_NEST, 0, 0, 0, { .n = matroska_chapter_display } }, | ||
676 | { MATROSKA_ID_CHAPTERFLAGHIDDEN, EBML_NONE }, | ||
677 | { MATROSKA_ID_CHAPTERFLAGENABLED, EBML_NONE }, | ||
678 | { MATROSKA_ID_CHAPTERPHYSEQUIV, EBML_NONE }, | ||
679 | { MATROSKA_ID_CHAPTERATOM, EBML_NONE }, | ||
680 | CHILD_OF(matroska_chapter) | ||
681 | }; | ||
682 | |||
683 | static EbmlSyntax matroska_chapter[] = { | ||
684 | { MATROSKA_ID_CHAPTERATOM, EBML_NEST, 0, sizeof(MatroskaChapter), offsetof(MatroskaDemuxContext, chapters), { .n = matroska_chapter_entry } }, | ||
685 | { MATROSKA_ID_EDITIONUID, EBML_NONE }, | ||
686 | { MATROSKA_ID_EDITIONFLAGHIDDEN, EBML_NONE }, | ||
687 | { MATROSKA_ID_EDITIONFLAGDEFAULT, EBML_NONE }, | ||
688 | { MATROSKA_ID_EDITIONFLAGORDERED, EBML_NONE }, | ||
689 | CHILD_OF(matroska_chapters) | ||
690 | }; | ||
691 | |||
692 | static EbmlSyntax matroska_chapters[] = { | ||
693 | { MATROSKA_ID_EDITIONENTRY, EBML_NEST, 0, 0, 0, { .n = matroska_chapter } }, | ||
694 | CHILD_OF(matroska_segment) | ||
695 | }; | ||
696 | |||
697 | static EbmlSyntax matroska_index_pos[] = { | ||
698 | { MATROSKA_ID_CUETRACK, EBML_UINT, 0, 0, offsetof(MatroskaIndexPos, track) }, | ||
699 | { MATROSKA_ID_CUECLUSTERPOSITION, EBML_UINT, 0, 0, offsetof(MatroskaIndexPos, pos) }, | ||
700 | { MATROSKA_ID_CUERELATIVEPOSITION,EBML_NONE }, | ||
701 | { MATROSKA_ID_CUEDURATION, EBML_NONE }, | ||
702 | { MATROSKA_ID_CUEBLOCKNUMBER, EBML_NONE }, | ||
703 | CHILD_OF(matroska_index_entry) | ||
704 | }; | ||
705 | |||
706 | static EbmlSyntax matroska_index_entry[] = { | ||
707 | { MATROSKA_ID_CUETIME, EBML_UINT, 0, 0, offsetof(MatroskaIndex, time) }, | ||
708 | { MATROSKA_ID_CUETRACKPOSITION, EBML_NEST, 0, sizeof(MatroskaIndexPos), offsetof(MatroskaIndex, pos), { .n = matroska_index_pos } }, | ||
709 | CHILD_OF(matroska_index) | ||
710 | }; | ||
711 | |||
712 | static EbmlSyntax matroska_index[] = { | ||
713 | { MATROSKA_ID_POINTENTRY, EBML_NEST, 0, sizeof(MatroskaIndex), offsetof(MatroskaDemuxContext, index), { .n = matroska_index_entry } }, | ||
714 | CHILD_OF(matroska_segment) | ||
715 | }; | ||
716 | |||
717 | static EbmlSyntax matroska_simpletag[] = { | ||
718 | { MATROSKA_ID_TAGNAME, EBML_UTF8, 0, 0, offsetof(MatroskaTag, name) }, | ||
719 | { MATROSKA_ID_TAGSTRING, EBML_UTF8, 0, 0, offsetof(MatroskaTag, string) }, | ||
720 | { MATROSKA_ID_TAGLANG, EBML_STR, 0, 0, offsetof(MatroskaTag, lang), { .s = "und" } }, | ||
721 | { MATROSKA_ID_TAGDEFAULT, EBML_UINT, 0, 0, offsetof(MatroskaTag, def) }, | ||
722 | { MATROSKA_ID_TAGDEFAULT_BUG, EBML_UINT, 0, 0, offsetof(MatroskaTag, def) }, | ||
723 | { MATROSKA_ID_SIMPLETAG, EBML_NEST, 0, sizeof(MatroskaTag), offsetof(MatroskaTag, sub), { .n = matroska_simpletag } }, | ||
724 | CHILD_OF(matroska_tag) | ||
725 | }; | ||
726 | |||
727 | static EbmlSyntax matroska_tagtargets[] = { | ||
728 | { MATROSKA_ID_TAGTARGETS_TYPE, EBML_STR, 0, 0, offsetof(MatroskaTagTarget, type) }, | ||
729 | { MATROSKA_ID_TAGTARGETS_TYPEVALUE, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, typevalue), { .u = 50 } }, | ||
730 | { MATROSKA_ID_TAGTARGETS_TRACKUID, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, trackuid), { .u = 0 } }, | ||
731 | { MATROSKA_ID_TAGTARGETS_CHAPTERUID, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, chapteruid), { .u = 0 } }, | ||
732 | { MATROSKA_ID_TAGTARGETS_ATTACHUID, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, attachuid), { .u = 0 } }, | ||
733 | CHILD_OF(matroska_tag) | ||
734 | }; | ||
735 | |||
736 | static EbmlSyntax matroska_tag[] = { | ||
737 | { MATROSKA_ID_SIMPLETAG, EBML_NEST, 0, sizeof(MatroskaTag), offsetof(MatroskaTags, tag), { .n = matroska_simpletag } }, | ||
738 | { MATROSKA_ID_TAGTARGETS, EBML_NEST, 0, 0, offsetof(MatroskaTags, target), { .n = matroska_tagtargets } }, | ||
739 | CHILD_OF(matroska_tags) | ||
740 | }; | ||
741 | |||
742 | static EbmlSyntax matroska_tags[] = { | ||
743 | { MATROSKA_ID_TAG, EBML_NEST, 0, sizeof(MatroskaTags), offsetof(MatroskaDemuxContext, tags), { .n = matroska_tag } }, | ||
744 | CHILD_OF(matroska_segment) | ||
745 | }; | ||
746 | |||
747 | static EbmlSyntax matroska_seekhead_entry[] = { | ||
748 | { MATROSKA_ID_SEEKID, EBML_UINT, 0, 0, offsetof(MatroskaSeekhead, id) }, | ||
749 | { MATROSKA_ID_SEEKPOSITION, EBML_UINT, 0, 0, offsetof(MatroskaSeekhead, pos), { .u = -1 } }, | ||
750 | CHILD_OF(matroska_seekhead) | ||
751 | }; | ||
752 | |||
753 | static EbmlSyntax matroska_seekhead[] = { | ||
754 | { MATROSKA_ID_SEEKENTRY, EBML_NEST, 0, sizeof(MatroskaSeekhead), offsetof(MatroskaDemuxContext, seekhead), { .n = matroska_seekhead_entry } }, | ||
755 | CHILD_OF(matroska_segment) | ||
756 | }; | ||
757 | |||
758 | static EbmlSyntax matroska_segment[] = { | ||
759 | { MATROSKA_ID_CLUSTER, EBML_STOP }, | ||
760 | { MATROSKA_ID_INFO, EBML_LEVEL1, 0, 0, 0, { .n = matroska_info } }, | ||
761 | { MATROSKA_ID_TRACKS, EBML_LEVEL1, 0, 0, 0, { .n = matroska_tracks } }, | ||
762 | { MATROSKA_ID_ATTACHMENTS, EBML_LEVEL1, 0, 0, 0, { .n = matroska_attachments } }, | ||
763 | { MATROSKA_ID_CHAPTERS, EBML_LEVEL1, 0, 0, 0, { .n = matroska_chapters } }, | ||
764 | { MATROSKA_ID_CUES, EBML_LEVEL1, 0, 0, 0, { .n = matroska_index } }, | ||
765 | { MATROSKA_ID_TAGS, EBML_LEVEL1, 0, 0, 0, { .n = matroska_tags } }, | ||
766 | { MATROSKA_ID_SEEKHEAD, EBML_LEVEL1, 0, 0, 0, { .n = matroska_seekhead } }, | ||
767 | { 0 } /* We don't want to go back to level 0, so don't add the parent. */ | ||
768 | }; | ||
769 | |||
770 | static EbmlSyntax matroska_segments[] = { | ||
771 | { MATROSKA_ID_SEGMENT, EBML_NEST, 0, 0, 0, { .n = matroska_segment } }, | ||
772 | { 0 } | ||
773 | }; | ||
774 | |||
775 | static EbmlSyntax matroska_blockmore[] = { | ||
776 | { MATROSKA_ID_BLOCKADDID, EBML_UINT, 0, 0, offsetof(MatroskaBlockMore,additional_id), { .u = MATROSKA_BLOCK_ADD_ID_OPAQUE } }, | ||
777 | { MATROSKA_ID_BLOCKADDITIONAL, EBML_BIN, 0, 0, offsetof(MatroskaBlockMore,additional) }, | ||
778 | CHILD_OF(matroska_blockadditions) | ||
779 | }; | ||
780 | |||
781 | static EbmlSyntax matroska_blockadditions[] = { | ||
782 | { MATROSKA_ID_BLOCKMORE, EBML_NEST, 0, sizeof(MatroskaBlockMore), offsetof(MatroskaBlock, blockmore), { .n = matroska_blockmore } }, | ||
783 | CHILD_OF(matroska_blockgroup) | ||
784 | }; | ||
785 | |||
786 | static EbmlSyntax matroska_blockgroup[] = { | ||
787 | { MATROSKA_ID_BLOCK, EBML_BIN, 0, 0, offsetof(MatroskaBlock, bin) }, | ||
788 | { MATROSKA_ID_BLOCKADDITIONS, EBML_NEST, 0, 0, 0, { .n = matroska_blockadditions} }, | ||
789 | { MATROSKA_ID_BLOCKDURATION, EBML_UINT, 0, 0, offsetof(MatroskaBlock, duration) }, | ||
790 | { MATROSKA_ID_DISCARDPADDING, EBML_SINT, 0, 0, offsetof(MatroskaBlock, discard_padding) }, | ||
791 | { MATROSKA_ID_BLOCKREFERENCE, EBML_SINT, 1, 0, offsetof(MatroskaBlock, reference) }, | ||
792 | { MATROSKA_ID_CODECSTATE, EBML_NONE }, | ||
793 | { 1, EBML_UINT, 0, 0, offsetof(MatroskaBlock, non_simple), { .u = 1 } }, | ||
794 | CHILD_OF(matroska_cluster_parsing) | ||
795 | }; | ||
796 | |||
797 | // The following array contains SimpleBlock and BlockGroup twice | ||
798 | // in order to reuse the other values for matroska_cluster_enter. | ||
799 | static EbmlSyntax matroska_cluster_parsing[] = { | ||
800 | { MATROSKA_ID_SIMPLEBLOCK, EBML_BIN, 0, 0, offsetof(MatroskaBlock, bin) }, | ||
801 | { MATROSKA_ID_BLOCKGROUP, EBML_NEST, 0, 0, 0, { .n = matroska_blockgroup } }, | ||
802 | { MATROSKA_ID_CLUSTERTIMECODE, EBML_UINT, 0, 0, offsetof(MatroskaCluster, timecode) }, | ||
803 | { MATROSKA_ID_SIMPLEBLOCK, EBML_STOP }, | ||
804 | { MATROSKA_ID_BLOCKGROUP, EBML_STOP }, | ||
805 | { MATROSKA_ID_CLUSTERPOSITION, EBML_NONE }, | ||
806 | { MATROSKA_ID_CLUSTERPREVSIZE, EBML_NONE }, | ||
807 | CHILD_OF(matroska_segment) | ||
808 | }; | ||
809 | |||
810 | static EbmlSyntax matroska_cluster_enter[] = { | ||
811 | { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, 0, { .n = &matroska_cluster_parsing[2] } }, | ||
812 | { 0 } | ||
813 | }; | ||
814 | #undef CHILD_OF | ||
815 | |||
816 | static const CodecMime mkv_image_mime_tags[] = { | ||
817 | {"image/gif" , AV_CODEC_ID_GIF}, | ||
818 | {"image/jpeg" , AV_CODEC_ID_MJPEG}, | ||
819 | {"image/png" , AV_CODEC_ID_PNG}, | ||
820 | {"image/tiff" , AV_CODEC_ID_TIFF}, | ||
821 | |||
822 | {"" , AV_CODEC_ID_NONE} | ||
823 | }; | ||
824 | |||
825 | static const CodecMime mkv_mime_tags[] = { | ||
826 | {"application/x-truetype-font", AV_CODEC_ID_TTF}, | ||
827 | {"application/x-font" , AV_CODEC_ID_TTF}, | ||
828 | {"application/vnd.ms-opentype", AV_CODEC_ID_OTF}, | ||
829 | {"binary" , AV_CODEC_ID_BIN_DATA}, | ||
830 | |||
831 | {"" , AV_CODEC_ID_NONE} | ||
832 | }; | ||
833 | |||
834 | static const char * const matroska_video_stereo_plane[MATROSKA_VIDEO_STEREO_PLANE_COUNT] = { | ||
835 | "left", | ||
836 | "right", | ||
837 | "background", | ||
838 | }; | ||
839 | |||
840 | static const char *const matroska_doctypes[] = { "matroska", "webm" }; | ||
841 | |||
842 | /* | ||
843 | * This function prepares the status for parsing of level 1 elements. | ||
844 | */ | ||
845 | 198 | static int matroska_reset_status(MatroskaDemuxContext *matroska, | |
846 | uint32_t id, int64_t position) | ||
847 | { | ||
848 | 198 | int64_t err = 0; | |
849 |
2/2✓ Branch 0 taken 185 times.
✓ Branch 1 taken 13 times.
|
198 | if (position >= 0) { |
850 | 185 | err = avio_seek(matroska->ctx->pb, position, SEEK_SET); | |
851 |
1/2✓ Branch 0 taken 185 times.
✗ Branch 1 not taken.
|
185 | if (err > 0) |
852 | 185 | err = 0; | |
853 | } else | ||
854 | 13 | position = avio_tell(matroska->ctx->pb); | |
855 | |||
856 | 198 | matroska->current_id = id; | |
857 | 198 | matroska->num_levels = 1; | |
858 | 198 | matroska->unknown_count = 0; | |
859 | 198 | matroska->resync_pos = position; | |
860 |
2/2✓ Branch 0 taken 35 times.
✓ Branch 1 taken 163 times.
|
198 | if (id) |
861 | 35 | matroska->resync_pos -= (av_log2(id) + 7) / 8; | |
862 | |||
863 | 198 | return err; | |
864 | } | ||
865 | |||
866 | 13 | static int matroska_resync(MatroskaDemuxContext *matroska, int64_t last_pos) | |
867 | { | ||
868 | 13 | AVIOContext *pb = matroska->ctx->pb; | |
869 | uint32_t id; | ||
870 | |||
871 | /* Try to seek to the last position to resync from. If this doesn't work, | ||
872 | * we resync from the earliest position available: The start of the buffer. */ | ||
873 |
3/4✓ Branch 1 taken 13 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 11 times.
|
13 | if (last_pos < avio_tell(pb) && avio_seek(pb, last_pos + 1, SEEK_SET) < 0) { |
874 | 2 | av_log(matroska->ctx, AV_LOG_WARNING, | |
875 | "Seek to desired resync point failed. Seeking to " | ||
876 | "earliest point available instead.\n"); | ||
877 |
1/2✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
|
2 | avio_seek(pb, FFMAX(avio_tell(pb) + (pb->buffer - pb->buf_ptr), |
878 | last_pos + 1), SEEK_SET); | ||
879 | } | ||
880 | |||
881 | 13 | id = avio_rb32(pb); | |
882 | |||
883 | // try to find a toplevel element | ||
884 |
2/2✓ Branch 1 taken 690589 times.
✓ Branch 2 taken 10 times.
|
690599 | while (!avio_feof(pb)) { |
885 |
3/6✓ Branch 0 taken 690589 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 690589 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 690589 times.
✗ Branch 5 not taken.
|
690589 | if (id == MATROSKA_ID_INFO || id == MATROSKA_ID_TRACKS || |
886 |
3/4✓ Branch 0 taken 690589 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 690587 times.
✓ Branch 3 taken 2 times.
|
690589 | id == MATROSKA_ID_CUES || id == MATROSKA_ID_TAGS || |
887 |
3/4✓ Branch 0 taken 690587 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 690586 times.
✓ Branch 3 taken 1 times.
|
690587 | id == MATROSKA_ID_SEEKHEAD || id == MATROSKA_ID_ATTACHMENTS || |
888 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 690586 times.
|
690586 | id == MATROSKA_ID_CLUSTER || id == MATROSKA_ID_CHAPTERS) { |
889 | /* Prepare the context for parsing of a level 1 element. */ | ||
890 | 3 | matroska_reset_status(matroska, id, -1); | |
891 | /* Given that we are here means that an error has occurred, | ||
892 | * so treat the segment as unknown length in order not to | ||
893 | * discard valid data that happens to be beyond the designated | ||
894 | * end of the segment. */ | ||
895 | 3 | matroska->levels[0].length = EBML_UNKNOWN_LENGTH; | |
896 | 3 | return 0; | |
897 | } | ||
898 | 690586 | id = (id << 8) | avio_r8(pb); | |
899 | } | ||
900 | |||
901 | 10 | matroska->done = 1; | |
902 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | return pb->error ? pb->error : AVERROR_EOF; |
903 | } | ||
904 | |||
905 | /* | ||
906 | * Read: an "EBML number", which is defined as a variable-length | ||
907 | * array of bytes. The first byte indicates the length by giving a | ||
908 | * number of 0-bits followed by a one. The position of the first | ||
909 | * "one" bit inside the first byte indicates the length of this | ||
910 | * number. | ||
911 | * Returns: number of bytes read, < 0 on error | ||
912 | */ | ||
913 | 143374 | static int ebml_read_num(MatroskaDemuxContext *matroska, AVIOContext *pb, | |
914 | int max_size, uint64_t *number, int eof_forbidden) | ||
915 | { | ||
916 | 143374 | int read, n = 1; | |
917 | uint64_t total; | ||
918 | int64_t pos; | ||
919 | |||
920 | /* The first byte tells us the length in bytes - except when it is zero. */ | ||
921 | 143374 | total = avio_r8(pb); | |
922 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 143360 times.
|
143374 | if (pb->eof_reached) |
923 | 14 | goto err; | |
924 | |||
925 | /* get the length of the EBML number */ | ||
926 | 143360 | read = 8 - ff_log2_tab[total]; | |
927 | |||
928 |
2/4✓ Branch 0 taken 143360 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 143360 times.
|
143360 | if (!total || read > max_size) { |
929 | ✗ | pos = avio_tell(pb) - 1; | |
930 | ✗ | if (!total) { | |
931 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
932 | "0x00 at pos %"PRId64" (0x%"PRIx64") invalid as first byte " | ||
933 | "of an EBML number\n", pos, pos); | ||
934 | } else { | ||
935 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
936 | "Length %d indicated by an EBML number's first byte 0x%02x " | ||
937 | "at pos %"PRId64" (0x%"PRIx64") exceeds max length %d.\n", | ||
938 | ✗ | read, (uint8_t) total, pos, pos, max_size); | |
939 | } | ||
940 | ✗ | return AVERROR_INVALIDDATA; | |
941 | } | ||
942 | |||
943 | /* read out length */ | ||
944 | 143360 | total ^= 1 << ff_log2_tab[total]; | |
945 |
2/2✓ Branch 0 taken 71884 times.
✓ Branch 1 taken 143360 times.
|
215244 | while (n++ < read) |
946 | 71884 | total = (total << 8) | avio_r8(pb); | |
947 | |||
948 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 143360 times.
|
143360 | if (pb->eof_reached) { |
949 | ✗ | eof_forbidden = 1; | |
950 | ✗ | goto err; | |
951 | } | ||
952 | |||
953 | 143360 | *number = total; | |
954 | |||
955 | 143360 | return read; | |
956 | |||
957 | 14 | err: | |
958 | 14 | pos = avio_tell(pb); | |
959 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (pb->error) { |
960 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
961 | "Read error at pos. %"PRIu64" (0x%"PRIx64")\n", | ||
962 | pos, pos); | ||
963 | ✗ | return pb->error; | |
964 | } | ||
965 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (eof_forbidden) { |
966 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "File ended prematurely " | |
967 | "at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos); | ||
968 | ✗ | return AVERROR(EIO); | |
969 | } | ||
970 | 14 | return AVERROR_EOF; | |
971 | } | ||
972 | |||
973 | /** | ||
974 | * Read a EBML length value. | ||
975 | * This needs special handling for the "unknown length" case which has multiple | ||
976 | * encodings. | ||
977 | */ | ||
978 | 56153 | static int ebml_read_length(MatroskaDemuxContext *matroska, AVIOContext *pb, | |
979 | uint64_t *number) | ||
980 | { | ||
981 | 56153 | int res = ebml_read_num(matroska, pb, 8, number, 1); | |
982 |
3/4✓ Branch 0 taken 56153 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 56136 times.
|
56153 | if (res > 0 && *number + 1 == 1ULL << (7 * res)) |
983 | 17 | *number = EBML_UNKNOWN_LENGTH; | |
984 | 56153 | return res; | |
985 | } | ||
986 | |||
987 | /* | ||
988 | * Read the next element as an unsigned int. | ||
989 | * Returns NEEDS_CHECKING unless size == 0. | ||
990 | */ | ||
991 | 10768 | static int ebml_read_uint(AVIOContext *pb, int size, | |
992 | uint64_t default_value, uint64_t *num) | ||
993 | { | ||
994 | 10768 | int n = 0; | |
995 | |||
996 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10768 times.
|
10768 | if (size == 0) { |
997 | ✗ | *num = default_value; | |
998 | ✗ | return 0; | |
999 | } | ||
1000 | /* big-endian ordering; build up number */ | ||
1001 | 10768 | *num = 0; | |
1002 |
2/2✓ Branch 0 taken 27214 times.
✓ Branch 1 taken 10768 times.
|
37982 | while (n++ < size) |
1003 | 27214 | *num = (*num << 8) | avio_r8(pb); | |
1004 | |||
1005 | 10768 | return NEEDS_CHECKING; | |
1006 | } | ||
1007 | |||
1008 | /* | ||
1009 | * Read the next element as a signed int. | ||
1010 | * Returns NEEDS_CHECKING unless size == 0. | ||
1011 | */ | ||
1012 | 160 | static int ebml_read_sint(AVIOContext *pb, int size, | |
1013 | int64_t default_value, int64_t *num) | ||
1014 | { | ||
1015 | 160 | int n = 1; | |
1016 | |||
1017 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 160 times.
|
160 | if (size == 0) { |
1018 | ✗ | *num = default_value; | |
1019 | ✗ | return 0; | |
1020 | } else { | ||
1021 | 160 | *num = sign_extend(avio_r8(pb), 8); | |
1022 | |||
1023 | /* big-endian ordering; build up number */ | ||
1024 |
2/2✓ Branch 0 taken 95 times.
✓ Branch 1 taken 160 times.
|
255 | while (n++ < size) |
1025 | 95 | *num = ((uint64_t)*num << 8) | avio_r8(pb); | |
1026 | } | ||
1027 | |||
1028 | 160 | return NEEDS_CHECKING; | |
1029 | } | ||
1030 | |||
1031 | /* | ||
1032 | * Read the next element as a float. | ||
1033 | * Returns 0 if size == 0, NEEDS_CHECKING or < 0 on obvious failure. | ||
1034 | */ | ||
1035 | 756 | static int ebml_read_float(AVIOContext *pb, int size, | |
1036 | double default_value, double *num) | ||
1037 | { | ||
1038 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 756 times.
|
756 | if (size == 0) { |
1039 | ✗ | *num = default_value; | |
1040 | ✗ | return 0; | |
1041 |
2/2✓ Branch 0 taken 86 times.
✓ Branch 1 taken 670 times.
|
756 | } else if (size == 4) { |
1042 | 86 | *num = av_int2float(avio_rb32(pb)); | |
1043 |
1/2✓ Branch 0 taken 670 times.
✗ Branch 1 not taken.
|
670 | } else if (size == 8) { |
1044 | 670 | *num = av_int2double(avio_rb64(pb)); | |
1045 | } else | ||
1046 | ✗ | return AVERROR_INVALIDDATA; | |
1047 | |||
1048 | 756 | return NEEDS_CHECKING; | |
1049 | } | ||
1050 | |||
1051 | /* | ||
1052 | * Read the next element as an ASCII string. | ||
1053 | * 0 is success, < 0 or NEEDS_CHECKING is failure. | ||
1054 | */ | ||
1055 | 2382 | static int ebml_read_ascii(AVIOContext *pb, int size, | |
1056 | const char *default_value, char **str) | ||
1057 | { | ||
1058 | char *res; | ||
1059 | int ret; | ||
1060 | |||
1061 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 2382 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2382 | if (size == 0 && default_value) { |
1062 | ✗ | res = av_strdup(default_value); | |
1063 | ✗ | if (!res) | |
1064 | ✗ | return AVERROR(ENOMEM); | |
1065 | } else { | ||
1066 | /* EBML strings are usually not 0-terminated, so we allocate one | ||
1067 | * byte more, read the string and NUL-terminate it ourselves. */ | ||
1068 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2382 times.
|
2382 | if (!(res = av_malloc(size + 1))) |
1069 | ✗ | return AVERROR(ENOMEM); | |
1070 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2382 times.
|
2382 | if ((ret = avio_read(pb, (uint8_t *) res, size)) != size) { |
1071 | ✗ | av_free(res); | |
1072 | ✗ | return ret < 0 ? ret : NEEDS_CHECKING; | |
1073 | } | ||
1074 | 2382 | (res)[size] = '\0'; | |
1075 | } | ||
1076 | 2382 | av_free(*str); | |
1077 | 2382 | *str = res; | |
1078 | |||
1079 | 2382 | return 0; | |
1080 | } | ||
1081 | |||
1082 | /* | ||
1083 | * Read the next element as binary data. | ||
1084 | * 0 is success, < 0 or NEEDS_CHECKING is failure. | ||
1085 | */ | ||
1086 | 31079 | static int ebml_read_binary(AVIOContext *pb, int length, | |
1087 | int64_t pos, EbmlBin *bin) | ||
1088 | { | ||
1089 | int ret; | ||
1090 | |||
1091 | 31079 | ret = av_buffer_realloc(&bin->buf, length + AV_INPUT_BUFFER_PADDING_SIZE); | |
1092 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31079 times.
|
31079 | if (ret < 0) |
1093 | ✗ | return ret; | |
1094 | 31079 | memset(bin->buf->data + length, 0, AV_INPUT_BUFFER_PADDING_SIZE); | |
1095 | |||
1096 | 31079 | bin->data = bin->buf->data; | |
1097 | 31079 | bin->size = length; | |
1098 | 31079 | bin->pos = pos; | |
1099 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 31069 times.
|
31079 | if ((ret = avio_read(pb, bin->data, length)) != length) { |
1100 | 10 | av_buffer_unref(&bin->buf); | |
1101 | 10 | bin->data = NULL; | |
1102 | 10 | bin->size = 0; | |
1103 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | return ret < 0 ? ret : NEEDS_CHECKING; |
1104 | } | ||
1105 | |||
1106 | 31069 | return 0; | |
1107 | } | ||
1108 | |||
1109 | /* | ||
1110 | * Read the next element, but only the header. The contents | ||
1111 | * are supposed to be sub-elements which can be read separately. | ||
1112 | * 0 is success, < 0 is failure. | ||
1113 | */ | ||
1114 | 7848 | static int ebml_read_master(MatroskaDemuxContext *matroska, | |
1115 | uint64_t length, int64_t pos) | ||
1116 | { | ||
1117 | MatroskaLevel *level; | ||
1118 | |||
1119 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7848 times.
|
7848 | if (matroska->num_levels >= EBML_MAX_DEPTH) { |
1120 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
1121 | "File moves beyond max. allowed depth (%d)\n", EBML_MAX_DEPTH); | ||
1122 | ✗ | return AVERROR(ENOSYS); | |
1123 | } | ||
1124 | |||
1125 | 7848 | level = &matroska->levels[matroska->num_levels++]; | |
1126 | 7848 | level->start = pos; | |
1127 | 7848 | level->length = length; | |
1128 | |||
1129 | 7848 | return 0; | |
1130 | } | ||
1131 | |||
1132 | /* | ||
1133 | * Read a signed "EBML number" | ||
1134 | * Return: number of bytes processed, < 0 on error | ||
1135 | */ | ||
1136 | 236 | static int matroska_ebmlnum_sint(MatroskaDemuxContext *matroska, | |
1137 | AVIOContext *pb, int64_t *num) | ||
1138 | { | ||
1139 | uint64_t unum; | ||
1140 | int res; | ||
1141 | |||
1142 | /* read as unsigned number first */ | ||
1143 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 236 times.
|
236 | if ((res = ebml_read_num(matroska, pb, 8, &unum, 1)) < 0) |
1144 | ✗ | return res; | |
1145 | |||
1146 | /* make signed (weird way) */ | ||
1147 | 236 | *num = unum - ((1LL << (7 * res - 1)) - 1); | |
1148 | |||
1149 | 236 | return res; | |
1150 | } | ||
1151 | |||
1152 | static int ebml_parse(MatroskaDemuxContext *matroska, | ||
1153 | EbmlSyntax *syntax, void *data); | ||
1154 | |||
1155 | 58044 | static EbmlSyntax *ebml_parse_id(EbmlSyntax *syntax, uint32_t id) | |
1156 | { | ||
1157 | int i; | ||
1158 | |||
1159 | // Whoever touches this should be aware of the duplication | ||
1160 | // existing in matroska_cluster_parsing. | ||
1161 |
2/2✓ Branch 0 taken 121918 times.
✓ Branch 1 taken 758 times.
|
122676 | for (i = 0; syntax[i].id; i++) |
1162 |
2/2✓ Branch 0 taken 57286 times.
✓ Branch 1 taken 64632 times.
|
121918 | if (id == syntax[i].id) |
1163 | 57286 | break; | |
1164 | |||
1165 | 58044 | return &syntax[i]; | |
1166 | } | ||
1167 | |||
1168 | 7848 | static int ebml_parse_nest(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, | |
1169 | void *data) | ||
1170 | { | ||
1171 | int res; | ||
1172 | |||
1173 |
1/2✓ Branch 0 taken 7848 times.
✗ Branch 1 not taken.
|
7848 | if (data) { |
1174 |
2/2✓ Branch 0 taken 49911 times.
✓ Branch 1 taken 7848 times.
|
57759 | for (int i = 0; syntax[i].id; i++) { |
1175 | 49911 | void *dst = (char *)data + syntax[i].data_offset; | |
1176 |
5/5✓ Branch 0 taken 21531 times.
✓ Branch 1 taken 968 times.
✓ Branch 2 taken 1441 times.
✓ Branch 3 taken 4048 times.
✓ Branch 4 taken 21923 times.
|
49911 | switch (syntax[i].type) { |
1177 | 21531 | case EBML_UINT: | |
1178 | 21531 | *(uint64_t *)dst = syntax[i].def.u; | |
1179 | 21531 | break; | |
1180 | 968 | case EBML_SINT: | |
1181 | 968 | *(int64_t *) dst = syntax[i].def.i; | |
1182 | 968 | break; | |
1183 | 1441 | case EBML_FLOAT: | |
1184 | 1441 | *(double *) dst = syntax[i].def.f; | |
1185 | 1441 | break; | |
1186 | 4048 | case EBML_STR: | |
1187 | case EBML_UTF8: | ||
1188 | // the default may be NULL | ||
1189 |
2/2✓ Branch 0 taken 1267 times.
✓ Branch 1 taken 2781 times.
|
4048 | if (syntax[i].def.s) { |
1190 | 1267 | *(char**)dst = av_strdup(syntax[i].def.s); | |
1191 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1267 times.
|
1267 | if (!*(char**)dst) |
1192 | ✗ | return AVERROR(ENOMEM); | |
1193 | } | ||
1194 | 4048 | break; | |
1195 | } | ||
1196 | } | ||
1197 | |||
1198 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 7795 times.
|
7848 | if (!matroska->levels[matroska->num_levels - 1].length) { |
1199 | 53 | matroska->num_levels--; | |
1200 | 53 | return 0; | |
1201 | } | ||
1202 | } | ||
1203 | |||
1204 | do { | ||
1205 | 24573 | res = ebml_parse(matroska, syntax, data); | |
1206 |
2/2✓ Branch 0 taken 16778 times.
✓ Branch 1 taken 7795 times.
|
24573 | } while (!res); |
1207 | |||
1208 |
2/2✓ Branch 0 taken 1175 times.
✓ Branch 1 taken 6620 times.
|
7795 | return res == LEVEL_ENDED ? 0 : res; |
1209 | } | ||
1210 | |||
1211 | 2435 | static int is_ebml_id_valid(uint32_t id) | |
1212 | { | ||
1213 | // Due to endian nonsense in Matroska, the highest byte with any bits set | ||
1214 | // will contain the leading length bit. This bit in turn identifies the | ||
1215 | // total byte length of the element by its position within the byte. | ||
1216 | 2435 | unsigned int bits = av_log2(id); | |
1217 |
2/4✓ Branch 0 taken 2435 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2435 times.
✗ Branch 3 not taken.
|
2435 | return id && (bits + 7) / 8 == (8 - bits % 8); |
1218 | } | ||
1219 | |||
1220 | /* | ||
1221 | * Allocate and return the entry for the level1 element with the given ID. If | ||
1222 | * an entry already exists, return the existing entry. | ||
1223 | */ | ||
1224 | 2435 | static MatroskaLevel1Element *matroska_find_level1_elem(MatroskaDemuxContext *matroska, | |
1225 | uint32_t id, int64_t pos) | ||
1226 | { | ||
1227 | int i; | ||
1228 | MatroskaLevel1Element *elem; | ||
1229 | |||
1230 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2435 times.
|
2435 | if (!is_ebml_id_valid(id)) |
1231 | ✗ | return NULL; | |
1232 | |||
1233 | // Some files link to all clusters; useless. | ||
1234 |
2/2✓ Branch 0 taken 25 times.
✓ Branch 1 taken 2410 times.
|
2435 | if (id == MATROSKA_ID_CLUSTER) |
1235 | 25 | return NULL; | |
1236 | |||
1237 | // There can be multiple SeekHeads and Tags. | ||
1238 |
2/2✓ Branch 0 taken 4935 times.
✓ Branch 1 taken 1558 times.
|
6493 | for (i = 0; i < matroska->num_level1_elems; i++) { |
1239 |
2/2✓ Branch 0 taken 860 times.
✓ Branch 1 taken 4075 times.
|
4935 | if (matroska->level1_elems[i].id == id) { |
1240 |
3/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 852 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
860 | if (matroska->level1_elems[i].pos == pos || |
1241 | ✗ | id != MATROSKA_ID_SEEKHEAD && id != MATROSKA_ID_TAGS) | |
1242 | 852 | return &matroska->level1_elems[i]; | |
1243 | } | ||
1244 | } | ||
1245 | |||
1246 | // Only a completely broken file would have more elements. | ||
1247 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1558 times.
|
1558 | if (matroska->num_level1_elems >= FF_ARRAY_ELEMS(matroska->level1_elems)) { |
1248 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "Too many level1 elements.\n"); | |
1249 | ✗ | return NULL; | |
1250 | } | ||
1251 | |||
1252 | 1558 | elem = &matroska->level1_elems[matroska->num_level1_elems++]; | |
1253 | 1558 | *elem = (MatroskaLevel1Element){.id = id}; | |
1254 | |||
1255 | 1558 | return elem; | |
1256 | } | ||
1257 | |||
1258 | 58055 | static int ebml_parse(MatroskaDemuxContext *matroska, | |
1259 | EbmlSyntax *syntax, void *data) | ||
1260 | { | ||
1261 | static const uint64_t max_lengths[EBML_TYPE_COUNT] = { | ||
1262 | // Forbid unknown-length EBML_NONE elements. | ||
1263 | [EBML_NONE] = EBML_UNKNOWN_LENGTH - 1, | ||
1264 | [EBML_UINT] = 8, | ||
1265 | [EBML_SINT] = 8, | ||
1266 | [EBML_FLOAT] = 8, | ||
1267 | // max. 16 MB for strings | ||
1268 | [EBML_STR] = 0x1000000, | ||
1269 | [EBML_UTF8] = 0x1000000, | ||
1270 | // max. 256 MB for binary data | ||
1271 | [EBML_BIN] = 0x10000000, | ||
1272 | // no limits for anything else | ||
1273 | }; | ||
1274 | 58055 | AVIOContext *pb = matroska->ctx->pb; | |
1275 | uint32_t id; | ||
1276 | uint64_t length; | ||
1277 | 58055 | int64_t pos = avio_tell(pb), pos_alt; | |
1278 | 58055 | int res, update_pos = 1, level_check; | |
1279 | MatroskaLevel1Element *level1_elem; | ||
1280 |
2/2✓ Branch 0 taken 57311 times.
✓ Branch 1 taken 744 times.
|
58055 | MatroskaLevel *level = matroska->num_levels ? &matroska->levels[matroska->num_levels - 1] : NULL; |
1281 | |||
1282 |
2/2✓ Branch 0 taken 56086 times.
✓ Branch 1 taken 1969 times.
|
58055 | if (!matroska->current_id) { |
1283 | uint64_t id; | ||
1284 | 56086 | res = ebml_read_num(matroska, pb, 4, &id, 0); | |
1285 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 56072 times.
|
56086 | if (res < 0) { |
1286 |
2/4✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
|
14 | if (pb->eof_reached && res == AVERROR_EOF) { |
1287 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 10 times.
|
14 | if (matroska->is_live) |
1288 | // in live mode, finish parsing if EOF is reached. | ||
1289 | 14 | return 1; | |
1290 |
2/4✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 10 times.
✗ Branch 4 not taken.
|
10 | if (level && pos == avio_tell(pb)) { |
1291 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | if (level->length == EBML_UNKNOWN_LENGTH) { |
1292 | // Unknown-length levels automatically end at EOF. | ||
1293 | 10 | matroska->num_levels--; | |
1294 | 10 | return LEVEL_ENDED; | |
1295 | } else { | ||
1296 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "File ended prematurely " | |
1297 | "at pos. %"PRIu64" (0x%"PRIx64")\n", pos, pos); | ||
1298 | } | ||
1299 | } | ||
1300 | } | ||
1301 | ✗ | return res; | |
1302 | } | ||
1303 | 56072 | matroska->current_id = id | 1 << 7 * res; | |
1304 | 56072 | pos_alt = pos + res; | |
1305 | } else { | ||
1306 | 1969 | pos_alt = pos; | |
1307 | 1969 | pos -= (av_log2(matroska->current_id) + 7) / 8; | |
1308 | } | ||
1309 | |||
1310 | 58041 | id = matroska->current_id; | |
1311 | |||
1312 | 58041 | syntax = ebml_parse_id(syntax, id); | |
1313 |
6/6✓ Branch 0 taken 758 times.
✓ Branch 1 taken 57283 times.
✓ Branch 2 taken 525 times.
✓ Branch 3 taken 233 times.
✓ Branch 4 taken 44 times.
✓ Branch 5 taken 481 times.
|
58041 | if (!syntax->id && id != EBML_ID_VOID && id != EBML_ID_CRC32) { |
1314 |
3/4✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 37 times.
|
44 | if (level && level->length == EBML_UNKNOWN_LENGTH) { |
1315 | // Unknown-length levels end when an element from an upper level | ||
1316 | // in the hierarchy is encountered. | ||
1317 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 4 times.
|
7 | while (syntax->def.n) { |
1318 | 3 | syntax = ebml_parse_id(syntax->def.n, id); | |
1319 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (syntax->id) { |
1320 | 3 | matroska->num_levels--; | |
1321 | 3 | return LEVEL_ENDED; | |
1322 | } | ||
1323 | // We have not encountered a known element; syntax is a sentinel. | ||
1324 | av_assert1(syntax->type == EBML_NONE); | ||
1325 | }; | ||
1326 | } | ||
1327 | |||
1328 | 41 | av_log(matroska->ctx, AV_LOG_DEBUG, "Unknown entry 0x%"PRIX32" at pos. " | |
1329 | "%"PRId64"\n", id, pos); | ||
1330 | 41 | update_pos = 0; /* Don't update resync_pos as an error might have happened. */ | |
1331 | } | ||
1332 | |||
1333 |
2/2✓ Branch 0 taken 56896 times.
✓ Branch 1 taken 1142 times.
|
58038 | if (data) { |
1334 | 56896 | data = (char *) data + syntax->data_offset; | |
1335 |
2/2✓ Branch 0 taken 3739 times.
✓ Branch 1 taken 53157 times.
|
56896 | if (syntax->list_elem_size) { |
1336 | 3739 | EbmlList *list = data; | |
1337 | void *newelem; | ||
1338 | |||
1339 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3739 times.
|
3739 | if ((unsigned)list->nb_elem + 1 >= UINT_MAX / syntax->list_elem_size) |
1340 | ✗ | return AVERROR(ENOMEM); | |
1341 | 3739 | newelem = av_fast_realloc(list->elem, | |
1342 | &list->alloc_elem_size, | ||
1343 | 3739 | (list->nb_elem + 1) * syntax->list_elem_size); | |
1344 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3739 times.
|
3739 | if (!newelem) |
1345 | ✗ | return AVERROR(ENOMEM); | |
1346 | 3739 | list->elem = newelem; | |
1347 | 3739 | data = (char *) list->elem + list->nb_elem * syntax->list_elem_size; | |
1348 | 3739 | memset(data, 0, syntax->list_elem_size); | |
1349 | 3739 | list->nb_elem++; | |
1350 | } | ||
1351 | } | ||
1352 | |||
1353 |
2/2✓ Branch 0 taken 56064 times.
✓ Branch 1 taken 1974 times.
|
58038 | if (syntax->type != EBML_STOP) { |
1354 | 56064 | matroska->current_id = 0; | |
1355 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 56064 times.
|
56064 | if ((res = ebml_read_length(matroska, pb, &length)) < 0) |
1356 | ✗ | return res; | |
1357 | |||
1358 | 56064 | pos_alt += res; | |
1359 | |||
1360 |
2/2✓ Branch 0 taken 55320 times.
✓ Branch 1 taken 744 times.
|
56064 | if (matroska->num_levels > 0) { |
1361 |
2/2✓ Branch 0 taken 55314 times.
✓ Branch 1 taken 6 times.
|
55320 | if (length != EBML_UNKNOWN_LENGTH && |
1362 |
2/2✓ Branch 0 taken 55204 times.
✓ Branch 1 taken 110 times.
|
110518 | level->length != EBML_UNKNOWN_LENGTH) { |
1363 | 55204 | uint64_t elem_end = pos_alt + length, | |
1364 | 55204 | level_end = level->start + level->length; | |
1365 | |||
1366 |
2/2✓ Branch 0 taken 47557 times.
✓ Branch 1 taken 7647 times.
|
55204 | if (elem_end < level_end) { |
1367 | 47557 | level_check = 0; | |
1368 |
1/2✓ Branch 0 taken 7647 times.
✗ Branch 1 not taken.
|
7647 | } else if (elem_end == level_end) { |
1369 | 7647 | level_check = LEVEL_ENDED; | |
1370 | } else { | ||
1371 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
1372 | "Element at 0x%"PRIx64" ending at 0x%"PRIx64" exceeds " | ||
1373 | "containing master element ending at 0x%"PRIx64"\n", | ||
1374 | pos, elem_end, level_end); | ||
1375 | ✗ | return AVERROR_INVALIDDATA; | |
1376 | } | ||
1377 |
2/2✓ Branch 0 taken 110 times.
✓ Branch 1 taken 6 times.
|
116 | } else if (length != EBML_UNKNOWN_LENGTH) { |
1378 | 110 | level_check = 0; | |
1379 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | } else if (level->length != EBML_UNKNOWN_LENGTH) { |
1380 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "Unknown-sized element " | |
1381 | "at 0x%"PRIx64" inside parent with finite size\n", pos); | ||
1382 | ✗ | return AVERROR_INVALIDDATA; | |
1383 | } else { | ||
1384 | 6 | level_check = 0; | |
1385 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
6 | if (id != MATROSKA_ID_CLUSTER && (syntax->type == EBML_LEVEL1 |
1386 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | || syntax->type == EBML_NEST)) { |
1387 | // According to the current specifications only clusters and | ||
1388 | // segments are allowed to be unknown-length. We also accept | ||
1389 | // other unknown-length master elements. | ||
1390 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, | |
1391 | "Found unknown-length element 0x%"PRIX32" other than " | ||
1392 | "a cluster at 0x%"PRIx64". Spec-incompliant, but " | ||
1393 | "parsing will nevertheless be attempted.\n", id, pos); | ||
1394 | ✗ | update_pos = -1; | |
1395 | } | ||
1396 | } | ||
1397 | } else | ||
1398 | 744 | level_check = 0; | |
1399 | |||
1400 |
4/4✓ Branch 0 taken 47886 times.
✓ Branch 1 taken 8178 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 47884 times.
|
56064 | if (max_lengths[syntax->type] && length > max_lengths[syntax->type]) { |
1401 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (length != EBML_UNKNOWN_LENGTH) { |
1402 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
1403 | "Invalid length 0x%"PRIx64" > 0x%"PRIx64" for element " | ||
1404 | "with ID 0x%"PRIX32" at 0x%"PRIx64"\n", | ||
1405 | ✗ | length, max_lengths[syntax->type], id, pos); | |
1406 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | } else if (syntax->type != EBML_NONE) { |
1407 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
1408 | "Element with ID 0x%"PRIX32" at pos. 0x%"PRIx64" has " | ||
1409 | "unknown length, yet the length of an element of its " | ||
1410 | "type must be known.\n", id, pos); | ||
1411 | } else { | ||
1412 | 2 | av_log(matroska->ctx, AV_LOG_ERROR, | |
1413 | "Found unknown-length element with ID 0x%"PRIX32" at " | ||
1414 | "pos. 0x%"PRIx64" for which no syntax for parsing is " | ||
1415 | "available.\n", id, pos); | ||
1416 | } | ||
1417 | 2 | return AVERROR_INVALIDDATA; | |
1418 | } | ||
1419 | |||
1420 |
2/2✓ Branch 0 taken 130 times.
✓ Branch 1 taken 55932 times.
|
56062 | if (!(pb->seekable & AVIO_SEEKABLE_NORMAL)) { |
1421 | // Loosing sync will likely manifest itself as encountering unknown | ||
1422 | // elements which are not reliably distinguishable from elements | ||
1423 | // belonging to future extensions of the format. | ||
1424 | // We use a heuristic to detect such situations: If the current | ||
1425 | // element is not expected at the current syntax level and there | ||
1426 | // were only a few unknown elements in a row, then the element is | ||
1427 | // skipped or considered defective based upon the length of the | ||
1428 | // current element (i.e. how much would be skipped); if there were | ||
1429 | // more than a few skipped elements in a row and skipping the current | ||
1430 | // element would lead us more than SKIP_THRESHOLD away from the last | ||
1431 | // known good position, then it is inferred that an error occurred. | ||
1432 | // The dependency on the number of unknown elements in a row exists | ||
1433 | // because the distance to the last known good position is | ||
1434 | // automatically big if the last parsed element was big. | ||
1435 | // In both cases, each unknown element is considered equivalent to | ||
1436 | // UNKNOWN_EQUIV of skipped bytes for the check. | ||
1437 | // The whole check is only done for non-seekable output, because | ||
1438 | // in this situation skipped data can't simply be rechecked later. | ||
1439 | // This is especially important when using unkown length elements | ||
1440 | // as the check for whether a child exceeds its containing master | ||
1441 | // element is not effective in this situation. | ||
1442 |
2/2✓ Branch 0 taken 128 times.
✓ Branch 1 taken 2 times.
|
130 | if (update_pos) { |
1443 | 128 | matroska->unknown_count = 0; | |
1444 | } else { | ||
1445 | 2 | int64_t dist = length + UNKNOWN_EQUIV * matroska->unknown_count++; | |
1446 | |||
1447 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (matroska->unknown_count > 3) |
1448 | ✗ | dist += pos_alt - matroska->resync_pos; | |
1449 | |||
1450 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (dist > SKIP_THRESHOLD) { |
1451 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
1452 | "Unknown element %"PRIX32" at pos. 0x%"PRIx64" with " | ||
1453 | "length 0x%"PRIx64" considered as invalid data. Last " | ||
1454 | "known good position 0x%"PRIx64", %d unknown elements" | ||
1455 | " in a row\n", id, pos, length, matroska->resync_pos, | ||
1456 | matroska->unknown_count); | ||
1457 | ✗ | return AVERROR_INVALIDDATA; | |
1458 | } | ||
1459 | } | ||
1460 | } | ||
1461 | |||
1462 |
2/2✓ Branch 0 taken 56023 times.
✓ Branch 1 taken 39 times.
|
56062 | if (update_pos > 0) { |
1463 | // We have found an element that is allowed at this place | ||
1464 | // in the hierarchy and it passed all checks, so treat the beginning | ||
1465 | // of the element as the "last known good" position. | ||
1466 | 56023 | matroska->resync_pos = pos; | |
1467 | } | ||
1468 | |||
1469 |
3/4✓ Branch 0 taken 337 times.
✓ Branch 1 taken 55725 times.
✓ Branch 2 taken 337 times.
✗ Branch 3 not taken.
|
56062 | if (!data && length != EBML_UNKNOWN_LENGTH) |
1470 | 337 | goto skip; | |
1471 | } | ||
1472 | |||
1473 |
8/8✓ Branch 0 taken 10768 times.
✓ Branch 1 taken 160 times.
✓ Branch 2 taken 756 times.
✓ Branch 3 taken 2382 times.
✓ Branch 4 taken 31079 times.
✓ Branch 5 taken 7848 times.
✓ Branch 6 taken 1974 times.
✓ Branch 7 taken 2732 times.
|
57699 | switch (syntax->type) { |
1474 | 10768 | case EBML_UINT: | |
1475 | 10768 | res = ebml_read_uint(pb, length, syntax->def.u, data); | |
1476 | 10768 | break; | |
1477 | 160 | case EBML_SINT: | |
1478 | 160 | res = ebml_read_sint(pb, length, syntax->def.i, data); | |
1479 | 160 | break; | |
1480 | 756 | case EBML_FLOAT: | |
1481 | 756 | res = ebml_read_float(pb, length, syntax->def.f, data); | |
1482 | 756 | break; | |
1483 | 2382 | case EBML_STR: | |
1484 | case EBML_UTF8: | ||
1485 | 2382 | res = ebml_read_ascii(pb, length, syntax->def.s, data); | |
1486 | 2382 | break; | |
1487 | 31079 | case EBML_BIN: | |
1488 | 31079 | res = ebml_read_binary(pb, length, pos_alt, data); | |
1489 | 31079 | break; | |
1490 | 7848 | case EBML_LEVEL1: | |
1491 | case EBML_NEST: | ||
1492 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7848 times.
|
7848 | if ((res = ebml_read_master(matroska, length, pos_alt)) < 0) |
1493 | ✗ | return res; | |
1494 |
2/2✓ Branch 0 taken 372 times.
✓ Branch 1 taken 7476 times.
|
7848 | if (id == MATROSKA_ID_SEGMENT) |
1495 | 372 | matroska->segment_start = pos_alt; | |
1496 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 7828 times.
|
7848 | if (id == MATROSKA_ID_CUES) |
1497 | 20 | matroska->cues_parsing_deferred = 0; | |
1498 |
3/4✓ Branch 0 taken 1239 times.
✓ Branch 1 taken 6609 times.
✓ Branch 2 taken 1239 times.
✗ Branch 3 not taken.
|
9087 | if (syntax->type == EBML_LEVEL1 && |
1499 | 1239 | (level1_elem = matroska_find_level1_elem(matroska, syntax->id, pos))) { | |
1500 |
2/2✓ Branch 0 taken 1217 times.
✓ Branch 1 taken 22 times.
|
1239 | if (!level1_elem->pos) { |
1501 | // Zero is not a valid position for a level 1 element. | ||
1502 | 1217 | level1_elem->pos = pos; | |
1503 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
|
22 | } else if (level1_elem->pos != pos) |
1504 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "Duplicate element\n"); | |
1505 | 1239 | level1_elem->parsed = 1; | |
1506 | } | ||
1507 |
2/2✓ Branch 1 taken 1175 times.
✓ Branch 2 taken 6673 times.
|
7848 | if (res = ebml_parse_nest(matroska, syntax->def.n, data)) |
1508 | 1175 | return res; | |
1509 | 6673 | break; | |
1510 | 1974 | case EBML_STOP: | |
1511 | 1974 | return 1; | |
1512 | 337 | skip: | |
1513 | 3069 | default: | |
1514 |
2/2✓ Branch 0 taken 3067 times.
✓ Branch 1 taken 2 times.
|
3069 | if (length) { |
1515 | int64_t res2; | ||
1516 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3067 times.
|
3067 | if (ffio_limit(pb, length) != length) { |
1517 | // ffio_limit emits its own error message, | ||
1518 | // so we don't have to. | ||
1519 | ✗ | return AVERROR(EIO); | |
1520 | } | ||
1521 |
1/2✓ Branch 1 taken 3067 times.
✗ Branch 2 not taken.
|
3067 | if ((res2 = avio_skip(pb, length - 1)) >= 0) { |
1522 | // avio_skip might take us past EOF. We check for this | ||
1523 | // by skipping only length - 1 bytes, reading a byte and | ||
1524 | // checking the error flags. This is done in order to check | ||
1525 | // that the element has been properly skipped even when | ||
1526 | // no filesize (that ffio_limit relies on) is available. | ||
1527 | 3067 | avio_r8(pb); | |
1528 | 3067 | res = NEEDS_CHECKING; | |
1529 | } else | ||
1530 | ✗ | res = res2; | |
1531 | } else | ||
1532 | 2 | res = 0; | |
1533 | } | ||
1534 |
2/2✓ Branch 0 taken 14761 times.
✓ Branch 1 taken 40126 times.
|
54887 | if (res) { |
1535 |
1/2✓ Branch 0 taken 14761 times.
✗ Branch 1 not taken.
|
14761 | if (res == NEEDS_CHECKING) { |
1536 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 14751 times.
|
14761 | if (pb->eof_reached) { |
1537 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (pb->error) |
1538 | ✗ | res = pb->error; | |
1539 | else | ||
1540 | 10 | res = AVERROR_EOF; | |
1541 | } else | ||
1542 | 14751 | goto level_check; | |
1543 | } | ||
1544 | |||
1545 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (res == AVERROR_INVALIDDATA) |
1546 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "Invalid element\n"); | |
1547 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | else if (res == AVERROR(EIO)) |
1548 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "Read error\n"); | |
1549 |
1/2✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
|
10 | else if (res == AVERROR_EOF) { |
1550 | 10 | av_log(matroska->ctx, AV_LOG_ERROR, "File ended prematurely\n"); | |
1551 | 10 | res = AVERROR(EIO); | |
1552 | } | ||
1553 | |||
1554 | 10 | return res; | |
1555 | } | ||
1556 | |||
1557 | 40126 | level_check: | |
1558 |
3/4✓ Branch 0 taken 144 times.
✓ Branch 1 taken 54733 times.
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
|
54877 | if (syntax->is_counted && data) { |
1559 | 144 | CountedElement *elem = data; | |
1560 |
1/2✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
|
144 | if (elem->count != UINT_MAX) |
1561 | 144 | elem->count++; | |
1562 | } | ||
1563 | |||
1564 |
4/4✓ Branch 0 taken 7582 times.
✓ Branch 1 taken 47295 times.
✓ Branch 2 taken 7552 times.
✓ Branch 3 taken 30 times.
|
54877 | if (level_check == LEVEL_ENDED && matroska->num_levels) { |
1565 | 7552 | level = &matroska->levels[matroska->num_levels - 1]; | |
1566 | 7552 | pos = avio_tell(pb); | |
1567 | |||
1568 | // Given that pos >= level->start no check for | ||
1569 | // level->length != EBML_UNKNOWN_LENGTH is necessary. | ||
1570 |
4/4✓ Branch 0 taken 14451 times.
✓ Branch 1 taken 731 times.
✓ Branch 2 taken 7630 times.
✓ Branch 3 taken 6821 times.
|
15182 | while (matroska->num_levels && pos == level->start + level->length) { |
1571 | 7630 | matroska->num_levels--; | |
1572 | 7630 | level--; | |
1573 | } | ||
1574 | } | ||
1575 | |||
1576 | 54877 | return level_check; | |
1577 | } | ||
1578 | |||
1579 | 72348 | static void ebml_free(EbmlSyntax *syntax, void *data) | |
1580 | { | ||
1581 | int i, j; | ||
1582 |
2/2✓ Branch 0 taken 299933 times.
✓ Branch 1 taken 72348 times.
|
372281 | for (i = 0; syntax[i].id; i++) { |
1583 | 299933 | void *data_off = (char *) data + syntax[i].data_offset; | |
1584 |
4/4✓ Branch 0 taken 4042 times.
✓ Branch 1 taken 32645 times.
✓ Branch 2 taken 73082 times.
✓ Branch 3 taken 190164 times.
|
299933 | switch (syntax[i].type) { |
1585 | 4042 | case EBML_STR: | |
1586 | case EBML_UTF8: | ||
1587 | 4042 | av_freep(data_off); | |
1588 | 4042 | break; | |
1589 | 32645 | case EBML_BIN: | |
1590 | 32645 | av_buffer_unref(&((EbmlBin *) data_off)->buf); | |
1591 | 32645 | break; | |
1592 | 73082 | case EBML_LEVEL1: | |
1593 | case EBML_NEST: | ||
1594 |
2/2✓ Branch 0 taken 35979 times.
✓ Branch 1 taken 37103 times.
|
73082 | if (syntax[i].list_elem_size) { |
1595 | 35979 | EbmlList *list = data_off; | |
1596 | 35979 | char *ptr = list->elem; | |
1597 |
2/2✓ Branch 0 taken 3739 times.
✓ Branch 1 taken 35979 times.
|
39718 | for (j = 0; j < list->nb_elem; |
1598 | 3739 | j++, ptr += syntax[i].list_elem_size) | |
1599 | 3739 | ebml_free(syntax[i].def.n, ptr); | |
1600 | 35979 | av_freep(&list->elem); | |
1601 | 35979 | list->nb_elem = 0; | |
1602 | 35979 | list->alloc_elem_size = 0; | |
1603 | } else | ||
1604 | 37103 | ebml_free(syntax[i].def.n, data_off); | |
1605 | default: | ||
1606 | 263246 | break; | |
1607 | } | ||
1608 | } | ||
1609 | 72348 | } | |
1610 | |||
1611 | /* | ||
1612 | * Autodetecting... | ||
1613 | */ | ||
1614 | 7235 | static int matroska_probe(const AVProbeData *p) | |
1615 | { | ||
1616 | 7235 | uint64_t total = 0; | |
1617 | 7235 | int len_mask = 0x80, size = 1, n = 1, i; | |
1618 | |||
1619 | /* EBML header? */ | ||
1620 |
2/2✓ Branch 0 taken 6885 times.
✓ Branch 1 taken 350 times.
|
7235 | if (AV_RB32(p->buf) != EBML_ID_HEADER) |
1621 | 6885 | return 0; | |
1622 | |||
1623 | /* length of header */ | ||
1624 | 350 | total = p->buf[4]; | |
1625 |
3/4✓ Branch 0 taken 2086 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1736 times.
✓ Branch 3 taken 350 times.
|
2086 | while (size <= 8 && !(total & len_mask)) { |
1626 | 1736 | size++; | |
1627 | 1736 | len_mask >>= 1; | |
1628 | } | ||
1629 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 350 times.
|
350 | if (size > 8) |
1630 | ✗ | return 0; | |
1631 | 350 | total &= (len_mask - 1); | |
1632 |
2/2✓ Branch 0 taken 1736 times.
✓ Branch 1 taken 350 times.
|
2086 | while (n < size) |
1633 | 1736 | total = (total << 8) | p->buf[4 + n++]; | |
1634 | |||
1635 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 350 times.
|
350 | if (total + 1 == 1ULL << (7 * size)){ |
1636 | /* Unknown-length header - simply parse the whole buffer. */ | ||
1637 | ✗ | total = p->buf_size - 4 - size; | |
1638 | } else { | ||
1639 | /* Does the probe data contain the whole header? */ | ||
1640 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 350 times.
|
350 | if (p->buf_size < 4 + size + total) |
1641 | ✗ | return 0; | |
1642 | } | ||
1643 | |||
1644 | /* The header should contain a known document type. For now, | ||
1645 | * we don't parse the whole header but simply check for the | ||
1646 | * availability of that array of characters inside the header. | ||
1647 | * Not fully fool-proof, but good enough. */ | ||
1648 |
1/2✓ Branch 0 taken 601 times.
✗ Branch 1 not taken.
|
601 | for (i = 0; i < FF_ARRAY_ELEMS(matroska_doctypes); i++) { |
1649 | 601 | size_t probelen = strlen(matroska_doctypes[i]); | |
1650 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 601 times.
|
601 | if (total < probelen) |
1651 | ✗ | continue; | |
1652 |
2/2✓ Branch 0 taken 12982 times.
✓ Branch 1 taken 251 times.
|
13233 | for (n = 4 + size; n <= 4 + size + total - probelen; n++) |
1653 |
2/2✓ Branch 0 taken 350 times.
✓ Branch 1 taken 12632 times.
|
12982 | if (!memcmp(p->buf + n, matroska_doctypes[i], probelen)) |
1654 | 350 | return AVPROBE_SCORE_MAX; | |
1655 | } | ||
1656 | |||
1657 | // probably valid EBML header but no recognized doctype | ||
1658 | ✗ | return AVPROBE_SCORE_EXTENSION; | |
1659 | } | ||
1660 | |||
1661 | 31403 | static MatroskaTrack *matroska_find_track_by_num(MatroskaDemuxContext *matroska, | |
1662 | uint64_t num) | ||
1663 | { | ||
1664 | 31403 | MatroskaTrack *tracks = matroska->tracks.elem; | |
1665 | int i; | ||
1666 | |||
1667 |
2/2✓ Branch 0 taken 34523 times.
✓ Branch 1 taken 1 times.
|
34524 | for (i = 0; i < matroska->tracks.nb_elem; i++) |
1668 |
2/2✓ Branch 0 taken 31402 times.
✓ Branch 1 taken 3121 times.
|
34523 | if (tracks[i].num == num) |
1669 | 31402 | return &tracks[i]; | |
1670 | |||
1671 | 1 | av_log(matroska->ctx, AV_LOG_ERROR, "Invalid track number %"PRIu64"\n", num); | |
1672 | 1 | return NULL; | |
1673 | } | ||
1674 | |||
1675 | 82 | static int matroska_decode_buffer(uint8_t **buf, int *buf_size, | |
1676 | MatroskaTrack *track) | ||
1677 | { | ||
1678 | 82 | MatroskaTrackEncoding *encodings = track->encodings.elem; | |
1679 | 82 | uint8_t *data = *buf; | |
1680 | 82 | int isize = *buf_size; | |
1681 | 82 | uint8_t *pkt_data = NULL; | |
1682 | uint8_t av_unused *newpktdata; | ||
1683 | 82 | int pkt_size = isize; | |
1684 | 82 | int result = 0; | |
1685 | int olen; | ||
1686 | |||
1687 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 82 times.
|
82 | if (pkt_size >= 10000000U) |
1688 | ✗ | return AVERROR_INVALIDDATA; | |
1689 | |||
1690 |
4/5✓ Branch 0 taken 70 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
82 | switch (encodings[0].compression.algo) { |
1691 | 70 | case MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP: | |
1692 | { | ||
1693 | 70 | int header_size = encodings[0].compression.settings.size; | |
1694 | 70 | uint8_t *header = encodings[0].compression.settings.data; | |
1695 | |||
1696 |
2/4✓ Branch 0 taken 70 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 70 times.
|
70 | if (header_size && !header) { |
1697 | ✗ | av_log(NULL, AV_LOG_ERROR, "Compression size but no data in headerstrip\n"); | |
1698 | ✗ | return -1; | |
1699 | } | ||
1700 | |||
1701 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
|
70 | if (!header_size) |
1702 | ✗ | return 0; | |
1703 | |||
1704 | 70 | pkt_size = isize + header_size; | |
1705 | 70 | pkt_data = av_malloc(pkt_size + AV_INPUT_BUFFER_PADDING_SIZE); | |
1706 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 70 times.
|
70 | if (!pkt_data) |
1707 | ✗ | return AVERROR(ENOMEM); | |
1708 | |||
1709 | 70 | memcpy(pkt_data, header, header_size); | |
1710 | 70 | memcpy(pkt_data + header_size, data, isize); | |
1711 | 70 | break; | |
1712 | } | ||
1713 | 15 | case MATROSKA_TRACK_ENCODING_COMP_LZO: | |
1714 | do { | ||
1715 | 15 | int insize = isize; | |
1716 | 15 | olen = pkt_size *= 3; | |
1717 | 15 | newpktdata = av_realloc(pkt_data, pkt_size + AV_LZO_OUTPUT_PADDING | |
1718 | 15 | + AV_INPUT_BUFFER_PADDING_SIZE); | |
1719 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15 times.
|
15 | if (!newpktdata) { |
1720 | ✗ | result = AVERROR(ENOMEM); | |
1721 | ✗ | goto failed; | |
1722 | } | ||
1723 | 15 | pkt_data = newpktdata; | |
1724 | 15 | result = av_lzo1x_decode(pkt_data, &olen, data, &insize); | |
1725 |
3/4✓ Branch 0 taken 11 times.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 11 times.
✗ Branch 3 not taken.
|
15 | } while (result == AV_LZO_OUTPUT_FULL && pkt_size < 10000000); |
1726 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (result) { |
1727 | ✗ | result = AVERROR_INVALIDDATA; | |
1728 | ✗ | goto failed; | |
1729 | } | ||
1730 | 4 | pkt_size -= olen; | |
1731 | 4 | break; | |
1732 | #if CONFIG_ZLIB | ||
1733 | 6 | case MATROSKA_TRACK_ENCODING_COMP_ZLIB: | |
1734 | { | ||
1735 | 6 | z_stream zstream = { 0 }; | |
1736 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 6 times.
|
6 | if (!pkt_size || inflateInit(&zstream) != Z_OK) |
1737 | ✗ | return -1; | |
1738 | 6 | zstream.next_in = data; | |
1739 | 6 | zstream.avail_in = isize; | |
1740 | do { | ||
1741 | 8 | pkt_size *= 3; | |
1742 | 8 | newpktdata = av_realloc(pkt_data, pkt_size + AV_INPUT_BUFFER_PADDING_SIZE); | |
1743 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (!newpktdata) { |
1744 | ✗ | inflateEnd(&zstream); | |
1745 | ✗ | result = AVERROR(ENOMEM); | |
1746 | ✗ | goto failed; | |
1747 | } | ||
1748 | 8 | pkt_data = newpktdata; | |
1749 | 8 | zstream.avail_out = pkt_size - zstream.total_out; | |
1750 | 8 | zstream.next_out = pkt_data + zstream.total_out; | |
1751 | 8 | result = inflate(&zstream, Z_NO_FLUSH); | |
1752 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
8 | } while (result == Z_OK && pkt_size < 10000000); |
1753 | 6 | pkt_size = zstream.total_out; | |
1754 | 6 | inflateEnd(&zstream); | |
1755 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (result != Z_STREAM_END) { |
1756 | ✗ | if (result == Z_MEM_ERROR) | |
1757 | ✗ | result = AVERROR(ENOMEM); | |
1758 | else | ||
1759 | ✗ | result = AVERROR_INVALIDDATA; | |
1760 | ✗ | goto failed; | |
1761 | } | ||
1762 | 6 | break; | |
1763 | } | ||
1764 | #endif | ||
1765 | #if CONFIG_BZLIB | ||
1766 | 2 | case MATROSKA_TRACK_ENCODING_COMP_BZLIB: | |
1767 | { | ||
1768 | 2 | bz_stream bzstream = { 0 }; | |
1769 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 2 times.
|
2 | if (!pkt_size || BZ2_bzDecompressInit(&bzstream, 0, 0) != BZ_OK) |
1770 | ✗ | return -1; | |
1771 | 2 | bzstream.next_in = data; | |
1772 | 2 | bzstream.avail_in = isize; | |
1773 | do { | ||
1774 | 6 | pkt_size *= 3; | |
1775 | 6 | newpktdata = av_realloc(pkt_data, pkt_size + AV_INPUT_BUFFER_PADDING_SIZE); | |
1776 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!newpktdata) { |
1777 | ✗ | BZ2_bzDecompressEnd(&bzstream); | |
1778 | ✗ | result = AVERROR(ENOMEM); | |
1779 | ✗ | goto failed; | |
1780 | } | ||
1781 | 6 | pkt_data = newpktdata; | |
1782 | 6 | bzstream.avail_out = pkt_size - bzstream.total_out_lo32; | |
1783 | 6 | bzstream.next_out = pkt_data + bzstream.total_out_lo32; | |
1784 | 6 | result = BZ2_bzDecompress(&bzstream); | |
1785 |
3/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
6 | } while (result == BZ_OK && pkt_size < 10000000); |
1786 | 2 | pkt_size = bzstream.total_out_lo32; | |
1787 | 2 | BZ2_bzDecompressEnd(&bzstream); | |
1788 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (result != BZ_STREAM_END) { |
1789 | ✗ | if (result == BZ_MEM_ERROR) | |
1790 | ✗ | result = AVERROR(ENOMEM); | |
1791 | else | ||
1792 | ✗ | result = AVERROR_INVALIDDATA; | |
1793 | ✗ | goto failed; | |
1794 | } | ||
1795 | 2 | break; | |
1796 | } | ||
1797 | #endif | ||
1798 | ✗ | default: | |
1799 | ✗ | return AVERROR_INVALIDDATA; | |
1800 | } | ||
1801 | |||
1802 | 82 | memset(pkt_data + pkt_size, 0, AV_INPUT_BUFFER_PADDING_SIZE); | |
1803 | |||
1804 | 82 | *buf = pkt_data; | |
1805 | 82 | *buf_size = pkt_size; | |
1806 | 82 | return 0; | |
1807 | |||
1808 | ✗ | failed: | |
1809 | ✗ | av_free(pkt_data); | |
1810 | ✗ | return result; | |
1811 | } | ||
1812 | |||
1813 | 209 | static void matroska_convert_tag(AVFormatContext *s, EbmlList *list, | |
1814 | AVDictionary **metadata, char *prefix) | ||
1815 | { | ||
1816 | 209 | MatroskaTag *tags = list->elem; | |
1817 | char key[1024]; | ||
1818 | int i; | ||
1819 | |||
1820 |
2/2✓ Branch 0 taken 448 times.
✓ Branch 1 taken 209 times.
|
657 | for (i = 0; i < list->nb_elem; i++) { |
1821 | 1344 | const char *lang = tags[i].lang && | |
1822 |
3/4✓ Branch 0 taken 448 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 403 times.
|
448 | strcmp(tags[i].lang, "und") ? tags[i].lang : NULL; |
1823 | |||
1824 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 448 times.
|
448 | if (!tags[i].name) { |
1825 | ✗ | av_log(s, AV_LOG_WARNING, "Skipping invalid tag with no TagName.\n"); | |
1826 | ✗ | continue; | |
1827 | } | ||
1828 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 448 times.
|
448 | if (prefix) |
1829 | ✗ | snprintf(key, sizeof(key), "%s/%s", prefix, tags[i].name); | |
1830 | else | ||
1831 | 448 | av_strlcpy(key, tags[i].name, sizeof(key)); | |
1832 |
3/4✓ Branch 0 taken 448 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 403 times.
✓ Branch 3 taken 45 times.
|
448 | if (tags[i].def || !lang) { |
1833 | 403 | av_dict_set(metadata, key, tags[i].string, 0); | |
1834 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 403 times.
|
403 | if (tags[i].sub.nb_elem) |
1835 | ✗ | matroska_convert_tag(s, &tags[i].sub, metadata, key); | |
1836 | } | ||
1837 |
2/2✓ Branch 0 taken 45 times.
✓ Branch 1 taken 403 times.
|
448 | if (lang) { |
1838 | 45 | av_strlcat(key, "-", sizeof(key)); | |
1839 | 45 | av_strlcat(key, lang, sizeof(key)); | |
1840 | 45 | av_dict_set(metadata, key, tags[i].string, 0); | |
1841 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
45 | if (tags[i].sub.nb_elem) |
1842 | ✗ | matroska_convert_tag(s, &tags[i].sub, metadata, key); | |
1843 | } | ||
1844 | } | ||
1845 | 209 | ff_metadata_conv(metadata, NULL, ff_mkv_metadata_conv); | |
1846 | 209 | } | |
1847 | |||
1848 | 372 | static void matroska_convert_tags(AVFormatContext *s) | |
1849 | { | ||
1850 | 372 | MatroskaDemuxContext *matroska = s->priv_data; | |
1851 | 372 | MatroskaTags *tags = matroska->tags.elem; | |
1852 | int i, j; | ||
1853 | |||
1854 |
2/2✓ Branch 0 taken 209 times.
✓ Branch 1 taken 372 times.
|
581 | for (i = 0; i < matroska->tags.nb_elem; i++) { |
1855 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 206 times.
|
209 | if (tags[i].target.attachuid) { |
1856 | 3 | MatroskaAttachment *attachment = matroska->attachments.elem; | |
1857 | 3 | int found = 0; | |
1858 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | for (j = 0; j < matroska->attachments.nb_elem; j++) { |
1859 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (attachment[j].uid == tags[i].target.attachuid && |
1860 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | attachment[j].stream) { |
1861 | 3 | matroska_convert_tag(s, &tags[i].tag, | |
1862 | 3 | &attachment[j].stream->metadata, NULL); | |
1863 | 3 | found = 1; | |
1864 | } | ||
1865 | } | ||
1866 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!found) { |
1867 | ✗ | av_log(s, AV_LOG_WARNING, | |
1868 | "The tags at index %d refer to a " | ||
1869 | "non-existent attachment %"PRId64".\n", | ||
1870 | ✗ | i, tags[i].target.attachuid); | |
1871 | } | ||
1872 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 203 times.
|
206 | } else if (tags[i].target.chapteruid) { |
1873 | 3 | MatroskaChapter *chapter = matroska->chapters.elem; | |
1874 | 3 | int found = 0; | |
1875 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 3 times.
|
9 | for (j = 0; j < matroska->chapters.nb_elem; j++) { |
1876 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 3 times.
|
6 | if (chapter[j].uid == tags[i].target.chapteruid && |
1877 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | chapter[j].chapter) { |
1878 | 3 | matroska_convert_tag(s, &tags[i].tag, | |
1879 | 3 | &chapter[j].chapter->metadata, NULL); | |
1880 | 3 | found = 1; | |
1881 | } | ||
1882 | } | ||
1883 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | if (!found) { |
1884 | ✗ | av_log(s, AV_LOG_WARNING, | |
1885 | "The tags at index %d refer to a non-existent chapter " | ||
1886 | "%"PRId64".\n", | ||
1887 | ✗ | i, tags[i].target.chapteruid); | |
1888 | } | ||
1889 |
2/2✓ Branch 0 taken 150 times.
✓ Branch 1 taken 53 times.
|
203 | } else if (tags[i].target.trackuid) { |
1890 | 150 | MatroskaTrack *track = matroska->tracks.elem; | |
1891 | 150 | int found = 0; | |
1892 |
2/2✓ Branch 0 taken 398 times.
✓ Branch 1 taken 150 times.
|
548 | for (j = 0; j < matroska->tracks.nb_elem; j++) { |
1893 |
2/2✓ Branch 0 taken 150 times.
✓ Branch 1 taken 248 times.
|
398 | if (track[j].uid == tags[i].target.trackuid && |
1894 |
1/2✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
|
150 | track[j].stream) { |
1895 | 150 | matroska_convert_tag(s, &tags[i].tag, | |
1896 | 150 | &track[j].stream->metadata, NULL); | |
1897 | 150 | found = 1; | |
1898 | } | ||
1899 | } | ||
1900 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 150 times.
|
150 | if (!found) { |
1901 | ✗ | av_log(s, AV_LOG_WARNING, | |
1902 | "The tags at index %d refer to a non-existent track " | ||
1903 | "%"PRId64".\n", | ||
1904 | ✗ | i, tags[i].target.trackuid); | |
1905 | } | ||
1906 | } else { | ||
1907 | 53 | matroska_convert_tag(s, &tags[i].tag, &s->metadata, | |
1908 | 53 | tags[i].target.type); | |
1909 | } | ||
1910 | } | ||
1911 | 372 | } | |
1912 | |||
1913 | 24 | static int matroska_parse_seekhead_entry(MatroskaDemuxContext *matroska, | |
1914 | int64_t pos) | ||
1915 | { | ||
1916 | 24 | uint32_t saved_id = matroska->current_id; | |
1917 | 24 | int64_t before_pos = avio_tell(matroska->ctx->pb); | |
1918 | 24 | int ret = 0; | |
1919 | int ret2; | ||
1920 | |||
1921 | /* seek */ | ||
1922 |
1/2✓ Branch 1 taken 24 times.
✗ Branch 2 not taken.
|
24 | if (avio_seek(matroska->ctx->pb, pos, SEEK_SET) == pos) { |
1923 | /* We don't want to lose our seekhead level, so we add | ||
1924 | * a dummy. This is a crude hack. */ | ||
1925 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | if (matroska->num_levels == EBML_MAX_DEPTH) { |
1926 | ✗ | av_log(matroska->ctx, AV_LOG_INFO, | |
1927 | "Max EBML element depth (%d) reached, " | ||
1928 | "cannot parse further.\n", EBML_MAX_DEPTH); | ||
1929 | ✗ | ret = AVERROR_INVALIDDATA; | |
1930 | } else { | ||
1931 | 24 | matroska->levels[matroska->num_levels] = (MatroskaLevel) { 0, EBML_UNKNOWN_LENGTH }; | |
1932 | 24 | matroska->num_levels++; | |
1933 | 24 | matroska->current_id = 0; | |
1934 | |||
1935 | 24 | ret = ebml_parse(matroska, matroska_segment, matroska); | |
1936 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
|
24 | if (ret == LEVEL_ENDED) { |
1937 | /* This can only happen if the seek brought us beyond EOF. */ | ||
1938 | 2 | ret = AVERROR_EOF; | |
1939 | } | ||
1940 | } | ||
1941 | } | ||
1942 | /* Seek back - notice that in all instances where this is used | ||
1943 | * it is safe to set the level to 1. */ | ||
1944 | 24 | ret2 = matroska_reset_status(matroska, saved_id, before_pos); | |
1945 |
2/2✓ Branch 0 taken 22 times.
✓ Branch 1 taken 2 times.
|
24 | if (ret >= 0) |
1946 | 22 | ret = ret2; | |
1947 | |||
1948 | 24 | return ret; | |
1949 | } | ||
1950 | |||
1951 | 372 | static void matroska_execute_seekhead(MatroskaDemuxContext *matroska) | |
1952 | { | ||
1953 | 372 | EbmlList *seekhead_list = &matroska->seekhead; | |
1954 | int i; | ||
1955 | |||
1956 | // we should not do any seeking in the streaming case | ||
1957 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 371 times.
|
372 | if (!(matroska->ctx->pb->seekable & AVIO_SEEKABLE_NORMAL)) |
1958 | 1 | return; | |
1959 | |||
1960 |
2/2✓ Branch 0 taken 1196 times.
✓ Branch 1 taken 370 times.
|
1566 | for (i = 0; i < seekhead_list->nb_elem; i++) { |
1961 | 1196 | MatroskaSeekhead *seekheads = seekhead_list->elem; | |
1962 | 1196 | uint32_t id = seekheads[i].id; | |
1963 | 1196 | int64_t pos = seekheads[i].pos + matroska->segment_start; | |
1964 | MatroskaLevel1Element *elem; | ||
1965 | |||
1966 |
2/4✓ Branch 0 taken 1196 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1196 times.
|
1196 | if (id != seekheads[i].id || pos < matroska->segment_start) |
1967 | ✗ | continue; | |
1968 | |||
1969 | 1196 | elem = matroska_find_level1_elem(matroska, id, pos); | |
1970 |
4/4✓ Branch 0 taken 1171 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 830 times.
✓ Branch 3 taken 341 times.
|
1196 | if (!elem || elem->parsed) |
1971 | 855 | continue; | |
1972 | |||
1973 | 341 | elem->pos = pos; | |
1974 | |||
1975 | // defer cues parsing until we actually need cue data. | ||
1976 |
2/2✓ Branch 0 taken 329 times.
✓ Branch 1 taken 12 times.
|
341 | if (id == MATROSKA_ID_CUES) |
1977 | 329 | continue; | |
1978 | |||
1979 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 11 times.
|
12 | if (matroska_parse_seekhead_entry(matroska, pos) < 0) { |
1980 | // mark index as broken | ||
1981 | 1 | matroska->cues_parsing_deferred = -1; | |
1982 | 1 | break; | |
1983 | } | ||
1984 | |||
1985 | 11 | elem->parsed = 1; | |
1986 | } | ||
1987 | } | ||
1988 | |||
1989 | 385 | static void matroska_add_index_entries(MatroskaDemuxContext *matroska) | |
1990 | { | ||
1991 | EbmlList *index_list; | ||
1992 | MatroskaIndex *index; | ||
1993 | 385 | uint64_t index_scale = 1; | |
1994 | int i, j; | ||
1995 | |||
1996 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 385 times.
|
385 | if (matroska->ctx->flags & AVFMT_FLAG_IGNIDX) |
1997 | ✗ | return; | |
1998 | |||
1999 | 385 | index_list = &matroska->index; | |
2000 | 385 | index = index_list->elem; | |
2001 |
2/2✓ Branch 0 taken 367 times.
✓ Branch 1 taken 18 times.
|
385 | if (index_list->nb_elem < 2) |
2002 | 367 | return; | |
2003 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 18 times.
|
18 | if (index[1].time > 1E14 / matroska->time_scale) { |
2004 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, "Dropping apparently-broken index.\n"); | |
2005 | ✗ | return; | |
2006 | } | ||
2007 |
2/2✓ Branch 0 taken 538 times.
✓ Branch 1 taken 18 times.
|
556 | for (i = 0; i < index_list->nb_elem; i++) { |
2008 | 538 | EbmlList *pos_list = &index[i].pos; | |
2009 | 538 | MatroskaIndexPos *pos = pos_list->elem; | |
2010 |
2/2✓ Branch 0 taken 656 times.
✓ Branch 1 taken 538 times.
|
1194 | for (j = 0; j < pos_list->nb_elem; j++) { |
2011 | 656 | MatroskaTrack *track = matroska_find_track_by_num(matroska, | |
2012 | 656 | pos[j].track); | |
2013 |
2/4✓ Branch 0 taken 656 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 656 times.
✗ Branch 3 not taken.
|
656 | if (track && track->stream) |
2014 | 656 | av_add_index_entry(track->stream, | |
2015 | 656 | pos[j].pos + matroska->segment_start, | |
2016 | 656 | index[i].time / index_scale, 0, 0, | |
2017 | AVINDEX_KEYFRAME); | ||
2018 | } | ||
2019 | } | ||
2020 | } | ||
2021 | |||
2022 | 13 | static void matroska_parse_cues(MatroskaDemuxContext *matroska) { | |
2023 | int i; | ||
2024 | |||
2025 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 13 times.
|
13 | if (matroska->ctx->flags & AVFMT_FLAG_IGNIDX) |
2026 | ✗ | return; | |
2027 | |||
2028 |
2/2✓ Branch 0 taken 53 times.
✓ Branch 1 taken 1 times.
|
54 | for (i = 0; i < matroska->num_level1_elems; i++) { |
2029 | 53 | MatroskaLevel1Element *elem = &matroska->level1_elems[i]; | |
2030 |
3/4✓ Branch 0 taken 12 times.
✓ Branch 1 taken 41 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
53 | if (elem->id == MATROSKA_ID_CUES && !elem->parsed) { |
2031 |
2/2✓ Branch 1 taken 1 times.
✓ Branch 2 taken 11 times.
|
12 | if (matroska_parse_seekhead_entry(matroska, elem->pos) < 0) |
2032 | 1 | matroska->cues_parsing_deferred = -1; | |
2033 | 12 | elem->parsed = 1; | |
2034 | 12 | break; | |
2035 | } | ||
2036 | } | ||
2037 | |||
2038 | 13 | matroska_add_index_entries(matroska); | |
2039 | } | ||
2040 | |||
2041 | 447 | static int matroska_parse_content_encodings(MatroskaTrackEncoding *encodings, | |
2042 | unsigned nb_encodings, | ||
2043 | MatroskaTrack *track, | ||
2044 | char **key_id_base64, void *logctx) | ||
2045 | { | ||
2046 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 447 times.
|
447 | if (nb_encodings > 1) { |
2047 | ✗ | av_log(logctx, AV_LOG_ERROR, | |
2048 | "Multiple combined encodings not supported\n"); | ||
2049 | ✗ | return 0; | |
2050 | } | ||
2051 |
2/2✓ Branch 0 taken 435 times.
✓ Branch 1 taken 12 times.
|
447 | if (!nb_encodings) |
2052 | 435 | return 0; | |
2053 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (encodings->type) { |
2054 | ✗ | if (encodings->encryption.key_id.size > 0) { | |
2055 | /* Save the encryption key id to be stored later | ||
2056 | * as a metadata tag. */ | ||
2057 | ✗ | const int b64_size = AV_BASE64_SIZE(encodings->encryption.key_id.size); | |
2058 | ✗ | *key_id_base64 = av_malloc(b64_size); | |
2059 | ✗ | if (!*key_id_base64) | |
2060 | ✗ | return AVERROR(ENOMEM); | |
2061 | |||
2062 | ✗ | av_base64_encode(*key_id_base64, b64_size, | |
2063 | ✗ | encodings->encryption.key_id.data, | |
2064 | encodings->encryption.key_id.size); | ||
2065 | } else { | ||
2066 | ✗ | encodings->scope = 0; | |
2067 | ✗ | av_log(logctx, AV_LOG_ERROR, "Unsupported encoding type\n"); | |
2068 | } | ||
2069 | 12 | } else if ( | |
2070 | #if CONFIG_ZLIB | ||
2071 |
2/2✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
|
12 | encodings->compression.algo != MATROSKA_TRACK_ENCODING_COMP_ZLIB && |
2072 | #endif | ||
2073 | #if CONFIG_BZLIB | ||
2074 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 1 times.
|
9 | encodings->compression.algo != MATROSKA_TRACK_ENCODING_COMP_BZLIB && |
2075 | #endif | ||
2076 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 1 times.
|
8 | encodings->compression.algo != MATROSKA_TRACK_ENCODING_COMP_LZO && |
2077 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | encodings->compression.algo != MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP) { |
2078 | ✗ | encodings->scope = 0; | |
2079 | ✗ | av_log(logctx, AV_LOG_ERROR, "Unsupported encoding type\n"); | |
2080 |
4/4✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 8 times.
|
12 | } else if (track->codec_priv.size && encodings[0].scope & 2) { |
2081 | 1 | uint8_t *codec_priv = track->codec_priv.data; | |
2082 | 1 | int ret = matroska_decode_buffer(&track->codec_priv.data, | |
2083 | &track->codec_priv.size, | ||
2084 | track); | ||
2085 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret < 0) { |
2086 | ✗ | track->codec_priv.data = NULL; | |
2087 | ✗ | track->codec_priv.size = 0; | |
2088 | ✗ | av_log(logctx, AV_LOG_ERROR, | |
2089 | "Failed to decode codec private data\n"); | ||
2090 | } | ||
2091 | |||
2092 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (codec_priv != track->codec_priv.data) { |
2093 | 1 | av_buffer_unref(&track->codec_priv.buf); | |
2094 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (track->codec_priv.data) { |
2095 | 2 | track->codec_priv.buf = av_buffer_create(track->codec_priv.data, | |
2096 | 1 | track->codec_priv.size + AV_INPUT_BUFFER_PADDING_SIZE, | |
2097 | NULL, NULL, 0); | ||
2098 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!track->codec_priv.buf) { |
2099 | ✗ | av_freep(&track->codec_priv.data); | |
2100 | ✗ | track->codec_priv.size = 0; | |
2101 | ✗ | return AVERROR(ENOMEM); | |
2102 | } | ||
2103 | } | ||
2104 | } | ||
2105 | } | ||
2106 | 36 | track->needs_decoding = !encodings->type && | |
2107 |
2/4✓ Branch 0 taken 12 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
|
24 | encodings->scope & 1 && |
2108 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 5 times.
|
12 | (encodings->compression.algo != |
2109 | 7 | MATROSKA_TRACK_ENCODING_COMP_HEADERSTRIP || | |
2110 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | encodings->compression.settings.size); |
2111 | |||
2112 | 12 | return 0; | |
2113 | } | ||
2114 | |||
2115 | ✗ | static int matroska_aac_profile(char *codec_id) | |
2116 | { | ||
2117 | static const char *const aac_profiles[] = { "MAIN", "LC", "SSR" }; | ||
2118 | int profile; | ||
2119 | |||
2120 | ✗ | for (profile = 0; profile < FF_ARRAY_ELEMS(aac_profiles); profile++) | |
2121 | ✗ | if (strstr(codec_id, aac_profiles[profile])) | |
2122 | ✗ | break; | |
2123 | ✗ | return profile + 1; | |
2124 | } | ||
2125 | |||
2126 | ✗ | static int matroska_aac_sri(int samplerate) | |
2127 | { | ||
2128 | int sri; | ||
2129 | |||
2130 | ✗ | for (sri = 0; sri < FF_ARRAY_ELEMS(ff_mpeg4audio_sample_rates); sri++) | |
2131 | ✗ | if (ff_mpeg4audio_sample_rates[sri] == samplerate) | |
2132 | ✗ | break; | |
2133 | ✗ | return sri; | |
2134 | } | ||
2135 | |||
2136 | 18 | static void matroska_metadata_creation_time(AVDictionary **metadata, int64_t date_utc) | |
2137 | { | ||
2138 | /* Convert to seconds and adjust by number of seconds between 2001-01-01 and Epoch */ | ||
2139 | 18 | ff_dict_set_timestamp(metadata, "creation_time", date_utc / 1000 + 978307200000000LL); | |
2140 | 18 | } | |
2141 | |||
2142 | 9 | static int matroska_parse_flac(AVFormatContext *s, | |
2143 | MatroskaTrack *track, | ||
2144 | int *offset) | ||
2145 | { | ||
2146 | 9 | AVStream *st = track->stream; | |
2147 | 9 | uint8_t *p = track->codec_priv.data; | |
2148 | 9 | int size = track->codec_priv.size; | |
2149 | |||
2150 |
2/4✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 9 times.
|
9 | if (size < 8 + FLAC_STREAMINFO_SIZE || p[4] & 0x7f) { |
2151 | ✗ | av_log(s, AV_LOG_WARNING, "Invalid FLAC private data\n"); | |
2152 | ✗ | track->codec_priv.size = 0; | |
2153 | ✗ | return 0; | |
2154 | } | ||
2155 | 9 | *offset = 8; | |
2156 | 9 | track->codec_priv.size = 8 + FLAC_STREAMINFO_SIZE; | |
2157 | |||
2158 | 9 | p += track->codec_priv.size; | |
2159 | 9 | size -= track->codec_priv.size; | |
2160 | |||
2161 | /* parse the remaining metadata blocks if present */ | ||
2162 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 9 times.
|
17 | while (size >= 4) { |
2163 | int block_last, block_type, block_size; | ||
2164 | |||
2165 | 8 | flac_parse_block_header(p, &block_last, &block_type, &block_size); | |
2166 | |||
2167 | 8 | p += 4; | |
2168 | 8 | size -= 4; | |
2169 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (block_size > size) |
2170 | ✗ | return 0; | |
2171 | |||
2172 | /* check for the channel mask */ | ||
2173 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (block_type == FLAC_METADATA_TYPE_VORBIS_COMMENT) { |
2174 | 8 | AVDictionary *dict = NULL; | |
2175 | AVDictionaryEntry *chmask; | ||
2176 | |||
2177 | 8 | ff_vorbis_comment(s, &dict, p, block_size, 0); | |
2178 | 8 | chmask = av_dict_get(dict, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", NULL, 0); | |
2179 |
1/2✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
|
8 | if (chmask) { |
2180 | 8 | uint64_t mask = strtol(chmask->value, NULL, 0); | |
2181 |
2/4✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
8 | if (!mask || mask & ~0x3ffffULL) { |
2182 | ✗ | av_log(s, AV_LOG_WARNING, | |
2183 | "Invalid value of WAVEFORMATEXTENSIBLE_CHANNEL_MASK\n"); | ||
2184 | } else | ||
2185 | 8 | av_channel_layout_from_mask(&st->codecpar->ch_layout, mask); | |
2186 | } | ||
2187 | 8 | av_dict_free(&dict); | |
2188 | } | ||
2189 | |||
2190 | 8 | p += block_size; | |
2191 | 8 | size -= block_size; | |
2192 | } | ||
2193 | |||
2194 | 9 | return 0; | |
2195 | } | ||
2196 | |||
2197 | 7 | static int mkv_field_order(const MatroskaDemuxContext *matroska, uint64_t field_order) | |
2198 | { | ||
2199 | 7 | int minor, micro, bttb = 0; | |
2200 | |||
2201 | /* workaround a bug in our Matroska muxer, introduced in version 57.36 alongside | ||
2202 | * this function, and fixed in 57.52 */ | ||
2203 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 7 times.
|
7 | if (matroska->muxingapp && sscanf(matroska->muxingapp, "Lavf57.%d.%d", &minor, µ) == 2) |
2204 | ✗ | bttb = (minor >= 36 && minor <= 51 && micro >= 100); | |
2205 | |||
2206 |
2/7✗ Branch 0 not taken.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
|
7 | switch (field_order) { |
2207 | ✗ | case MATROSKA_VIDEO_FIELDORDER_PROGRESSIVE: | |
2208 | ✗ | return AV_FIELD_PROGRESSIVE; | |
2209 | ✗ | case MATROSKA_VIDEO_FIELDORDER_UNDETERMINED: | |
2210 | ✗ | return AV_FIELD_UNKNOWN; | |
2211 | 6 | case MATROSKA_VIDEO_FIELDORDER_TT: | |
2212 | 6 | return AV_FIELD_TT; | |
2213 | 1 | case MATROSKA_VIDEO_FIELDORDER_BB: | |
2214 | 1 | return AV_FIELD_BB; | |
2215 | ✗ | case MATROSKA_VIDEO_FIELDORDER_BT: | |
2216 | ✗ | return bttb ? AV_FIELD_TB : AV_FIELD_BT; | |
2217 | ✗ | case MATROSKA_VIDEO_FIELDORDER_TB: | |
2218 | ✗ | return bttb ? AV_FIELD_BT : AV_FIELD_TB; | |
2219 | ✗ | default: | |
2220 | ✗ | return AV_FIELD_UNKNOWN; | |
2221 | } | ||
2222 | } | ||
2223 | |||
2224 | 12 | static void mkv_stereo_mode_display_mul(int stereo_mode, | |
2225 | int *h_width, int *h_height) | ||
2226 | { | ||
2227 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 4 times.
|
12 | switch (stereo_mode) { |
2228 | ✗ | case MATROSKA_VIDEO_STEREOMODE_TYPE_MONO: | |
2229 | case MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_RL: | ||
2230 | case MATROSKA_VIDEO_STEREOMODE_TYPE_CHECKERBOARD_LR: | ||
2231 | case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_RL: | ||
2232 | case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTH_EYES_BLOCK_LR: | ||
2233 | ✗ | break; | |
2234 | 4 | case MATROSKA_VIDEO_STEREOMODE_TYPE_RIGHT_LEFT: | |
2235 | case MATROSKA_VIDEO_STEREOMODE_TYPE_LEFT_RIGHT: | ||
2236 | case MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_RL: | ||
2237 | case MATROSKA_VIDEO_STEREOMODE_TYPE_COL_INTERLEAVED_LR: | ||
2238 | 4 | *h_width = 2; | |
2239 | 4 | break; | |
2240 | 4 | case MATROSKA_VIDEO_STEREOMODE_TYPE_BOTTOM_TOP: | |
2241 | case MATROSKA_VIDEO_STEREOMODE_TYPE_TOP_BOTTOM: | ||
2242 | case MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_RL: | ||
2243 | case MATROSKA_VIDEO_STEREOMODE_TYPE_ROW_INTERLEAVED_LR: | ||
2244 | 4 | *h_height = 2; | |
2245 | 4 | break; | |
2246 | } | ||
2247 | 12 | } | |
2248 | |||
2249 | 236 | static int mkv_stereo3d_conv(AVStream *st, MatroskaVideoStereoModeType stereo_mode) | |
2250 | { | ||
2251 | static const struct { | ||
2252 | char type; | ||
2253 | char flags; | ||
2254 | } stereo_mode_conv [] = { | ||
2255 | #define STEREO_MODE_CONV(STEREOMODETYPE, STEREO3DTYPE, FLAGS, WDIV, HDIV, WEBM) \ | ||
2256 | [(STEREOMODETYPE)] = { .type = (STEREO3DTYPE), .flags = (FLAGS) }, | ||
2257 | #define NOTHING(STEREOMODETYPE, WDIV, HDIV, WEBM) | ||
2258 | STEREOMODE_STEREO3D_MAPPING(STEREO_MODE_CONV, NOTHING) | ||
2259 | }; | ||
2260 | AVStereo3D *stereo; | ||
2261 | size_t size; | ||
2262 | |||
2263 | 236 | stereo = av_stereo3d_alloc_size(&size); | |
2264 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 236 times.
|
236 | if (!stereo) |
2265 | ✗ | return AVERROR(ENOMEM); | |
2266 | |||
2267 | 236 | stereo->type = stereo_mode_conv[stereo_mode].type; | |
2268 | 236 | stereo->flags = stereo_mode_conv[stereo_mode].flags; | |
2269 | |||
2270 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 236 times.
|
236 | if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data, |
2271 | AV_PKT_DATA_STEREO3D, stereo, size, 0)) { | ||
2272 | ✗ | av_freep(&stereo); | |
2273 | ✗ | return AVERROR(ENOMEM); | |
2274 | } | ||
2275 | |||
2276 | 236 | return 0; | |
2277 | } | ||
2278 | |||
2279 | 339 | static int mkv_parse_video_color(AVStream *st, const MatroskaTrack *track) { | |
2280 | 339 | const MatroskaTrackVideoColor *color = track->video.color.elem; | |
2281 | const MatroskaMasteringMeta *mastering_meta; | ||
2282 | int has_mastering_primaries, has_mastering_luminance; | ||
2283 | |||
2284 |
2/2✓ Branch 0 taken 275 times.
✓ Branch 1 taken 64 times.
|
339 | if (!track->video.color.nb_elem) |
2285 | 275 | return 0; | |
2286 | |||
2287 | 64 | mastering_meta = &color->mastering_meta; | |
2288 | // Mastering primaries are CIE 1931 coords, and must be > 0. | ||
2289 | 64 | has_mastering_primaries = | |
2290 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | mastering_meta->r_x > 0 && mastering_meta->r_y > 0 && |
2291 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | mastering_meta->g_x > 0 && mastering_meta->g_y > 0 && |
2292 |
2/4✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
7 | mastering_meta->b_x > 0 && mastering_meta->b_y > 0 && |
2293 |
4/6✓ Branch 0 taken 7 times.
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
71 | mastering_meta->white_x > 0 && mastering_meta->white_y > 0; |
2294 | 128 | has_mastering_luminance = mastering_meta->max_luminance > | |
2295 | 71 | mastering_meta->min_luminance.el.f && | |
2296 |
3/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
71 | mastering_meta->min_luminance.el.f >= 0 && |
2297 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | mastering_meta->min_luminance.count; |
2298 | |||
2299 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | if (color->matrix_coefficients != AVCOL_SPC_RESERVED) |
2300 | 64 | st->codecpar->color_space = color->matrix_coefficients; | |
2301 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | if (color->primaries != AVCOL_PRI_RESERVED && |
2302 |
2/2✓ Branch 0 taken 62 times.
✓ Branch 1 taken 2 times.
|
64 | color->primaries != AVCOL_PRI_RESERVED0) |
2303 | 62 | st->codecpar->color_primaries = color->primaries; | |
2304 |
1/2✓ Branch 0 taken 64 times.
✗ Branch 1 not taken.
|
64 | if (color->transfer_characteristics != AVCOL_TRC_RESERVED && |
2305 |
2/2✓ Branch 0 taken 62 times.
✓ Branch 1 taken 2 times.
|
64 | color->transfer_characteristics != AVCOL_TRC_RESERVED0) |
2306 | 62 | st->codecpar->color_trc = color->transfer_characteristics; | |
2307 |
2/2✓ Branch 0 taken 44 times.
✓ Branch 1 taken 20 times.
|
64 | if (color->range != AVCOL_RANGE_UNSPECIFIED && |
2308 |
1/2✓ Branch 0 taken 44 times.
✗ Branch 1 not taken.
|
44 | color->range <= AVCOL_RANGE_JPEG) |
2309 | 44 | st->codecpar->color_range = color->range; | |
2310 |
2/2✓ Branch 0 taken 43 times.
✓ Branch 1 taken 21 times.
|
64 | if (color->chroma_siting_horz != MATROSKA_COLOUR_CHROMASITINGHORZ_UNDETERMINED && |
2311 |
1/2✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
|
43 | color->chroma_siting_vert != MATROSKA_COLOUR_CHROMASITINGVERT_UNDETERMINED && |
2312 |
1/2✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
|
43 | color->chroma_siting_horz < MATROSKA_COLOUR_CHROMASITINGHORZ_NB && |
2313 |
1/2✓ Branch 0 taken 43 times.
✗ Branch 1 not taken.
|
43 | color->chroma_siting_vert < MATROSKA_COLOUR_CHROMASITINGVERT_NB) { |
2314 | 43 | st->codecpar->chroma_location = | |
2315 | 43 | av_chroma_location_pos_to_enum((color->chroma_siting_horz - 1) << 7, | |
2316 | 43 | (color->chroma_siting_vert - 1) << 7); | |
2317 | } | ||
2318 |
3/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 57 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
64 | if (color->max_cll && color->max_fall) { |
2319 | 7 | size_t size = 0; | |
2320 | 7 | AVContentLightMetadata *metadata = av_content_light_metadata_alloc(&size); | |
2321 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (!metadata) |
2322 | ✗ | return AVERROR(ENOMEM); | |
2323 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
|
7 | if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data, |
2324 | AV_PKT_DATA_CONTENT_LIGHT_LEVEL, metadata, size, 0)) { | ||
2325 | ✗ | av_freep(&metadata); | |
2326 | ✗ | return AVERROR(ENOMEM); | |
2327 | } | ||
2328 | 7 | metadata->MaxCLL = color->max_cll; | |
2329 | 7 | metadata->MaxFALL = color->max_fall; | |
2330 | } | ||
2331 | |||
2332 |
3/4✓ Branch 0 taken 57 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 57 times.
|
64 | if (has_mastering_primaries || has_mastering_luminance) { |
2333 | 7 | size_t size = 0; | |
2334 | 7 | AVMasteringDisplayMetadata *metadata = av_mastering_display_metadata_alloc_size(&size); | |
2335 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 7 times.
|
7 | if (!metadata) |
2336 | ✗ | return AVERROR(ENOMEM); | |
2337 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
|
7 | if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data, |
2338 | AV_PKT_DATA_MASTERING_DISPLAY_METADATA, metadata, size, 0)) { | ||
2339 | ✗ | av_freep(&metadata); | |
2340 | ✗ | return AVERROR(ENOMEM); | |
2341 | } | ||
2342 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | if (has_mastering_primaries) { |
2343 | 7 | metadata->display_primaries[0][0] = av_d2q(mastering_meta->r_x, INT_MAX); | |
2344 | 7 | metadata->display_primaries[0][1] = av_d2q(mastering_meta->r_y, INT_MAX); | |
2345 | 7 | metadata->display_primaries[1][0] = av_d2q(mastering_meta->g_x, INT_MAX); | |
2346 | 7 | metadata->display_primaries[1][1] = av_d2q(mastering_meta->g_y, INT_MAX); | |
2347 | 7 | metadata->display_primaries[2][0] = av_d2q(mastering_meta->b_x, INT_MAX); | |
2348 | 7 | metadata->display_primaries[2][1] = av_d2q(mastering_meta->b_y, INT_MAX); | |
2349 | 7 | metadata->white_point[0] = av_d2q(mastering_meta->white_x, INT_MAX); | |
2350 | 7 | metadata->white_point[1] = av_d2q(mastering_meta->white_y, INT_MAX); | |
2351 | 7 | metadata->has_primaries = 1; | |
2352 | } | ||
2353 |
1/2✓ Branch 0 taken 7 times.
✗ Branch 1 not taken.
|
7 | if (has_mastering_luminance) { |
2354 | 7 | metadata->max_luminance = av_d2q(mastering_meta->max_luminance, INT_MAX); | |
2355 | 7 | metadata->min_luminance = av_d2q(mastering_meta->min_luminance.el.f, INT_MAX); | |
2356 | 7 | metadata->has_luminance = 1; | |
2357 | } | ||
2358 | } | ||
2359 | 64 | return 0; | |
2360 | } | ||
2361 | |||
2362 | 333 | static int mkv_create_display_matrix(AVStream *st, | |
2363 | const MatroskaTrackVideoProjection *proj, | ||
2364 | void *logctx) | ||
2365 | { | ||
2366 | AVPacketSideData *sd; | ||
2367 | 333 | double pitch = proj->pitch, yaw = proj->yaw, roll = proj->roll; | |
2368 | int32_t *matrix; | ||
2369 | int hflip; | ||
2370 | |||
2371 |
5/6✓ Branch 0 taken 333 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 326 times.
✓ Branch 3 taken 7 times.
✓ Branch 4 taken 324 times.
✓ Branch 5 taken 2 times.
|
333 | if (pitch == 0.0 && yaw == 0.0 && roll == 0.0) |
2372 | 324 | return 0; | |
2373 | |||
2374 | /* Note: The following constants are exactly representable | ||
2375 | * as floating-point numbers. */ | ||
2376 |
7/10✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 7 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 3 times.
✓ Branch 5 taken 4 times.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 9 times.
|
9 | if (pitch != 0.0 || (yaw != 0.0 && yaw != 180.0 && yaw != -180.0) || |
2377 | isnan(roll)) { | ||
2378 | ✗ | av_log(logctx, AV_LOG_WARNING, "Ignoring non-2D rectangular " | |
2379 | "projection in stream %u (yaw %f, pitch %f, roll %f)\n", | ||
2380 | st->index, yaw, pitch, roll); | ||
2381 | ✗ | return 0; | |
2382 | } | ||
2383 | 9 | sd = av_packet_side_data_new(&st->codecpar->coded_side_data, | |
2384 | 9 | &st->codecpar->nb_coded_side_data, | |
2385 | AV_PKT_DATA_DISPLAYMATRIX, | ||
2386 | 9 * sizeof(*matrix), 0); | ||
2387 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if (!sd) |
2388 | ✗ | return AVERROR(ENOMEM); | |
2389 | 9 | matrix = (int32_t*)sd->data; | |
2390 | |||
2391 | 9 | hflip = yaw != 0.0; | |
2392 | /* ProjectionPoseRoll is in the counter-clockwise direction | ||
2393 | * whereas av_display_rotation_set() expects its argument | ||
2394 | * to be oriented clockwise, so we need to negate roll. | ||
2395 | * Furthermore, if hflip is set, we need to negate it again | ||
2396 | * to account for the fact that the Matroska specifications | ||
2397 | * require the yaw rotation to be applied first. */ | ||
2398 | 9 | av_display_rotation_set(matrix, roll * (2 * hflip - 1)); | |
2399 | 9 | av_display_matrix_flip(matrix, hflip, 0); | |
2400 | |||
2401 | 9 | return 0; | |
2402 | } | ||
2403 | |||
2404 | 339 | static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track, | |
2405 | void *logctx) | ||
2406 | { | ||
2407 | AVSphericalMapping *spherical; | ||
2408 | 339 | const MatroskaTrackVideoProjection *mkv_projection = &track->video.projection; | |
2409 | 339 | const uint8_t *priv_data = mkv_projection->private.data; | |
2410 | enum AVSphericalProjection projection; | ||
2411 | size_t spherical_size; | ||
2412 | 339 | uint32_t l = 0, t = 0, r = 0, b = 0; | |
2413 | 339 | uint32_t padding = 0; | |
2414 | |||
2415 |
3/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 333 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
|
339 | if (mkv_projection->private.size && priv_data[0] != 0) { |
2416 | ✗ | av_log(logctx, AV_LOG_WARNING, "Unknown spherical metadata\n"); | |
2417 | ✗ | return 0; | |
2418 | } | ||
2419 | |||
2420 |
2/4✓ Branch 0 taken 333 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
339 | switch (track->video.projection.type) { |
2421 | 333 | case MATROSKA_VIDEO_PROJECTION_TYPE_RECTANGULAR: | |
2422 | 333 | return mkv_create_display_matrix(st, mkv_projection, logctx); | |
2423 | 6 | case MATROSKA_VIDEO_PROJECTION_TYPE_EQUIRECTANGULAR: | |
2424 |
1/2✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
|
6 | if (track->video.projection.private.size == 20) { |
2425 | 6 | t = AV_RB32(priv_data + 4); | |
2426 | 6 | b = AV_RB32(priv_data + 8); | |
2427 | 6 | l = AV_RB32(priv_data + 12); | |
2428 | 6 | r = AV_RB32(priv_data + 16); | |
2429 | |||
2430 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
|
6 | if (b >= UINT_MAX - t || r >= UINT_MAX - l) { |
2431 | ✗ | av_log(logctx, AV_LOG_ERROR, | |
2432 | "Invalid bounding rectangle coordinates " | ||
2433 | "%"PRIu32",%"PRIu32",%"PRIu32",%"PRIu32"\n", | ||
2434 | l, t, r, b); | ||
2435 | ✗ | return AVERROR_INVALIDDATA; | |
2436 | } | ||
2437 | ✗ | } else if (track->video.projection.private.size != 0) { | |
2438 | ✗ | av_log(logctx, AV_LOG_ERROR, "Unknown spherical metadata\n"); | |
2439 | ✗ | return AVERROR_INVALIDDATA; | |
2440 | } | ||
2441 | |||
2442 |
1/8✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
|
6 | if (l || t || r || b) |
2443 | 6 | projection = AV_SPHERICAL_EQUIRECTANGULAR_TILE; | |
2444 | else | ||
2445 | ✗ | projection = AV_SPHERICAL_EQUIRECTANGULAR; | |
2446 | 6 | break; | |
2447 | ✗ | case MATROSKA_VIDEO_PROJECTION_TYPE_CUBEMAP: | |
2448 | ✗ | if (track->video.projection.private.size < 4) { | |
2449 | ✗ | av_log(logctx, AV_LOG_ERROR, "Missing projection private properties\n"); | |
2450 | ✗ | return AVERROR_INVALIDDATA; | |
2451 | ✗ | } else if (track->video.projection.private.size == 12) { | |
2452 | ✗ | uint32_t layout = AV_RB32(priv_data + 4); | |
2453 | ✗ | if (layout) { | |
2454 | ✗ | av_log(logctx, AV_LOG_WARNING, | |
2455 | "Unknown spherical cubemap layout %"PRIu32"\n", layout); | ||
2456 | ✗ | return 0; | |
2457 | } | ||
2458 | ✗ | projection = AV_SPHERICAL_CUBEMAP; | |
2459 | ✗ | padding = AV_RB32(priv_data + 8); | |
2460 | } else { | ||
2461 | ✗ | av_log(logctx, AV_LOG_ERROR, "Unknown spherical metadata\n"); | |
2462 | ✗ | return AVERROR_INVALIDDATA; | |
2463 | } | ||
2464 | ✗ | break; | |
2465 | ✗ | default: | |
2466 | ✗ | av_log(logctx, AV_LOG_WARNING, | |
2467 | "Unknown spherical metadata type %"PRIu64"\n", | ||
2468 | ✗ | track->video.projection.type); | |
2469 | ✗ | return 0; | |
2470 | } | ||
2471 | |||
2472 | 6 | spherical = av_spherical_alloc(&spherical_size); | |
2473 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!spherical) |
2474 | ✗ | return AVERROR(ENOMEM); | |
2475 | |||
2476 | 6 | spherical->projection = projection; | |
2477 | |||
2478 | 6 | spherical->yaw = (int32_t) (track->video.projection.yaw * (1 << 16)); | |
2479 | 6 | spherical->pitch = (int32_t) (track->video.projection.pitch * (1 << 16)); | |
2480 | 6 | spherical->roll = (int32_t) (track->video.projection.roll * (1 << 16)); | |
2481 | |||
2482 | 6 | spherical->padding = padding; | |
2483 | |||
2484 | 6 | spherical->bound_left = l; | |
2485 | 6 | spherical->bound_top = t; | |
2486 | 6 | spherical->bound_right = r; | |
2487 | 6 | spherical->bound_bottom = b; | |
2488 | |||
2489 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
6 | if (!av_packet_side_data_add(&st->codecpar->coded_side_data, &st->codecpar->nb_coded_side_data, |
2490 | AV_PKT_DATA_SPHERICAL, spherical, spherical_size, 0)) { | ||
2491 | ✗ | av_freep(&spherical); | |
2492 | ✗ | return AVERROR(ENOMEM); | |
2493 | } | ||
2494 | |||
2495 | 6 | return 0; | |
2496 | } | ||
2497 | |||
2498 | 4 | static int mkv_parse_dvcc_dvvc(AVFormatContext *s, AVStream *st, const MatroskaTrack *track, | |
2499 | EbmlBin *bin) | ||
2500 | { | ||
2501 | 4 | return ff_isom_parse_dvcc_dvvc(s, st, bin->data, bin->size); | |
2502 | } | ||
2503 | |||
2504 | 447 | static int mkv_parse_block_addition_mappings(AVFormatContext *s, AVStream *st, MatroskaTrack *track) | |
2505 | { | ||
2506 | 447 | const EbmlList *mappings_list = &track->block_addition_mappings; | |
2507 | 447 | MatroskaBlockAdditionMapping *mappings = mappings_list->elem; | |
2508 | int ret; | ||
2509 | |||
2510 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 447 times.
|
453 | for (int i = 0; i < mappings_list->nb_elem; i++) { |
2511 | 6 | MatroskaBlockAdditionMapping *mapping = &mappings[i]; | |
2512 | 6 | uint64_t type = mapping->type; | |
2513 | |||
2514 |
2/4✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
6 | switch (mapping->type) { |
2515 | ✗ | case MATROSKA_BLOCK_ADD_ID_TYPE_DEFAULT: | |
2516 | ✗ | av_log(s, AV_LOG_DEBUG, | |
2517 | "Explicit block Addition Mapping type \"Use BlockAddIDValue\", value %"PRIu64"," | ||
2518 | ✗ | " name \"%s\" found.\n", mapping->value, mapping->name ? mapping->name : ""); | |
2519 | ✗ | type = MATROSKA_BLOCK_ADD_ID_TYPE_OPAQUE; | |
2520 | // fall-through | ||
2521 | 2 | case MATROSKA_BLOCK_ADD_ID_TYPE_OPAQUE: | |
2522 | case MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35: | ||
2523 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (mapping->value != type) { |
2524 | ✗ | int strict = s->strict_std_compliance >= FF_COMPLIANCE_STRICT; | |
2525 | ✗ | av_log(s, strict ? AV_LOG_ERROR : AV_LOG_WARNING, | |
2526 | "Invalid Block Addition Value 0x%"PRIx64" for Block Addition Mapping Type " | ||
2527 | "0x%"PRIx64", name \"%s\"\n", mapping->value, mapping->type, | ||
2528 | ✗ | mapping->name ? mapping->name : ""); | |
2529 | ✗ | if (strict) | |
2530 | ✗ | return AVERROR_INVALIDDATA; | |
2531 | } | ||
2532 | 2 | break; | |
2533 | 4 | case MATROSKA_BLOCK_ADD_ID_TYPE_DVCC: | |
2534 | case MATROSKA_BLOCK_ADD_ID_TYPE_DVVC: | ||
2535 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if ((ret = mkv_parse_dvcc_dvvc(s, st, track, &mapping->extradata)) < 0) |
2536 | ✗ | return ret; | |
2537 | |||
2538 | 4 | break; | |
2539 | ✗ | default: | |
2540 | ✗ | av_log(s, AV_LOG_DEBUG, | |
2541 | "Unknown Block Addition Mapping type 0x%"PRIx64", value %"PRIu64", name \"%s\"\n", | ||
2542 | ✗ | mapping->type, mapping->value, mapping->name ? mapping->name : ""); | |
2543 | ✗ | if (mapping->value < 2) { | |
2544 | ✗ | int strict = s->strict_std_compliance >= FF_COMPLIANCE_STRICT; | |
2545 | ✗ | av_log(s, strict ? AV_LOG_ERROR : AV_LOG_WARNING, | |
2546 | "Invalid Block Addition value 0x%"PRIu64" for unknown Block Addition Mapping " | ||
2547 | "type %"PRIx64", name \"%s\"\n", mapping->value, mapping->type, | ||
2548 | ✗ | mapping->name ? mapping->name : ""); | |
2549 | ✗ | if (strict) | |
2550 | ✗ | return AVERROR_INVALIDDATA; | |
2551 | } | ||
2552 | ✗ | break; | |
2553 | } | ||
2554 | } | ||
2555 | |||
2556 | 447 | return 0; | |
2557 | } | ||
2558 | |||
2559 | 1 | static int get_qt_codec(MatroskaTrack *track, uint32_t *fourcc, enum AVCodecID *codec_id) | |
2560 | { | ||
2561 | const AVCodecTag *codec_tags; | ||
2562 | |||
2563 | 2 | codec_tags = track->type == MATROSKA_TRACK_TYPE_VIDEO ? | |
2564 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | ff_codec_movvideo_tags : ff_codec_movaudio_tags; |
2565 | |||
2566 | /* Normalize noncompliant private data that starts with the fourcc | ||
2567 | * by expanding/shifting the data by 4 bytes and storing the data | ||
2568 | * size at the start. */ | ||
2569 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (ff_codec_get_id(codec_tags, AV_RL32(track->codec_priv.data))) { |
2570 | ✗ | int ret = av_buffer_realloc(&track->codec_priv.buf, | |
2571 | ✗ | track->codec_priv.size + 4 + AV_INPUT_BUFFER_PADDING_SIZE); | |
2572 | ✗ | if (ret < 0) | |
2573 | ✗ | return ret; | |
2574 | |||
2575 | ✗ | track->codec_priv.data = track->codec_priv.buf->data; | |
2576 | ✗ | memmove(track->codec_priv.data + 4, track->codec_priv.data, track->codec_priv.size); | |
2577 | ✗ | track->codec_priv.size += 4; | |
2578 | ✗ | AV_WB32(track->codec_priv.data, track->codec_priv.size); | |
2579 | } | ||
2580 | |||
2581 | 1 | *fourcc = AV_RL32(track->codec_priv.data + 4); | |
2582 | 1 | *codec_id = ff_codec_get_id(codec_tags, *fourcc); | |
2583 | |||
2584 | 1 | return 0; | |
2585 | } | ||
2586 | |||
2587 | /* An enum with potential return values of the functions for parsing a track. | ||
2588 | * Apart from that all these functions can also indicate ordinary errors via | ||
2589 | * negative return values. */ | ||
2590 | enum { | ||
2591 | SKIP_TRACK = 1, | ||
2592 | }; | ||
2593 | |||
2594 | #define AAC_MAX_EXTRADATA_SIZE 5 | ||
2595 | #define TTA_EXTRADATA_SIZE 22 | ||
2596 | #define WAVPACK_EXTRADATA_SIZE 2 | ||
2597 | /* Performs the codec-specific part of parsing an audio track. */ | ||
2598 | 84 | static int mka_parse_audio_codec(MatroskaTrack *track, AVCodecParameters *par, | |
2599 | const MatroskaDemuxContext *matroska, | ||
2600 | AVFormatContext *s, int *extradata_offset) | ||
2601 | { | ||
2602 | uint8_t extradata[FFMAX3(AAC_MAX_EXTRADATA_SIZE, | ||
2603 | TTA_EXTRADATA_SIZE, | ||
2604 | WAVPACK_EXTRADATA_SIZE)]; | ||
2605 | 84 | int extradata_size = 0; // > 0 means that the extradata buffer is used | |
2606 | int ret; | ||
2607 | |||
2608 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 83 times.
|
84 | if (!strcmp(track->codec_id, "A_MS/ACM") && |
2609 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | track->codec_priv.size >= 14) { |
2610 | FFIOContext b; | ||
2611 | 1 | ffio_init_read_context(&b, track->codec_priv.data, | |
2612 | track->codec_priv.size); | ||
2613 | 1 | ret = ff_get_wav_header(s, &b.pub, par, | |
2614 | track->codec_priv.size, 0); | ||
2615 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret < 0) |
2616 | ✗ | return ret; | |
2617 | 1 | *extradata_offset = FFMIN(track->codec_priv.size, 18); | |
2618 | 1 | return 0; | |
2619 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
|
83 | } else if (!strcmp(track->codec_id, "A_QUICKTIME") && |
2620 | /* Normally 36, but allow noncompliant private data */ | ||
2621 | ✗ | track->codec_priv.size >= 32) { | |
2622 | enum AVCodecID codec_id; | ||
2623 | uint32_t fourcc; | ||
2624 | uint16_t sample_size; | ||
2625 | |||
2626 | ✗ | ret = get_qt_codec(track, &fourcc, &codec_id); | |
2627 | ✗ | if (ret < 0) | |
2628 | ✗ | return ret; | |
2629 | ✗ | sample_size = AV_RB16(track->codec_priv.data + 26); | |
2630 | ✗ | if (fourcc == 0) { | |
2631 | ✗ | if (sample_size == 8) { | |
2632 | ✗ | fourcc = MKTAG('r','a','w',' '); | |
2633 | ✗ | codec_id = ff_codec_get_id(ff_codec_movaudio_tags, fourcc); | |
2634 | ✗ | } else if (sample_size == 16) { | |
2635 | ✗ | fourcc = MKTAG('t','w','o','s'); | |
2636 | ✗ | codec_id = ff_codec_get_id(ff_codec_movaudio_tags, fourcc); | |
2637 | } | ||
2638 | } | ||
2639 | ✗ | if ((fourcc == MKTAG('t','w','o','s') || | |
2640 | ✗ | fourcc == MKTAG('s','o','w','t')) && sample_size == 8) | |
2641 | ✗ | codec_id = AV_CODEC_ID_PCM_S8; | |
2642 | ✗ | par->codec_id = codec_id; | |
2643 | ✗ | par->codec_tag = fourcc; | |
2644 | ✗ | return 0; | |
2645 | } | ||
2646 | |||
2647 |
9/12✓ Branch 0 taken 5 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 12 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 3 times.
✗ Branch 6 not taken.
✗ Branch 7 not taken.
✓ Branch 8 taken 1 times.
✓ Branch 9 taken 9 times.
✓ Branch 10 taken 2 times.
✓ Branch 11 taken 42 times.
|
83 | switch (par->codec_id) { |
2648 | 5 | case AV_CODEC_ID_PCM_S16BE: | |
2649 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 2 times.
|
5 | switch (track->audio.bitdepth) { |
2650 | ✗ | case 8: | |
2651 | ✗ | par->codec_id = AV_CODEC_ID_PCM_U8; | |
2652 | ✗ | break; | |
2653 | 1 | case 24: | |
2654 | 1 | par->codec_id = AV_CODEC_ID_PCM_S24BE; | |
2655 | 1 | break; | |
2656 | 2 | case 32: | |
2657 | 2 | par->codec_id = AV_CODEC_ID_PCM_S32BE; | |
2658 | 2 | break; | |
2659 | } | ||
2660 | 5 | break; | |
2661 | 7 | case AV_CODEC_ID_PCM_S16LE: | |
2662 |
4/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 3 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 1 times.
|
7 | switch (track->audio.bitdepth) { |
2663 | 1 | case 8: | |
2664 | 1 | par->codec_id = AV_CODEC_ID_PCM_U8; | |
2665 | 1 | break; | |
2666 | 3 | case 24: | |
2667 | 3 | par->codec_id = AV_CODEC_ID_PCM_S24LE; | |
2668 | 3 | break; | |
2669 | 2 | case 32: | |
2670 | 2 | par->codec_id = AV_CODEC_ID_PCM_S32LE; | |
2671 | 2 | break; | |
2672 | } | ||
2673 | 7 | break; | |
2674 | ✗ | case AV_CODEC_ID_PCM_F32LE: | |
2675 | ✗ | if (track->audio.bitdepth == 64) | |
2676 | ✗ | par->codec_id = AV_CODEC_ID_PCM_F64LE; | |
2677 | ✗ | break; | |
2678 | 12 | case AV_CODEC_ID_AAC: | |
2679 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (!track->codec_priv.size) { |
2680 | ✗ | int profile = matroska_aac_profile(track->codec_id); | |
2681 | ✗ | int sri = matroska_aac_sri(track->audio.samplerate); | |
2682 | |||
2683 | ✗ | extradata[0] = (profile << 3) | ((sri & 0x0E) >> 1); | |
2684 | ✗ | extradata[1] = ((sri & 0x01) << 7) | (track->audio.channels << 3); | |
2685 | ✗ | if (strstr(track->codec_id, "SBR")) { | |
2686 | ✗ | sri = matroska_aac_sri(track->audio.out_samplerate); | |
2687 | ✗ | extradata[2] = 0x56; | |
2688 | ✗ | extradata[3] = 0xE5; | |
2689 | ✗ | extradata[4] = 0x80 | (sri << 3); | |
2690 | ✗ | extradata_size = 5; | |
2691 | } else | ||
2692 | ✗ | extradata_size = 2; | |
2693 | } | ||
2694 | 12 | break; | |
2695 | 2 | case AV_CODEC_ID_ALAC: | |
2696 |
2/4✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
2 | if (track->codec_priv.size && track->codec_priv.size < INT_MAX - 12 - AV_INPUT_BUFFER_PADDING_SIZE) { |
2697 | /* Only ALAC's magic cookie is stored in Matroska's track headers. | ||
2698 | * Create the "atom size", "tag", and "tag version" fields the | ||
2699 | * decoder expects manually. */ | ||
2700 | 2 | ret = ff_alloc_extradata(par, 12 + track->codec_priv.size); | |
2701 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (ret < 0) |
2702 | ✗ | return ret; | |
2703 | 2 | AV_WB32(par->extradata, par->extradata_size); | |
2704 | 2 | AV_WB32(&par->extradata[4], MKBETAG('a', 'l', 'a', 'c')); | |
2705 | 2 | AV_WB32(&par->extradata[8], 0); | |
2706 | 2 | memcpy(&par->extradata[12], track->codec_priv.data, | |
2707 | 2 | track->codec_priv.size); | |
2708 | } | ||
2709 | 2 | break; | |
2710 | 3 | case AV_CODEC_ID_TTA: | |
2711 | { | ||
2712 | uint8_t *ptr; | ||
2713 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
3 | if (track->audio.channels > UINT16_MAX || |
2714 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | track->audio.bitdepth > UINT16_MAX) { |
2715 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, | |
2716 | "Too large audio channel number %"PRIu64 | ||
2717 | " or bitdepth %"PRIu64". Skipping track.\n", | ||
2718 | track->audio.channels, track->audio.bitdepth); | ||
2719 | ✗ | if (matroska->ctx->error_recognition & AV_EF_EXPLODE) | |
2720 | ✗ | return AVERROR_INVALIDDATA; | |
2721 | else | ||
2722 | ✗ | return SKIP_TRACK; | |
2723 | } | ||
2724 |
2/4✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
|
3 | if (track->audio.out_samplerate < 0 || track->audio.out_samplerate > INT_MAX) |
2725 | ✗ | return AVERROR_INVALIDDATA; | |
2726 | 3 | extradata_size = TTA_EXTRADATA_SIZE; | |
2727 | 3 | ptr = extradata; | |
2728 | 3 | bytestream_put_be32(&ptr, AV_RB32("TTA1")); | |
2729 | 3 | bytestream_put_le16(&ptr, 1); | |
2730 | 3 | bytestream_put_le16(&ptr, track->audio.channels); | |
2731 | 3 | bytestream_put_le16(&ptr, track->audio.bitdepth); | |
2732 | 3 | bytestream_put_le32(&ptr, track->audio.out_samplerate); | |
2733 | 3 | bytestream_put_le32(&ptr, av_rescale(matroska->duration * matroska->time_scale, | |
2734 | 3 | track->audio.out_samplerate, | |
2735 | AV_TIME_BASE * 1000)); | ||
2736 | 3 | break; | |
2737 | } | ||
2738 | ✗ | case AV_CODEC_ID_RA_144: | |
2739 | ✗ | track->audio.out_samplerate = 8000; | |
2740 | ✗ | track->audio.channels = 1; | |
2741 | ✗ | break; | |
2742 | ✗ | case AV_CODEC_ID_RA_288: | |
2743 | case AV_CODEC_ID_COOK: | ||
2744 | case AV_CODEC_ID_ATRAC3: | ||
2745 | case AV_CODEC_ID_SIPR: | ||
2746 | { | ||
2747 | ✗ | const uint8_t *ptr = track->codec_priv.data; | |
2748 | int flavor; | ||
2749 | |||
2750 | ✗ | if (!track->codec_priv.size) | |
2751 | ✗ | break; | |
2752 | |||
2753 | ✗ | if (track->codec_priv.size < 46) | |
2754 | ✗ | return AVERROR_INVALIDDATA; | |
2755 | ✗ | ptr += 22; | |
2756 | ✗ | flavor = bytestream_get_be16(&ptr); | |
2757 | ✗ | track->audio.coded_framesize = bytestream_get_be32(&ptr); | |
2758 | ✗ | ptr += 12; | |
2759 | ✗ | track->audio.sub_packet_h = bytestream_get_be16(&ptr); | |
2760 | ✗ | track->audio.frame_size = bytestream_get_be16(&ptr); | |
2761 | ✗ | track->audio.sub_packet_size = bytestream_get_be16(&ptr); | |
2762 | ✗ | if (track->audio.coded_framesize <= 0 || | |
2763 | ✗ | track->audio.sub_packet_h <= 0 || | |
2764 | ✗ | track->audio.frame_size <= 0) | |
2765 | ✗ | return AVERROR_INVALIDDATA; | |
2766 | |||
2767 | ✗ | if (par->codec_id == AV_CODEC_ID_RA_288) { | |
2768 | ✗ | if (track->audio.sub_packet_h & 1 || 2 * track->audio.frame_size | |
2769 | ✗ | != (int64_t)track->audio.sub_packet_h * track->audio.coded_framesize) | |
2770 | ✗ | return AVERROR_INVALIDDATA; | |
2771 | ✗ | par->block_align = track->audio.coded_framesize; | |
2772 | ✗ | track->codec_priv.size = 0; | |
2773 | } else { | ||
2774 | ✗ | if (par->codec_id == AV_CODEC_ID_SIPR) { | |
2775 | static const int sipr_bit_rate[4] = { 6504, 8496, 5000, 16000 }; | ||
2776 | ✗ | if (flavor > 3) | |
2777 | ✗ | return AVERROR_INVALIDDATA; | |
2778 | ✗ | track->audio.sub_packet_size = ff_sipr_subpk_size[flavor]; | |
2779 | ✗ | par->bit_rate = sipr_bit_rate[flavor]; | |
2780 | ✗ | } else if (track->audio.sub_packet_size <= 0 || | |
2781 | ✗ | track->audio.frame_size % track->audio.sub_packet_size) | |
2782 | ✗ | return AVERROR_INVALIDDATA; | |
2783 | ✗ | par->block_align = track->audio.sub_packet_size; | |
2784 | ✗ | *extradata_offset = 78; | |
2785 | } | ||
2786 | ✗ | track->audio.buf = av_malloc_array(track->audio.sub_packet_h, | |
2787 | ✗ | track->audio.frame_size); | |
2788 | ✗ | if (!track->audio.buf) | |
2789 | ✗ | return AVERROR(ENOMEM); | |
2790 | ✗ | break; | |
2791 | } | ||
2792 | 1 | case AV_CODEC_ID_ATRAC1: | |
2793 | /* ATRAC1 uses a constant frame size. | ||
2794 | * Typical ATRAC1 streams are either mono or stereo. | ||
2795 | * At most, ATRAC1 was used to store 8 channels of audio. */ | ||
2796 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (track->audio.channels > 8) |
2797 | ✗ | return AVERROR_INVALIDDATA; | |
2798 | 1 | par->block_align = track->audio.channels * 212; | |
2799 | 1 | break; | |
2800 | 9 | case AV_CODEC_ID_FLAC: | |
2801 |
1/2✓ Branch 0 taken 9 times.
✗ Branch 1 not taken.
|
9 | if (track->codec_priv.size) { |
2802 | 9 | ret = matroska_parse_flac(s, track, extradata_offset); | |
2803 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9 times.
|
9 | if (ret < 0) |
2804 | ✗ | return ret; | |
2805 | } | ||
2806 | 9 | break; | |
2807 | 2 | case AV_CODEC_ID_WAVPACK: | |
2808 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (track->codec_priv.size < 2) { |
2809 | 1 | av_log(matroska->ctx, AV_LOG_INFO, "Assuming WavPack version 4.10 " | |
2810 | "in absence of valid CodecPrivate.\n"); | ||
2811 | 1 | extradata_size = WAVPACK_EXTRADATA_SIZE; | |
2812 | 1 | AV_WL16(extradata, 0x410); | |
2813 | } | ||
2814 | 2 | break; | |
2815 | } | ||
2816 | |||
2817 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 79 times.
|
83 | if (extradata_size > 0) { |
2818 | 4 | ret = ff_alloc_extradata(par, extradata_size); | |
2819 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (ret < 0) |
2820 | ✗ | return ret; | |
2821 | 4 | memcpy(par->extradata, extradata, extradata_size); | |
2822 | } | ||
2823 | |||
2824 | 83 | return 0; | |
2825 | } | ||
2826 | |||
2827 | /* Performs the generic part of parsing an audio track. */ | ||
2828 | 84 | static int mka_parse_audio(MatroskaTrack *track, AVStream *st, | |
2829 | AVCodecParameters *par, | ||
2830 | const MatroskaDemuxContext *matroska, | ||
2831 | AVFormatContext *s, int *extradata_offset) | ||
2832 | { | ||
2833 | 84 | FFStream *const sti = ffstream(st); | |
2834 | int ret; | ||
2835 | |||
2836 | 84 | ret = mka_parse_audio_codec(track, par, matroska, | |
2837 | s, extradata_offset); | ||
2838 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
|
84 | if (ret) |
2839 | ✗ | return ret; | |
2840 | |||
2841 | 84 | par->codec_type = AVMEDIA_TYPE_AUDIO; | |
2842 | 84 | par->sample_rate = track->audio.out_samplerate; | |
2843 | // channel layout may be already set by codec private checks above | ||
2844 |
2/2✓ Branch 1 taken 75 times.
✓ Branch 2 taken 9 times.
|
84 | if (!av_channel_layout_check(&par->ch_layout)) { |
2845 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
|
75 | if (track->audio.channels > INT32_MAX) |
2846 | ✗ | return AVERROR_PATCHWELCOME; | |
2847 | 75 | par->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; | |
2848 | 75 | par->ch_layout.nb_channels = track->audio.channels; | |
2849 | } | ||
2850 |
2/2✓ Branch 0 taken 83 times.
✓ Branch 1 taken 1 times.
|
84 | if (!par->bits_per_coded_sample) |
2851 | 83 | par->bits_per_coded_sample = track->audio.bitdepth; | |
2852 |
2/2✓ Branch 0 taken 83 times.
✓ Branch 1 taken 1 times.
|
84 | if (par->codec_id == AV_CODEC_ID_MP3 || |
2853 |
1/2✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
|
83 | par->codec_id == AV_CODEC_ID_MLP || |
2854 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
|
83 | par->codec_id == AV_CODEC_ID_TRUEHD) |
2855 | 1 | sti->need_parsing = AVSTREAM_PARSE_FULL; | |
2856 |
2/2✓ Branch 0 taken 71 times.
✓ Branch 1 taken 12 times.
|
83 | else if (par->codec_id != AV_CODEC_ID_AAC) |
2857 | 71 | sti->need_parsing = AVSTREAM_PARSE_HEADERS; | |
2858 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 73 times.
|
84 | if (track->codec_delay > 0) { |
2859 | 11 | par->initial_padding = av_rescale_q(track->codec_delay, | |
2860 | 11 | (AVRational){1, 1000000000}, | |
2861 | 11 | (AVRational){1, par->codec_id == AV_CODEC_ID_OPUS ? | |
2862 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6 times.
|
11 | 48000 : par->sample_rate}); |
2863 | } | ||
2864 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 77 times.
|
84 | if (track->seek_preroll > 0) { |
2865 | 7 | par->seek_preroll = av_rescale_q(track->seek_preroll, | |
2866 | 7 | (AVRational){1, 1000000000}, | |
2867 | 7 | (AVRational){1, par->sample_rate}); | |
2868 | } | ||
2869 | |||
2870 | 84 | return 0; | |
2871 | } | ||
2872 | |||
2873 | /* Performs the codec-specific part of parsing a video track. */ | ||
2874 | 339 | static int mkv_parse_video_codec(MatroskaTrack *track, AVCodecParameters *par, | |
2875 | const MatroskaDemuxContext *matroska, | ||
2876 | int *extradata_offset) | ||
2877 | { | ||
2878 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 334 times.
|
339 | if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC") && |
2879 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | track->codec_priv.size >= 40) { |
2880 | 5 | uint32_t size = AV_RL32A(track->codec_priv.data); | |
2881 | // VFW extradata is padded to an even length, yet | ||
2882 | // the size field contains the real length. | ||
2883 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
5 | if (size & 1 && size == track->codec_priv.size - 1) |
2884 | ✗ | --track->codec_priv.size; | |
2885 | 5 | track->ms_compat = 1; | |
2886 | 5 | par->bits_per_coded_sample = AV_RL16(track->codec_priv.data + 14); | |
2887 | 5 | par->codec_tag = AV_RL32(track->codec_priv.data + 16); | |
2888 | 5 | par->codec_id = ff_codec_get_id(ff_codec_bmp_tags, | |
2889 | par->codec_tag); | ||
2890 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (!par->codec_id) |
2891 | ✗ | par->codec_id = ff_codec_get_id(ff_codec_movvideo_tags, | |
2892 | par->codec_tag); | ||
2893 | 5 | *extradata_offset = 40; | |
2894 | 5 | return 0; | |
2895 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 333 times.
|
334 | } else if (!strcmp(track->codec_id, "V_QUICKTIME") && |
2896 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | track->codec_priv.size >= 21) { |
2897 | enum AVCodecID codec_id; | ||
2898 | uint32_t fourcc; | ||
2899 | 1 | int ret = get_qt_codec(track, &fourcc, &codec_id); | |
2900 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret < 0) |
2901 | ✗ | return ret; | |
2902 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
1 | if (codec_id == AV_CODEC_ID_NONE && AV_RL32(track->codec_priv.data+4) == AV_RL32("SMI ")) { |
2903 | ✗ | fourcc = MKTAG('S','V','Q','3'); | |
2904 | ✗ | codec_id = ff_codec_get_id(ff_codec_movvideo_tags, fourcc); | |
2905 | } | ||
2906 | 1 | par->codec_id = codec_id; | |
2907 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (codec_id == AV_CODEC_ID_NONE) |
2908 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
2909 | ✗ | "mov FourCC not found %s.\n", av_fourcc2str(fourcc)); | |
2910 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (track->codec_priv.size >= 86) { |
2911 | FFIOContext b; | ||
2912 | 1 | unsigned bit_depth = AV_RB16(track->codec_priv.data + 82); | |
2913 | 1 | ffio_init_read_context(&b, track->codec_priv.data, | |
2914 | track->codec_priv.size); | ||
2915 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (ff_get_qtpalette(codec_id, &b.pub, track->palette)) { |
2916 | ✗ | bit_depth &= 0x1F; | |
2917 | ✗ | track->has_palette = 1; | |
2918 | } | ||
2919 | 1 | par->bits_per_coded_sample = bit_depth; | |
2920 | } | ||
2921 | 1 | par->codec_tag = fourcc; | |
2922 | 1 | return 0; | |
2923 | } | ||
2924 | |||
2925 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 249 times.
✓ Branch 3 taken 79 times.
|
333 | switch (par->codec_id) { |
2926 | ✗ | case AV_CODEC_ID_RV10: | |
2927 | case AV_CODEC_ID_RV20: | ||
2928 | case AV_CODEC_ID_RV30: | ||
2929 | case AV_CODEC_ID_RV40: | ||
2930 | ✗ | *extradata_offset = 26; | |
2931 | ✗ | break; | |
2932 | 5 | case AV_CODEC_ID_PRORES: | |
2933 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (track->codec_priv.size == 4) |
2934 | 5 | par->codec_tag = AV_RL32(track->codec_priv.data); | |
2935 | 5 | break; | |
2936 | 249 | case AV_CODEC_ID_VP9: | |
2937 | /* we don't need any value stored in CodecPrivate. | ||
2938 | * make sure that it's not exported as extradata. */ | ||
2939 | 249 | track->codec_priv.size = 0; | |
2940 | 249 | break; | |
2941 | } | ||
2942 | |||
2943 | 333 | return 0; | |
2944 | } | ||
2945 | |||
2946 | /* Performs the generic part of parsing a video track. */ | ||
2947 | 339 | static int mkv_parse_video(MatroskaTrack *track, AVStream *st, | |
2948 | AVCodecParameters *par, | ||
2949 | const MatroskaDemuxContext *matroska, | ||
2950 | int *extradata_offset) | ||
2951 | { | ||
2952 | 339 | FFStream *const sti = ffstream(st); | |
2953 | MatroskaTrackPlane *planes; | ||
2954 | 339 | int display_width_mul = 1; | |
2955 | 339 | int display_height_mul = 1; | |
2956 | int ret; | ||
2957 | |||
2958 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 335 times.
|
339 | if (track->video.color_space.size == 4) |
2959 | 4 | par->codec_tag = AV_RL32(track->video.color_space.data); | |
2960 | |||
2961 | 339 | ret = mkv_parse_video_codec(track, par, matroska, | |
2962 | extradata_offset); | ||
2963 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 339 times.
|
339 | if (ret < 0) |
2964 | ✗ | return ret; | |
2965 | |||
2966 | 339 | par->codec_type = AVMEDIA_TYPE_VIDEO; | |
2967 | 339 | par->width = track->video.pixel_width; | |
2968 | 339 | par->height = track->video.pixel_height; | |
2969 | |||
2970 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 332 times.
|
339 | if (track->video.interlaced == MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED) |
2971 | 7 | par->field_order = mkv_field_order(matroska, track->video.field_order); | |
2972 |
2/2✓ Branch 0 taken 21 times.
✓ Branch 1 taken 311 times.
|
332 | else if (track->video.interlaced == MATROSKA_VIDEO_INTERLACE_FLAG_PROGRESSIVE) |
2973 | 21 | par->field_order = AV_FIELD_PROGRESSIVE; | |
2974 | |||
2975 |
4/4✓ Branch 0 taken 111 times.
✓ Branch 1 taken 228 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 99 times.
|
339 | if (track->video.stereo_mode && track->video.stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB) |
2976 | 12 | mkv_stereo_mode_display_mul(track->video.stereo_mode, | |
2977 | &display_width_mul, &display_height_mul); | ||
2978 | |||
2979 |
2/2✓ Branch 0 taken 311 times.
✓ Branch 1 taken 28 times.
|
339 | if (track->video.display_unit < MATROSKA_VIDEO_DISPLAYUNIT_UNKNOWN) { |
2980 |
2/4✓ Branch 0 taken 311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 311 times.
✗ Branch 3 not taken.
|
311 | if (track->video.display_width && track->video.display_height && |
2981 |
2/4✓ Branch 0 taken 311 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 311 times.
✗ Branch 3 not taken.
|
311 | track->video.display_width != -1 && track->video.display_height != -1 && |
2982 |
1/2✓ Branch 0 taken 311 times.
✗ Branch 1 not taken.
|
311 | track->video.cropped_height < INT64_MAX / track->video.display_width / display_width_mul && |
2983 |
1/2✓ Branch 0 taken 311 times.
✗ Branch 1 not taken.
|
311 | track->video.cropped_width < INT64_MAX / track->video.display_height / display_height_mul) |
2984 | 311 | av_reduce(&st->sample_aspect_ratio.num, | |
2985 | &st->sample_aspect_ratio.den, | ||
2986 | 311 | track->video.cropped_height * track->video.display_width * display_width_mul, | |
2987 | 311 | track->video.cropped_width * track->video.display_height * display_height_mul, | |
2988 | INT_MAX); | ||
2989 | } | ||
2990 |
2/2✓ Branch 0 taken 335 times.
✓ Branch 1 taken 4 times.
|
339 | if (track->video.cropped_width != track->video.pixel_width || |
2991 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 335 times.
|
335 | track->video.cropped_height != track->video.pixel_height) { |
2992 | uint8_t *cropping; | ||
2993 | 4 | AVPacketSideData *sd = av_packet_side_data_new(&st->codecpar->coded_side_data, | |
2994 | 4 | &st->codecpar->nb_coded_side_data, | |
2995 | AV_PKT_DATA_FRAME_CROPPING, | ||
2996 | sizeof(uint32_t) * 4, 0); | ||
2997 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (!sd) |
2998 | ✗ | return AVERROR(ENOMEM); | |
2999 | |||
3000 | 4 | cropping = sd->data; | |
3001 | 4 | bytestream_put_le32(&cropping, track->video.pixel_cropt); | |
3002 | 4 | bytestream_put_le32(&cropping, track->video.pixel_cropb); | |
3003 | 4 | bytestream_put_le32(&cropping, track->video.pixel_cropl); | |
3004 | 4 | bytestream_put_le32(&cropping, track->video.pixel_cropr); | |
3005 | } | ||
3006 |
2/2✓ Branch 0 taken 326 times.
✓ Branch 1 taken 13 times.
|
339 | if (par->codec_id != AV_CODEC_ID_HEVC) |
3007 | 326 | sti->need_parsing = AVSTREAM_PARSE_HEADERS; | |
3008 | |||
3009 |
2/2✓ Branch 0 taken 297 times.
✓ Branch 1 taken 42 times.
|
339 | if (track->default_duration) { |
3010 |
1/2✓ Branch 0 taken 297 times.
✗ Branch 1 not taken.
|
297 | int div = track->default_duration <= INT64_MAX ? 1 : 2; |
3011 | 297 | av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, | |
3012 | 297 | 1000000000 / div, track->default_duration / div, 30000); | |
3013 | #if FF_API_R_FRAME_RATE | ||
3014 |
2/2✓ Branch 0 taken 295 times.
✓ Branch 1 taken 2 times.
|
297 | if ( st->avg_frame_rate.num < st->avg_frame_rate.den * 1000LL |
3015 |
2/2✓ Branch 0 taken 274 times.
✓ Branch 1 taken 21 times.
|
295 | && st->avg_frame_rate.num > st->avg_frame_rate.den * 5LL) |
3016 | 274 | st->r_frame_rate = st->avg_frame_rate; | |
3017 | #endif | ||
3018 | } | ||
3019 | |||
3020 | /* export stereo mode flag as metadata tag */ | ||
3021 |
4/4✓ Branch 0 taken 111 times.
✓ Branch 1 taken 228 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 99 times.
|
339 | if (track->video.stereo_mode && track->video.stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB) |
3022 | 12 | av_dict_set(&st->metadata, "stereo_mode", ff_matroska_video_stereo_mode[track->video.stereo_mode], 0); | |
3023 | |||
3024 | /* export alpha mode flag as metadata tag */ | ||
3025 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 336 times.
|
339 | if (track->video.alpha_mode) |
3026 | 3 | av_dict_set_int(&st->metadata, "alpha_mode", 1, 0); | |
3027 | |||
3028 | /* if we have virtual track, mark the real tracks */ | ||
3029 | 339 | planes = track->operation.combine_planes.elem; | |
3030 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 339 times.
|
339 | for (int j = 0; j < track->operation.combine_planes.nb_elem; j++) { |
3031 | ✗ | MatroskaTrack *tracks = matroska->tracks.elem; | |
3032 | char buf[32]; | ||
3033 | ✗ | if (planes[j].type >= MATROSKA_VIDEO_STEREO_PLANE_COUNT) | |
3034 | ✗ | continue; | |
3035 | ✗ | snprintf(buf, sizeof(buf), "%s_%d", | |
3036 | ✗ | matroska_video_stereo_plane[planes[j].type], st->index); | |
3037 | ✗ | for (int k = 0; k < matroska->tracks.nb_elem; k++) | |
3038 | ✗ | if (planes[j].uid == tracks[k].uid && tracks[k].stream) { | |
3039 | ✗ | av_dict_set(&tracks[k].stream->metadata, | |
3040 | "stereo_mode", buf, 0); | ||
3041 | ✗ | break; | |
3042 | } | ||
3043 | } | ||
3044 | // add stream level stereo3d side data if it is a supported format | ||
3045 |
2/2✓ Branch 0 taken 240 times.
✓ Branch 1 taken 99 times.
|
339 | if (track->video.stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB && |
3046 |
2/2✓ Branch 0 taken 238 times.
✓ Branch 1 taken 2 times.
|
240 | track->video.stereo_mode != MATROSKA_VIDEO_STEREOMODE_TYPE_ANAGLYPH_CYAN_RED && |
3047 |
2/2✓ Branch 0 taken 236 times.
✓ Branch 1 taken 2 times.
|
238 | track->video.stereo_mode != MATROSKA_VIDEO_STEREOMODE_TYPE_ANAGLYPH_GREEN_MAG) { |
3048 | 236 | int ret = mkv_stereo3d_conv(st, track->video.stereo_mode); | |
3049 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 236 times.
|
236 | if (ret < 0) |
3050 | ✗ | return ret; | |
3051 | } | ||
3052 | |||
3053 | 339 | ret = mkv_parse_video_color(st, track); | |
3054 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 339 times.
|
339 | if (ret < 0) |
3055 | ✗ | return ret; | |
3056 | 339 | ret = mkv_parse_video_projection(st, track, matroska->ctx); | |
3057 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 339 times.
|
339 | if (ret < 0) |
3058 | ✗ | return ret; | |
3059 | |||
3060 | 339 | return 0; | |
3061 | } | ||
3062 | |||
3063 | /* Performs the codec-specific part of parsing a subtitle track. */ | ||
3064 | 24 | static int mkv_parse_subtitle_codec(MatroskaTrack *track, AVStream *st, | |
3065 | AVCodecParameters *par, | ||
3066 | const MatroskaDemuxContext *matroska) | ||
3067 | { | ||
3068 |
2/3✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 16 times.
|
24 | switch (par->codec_id) { |
3069 | ✗ | case AV_CODEC_ID_ARIB_CAPTION: | |
3070 | ✗ | if (track->codec_priv.size == 3) { | |
3071 | ✗ | int component_tag = track->codec_priv.data[0]; | |
3072 | ✗ | int data_component_id = AV_RB16(track->codec_priv.data + 1); | |
3073 | |||
3074 | ✗ | switch (data_component_id) { | |
3075 | ✗ | case 0x0008: | |
3076 | // [0x30..0x37] are component tags utilized for | ||
3077 | // non-mobile captioning service ("profile A"). | ||
3078 | ✗ | if (component_tag >= 0x30 && component_tag <= 0x37) { | |
3079 | ✗ | par->profile = AV_PROFILE_ARIB_PROFILE_A; | |
3080 | } | ||
3081 | ✗ | break; | |
3082 | ✗ | case 0x0012: | |
3083 | // component tag 0x87 signifies a mobile/partial reception | ||
3084 | // (1seg) captioning service ("profile C"). | ||
3085 | ✗ | if (component_tag == 0x87) { | |
3086 | ✗ | par->profile = AV_PROFILE_ARIB_PROFILE_C; | |
3087 | } | ||
3088 | ✗ | break; | |
3089 | ✗ | default: | |
3090 | ✗ | break; | |
3091 | } | ||
3092 | |||
3093 | ✗ | if (par->profile == AV_PROFILE_UNKNOWN) | |
3094 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, | |
3095 | "Unknown ARIB caption profile utilized: %02x / %04x\n", | ||
3096 | component_tag, data_component_id); | ||
3097 | |||
3098 | ✗ | track->codec_priv.size = 0; | |
3099 | } | ||
3100 | ✗ | break; | |
3101 | 8 | case AV_CODEC_ID_WEBVTT: | |
3102 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
|
8 | if (!strcmp(track->codec_id, "D_WEBVTT/CAPTIONS")) { |
3103 | 2 | st->disposition |= AV_DISPOSITION_CAPTIONS; | |
3104 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
|
6 | } else if (!strcmp(track->codec_id, "D_WEBVTT/DESCRIPTIONS")) { |
3105 | 2 | st->disposition |= AV_DISPOSITION_DESCRIPTIONS; | |
3106 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | } else if (!strcmp(track->codec_id, "D_WEBVTT/METADATA")) { |
3107 | 2 | st->disposition |= AV_DISPOSITION_METADATA; | |
3108 | } | ||
3109 | 8 | break; | |
3110 | } | ||
3111 | |||
3112 | 24 | return 0; | |
3113 | } | ||
3114 | |||
3115 | 372 | static int matroska_parse_tracks(AVFormatContext *s) | |
3116 | { | ||
3117 | 372 | MatroskaDemuxContext *matroska = s->priv_data; | |
3118 | 372 | MatroskaTrack *tracks = matroska->tracks.elem; | |
3119 | int i, j, ret; | ||
3120 | |||
3121 |
2/2✓ Branch 0 taken 447 times.
✓ Branch 1 taken 372 times.
|
819 | for (i = 0; i < matroska->tracks.nb_elem; i++) { |
3122 | 447 | MatroskaTrack *track = &tracks[i]; | |
3123 | 447 | enum AVCodecID codec_id = AV_CODEC_ID_NONE; | |
3124 | AVCodecParameters *par; | ||
3125 | MatroskaTrackType type; | ||
3126 | 447 | int extradata_offset = 0; | |
3127 | AVStream *st; | ||
3128 | 447 | char* key_id_base64 = NULL; | |
3129 | |||
3130 | /* Apply some sanity checks. */ | ||
3131 |
2/2✓ Branch 0 taken 108 times.
✓ Branch 1 taken 339 times.
|
447 | if (track->type != MATROSKA_TRACK_TYPE_VIDEO && |
3132 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 84 times.
|
108 | track->type != MATROSKA_TRACK_TYPE_AUDIO && |
3133 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 20 times.
|
24 | track->type != MATROSKA_TRACK_TYPE_SUBTITLE && |
3134 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | track->type != MATROSKA_TRACK_TYPE_METADATA) { |
3135 | ✗ | av_log(matroska->ctx, AV_LOG_INFO, | |
3136 | "Unknown or unsupported track type %"PRIu64"\n", | ||
3137 | track->type); | ||
3138 | ✗ | continue; | |
3139 | } | ||
3140 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 447 times.
|
447 | if (!track->codec_id) |
3141 | ✗ | continue; | |
3142 | |||
3143 |
3/4✓ Branch 0 taken 84 times.
✓ Branch 1 taken 363 times.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
|
447 | if ( track->type == MATROSKA_TRACK_TYPE_AUDIO && track->codec_id[0] != 'A' |
3144 |
3/4✓ Branch 0 taken 339 times.
✓ Branch 1 taken 108 times.
✓ Branch 2 taken 339 times.
✗ Branch 3 not taken.
|
447 | || track->type == MATROSKA_TRACK_TYPE_VIDEO && track->codec_id[0] != 'V' |
3145 |
5/6✓ Branch 0 taken 20 times.
✓ Branch 1 taken 427 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
|
447 | || track->type == MATROSKA_TRACK_TYPE_SUBTITLE && track->codec_id[0] != 'D' && track->codec_id[0] != 'S' |
3146 |
3/6✓ Branch 0 taken 4 times.
✓ Branch 1 taken 443 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
447 | || track->type == MATROSKA_TRACK_TYPE_METADATA && track->codec_id[0] != 'D' && track->codec_id[0] != 'S' |
3147 | ) { | ||
3148 | ✗ | av_log(matroska->ctx, AV_LOG_INFO, "Inconsistent track type\n"); | |
3149 | ✗ | continue; | |
3150 | } | ||
3151 | |||
3152 |
2/4✓ Branch 0 taken 447 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 447 times.
✗ Branch 3 not taken.
|
447 | if (track->audio.samplerate < 0 || track->audio.samplerate > INT_MAX || |
3153 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 447 times.
|
447 | isnan(track->audio.samplerate)) { |
3154 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, | |
3155 | "Invalid sample rate %f, defaulting to 8000 instead.\n", | ||
3156 | track->audio.samplerate); | ||
3157 | ✗ | track->audio.samplerate = 8000; | |
3158 | } | ||
3159 | |||
3160 |
2/2✓ Branch 0 taken 339 times.
✓ Branch 1 taken 108 times.
|
447 | if (track->type == MATROSKA_TRACK_TYPE_VIDEO) { |
3161 |
4/4✓ Branch 0 taken 246 times.
✓ Branch 1 taken 93 times.
✓ Branch 2 taken 204 times.
✓ Branch 3 taken 42 times.
|
339 | if (!track->default_duration && track->video.frame_rate > 0) { |
3162 | 204 | double default_duration = 1000000000 / track->video.frame_rate; | |
3163 |
2/4✓ Branch 0 taken 204 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 204 times.
|
204 | if (default_duration > UINT64_MAX || default_duration < 0) { |
3164 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, | |
3165 | "Invalid frame rate %e. Cannot calculate default duration.\n", | ||
3166 | track->video.frame_rate); | ||
3167 | } else { | ||
3168 | 204 | track->default_duration = default_duration; | |
3169 | } | ||
3170 | } | ||
3171 |
1/2✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
|
339 | if (track->video.pixel_cropl >= INT_MAX - track->video.pixel_cropr || |
3172 |
1/2✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
|
339 | track->video.pixel_cropt >= INT_MAX - track->video.pixel_cropb || |
3173 |
1/2✓ Branch 0 taken 339 times.
✗ Branch 1 not taken.
|
339 | (track->video.pixel_cropl + track->video.pixel_cropr) >= track->video.pixel_width || |
3174 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 339 times.
|
339 | (track->video.pixel_cropt + track->video.pixel_cropb) >= track->video.pixel_height) |
3175 | ✗ | return AVERROR_INVALIDDATA; | |
3176 | 339 | track->video.cropped_width = track->video.pixel_width - | |
3177 | 339 | track->video.pixel_cropl - track->video.pixel_cropr; | |
3178 | 339 | track->video.cropped_height = track->video.pixel_height - | |
3179 | 339 | track->video.pixel_cropt - track->video.pixel_cropb; | |
3180 |
2/2✓ Branch 0 taken 296 times.
✓ Branch 1 taken 43 times.
|
339 | if (track->video.display_unit == MATROSKA_VIDEO_DISPLAYUNIT_PIXELS) { |
3181 |
2/2✓ Branch 0 taken 263 times.
✓ Branch 1 taken 33 times.
|
296 | if (track->video.display_width == -1) |
3182 | 263 | track->video.display_width = track->video.cropped_width; | |
3183 |
2/2✓ Branch 0 taken 263 times.
✓ Branch 1 taken 33 times.
|
296 | if (track->video.display_height == -1) |
3184 | 263 | track->video.display_height = track->video.cropped_height; | |
3185 | } | ||
3186 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 24 times.
|
108 | } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) { |
3187 |
2/2✓ Branch 0 taken 83 times.
✓ Branch 1 taken 1 times.
|
84 | if (!track->audio.out_samplerate) |
3188 | 83 | track->audio.out_samplerate = track->audio.samplerate; | |
3189 | } | ||
3190 | 447 | ret = matroska_parse_content_encodings(track->encodings.elem, | |
3191 | 447 | track->encodings.nb_elem, | |
3192 | 447 | track, &key_id_base64, matroska->ctx); | |
3193 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 447 times.
|
447 | if (ret < 0) |
3194 | ✗ | return ret; | |
3195 | |||
3196 |
2/2✓ Branch 0 taken 26799 times.
✓ Branch 1 taken 7 times.
|
26806 | for (j = 0; ff_mkv_codec_tags[j].id != AV_CODEC_ID_NONE; j++) { |
3197 |
2/2✓ Branch 1 taken 440 times.
✓ Branch 2 taken 26359 times.
|
26799 | if (av_strstart(track->codec_id, ff_mkv_codec_tags[j].str, NULL)) { |
3198 | 440 | codec_id = ff_mkv_codec_tags[j].id; | |
3199 | 440 | break; | |
3200 | } | ||
3201 | } | ||
3202 | |||
3203 | 447 | st = track->stream = avformat_new_stream(s, NULL); | |
3204 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 447 times.
|
447 | if (!st) { |
3205 | ✗ | av_free(key_id_base64); | |
3206 | ✗ | return AVERROR(ENOMEM); | |
3207 | } | ||
3208 | 447 | par = st->codecpar; | |
3209 | |||
3210 | 447 | par->codec_id = codec_id; | |
3211 | |||
3212 |
2/2✓ Branch 0 taken 359 times.
✓ Branch 1 taken 88 times.
|
447 | if (track->flag_default) |
3213 | 359 | st->disposition |= AV_DISPOSITION_DEFAULT; | |
3214 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 443 times.
|
447 | if (track->flag_forced) |
3215 | 4 | st->disposition |= AV_DISPOSITION_FORCED; | |
3216 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 445 times.
|
447 | if (track->flag_comment) |
3217 | 2 | st->disposition |= AV_DISPOSITION_COMMENT; | |
3218 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 439 times.
|
447 | if (track->flag_hearingimpaired) |
3219 | 8 | st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED; | |
3220 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 445 times.
|
447 | if (track->flag_visualimpaired) |
3221 | 2 | st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; | |
3222 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 443 times.
|
447 | if (track->flag_original.count > 0) |
3223 | 4 | st->disposition |= track->flag_original.el.u ? AV_DISPOSITION_ORIGINAL | |
3224 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | : AV_DISPOSITION_DUB; |
3225 | |||
3226 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 447 times.
|
447 | if (key_id_base64) { |
3227 | /* export encryption key id as base64 metadata tag */ | ||
3228 | ✗ | av_dict_set(&st->metadata, "enc_key_id", key_id_base64, | |
3229 | AV_DICT_DONT_STRDUP_VAL); | ||
3230 | } | ||
3231 | |||
3232 |
2/2✓ Branch 0 taken 323 times.
✓ Branch 1 taken 124 times.
|
447 | if (strcmp(track->language, "und")) |
3233 | 323 | av_dict_set(&st->metadata, "language", track->language, 0); | |
3234 | 447 | av_dict_set(&st->metadata, "title", track->name, 0); | |
3235 | |||
3236 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 447 times.
|
447 | if (track->time_scale < 0.01) { |
3237 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, | |
3238 | "Track TimestampScale too small %f, assuming 1.0.\n", | ||
3239 | track->time_scale); | ||
3240 | ✗ | track->time_scale = 1.0; | |
3241 | } | ||
3242 | |||
3243 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 447 times.
|
447 | if (matroska->time_scale * track->time_scale > UINT_MAX) |
3244 | ✗ | return AVERROR_INVALIDDATA; | |
3245 | |||
3246 | 447 | avpriv_set_pts_info(st, 64, matroska->time_scale * track->time_scale, | |
3247 | 1000 * 1000 * 1000); /* 64 bit pts in ns */ | ||
3248 | |||
3249 | /* convert the delay from ns to the track timebase */ | ||
3250 | 447 | track->codec_delay_in_track_tb = av_rescale_q(track->codec_delay, | |
3251 | 447 | (AVRational){ 1, 1000000000 }, | |
3252 | st->time_base); | ||
3253 | |||
3254 | 447 | type = track->type; | |
3255 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 439 times.
|
447 | if (par->codec_id == AV_CODEC_ID_WEBVTT) |
3256 | 8 | type = MATROSKA_TRACK_TYPE_SUBTITLE; | |
3257 |
3/4✓ Branch 0 taken 84 times.
✓ Branch 1 taken 339 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
|
447 | switch (type) { |
3258 | 84 | case MATROSKA_TRACK_TYPE_AUDIO: | |
3259 | 84 | ret = mka_parse_audio(track, st, par, matroska, | |
3260 | s, &extradata_offset); | ||
3261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
|
84 | if (ret < 0) |
3262 | ✗ | return ret; | |
3263 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
|
84 | if (ret == SKIP_TRACK) |
3264 | ✗ | continue; | |
3265 | 84 | break; | |
3266 | 339 | case MATROSKA_TRACK_TYPE_VIDEO: | |
3267 | 339 | ret = mkv_parse_video(track, st, par, matroska, &extradata_offset); | |
3268 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 339 times.
|
339 | if (ret < 0) |
3269 | ✗ | return ret; | |
3270 | 339 | break; | |
3271 | 24 | case MATROSKA_TRACK_TYPE_SUBTITLE: | |
3272 | 24 | ret = mkv_parse_subtitle_codec(track, st, par, matroska); | |
3273 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | if (ret < 0) |
3274 | ✗ | return ret; | |
3275 | 24 | par->codec_type = AVMEDIA_TYPE_SUBTITLE; | |
3276 | |||
3277 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | if (track->flag_textdescriptions) |
3278 | ✗ | st->disposition |= AV_DISPOSITION_DESCRIPTIONS; | |
3279 | 24 | break; | |
3280 | } | ||
3281 | |||
3282 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 447 times.
|
447 | if (par->codec_id == AV_CODEC_ID_NONE) |
3283 | ✗ | av_log(matroska->ctx, AV_LOG_INFO, | |
3284 | "Unknown/unsupported AVCodecID %s.\n", track->codec_id); | ||
3285 | |||
3286 |
4/4✓ Branch 0 taken 440 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 138 times.
✓ Branch 3 taken 302 times.
|
447 | if (!par->extradata && track->codec_priv.size > extradata_offset) { |
3287 | 138 | const uint8_t *src = track->codec_priv.data + extradata_offset; | |
3288 | 138 | unsigned extra_size = track->codec_priv.size - extradata_offset; | |
3289 | 138 | ret = ff_alloc_extradata(par, extra_size); | |
3290 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 138 times.
|
138 | if (ret < 0) |
3291 | ✗ | return ret; | |
3292 | 138 | memcpy(par->extradata, src, extra_size); | |
3293 | } | ||
3294 | |||
3295 | 447 | ret = mkv_parse_block_addition_mappings(s, st, track); | |
3296 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 447 times.
|
447 | if (ret < 0) |
3297 | ✗ | return ret; | |
3298 | } | ||
3299 | |||
3300 | 372 | return 0; | |
3301 | } | ||
3302 | |||
3303 | 372 | static int matroska_read_header(AVFormatContext *s) | |
3304 | { | ||
3305 | 372 | FFFormatContext *const si = ffformatcontext(s); | |
3306 | 372 | MatroskaDemuxContext *matroska = s->priv_data; | |
3307 | 372 | EbmlList *attachments_list = &matroska->attachments; | |
3308 | 372 | EbmlList *chapters_list = &matroska->chapters; | |
3309 | MatroskaAttachment *attachments; | ||
3310 | MatroskaChapter *chapters; | ||
3311 | 372 | uint64_t max_start = 0; | |
3312 | int64_t pos; | ||
3313 | 372 | Ebml ebml = { 0 }; | |
3314 | int i, j, res; | ||
3315 | |||
3316 | 372 | matroska->ctx = s; | |
3317 | 372 | matroska->cues_parsing_deferred = 1; | |
3318 | |||
3319 | /* First read the EBML header. */ | ||
3320 |
2/4✓ Branch 1 taken 372 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 372 times.
|
372 | if (ebml_parse(matroska, ebml_syntax, &ebml) || !ebml.doctype) { |
3321 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "EBML header parsing failed\n"); | |
3322 | ✗ | ebml_free(ebml_syntax, &ebml); | |
3323 | ✗ | return AVERROR_INVALIDDATA; | |
3324 | } | ||
3325 |
1/2✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
|
372 | if (ebml.version > EBML_VERSION || |
3326 |
1/2✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
|
372 | ebml.max_size > sizeof(uint64_t) || |
3327 |
1/2✓ Branch 0 taken 372 times.
✗ Branch 1 not taken.
|
372 | ebml.id_length > sizeof(uint32_t) || |
3328 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
|
372 | ebml.doctype_version > 3) { |
3329 | ✗ | avpriv_report_missing_feature(matroska->ctx, | |
3330 | "EBML version %"PRIu64", doctype %s, doc version %"PRIu64, | ||
3331 | ebml.version, ebml.doctype, ebml.doctype_version); | ||
3332 | ✗ | ebml_free(ebml_syntax, &ebml); | |
3333 | ✗ | return AVERROR_PATCHWELCOME; | |
3334 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
|
372 | } else if (ebml.doctype_version == 3) { |
3335 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, | |
3336 | "EBML header using unsupported features\n" | ||
3337 | "(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n", | ||
3338 | ebml.version, ebml.doctype, ebml.doctype_version); | ||
3339 | } | ||
3340 |
1/2✓ Branch 0 taken 640 times.
✗ Branch 1 not taken.
|
640 | for (i = 0; i < FF_ARRAY_ELEMS(matroska_doctypes); i++) |
3341 |
2/2✓ Branch 0 taken 372 times.
✓ Branch 1 taken 268 times.
|
640 | if (!strcmp(ebml.doctype, matroska_doctypes[i])) |
3342 | 372 | break; | |
3343 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
|
372 | if (i >= FF_ARRAY_ELEMS(matroska_doctypes)) { |
3344 | ✗ | av_log(s, AV_LOG_WARNING, "Unknown EBML doctype '%s'\n", ebml.doctype); | |
3345 | ✗ | if (matroska->ctx->error_recognition & AV_EF_EXPLODE) { | |
3346 | ✗ | ebml_free(ebml_syntax, &ebml); | |
3347 | ✗ | return AVERROR_INVALIDDATA; | |
3348 | } | ||
3349 | } | ||
3350 | 372 | matroska->is_webm = !strcmp(ebml.doctype, "webm"); | |
3351 | |||
3352 | 372 | ebml_free(ebml_syntax, &ebml); | |
3353 | |||
3354 | 372 | matroska->pkt = si->parse_pkt; | |
3355 | |||
3356 | /* The next thing is a segment. */ | ||
3357 | 372 | pos = avio_tell(matroska->ctx->pb); | |
3358 | 372 | res = ebml_parse(matroska, matroska_segments, matroska); | |
3359 | // Try resyncing until we find an EBML_STOP type element. | ||
3360 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
|
372 | while (res != 1) { |
3361 | ✗ | res = matroska_resync(matroska, pos); | |
3362 | ✗ | if (res < 0) | |
3363 | ✗ | return res; | |
3364 | ✗ | pos = avio_tell(matroska->ctx->pb); | |
3365 | ✗ | res = ebml_parse(matroska, matroska_segment, matroska); | |
3366 | ✗ | if (res == AVERROR(EIO)) // EOF is translated to EIO, this exists the loop on EOF | |
3367 | ✗ | return res; | |
3368 | } | ||
3369 | /* Set data_offset as it might be needed later by seek_frame_generic. */ | ||
3370 |
2/2✓ Branch 0 taken 368 times.
✓ Branch 1 taken 4 times.
|
372 | if (matroska->current_id == MATROSKA_ID_CLUSTER) |
3371 | 368 | si->data_offset = avio_tell(matroska->ctx->pb) - 4; | |
3372 | 372 | matroska_execute_seekhead(matroska); | |
3373 | |||
3374 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
|
372 | if (!matroska->time_scale) |
3375 | ✗ | matroska->time_scale = 1000000; | |
3376 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
|
372 | if (isnan(matroska->duration)) |
3377 | ✗ | matroska->duration = 0; | |
3378 |
2/2✓ Branch 0 taken 361 times.
✓ Branch 1 taken 11 times.
|
372 | if (matroska->duration) |
3379 | 361 | matroska->ctx->duration = matroska->duration * matroska->time_scale * | |
3380 | 361 | 1000 / AV_TIME_BASE; | |
3381 | 372 | av_dict_set(&s->metadata, "title", matroska->title, 0); | |
3382 | 372 | av_dict_set(&s->metadata, "encoder", matroska->muxingapp, 0); | |
3383 | |||
3384 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 354 times.
|
372 | if (matroska->date_utc.size == 8) |
3385 | 18 | matroska_metadata_creation_time(&s->metadata, AV_RB64(matroska->date_utc.data)); | |
3386 | |||
3387 | 372 | res = matroska_parse_tracks(s); | |
3388 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 372 times.
|
372 | if (res < 0) |
3389 | ✗ | return res; | |
3390 | |||
3391 | 372 | attachments = attachments_list->elem; | |
3392 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 372 times.
|
376 | for (j = 0; j < attachments_list->nb_elem; j++) { |
3393 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | if (!(attachments[j].filename && attachments[j].mime && |
3394 |
2/4✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
|
4 | attachments[j].bin.data && attachments[j].bin.size > 0)) { |
3395 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "incomplete attachment\n"); | |
3396 | } else { | ||
3397 | 4 | AVStream *st = avformat_new_stream(s, NULL); | |
3398 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (!st) |
3399 | ✗ | break; | |
3400 | 4 | av_dict_set(&st->metadata, "filename", attachments[j].filename, 0); | |
3401 | 4 | av_dict_set(&st->metadata, "mimetype", attachments[j].mime, 0); | |
3402 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (attachments[j].description) |
3403 | ✗ | av_dict_set(&st->metadata, "title", attachments[j].description, 0); | |
3404 | 4 | st->codecpar->codec_id = AV_CODEC_ID_NONE; | |
3405 | |||
3406 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
|
20 | for (i = 0; mkv_image_mime_tags[i].id != AV_CODEC_ID_NONE; i++) { |
3407 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
|
16 | if (av_strstart(attachments[j].mime, mkv_image_mime_tags[i].str, NULL)) { |
3408 | ✗ | st->codecpar->codec_id = mkv_image_mime_tags[i].id; | |
3409 | ✗ | break; | |
3410 | } | ||
3411 | } | ||
3412 | |||
3413 | 4 | attachments[j].stream = st; | |
3414 | |||
3415 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (st->codecpar->codec_id != AV_CODEC_ID_NONE) { |
3416 | ✗ | res = ff_add_attached_pic(s, st, NULL, &attachments[j].bin.buf, 0); | |
3417 | ✗ | if (res < 0) | |
3418 | ✗ | return res; | |
3419 | } else { | ||
3420 | 4 | st->codecpar->codec_type = AVMEDIA_TYPE_ATTACHMENT; | |
3421 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (ff_alloc_extradata(st->codecpar, attachments[j].bin.size)) |
3422 | ✗ | break; | |
3423 | 4 | memcpy(st->codecpar->extradata, attachments[j].bin.data, | |
3424 | 4 | attachments[j].bin.size); | |
3425 | |||
3426 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 4 times.
|
20 | for (i = 0; mkv_mime_tags[i].id != AV_CODEC_ID_NONE; i++) { |
3427 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
|
16 | if (av_strstart(attachments[j].mime, mkv_mime_tags[i].str, NULL)) { |
3428 | ✗ | st->codecpar->codec_id = mkv_mime_tags[i].id; | |
3429 | ✗ | break; | |
3430 | } | ||
3431 | } | ||
3432 | } | ||
3433 | } | ||
3434 | } | ||
3435 | |||
3436 | 372 | chapters = chapters_list->elem; | |
3437 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 372 times.
|
386 | for (i = 0; i < chapters_list->nb_elem; i++) |
3438 |
4/6✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 14 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 4 times.
✓ Branch 5 taken 10 times.
|
14 | if (chapters[i].start != AV_NOPTS_VALUE && chapters[i].uid && |
3439 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | (max_start == 0 || chapters[i].start > max_start)) { |
3440 | 28 | chapters[i].chapter = | |
3441 | 14 | avpriv_new_chapter(s, chapters[i].uid, | |
3442 | 14 | (AVRational) { 1, 1000000000 }, | |
3443 | 14 | chapters[i].start, chapters[i].end, | |
3444 | 14 | chapters[i].title); | |
3445 | 14 | max_start = chapters[i].start; | |
3446 | } | ||
3447 | |||
3448 | 372 | matroska_add_index_entries(matroska); | |
3449 | |||
3450 | 372 | matroska_convert_tags(s); | |
3451 | |||
3452 | 372 | return 0; | |
3453 | } | ||
3454 | |||
3455 | /* | ||
3456 | * Put one packet in an application-supplied AVPacket struct. | ||
3457 | * Returns 0 on success or -1 on failure. | ||
3458 | */ | ||
3459 | 60279 | static int matroska_deliver_packet(MatroskaDemuxContext *matroska, | |
3460 | AVPacket *pkt) | ||
3461 | { | ||
3462 |
2/2✓ Branch 0 taken 29517 times.
✓ Branch 1 taken 30762 times.
|
60279 | if (matroska->queue.head) { |
3463 | 29517 | MatroskaTrack *tracks = matroska->tracks.elem; | |
3464 | MatroskaTrack *track; | ||
3465 | |||
3466 | 29517 | avpriv_packet_list_get(&matroska->queue, pkt); | |
3467 | 29517 | track = &tracks[pkt->stream_index]; | |
3468 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29517 times.
|
29517 | if (track->has_palette) { |
3469 | ✗ | uint8_t *pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); | |
3470 | ✗ | if (!pal) { | |
3471 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "Cannot append palette to packet\n"); | |
3472 | } else { | ||
3473 | ✗ | memcpy(pal, track->palette, AVPALETTE_SIZE); | |
3474 | } | ||
3475 | ✗ | track->has_palette = 0; | |
3476 | } | ||
3477 | 29517 | return 0; | |
3478 | } | ||
3479 | |||
3480 | 30762 | return -1; | |
3481 | } | ||
3482 | |||
3483 | /* | ||
3484 | * Free all packets in our internal queue. | ||
3485 | */ | ||
3486 | 1210 | static void matroska_clear_queue(MatroskaDemuxContext *matroska) | |
3487 | { | ||
3488 | 1210 | avpriv_packet_list_free(&matroska->queue); | |
3489 | 1210 | } | |
3490 | |||
3491 | 29887 | static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, | |
3492 | int size, int type, AVIOContext *pb, | ||
3493 | uint32_t lace_size[256], int *laces) | ||
3494 | { | ||
3495 | int n; | ||
3496 | 29887 | uint8_t *data = *buf; | |
3497 | |||
3498 |
2/2✓ Branch 0 taken 29812 times.
✓ Branch 1 taken 75 times.
|
29887 | if (!type) { |
3499 | 29812 | *laces = 1; | |
3500 | 29812 | lace_size[0] = size; | |
3501 | 29812 | return 0; | |
3502 | } | ||
3503 | |||
3504 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
|
75 | if (size <= 0) |
3505 | ✗ | return AVERROR_INVALIDDATA; | |
3506 | |||
3507 | 75 | *laces = *data + 1; | |
3508 | 75 | data += 1; | |
3509 | 75 | size -= 1; | |
3510 | |||
3511 |
3/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
|
75 | switch (type) { |
3512 | 4 | case 0x1: /* Xiph lacing */ | |
3513 | { | ||
3514 | uint8_t temp; | ||
3515 | 4 | uint32_t total = 0; | |
3516 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 4 times.
|
27 | for (n = 0; n < *laces - 1; n++) { |
3517 | 23 | lace_size[n] = 0; | |
3518 | |||
3519 | do { | ||
3520 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
25 | if (size <= total) |
3521 | ✗ | return AVERROR_INVALIDDATA; | |
3522 | 25 | temp = *data; | |
3523 | 25 | total += temp; | |
3524 | 25 | lace_size[n] += temp; | |
3525 | 25 | data += 1; | |
3526 | 25 | size -= 1; | |
3527 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23 times.
|
25 | } while (temp == 0xff); |
3528 | } | ||
3529 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (size < total) |
3530 | ✗ | return AVERROR_INVALIDDATA; | |
3531 | |||
3532 | 4 | lace_size[n] = size - total; | |
3533 | 4 | break; | |
3534 | } | ||
3535 | |||
3536 | 17 | case 0x2: /* fixed-size lacing */ | |
3537 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (size % (*laces)) |
3538 | ✗ | return AVERROR_INVALIDDATA; | |
3539 |
2/2✓ Branch 0 taken 81 times.
✓ Branch 1 taken 17 times.
|
98 | for (n = 0; n < *laces; n++) |
3540 | 81 | lace_size[n] = size / *laces; | |
3541 | 17 | break; | |
3542 | |||
3543 | 54 | case 0x3: /* EBML lacing */ | |
3544 | { | ||
3545 | uint64_t num; | ||
3546 | uint64_t total; | ||
3547 | int offset; | ||
3548 | |||
3549 | 54 | avio_skip(pb, 4); | |
3550 | |||
3551 | 54 | n = ebml_read_num(matroska, pb, 8, &num, 1); | |
3552 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (n < 0) |
3553 | ✗ | return n; | |
3554 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (num > INT_MAX) |
3555 | ✗ | return AVERROR_INVALIDDATA; | |
3556 | |||
3557 | 54 | total = lace_size[0] = num; | |
3558 | 54 | offset = n; | |
3559 |
2/2✓ Branch 0 taken 236 times.
✓ Branch 1 taken 54 times.
|
290 | for (n = 1; n < *laces - 1; n++) { |
3560 | int64_t snum; | ||
3561 | int r; | ||
3562 | 236 | r = matroska_ebmlnum_sint(matroska, pb, &snum); | |
3563 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 236 times.
|
236 | if (r < 0) |
3564 | ✗ | return r; | |
3565 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 236 times.
|
236 | if (lace_size[n - 1] + snum > (uint64_t)INT_MAX) |
3566 | ✗ | return AVERROR_INVALIDDATA; | |
3567 | |||
3568 | 236 | lace_size[n] = lace_size[n - 1] + snum; | |
3569 | 236 | total += lace_size[n]; | |
3570 | 236 | offset += r; | |
3571 | } | ||
3572 | 54 | data += offset; | |
3573 | 54 | size -= offset; | |
3574 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (size < total) |
3575 | ✗ | return AVERROR_INVALIDDATA; | |
3576 | |||
3577 | 54 | lace_size[*laces - 1] = size - total; | |
3578 | 54 | break; | |
3579 | } | ||
3580 | } | ||
3581 | |||
3582 | 75 | *buf = data; | |
3583 | |||
3584 | 75 | return 0; | |
3585 | } | ||
3586 | |||
3587 | ✗ | static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, | |
3588 | MatroskaTrack *track, AVStream *st, | ||
3589 | uint8_t *data, int size, uint64_t timecode, | ||
3590 | int64_t pos) | ||
3591 | { | ||
3592 | ✗ | const int a = st->codecpar->block_align; | |
3593 | ✗ | const int sps = track->audio.sub_packet_size; | |
3594 | ✗ | const int cfs = track->audio.coded_framesize; | |
3595 | ✗ | const int h = track->audio.sub_packet_h; | |
3596 | ✗ | const int w = track->audio.frame_size; | |
3597 | ✗ | int y = track->audio.sub_packet_cnt; | |
3598 | int x; | ||
3599 | |||
3600 | ✗ | if (!track->audio.pkt_cnt) { | |
3601 | ✗ | if (track->audio.sub_packet_cnt == 0) | |
3602 | ✗ | track->audio.buf_timecode = timecode; | |
3603 | ✗ | if (st->codecpar->codec_id == AV_CODEC_ID_RA_288) { | |
3604 | ✗ | if (size < cfs * h / 2) { | |
3605 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
3606 | "Corrupt int4 RM-style audio packet size\n"); | ||
3607 | ✗ | return AVERROR_INVALIDDATA; | |
3608 | } | ||
3609 | ✗ | for (x = 0; x < h / 2; x++) | |
3610 | ✗ | memcpy(track->audio.buf + x * 2 * w + y * cfs, | |
3611 | ✗ | data + x * cfs, cfs); | |
3612 | ✗ | } else if (st->codecpar->codec_id == AV_CODEC_ID_SIPR) { | |
3613 | ✗ | if (size < w) { | |
3614 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
3615 | "Corrupt sipr RM-style audio packet size\n"); | ||
3616 | ✗ | return AVERROR_INVALIDDATA; | |
3617 | } | ||
3618 | ✗ | memcpy(track->audio.buf + y * w, data, w); | |
3619 | } else { | ||
3620 | ✗ | if (size < w) { | |
3621 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
3622 | "Corrupt generic RM-style audio packet size\n"); | ||
3623 | ✗ | return AVERROR_INVALIDDATA; | |
3624 | } | ||
3625 | ✗ | for (x = 0; x < w / sps; x++) | |
3626 | ✗ | memcpy(track->audio.buf + | |
3627 | ✗ | sps * (h * x + ((h + 1) / 2) * (y & 1) + (y >> 1)), | |
3628 | ✗ | data + x * sps, sps); | |
3629 | } | ||
3630 | |||
3631 | ✗ | if (++track->audio.sub_packet_cnt >= h) { | |
3632 | ✗ | if (st->codecpar->codec_id == AV_CODEC_ID_SIPR) | |
3633 | ✗ | ff_rm_reorder_sipr_data(track->audio.buf, h, w); | |
3634 | ✗ | track->audio.sub_packet_cnt = 0; | |
3635 | ✗ | track->audio.pkt_cnt = h * w / a; | |
3636 | } | ||
3637 | } | ||
3638 | |||
3639 | ✗ | while (track->audio.pkt_cnt) { | |
3640 | int ret; | ||
3641 | ✗ | AVPacket *pkt = matroska->pkt; | |
3642 | |||
3643 | ✗ | ret = av_new_packet(pkt, a); | |
3644 | ✗ | if (ret < 0) { | |
3645 | ✗ | return ret; | |
3646 | } | ||
3647 | ✗ | memcpy(pkt->data, | |
3648 | ✗ | track->audio.buf + a * (h * w / a - track->audio.pkt_cnt--), | |
3649 | a); | ||
3650 | ✗ | pkt->pts = track->audio.buf_timecode; | |
3651 | ✗ | track->audio.buf_timecode = AV_NOPTS_VALUE; | |
3652 | ✗ | pkt->pos = pos; | |
3653 | ✗ | pkt->stream_index = st->index; | |
3654 | ✗ | ret = avpriv_packet_list_put(&matroska->queue, pkt, NULL, 0); | |
3655 | ✗ | if (ret < 0) { | |
3656 | ✗ | av_packet_unref(pkt); | |
3657 | ✗ | return AVERROR(ENOMEM); | |
3658 | } | ||
3659 | } | ||
3660 | |||
3661 | ✗ | return 0; | |
3662 | } | ||
3663 | |||
3664 | /* reconstruct full wavpack blocks from mangled matroska ones */ | ||
3665 | 24 | static int matroska_parse_wavpack(MatroskaTrack *track, | |
3666 | uint8_t **data, int *size) | ||
3667 | { | ||
3668 | 24 | uint8_t *dst = NULL; | |
3669 | 24 | uint8_t *src = *data; | |
3670 | 24 | int dstlen = 0; | |
3671 | 24 | int srclen = *size; | |
3672 | uint32_t samples; | ||
3673 | uint16_t ver; | ||
3674 | 24 | int ret, offset = 0; | |
3675 | |||
3676 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | if (srclen < 12) |
3677 | ✗ | return AVERROR_INVALIDDATA; | |
3678 | |||
3679 | av_assert1(track->stream->codecpar->extradata_size >= 2); | ||
3680 | 24 | ver = AV_RL16(track->stream->codecpar->extradata); | |
3681 | |||
3682 | 24 | samples = AV_RL32(src); | |
3683 | 24 | src += 4; | |
3684 | 24 | srclen -= 4; | |
3685 | |||
3686 |
2/2✓ Branch 0 taken 112 times.
✓ Branch 1 taken 24 times.
|
136 | while (srclen >= 8) { |
3687 | int multiblock; | ||
3688 | uint32_t blocksize; | ||
3689 | uint8_t *tmp; | ||
3690 | |||
3691 | 112 | uint32_t flags = AV_RL32(src); | |
3692 | 112 | uint32_t crc = AV_RL32(src + 4); | |
3693 | 112 | src += 8; | |
3694 | 112 | srclen -= 8; | |
3695 | |||
3696 | 112 | multiblock = (flags & 0x1800) != 0x1800; | |
3697 |
2/2✓ Branch 0 taken 110 times.
✓ Branch 1 taken 2 times.
|
112 | if (multiblock) { |
3698 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
|
110 | if (srclen < 4) { |
3699 | ✗ | ret = AVERROR_INVALIDDATA; | |
3700 | ✗ | goto fail; | |
3701 | } | ||
3702 | 110 | blocksize = AV_RL32(src); | |
3703 | 110 | src += 4; | |
3704 | 110 | srclen -= 4; | |
3705 | } else | ||
3706 | 2 | blocksize = srclen; | |
3707 | |||
3708 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
|
112 | if (blocksize > srclen) { |
3709 | ✗ | ret = AVERROR_INVALIDDATA; | |
3710 | ✗ | goto fail; | |
3711 | } | ||
3712 | |||
3713 | 112 | tmp = av_realloc(dst, dstlen + blocksize + 32 + AV_INPUT_BUFFER_PADDING_SIZE); | |
3714 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
|
112 | if (!tmp) { |
3715 | ✗ | ret = AVERROR(ENOMEM); | |
3716 | ✗ | goto fail; | |
3717 | } | ||
3718 | 112 | dst = tmp; | |
3719 | 112 | dstlen += blocksize + 32; | |
3720 | |||
3721 | 112 | AV_WL32(dst + offset, MKTAG('w', 'v', 'p', 'k')); // tag | |
3722 | 112 | AV_WL32(dst + offset + 4, blocksize + 24); // blocksize - 8 | |
3723 | 112 | AV_WL16(dst + offset + 8, ver); // version | |
3724 | 112 | AV_WL16(dst + offset + 10, 0); // track/index_no | |
3725 | 112 | AV_WL32(dst + offset + 12, 0); // total samples | |
3726 | 112 | AV_WL32(dst + offset + 16, 0); // block index | |
3727 | 112 | AV_WL32(dst + offset + 20, samples); // number of samples | |
3728 | 112 | AV_WL32(dst + offset + 24, flags); // flags | |
3729 | 112 | AV_WL32(dst + offset + 28, crc); // crc | |
3730 | 112 | memcpy(dst + offset + 32, src, blocksize); // block data | |
3731 | |||
3732 | 112 | src += blocksize; | |
3733 | 112 | srclen -= blocksize; | |
3734 | 112 | offset += blocksize + 32; | |
3735 | } | ||
3736 | |||
3737 | 24 | memset(dst + dstlen, 0, AV_INPUT_BUFFER_PADDING_SIZE); | |
3738 | |||
3739 | 24 | *data = dst; | |
3740 | 24 | *size = dstlen; | |
3741 | |||
3742 | 24 | return 0; | |
3743 | |||
3744 | ✗ | fail: | |
3745 | ✗ | av_freep(&dst); | |
3746 | ✗ | return ret; | |
3747 | } | ||
3748 | |||
3749 | 11 | static int matroska_parse_prores(MatroskaTrack *track, | |
3750 | uint8_t **data, int *size) | ||
3751 | { | ||
3752 | uint8_t *dst; | ||
3753 | 11 | int dstlen = *size + 8; | |
3754 | |||
3755 | 11 | dst = av_malloc(dstlen + AV_INPUT_BUFFER_PADDING_SIZE); | |
3756 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (!dst) |
3757 | ✗ | return AVERROR(ENOMEM); | |
3758 | |||
3759 | 11 | AV_WB32(dst, dstlen); | |
3760 | 11 | AV_WB32(dst + 4, MKBETAG('i', 'c', 'p', 'f')); | |
3761 | 11 | memcpy(dst + 8, *data, dstlen - 8); | |
3762 | 11 | memset(dst + dstlen, 0, AV_INPUT_BUFFER_PADDING_SIZE); | |
3763 | |||
3764 | 11 | *data = dst; | |
3765 | 11 | *size = dstlen; | |
3766 | |||
3767 | 11 | return 0; | |
3768 | } | ||
3769 | |||
3770 | 90 | static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, | |
3771 | MatroskaTrack *track, | ||
3772 | AVStream *st, | ||
3773 | uint8_t *data, int data_len, | ||
3774 | uint64_t timecode, | ||
3775 | uint64_t duration, | ||
3776 | int64_t pos) | ||
3777 | { | ||
3778 | 90 | AVPacket *pkt = matroska->pkt; | |
3779 | uint8_t *id, *settings, *text, *buf; | ||
3780 | int id_len, settings_len, text_len; | ||
3781 | uint8_t *p, *q; | ||
3782 | int err; | ||
3783 | |||
3784 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (data_len <= 0) |
3785 | ✗ | return AVERROR_INVALIDDATA; | |
3786 | |||
3787 | 90 | p = data; | |
3788 | 90 | q = data + data_len; | |
3789 | |||
3790 | 90 | id = p; | |
3791 | 90 | id_len = -1; | |
3792 |
1/2✓ Branch 0 taken 192 times.
✗ Branch 1 not taken.
|
192 | while (p < q) { |
3793 |
3/4✓ Branch 0 taken 192 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
✓ Branch 3 taken 102 times.
|
192 | if (*p == '\r' || *p == '\n') { |
3794 | 90 | id_len = p - id; | |
3795 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (*p == '\r') |
3796 | ✗ | p++; | |
3797 | 90 | break; | |
3798 | } | ||
3799 | 102 | p++; | |
3800 | } | ||
3801 | |||
3802 |
2/4✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 90 times.
|
90 | if (p >= q || *p != '\n') |
3803 | ✗ | return AVERROR_INVALIDDATA; | |
3804 | 90 | p++; | |
3805 | |||
3806 | 90 | settings = p; | |
3807 | 90 | settings_len = -1; | |
3808 |
1/2✓ Branch 0 taken 546 times.
✗ Branch 1 not taken.
|
546 | while (p < q) { |
3809 |
3/4✓ Branch 0 taken 546 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
✓ Branch 3 taken 456 times.
|
546 | if (*p == '\r' || *p == '\n') { |
3810 | 90 | settings_len = p - settings; | |
3811 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (*p == '\r') |
3812 | ✗ | p++; | |
3813 | 90 | break; | |
3814 | } | ||
3815 | 456 | p++; | |
3816 | } | ||
3817 | |||
3818 |
2/4✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 90 times.
|
90 | if (p >= q || *p != '\n') |
3819 | ✗ | return AVERROR_INVALIDDATA; | |
3820 | 90 | p++; | |
3821 | |||
3822 | 90 | text = p; | |
3823 | 90 | text_len = q - p; | |
3824 |
1/2✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
|
90 | while (text_len > 0) { |
3825 | 90 | const int len = text_len - 1; | |
3826 | 90 | const uint8_t c = p[len]; | |
3827 |
2/4✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 90 times.
✗ Branch 3 not taken.
|
90 | if (c != '\r' && c != '\n') |
3828 | 90 | break; | |
3829 | ✗ | text_len = len; | |
3830 | } | ||
3831 | |||
3832 | 90 | err = av_new_packet(pkt, text_len); | |
3833 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (err < 0) { |
3834 | ✗ | return err; | |
3835 | } | ||
3836 | |||
3837 | 90 | memcpy(pkt->data, text, text_len); | |
3838 | |||
3839 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 78 times.
|
90 | if (id_len > 0) { |
3840 | 12 | buf = av_packet_new_side_data(pkt, | |
3841 | AV_PKT_DATA_WEBVTT_IDENTIFIER, | ||
3842 | id_len); | ||
3843 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (!buf) { |
3844 | ✗ | av_packet_unref(pkt); | |
3845 | ✗ | return AVERROR(ENOMEM); | |
3846 | } | ||
3847 | 12 | memcpy(buf, id, id_len); | |
3848 | } | ||
3849 | |||
3850 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 66 times.
|
90 | if (settings_len > 0) { |
3851 | 24 | buf = av_packet_new_side_data(pkt, | |
3852 | AV_PKT_DATA_WEBVTT_SETTINGS, | ||
3853 | settings_len); | ||
3854 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | if (!buf) { |
3855 | ✗ | av_packet_unref(pkt); | |
3856 | ✗ | return AVERROR(ENOMEM); | |
3857 | } | ||
3858 | 24 | memcpy(buf, settings, settings_len); | |
3859 | } | ||
3860 | |||
3861 | // Do we need this for subtitles? | ||
3862 | // pkt->flags = AV_PKT_FLAG_KEY; | ||
3863 | |||
3864 | 90 | pkt->stream_index = st->index; | |
3865 | 90 | pkt->pts = timecode; | |
3866 | |||
3867 | // Do we need this for subtitles? | ||
3868 | // pkt->dts = timecode; | ||
3869 | |||
3870 | 90 | pkt->duration = duration; | |
3871 | 90 | pkt->pos = pos; | |
3872 | |||
3873 | 90 | err = avpriv_packet_list_put(&matroska->queue, pkt, NULL, 0); | |
3874 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (err < 0) { |
3875 | ✗ | av_packet_unref(pkt); | |
3876 | ✗ | return AVERROR(ENOMEM); | |
3877 | } | ||
3878 | |||
3879 | 90 | return 0; | |
3880 | } | ||
3881 | |||
3882 | 136 | static int matroska_parse_block_additional(MatroskaDemuxContext *matroska, | |
3883 | MatroskaTrack *track, AVPacket *pkt, | ||
3884 | const uint8_t *data, int size, uint64_t id) | ||
3885 | { | ||
3886 | 136 | const EbmlList *mappings_list = &track->block_addition_mappings; | |
3887 | 136 | MatroskaBlockAdditionMapping *mappings = mappings_list->elem, *mapping = NULL; | |
3888 | uint8_t *side_data; | ||
3889 | int res; | ||
3890 | |||
3891 |
4/6✓ Branch 0 taken 12 times.
✓ Branch 1 taken 124 times.
✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
|
136 | if (!matroska->is_webm && track->max_block_additional_id && id > track->max_block_additional_id) { |
3892 | ✗ | int strict = matroska->ctx->strict_std_compliance >= FF_COMPLIANCE_STRICT; | |
3893 | ✗ | av_log(matroska->ctx, strict ? AV_LOG_ERROR : AV_LOG_WARNING, | |
3894 | "BlockAddID %"PRIu64" is higher than the reported MaxBlockAdditionID %"PRIu64" " | ||
3895 | "for Track with TrackNumber %"PRIu64"\n", id, track->max_block_additional_id, | ||
3896 | track->num); | ||
3897 | ✗ | if (strict) | |
3898 | ✗ | return AVERROR_INVALIDDATA; | |
3899 | } | ||
3900 | |||
3901 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 134 times.
|
136 | for (int i = 0; i < mappings_list->nb_elem; i++) { |
3902 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (id != mappings[i].value) |
3903 | ✗ | continue; | |
3904 | 2 | mapping = &mappings[i]; | |
3905 | 2 | break; | |
3906 | } | ||
3907 | |||
3908 |
5/6✓ Branch 0 taken 6 times.
✓ Branch 1 taken 130 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 2 times.
|
136 | if (id != 1 && !matroska->is_webm && !mapping) { |
3909 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, "BlockAddID %"PRIu64" has no mapping. Skipping\n", id); | |
3910 | ✗ | return 0; | |
3911 | } | ||
3912 | |||
3913 |
3/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 134 times.
✓ Branch 2 taken 2 times.
✗ Branch 3 not taken.
|
136 | if (mapping && mapping->type) |
3914 | 2 | id = mapping->type; | |
3915 | |||
3916 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 130 times.
|
136 | switch (id) { |
3917 | 6 | case MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35: { | |
3918 | GetByteContext bc; | ||
3919 | int country_code, provider_code; | ||
3920 | int provider_oriented_code, application_identifier; | ||
3921 | size_t hdrplus_size; | ||
3922 | AVDynamicHDRPlus *hdrplus; | ||
3923 | |||
3924 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (size < 6) |
3925 | ✗ | break; //ignore | |
3926 | |||
3927 | 6 | bytestream2_init(&bc, data, size); | |
3928 | |||
3929 | /* ITU-T T.35 metadata */ | ||
3930 | 6 | country_code = bytestream2_get_byteu(&bc); | |
3931 | 6 | provider_code = bytestream2_get_be16u(&bc); | |
3932 | |||
3933 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | if (country_code != ITU_T_T35_COUNTRY_CODE_US || |
3934 | provider_code != ITU_T_T35_PROVIDER_CODE_SMTPE) | ||
3935 | break; // ignore | ||
3936 | |||
3937 | 6 | provider_oriented_code = bytestream2_get_be16u(&bc); | |
3938 | 6 | application_identifier = bytestream2_get_byteu(&bc); | |
3939 | |||
3940 |
2/4✓ Branch 0 taken 6 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
✗ Branch 3 not taken.
|
6 | if (provider_oriented_code != 1 || application_identifier != 4) |
3941 | break; // ignore | ||
3942 | |||
3943 | 6 | hdrplus = av_dynamic_hdr_plus_alloc(&hdrplus_size); | |
3944 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!hdrplus) |
3945 | 6 | return AVERROR(ENOMEM); | |
3946 | |||
3947 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if ((res = av_dynamic_hdr_plus_from_t35(hdrplus, bc.buffer, |
3948 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
12 | bytestream2_get_bytes_left(&bc))) < 0 || |
3949 | 6 | (res = av_packet_add_side_data(pkt, AV_PKT_DATA_DYNAMIC_HDR10_PLUS, | |
3950 | (uint8_t *)hdrplus, hdrplus_size)) < 0) { | ||
3951 | ✗ | av_free(hdrplus); | |
3952 | ✗ | return res; | |
3953 | } | ||
3954 | |||
3955 | 6 | return 0; | |
3956 | } | ||
3957 | 130 | default: | |
3958 | 130 | break; | |
3959 | } | ||
3960 | |||
3961 | 130 | side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, | |
3962 | size + (size_t)8); | ||
3963 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 130 times.
|
130 | if (!side_data) |
3964 | ✗ | return AVERROR(ENOMEM); | |
3965 | |||
3966 | 130 | AV_WB64(side_data, id); | |
3967 | 130 | memcpy(side_data + 8, data, size); | |
3968 | |||
3969 | 130 | return 0; | |
3970 | } | ||
3971 | |||
3972 | 30174 | static int matroska_parse_frame(MatroskaDemuxContext *matroska, | |
3973 | MatroskaTrack *track, AVStream *st, | ||
3974 | AVBufferRef *buf, uint8_t *data, int pkt_size, | ||
3975 | uint64_t timecode, uint64_t lace_duration, | ||
3976 | int64_t pos, int is_keyframe, | ||
3977 | MatroskaBlockMore *blockmore, int nb_blockmore, | ||
3978 | int64_t discard_padding) | ||
3979 | { | ||
3980 | 30174 | uint8_t *pkt_data = data; | |
3981 | 30174 | int res = 0; | |
3982 | 30174 | AVPacket *pkt = matroska->pkt; | |
3983 | |||
3984 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 30150 times.
|
30174 | if (st->codecpar->codec_id == AV_CODEC_ID_WAVPACK) { |
3985 | 24 | res = matroska_parse_wavpack(track, &pkt_data, &pkt_size); | |
3986 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | if (res < 0) { |
3987 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
3988 | "Error parsing a wavpack block.\n"); | ||
3989 | ✗ | goto fail; | |
3990 | } | ||
3991 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
|
24 | if (!buf) |
3992 | 2 | av_freep(&data); | |
3993 | 24 | buf = NULL; | |
3994 | } | ||
3995 | |||
3996 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 30161 times.
|
30174 | if (st->codecpar->codec_id == AV_CODEC_ID_PRORES && |
3997 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2 times.
|
13 | AV_RB32(pkt_data + 4) != MKBETAG('i', 'c', 'p', 'f')) { |
3998 | 11 | res = matroska_parse_prores(track, &pkt_data, &pkt_size); | |
3999 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (res < 0) { |
4000 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
4001 | "Error parsing a prores block.\n"); | ||
4002 | ✗ | goto fail; | |
4003 | } | ||
4004 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
|
11 | if (!buf) |
4005 | 2 | av_freep(&data); | |
4006 | 11 | buf = NULL; | |
4007 | } | ||
4008 | |||
4009 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 30174 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
30174 | if (!pkt_size && !nb_blockmore) |
4010 | ✗ | goto no_output; | |
4011 | |||
4012 |
5/6✓ Branch 0 taken 26950 times.
✓ Branch 1 taken 3224 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 26938 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
|
30174 | if (!matroska->is_webm && nb_blockmore && !track->max_block_additional_id) { |
4013 | ✗ | int strict = matroska->ctx->strict_std_compliance >= FF_COMPLIANCE_STRICT; | |
4014 | ✗ | av_log(matroska->ctx, strict ? AV_LOG_ERROR : AV_LOG_WARNING, | |
4015 | "Unexpected BlockAdditions found in a Block from Track with TrackNumber %"PRIu64" " | ||
4016 | "where MaxBlockAdditionID is 0\n", track->num); | ||
4017 | ✗ | if (strict) { | |
4018 | ✗ | res = AVERROR_INVALIDDATA; | |
4019 | ✗ | goto fail; | |
4020 | } | ||
4021 | } | ||
4022 | |||
4023 |
2/2✓ Branch 0 taken 112 times.
✓ Branch 1 taken 30062 times.
|
30174 | if (!buf) |
4024 | 112 | pkt->buf = av_buffer_create(pkt_data, pkt_size + AV_INPUT_BUFFER_PADDING_SIZE, | |
4025 | NULL, NULL, 0); | ||
4026 | else | ||
4027 | 30062 | pkt->buf = av_buffer_ref(buf); | |
4028 | |||
4029 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30174 times.
|
30174 | if (!pkt->buf) { |
4030 | ✗ | res = AVERROR(ENOMEM); | |
4031 | ✗ | goto fail; | |
4032 | } | ||
4033 | |||
4034 | 30174 | pkt->data = pkt_data; | |
4035 | 30174 | pkt->size = pkt_size; | |
4036 | 30174 | pkt->flags = is_keyframe; | |
4037 | 30174 | pkt->stream_index = st->index; | |
4038 | |||
4039 |
2/2✓ Branch 0 taken 136 times.
✓ Branch 1 taken 30174 times.
|
30310 | for (int i = 0; i < nb_blockmore; i++) { |
4040 | 136 | MatroskaBlockMore *more = &blockmore[i]; | |
4041 | |||
4042 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
|
136 | if (!more->additional.size) |
4043 | ✗ | continue; | |
4044 | |||
4045 | 136 | res = matroska_parse_block_additional(matroska, track, pkt, more->additional.data, | |
4046 | more->additional.size, more->additional_id); | ||
4047 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
|
136 | if (res < 0) { |
4048 | ✗ | av_packet_unref(pkt); | |
4049 | ✗ | return res; | |
4050 | } | ||
4051 | } | ||
4052 | |||
4053 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 30147 times.
|
30174 | if (discard_padding) { |
4054 | 27 | uint8_t *side_data = av_packet_new_side_data(pkt, | |
4055 | AV_PKT_DATA_SKIP_SAMPLES, | ||
4056 | 10); | ||
4057 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
|
27 | if (!side_data) { |
4058 | ✗ | av_packet_unref(pkt); | |
4059 | ✗ | return AVERROR(ENOMEM); | |
4060 | } | ||
4061 | 27 | discard_padding = av_rescale_q(discard_padding, | |
4062 | 27 | (AVRational){1, 1000000000}, | |
4063 | 27 | (AVRational){1, st->codecpar->sample_rate}); | |
4064 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | if (discard_padding > 0) { |
4065 | 27 | AV_WL32A(side_data + 4, discard_padding); | |
4066 | } else { | ||
4067 | ✗ | AV_WL32A(side_data, -discard_padding); | |
4068 | } | ||
4069 | } | ||
4070 | |||
4071 |
2/2✓ Branch 0 taken 432 times.
✓ Branch 1 taken 29742 times.
|
30174 | if (track->ms_compat) |
4072 | 432 | pkt->dts = timecode; | |
4073 | else | ||
4074 | 29742 | pkt->pts = timecode; | |
4075 | 30174 | pkt->pos = pos; | |
4076 | 30174 | pkt->duration = lace_duration; | |
4077 | |||
4078 | 30174 | res = avpriv_packet_list_put(&matroska->queue, pkt, NULL, 0); | |
4079 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30174 times.
|
30174 | if (res < 0) { |
4080 | ✗ | av_packet_unref(pkt); | |
4081 | ✗ | return AVERROR(ENOMEM); | |
4082 | } | ||
4083 | |||
4084 | 30174 | return 0; | |
4085 | |||
4086 | ✗ | no_output: | |
4087 | ✗ | fail: | |
4088 | ✗ | if (!buf) | |
4089 | ✗ | av_free(pkt_data); | |
4090 | ✗ | return res; | |
4091 | } | ||
4092 | |||
4093 | 30747 | static int matroska_parse_block(MatroskaDemuxContext *matroska, AVBufferRef *buf, uint8_t *data, | |
4094 | int size, int64_t pos, uint64_t cluster_time, | ||
4095 | uint64_t block_duration, int is_keyframe, | ||
4096 | MatroskaBlockMore *blockmore, int nb_blockmore, | ||
4097 | int64_t cluster_pos, int64_t discard_padding) | ||
4098 | { | ||
4099 | 30747 | uint64_t timecode = AV_NOPTS_VALUE; | |
4100 | MatroskaTrack *track; | ||
4101 | FFIOContext pb; | ||
4102 | 30747 | int res = 0; | |
4103 | AVStream *st; | ||
4104 | int16_t block_time; | ||
4105 | uint32_t lace_size[256]; | ||
4106 | 30747 | int n, flags, laces = 0; | |
4107 | uint64_t num; | ||
4108 | int trust_default_duration; | ||
4109 | |||
4110 | av_assert1(buf); | ||
4111 | |||
4112 | 30747 | ffio_init_read_context(&pb, data, size); | |
4113 | |||
4114 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 30747 times.
|
30747 | if ((n = ebml_read_num(matroska, &pb.pub, 8, &num, 1)) < 0) |
4115 | ✗ | return n; | |
4116 | 30747 | data += n; | |
4117 | 30747 | size -= n; | |
4118 | |||
4119 | 30747 | track = matroska_find_track_by_num(matroska, num); | |
4120 |
3/4✓ Branch 0 taken 30746 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30746 times.
|
30747 | if (!track || size < 3) |
4121 | 1 | return AVERROR_INVALIDDATA; | |
4122 | |||
4123 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30746 times.
|
30746 | if (!(st = track->stream)) { |
4124 | ✗ | av_log(matroska->ctx, AV_LOG_VERBOSE, | |
4125 | "No stream associated to TrackNumber %"PRIu64". " | ||
4126 | "Ignoring Block with this TrackNumber.\n", num); | ||
4127 | ✗ | return 0; | |
4128 | } | ||
4129 | |||
4130 |
2/2✓ Branch 0 taken 311 times.
✓ Branch 1 taken 30435 times.
|
30746 | if (st->discard >= AVDISCARD_ALL) |
4131 | 311 | return res; | |
4132 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30435 times.
|
30435 | if (block_duration > INT64_MAX) |
4133 | ✗ | block_duration = INT64_MAX; | |
4134 | |||
4135 | 30435 | block_time = sign_extend(AV_RB16(data), 16); | |
4136 | 30435 | data += 2; | |
4137 | 30435 | flags = *data++; | |
4138 | 30435 | size -= 3; | |
4139 |
2/2✓ Branch 0 taken 29992 times.
✓ Branch 1 taken 443 times.
|
30435 | if (is_keyframe == -1) |
4140 | 29992 | is_keyframe = flags & 0x80 ? AV_PKT_FLAG_KEY : 0; | |
4141 | |||
4142 |
3/4✓ Branch 0 taken 30435 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
✓ Branch 3 taken 30356 times.
|
30435 | if (cluster_time != (uint64_t) -1 && |
4143 |
2/2✓ Branch 0 taken 63 times.
✓ Branch 1 taken 16 times.
|
79 | (block_time >= 0 || cluster_time >= -block_time)) { |
4144 | 30419 | uint64_t timecode_cluster_in_track_tb = (double) cluster_time / track->time_scale; | |
4145 | 30419 | timecode = timecode_cluster_in_track_tb + block_time - track->codec_delay_in_track_tb; | |
4146 |
2/2✓ Branch 0 taken 128 times.
✓ Branch 1 taken 30291 times.
|
30419 | if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE && |
4147 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 122 times.
|
128 | timecode < track->end_timecode) |
4148 | 6 | is_keyframe = 0; /* overlapping subtitles are not key frame */ | |
4149 |
2/2✓ Branch 0 taken 26821 times.
✓ Branch 1 taken 3598 times.
|
30419 | if (is_keyframe) { |
4150 | 26821 | ff_reduce_index(matroska->ctx, st->index); | |
4151 | 26821 | av_add_index_entry(st, cluster_pos, timecode, 0, 0, | |
4152 | AVINDEX_KEYFRAME); | ||
4153 | } | ||
4154 | } | ||
4155 | |||
4156 |
2/2✓ Branch 0 taken 593 times.
✓ Branch 1 taken 29842 times.
|
30435 | if (matroska->skip_to_keyframe && |
4157 |
1/2✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
|
593 | track->type != MATROSKA_TRACK_TYPE_SUBTITLE) { |
4158 | // Compare signed timecodes. Timecode may be negative due to codec delay | ||
4159 | // offset. We don't support timestamps greater than int64_t anyway - see | ||
4160 | // AVPacket's pts. | ||
4161 |
2/2✓ Branch 0 taken 548 times.
✓ Branch 1 taken 45 times.
|
593 | if ((int64_t)timecode < (int64_t)matroska->skip_to_timecode) |
4162 | 548 | return res; | |
4163 |
1/2✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
|
45 | if (is_keyframe) |
4164 | 45 | matroska->skip_to_keyframe = 0; | |
4165 | ✗ | else if (!ffstream(st)->skip_to_keyframe) { | |
4166 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "File is broken, keyframes not correctly marked!\n"); | |
4167 | ✗ | matroska->skip_to_keyframe = 0; | |
4168 | } | ||
4169 | } | ||
4170 | |||
4171 | 29887 | res = matroska_parse_laces(matroska, &data, size, (flags & 0x06) >> 1, | |
4172 | &pb.pub, lace_size, &laces); | ||
4173 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29887 times.
|
29887 | if (res < 0) { |
4174 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "Error parsing frame sizes.\n"); | |
4175 | ✗ | return res; | |
4176 | } | ||
4177 | |||
4178 | 29887 | trust_default_duration = track->default_duration != 0; | |
4179 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 29887 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
29887 | if (track->audio.samplerate == 8000 && trust_default_duration) { |
4180 | // If this is needed for more codecs, then add them here | ||
4181 | ✗ | if (st->codecpar->codec_id == AV_CODEC_ID_AC3) { | |
4182 | ✗ | if (track->audio.samplerate != st->codecpar->sample_rate || !st->codecpar->frame_size) | |
4183 | ✗ | trust_default_duration = 0; | |
4184 | } | ||
4185 | } | ||
4186 | |||
4187 |
4/4✓ Branch 0 taken 29607 times.
✓ Branch 1 taken 280 times.
✓ Branch 2 taken 4278 times.
✓ Branch 3 taken 25329 times.
|
29887 | if (!block_duration && trust_default_duration) |
4188 | 4278 | block_duration = track->default_duration * laces / matroska->time_scale; | |
4189 | |||
4190 |
5/6✓ Branch 0 taken 29887 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
✓ Branch 3 taken 29811 times.
✓ Branch 4 taken 60 times.
✓ Branch 5 taken 16 times.
|
29887 | if (cluster_time != (uint64_t)-1 && (block_time >= 0 || cluster_time >= -block_time)) |
4191 | 29871 | track->end_timecode = | |
4192 | 29871 | FFMAX(track->end_timecode, timecode + block_duration); | |
4193 | |||
4194 |
2/2✓ Branch 0 taken 30264 times.
✓ Branch 1 taken 29887 times.
|
60151 | for (n = 0; n < laces; n++) { |
4195 | 30264 | int64_t lace_duration = block_duration*(n+1) / laces - block_duration*n / laces; | |
4196 | 30264 | uint8_t *out_data = data; | |
4197 | 30264 | int out_size = lace_size[n]; | |
4198 | |||
4199 |
2/2✓ Branch 0 taken 81 times.
✓ Branch 1 taken 30183 times.
|
30264 | if (track->needs_decoding) { |
4200 | 81 | res = matroska_decode_buffer(&out_data, &out_size, track); | |
4201 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
|
81 | if (res < 0) |
4202 | ✗ | return res; | |
4203 | /* Given that we are here means that out_data is no longer | ||
4204 | * owned by buf, so set it to NULL. This depends upon | ||
4205 | * zero-length header removal compression being ignored. */ | ||
4206 | av_assert1(out_data != data); | ||
4207 | 81 | buf = NULL; | |
4208 | } | ||
4209 | |||
4210 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30264 times.
|
30264 | if (track->audio.buf) { |
4211 | ✗ | res = matroska_parse_rm_audio(matroska, track, st, | |
4212 | out_data, out_size, | ||
4213 | timecode, pos); | ||
4214 | ✗ | if (!buf) | |
4215 | ✗ | av_free(out_data); | |
4216 | ✗ | if (res) | |
4217 | ✗ | return res; | |
4218 |
2/2✓ Branch 0 taken 90 times.
✓ Branch 1 taken 30174 times.
|
30264 | } else if (st->codecpar->codec_id == AV_CODEC_ID_WEBVTT) { |
4219 | 90 | res = matroska_parse_webvtt(matroska, track, st, | |
4220 | out_data, out_size, | ||
4221 | timecode, lace_duration, | ||
4222 | pos); | ||
4223 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (!buf) |
4224 | ✗ | av_free(out_data); | |
4225 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (res) |
4226 | ✗ | return res; | |
4227 | } else { | ||
4228 | 30174 | res = matroska_parse_frame(matroska, track, st, buf, out_data, | |
4229 | out_size, timecode, lace_duration, | ||
4230 | pos, is_keyframe, | ||
4231 | blockmore, nb_blockmore, | ||
4232 | discard_padding); | ||
4233 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30174 times.
|
30174 | if (res) |
4234 | ✗ | return res; | |
4235 | } | ||
4236 | |||
4237 |
2/2✓ Branch 0 taken 30176 times.
✓ Branch 1 taken 88 times.
|
30264 | if (timecode != AV_NOPTS_VALUE) |
4238 |
2/2✓ Branch 0 taken 4847 times.
✓ Branch 1 taken 25329 times.
|
30176 | timecode = lace_duration ? timecode + lace_duration : AV_NOPTS_VALUE; |
4239 | 30264 | data += lace_size[n]; | |
4240 | } | ||
4241 | |||
4242 | 29887 | return 0; | |
4243 | } | ||
4244 | |||
4245 | 31149 | static int matroska_parse_cluster(MatroskaDemuxContext *matroska) | |
4246 | { | ||
4247 | 31149 | MatroskaCluster *cluster = &matroska->current_cluster; | |
4248 | 31149 | MatroskaBlock *block = &cluster->block; | |
4249 | int res; | ||
4250 | |||
4251 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31149 times.
|
31149 | av_assert0(matroska->num_levels <= 2U); |
4252 | |||
4253 |
2/2✓ Branch 0 taken 1149 times.
✓ Branch 1 taken 30000 times.
|
31149 | if (matroska->num_levels == 1) { |
4254 | 1149 | res = ebml_parse(matroska, matroska_segment, NULL); | |
4255 | |||
4256 |
2/2✓ Branch 0 taken 803 times.
✓ Branch 1 taken 346 times.
|
1149 | if (res == 1) { |
4257 | /* Found a cluster: subtract the size of the ID already read. */ | ||
4258 | 803 | cluster->pos = avio_tell(matroska->ctx->pb) - 4; | |
4259 | |||
4260 | 803 | res = ebml_parse(matroska, matroska_cluster_enter, cluster); | |
4261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 803 times.
|
803 | if (res < 0) |
4262 | ✗ | return res; | |
4263 | } | ||
4264 | } | ||
4265 | |||
4266 |
2/2✓ Branch 0 taken 30762 times.
✓ Branch 1 taken 387 times.
|
31149 | if (matroska->num_levels == 2) { |
4267 | /* We are inside a cluster. */ | ||
4268 | 30762 | res = ebml_parse(matroska, matroska_cluster_parsing, cluster); | |
4269 | |||
4270 |
4/4✓ Branch 0 taken 30752 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 30747 times.
✓ Branch 3 taken 5 times.
|
30762 | if (res >= 0 && block->bin.size > 0) { |
4271 |
2/2✓ Branch 0 taken 484 times.
✓ Branch 1 taken 30263 times.
|
30747 | int is_keyframe = block->non_simple ? block->reference.count == 0 : -1; |
4272 | |||
4273 | 30747 | res = matroska_parse_block(matroska, block->bin.buf, block->bin.data, | |
4274 | block->bin.size, block->bin.pos, | ||
4275 | cluster->timecode, block->duration, | ||
4276 | 30747 | is_keyframe, block->blockmore.elem, | |
4277 | block->blockmore.nb_elem, cluster->pos, | ||
4278 | block->discard_padding); | ||
4279 | } | ||
4280 | |||
4281 | 30762 | ebml_free(matroska_blockgroup, block); | |
4282 | 30762 | memset(block, 0, sizeof(*block)); | |
4283 |
2/2✓ Branch 0 taken 359 times.
✓ Branch 1 taken 28 times.
|
387 | } else if (!matroska->num_levels) { |
4284 |
2/2✓ Branch 1 taken 352 times.
✓ Branch 2 taken 7 times.
|
359 | if (!avio_feof(matroska->ctx->pb)) { |
4285 | 352 | avio_r8(matroska->ctx->pb); | |
4286 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 352 times.
|
352 | if (!avio_feof(matroska->ctx->pb)) { |
4287 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, "File extends beyond " | |
4288 | "end of segment.\n"); | ||
4289 | ✗ | return AVERROR_INVALIDDATA; | |
4290 | } | ||
4291 | } | ||
4292 | 359 | matroska->done = 1; | |
4293 | 359 | return AVERROR_EOF; | |
4294 | } | ||
4295 | |||
4296 | 30790 | return res; | |
4297 | } | ||
4298 | |||
4299 | 29903 | static int matroska_read_packet(AVFormatContext *s, AVPacket *pkt) | |
4300 | { | ||
4301 | 29903 | MatroskaDemuxContext *matroska = s->priv_data; | |
4302 | 29903 | int ret = 0; | |
4303 | |||
4304 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 29893 times.
|
29903 | if (matroska->resync_pos == -1) { |
4305 | // This can only happen if generic seeking has been used. | ||
4306 | 10 | matroska->resync_pos = avio_tell(s->pb); | |
4307 | } | ||
4308 | |||
4309 |
2/2✓ Branch 1 taken 30762 times.
✓ Branch 2 taken 29517 times.
|
60279 | while (matroska_deliver_packet(matroska, pkt)) { |
4310 |
2/2✓ Branch 0 taken 386 times.
✓ Branch 1 taken 30376 times.
|
30762 | if (matroska->done) |
4311 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 376 times.
|
386 | return (ret < 0) ? ret : AVERROR_EOF; |
4312 |
4/4✓ Branch 1 taken 346 times.
✓ Branch 2 taken 30030 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 333 times.
|
30376 | if (matroska_parse_cluster(matroska) < 0 && !matroska->done) |
4313 | 13 | ret = matroska_resync(matroska, matroska->resync_pos); | |
4314 | } | ||
4315 | |||
4316 | 29517 | return 0; | |
4317 | } | ||
4318 | |||
4319 | 55 | static int matroska_read_seek(AVFormatContext *s, int stream_index, | |
4320 | int64_t timestamp, int flags) | ||
4321 | { | ||
4322 | 55 | MatroskaDemuxContext *matroska = s->priv_data; | |
4323 | 55 | MatroskaTrack *tracks = NULL; | |
4324 | 55 | AVStream *st = s->streams[stream_index]; | |
4325 | 55 | FFStream *const sti = ffstream(st); | |
4326 | int i, index; | ||
4327 | |||
4328 | /* Parse the CUES now since we need the index data to seek. */ | ||
4329 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 52 times.
|
55 | if (matroska->cues_parsing_deferred > 0) { |
4330 | 3 | matroska->cues_parsing_deferred = 0; | |
4331 | 3 | matroska_parse_cues(matroska); | |
4332 | } | ||
4333 | |||
4334 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
|
55 | if (!sti->nb_index_entries) |
4335 | ✗ | goto err; | |
4336 | 55 | timestamp = FFMAX(timestamp, sti->index_entries[0].timestamp); | |
4337 | |||
4338 |
2/2✓ Branch 1 taken 45 times.
✓ Branch 2 taken 10 times.
|
55 | if ((index = av_index_search_timestamp(st, timestamp, flags)) < 0 || |
4339 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 28 times.
|
45 | index == sti->nb_index_entries - 1) { |
4340 | 27 | matroska_reset_status(matroska, 0, sti->index_entries[sti->nb_index_entries - 1].pos); | |
4341 |
2/2✓ Branch 1 taken 285 times.
✓ Branch 2 taken 410 times.
|
695 | while ((index = av_index_search_timestamp(st, timestamp, flags)) < 0 || |
4342 |
2/2✓ Branch 0 taken 409 times.
✓ Branch 1 taken 1 times.
|
410 | index == sti->nb_index_entries - 1) { |
4343 | 694 | matroska_clear_queue(matroska); | |
4344 |
2/2✓ Branch 1 taken 26 times.
✓ Branch 2 taken 668 times.
|
694 | if (matroska_parse_cluster(matroska) < 0) |
4345 | 26 | break; | |
4346 | } | ||
4347 | } | ||
4348 | |||
4349 | 55 | matroska_clear_queue(matroska); | |
4350 |
4/4✓ Branch 0 taken 45 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 42 times.
|
55 | if (index < 0 || (matroska->cues_parsing_deferred < 0 && |
4351 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | index == sti->nb_index_entries - 1)) |
4352 | 10 | goto err; | |
4353 | |||
4354 | 45 | tracks = matroska->tracks.elem; | |
4355 |
2/2✓ Branch 0 taken 69 times.
✓ Branch 1 taken 45 times.
|
114 | for (i = 0; i < matroska->tracks.nb_elem; i++) { |
4356 | 69 | tracks[i].audio.pkt_cnt = 0; | |
4357 | 69 | tracks[i].audio.sub_packet_cnt = 0; | |
4358 | 69 | tracks[i].audio.buf_timecode = AV_NOPTS_VALUE; | |
4359 | 69 | tracks[i].end_timecode = 0; | |
4360 | } | ||
4361 | |||
4362 | /* We seek to a level 1 element, so set the appropriate status. */ | ||
4363 | 45 | matroska_reset_status(matroska, 0, sti->index_entries[index].pos); | |
4364 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
45 | if (flags & AVSEEK_FLAG_ANY) { |
4365 | ✗ | sti->skip_to_keyframe = 0; | |
4366 | ✗ | matroska->skip_to_timecode = timestamp; | |
4367 | } else { | ||
4368 | 45 | sti->skip_to_keyframe = 1; | |
4369 | 45 | matroska->skip_to_timecode = sti->index_entries[index].timestamp; | |
4370 | } | ||
4371 | 45 | matroska->skip_to_keyframe = 1; | |
4372 | 45 | matroska->done = 0; | |
4373 | 45 | avpriv_update_cur_dts(s, st, sti->index_entries[index].timestamp); | |
4374 | 45 | return 0; | |
4375 | 10 | err: | |
4376 | // slightly hackish but allows proper fallback to | ||
4377 | // the generic seeking code. | ||
4378 | 10 | matroska_reset_status(matroska, 0, -1); | |
4379 | 10 | matroska->resync_pos = -1; | |
4380 | 10 | matroska_clear_queue(matroska); | |
4381 | 10 | sti->skip_to_keyframe = | |
4382 | 10 | matroska->skip_to_keyframe = 0; | |
4383 | 10 | matroska->done = 0; | |
4384 | 10 | return -1; | |
4385 | } | ||
4386 | |||
4387 | 372 | static int matroska_read_close(AVFormatContext *s) | |
4388 | { | ||
4389 | 372 | MatroskaDemuxContext *matroska = s->priv_data; | |
4390 | 372 | MatroskaTrack *tracks = matroska->tracks.elem; | |
4391 | int n; | ||
4392 | |||
4393 | 372 | matroska_clear_queue(matroska); | |
4394 | |||
4395 |
2/2✓ Branch 0 taken 447 times.
✓ Branch 1 taken 372 times.
|
819 | for (n = 0; n < matroska->tracks.nb_elem; n++) |
4396 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 363 times.
|
447 | if (tracks[n].type == MATROSKA_TRACK_TYPE_AUDIO) |
4397 | 84 | av_freep(&tracks[n].audio.buf); | |
4398 | 372 | ebml_free(matroska_segment, matroska); | |
4399 | |||
4400 | 372 | return 0; | |
4401 | } | ||
4402 | |||
4403 | #if CONFIG_WEBM_DASH_MANIFEST_DEMUXER | ||
4404 | typedef struct { | ||
4405 | int64_t start_time_ns; | ||
4406 | int64_t end_time_ns; | ||
4407 | int64_t start_offset; | ||
4408 | int64_t end_offset; | ||
4409 | } CueDesc; | ||
4410 | |||
4411 | /* This function searches all the Cues and returns the CueDesc corresponding to | ||
4412 | * the timestamp ts. Returned CueDesc will be such that start_time_ns <= ts < | ||
4413 | * end_time_ns. All 4 fields will be set to -1 if ts >= file's duration or | ||
4414 | * if an error occurred. | ||
4415 | */ | ||
4416 | 4051 | static CueDesc get_cue_desc(AVFormatContext *s, int64_t ts, int64_t cues_start) { | |
4417 | 4051 | MatroskaDemuxContext *matroska = s->priv_data; | |
4418 | 4051 | FFStream *const sti = ffstream(s->streams[0]); | |
4419 | 4051 | AVIndexEntry *const index_entries = sti->index_entries; | |
4420 | 4051 | int nb_index_entries = sti->nb_index_entries; | |
4421 | CueDesc cue_desc; | ||
4422 | int i; | ||
4423 | |||
4424 |
2/2✓ Branch 0 taken 101 times.
✓ Branch 1 taken 3950 times.
|
4051 | if (ts >= (int64_t)(matroska->duration * matroska->time_scale)) |
4425 | 101 | return (CueDesc) {-1, -1, -1, -1}; | |
4426 |
2/2✓ Branch 0 taken 45235 times.
✓ Branch 1 taken 156 times.
|
45391 | for (i = 1; i < nb_index_entries; i++) { |
4427 |
1/2✓ Branch 0 taken 45235 times.
✗ Branch 1 not taken.
|
45235 | if (index_entries[i - 1].timestamp * matroska->time_scale <= ts && |
4428 |
2/2✓ Branch 0 taken 3794 times.
✓ Branch 1 taken 41441 times.
|
45235 | index_entries[i].timestamp * matroska->time_scale > ts) { |
4429 | 3794 | break; | |
4430 | } | ||
4431 | } | ||
4432 | 3950 | --i; | |
4433 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3950 times.
|
3950 | if (index_entries[i].timestamp > matroska->duration) |
4434 | ✗ | return (CueDesc) {-1, -1, -1, -1}; | |
4435 | 3950 | cue_desc.start_time_ns = index_entries[i].timestamp * matroska->time_scale; | |
4436 | 3950 | cue_desc.start_offset = index_entries[i].pos - matroska->segment_start; | |
4437 |
2/2✓ Branch 0 taken 3794 times.
✓ Branch 1 taken 156 times.
|
3950 | if (i != nb_index_entries - 1) { |
4438 | 3794 | cue_desc.end_time_ns = index_entries[i + 1].timestamp * matroska->time_scale; | |
4439 | 3794 | cue_desc.end_offset = index_entries[i + 1].pos - matroska->segment_start; | |
4440 | } else { | ||
4441 | 156 | cue_desc.end_time_ns = matroska->duration * matroska->time_scale; | |
4442 | // FIXME: this needs special handling for files where Cues appear | ||
4443 | // before Clusters. the current logic assumes Cues appear after | ||
4444 | // Clusters. | ||
4445 | 156 | cue_desc.end_offset = cues_start - matroska->segment_start; | |
4446 | } | ||
4447 | 3950 | return cue_desc; | |
4448 | } | ||
4449 | |||
4450 | 10 | static int webm_clusters_start_with_keyframe(AVFormatContext *s) | |
4451 | { | ||
4452 | 10 | MatroskaDemuxContext *matroska = s->priv_data; | |
4453 | 10 | AVStream *const st = s->streams[0]; | |
4454 | 10 | FFStream *const sti = ffstream(st); | |
4455 | 10 | uint32_t id = matroska->current_id; | |
4456 | int64_t cluster_pos, before_pos; | ||
4457 | 10 | int index, rv = 1; | |
4458 | |||
4459 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (sti->nb_index_entries <= 0) |
4460 | ✗ | return 0; | |
4461 | |||
4462 | // seek to the first cluster using cues. | ||
4463 | 10 | index = av_index_search_timestamp(st, 0, 0); | |
4464 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (index < 0) |
4465 | ✗ | return 0; | |
4466 | 10 | cluster_pos = sti->index_entries[index].pos; | |
4467 | 10 | before_pos = avio_tell(s->pb); | |
4468 | 78 | while (1) { | |
4469 | uint64_t cluster_id, cluster_length; | ||
4470 | int read; | ||
4471 | AVPacket *pkt; | ||
4472 | 88 | avio_seek(s->pb, cluster_pos, SEEK_SET); | |
4473 | // read cluster id and length | ||
4474 | 88 | read = ebml_read_num(matroska, matroska->ctx->pb, 4, &cluster_id, 1); | |
4475 |
3/4✓ Branch 0 taken 88 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
✓ Branch 3 taken 9 times.
|
88 | if (read < 0 || cluster_id != 0xF43B675) // done with all clusters |
4476 | break; | ||
4477 | 79 | read = ebml_read_length(matroska, matroska->ctx->pb, &cluster_length); | |
4478 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
|
79 | if (read < 0) |
4479 | ✗ | break; | |
4480 | |||
4481 | 79 | matroska_reset_status(matroska, 0, cluster_pos); | |
4482 | 79 | matroska_clear_queue(matroska); | |
4483 |
1/2✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
|
79 | if (matroska_parse_cluster(matroska) < 0 || |
4484 |
1/2✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
|
79 | !matroska->queue.head) { |
4485 | break; | ||
4486 | } | ||
4487 | 79 | pkt = &matroska->queue.head->pkt; | |
4488 | // 4 + read is the length of the cluster id and the cluster length field. | ||
4489 | 79 | cluster_pos += 4 + read + cluster_length; | |
4490 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 78 times.
|
79 | if (!(pkt->flags & AV_PKT_FLAG_KEY)) { |
4491 | 1 | rv = 0; | |
4492 | 1 | break; | |
4493 | } | ||
4494 | } | ||
4495 | |||
4496 | /* Restore the status after matroska_read_header: */ | ||
4497 | 10 | matroska_reset_status(matroska, id, before_pos); | |
4498 | |||
4499 | 10 | return rv; | |
4500 | } | ||
4501 | |||
4502 | 555 | static int buffer_size_after_time_downloaded(int64_t time_ns, double search_sec, int64_t bps, | |
4503 | double min_buffer, double* buffer, | ||
4504 | double* sec_to_download, AVFormatContext *s, | ||
4505 | int64_t cues_start) | ||
4506 | { | ||
4507 | 555 | double nano_seconds_per_second = 1000000000.0; | |
4508 | 555 | double time_sec = time_ns / nano_seconds_per_second; | |
4509 | 555 | int rv = 0; | |
4510 | 555 | int64_t time_to_search_ns = (int64_t)(search_sec * nano_seconds_per_second); | |
4511 | 555 | int64_t end_time_ns = time_ns + time_to_search_ns; | |
4512 | 555 | double sec_downloaded = 0.0; | |
4513 | 555 | CueDesc desc_curr = get_cue_desc(s, time_ns, cues_start); | |
4514 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 555 times.
|
555 | if (desc_curr.start_time_ns == -1) |
4515 | ✗ | return -1; | |
4516 | 555 | *sec_to_download = 0.0; | |
4517 | |||
4518 | // Check for non cue start time. | ||
4519 |
2/2✓ Branch 0 taken 513 times.
✓ Branch 1 taken 42 times.
|
555 | if (time_ns > desc_curr.start_time_ns) { |
4520 | 513 | int64_t cue_nano = desc_curr.end_time_ns - time_ns; | |
4521 | 513 | double percent = (double)(cue_nano) / (desc_curr.end_time_ns - desc_curr.start_time_ns); | |
4522 | 513 | double cueBytes = (desc_curr.end_offset - desc_curr.start_offset) * percent; | |
4523 | 513 | double timeToDownload = (cueBytes * 8.0) / bps; | |
4524 | |||
4525 | 513 | sec_downloaded += (cue_nano / nano_seconds_per_second) - timeToDownload; | |
4526 | 513 | *sec_to_download += timeToDownload; | |
4527 | |||
4528 | // Check if the search ends within the first cue. | ||
4529 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 513 times.
|
513 | if (desc_curr.end_time_ns >= end_time_ns) { |
4530 | ✗ | double desc_end_time_sec = desc_curr.end_time_ns / nano_seconds_per_second; | |
4531 | ✗ | double percent_to_sub = search_sec / (desc_end_time_sec - time_sec); | |
4532 | ✗ | sec_downloaded = percent_to_sub * sec_downloaded; | |
4533 | ✗ | *sec_to_download = percent_to_sub * *sec_to_download; | |
4534 | } | ||
4535 | |||
4536 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 509 times.
|
513 | if ((sec_downloaded + *buffer) <= min_buffer) { |
4537 | 4 | return 1; | |
4538 | } | ||
4539 | |||
4540 | // Get the next Cue. | ||
4541 | 509 | desc_curr = get_cue_desc(s, desc_curr.end_time_ns, cues_start); | |
4542 | } | ||
4543 | |||
4544 |
2/2✓ Branch 0 taken 2856 times.
✓ Branch 1 taken 100 times.
|
2956 | while (desc_curr.start_time_ns != -1) { |
4545 | 2856 | int64_t desc_bytes = desc_curr.end_offset - desc_curr.start_offset; | |
4546 | 2856 | int64_t desc_ns = desc_curr.end_time_ns - desc_curr.start_time_ns; | |
4547 | 2856 | double desc_sec = desc_ns / nano_seconds_per_second; | |
4548 | 2856 | double bits = (desc_bytes * 8.0); | |
4549 | 2856 | double time_to_download = bits / bps; | |
4550 | |||
4551 | 2856 | sec_downloaded += desc_sec - time_to_download; | |
4552 | 2856 | *sec_to_download += time_to_download; | |
4553 | |||
4554 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2856 times.
|
2856 | if (desc_curr.end_time_ns >= end_time_ns) { |
4555 | ✗ | double desc_end_time_sec = desc_curr.end_time_ns / nano_seconds_per_second; | |
4556 | ✗ | double percent_to_sub = search_sec / (desc_end_time_sec - time_sec); | |
4557 | ✗ | sec_downloaded = percent_to_sub * sec_downloaded; | |
4558 | ✗ | *sec_to_download = percent_to_sub * *sec_to_download; | |
4559 | |||
4560 | ✗ | if ((sec_downloaded + *buffer) <= min_buffer) | |
4561 | ✗ | rv = 1; | |
4562 | ✗ | break; | |
4563 | } | ||
4564 | |||
4565 |
2/2✓ Branch 0 taken 451 times.
✓ Branch 1 taken 2405 times.
|
2856 | if ((sec_downloaded + *buffer) <= min_buffer) { |
4566 | 451 | rv = 1; | |
4567 | 451 | break; | |
4568 | } | ||
4569 | |||
4570 | 2405 | desc_curr = get_cue_desc(s, desc_curr.end_time_ns, cues_start); | |
4571 | } | ||
4572 | 551 | *buffer = *buffer + sec_downloaded; | |
4573 | 551 | return rv; | |
4574 | } | ||
4575 | |||
4576 | /* This function computes the bandwidth of the WebM file with the help of | ||
4577 | * buffer_size_after_time_downloaded() function. Both of these functions are | ||
4578 | * adapted from WebM Tools project and are adapted to work with FFmpeg's | ||
4579 | * Matroska parsing mechanism. | ||
4580 | * | ||
4581 | * Returns the bandwidth of the file on success; -1 on error. | ||
4582 | * */ | ||
4583 | 10 | static int64_t webm_dash_manifest_compute_bandwidth(AVFormatContext *s, int64_t cues_start) | |
4584 | { | ||
4585 | 10 | MatroskaDemuxContext *matroska = s->priv_data; | |
4586 | 10 | AVStream *st = s->streams[0]; | |
4587 | 10 | FFStream *const sti = ffstream(st); | |
4588 | 10 | double bandwidth = 0.0; | |
4589 | |||
4590 |
2/2✓ Branch 0 taken 101 times.
✓ Branch 1 taken 10 times.
|
111 | for (int i = 0; i < sti->nb_index_entries; i++) { |
4591 | 101 | int64_t prebuffer_ns = 1000000000; | |
4592 | 101 | int64_t time_ns = sti->index_entries[i].timestamp * matroska->time_scale; | |
4593 | 101 | double nano_seconds_per_second = 1000000000.0; | |
4594 | int64_t prebuffered_ns; | ||
4595 | 101 | double prebuffer_bytes = 0.0; | |
4596 | 101 | int64_t temp_prebuffer_ns = prebuffer_ns; | |
4597 | int64_t pre_bytes, pre_ns; | ||
4598 | double pre_sec, prebuffer, bits_per_second; | ||
4599 | 101 | CueDesc desc_beg = get_cue_desc(s, time_ns, cues_start); | |
4600 | // Start with the first Cue. | ||
4601 | 101 | CueDesc desc_end = desc_beg; | |
4602 | |||
4603 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 101 times.
|
101 | if (time_ns > INT64_MAX - prebuffer_ns) |
4604 | ✗ | return -1; | |
4605 | 101 | prebuffered_ns = time_ns + prebuffer_ns; | |
4606 | |||
4607 | // Figure out how much data we have downloaded for the prebuffer. This will | ||
4608 | // be used later to adjust the bits per sample to try. | ||
4609 |
4/4✓ Branch 0 taken 121 times.
✓ Branch 1 taken 1 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 100 times.
|
122 | while (desc_end.start_time_ns != -1 && desc_end.end_time_ns < prebuffered_ns) { |
4610 | // Prebuffered the entire Cue. | ||
4611 | 21 | prebuffer_bytes += desc_end.end_offset - desc_end.start_offset; | |
4612 | 21 | temp_prebuffer_ns -= desc_end.end_time_ns - desc_end.start_time_ns; | |
4613 | 21 | desc_end = get_cue_desc(s, desc_end.end_time_ns, cues_start); | |
4614 | } | ||
4615 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 100 times.
|
101 | if (desc_end.start_time_ns == -1) { |
4616 | // The prebuffer is larger than the duration. | ||
4617 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (matroska->duration * matroska->time_scale >= prebuffered_ns) |
4618 | ✗ | return -1; | |
4619 | 1 | bits_per_second = 0.0; | |
4620 | } else { | ||
4621 | // The prebuffer ends in the last Cue. Estimate how much data was | ||
4622 | // prebuffered. | ||
4623 | 100 | pre_bytes = desc_end.end_offset - desc_end.start_offset; | |
4624 |
1/2✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
|
100 | if (desc_end.end_time_ns <= desc_end.start_time_ns || |
4625 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
|
100 | desc_end.end_time_ns - (uint64_t)desc_end.start_time_ns > INT64_MAX) |
4626 | ✗ | return -1; | |
4627 | 100 | pre_ns = desc_end.end_time_ns - desc_end.start_time_ns; | |
4628 | 100 | pre_sec = pre_ns / nano_seconds_per_second; | |
4629 | 100 | prebuffer_bytes += | |
4630 | 100 | pre_bytes * ((temp_prebuffer_ns / nano_seconds_per_second) / pre_sec); | |
4631 | |||
4632 | 100 | prebuffer = prebuffer_ns / nano_seconds_per_second; | |
4633 | |||
4634 | // Set this to 0.0 in case our prebuffer buffers the entire video. | ||
4635 | 100 | bits_per_second = 0.0; | |
4636 | do { | ||
4637 | 560 | int64_t desc_bytes = desc_end.end_offset - desc_beg.start_offset; | |
4638 | 560 | int64_t desc_ns = desc_end.end_time_ns - desc_beg.start_time_ns; | |
4639 | double desc_sec, calc_bits_per_second, percent, mod_bits_per_second; | ||
4640 |
2/4✓ Branch 0 taken 560 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 560 times.
|
560 | if (desc_bytes <= 0 || desc_bytes > INT64_MAX/8) |
4641 | ✗ | return -1; | |
4642 | |||
4643 | 560 | desc_sec = desc_ns / nano_seconds_per_second; | |
4644 | 560 | calc_bits_per_second = (desc_bytes * 8) / desc_sec; | |
4645 | |||
4646 | // Drop the bps by the percentage of bytes buffered. | ||
4647 | 560 | percent = (desc_bytes - prebuffer_bytes) / desc_bytes; | |
4648 | 560 | mod_bits_per_second = calc_bits_per_second * percent; | |
4649 | |||
4650 |
2/2✓ Branch 0 taken 555 times.
✓ Branch 1 taken 5 times.
|
560 | if (prebuffer < desc_sec) { |
4651 | 555 | double search_sec = | |
4652 | 555 | (double)(matroska->duration * matroska->time_scale) / nano_seconds_per_second; | |
4653 | |||
4654 | // Add 1 so the bits per second should be a little bit greater than file | ||
4655 | // datarate. | ||
4656 | 555 | int64_t bps = (int64_t)(mod_bits_per_second) + 1; | |
4657 | 555 | const double min_buffer = 0.0; | |
4658 | 555 | double buffer = prebuffer; | |
4659 | 555 | double sec_to_download = 0.0; | |
4660 | |||
4661 | 555 | int rv = buffer_size_after_time_downloaded(prebuffered_ns, search_sec, bps, | |
4662 | min_buffer, &buffer, &sec_to_download, | ||
4663 | s, cues_start); | ||
4664 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 555 times.
|
555 | if (rv < 0) { |
4665 | ✗ | return -1; | |
4666 |
2/2✓ Branch 0 taken 100 times.
✓ Branch 1 taken 455 times.
|
555 | } else if (rv == 0) { |
4667 | 100 | bits_per_second = (double)(bps); | |
4668 | 100 | break; | |
4669 | } | ||
4670 | } | ||
4671 | |||
4672 | 460 | desc_end = get_cue_desc(s, desc_end.end_time_ns, cues_start); | |
4673 |
1/2✓ Branch 0 taken 460 times.
✗ Branch 1 not taken.
|
460 | } while (desc_end.start_time_ns != -1); |
4674 | } | ||
4675 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 63 times.
|
101 | if (bandwidth < bits_per_second) bandwidth = bits_per_second; |
4676 | } | ||
4677 | 10 | return (int64_t)bandwidth; | |
4678 | } | ||
4679 | |||
4680 | 10 | static int webm_dash_manifest_cues(AVFormatContext *s, int64_t init_range) | |
4681 | { | ||
4682 | 10 | MatroskaDemuxContext *matroska = s->priv_data; | |
4683 | 10 | EbmlList *seekhead_list = &matroska->seekhead; | |
4684 | 10 | MatroskaSeekhead *seekhead = seekhead_list->elem; | |
4685 | 10 | AVStream *const st = s->streams[0]; | |
4686 | 10 | FFStream *const sti = ffstream(st); | |
4687 | AVBPrint bprint; | ||
4688 | char *buf; | ||
4689 | 10 | int64_t cues_start = -1, cues_end = -1, before_pos, bandwidth; | |
4690 | int i; | ||
4691 | int ret; | ||
4692 | |||
4693 | // determine cues start and end positions | ||
4694 |
1/2✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
|
34 | for (i = 0; i < seekhead_list->nb_elem; i++) |
4695 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 24 times.
|
34 | if (seekhead[i].id == MATROSKA_ID_CUES) |
4696 | 10 | break; | |
4697 | |||
4698 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (i >= seekhead_list->nb_elem) return -1; |
4699 | |||
4700 | 10 | before_pos = avio_tell(matroska->ctx->pb); | |
4701 | 10 | cues_start = seekhead[i].pos + matroska->segment_start; | |
4702 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | if (avio_seek(matroska->ctx->pb, cues_start, SEEK_SET) == cues_start) { |
4703 | // cues_end is computed as cues_start + cues_length + length of the | ||
4704 | // Cues element ID (i.e. 4) + EBML length of the Cues element. | ||
4705 | // cues_end is inclusive and the above sum is reduced by 1. | ||
4706 | uint64_t cues_length, cues_id; | ||
4707 | int bytes_read; | ||
4708 | 10 | bytes_read = ebml_read_num (matroska, matroska->ctx->pb, 4, &cues_id, 1); | |
4709 |
2/4✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
|
10 | if (bytes_read < 0 || cues_id != (MATROSKA_ID_CUES & 0xfffffff)) |
4710 | ✗ | return bytes_read < 0 ? bytes_read : AVERROR_INVALIDDATA; | |
4711 | 10 | bytes_read = ebml_read_length(matroska, matroska->ctx->pb, &cues_length); | |
4712 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (bytes_read < 0) |
4713 | ✗ | return bytes_read; | |
4714 | 10 | cues_end = cues_start + 4 + bytes_read + cues_length - 1; | |
4715 | } | ||
4716 | 10 | avio_seek(matroska->ctx->pb, before_pos, SEEK_SET); | |
4717 |
2/4✓ Branch 0 taken 10 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 10 times.
|
10 | if (cues_start == -1 || cues_end == -1) return -1; |
4718 | |||
4719 | // parse the cues | ||
4720 | 10 | matroska_parse_cues(matroska); | |
4721 | |||
4722 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (!sti->nb_index_entries) |
4723 | ✗ | return AVERROR_INVALIDDATA; | |
4724 | |||
4725 | // cues start | ||
4726 | 10 | av_dict_set_int(&s->streams[0]->metadata, CUES_START, cues_start, 0); | |
4727 | |||
4728 | // cues end | ||
4729 | 10 | av_dict_set_int(&s->streams[0]->metadata, CUES_END, cues_end, 0); | |
4730 | |||
4731 | // if the file has cues at the start, fix up the init range so that | ||
4732 | // it does not include it | ||
4733 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (cues_start <= init_range) |
4734 | ✗ | av_dict_set_int(&s->streams[0]->metadata, INITIALIZATION_RANGE, cues_start - 1, 0); | |
4735 | |||
4736 | // bandwidth | ||
4737 | 10 | bandwidth = webm_dash_manifest_compute_bandwidth(s, cues_start); | |
4738 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (bandwidth < 0) return -1; |
4739 | 10 | av_dict_set_int(&s->streams[0]->metadata, BANDWIDTH, bandwidth, 0); | |
4740 | |||
4741 | // check if all clusters start with key frames | ||
4742 | 10 | av_dict_set_int(&s->streams[0]->metadata, CLUSTER_KEYFRAME, webm_clusters_start_with_keyframe(s), 0); | |
4743 | |||
4744 | // Store cue point timestamps as a comma separated list | ||
4745 | // for checking subsegment alignment in the muxer. | ||
4746 | 10 | av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); | |
4747 |
2/2✓ Branch 0 taken 101 times.
✓ Branch 1 taken 10 times.
|
111 | for (int i = 0; i < sti->nb_index_entries; i++) |
4748 | 101 | av_bprintf(&bprint, "%" PRId64",", sti->index_entries[i].timestamp); | |
4749 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
|
10 | if (!av_bprint_is_complete(&bprint)) { |
4750 | ✗ | av_bprint_finalize(&bprint, NULL); | |
4751 | ✗ | return AVERROR(ENOMEM); | |
4752 | } | ||
4753 | // Remove the trailing ',' | ||
4754 | 10 | bprint.str[--bprint.len] = '\0'; | |
4755 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
|
10 | if ((ret = av_bprint_finalize(&bprint, &buf)) < 0) |
4756 | ✗ | return ret; | |
4757 | 10 | av_dict_set(&s->streams[0]->metadata, CUE_TIMESTAMPS, | |
4758 | buf, AV_DICT_DONT_STRDUP_VAL); | ||
4759 | |||
4760 | 10 | return 0; | |
4761 | } | ||
4762 | |||
4763 | 14 | static int webm_dash_manifest_read_header(AVFormatContext *s) | |
4764 | { | ||
4765 | char *buf; | ||
4766 | 14 | int ret = matroska_read_header(s); | |
4767 | int64_t init_range; | ||
4768 | MatroskaTrack *tracks; | ||
4769 | 14 | MatroskaDemuxContext *matroska = s->priv_data; | |
4770 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (ret) { |
4771 | ✗ | av_log(s, AV_LOG_ERROR, "Failed to read file headers\n"); | |
4772 | ✗ | return -1; | |
4773 | } | ||
4774 |
2/4✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 14 times.
|
14 | if (!matroska->tracks.nb_elem || !s->nb_streams) { |
4775 | ✗ | av_log(s, AV_LOG_ERROR, "No track found\n"); | |
4776 | ✗ | return AVERROR_INVALIDDATA; | |
4777 | } | ||
4778 | |||
4779 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
|
14 | if (!matroska->is_live) { |
4780 | 10 | buf = av_asprintf("%g", matroska->duration); | |
4781 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (!buf) |
4782 | ✗ | return AVERROR(ENOMEM); | |
4783 | 10 | av_dict_set(&s->streams[0]->metadata, DURATION, | |
4784 | buf, AV_DICT_DONT_STRDUP_VAL); | ||
4785 | |||
4786 | // initialization range | ||
4787 | // 5 is the offset of Cluster ID. | ||
4788 | 10 | init_range = avio_tell(s->pb) - 5; | |
4789 | 10 | av_dict_set_int(&s->streams[0]->metadata, INITIALIZATION_RANGE, init_range, 0); | |
4790 | } | ||
4791 | |||
4792 | // basename of the file | ||
4793 | 14 | buf = strrchr(s->url, '/'); | |
4794 |
1/2✓ Branch 0 taken 14 times.
✗ Branch 1 not taken.
|
14 | av_dict_set(&s->streams[0]->metadata, FILENAME, buf ? ++buf : s->url, 0); |
4795 | |||
4796 | // track number | ||
4797 | 14 | tracks = matroska->tracks.elem; | |
4798 | 14 | av_dict_set_int(&s->streams[0]->metadata, TRACK_NUMBER, tracks[0].num, 0); | |
4799 | |||
4800 | // parse the cues and populate Cue related fields | ||
4801 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
|
14 | if (!matroska->is_live) { |
4802 | 10 | ret = webm_dash_manifest_cues(s, init_range); | |
4803 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (ret < 0) { |
4804 | ✗ | av_log(s, AV_LOG_ERROR, "Error parsing Cues\n"); | |
4805 | ✗ | return ret; | |
4806 | } | ||
4807 | } | ||
4808 | |||
4809 | // use the bandwidth from the command line if it was provided | ||
4810 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
|
14 | if (matroska->bandwidth > 0) { |
4811 | 2 | av_dict_set_int(&s->streams[0]->metadata, BANDWIDTH, | |
4812 | 2 | matroska->bandwidth, 0); | |
4813 | } | ||
4814 | 14 | return 0; | |
4815 | } | ||
4816 | |||
4817 | 28 | static int webm_dash_manifest_read_packet(AVFormatContext *s, AVPacket *pkt) | |
4818 | { | ||
4819 | 28 | return AVERROR_EOF; | |
4820 | } | ||
4821 | |||
4822 | #define OFFSET(x) offsetof(MatroskaDemuxContext, x) | ||
4823 | static const AVOption options[] = { | ||
4824 | { "live", "flag indicating that the input is a live file that only has the headers.", OFFSET(is_live), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, AV_OPT_FLAG_DECODING_PARAM }, | ||
4825 | { "bandwidth", "bandwidth of this stream to be specified in the DASH manifest.", OFFSET(bandwidth), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, AV_OPT_FLAG_DECODING_PARAM }, | ||
4826 | { NULL }, | ||
4827 | }; | ||
4828 | |||
4829 | static const AVClass webm_dash_class = { | ||
4830 | .class_name = "WebM DASH Manifest demuxer", | ||
4831 | .item_name = av_default_item_name, | ||
4832 | .option = options, | ||
4833 | .version = LIBAVUTIL_VERSION_INT, | ||
4834 | }; | ||
4835 | |||
4836 | const FFInputFormat ff_webm_dash_manifest_demuxer = { | ||
4837 | .p.name = "webm_dash_manifest", | ||
4838 | .p.long_name = NULL_IF_CONFIG_SMALL("WebM DASH Manifest"), | ||
4839 | .p.priv_class = &webm_dash_class, | ||
4840 | .priv_data_size = sizeof(MatroskaDemuxContext), | ||
4841 | .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP, | ||
4842 | .read_header = webm_dash_manifest_read_header, | ||
4843 | .read_packet = webm_dash_manifest_read_packet, | ||
4844 | .read_close = matroska_read_close, | ||
4845 | }; | ||
4846 | #endif | ||
4847 | |||
4848 | const FFInputFormat ff_matroska_demuxer = { | ||
4849 | .p.name = "matroska,webm", | ||
4850 | .p.long_name = NULL_IF_CONFIG_SMALL("Matroska / WebM"), | ||
4851 | .p.extensions = "mkv,mk3d,mka,mks,webm", | ||
4852 | .p.mime_type = "audio/webm,audio/x-matroska,video/webm,video/x-matroska", | ||
4853 | .priv_data_size = sizeof(MatroskaDemuxContext), | ||
4854 | .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP, | ||
4855 | .read_probe = matroska_probe, | ||
4856 | .read_header = matroska_read_header, | ||
4857 | .read_packet = matroska_read_packet, | ||
4858 | .read_close = matroska_read_close, | ||
4859 | .read_seek = matroska_read_seek, | ||
4860 | }; | ||
4861 |