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 | 142681 | static int ebml_read_num(MatroskaDemuxContext *matroska, AVIOContext *pb, | |
914 | int max_size, uint64_t *number, int eof_forbidden) | ||
915 | { | ||
916 | 142681 | 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 | 142681 | total = avio_r8(pb); | |
922 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 142667 times.
|
142681 | if (pb->eof_reached) |
923 | 14 | goto err; | |
924 | |||
925 | /* get the length of the EBML number */ | ||
926 | 142667 | read = 8 - ff_log2_tab[total]; | |
927 | |||
928 |
2/4✓ Branch 0 taken 142667 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 142667 times.
|
142667 | 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 | 142667 | total ^= 1 << ff_log2_tab[total]; | |
945 |
2/2✓ Branch 0 taken 71467 times.
✓ Branch 1 taken 142667 times.
|
214134 | while (n++ < read) |
946 | 71467 | total = (total << 8) | avio_r8(pb); | |
947 | |||
948 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 142667 times.
|
142667 | if (pb->eof_reached) { |
949 | ✗ | eof_forbidden = 1; | |
950 | ✗ | goto err; | |
951 | } | ||
952 | |||
953 | 142667 | *number = total; | |
954 | |||
955 | 142667 | 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 | 55823 | static int ebml_read_length(MatroskaDemuxContext *matroska, AVIOContext *pb, | |
979 | uint64_t *number) | ||
980 | { | ||
981 | 55823 | int res = ebml_read_num(matroska, pb, 8, number, 1); | |
982 |
3/4✓ Branch 0 taken 55823 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
✓ Branch 3 taken 55806 times.
|
55823 | if (res > 0 && *number + 1 == 1ULL << (7 * res)) |
983 | 17 | *number = EBML_UNKNOWN_LENGTH; | |
984 | 55823 | return res; | |
985 | } | ||
986 | |||
987 | /* | ||
988 | * Read the next element as an unsigned int. | ||
989 | * Returns NEEDS_CHECKING unless size == 0. | ||
990 | */ | ||
991 | 10649 | static int ebml_read_uint(AVIOContext *pb, int size, | |
992 | uint64_t default_value, uint64_t *num) | ||
993 | { | ||
994 | 10649 | int n = 0; | |
995 | |||
996 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10649 times.
|
10649 | if (size == 0) { |
997 | ✗ | *num = default_value; | |
998 | ✗ | return 0; | |
999 | } | ||
1000 | /* big-endian ordering; build up number */ | ||
1001 | 10649 | *num = 0; | |
1002 |
2/2✓ Branch 0 taken 26942 times.
✓ Branch 1 taken 10649 times.
|
37591 | while (n++ < size) |
1003 | 26942 | *num = (*num << 8) | avio_r8(pb); | |
1004 | |||
1005 | 10649 | 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 | 746 | 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 746 times.
|
746 | if (size == 0) { |
1039 | ✗ | *num = default_value; | |
1040 | ✗ | return 0; | |
1041 |
2/2✓ Branch 0 taken 86 times.
✓ Branch 1 taken 660 times.
|
746 | } else if (size == 4) { |
1042 | 86 | *num = av_int2float(avio_rb32(pb)); | |
1043 |
1/2✓ Branch 0 taken 660 times.
✗ Branch 1 not taken.
|
660 | } else if (size == 8) { |
1044 | 660 | *num = av_int2double(avio_rb64(pb)); | |
1045 | } else | ||
1046 | ✗ | return AVERROR_INVALIDDATA; | |
1047 | |||
1048 | 746 | 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 | 2332 | 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 2332 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
2332 | 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 2332 times.
|
2332 | if (!(res = av_malloc(size + 1))) |
1069 | ✗ | return AVERROR(ENOMEM); | |
1070 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 2332 times.
|
2332 | if ((ret = avio_read(pb, (uint8_t *) res, size)) != size) { |
1071 | ✗ | av_free(res); | |
1072 | ✗ | return ret < 0 ? ret : NEEDS_CHECKING; | |
1073 | } | ||
1074 | 2332 | (res)[size] = '\0'; | |
1075 | } | ||
1076 | 2332 | av_free(*str); | |
1077 | 2332 | *str = res; | |
1078 | |||
1079 | 2332 | 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 | 31040 | static int ebml_read_binary(AVIOContext *pb, int length, | |
1087 | int64_t pos, EbmlBin *bin) | ||
1088 | { | ||
1089 | int ret; | ||
1090 | |||
1091 | 31040 | ret = av_buffer_realloc(&bin->buf, length + AV_INPUT_BUFFER_PADDING_SIZE); | |
1092 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31040 times.
|
31040 | if (ret < 0) |
1093 | ✗ | return ret; | |
1094 | 31040 | memset(bin->buf->data + length, 0, AV_INPUT_BUFFER_PADDING_SIZE); | |
1095 | |||
1096 | 31040 | bin->data = bin->buf->data; | |
1097 | 31040 | bin->size = length; | |
1098 | 31040 | bin->pos = pos; | |
1099 |
2/2✓ Branch 1 taken 10 times.
✓ Branch 2 taken 31030 times.
|
31040 | 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 | 31030 | 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 | 7773 | 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 7773 times.
|
7773 | 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 | 7773 | level = &matroska->levels[matroska->num_levels++]; | |
1126 | 7773 | level->start = pos; | |
1127 | 7773 | level->length = length; | |
1128 | |||
1129 | 7773 | 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 | 57706 | 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 120097 times.
✓ Branch 1 taken 735 times.
|
120832 | for (i = 0; syntax[i].id; i++) |
1162 |
2/2✓ Branch 0 taken 56971 times.
✓ Branch 1 taken 63126 times.
|
120097 | if (id == syntax[i].id) |
1163 | 56971 | break; | |
1164 | |||
1165 | 57706 | return &syntax[i]; | |
1166 | } | ||
1167 | |||
1168 | 7773 | static int ebml_parse_nest(MatroskaDemuxContext *matroska, EbmlSyntax *syntax, | |
1169 | void *data) | ||
1170 | { | ||
1171 | int res; | ||
1172 | |||
1173 |
1/2✓ Branch 0 taken 7773 times.
✗ Branch 1 not taken.
|
7773 | if (data) { |
1174 |
2/2✓ Branch 0 taken 49286 times.
✓ Branch 1 taken 7773 times.
|
57059 | for (int i = 0; syntax[i].id; i++) { |
1175 | 49286 | void *dst = (char *)data + syntax[i].data_offset; | |
1176 |
5/5✓ Branch 0 taken 21198 times.
✓ Branch 1 taken 968 times.
✓ Branch 2 taken 1415 times.
✓ Branch 3 taken 3974 times.
✓ Branch 4 taken 21731 times.
|
49286 | switch (syntax[i].type) { |
1177 | 21198 | case EBML_UINT: | |
1178 | 21198 | *(uint64_t *)dst = syntax[i].def.u; | |
1179 | 21198 | break; | |
1180 | 968 | case EBML_SINT: | |
1181 | 968 | *(int64_t *) dst = syntax[i].def.i; | |
1182 | 968 | break; | |
1183 | 1415 | case EBML_FLOAT: | |
1184 | 1415 | *(double *) dst = syntax[i].def.f; | |
1185 | 1415 | break; | |
1186 | 3974 | case EBML_STR: | |
1187 | case EBML_UTF8: | ||
1188 | // the default may be NULL | ||
1189 |
2/2✓ Branch 0 taken 1245 times.
✓ Branch 1 taken 2729 times.
|
3974 | if (syntax[i].def.s) { |
1190 | 1245 | *(char**)dst = av_strdup(syntax[i].def.s); | |
1191 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1245 times.
|
1245 | if (!*(char**)dst) |
1192 | ✗ | return AVERROR(ENOMEM); | |
1193 | } | ||
1194 | 3974 | break; | |
1195 | } | ||
1196 | } | ||
1197 | |||
1198 |
2/2✓ Branch 0 taken 51 times.
✓ Branch 1 taken 7722 times.
|
7773 | if (!matroska->levels[matroska->num_levels - 1].length) { |
1199 | 51 | matroska->num_levels--; | |
1200 | 51 | return 0; | |
1201 | } | ||
1202 | } | ||
1203 | |||
1204 | do { | ||
1205 | 24280 | res = ebml_parse(matroska, syntax, data); | |
1206 |
2/2✓ Branch 0 taken 16558 times.
✓ Branch 1 taken 7722 times.
|
24280 | } while (!res); |
1207 | |||
1208 |
2/2✓ Branch 0 taken 1170 times.
✓ Branch 1 taken 6552 times.
|
7722 | return res == LEVEL_ENDED ? 0 : res; |
1209 | } | ||
1210 | |||
1211 | 2419 | 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 | 2419 | unsigned int bits = av_log2(id); | |
1217 |
2/4✓ Branch 0 taken 2419 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 2419 times.
✗ Branch 3 not taken.
|
2419 | 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 | 2419 | 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 2419 times.
|
2419 | 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 2394 times.
|
2419 | if (id == MATROSKA_ID_CLUSTER) |
1235 | 25 | return NULL; | |
1236 | |||
1237 | // There can be multiple SeekHeads and Tags. | ||
1238 |
2/2✓ Branch 0 taken 4897 times.
✓ Branch 1 taken 1548 times.
|
6445 | for (i = 0; i < matroska->num_level1_elems; i++) { |
1239 |
2/2✓ Branch 0 taken 854 times.
✓ Branch 1 taken 4043 times.
|
4897 | if (matroska->level1_elems[i].id == id) { |
1240 |
3/4✓ Branch 0 taken 8 times.
✓ Branch 1 taken 846 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 8 times.
|
854 | if (matroska->level1_elems[i].pos == pos || |
1241 | ✗ | id != MATROSKA_ID_SEEKHEAD && id != MATROSKA_ID_TAGS) | |
1242 | 846 | 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 1548 times.
|
1548 | 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 | 1548 | elem = &matroska->level1_elems[matroska->num_level1_elems++]; | |
1253 | 1548 | *elem = (MatroskaLevel1Element){.id = id}; | |
1254 | |||
1255 | 1548 | return elem; | |
1256 | } | ||
1257 | |||
1258 | 57717 | 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 | 57717 | AVIOContext *pb = matroska->ctx->pb; | |
1275 | uint32_t id; | ||
1276 | uint64_t length; | ||
1277 | 57717 | int64_t pos = avio_tell(pb), pos_alt; | |
1278 | 57717 | int res, update_pos = 1, level_check; | |
1279 | MatroskaLevel1Element *level1_elem; | ||
1280 |
2/2✓ Branch 0 taken 56977 times.
✓ Branch 1 taken 740 times.
|
57717 | MatroskaLevel *level = matroska->num_levels ? &matroska->levels[matroska->num_levels - 1] : NULL; |
1281 | |||
1282 |
2/2✓ Branch 0 taken 55756 times.
✓ Branch 1 taken 1961 times.
|
57717 | if (!matroska->current_id) { |
1283 | uint64_t id; | ||
1284 | 55756 | res = ebml_read_num(matroska, pb, 4, &id, 0); | |
1285 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 55742 times.
|
55756 | 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 | 55742 | matroska->current_id = id | 1 << 7 * res; | |
1304 | 55742 | pos_alt = pos + res; | |
1305 | } else { | ||
1306 | 1961 | pos_alt = pos; | |
1307 | 1961 | pos -= (av_log2(matroska->current_id) + 7) / 8; | |
1308 | } | ||
1309 | |||
1310 | 57703 | id = matroska->current_id; | |
1311 | |||
1312 | 57703 | syntax = ebml_parse_id(syntax, id); | |
1313 |
6/6✓ Branch 0 taken 735 times.
✓ Branch 1 taken 56968 times.
✓ Branch 2 taken 510 times.
✓ Branch 3 taken 225 times.
✓ Branch 4 taken 44 times.
✓ Branch 5 taken 466 times.
|
57703 | 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 56563 times.
✓ Branch 1 taken 1137 times.
|
57700 | if (data) { |
1334 | 56563 | data = (char *) data + syntax->data_offset; | |
1335 |
2/2✓ Branch 0 taken 3697 times.
✓ Branch 1 taken 52866 times.
|
56563 | if (syntax->list_elem_size) { |
1336 | 3697 | EbmlList *list = data; | |
1337 | void *newelem; | ||
1338 | |||
1339 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3697 times.
|
3697 | if ((unsigned)list->nb_elem + 1 >= UINT_MAX / syntax->list_elem_size) |
1340 | ✗ | return AVERROR(ENOMEM); | |
1341 | 3697 | newelem = av_fast_realloc(list->elem, | |
1342 | &list->alloc_elem_size, | ||
1343 | 3697 | (list->nb_elem + 1) * syntax->list_elem_size); | |
1344 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3697 times.
|
3697 | if (!newelem) |
1345 | ✗ | return AVERROR(ENOMEM); | |
1346 | 3697 | list->elem = newelem; | |
1347 | 3697 | data = (char *) list->elem + list->nb_elem * syntax->list_elem_size; | |
1348 | 3697 | memset(data, 0, syntax->list_elem_size); | |
1349 | 3697 | list->nb_elem++; | |
1350 | } | ||
1351 | } | ||
1352 | |||
1353 |
2/2✓ Branch 0 taken 55734 times.
✓ Branch 1 taken 1966 times.
|
57700 | if (syntax->type != EBML_STOP) { |
1354 | 55734 | matroska->current_id = 0; | |
1355 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 55734 times.
|
55734 | if ((res = ebml_read_length(matroska, pb, &length)) < 0) |
1356 | ✗ | return res; | |
1357 | |||
1358 | 55734 | pos_alt += res; | |
1359 | |||
1360 |
2/2✓ Branch 0 taken 54994 times.
✓ Branch 1 taken 740 times.
|
55734 | if (matroska->num_levels > 0) { |
1361 |
2/2✓ Branch 0 taken 54988 times.
✓ Branch 1 taken 6 times.
|
54994 | if (length != EBML_UNKNOWN_LENGTH && |
1362 |
2/2✓ Branch 0 taken 54878 times.
✓ Branch 1 taken 110 times.
|
109866 | level->length != EBML_UNKNOWN_LENGTH) { |
1363 | 54878 | uint64_t elem_end = pos_alt + length, | |
1364 | 54878 | level_end = level->start + level->length; | |
1365 | |||
1366 |
2/2✓ Branch 0 taken 47305 times.
✓ Branch 1 taken 7573 times.
|
54878 | if (elem_end < level_end) { |
1367 | 47305 | level_check = 0; | |
1368 |
1/2✓ Branch 0 taken 7573 times.
✗ Branch 1 not taken.
|
7573 | } else if (elem_end == level_end) { |
1369 | 7573 | 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 | 740 | level_check = 0; | |
1399 | |||
1400 |
4/4✓ Branch 0 taken 47633 times.
✓ Branch 1 taken 8101 times.
✓ Branch 2 taken 2 times.
✓ Branch 3 taken 47631 times.
|
55734 | 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 55602 times.
|
55732 | 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 55693 times.
✓ Branch 1 taken 39 times.
|
55732 | 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 | 55693 | matroska->resync_pos = pos; | |
1467 | } | ||
1468 | |||
1469 |
3/4✓ Branch 0 taken 335 times.
✓ Branch 1 taken 55397 times.
✓ Branch 2 taken 335 times.
✗ Branch 3 not taken.
|
55732 | if (!data && length != EBML_UNKNOWN_LENGTH) |
1470 | 335 | goto skip; | |
1471 | } | ||
1472 | |||
1473 |
8/8✓ Branch 0 taken 10649 times.
✓ Branch 1 taken 160 times.
✓ Branch 2 taken 746 times.
✓ Branch 3 taken 2332 times.
✓ Branch 4 taken 31040 times.
✓ Branch 5 taken 7773 times.
✓ Branch 6 taken 1966 times.
✓ Branch 7 taken 2697 times.
|
57363 | switch (syntax->type) { |
1474 | 10649 | case EBML_UINT: | |
1475 | 10649 | res = ebml_read_uint(pb, length, syntax->def.u, data); | |
1476 | 10649 | break; | |
1477 | 160 | case EBML_SINT: | |
1478 | 160 | res = ebml_read_sint(pb, length, syntax->def.i, data); | |
1479 | 160 | break; | |
1480 | 746 | case EBML_FLOAT: | |
1481 | 746 | res = ebml_read_float(pb, length, syntax->def.f, data); | |
1482 | 746 | break; | |
1483 | 2332 | case EBML_STR: | |
1484 | case EBML_UTF8: | ||
1485 | 2332 | res = ebml_read_ascii(pb, length, syntax->def.s, data); | |
1486 | 2332 | break; | |
1487 | 31040 | case EBML_BIN: | |
1488 | 31040 | res = ebml_read_binary(pb, length, pos_alt, data); | |
1489 | 31040 | break; | |
1490 | 7773 | case EBML_LEVEL1: | |
1491 | case EBML_NEST: | ||
1492 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 7773 times.
|
7773 | if ((res = ebml_read_master(matroska, length, pos_alt)) < 0) |
1493 | ✗ | return res; | |
1494 |
2/2✓ Branch 0 taken 370 times.
✓ Branch 1 taken 7403 times.
|
7773 | if (id == MATROSKA_ID_SEGMENT) |
1495 | 370 | matroska->segment_start = pos_alt; | |
1496 |
2/2✓ Branch 0 taken 20 times.
✓ Branch 1 taken 7753 times.
|
7773 | if (id == MATROSKA_ID_CUES) |
1497 | 20 | matroska->cues_parsing_deferred = 0; | |
1498 |
3/4✓ Branch 0 taken 1231 times.
✓ Branch 1 taken 6542 times.
✓ Branch 2 taken 1231 times.
✗ Branch 3 not taken.
|
9004 | if (syntax->type == EBML_LEVEL1 && |
1499 | 1231 | (level1_elem = matroska_find_level1_elem(matroska, syntax->id, pos))) { | |
1500 |
2/2✓ Branch 0 taken 1209 times.
✓ Branch 1 taken 22 times.
|
1231 | if (!level1_elem->pos) { |
1501 | // Zero is not a valid position for a level 1 element. | ||
1502 | 1209 | 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 | 1231 | level1_elem->parsed = 1; | |
1506 | } | ||
1507 |
2/2✓ Branch 1 taken 1170 times.
✓ Branch 2 taken 6603 times.
|
7773 | if (res = ebml_parse_nest(matroska, syntax->def.n, data)) |
1508 | 1170 | return res; | |
1509 | 6603 | break; | |
1510 | 1966 | case EBML_STOP: | |
1511 | 1966 | return 1; | |
1512 | 335 | skip: | |
1513 | 3032 | default: | |
1514 |
2/2✓ Branch 0 taken 3030 times.
✓ Branch 1 taken 2 times.
|
3032 | if (length) { |
1515 | int64_t res2; | ||
1516 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 3030 times.
|
3030 | 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 3030 times.
✗ Branch 2 not taken.
|
3030 | 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 | 3030 | avio_r8(pb); | |
1528 | 3030 | res = NEEDS_CHECKING; | |
1529 | } else | ||
1530 | ✗ | res = res2; | |
1531 | } else | ||
1532 | 2 | res = 0; | |
1533 | } | ||
1534 |
2/2✓ Branch 0 taken 14595 times.
✓ Branch 1 taken 39967 times.
|
54562 | if (res) { |
1535 |
1/2✓ Branch 0 taken 14595 times.
✗ Branch 1 not taken.
|
14595 | if (res == NEEDS_CHECKING) { |
1536 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 14585 times.
|
14595 | 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 | 14585 | 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 | 39967 | level_check: | |
1558 |
3/4✓ Branch 0 taken 144 times.
✓ Branch 1 taken 54408 times.
✓ Branch 2 taken 144 times.
✗ Branch 3 not taken.
|
54552 | 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 7508 times.
✓ Branch 1 taken 47044 times.
✓ Branch 2 taken 7478 times.
✓ Branch 3 taken 30 times.
|
54552 | if (level_check == LEVEL_ENDED && matroska->num_levels) { |
1565 | 7478 | level = &matroska->levels[matroska->num_levels - 1]; | |
1566 | 7478 | 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 14307 times.
✓ Branch 1 taken 727 times.
✓ Branch 2 taken 7556 times.
✓ Branch 3 taken 6751 times.
|
15034 | while (matroska->num_levels && pos == level->start + level->length) { |
1571 | 7556 | matroska->num_levels--; | |
1572 | 7556 | level--; | |
1573 | } | ||
1574 | } | ||
1575 | |||
1576 | 54552 | return level_check; | |
1577 | } | ||
1578 | |||
1579 | 72168 | static void ebml_free(EbmlSyntax *syntax, void *data) | |
1580 | { | ||
1581 | int i, j; | ||
1582 |
2/2✓ Branch 0 taken 298927 times.
✓ Branch 1 taken 72168 times.
|
371095 | for (i = 0; syntax[i].id; i++) { |
1583 | 298927 | void *data_off = (char *) data + syntax[i].data_offset; | |
1584 |
4/4✓ Branch 0 taken 3968 times.
✓ Branch 1 taken 32592 times.
✓ Branch 2 taken 72890 times.
✓ Branch 3 taken 189477 times.
|
298927 | switch (syntax[i].type) { |
1585 | 3968 | case EBML_STR: | |
1586 | case EBML_UTF8: | ||
1587 | 3968 | av_freep(data_off); | |
1588 | 3968 | break; | |
1589 | 32592 | case EBML_BIN: | |
1590 | 32592 | av_buffer_unref(&((EbmlBin *) data_off)->buf); | |
1591 | 32592 | break; | |
1592 | 72890 | case EBML_LEVEL1: | |
1593 | case EBML_NEST: | ||
1594 |
2/2✓ Branch 0 taken 35888 times.
✓ Branch 1 taken 37002 times.
|
72890 | if (syntax[i].list_elem_size) { |
1595 | 35888 | EbmlList *list = data_off; | |
1596 | 35888 | char *ptr = list->elem; | |
1597 |
2/2✓ Branch 0 taken 3697 times.
✓ Branch 1 taken 35888 times.
|
39585 | for (j = 0; j < list->nb_elem; |
1598 | 3697 | j++, ptr += syntax[i].list_elem_size) | |
1599 | 3697 | ebml_free(syntax[i].def.n, ptr); | |
1600 | 35888 | av_freep(&list->elem); | |
1601 | 35888 | list->nb_elem = 0; | |
1602 | 35888 | list->alloc_elem_size = 0; | |
1603 | } else | ||
1604 | 37002 | ebml_free(syntax[i].def.n, data_off); | |
1605 | default: | ||
1606 | 262367 | break; | |
1607 | } | ||
1608 | } | ||
1609 | 72168 | } | |
1610 | |||
1611 | /* | ||
1612 | * Autodetecting... | ||
1613 | */ | ||
1614 | 7211 | static int matroska_probe(const AVProbeData *p) | |
1615 | { | ||
1616 | 7211 | uint64_t total = 0; | |
1617 | 7211 | int len_mask = 0x80, size = 1, n = 1, i; | |
1618 | |||
1619 | /* EBML header? */ | ||
1620 |
2/2✓ Branch 0 taken 6863 times.
✓ Branch 1 taken 348 times.
|
7211 | if (AV_RB32(p->buf) != EBML_ID_HEADER) |
1621 | 6863 | return 0; | |
1622 | |||
1623 | /* length of header */ | ||
1624 | 348 | total = p->buf[4]; | |
1625 |
3/4✓ Branch 0 taken 2084 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1736 times.
✓ Branch 3 taken 348 times.
|
2084 | 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 348 times.
|
348 | if (size > 8) |
1630 | ✗ | return 0; | |
1631 | 348 | total &= (len_mask - 1); | |
1632 |
2/2✓ Branch 0 taken 1736 times.
✓ Branch 1 taken 348 times.
|
2084 | while (n < size) |
1633 | 1736 | total = (total << 8) | p->buf[4 + n++]; | |
1634 | |||
1635 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 348 times.
|
348 | 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 348 times.
|
348 | 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 599 times.
✗ Branch 1 not taken.
|
599 | for (i = 0; i < FF_ARRAY_ELEMS(matroska_doctypes); i++) { |
1649 | 599 | size_t probelen = strlen(matroska_doctypes[i]); | |
1650 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 599 times.
|
599 | if (total < probelen) |
1651 | ✗ | continue; | |
1652 |
2/2✓ Branch 0 taken 12942 times.
✓ Branch 1 taken 251 times.
|
13193 | for (n = 4 + size; n <= 4 + size + total - probelen; n++) |
1653 |
2/2✓ Branch 0 taken 348 times.
✓ Branch 1 taken 12594 times.
|
12942 | if (!memcmp(p->buf + n, matroska_doctypes[i], probelen)) |
1654 | 348 | return AVPROBE_SCORE_MAX; | |
1655 | } | ||
1656 | |||
1657 | // probably valid EBML header but no recognized doctype | ||
1658 | ✗ | return AVPROBE_SCORE_EXTENSION; | |
1659 | } | ||
1660 | |||
1661 | 31370 | static MatroskaTrack *matroska_find_track_by_num(MatroskaDemuxContext *matroska, | |
1662 | uint64_t num) | ||
1663 | { | ||
1664 | 31370 | MatroskaTrack *tracks = matroska->tracks.elem; | |
1665 | int i; | ||
1666 | |||
1667 |
2/2✓ Branch 0 taken 34467 times.
✓ Branch 1 taken 1 times.
|
34468 | for (i = 0; i < matroska->tracks.nb_elem; i++) |
1668 |
2/2✓ Branch 0 taken 31369 times.
✓ Branch 1 taken 3098 times.
|
34467 | if (tracks[i].num == num) |
1669 | 31369 | 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 | 201 | static void matroska_convert_tag(AVFormatContext *s, EbmlList *list, | |
1814 | AVDictionary **metadata, char *prefix) | ||
1815 | { | ||
1816 | 201 | MatroskaTag *tags = list->elem; | |
1817 | char key[1024]; | ||
1818 | int i; | ||
1819 | |||
1820 |
2/2✓ Branch 0 taken 434 times.
✓ Branch 1 taken 201 times.
|
635 | for (i = 0; i < list->nb_elem; i++) { |
1821 | 1302 | const char *lang = tags[i].lang && | |
1822 |
3/4✓ Branch 0 taken 434 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 45 times.
✓ Branch 3 taken 389 times.
|
434 | strcmp(tags[i].lang, "und") ? tags[i].lang : NULL; |
1823 | |||
1824 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 434 times.
|
434 | 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 434 times.
|
434 | if (prefix) |
1829 | ✗ | snprintf(key, sizeof(key), "%s/%s", prefix, tags[i].name); | |
1830 | else | ||
1831 | 434 | av_strlcpy(key, tags[i].name, sizeof(key)); | |
1832 |
3/4✓ Branch 0 taken 434 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 389 times.
✓ Branch 3 taken 45 times.
|
434 | if (tags[i].def || !lang) { |
1833 | 389 | av_dict_set(metadata, key, tags[i].string, 0); | |
1834 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 389 times.
|
389 | 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 389 times.
|
434 | 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 | 201 | ff_metadata_conv(metadata, NULL, ff_mkv_metadata_conv); | |
1846 | 201 | } | |
1847 | |||
1848 | 370 | static void matroska_convert_tags(AVFormatContext *s) | |
1849 | { | ||
1850 | 370 | MatroskaDemuxContext *matroska = s->priv_data; | |
1851 | 370 | MatroskaTags *tags = matroska->tags.elem; | |
1852 | int i, j; | ||
1853 | |||
1854 |
2/2✓ Branch 0 taken 201 times.
✓ Branch 1 taken 370 times.
|
571 | for (i = 0; i < matroska->tags.nb_elem; i++) { |
1855 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 198 times.
|
201 | 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 195 times.
|
198 | } 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 144 times.
✓ Branch 1 taken 51 times.
|
195 | } else if (tags[i].target.trackuid) { |
1890 | 144 | MatroskaTrack *track = matroska->tracks.elem; | |
1891 | 144 | int found = 0; | |
1892 |
2/2✓ Branch 0 taken 380 times.
✓ Branch 1 taken 144 times.
|
524 | for (j = 0; j < matroska->tracks.nb_elem; j++) { |
1893 |
2/2✓ Branch 0 taken 144 times.
✓ Branch 1 taken 236 times.
|
380 | if (track[j].uid == tags[i].target.trackuid && |
1894 |
1/2✓ Branch 0 taken 144 times.
✗ Branch 1 not taken.
|
144 | track[j].stream) { |
1895 | 144 | matroska_convert_tag(s, &tags[i].tag, | |
1896 | 144 | &track[j].stream->metadata, NULL); | |
1897 | 144 | found = 1; | |
1898 | } | ||
1899 | } | ||
1900 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 144 times.
|
144 | 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 | 51 | matroska_convert_tag(s, &tags[i].tag, &s->metadata, | |
1908 | 51 | tags[i].target.type); | |
1909 | } | ||
1910 | } | ||
1911 | 370 | } | |
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 | 370 | static void matroska_execute_seekhead(MatroskaDemuxContext *matroska) | |
1952 | { | ||
1953 | 370 | 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 369 times.
|
370 | if (!(matroska->ctx->pb->seekable & AVIO_SEEKABLE_NORMAL)) |
1958 | 1 | return; | |
1959 | |||
1960 |
2/2✓ Branch 0 taken 1188 times.
✓ Branch 1 taken 368 times.
|
1556 | for (i = 0; i < seekhead_list->nb_elem; i++) { |
1961 | 1188 | MatroskaSeekhead *seekheads = seekhead_list->elem; | |
1962 | 1188 | uint32_t id = seekheads[i].id; | |
1963 | 1188 | int64_t pos = seekheads[i].pos + matroska->segment_start; | |
1964 | MatroskaLevel1Element *elem; | ||
1965 | |||
1966 |
2/4✓ Branch 0 taken 1188 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 1188 times.
|
1188 | if (id != seekheads[i].id || pos < matroska->segment_start) |
1967 | ✗ | continue; | |
1968 | |||
1969 | 1188 | elem = matroska_find_level1_elem(matroska, id, pos); | |
1970 |
4/4✓ Branch 0 taken 1163 times.
✓ Branch 1 taken 25 times.
✓ Branch 2 taken 824 times.
✓ Branch 3 taken 339 times.
|
1188 | if (!elem || elem->parsed) |
1971 | 849 | continue; | |
1972 | |||
1973 | 339 | elem->pos = pos; | |
1974 | |||
1975 | // defer cues parsing until we actually need cue data. | ||
1976 |
2/2✓ Branch 0 taken 327 times.
✓ Branch 1 taken 12 times.
|
339 | if (id == MATROSKA_ID_CUES) |
1977 | 327 | 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 | 383 | static void matroska_add_index_entries(MatroskaDemuxContext *matroska) | |
1990 | { | ||
1991 | EbmlList *index_list; | ||
1992 | MatroskaIndex *index; | ||
1993 | 383 | uint64_t index_scale = 1; | |
1994 | int i, j; | ||
1995 | |||
1996 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 383 times.
|
383 | if (matroska->ctx->flags & AVFMT_FLAG_IGNIDX) |
1997 | ✗ | return; | |
1998 | |||
1999 | 383 | index_list = &matroska->index; | |
2000 | 383 | index = index_list->elem; | |
2001 |
2/2✓ Branch 0 taken 365 times.
✓ Branch 1 taken 18 times.
|
383 | if (index_list->nb_elem < 2) |
2002 | 365 | 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 | 441 | 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 441 times.
|
441 | 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 429 times.
✓ Branch 1 taken 12 times.
|
441 | if (!nb_encodings) |
2052 | 429 | 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 | 333 | static int mkv_parse_video_color(AVStream *st, const MatroskaTrack *track) { | |
2280 | 333 | 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 58 times.
|
333 | if (!track->video.color.nb_elem) |
2285 | 275 | return 0; | |
2286 | |||
2287 | 58 | mastering_meta = &color->mastering_meta; | |
2288 | // Mastering primaries are CIE 1931 coords, and must be > 0. | ||
2289 | 58 | 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 51 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 7 times.
✗ Branch 5 not taken.
|
65 | mastering_meta->white_x > 0 && mastering_meta->white_y > 0; |
2294 | 116 | has_mastering_luminance = mastering_meta->max_luminance > | |
2295 | 65 | mastering_meta->min_luminance.el.f && | |
2296 |
3/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
65 | 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 58 times.
✗ Branch 1 not taken.
|
58 | if (color->matrix_coefficients != AVCOL_SPC_RESERVED) |
2300 | 58 | st->codecpar->color_space = color->matrix_coefficients; | |
2301 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | if (color->primaries != AVCOL_PRI_RESERVED && |
2302 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 2 times.
|
58 | color->primaries != AVCOL_PRI_RESERVED0) |
2303 | 56 | st->codecpar->color_primaries = color->primaries; | |
2304 |
1/2✓ Branch 0 taken 58 times.
✗ Branch 1 not taken.
|
58 | if (color->transfer_characteristics != AVCOL_TRC_RESERVED && |
2305 |
2/2✓ Branch 0 taken 56 times.
✓ Branch 1 taken 2 times.
|
58 | color->transfer_characteristics != AVCOL_TRC_RESERVED0) |
2306 | 56 | st->codecpar->color_trc = color->transfer_characteristics; | |
2307 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 20 times.
|
58 | if (color->range != AVCOL_RANGE_UNSPECIFIED && |
2308 |
1/2✓ Branch 0 taken 38 times.
✗ Branch 1 not taken.
|
38 | color->range <= AVCOL_RANGE_JPEG) |
2309 | 38 | st->codecpar->color_range = color->range; | |
2310 |
2/2✓ Branch 0 taken 37 times.
✓ Branch 1 taken 21 times.
|
58 | if (color->chroma_siting_horz != MATROSKA_COLOUR_CHROMASITINGHORZ_UNDETERMINED && |
2311 |
1/2✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
|
37 | color->chroma_siting_vert != MATROSKA_COLOUR_CHROMASITINGVERT_UNDETERMINED && |
2312 |
1/2✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
|
37 | color->chroma_siting_horz < MATROSKA_COLOUR_CHROMASITINGHORZ_NB && |
2313 |
1/2✓ Branch 0 taken 37 times.
✗ Branch 1 not taken.
|
37 | color->chroma_siting_vert < MATROSKA_COLOUR_CHROMASITINGVERT_NB) { |
2314 | 37 | st->codecpar->chroma_location = | |
2315 | 37 | av_chroma_location_pos_to_enum((color->chroma_siting_horz - 1) << 7, | |
2316 | 37 | (color->chroma_siting_vert - 1) << 7); | |
2317 | } | ||
2318 |
3/4✓ Branch 0 taken 7 times.
✓ Branch 1 taken 51 times.
✓ Branch 2 taken 7 times.
✗ Branch 3 not taken.
|
58 | 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 51 times.
✓ Branch 1 taken 7 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 51 times.
|
58 | 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 | 58 | return 0; | |
2360 | } | ||
2361 | |||
2362 | 327 | static int mkv_create_display_matrix(AVStream *st, | |
2363 | const MatroskaTrackVideoProjection *proj, | ||
2364 | void *logctx) | ||
2365 | { | ||
2366 | AVPacketSideData *sd; | ||
2367 | 327 | double pitch = proj->pitch, yaw = proj->yaw, roll = proj->roll; | |
2368 | int32_t *matrix; | ||
2369 | int hflip; | ||
2370 | |||
2371 |
5/6✓ Branch 0 taken 327 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 324 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 322 times.
✓ Branch 5 taken 2 times.
|
327 | if (pitch == 0.0 && yaw == 0.0 && roll == 0.0) |
2372 | 322 | return 0; | |
2373 | |||
2374 | /* Note: The following constants are exactly representable | ||
2375 | * as floating-point numbers. */ | ||
2376 |
6/10✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 3 times.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
✓ Branch 9 taken 5 times.
|
5 | 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 | 5 | sd = av_packet_side_data_new(&st->codecpar->coded_side_data, | |
2384 | 5 | &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 5 times.
|
5 | if (!sd) |
2388 | ✗ | return AVERROR(ENOMEM); | |
2389 | 5 | matrix = (int32_t*)sd->data; | |
2390 | |||
2391 | 5 | 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 | 5 | av_display_rotation_set(matrix, roll * (2 * hflip - 1)); | |
2399 | 5 | av_display_matrix_flip(matrix, hflip, 0); | |
2400 | |||
2401 | 5 | return 0; | |
2402 | } | ||
2403 | |||
2404 | 333 | static int mkv_parse_video_projection(AVStream *st, const MatroskaTrack *track, | |
2405 | void *logctx) | ||
2406 | { | ||
2407 | AVSphericalMapping *spherical; | ||
2408 | 333 | const MatroskaTrackVideoProjection *mkv_projection = &track->video.projection; | |
2409 | 333 | const uint8_t *priv_data = mkv_projection->private.data; | |
2410 | enum AVSphericalProjection projection; | ||
2411 | size_t spherical_size; | ||
2412 | 333 | uint32_t l = 0, t = 0, r = 0, b = 0; | |
2413 | 333 | uint32_t padding = 0; | |
2414 | |||
2415 |
3/4✓ Branch 0 taken 6 times.
✓ Branch 1 taken 327 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 6 times.
|
333 | 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 327 times.
✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
333 | switch (track->video.projection.type) { |
2421 | 327 | case MATROSKA_VIDEO_PROJECTION_TYPE_RECTANGULAR: | |
2422 | 327 | 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 | 441 | static int mkv_parse_block_addition_mappings(AVFormatContext *s, AVStream *st, MatroskaTrack *track) | |
2505 | { | ||
2506 | 441 | const EbmlList *mappings_list = &track->block_addition_mappings; | |
2507 | 441 | MatroskaBlockAdditionMapping *mappings = mappings_list->elem; | |
2508 | int ret; | ||
2509 | |||
2510 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 441 times.
|
447 | 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 | 441 | 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 | 75 | par->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; | |
2846 | 75 | par->ch_layout.nb_channels = track->audio.channels; | |
2847 | } | ||
2848 |
2/2✓ Branch 0 taken 83 times.
✓ Branch 1 taken 1 times.
|
84 | if (!par->bits_per_coded_sample) |
2849 | 83 | par->bits_per_coded_sample = track->audio.bitdepth; | |
2850 |
2/2✓ Branch 0 taken 83 times.
✓ Branch 1 taken 1 times.
|
84 | if (par->codec_id == AV_CODEC_ID_MP3 || |
2851 |
1/2✓ Branch 0 taken 83 times.
✗ Branch 1 not taken.
|
83 | par->codec_id == AV_CODEC_ID_MLP || |
2852 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 83 times.
|
83 | par->codec_id == AV_CODEC_ID_TRUEHD) |
2853 | 1 | sti->need_parsing = AVSTREAM_PARSE_FULL; | |
2854 |
2/2✓ Branch 0 taken 71 times.
✓ Branch 1 taken 12 times.
|
83 | else if (par->codec_id != AV_CODEC_ID_AAC) |
2855 | 71 | sti->need_parsing = AVSTREAM_PARSE_HEADERS; | |
2856 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 73 times.
|
84 | if (track->codec_delay > 0) { |
2857 | 11 | par->initial_padding = av_rescale_q(track->codec_delay, | |
2858 | 11 | (AVRational){1, 1000000000}, | |
2859 | 11 | (AVRational){1, par->codec_id == AV_CODEC_ID_OPUS ? | |
2860 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 6 times.
|
11 | 48000 : par->sample_rate}); |
2861 | } | ||
2862 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 77 times.
|
84 | if (track->seek_preroll > 0) { |
2863 | 7 | par->seek_preroll = av_rescale_q(track->seek_preroll, | |
2864 | 7 | (AVRational){1, 1000000000}, | |
2865 | 7 | (AVRational){1, par->sample_rate}); | |
2866 | } | ||
2867 | |||
2868 | 84 | return 0; | |
2869 | } | ||
2870 | |||
2871 | /* Performs the codec-specific part of parsing a video track. */ | ||
2872 | 333 | static int mkv_parse_video_codec(MatroskaTrack *track, AVCodecParameters *par, | |
2873 | const MatroskaDemuxContext *matroska, | ||
2874 | int *extradata_offset) | ||
2875 | { | ||
2876 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 328 times.
|
333 | if (!strcmp(track->codec_id, "V_MS/VFW/FOURCC") && |
2877 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | track->codec_priv.size >= 40) { |
2878 | 5 | track->ms_compat = 1; | |
2879 | 5 | par->bits_per_coded_sample = AV_RL16(track->codec_priv.data + 14); | |
2880 | 5 | par->codec_tag = AV_RL32(track->codec_priv.data + 16); | |
2881 | 5 | par->codec_id = ff_codec_get_id(ff_codec_bmp_tags, | |
2882 | par->codec_tag); | ||
2883 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (!par->codec_id) |
2884 | ✗ | par->codec_id = ff_codec_get_id(ff_codec_movvideo_tags, | |
2885 | par->codec_tag); | ||
2886 | 5 | *extradata_offset = 40; | |
2887 | 5 | return 0; | |
2888 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 327 times.
|
328 | } else if (!strcmp(track->codec_id, "V_QUICKTIME") && |
2889 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | track->codec_priv.size >= 21) { |
2890 | enum AVCodecID codec_id; | ||
2891 | uint32_t fourcc; | ||
2892 | 1 | int ret = get_qt_codec(track, &fourcc, &codec_id); | |
2893 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (ret < 0) |
2894 | ✗ | return ret; | |
2895 |
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 ")) { |
2896 | ✗ | fourcc = MKTAG('S','V','Q','3'); | |
2897 | ✗ | codec_id = ff_codec_get_id(ff_codec_movvideo_tags, fourcc); | |
2898 | } | ||
2899 | 1 | par->codec_id = codec_id; | |
2900 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (codec_id == AV_CODEC_ID_NONE) |
2901 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
2902 | ✗ | "mov FourCC not found %s.\n", av_fourcc2str(fourcc)); | |
2903 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (track->codec_priv.size >= 86) { |
2904 | FFIOContext b; | ||
2905 | 1 | unsigned bit_depth = AV_RB16(track->codec_priv.data + 82); | |
2906 | 1 | ffio_init_read_context(&b, track->codec_priv.data, | |
2907 | track->codec_priv.size); | ||
2908 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
|
1 | if (ff_get_qtpalette(codec_id, &b.pub, track->palette)) { |
2909 | ✗ | bit_depth &= 0x1F; | |
2910 | ✗ | track->has_palette = 1; | |
2911 | } | ||
2912 | 1 | par->bits_per_coded_sample = bit_depth; | |
2913 | } | ||
2914 | 1 | par->codec_tag = fourcc; | |
2915 | 1 | return 0; | |
2916 | } | ||
2917 | |||
2918 |
3/4✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 249 times.
✓ Branch 3 taken 73 times.
|
327 | switch (par->codec_id) { |
2919 | ✗ | case AV_CODEC_ID_RV10: | |
2920 | case AV_CODEC_ID_RV20: | ||
2921 | case AV_CODEC_ID_RV30: | ||
2922 | case AV_CODEC_ID_RV40: | ||
2923 | ✗ | *extradata_offset = 26; | |
2924 | ✗ | break; | |
2925 | 5 | case AV_CODEC_ID_PRORES: | |
2926 |
1/2✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
|
5 | if (track->codec_priv.size == 4) |
2927 | 5 | par->codec_tag = AV_RL32(track->codec_priv.data); | |
2928 | 5 | break; | |
2929 | 249 | case AV_CODEC_ID_VP9: | |
2930 | /* we don't need any value stored in CodecPrivate. | ||
2931 | * make sure that it's not exported as extradata. */ | ||
2932 | 249 | track->codec_priv.size = 0; | |
2933 | 249 | break; | |
2934 | } | ||
2935 | |||
2936 | 327 | return 0; | |
2937 | } | ||
2938 | |||
2939 | /* Performs the generic part of parsing a video track. */ | ||
2940 | 333 | static int mkv_parse_video(MatroskaTrack *track, AVStream *st, | |
2941 | AVCodecParameters *par, | ||
2942 | const MatroskaDemuxContext *matroska, | ||
2943 | int *extradata_offset) | ||
2944 | { | ||
2945 | 333 | FFStream *const sti = ffstream(st); | |
2946 | MatroskaTrackPlane *planes; | ||
2947 | 333 | int display_width_mul = 1; | |
2948 | 333 | int display_height_mul = 1; | |
2949 | int ret; | ||
2950 | |||
2951 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 329 times.
|
333 | if (track->video.color_space.size == 4) |
2952 | 4 | par->codec_tag = AV_RL32(track->video.color_space.data); | |
2953 | |||
2954 | 333 | ret = mkv_parse_video_codec(track, par, matroska, | |
2955 | extradata_offset); | ||
2956 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
|
333 | if (ret < 0) |
2957 | ✗ | return ret; | |
2958 | |||
2959 | 333 | par->codec_type = AVMEDIA_TYPE_VIDEO; | |
2960 | 333 | par->width = track->video.pixel_width; | |
2961 | 333 | par->height = track->video.pixel_height; | |
2962 | |||
2963 |
2/2✓ Branch 0 taken 7 times.
✓ Branch 1 taken 326 times.
|
333 | if (track->video.interlaced == MATROSKA_VIDEO_INTERLACE_FLAG_INTERLACED) |
2964 | 7 | par->field_order = mkv_field_order(matroska, track->video.field_order); | |
2965 |
2/2✓ Branch 0 taken 19 times.
✓ Branch 1 taken 307 times.
|
326 | else if (track->video.interlaced == MATROSKA_VIDEO_INTERLACE_FLAG_PROGRESSIVE) |
2966 | 19 | par->field_order = AV_FIELD_PROGRESSIVE; | |
2967 | |||
2968 |
4/4✓ Branch 0 taken 105 times.
✓ Branch 1 taken 228 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 93 times.
|
333 | if (track->video.stereo_mode && track->video.stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB) |
2969 | 12 | mkv_stereo_mode_display_mul(track->video.stereo_mode, | |
2970 | &display_width_mul, &display_height_mul); | ||
2971 | |||
2972 |
2/2✓ Branch 0 taken 311 times.
✓ Branch 1 taken 22 times.
|
333 | if (track->video.display_unit < MATROSKA_VIDEO_DISPLAYUNIT_UNKNOWN) { |
2973 |
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 && |
2974 |
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 && |
2975 |
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 && |
2976 |
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) |
2977 | 311 | av_reduce(&st->sample_aspect_ratio.num, | |
2978 | &st->sample_aspect_ratio.den, | ||
2979 | 311 | track->video.cropped_height * track->video.display_width * display_width_mul, | |
2980 | 311 | track->video.cropped_width * track->video.display_height * display_height_mul, | |
2981 | INT_MAX); | ||
2982 | } | ||
2983 |
1/2✓ Branch 0 taken 333 times.
✗ Branch 1 not taken.
|
333 | if (track->video.cropped_width != track->video.pixel_width || |
2984 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
|
333 | track->video.cropped_height != track->video.pixel_height) { |
2985 | uint8_t *cropping; | ||
2986 | ✗ | AVPacketSideData *sd = av_packet_side_data_new(&st->codecpar->coded_side_data, | |
2987 | ✗ | &st->codecpar->nb_coded_side_data, | |
2988 | AV_PKT_DATA_FRAME_CROPPING, | ||
2989 | sizeof(uint32_t) * 4, 0); | ||
2990 | ✗ | if (!sd) | |
2991 | ✗ | return AVERROR(ENOMEM); | |
2992 | |||
2993 | ✗ | cropping = sd->data; | |
2994 | ✗ | bytestream_put_le32(&cropping, track->video.pixel_cropt); | |
2995 | ✗ | bytestream_put_le32(&cropping, track->video.pixel_cropb); | |
2996 | ✗ | bytestream_put_le32(&cropping, track->video.pixel_cropl); | |
2997 | ✗ | bytestream_put_le32(&cropping, track->video.pixel_cropr); | |
2998 | } | ||
2999 |
2/2✓ Branch 0 taken 324 times.
✓ Branch 1 taken 9 times.
|
333 | if (par->codec_id != AV_CODEC_ID_HEVC) |
3000 | 324 | sti->need_parsing = AVSTREAM_PARSE_HEADERS; | |
3001 | |||
3002 |
2/2✓ Branch 0 taken 291 times.
✓ Branch 1 taken 42 times.
|
333 | if (track->default_duration) { |
3003 |
1/2✓ Branch 0 taken 291 times.
✗ Branch 1 not taken.
|
291 | int div = track->default_duration <= INT64_MAX ? 1 : 2; |
3004 | 291 | av_reduce(&st->avg_frame_rate.num, &st->avg_frame_rate.den, | |
3005 | 291 | 1000000000 / div, track->default_duration / div, 30000); | |
3006 | #if FF_API_R_FRAME_RATE | ||
3007 |
2/2✓ Branch 0 taken 289 times.
✓ Branch 1 taken 2 times.
|
291 | if ( st->avg_frame_rate.num < st->avg_frame_rate.den * 1000LL |
3008 |
2/2✓ Branch 0 taken 274 times.
✓ Branch 1 taken 15 times.
|
289 | && st->avg_frame_rate.num > st->avg_frame_rate.den * 5LL) |
3009 | 274 | st->r_frame_rate = st->avg_frame_rate; | |
3010 | #endif | ||
3011 | } | ||
3012 | |||
3013 | /* export stereo mode flag as metadata tag */ | ||
3014 |
4/4✓ Branch 0 taken 105 times.
✓ Branch 1 taken 228 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 93 times.
|
333 | if (track->video.stereo_mode && track->video.stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB) |
3015 | 12 | av_dict_set(&st->metadata, "stereo_mode", ff_matroska_video_stereo_mode[track->video.stereo_mode], 0); | |
3016 | |||
3017 | /* export alpha mode flag as metadata tag */ | ||
3018 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 330 times.
|
333 | if (track->video.alpha_mode) |
3019 | 3 | av_dict_set_int(&st->metadata, "alpha_mode", 1, 0); | |
3020 | |||
3021 | /* if we have virtual track, mark the real tracks */ | ||
3022 | 333 | planes = track->operation.combine_planes.elem; | |
3023 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
|
333 | for (int j = 0; j < track->operation.combine_planes.nb_elem; j++) { |
3024 | ✗ | MatroskaTrack *tracks = matroska->tracks.elem; | |
3025 | char buf[32]; | ||
3026 | ✗ | if (planes[j].type >= MATROSKA_VIDEO_STEREO_PLANE_COUNT) | |
3027 | ✗ | continue; | |
3028 | ✗ | snprintf(buf, sizeof(buf), "%s_%d", | |
3029 | ✗ | matroska_video_stereo_plane[planes[j].type], st->index); | |
3030 | ✗ | for (int k = 0; k < matroska->tracks.nb_elem; k++) | |
3031 | ✗ | if (planes[j].uid == tracks[k].uid && tracks[k].stream) { | |
3032 | ✗ | av_dict_set(&tracks[k].stream->metadata, | |
3033 | "stereo_mode", buf, 0); | ||
3034 | ✗ | break; | |
3035 | } | ||
3036 | } | ||
3037 | // add stream level stereo3d side data if it is a supported format | ||
3038 |
2/2✓ Branch 0 taken 240 times.
✓ Branch 1 taken 93 times.
|
333 | if (track->video.stereo_mode < MATROSKA_VIDEO_STEREOMODE_TYPE_NB && |
3039 |
2/2✓ Branch 0 taken 238 times.
✓ Branch 1 taken 2 times.
|
240 | track->video.stereo_mode != MATROSKA_VIDEO_STEREOMODE_TYPE_ANAGLYPH_CYAN_RED && |
3040 |
2/2✓ Branch 0 taken 236 times.
✓ Branch 1 taken 2 times.
|
238 | track->video.stereo_mode != MATROSKA_VIDEO_STEREOMODE_TYPE_ANAGLYPH_GREEN_MAG) { |
3041 | 236 | int ret = mkv_stereo3d_conv(st, track->video.stereo_mode); | |
3042 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 236 times.
|
236 | if (ret < 0) |
3043 | ✗ | return ret; | |
3044 | } | ||
3045 | |||
3046 | 333 | ret = mkv_parse_video_color(st, track); | |
3047 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
|
333 | if (ret < 0) |
3048 | ✗ | return ret; | |
3049 | 333 | ret = mkv_parse_video_projection(st, track, matroska->ctx); | |
3050 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
|
333 | if (ret < 0) |
3051 | ✗ | return ret; | |
3052 | |||
3053 | 333 | return 0; | |
3054 | } | ||
3055 | |||
3056 | /* Performs the codec-specific part of parsing a subtitle track. */ | ||
3057 | 24 | static int mkv_parse_subtitle_codec(MatroskaTrack *track, AVStream *st, | |
3058 | AVCodecParameters *par, | ||
3059 | const MatroskaDemuxContext *matroska) | ||
3060 | { | ||
3061 |
2/3✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 16 times.
|
24 | switch (par->codec_id) { |
3062 | ✗ | case AV_CODEC_ID_ARIB_CAPTION: | |
3063 | ✗ | if (track->codec_priv.size == 3) { | |
3064 | ✗ | int component_tag = track->codec_priv.data[0]; | |
3065 | ✗ | int data_component_id = AV_RB16(track->codec_priv.data + 1); | |
3066 | |||
3067 | ✗ | switch (data_component_id) { | |
3068 | ✗ | case 0x0008: | |
3069 | // [0x30..0x37] are component tags utilized for | ||
3070 | // non-mobile captioning service ("profile A"). | ||
3071 | ✗ | if (component_tag >= 0x30 && component_tag <= 0x37) { | |
3072 | ✗ | par->profile = AV_PROFILE_ARIB_PROFILE_A; | |
3073 | } | ||
3074 | ✗ | break; | |
3075 | ✗ | case 0x0012: | |
3076 | // component tag 0x87 signifies a mobile/partial reception | ||
3077 | // (1seg) captioning service ("profile C"). | ||
3078 | ✗ | if (component_tag == 0x87) { | |
3079 | ✗ | par->profile = AV_PROFILE_ARIB_PROFILE_C; | |
3080 | } | ||
3081 | ✗ | break; | |
3082 | ✗ | default: | |
3083 | ✗ | break; | |
3084 | } | ||
3085 | |||
3086 | ✗ | if (par->profile == AV_PROFILE_UNKNOWN) | |
3087 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, | |
3088 | "Unknown ARIB caption profile utilized: %02x / %04x\n", | ||
3089 | component_tag, data_component_id); | ||
3090 | |||
3091 | ✗ | track->codec_priv.size = 0; | |
3092 | } | ||
3093 | ✗ | break; | |
3094 | 8 | case AV_CODEC_ID_WEBVTT: | |
3095 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 6 times.
|
8 | if (!strcmp(track->codec_id, "D_WEBVTT/CAPTIONS")) { |
3096 | 2 | st->disposition |= AV_DISPOSITION_CAPTIONS; | |
3097 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 4 times.
|
6 | } else if (!strcmp(track->codec_id, "D_WEBVTT/DESCRIPTIONS")) { |
3098 | 2 | st->disposition |= AV_DISPOSITION_DESCRIPTIONS; | |
3099 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | } else if (!strcmp(track->codec_id, "D_WEBVTT/METADATA")) { |
3100 | 2 | st->disposition |= AV_DISPOSITION_METADATA; | |
3101 | } | ||
3102 | 8 | break; | |
3103 | } | ||
3104 | |||
3105 | 24 | return 0; | |
3106 | } | ||
3107 | |||
3108 | 370 | static int matroska_parse_tracks(AVFormatContext *s) | |
3109 | { | ||
3110 | 370 | MatroskaDemuxContext *matroska = s->priv_data; | |
3111 | 370 | MatroskaTrack *tracks = matroska->tracks.elem; | |
3112 | int i, j, ret; | ||
3113 | |||
3114 |
2/2✓ Branch 0 taken 441 times.
✓ Branch 1 taken 370 times.
|
811 | for (i = 0; i < matroska->tracks.nb_elem; i++) { |
3115 | 441 | MatroskaTrack *track = &tracks[i]; | |
3116 | 441 | enum AVCodecID codec_id = AV_CODEC_ID_NONE; | |
3117 | AVCodecParameters *par; | ||
3118 | MatroskaTrackType type; | ||
3119 | 441 | int extradata_offset = 0; | |
3120 | AVStream *st; | ||
3121 | 441 | char* key_id_base64 = NULL; | |
3122 | |||
3123 | /* Apply some sanity checks. */ | ||
3124 |
2/2✓ Branch 0 taken 108 times.
✓ Branch 1 taken 333 times.
|
441 | if (track->type != MATROSKA_TRACK_TYPE_VIDEO && |
3125 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 84 times.
|
108 | track->type != MATROSKA_TRACK_TYPE_AUDIO && |
3126 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 20 times.
|
24 | track->type != MATROSKA_TRACK_TYPE_SUBTITLE && |
3127 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | track->type != MATROSKA_TRACK_TYPE_METADATA) { |
3128 | ✗ | av_log(matroska->ctx, AV_LOG_INFO, | |
3129 | "Unknown or unsupported track type %"PRIu64"\n", | ||
3130 | track->type); | ||
3131 | ✗ | continue; | |
3132 | } | ||
3133 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 441 times.
|
441 | if (!track->codec_id) |
3134 | ✗ | continue; | |
3135 | |||
3136 |
3/4✓ Branch 0 taken 84 times.
✓ Branch 1 taken 357 times.
✓ Branch 2 taken 84 times.
✗ Branch 3 not taken.
|
441 | if ( track->type == MATROSKA_TRACK_TYPE_AUDIO && track->codec_id[0] != 'A' |
3137 |
3/4✓ Branch 0 taken 333 times.
✓ Branch 1 taken 108 times.
✓ Branch 2 taken 333 times.
✗ Branch 3 not taken.
|
441 | || track->type == MATROSKA_TRACK_TYPE_VIDEO && track->codec_id[0] != 'V' |
3138 |
5/6✓ Branch 0 taken 20 times.
✓ Branch 1 taken 421 times.
✓ Branch 2 taken 16 times.
✓ Branch 3 taken 4 times.
✓ Branch 4 taken 16 times.
✗ Branch 5 not taken.
|
441 | || track->type == MATROSKA_TRACK_TYPE_SUBTITLE && track->codec_id[0] != 'D' && track->codec_id[0] != 'S' |
3139 |
3/6✓ Branch 0 taken 4 times.
✓ Branch 1 taken 437 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 4 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
441 | || track->type == MATROSKA_TRACK_TYPE_METADATA && track->codec_id[0] != 'D' && track->codec_id[0] != 'S' |
3140 | ) { | ||
3141 | ✗ | av_log(matroska->ctx, AV_LOG_INFO, "Inconsistent track type\n"); | |
3142 | ✗ | continue; | |
3143 | } | ||
3144 | |||
3145 |
2/4✓ Branch 0 taken 441 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 441 times.
✗ Branch 3 not taken.
|
441 | if (track->audio.samplerate < 0 || track->audio.samplerate > INT_MAX || |
3146 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 441 times.
|
441 | isnan(track->audio.samplerate)) { |
3147 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, | |
3148 | "Invalid sample rate %f, defaulting to 8000 instead.\n", | ||
3149 | track->audio.samplerate); | ||
3150 | ✗ | track->audio.samplerate = 8000; | |
3151 | } | ||
3152 | |||
3153 |
2/2✓ Branch 0 taken 333 times.
✓ Branch 1 taken 108 times.
|
441 | if (track->type == MATROSKA_TRACK_TYPE_VIDEO) { |
3154 |
4/4✓ Branch 0 taken 246 times.
✓ Branch 1 taken 87 times.
✓ Branch 2 taken 204 times.
✓ Branch 3 taken 42 times.
|
333 | if (!track->default_duration && track->video.frame_rate > 0) { |
3155 | 204 | double default_duration = 1000000000 / track->video.frame_rate; | |
3156 |
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) { |
3157 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, | |
3158 | "Invalid frame rate %e. Cannot calculate default duration.\n", | ||
3159 | track->video.frame_rate); | ||
3160 | } else { | ||
3161 | 204 | track->default_duration = default_duration; | |
3162 | } | ||
3163 | } | ||
3164 |
1/2✓ Branch 0 taken 333 times.
✗ Branch 1 not taken.
|
333 | if (track->video.pixel_cropl >= INT_MAX - track->video.pixel_cropr || |
3165 |
1/2✓ Branch 0 taken 333 times.
✗ Branch 1 not taken.
|
333 | track->video.pixel_cropt >= INT_MAX - track->video.pixel_cropb || |
3166 |
1/2✓ Branch 0 taken 333 times.
✗ Branch 1 not taken.
|
333 | (track->video.pixel_cropl + track->video.pixel_cropr) >= track->video.pixel_width || |
3167 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
|
333 | (track->video.pixel_cropt + track->video.pixel_cropb) >= track->video.pixel_height) |
3168 | ✗ | return AVERROR_INVALIDDATA; | |
3169 | 333 | track->video.cropped_width = track->video.pixel_width - | |
3170 | 333 | track->video.pixel_cropl - track->video.pixel_cropr; | |
3171 | 333 | track->video.cropped_height = track->video.pixel_height - | |
3172 | 333 | track->video.pixel_cropt - track->video.pixel_cropb; | |
3173 |
2/2✓ Branch 0 taken 296 times.
✓ Branch 1 taken 37 times.
|
333 | if (track->video.display_unit == MATROSKA_VIDEO_DISPLAYUNIT_PIXELS) { |
3174 |
2/2✓ Branch 0 taken 263 times.
✓ Branch 1 taken 33 times.
|
296 | if (track->video.display_width == -1) |
3175 | 263 | track->video.display_width = track->video.cropped_width; | |
3176 |
2/2✓ Branch 0 taken 263 times.
✓ Branch 1 taken 33 times.
|
296 | if (track->video.display_height == -1) |
3177 | 263 | track->video.display_height = track->video.cropped_height; | |
3178 | } | ||
3179 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 24 times.
|
108 | } else if (track->type == MATROSKA_TRACK_TYPE_AUDIO) { |
3180 |
2/2✓ Branch 0 taken 83 times.
✓ Branch 1 taken 1 times.
|
84 | if (!track->audio.out_samplerate) |
3181 | 83 | track->audio.out_samplerate = track->audio.samplerate; | |
3182 | } | ||
3183 | 441 | ret = matroska_parse_content_encodings(track->encodings.elem, | |
3184 | 441 | track->encodings.nb_elem, | |
3185 | 441 | track, &key_id_base64, matroska->ctx); | |
3186 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 441 times.
|
441 | if (ret < 0) |
3187 | ✗ | return ret; | |
3188 | |||
3189 |
2/2✓ Branch 0 taken 26107 times.
✓ Branch 1 taken 7 times.
|
26114 | for (j = 0; ff_mkv_codec_tags[j].id != AV_CODEC_ID_NONE; j++) { |
3190 |
2/2✓ Branch 1 taken 434 times.
✓ Branch 2 taken 25673 times.
|
26107 | if (av_strstart(track->codec_id, ff_mkv_codec_tags[j].str, NULL)) { |
3191 | 434 | codec_id = ff_mkv_codec_tags[j].id; | |
3192 | 434 | break; | |
3193 | } | ||
3194 | } | ||
3195 | |||
3196 | 441 | st = track->stream = avformat_new_stream(s, NULL); | |
3197 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 441 times.
|
441 | if (!st) { |
3198 | ✗ | av_free(key_id_base64); | |
3199 | ✗ | return AVERROR(ENOMEM); | |
3200 | } | ||
3201 | 441 | par = st->codecpar; | |
3202 | |||
3203 | 441 | par->codec_id = codec_id; | |
3204 | |||
3205 |
2/2✓ Branch 0 taken 353 times.
✓ Branch 1 taken 88 times.
|
441 | if (track->flag_default) |
3206 | 353 | st->disposition |= AV_DISPOSITION_DEFAULT; | |
3207 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 437 times.
|
441 | if (track->flag_forced) |
3208 | 4 | st->disposition |= AV_DISPOSITION_FORCED; | |
3209 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 439 times.
|
441 | if (track->flag_comment) |
3210 | 2 | st->disposition |= AV_DISPOSITION_COMMENT; | |
3211 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 433 times.
|
441 | if (track->flag_hearingimpaired) |
3212 | 8 | st->disposition |= AV_DISPOSITION_HEARING_IMPAIRED; | |
3213 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 439 times.
|
441 | if (track->flag_visualimpaired) |
3214 | 2 | st->disposition |= AV_DISPOSITION_VISUAL_IMPAIRED; | |
3215 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 437 times.
|
441 | if (track->flag_original.count > 0) |
3216 | 4 | st->disposition |= track->flag_original.el.u ? AV_DISPOSITION_ORIGINAL | |
3217 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 2 times.
|
4 | : AV_DISPOSITION_DUB; |
3218 | |||
3219 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 441 times.
|
441 | if (key_id_base64) { |
3220 | /* export encryption key id as base64 metadata tag */ | ||
3221 | ✗ | av_dict_set(&st->metadata, "enc_key_id", key_id_base64, | |
3222 | AV_DICT_DONT_STRDUP_VAL); | ||
3223 | } | ||
3224 | |||
3225 |
2/2✓ Branch 0 taken 323 times.
✓ Branch 1 taken 118 times.
|
441 | if (strcmp(track->language, "und")) |
3226 | 323 | av_dict_set(&st->metadata, "language", track->language, 0); | |
3227 | 441 | av_dict_set(&st->metadata, "title", track->name, 0); | |
3228 | |||
3229 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 441 times.
|
441 | if (track->time_scale < 0.01) { |
3230 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, | |
3231 | "Track TimestampScale too small %f, assuming 1.0.\n", | ||
3232 | track->time_scale); | ||
3233 | ✗ | track->time_scale = 1.0; | |
3234 | } | ||
3235 | |||
3236 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 441 times.
|
441 | if (matroska->time_scale * track->time_scale > UINT_MAX) |
3237 | ✗ | return AVERROR_INVALIDDATA; | |
3238 | |||
3239 | 441 | avpriv_set_pts_info(st, 64, matroska->time_scale * track->time_scale, | |
3240 | 1000 * 1000 * 1000); /* 64 bit pts in ns */ | ||
3241 | |||
3242 | /* convert the delay from ns to the track timebase */ | ||
3243 | 441 | track->codec_delay_in_track_tb = av_rescale_q(track->codec_delay, | |
3244 | 441 | (AVRational){ 1, 1000000000 }, | |
3245 | st->time_base); | ||
3246 | |||
3247 | 441 | type = track->type; | |
3248 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 433 times.
|
441 | if (par->codec_id == AV_CODEC_ID_WEBVTT) |
3249 | 8 | type = MATROSKA_TRACK_TYPE_SUBTITLE; | |
3250 |
3/4✓ Branch 0 taken 84 times.
✓ Branch 1 taken 333 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
|
441 | switch (type) { |
3251 | 84 | case MATROSKA_TRACK_TYPE_AUDIO: | |
3252 | 84 | ret = mka_parse_audio(track, st, par, matroska, | |
3253 | s, &extradata_offset); | ||
3254 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
|
84 | if (ret < 0) |
3255 | ✗ | return ret; | |
3256 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 84 times.
|
84 | if (ret == SKIP_TRACK) |
3257 | ✗ | continue; | |
3258 | 84 | break; | |
3259 | 333 | case MATROSKA_TRACK_TYPE_VIDEO: | |
3260 | 333 | ret = mkv_parse_video(track, st, par, matroska, &extradata_offset); | |
3261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 333 times.
|
333 | if (ret < 0) |
3262 | ✗ | return ret; | |
3263 | 333 | break; | |
3264 | 24 | case MATROSKA_TRACK_TYPE_SUBTITLE: | |
3265 | 24 | ret = mkv_parse_subtitle_codec(track, st, par, matroska); | |
3266 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | if (ret < 0) |
3267 | ✗ | return ret; | |
3268 | 24 | par->codec_type = AVMEDIA_TYPE_SUBTITLE; | |
3269 | |||
3270 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | if (track->flag_textdescriptions) |
3271 | ✗ | st->disposition |= AV_DISPOSITION_DESCRIPTIONS; | |
3272 | 24 | break; | |
3273 | } | ||
3274 | |||
3275 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 441 times.
|
441 | if (par->codec_id == AV_CODEC_ID_NONE) |
3276 | ✗ | av_log(matroska->ctx, AV_LOG_INFO, | |
3277 | "Unknown/unsupported AVCodecID %s.\n", track->codec_id); | ||
3278 | |||
3279 |
4/4✓ Branch 0 taken 434 times.
✓ Branch 1 taken 7 times.
✓ Branch 2 taken 132 times.
✓ Branch 3 taken 302 times.
|
441 | if (!par->extradata && track->codec_priv.size > extradata_offset) { |
3280 | 132 | const uint8_t *src = track->codec_priv.data + extradata_offset; | |
3281 | 132 | unsigned extra_size = track->codec_priv.size - extradata_offset; | |
3282 | 132 | ret = ff_alloc_extradata(par, extra_size); | |
3283 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 132 times.
|
132 | if (ret < 0) |
3284 | ✗ | return ret; | |
3285 | 132 | memcpy(par->extradata, src, extra_size); | |
3286 | } | ||
3287 | |||
3288 | 441 | ret = mkv_parse_block_addition_mappings(s, st, track); | |
3289 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 441 times.
|
441 | if (ret < 0) |
3290 | ✗ | return ret; | |
3291 | } | ||
3292 | |||
3293 | 370 | return 0; | |
3294 | } | ||
3295 | |||
3296 | 370 | static int matroska_read_header(AVFormatContext *s) | |
3297 | { | ||
3298 | 370 | FFFormatContext *const si = ffformatcontext(s); | |
3299 | 370 | MatroskaDemuxContext *matroska = s->priv_data; | |
3300 | 370 | EbmlList *attachments_list = &matroska->attachments; | |
3301 | 370 | EbmlList *chapters_list = &matroska->chapters; | |
3302 | MatroskaAttachment *attachments; | ||
3303 | MatroskaChapter *chapters; | ||
3304 | 370 | uint64_t max_start = 0; | |
3305 | int64_t pos; | ||
3306 | 370 | Ebml ebml = { 0 }; | |
3307 | int i, j, res; | ||
3308 | |||
3309 | 370 | matroska->ctx = s; | |
3310 | 370 | matroska->cues_parsing_deferred = 1; | |
3311 | |||
3312 | /* First read the EBML header. */ | ||
3313 |
2/4✓ Branch 1 taken 370 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 370 times.
|
370 | if (ebml_parse(matroska, ebml_syntax, &ebml) || !ebml.doctype) { |
3314 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "EBML header parsing failed\n"); | |
3315 | ✗ | ebml_free(ebml_syntax, &ebml); | |
3316 | ✗ | return AVERROR_INVALIDDATA; | |
3317 | } | ||
3318 |
1/2✓ Branch 0 taken 370 times.
✗ Branch 1 not taken.
|
370 | if (ebml.version > EBML_VERSION || |
3319 |
1/2✓ Branch 0 taken 370 times.
✗ Branch 1 not taken.
|
370 | ebml.max_size > sizeof(uint64_t) || |
3320 |
1/2✓ Branch 0 taken 370 times.
✗ Branch 1 not taken.
|
370 | ebml.id_length > sizeof(uint32_t) || |
3321 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 370 times.
|
370 | ebml.doctype_version > 3) { |
3322 | ✗ | avpriv_report_missing_feature(matroska->ctx, | |
3323 | "EBML version %"PRIu64", doctype %s, doc version %"PRIu64, | ||
3324 | ebml.version, ebml.doctype, ebml.doctype_version); | ||
3325 | ✗ | ebml_free(ebml_syntax, &ebml); | |
3326 | ✗ | return AVERROR_PATCHWELCOME; | |
3327 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 370 times.
|
370 | } else if (ebml.doctype_version == 3) { |
3328 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, | |
3329 | "EBML header using unsupported features\n" | ||
3330 | "(EBML version %"PRIu64", doctype %s, doc version %"PRIu64")\n", | ||
3331 | ebml.version, ebml.doctype, ebml.doctype_version); | ||
3332 | } | ||
3333 |
1/2✓ Branch 0 taken 638 times.
✗ Branch 1 not taken.
|
638 | for (i = 0; i < FF_ARRAY_ELEMS(matroska_doctypes); i++) |
3334 |
2/2✓ Branch 0 taken 370 times.
✓ Branch 1 taken 268 times.
|
638 | if (!strcmp(ebml.doctype, matroska_doctypes[i])) |
3335 | 370 | break; | |
3336 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 370 times.
|
370 | if (i >= FF_ARRAY_ELEMS(matroska_doctypes)) { |
3337 | ✗ | av_log(s, AV_LOG_WARNING, "Unknown EBML doctype '%s'\n", ebml.doctype); | |
3338 | ✗ | if (matroska->ctx->error_recognition & AV_EF_EXPLODE) { | |
3339 | ✗ | ebml_free(ebml_syntax, &ebml); | |
3340 | ✗ | return AVERROR_INVALIDDATA; | |
3341 | } | ||
3342 | } | ||
3343 | 370 | matroska->is_webm = !strcmp(ebml.doctype, "webm"); | |
3344 | |||
3345 | 370 | ebml_free(ebml_syntax, &ebml); | |
3346 | |||
3347 | 370 | matroska->pkt = si->parse_pkt; | |
3348 | |||
3349 | /* The next thing is a segment. */ | ||
3350 | 370 | pos = avio_tell(matroska->ctx->pb); | |
3351 | 370 | res = ebml_parse(matroska, matroska_segments, matroska); | |
3352 | // Try resyncing until we find an EBML_STOP type element. | ||
3353 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 370 times.
|
370 | while (res != 1) { |
3354 | ✗ | res = matroska_resync(matroska, pos); | |
3355 | ✗ | if (res < 0) | |
3356 | ✗ | return res; | |
3357 | ✗ | pos = avio_tell(matroska->ctx->pb); | |
3358 | ✗ | res = ebml_parse(matroska, matroska_segment, matroska); | |
3359 | ✗ | if (res == AVERROR(EIO)) // EOF is translated to EIO, this exists the loop on EOF | |
3360 | ✗ | return res; | |
3361 | } | ||
3362 | /* Set data_offset as it might be needed later by seek_frame_generic. */ | ||
3363 |
2/2✓ Branch 0 taken 366 times.
✓ Branch 1 taken 4 times.
|
370 | if (matroska->current_id == MATROSKA_ID_CLUSTER) |
3364 | 366 | si->data_offset = avio_tell(matroska->ctx->pb) - 4; | |
3365 | 370 | matroska_execute_seekhead(matroska); | |
3366 | |||
3367 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 370 times.
|
370 | if (!matroska->time_scale) |
3368 | ✗ | matroska->time_scale = 1000000; | |
3369 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 370 times.
|
370 | if (isnan(matroska->duration)) |
3370 | ✗ | matroska->duration = 0; | |
3371 |
2/2✓ Branch 0 taken 359 times.
✓ Branch 1 taken 11 times.
|
370 | if (matroska->duration) |
3372 | 359 | matroska->ctx->duration = matroska->duration * matroska->time_scale * | |
3373 | 359 | 1000 / AV_TIME_BASE; | |
3374 | 370 | av_dict_set(&s->metadata, "title", matroska->title, 0); | |
3375 | 370 | av_dict_set(&s->metadata, "encoder", matroska->muxingapp, 0); | |
3376 | |||
3377 |
2/2✓ Branch 0 taken 18 times.
✓ Branch 1 taken 352 times.
|
370 | if (matroska->date_utc.size == 8) |
3378 | 18 | matroska_metadata_creation_time(&s->metadata, AV_RB64(matroska->date_utc.data)); | |
3379 | |||
3380 | 370 | res = matroska_parse_tracks(s); | |
3381 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 370 times.
|
370 | if (res < 0) |
3382 | ✗ | return res; | |
3383 | |||
3384 | 370 | attachments = attachments_list->elem; | |
3385 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 370 times.
|
374 | for (j = 0; j < attachments_list->nb_elem; j++) { |
3386 |
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 && |
3387 |
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)) { |
3388 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "incomplete attachment\n"); | |
3389 | } else { | ||
3390 | 4 | AVStream *st = avformat_new_stream(s, NULL); | |
3391 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (!st) |
3392 | ✗ | break; | |
3393 | 4 | av_dict_set(&st->metadata, "filename", attachments[j].filename, 0); | |
3394 | 4 | av_dict_set(&st->metadata, "mimetype", attachments[j].mime, 0); | |
3395 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (attachments[j].description) |
3396 | ✗ | av_dict_set(&st->metadata, "title", attachments[j].description, 0); | |
3397 | 4 | st->codecpar->codec_id = AV_CODEC_ID_NONE; | |
3398 | |||
3399 |
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++) { |
3400 |
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)) { |
3401 | ✗ | st->codecpar->codec_id = mkv_image_mime_tags[i].id; | |
3402 | ✗ | break; | |
3403 | } | ||
3404 | } | ||
3405 | |||
3406 | 4 | attachments[j].stream = st; | |
3407 | |||
3408 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (st->codecpar->codec_id != AV_CODEC_ID_NONE) { |
3409 | ✗ | res = ff_add_attached_pic(s, st, NULL, &attachments[j].bin.buf, 0); | |
3410 | ✗ | if (res < 0) | |
3411 | ✗ | return res; | |
3412 | } else { | ||
3413 | 4 | st->codecpar->codec_type = AVMEDIA_TYPE_ATTACHMENT; | |
3414 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4 times.
|
4 | if (ff_alloc_extradata(st->codecpar, attachments[j].bin.size)) |
3415 | ✗ | break; | |
3416 | 4 | memcpy(st->codecpar->extradata, attachments[j].bin.data, | |
3417 | 4 | attachments[j].bin.size); | |
3418 | |||
3419 |
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++) { |
3420 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 16 times.
|
16 | if (av_strstart(attachments[j].mime, mkv_mime_tags[i].str, NULL)) { |
3421 | ✗ | st->codecpar->codec_id = mkv_mime_tags[i].id; | |
3422 | ✗ | break; | |
3423 | } | ||
3424 | } | ||
3425 | } | ||
3426 | } | ||
3427 | } | ||
3428 | |||
3429 | 370 | chapters = chapters_list->elem; | |
3430 |
2/2✓ Branch 0 taken 14 times.
✓ Branch 1 taken 370 times.
|
384 | for (i = 0; i < chapters_list->nb_elem; i++) |
3431 |
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 && |
3432 |
1/2✓ Branch 0 taken 4 times.
✗ Branch 1 not taken.
|
4 | (max_start == 0 || chapters[i].start > max_start)) { |
3433 | 28 | chapters[i].chapter = | |
3434 | 14 | avpriv_new_chapter(s, chapters[i].uid, | |
3435 | 14 | (AVRational) { 1, 1000000000 }, | |
3436 | 14 | chapters[i].start, chapters[i].end, | |
3437 | 14 | chapters[i].title); | |
3438 | 14 | max_start = chapters[i].start; | |
3439 | } | ||
3440 | |||
3441 | 370 | matroska_add_index_entries(matroska); | |
3442 | |||
3443 | 370 | matroska_convert_tags(s); | |
3444 | |||
3445 | 370 | return 0; | |
3446 | } | ||
3447 | |||
3448 | /* | ||
3449 | * Put one packet in an application-supplied AVPacket struct. | ||
3450 | * Returns 0 on success or -1 on failure. | ||
3451 | */ | ||
3452 | 60208 | static int matroska_deliver_packet(MatroskaDemuxContext *matroska, | |
3453 | AVPacket *pkt) | ||
3454 | { | ||
3455 |
2/2✓ Branch 0 taken 29484 times.
✓ Branch 1 taken 30724 times.
|
60208 | if (matroska->queue.head) { |
3456 | 29484 | MatroskaTrack *tracks = matroska->tracks.elem; | |
3457 | MatroskaTrack *track; | ||
3458 | |||
3459 | 29484 | avpriv_packet_list_get(&matroska->queue, pkt); | |
3460 | 29484 | track = &tracks[pkt->stream_index]; | |
3461 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29484 times.
|
29484 | if (track->has_palette) { |
3462 | ✗ | uint8_t *pal = av_packet_new_side_data(pkt, AV_PKT_DATA_PALETTE, AVPALETTE_SIZE); | |
3463 | ✗ | if (!pal) { | |
3464 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "Cannot append palette to packet\n"); | |
3465 | } else { | ||
3466 | ✗ | memcpy(pal, track->palette, AVPALETTE_SIZE); | |
3467 | } | ||
3468 | ✗ | track->has_palette = 0; | |
3469 | } | ||
3470 | 29484 | return 0; | |
3471 | } | ||
3472 | |||
3473 | 30724 | return -1; | |
3474 | } | ||
3475 | |||
3476 | /* | ||
3477 | * Free all packets in our internal queue. | ||
3478 | */ | ||
3479 | 1208 | static void matroska_clear_queue(MatroskaDemuxContext *matroska) | |
3480 | { | ||
3481 | 1208 | avpriv_packet_list_free(&matroska->queue); | |
3482 | 1208 | } | |
3483 | |||
3484 | 29854 | static int matroska_parse_laces(MatroskaDemuxContext *matroska, uint8_t **buf, | |
3485 | int size, int type, AVIOContext *pb, | ||
3486 | uint32_t lace_size[256], int *laces) | ||
3487 | { | ||
3488 | int n; | ||
3489 | 29854 | uint8_t *data = *buf; | |
3490 | |||
3491 |
2/2✓ Branch 0 taken 29779 times.
✓ Branch 1 taken 75 times.
|
29854 | if (!type) { |
3492 | 29779 | *laces = 1; | |
3493 | 29779 | lace_size[0] = size; | |
3494 | 29779 | return 0; | |
3495 | } | ||
3496 | |||
3497 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 75 times.
|
75 | if (size <= 0) |
3498 | ✗ | return AVERROR_INVALIDDATA; | |
3499 | |||
3500 | 75 | *laces = *data + 1; | |
3501 | 75 | data += 1; | |
3502 | 75 | size -= 1; | |
3503 | |||
3504 |
3/4✓ Branch 0 taken 4 times.
✓ Branch 1 taken 17 times.
✓ Branch 2 taken 54 times.
✗ Branch 3 not taken.
|
75 | switch (type) { |
3505 | 4 | case 0x1: /* Xiph lacing */ | |
3506 | { | ||
3507 | uint8_t temp; | ||
3508 | 4 | uint32_t total = 0; | |
3509 |
2/2✓ Branch 0 taken 23 times.
✓ Branch 1 taken 4 times.
|
27 | for (n = 0; n < *laces - 1; n++) { |
3510 | 23 | lace_size[n] = 0; | |
3511 | |||
3512 | do { | ||
3513 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 25 times.
|
25 | if (size <= total) |
3514 | ✗ | return AVERROR_INVALIDDATA; | |
3515 | 25 | temp = *data; | |
3516 | 25 | total += temp; | |
3517 | 25 | lace_size[n] += temp; | |
3518 | 25 | data += 1; | |
3519 | 25 | size -= 1; | |
3520 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 23 times.
|
25 | } while (temp == 0xff); |
3521 | } | ||
3522 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4 times.
|
4 | if (size < total) |
3523 | ✗ | return AVERROR_INVALIDDATA; | |
3524 | |||
3525 | 4 | lace_size[n] = size - total; | |
3526 | 4 | break; | |
3527 | } | ||
3528 | |||
3529 | 17 | case 0x2: /* fixed-size lacing */ | |
3530 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (size % (*laces)) |
3531 | ✗ | return AVERROR_INVALIDDATA; | |
3532 |
2/2✓ Branch 0 taken 81 times.
✓ Branch 1 taken 17 times.
|
98 | for (n = 0; n < *laces; n++) |
3533 | 81 | lace_size[n] = size / *laces; | |
3534 | 17 | break; | |
3535 | |||
3536 | 54 | case 0x3: /* EBML lacing */ | |
3537 | { | ||
3538 | uint64_t num; | ||
3539 | uint64_t total; | ||
3540 | int offset; | ||
3541 | |||
3542 | 54 | avio_skip(pb, 4); | |
3543 | |||
3544 | 54 | n = ebml_read_num(matroska, pb, 8, &num, 1); | |
3545 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (n < 0) |
3546 | ✗ | return n; | |
3547 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (num > INT_MAX) |
3548 | ✗ | return AVERROR_INVALIDDATA; | |
3549 | |||
3550 | 54 | total = lace_size[0] = num; | |
3551 | 54 | offset = n; | |
3552 |
2/2✓ Branch 0 taken 236 times.
✓ Branch 1 taken 54 times.
|
290 | for (n = 1; n < *laces - 1; n++) { |
3553 | int64_t snum; | ||
3554 | int r; | ||
3555 | 236 | r = matroska_ebmlnum_sint(matroska, pb, &snum); | |
3556 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 236 times.
|
236 | if (r < 0) |
3557 | ✗ | return r; | |
3558 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 236 times.
|
236 | if (lace_size[n - 1] + snum > (uint64_t)INT_MAX) |
3559 | ✗ | return AVERROR_INVALIDDATA; | |
3560 | |||
3561 | 236 | lace_size[n] = lace_size[n - 1] + snum; | |
3562 | 236 | total += lace_size[n]; | |
3563 | 236 | offset += r; | |
3564 | } | ||
3565 | 54 | data += offset; | |
3566 | 54 | size -= offset; | |
3567 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 54 times.
|
54 | if (size < total) |
3568 | ✗ | return AVERROR_INVALIDDATA; | |
3569 | |||
3570 | 54 | lace_size[*laces - 1] = size - total; | |
3571 | 54 | break; | |
3572 | } | ||
3573 | } | ||
3574 | |||
3575 | 75 | *buf = data; | |
3576 | |||
3577 | 75 | return 0; | |
3578 | } | ||
3579 | |||
3580 | ✗ | static int matroska_parse_rm_audio(MatroskaDemuxContext *matroska, | |
3581 | MatroskaTrack *track, AVStream *st, | ||
3582 | uint8_t *data, int size, uint64_t timecode, | ||
3583 | int64_t pos) | ||
3584 | { | ||
3585 | ✗ | const int a = st->codecpar->block_align; | |
3586 | ✗ | const int sps = track->audio.sub_packet_size; | |
3587 | ✗ | const int cfs = track->audio.coded_framesize; | |
3588 | ✗ | const int h = track->audio.sub_packet_h; | |
3589 | ✗ | const int w = track->audio.frame_size; | |
3590 | ✗ | int y = track->audio.sub_packet_cnt; | |
3591 | int x; | ||
3592 | |||
3593 | ✗ | if (!track->audio.pkt_cnt) { | |
3594 | ✗ | if (track->audio.sub_packet_cnt == 0) | |
3595 | ✗ | track->audio.buf_timecode = timecode; | |
3596 | ✗ | if (st->codecpar->codec_id == AV_CODEC_ID_RA_288) { | |
3597 | ✗ | if (size < cfs * h / 2) { | |
3598 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
3599 | "Corrupt int4 RM-style audio packet size\n"); | ||
3600 | ✗ | return AVERROR_INVALIDDATA; | |
3601 | } | ||
3602 | ✗ | for (x = 0; x < h / 2; x++) | |
3603 | ✗ | memcpy(track->audio.buf + x * 2 * w + y * cfs, | |
3604 | ✗ | data + x * cfs, cfs); | |
3605 | ✗ | } else if (st->codecpar->codec_id == AV_CODEC_ID_SIPR) { | |
3606 | ✗ | if (size < w) { | |
3607 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
3608 | "Corrupt sipr RM-style audio packet size\n"); | ||
3609 | ✗ | return AVERROR_INVALIDDATA; | |
3610 | } | ||
3611 | ✗ | memcpy(track->audio.buf + y * w, data, w); | |
3612 | } else { | ||
3613 | ✗ | if (size < w) { | |
3614 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
3615 | "Corrupt generic RM-style audio packet size\n"); | ||
3616 | ✗ | return AVERROR_INVALIDDATA; | |
3617 | } | ||
3618 | ✗ | for (x = 0; x < w / sps; x++) | |
3619 | ✗ | memcpy(track->audio.buf + | |
3620 | ✗ | sps * (h * x + ((h + 1) / 2) * (y & 1) + (y >> 1)), | |
3621 | ✗ | data + x * sps, sps); | |
3622 | } | ||
3623 | |||
3624 | ✗ | if (++track->audio.sub_packet_cnt >= h) { | |
3625 | ✗ | if (st->codecpar->codec_id == AV_CODEC_ID_SIPR) | |
3626 | ✗ | ff_rm_reorder_sipr_data(track->audio.buf, h, w); | |
3627 | ✗ | track->audio.sub_packet_cnt = 0; | |
3628 | ✗ | track->audio.pkt_cnt = h * w / a; | |
3629 | } | ||
3630 | } | ||
3631 | |||
3632 | ✗ | while (track->audio.pkt_cnt) { | |
3633 | int ret; | ||
3634 | ✗ | AVPacket *pkt = matroska->pkt; | |
3635 | |||
3636 | ✗ | ret = av_new_packet(pkt, a); | |
3637 | ✗ | if (ret < 0) { | |
3638 | ✗ | return ret; | |
3639 | } | ||
3640 | ✗ | memcpy(pkt->data, | |
3641 | ✗ | track->audio.buf + a * (h * w / a - track->audio.pkt_cnt--), | |
3642 | a); | ||
3643 | ✗ | pkt->pts = track->audio.buf_timecode; | |
3644 | ✗ | track->audio.buf_timecode = AV_NOPTS_VALUE; | |
3645 | ✗ | pkt->pos = pos; | |
3646 | ✗ | pkt->stream_index = st->index; | |
3647 | ✗ | ret = avpriv_packet_list_put(&matroska->queue, pkt, NULL, 0); | |
3648 | ✗ | if (ret < 0) { | |
3649 | ✗ | av_packet_unref(pkt); | |
3650 | ✗ | return AVERROR(ENOMEM); | |
3651 | } | ||
3652 | } | ||
3653 | |||
3654 | ✗ | return 0; | |
3655 | } | ||
3656 | |||
3657 | /* reconstruct full wavpack blocks from mangled matroska ones */ | ||
3658 | 24 | static int matroska_parse_wavpack(MatroskaTrack *track, | |
3659 | uint8_t **data, int *size) | ||
3660 | { | ||
3661 | 24 | uint8_t *dst = NULL; | |
3662 | 24 | uint8_t *src = *data; | |
3663 | 24 | int dstlen = 0; | |
3664 | 24 | int srclen = *size; | |
3665 | uint32_t samples; | ||
3666 | uint16_t ver; | ||
3667 | 24 | int ret, offset = 0; | |
3668 | |||
3669 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | if (srclen < 12) |
3670 | ✗ | return AVERROR_INVALIDDATA; | |
3671 | |||
3672 | av_assert1(track->stream->codecpar->extradata_size >= 2); | ||
3673 | 24 | ver = AV_RL16(track->stream->codecpar->extradata); | |
3674 | |||
3675 | 24 | samples = AV_RL32(src); | |
3676 | 24 | src += 4; | |
3677 | 24 | srclen -= 4; | |
3678 | |||
3679 |
2/2✓ Branch 0 taken 112 times.
✓ Branch 1 taken 24 times.
|
136 | while (srclen >= 8) { |
3680 | int multiblock; | ||
3681 | uint32_t blocksize; | ||
3682 | uint8_t *tmp; | ||
3683 | |||
3684 | 112 | uint32_t flags = AV_RL32(src); | |
3685 | 112 | uint32_t crc = AV_RL32(src + 4); | |
3686 | 112 | src += 8; | |
3687 | 112 | srclen -= 8; | |
3688 | |||
3689 | 112 | multiblock = (flags & 0x1800) != 0x1800; | |
3690 |
2/2✓ Branch 0 taken 110 times.
✓ Branch 1 taken 2 times.
|
112 | if (multiblock) { |
3691 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 110 times.
|
110 | if (srclen < 4) { |
3692 | ✗ | ret = AVERROR_INVALIDDATA; | |
3693 | ✗ | goto fail; | |
3694 | } | ||
3695 | 110 | blocksize = AV_RL32(src); | |
3696 | 110 | src += 4; | |
3697 | 110 | srclen -= 4; | |
3698 | } else | ||
3699 | 2 | blocksize = srclen; | |
3700 | |||
3701 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
|
112 | if (blocksize > srclen) { |
3702 | ✗ | ret = AVERROR_INVALIDDATA; | |
3703 | ✗ | goto fail; | |
3704 | } | ||
3705 | |||
3706 | 112 | tmp = av_realloc(dst, dstlen + blocksize + 32 + AV_INPUT_BUFFER_PADDING_SIZE); | |
3707 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 112 times.
|
112 | if (!tmp) { |
3708 | ✗ | ret = AVERROR(ENOMEM); | |
3709 | ✗ | goto fail; | |
3710 | } | ||
3711 | 112 | dst = tmp; | |
3712 | 112 | dstlen += blocksize + 32; | |
3713 | |||
3714 | 112 | AV_WL32(dst + offset, MKTAG('w', 'v', 'p', 'k')); // tag | |
3715 | 112 | AV_WL32(dst + offset + 4, blocksize + 24); // blocksize - 8 | |
3716 | 112 | AV_WL16(dst + offset + 8, ver); // version | |
3717 | 112 | AV_WL16(dst + offset + 10, 0); // track/index_no | |
3718 | 112 | AV_WL32(dst + offset + 12, 0); // total samples | |
3719 | 112 | AV_WL32(dst + offset + 16, 0); // block index | |
3720 | 112 | AV_WL32(dst + offset + 20, samples); // number of samples | |
3721 | 112 | AV_WL32(dst + offset + 24, flags); // flags | |
3722 | 112 | AV_WL32(dst + offset + 28, crc); // crc | |
3723 | 112 | memcpy(dst + offset + 32, src, blocksize); // block data | |
3724 | |||
3725 | 112 | src += blocksize; | |
3726 | 112 | srclen -= blocksize; | |
3727 | 112 | offset += blocksize + 32; | |
3728 | } | ||
3729 | |||
3730 | 24 | memset(dst + dstlen, 0, AV_INPUT_BUFFER_PADDING_SIZE); | |
3731 | |||
3732 | 24 | *data = dst; | |
3733 | 24 | *size = dstlen; | |
3734 | |||
3735 | 24 | return 0; | |
3736 | |||
3737 | ✗ | fail: | |
3738 | ✗ | av_freep(&dst); | |
3739 | ✗ | return ret; | |
3740 | } | ||
3741 | |||
3742 | 11 | static int matroska_parse_prores(MatroskaTrack *track, | |
3743 | uint8_t **data, int *size) | ||
3744 | { | ||
3745 | uint8_t *dst; | ||
3746 | 11 | int dstlen = *size + 8; | |
3747 | |||
3748 | 11 | dst = av_malloc(dstlen + AV_INPUT_BUFFER_PADDING_SIZE); | |
3749 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (!dst) |
3750 | ✗ | return AVERROR(ENOMEM); | |
3751 | |||
3752 | 11 | AV_WB32(dst, dstlen); | |
3753 | 11 | AV_WB32(dst + 4, MKBETAG('i', 'c', 'p', 'f')); | |
3754 | 11 | memcpy(dst + 8, *data, dstlen - 8); | |
3755 | 11 | memset(dst + dstlen, 0, AV_INPUT_BUFFER_PADDING_SIZE); | |
3756 | |||
3757 | 11 | *data = dst; | |
3758 | 11 | *size = dstlen; | |
3759 | |||
3760 | 11 | return 0; | |
3761 | } | ||
3762 | |||
3763 | 90 | static int matroska_parse_webvtt(MatroskaDemuxContext *matroska, | |
3764 | MatroskaTrack *track, | ||
3765 | AVStream *st, | ||
3766 | uint8_t *data, int data_len, | ||
3767 | uint64_t timecode, | ||
3768 | uint64_t duration, | ||
3769 | int64_t pos) | ||
3770 | { | ||
3771 | 90 | AVPacket *pkt = matroska->pkt; | |
3772 | uint8_t *id, *settings, *text, *buf; | ||
3773 | int id_len, settings_len, text_len; | ||
3774 | uint8_t *p, *q; | ||
3775 | int err; | ||
3776 | |||
3777 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (data_len <= 0) |
3778 | ✗ | return AVERROR_INVALIDDATA; | |
3779 | |||
3780 | 90 | p = data; | |
3781 | 90 | q = data + data_len; | |
3782 | |||
3783 | 90 | id = p; | |
3784 | 90 | id_len = -1; | |
3785 |
1/2✓ Branch 0 taken 192 times.
✗ Branch 1 not taken.
|
192 | while (p < q) { |
3786 |
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') { |
3787 | 90 | id_len = p - id; | |
3788 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (*p == '\r') |
3789 | ✗ | p++; | |
3790 | 90 | break; | |
3791 | } | ||
3792 | 102 | p++; | |
3793 | } | ||
3794 | |||
3795 |
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') |
3796 | ✗ | return AVERROR_INVALIDDATA; | |
3797 | 90 | p++; | |
3798 | |||
3799 | 90 | settings = p; | |
3800 | 90 | settings_len = -1; | |
3801 |
1/2✓ Branch 0 taken 546 times.
✗ Branch 1 not taken.
|
546 | while (p < q) { |
3802 |
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') { |
3803 | 90 | settings_len = p - settings; | |
3804 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (*p == '\r') |
3805 | ✗ | p++; | |
3806 | 90 | break; | |
3807 | } | ||
3808 | 456 | p++; | |
3809 | } | ||
3810 | |||
3811 |
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') |
3812 | ✗ | return AVERROR_INVALIDDATA; | |
3813 | 90 | p++; | |
3814 | |||
3815 | 90 | text = p; | |
3816 | 90 | text_len = q - p; | |
3817 |
1/2✓ Branch 0 taken 90 times.
✗ Branch 1 not taken.
|
90 | while (text_len > 0) { |
3818 | 90 | const int len = text_len - 1; | |
3819 | 90 | const uint8_t c = p[len]; | |
3820 |
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') |
3821 | 90 | break; | |
3822 | ✗ | text_len = len; | |
3823 | } | ||
3824 | |||
3825 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (text_len <= 0) |
3826 | ✗ | return AVERROR_INVALIDDATA; | |
3827 | |||
3828 | 90 | err = av_new_packet(pkt, text_len); | |
3829 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (err < 0) { |
3830 | ✗ | return err; | |
3831 | } | ||
3832 | |||
3833 | 90 | memcpy(pkt->data, text, text_len); | |
3834 | |||
3835 |
2/2✓ Branch 0 taken 12 times.
✓ Branch 1 taken 78 times.
|
90 | if (id_len > 0) { |
3836 | 12 | buf = av_packet_new_side_data(pkt, | |
3837 | AV_PKT_DATA_WEBVTT_IDENTIFIER, | ||
3838 | id_len); | ||
3839 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 12 times.
|
12 | if (!buf) { |
3840 | ✗ | av_packet_unref(pkt); | |
3841 | ✗ | return AVERROR(ENOMEM); | |
3842 | } | ||
3843 | 12 | memcpy(buf, id, id_len); | |
3844 | } | ||
3845 | |||
3846 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 66 times.
|
90 | if (settings_len > 0) { |
3847 | 24 | buf = av_packet_new_side_data(pkt, | |
3848 | AV_PKT_DATA_WEBVTT_SETTINGS, | ||
3849 | settings_len); | ||
3850 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | if (!buf) { |
3851 | ✗ | av_packet_unref(pkt); | |
3852 | ✗ | return AVERROR(ENOMEM); | |
3853 | } | ||
3854 | 24 | memcpy(buf, settings, settings_len); | |
3855 | } | ||
3856 | |||
3857 | // Do we need this for subtitles? | ||
3858 | // pkt->flags = AV_PKT_FLAG_KEY; | ||
3859 | |||
3860 | 90 | pkt->stream_index = st->index; | |
3861 | 90 | pkt->pts = timecode; | |
3862 | |||
3863 | // Do we need this for subtitles? | ||
3864 | // pkt->dts = timecode; | ||
3865 | |||
3866 | 90 | pkt->duration = duration; | |
3867 | 90 | pkt->pos = pos; | |
3868 | |||
3869 | 90 | err = avpriv_packet_list_put(&matroska->queue, pkt, NULL, 0); | |
3870 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (err < 0) { |
3871 | ✗ | av_packet_unref(pkt); | |
3872 | ✗ | return AVERROR(ENOMEM); | |
3873 | } | ||
3874 | |||
3875 | 90 | return 0; | |
3876 | } | ||
3877 | |||
3878 | 136 | static int matroska_parse_block_additional(MatroskaDemuxContext *matroska, | |
3879 | MatroskaTrack *track, AVPacket *pkt, | ||
3880 | const uint8_t *data, int size, uint64_t id) | ||
3881 | { | ||
3882 | 136 | const EbmlList *mappings_list = &track->block_addition_mappings; | |
3883 | 136 | MatroskaBlockAdditionMapping *mappings = mappings_list->elem, *mapping = NULL; | |
3884 | uint8_t *side_data; | ||
3885 | int res; | ||
3886 | |||
3887 |
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) { |
3888 | ✗ | int strict = matroska->ctx->strict_std_compliance >= FF_COMPLIANCE_STRICT; | |
3889 | ✗ | av_log(matroska->ctx, strict ? AV_LOG_ERROR : AV_LOG_WARNING, | |
3890 | "BlockAddID %"PRIu64" is higher than the reported MaxBlockAdditionID %"PRIu64" " | ||
3891 | "for Track with TrackNumber %"PRIu64"\n", id, track->max_block_additional_id, | ||
3892 | track->num); | ||
3893 | ✗ | if (strict) | |
3894 | ✗ | return AVERROR_INVALIDDATA; | |
3895 | } | ||
3896 | |||
3897 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 134 times.
|
136 | for (int i = 0; i < mappings_list->nb_elem; i++) { |
3898 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if (id != mappings[i].value) |
3899 | ✗ | continue; | |
3900 | 2 | mapping = &mappings[i]; | |
3901 | 2 | break; | |
3902 | } | ||
3903 | |||
3904 |
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) { |
3905 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, "BlockAddID %"PRIu64" has no mapping. Skipping\n", id); | |
3906 | ✗ | return 0; | |
3907 | } | ||
3908 | |||
3909 |
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) |
3910 | 2 | id = mapping->type; | |
3911 | |||
3912 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 130 times.
|
136 | switch (id) { |
3913 | 6 | case MATROSKA_BLOCK_ADD_ID_TYPE_ITU_T_T35: { | |
3914 | GetByteContext bc; | ||
3915 | int country_code, provider_code; | ||
3916 | int provider_oriented_code, application_identifier; | ||
3917 | size_t hdrplus_size; | ||
3918 | AVDynamicHDRPlus *hdrplus; | ||
3919 | |||
3920 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (size < 6) |
3921 | ✗ | break; //ignore | |
3922 | |||
3923 | 6 | bytestream2_init(&bc, data, size); | |
3924 | |||
3925 | /* ITU-T T.35 metadata */ | ||
3926 | 6 | country_code = bytestream2_get_byteu(&bc); | |
3927 | 6 | provider_code = bytestream2_get_be16u(&bc); | |
3928 | |||
3929 |
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 || |
3930 | provider_code != ITU_T_T35_PROVIDER_CODE_SMTPE) | ||
3931 | break; // ignore | ||
3932 | |||
3933 | 6 | provider_oriented_code = bytestream2_get_be16u(&bc); | |
3934 | 6 | application_identifier = bytestream2_get_byteu(&bc); | |
3935 | |||
3936 |
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) |
3937 | break; // ignore | ||
3938 | |||
3939 | 6 | hdrplus = av_dynamic_hdr_plus_alloc(&hdrplus_size); | |
3940 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 6 times.
|
6 | if (!hdrplus) |
3941 | 6 | return AVERROR(ENOMEM); | |
3942 | |||
3943 |
1/2✓ Branch 1 taken 6 times.
✗ Branch 2 not taken.
|
6 | if ((res = av_dynamic_hdr_plus_from_t35(hdrplus, bc.buffer, |
3944 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 6 times.
|
12 | bytestream2_get_bytes_left(&bc))) < 0 || |
3945 | 6 | (res = av_packet_add_side_data(pkt, AV_PKT_DATA_DYNAMIC_HDR10_PLUS, | |
3946 | (uint8_t *)hdrplus, hdrplus_size)) < 0) { | ||
3947 | ✗ | av_free(hdrplus); | |
3948 | ✗ | return res; | |
3949 | } | ||
3950 | |||
3951 | 6 | return 0; | |
3952 | } | ||
3953 | 130 | default: | |
3954 | 130 | break; | |
3955 | } | ||
3956 | |||
3957 | 130 | side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, | |
3958 | size + (size_t)8); | ||
3959 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 130 times.
|
130 | if (!side_data) |
3960 | ✗ | return AVERROR(ENOMEM); | |
3961 | |||
3962 | 130 | AV_WB64(side_data, id); | |
3963 | 130 | memcpy(side_data + 8, data, size); | |
3964 | |||
3965 | 130 | return 0; | |
3966 | } | ||
3967 | |||
3968 | 30141 | static int matroska_parse_frame(MatroskaDemuxContext *matroska, | |
3969 | MatroskaTrack *track, AVStream *st, | ||
3970 | AVBufferRef *buf, uint8_t *data, int pkt_size, | ||
3971 | uint64_t timecode, uint64_t lace_duration, | ||
3972 | int64_t pos, int is_keyframe, | ||
3973 | MatroskaBlockMore *blockmore, int nb_blockmore, | ||
3974 | int64_t discard_padding) | ||
3975 | { | ||
3976 | 30141 | uint8_t *pkt_data = data; | |
3977 | 30141 | int res = 0; | |
3978 | 30141 | AVPacket *pkt = matroska->pkt; | |
3979 | |||
3980 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 30117 times.
|
30141 | if (st->codecpar->codec_id == AV_CODEC_ID_WAVPACK) { |
3981 | 24 | res = matroska_parse_wavpack(track, &pkt_data, &pkt_size); | |
3982 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | if (res < 0) { |
3983 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
3984 | "Error parsing a wavpack block.\n"); | ||
3985 | ✗ | goto fail; | |
3986 | } | ||
3987 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 22 times.
|
24 | if (!buf) |
3988 | 2 | av_freep(&data); | |
3989 | 24 | buf = NULL; | |
3990 | } | ||
3991 | |||
3992 |
2/2✓ Branch 0 taken 13 times.
✓ Branch 1 taken 30128 times.
|
30141 | if (st->codecpar->codec_id == AV_CODEC_ID_PRORES && |
3993 |
2/2✓ Branch 0 taken 11 times.
✓ Branch 1 taken 2 times.
|
13 | AV_RB32(pkt_data + 4) != MKBETAG('i', 'c', 'p', 'f')) { |
3994 | 11 | res = matroska_parse_prores(track, &pkt_data, &pkt_size); | |
3995 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 11 times.
|
11 | if (res < 0) { |
3996 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, | |
3997 | "Error parsing a prores block.\n"); | ||
3998 | ✗ | goto fail; | |
3999 | } | ||
4000 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 9 times.
|
11 | if (!buf) |
4001 | 2 | av_freep(&data); | |
4002 | 11 | buf = NULL; | |
4003 | } | ||
4004 | |||
4005 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 30141 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
30141 | if (!pkt_size && !nb_blockmore) |
4006 | ✗ | goto no_output; | |
4007 | |||
4008 |
5/6✓ Branch 0 taken 26914 times.
✓ Branch 1 taken 3227 times.
✓ Branch 2 taken 12 times.
✓ Branch 3 taken 26902 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 12 times.
|
30141 | if (!matroska->is_webm && nb_blockmore && !track->max_block_additional_id) { |
4009 | ✗ | int strict = matroska->ctx->strict_std_compliance >= FF_COMPLIANCE_STRICT; | |
4010 | ✗ | av_log(matroska->ctx, strict ? AV_LOG_ERROR : AV_LOG_WARNING, | |
4011 | "Unexpected BlockAdditions found in a Block from Track with TrackNumber %"PRIu64" " | ||
4012 | "where MaxBlockAdditionID is 0\n", track->num); | ||
4013 | ✗ | if (strict) { | |
4014 | ✗ | res = AVERROR_INVALIDDATA; | |
4015 | ✗ | goto fail; | |
4016 | } | ||
4017 | } | ||
4018 | |||
4019 |
2/2✓ Branch 0 taken 112 times.
✓ Branch 1 taken 30029 times.
|
30141 | if (!buf) |
4020 | 112 | pkt->buf = av_buffer_create(pkt_data, pkt_size + AV_INPUT_BUFFER_PADDING_SIZE, | |
4021 | NULL, NULL, 0); | ||
4022 | else | ||
4023 | 30029 | pkt->buf = av_buffer_ref(buf); | |
4024 | |||
4025 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30141 times.
|
30141 | if (!pkt->buf) { |
4026 | ✗ | res = AVERROR(ENOMEM); | |
4027 | ✗ | goto fail; | |
4028 | } | ||
4029 | |||
4030 | 30141 | pkt->data = pkt_data; | |
4031 | 30141 | pkt->size = pkt_size; | |
4032 | 30141 | pkt->flags = is_keyframe; | |
4033 | 30141 | pkt->stream_index = st->index; | |
4034 | |||
4035 |
2/2✓ Branch 0 taken 136 times.
✓ Branch 1 taken 30141 times.
|
30277 | for (int i = 0; i < nb_blockmore; i++) { |
4036 | 136 | MatroskaBlockMore *more = &blockmore[i]; | |
4037 | |||
4038 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
|
136 | if (!more->additional.size) |
4039 | ✗ | continue; | |
4040 | |||
4041 | 136 | res = matroska_parse_block_additional(matroska, track, pkt, more->additional.data, | |
4042 | more->additional.size, more->additional_id); | ||
4043 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 136 times.
|
136 | if (res < 0) { |
4044 | ✗ | av_packet_unref(pkt); | |
4045 | ✗ | return res; | |
4046 | } | ||
4047 | } | ||
4048 | |||
4049 |
2/2✓ Branch 0 taken 27 times.
✓ Branch 1 taken 30114 times.
|
30141 | if (discard_padding) { |
4050 | 27 | uint8_t *side_data = av_packet_new_side_data(pkt, | |
4051 | AV_PKT_DATA_SKIP_SAMPLES, | ||
4052 | 10); | ||
4053 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 27 times.
|
27 | if (!side_data) { |
4054 | ✗ | av_packet_unref(pkt); | |
4055 | ✗ | return AVERROR(ENOMEM); | |
4056 | } | ||
4057 | 27 | discard_padding = av_rescale_q(discard_padding, | |
4058 | 27 | (AVRational){1, 1000000000}, | |
4059 | 27 | (AVRational){1, st->codecpar->sample_rate}); | |
4060 |
1/2✓ Branch 0 taken 27 times.
✗ Branch 1 not taken.
|
27 | if (discard_padding > 0) { |
4061 | 27 | AV_WL32A(side_data + 4, discard_padding); | |
4062 | } else { | ||
4063 | ✗ | AV_WL32A(side_data, -discard_padding); | |
4064 | } | ||
4065 | } | ||
4066 | |||
4067 |
2/2✓ Branch 0 taken 433 times.
✓ Branch 1 taken 29708 times.
|
30141 | if (track->ms_compat) |
4068 | 433 | pkt->dts = timecode; | |
4069 | else | ||
4070 | 29708 | pkt->pts = timecode; | |
4071 | 30141 | pkt->pos = pos; | |
4072 | 30141 | pkt->duration = lace_duration; | |
4073 | |||
4074 | 30141 | res = avpriv_packet_list_put(&matroska->queue, pkt, NULL, 0); | |
4075 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30141 times.
|
30141 | if (res < 0) { |
4076 | ✗ | av_packet_unref(pkt); | |
4077 | ✗ | return AVERROR(ENOMEM); | |
4078 | } | ||
4079 | |||
4080 | 30141 | return 0; | |
4081 | |||
4082 | ✗ | no_output: | |
4083 | ✗ | fail: | |
4084 | ✗ | if (!buf) | |
4085 | ✗ | av_free(pkt_data); | |
4086 | ✗ | return res; | |
4087 | } | ||
4088 | |||
4089 | 30714 | static int matroska_parse_block(MatroskaDemuxContext *matroska, AVBufferRef *buf, uint8_t *data, | |
4090 | int size, int64_t pos, uint64_t cluster_time, | ||
4091 | uint64_t block_duration, int is_keyframe, | ||
4092 | MatroskaBlockMore *blockmore, int nb_blockmore, | ||
4093 | int64_t cluster_pos, int64_t discard_padding) | ||
4094 | { | ||
4095 | 30714 | uint64_t timecode = AV_NOPTS_VALUE; | |
4096 | MatroskaTrack *track; | ||
4097 | FFIOContext pb; | ||
4098 | 30714 | int res = 0; | |
4099 | AVStream *st; | ||
4100 | int16_t block_time; | ||
4101 | uint32_t lace_size[256]; | ||
4102 | 30714 | int n, flags, laces = 0; | |
4103 | uint64_t num; | ||
4104 | int trust_default_duration; | ||
4105 | |||
4106 | av_assert1(buf); | ||
4107 | |||
4108 | 30714 | ffio_init_read_context(&pb, data, size); | |
4109 | |||
4110 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 30714 times.
|
30714 | if ((n = ebml_read_num(matroska, &pb.pub, 8, &num, 1)) < 0) |
4111 | ✗ | return n; | |
4112 | 30714 | data += n; | |
4113 | 30714 | size -= n; | |
4114 | |||
4115 | 30714 | track = matroska_find_track_by_num(matroska, num); | |
4116 |
3/4✓ Branch 0 taken 30713 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 30713 times.
|
30714 | if (!track || size < 3) |
4117 | 1 | return AVERROR_INVALIDDATA; | |
4118 | |||
4119 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30713 times.
|
30713 | if (!(st = track->stream)) { |
4120 | ✗ | av_log(matroska->ctx, AV_LOG_VERBOSE, | |
4121 | "No stream associated to TrackNumber %"PRIu64". " | ||
4122 | "Ignoring Block with this TrackNumber.\n", num); | ||
4123 | ✗ | return 0; | |
4124 | } | ||
4125 | |||
4126 |
2/2✓ Branch 0 taken 311 times.
✓ Branch 1 taken 30402 times.
|
30713 | if (st->discard >= AVDISCARD_ALL) |
4127 | 311 | return res; | |
4128 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30402 times.
|
30402 | if (block_duration > INT64_MAX) |
4129 | ✗ | block_duration = INT64_MAX; | |
4130 | |||
4131 | 30402 | block_time = sign_extend(AV_RB16(data), 16); | |
4132 | 30402 | data += 2; | |
4133 | 30402 | flags = *data++; | |
4134 | 30402 | size -= 3; | |
4135 |
2/2✓ Branch 0 taken 29959 times.
✓ Branch 1 taken 443 times.
|
30402 | if (is_keyframe == -1) |
4136 | 29959 | is_keyframe = flags & 0x80 ? AV_PKT_FLAG_KEY : 0; | |
4137 | |||
4138 |
3/4✓ Branch 0 taken 30402 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 79 times.
✓ Branch 3 taken 30323 times.
|
30402 | if (cluster_time != (uint64_t) -1 && |
4139 |
2/2✓ Branch 0 taken 63 times.
✓ Branch 1 taken 16 times.
|
79 | (block_time >= 0 || cluster_time >= -block_time)) { |
4140 | 30386 | uint64_t timecode_cluster_in_track_tb = (double) cluster_time / track->time_scale; | |
4141 | 30386 | timecode = timecode_cluster_in_track_tb + block_time - track->codec_delay_in_track_tb; | |
4142 |
2/2✓ Branch 0 taken 128 times.
✓ Branch 1 taken 30258 times.
|
30386 | if (track->type == MATROSKA_TRACK_TYPE_SUBTITLE && |
4143 |
2/2✓ Branch 0 taken 6 times.
✓ Branch 1 taken 122 times.
|
128 | timecode < track->end_timecode) |
4144 | 6 | is_keyframe = 0; /* overlapping subtitles are not key frame */ | |
4145 |
2/2✓ Branch 0 taken 26793 times.
✓ Branch 1 taken 3593 times.
|
30386 | if (is_keyframe) { |
4146 | 26793 | ff_reduce_index(matroska->ctx, st->index); | |
4147 | 26793 | av_add_index_entry(st, cluster_pos, timecode, 0, 0, | |
4148 | AVINDEX_KEYFRAME); | ||
4149 | } | ||
4150 | } | ||
4151 | |||
4152 |
2/2✓ Branch 0 taken 593 times.
✓ Branch 1 taken 29809 times.
|
30402 | if (matroska->skip_to_keyframe && |
4153 |
1/2✓ Branch 0 taken 593 times.
✗ Branch 1 not taken.
|
593 | track->type != MATROSKA_TRACK_TYPE_SUBTITLE) { |
4154 | // Compare signed timecodes. Timecode may be negative due to codec delay | ||
4155 | // offset. We don't support timestamps greater than int64_t anyway - see | ||
4156 | // AVPacket's pts. | ||
4157 |
2/2✓ Branch 0 taken 548 times.
✓ Branch 1 taken 45 times.
|
593 | if ((int64_t)timecode < (int64_t)matroska->skip_to_timecode) |
4158 | 548 | return res; | |
4159 |
1/2✓ Branch 0 taken 45 times.
✗ Branch 1 not taken.
|
45 | if (is_keyframe) |
4160 | 45 | matroska->skip_to_keyframe = 0; | |
4161 | ✗ | else if (!ffstream(st)->skip_to_keyframe) { | |
4162 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "File is broken, keyframes not correctly marked!\n"); | |
4163 | ✗ | matroska->skip_to_keyframe = 0; | |
4164 | } | ||
4165 | } | ||
4166 | |||
4167 | 29854 | res = matroska_parse_laces(matroska, &data, size, (flags & 0x06) >> 1, | |
4168 | &pb.pub, lace_size, &laces); | ||
4169 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 29854 times.
|
29854 | if (res < 0) { |
4170 | ✗ | av_log(matroska->ctx, AV_LOG_ERROR, "Error parsing frame sizes.\n"); | |
4171 | ✗ | return res; | |
4172 | } | ||
4173 | |||
4174 | 29854 | trust_default_duration = track->default_duration != 0; | |
4175 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 29854 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
29854 | if (track->audio.samplerate == 8000 && trust_default_duration) { |
4176 | // If this is needed for more codecs, then add them here | ||
4177 | ✗ | if (st->codecpar->codec_id == AV_CODEC_ID_AC3) { | |
4178 | ✗ | if (track->audio.samplerate != st->codecpar->sample_rate || !st->codecpar->frame_size) | |
4179 | ✗ | trust_default_duration = 0; | |
4180 | } | ||
4181 | } | ||
4182 | |||
4183 |
4/4✓ Branch 0 taken 29574 times.
✓ Branch 1 taken 280 times.
✓ Branch 2 taken 4252 times.
✓ Branch 3 taken 25322 times.
|
29854 | if (!block_duration && trust_default_duration) |
4184 | 4252 | block_duration = track->default_duration * laces / matroska->time_scale; | |
4185 | |||
4186 |
5/6✓ Branch 0 taken 29854 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 76 times.
✓ Branch 3 taken 29778 times.
✓ Branch 4 taken 60 times.
✓ Branch 5 taken 16 times.
|
29854 | if (cluster_time != (uint64_t)-1 && (block_time >= 0 || cluster_time >= -block_time)) |
4187 | 29838 | track->end_timecode = | |
4188 | 29838 | FFMAX(track->end_timecode, timecode + block_duration); | |
4189 | |||
4190 |
2/2✓ Branch 0 taken 30231 times.
✓ Branch 1 taken 29854 times.
|
60085 | for (n = 0; n < laces; n++) { |
4191 | 30231 | int64_t lace_duration = block_duration*(n+1) / laces - block_duration*n / laces; | |
4192 | 30231 | uint8_t *out_data = data; | |
4193 | 30231 | int out_size = lace_size[n]; | |
4194 | |||
4195 |
2/2✓ Branch 0 taken 81 times.
✓ Branch 1 taken 30150 times.
|
30231 | if (track->needs_decoding) { |
4196 | 81 | res = matroska_decode_buffer(&out_data, &out_size, track); | |
4197 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 81 times.
|
81 | if (res < 0) |
4198 | ✗ | return res; | |
4199 | /* Given that we are here means that out_data is no longer | ||
4200 | * owned by buf, so set it to NULL. This depends upon | ||
4201 | * zero-length header removal compression being ignored. */ | ||
4202 | av_assert1(out_data != data); | ||
4203 | 81 | buf = NULL; | |
4204 | } | ||
4205 | |||
4206 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30231 times.
|
30231 | if (track->audio.buf) { |
4207 | ✗ | res = matroska_parse_rm_audio(matroska, track, st, | |
4208 | out_data, out_size, | ||
4209 | timecode, pos); | ||
4210 | ✗ | if (!buf) | |
4211 | ✗ | av_free(out_data); | |
4212 | ✗ | if (res) | |
4213 | ✗ | return res; | |
4214 |
2/2✓ Branch 0 taken 90 times.
✓ Branch 1 taken 30141 times.
|
30231 | } else if (st->codecpar->codec_id == AV_CODEC_ID_WEBVTT) { |
4215 | 90 | res = matroska_parse_webvtt(matroska, track, st, | |
4216 | out_data, out_size, | ||
4217 | timecode, lace_duration, | ||
4218 | pos); | ||
4219 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (!buf) |
4220 | ✗ | av_free(out_data); | |
4221 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 90 times.
|
90 | if (res) |
4222 | ✗ | return res; | |
4223 | } else { | ||
4224 | 30141 | res = matroska_parse_frame(matroska, track, st, buf, out_data, | |
4225 | out_size, timecode, lace_duration, | ||
4226 | pos, is_keyframe, | ||
4227 | blockmore, nb_blockmore, | ||
4228 | discard_padding); | ||
4229 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 30141 times.
|
30141 | if (res) |
4230 | ✗ | return res; | |
4231 | } | ||
4232 | |||
4233 |
2/2✓ Branch 0 taken 30143 times.
✓ Branch 1 taken 88 times.
|
30231 | if (timecode != AV_NOPTS_VALUE) |
4234 |
2/2✓ Branch 0 taken 4821 times.
✓ Branch 1 taken 25322 times.
|
30143 | timecode = lace_duration ? timecode + lace_duration : AV_NOPTS_VALUE; |
4235 | 30231 | data += lace_size[n]; | |
4236 | } | ||
4237 | |||
4238 | 29854 | return 0; | |
4239 | } | ||
4240 | |||
4241 | 31114 | static int matroska_parse_cluster(MatroskaDemuxContext *matroska) | |
4242 | { | ||
4243 | 31114 | MatroskaCluster *cluster = &matroska->current_cluster; | |
4244 | 31114 | MatroskaBlock *block = &cluster->block; | |
4245 | int res; | ||
4246 | |||
4247 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 31114 times.
|
31114 | av_assert0(matroska->num_levels <= 2U); |
4248 | |||
4249 |
2/2✓ Branch 0 taken 1144 times.
✓ Branch 1 taken 29970 times.
|
31114 | if (matroska->num_levels == 1) { |
4250 | 1144 | res = ebml_parse(matroska, matroska_segment, NULL); | |
4251 | |||
4252 |
2/2✓ Branch 0 taken 800 times.
✓ Branch 1 taken 344 times.
|
1144 | if (res == 1) { |
4253 | /* Found a cluster: subtract the size of the ID already read. */ | ||
4254 | 800 | cluster->pos = avio_tell(matroska->ctx->pb) - 4; | |
4255 | |||
4256 | 800 | res = ebml_parse(matroska, matroska_cluster_enter, cluster); | |
4257 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 800 times.
|
800 | if (res < 0) |
4258 | ✗ | return res; | |
4259 | } | ||
4260 | } | ||
4261 | |||
4262 |
2/2✓ Branch 0 taken 30729 times.
✓ Branch 1 taken 385 times.
|
31114 | if (matroska->num_levels == 2) { |
4263 | /* We are inside a cluster. */ | ||
4264 | 30729 | res = ebml_parse(matroska, matroska_cluster_parsing, cluster); | |
4265 | |||
4266 |
4/4✓ Branch 0 taken 30719 times.
✓ Branch 1 taken 10 times.
✓ Branch 2 taken 30714 times.
✓ Branch 3 taken 5 times.
|
30729 | if (res >= 0 && block->bin.size > 0) { |
4267 |
2/2✓ Branch 0 taken 484 times.
✓ Branch 1 taken 30230 times.
|
30714 | int is_keyframe = block->non_simple ? block->reference.count == 0 : -1; |
4268 | |||
4269 | 30714 | res = matroska_parse_block(matroska, block->bin.buf, block->bin.data, | |
4270 | block->bin.size, block->bin.pos, | ||
4271 | cluster->timecode, block->duration, | ||
4272 | 30714 | is_keyframe, block->blockmore.elem, | |
4273 | block->blockmore.nb_elem, cluster->pos, | ||
4274 | block->discard_padding); | ||
4275 | } | ||
4276 | |||
4277 | 30729 | ebml_free(matroska_blockgroup, block); | |
4278 | 30729 | memset(block, 0, sizeof(*block)); | |
4279 |
2/2✓ Branch 0 taken 357 times.
✓ Branch 1 taken 28 times.
|
385 | } else if (!matroska->num_levels) { |
4280 |
2/2✓ Branch 1 taken 350 times.
✓ Branch 2 taken 7 times.
|
357 | if (!avio_feof(matroska->ctx->pb)) { |
4281 | 350 | avio_r8(matroska->ctx->pb); | |
4282 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 350 times.
|
350 | if (!avio_feof(matroska->ctx->pb)) { |
4283 | ✗ | av_log(matroska->ctx, AV_LOG_WARNING, "File extends beyond " | |
4284 | "end of segment.\n"); | ||
4285 | ✗ | return AVERROR_INVALIDDATA; | |
4286 | } | ||
4287 | } | ||
4288 | 357 | matroska->done = 1; | |
4289 | 357 | return AVERROR_EOF; | |
4290 | } | ||
4291 | |||
4292 | 30757 | return res; | |
4293 | } | ||
4294 | |||
4295 | 29867 | static int matroska_read_packet(AVFormatContext *s, AVPacket *pkt) | |
4296 | { | ||
4297 | 29867 | MatroskaDemuxContext *matroska = s->priv_data; | |
4298 | 29867 | int ret = 0; | |
4299 | |||
4300 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 29857 times.
|
29867 | if (matroska->resync_pos == -1) { |
4301 | // This can only happen if generic seeking has been used. | ||
4302 | 10 | matroska->resync_pos = avio_tell(s->pb); | |
4303 | } | ||
4304 | |||
4305 |
2/2✓ Branch 1 taken 30724 times.
✓ Branch 2 taken 29484 times.
|
60208 | while (matroska_deliver_packet(matroska, pkt)) { |
4306 |
2/2✓ Branch 0 taken 383 times.
✓ Branch 1 taken 30341 times.
|
30724 | if (matroska->done) |
4307 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 373 times.
|
383 | return (ret < 0) ? ret : AVERROR_EOF; |
4308 |
4/4✓ Branch 1 taken 344 times.
✓ Branch 2 taken 29997 times.
✓ Branch 3 taken 13 times.
✓ Branch 4 taken 331 times.
|
30341 | if (matroska_parse_cluster(matroska) < 0 && !matroska->done) |
4309 | 13 | ret = matroska_resync(matroska, matroska->resync_pos); | |
4310 | } | ||
4311 | |||
4312 | 29484 | return 0; | |
4313 | } | ||
4314 | |||
4315 | 55 | static int matroska_read_seek(AVFormatContext *s, int stream_index, | |
4316 | int64_t timestamp, int flags) | ||
4317 | { | ||
4318 | 55 | MatroskaDemuxContext *matroska = s->priv_data; | |
4319 | 55 | MatroskaTrack *tracks = NULL; | |
4320 | 55 | AVStream *st = s->streams[stream_index]; | |
4321 | 55 | FFStream *const sti = ffstream(st); | |
4322 | int i, index; | ||
4323 | |||
4324 | /* Parse the CUES now since we need the index data to seek. */ | ||
4325 |
2/2✓ Branch 0 taken 3 times.
✓ Branch 1 taken 52 times.
|
55 | if (matroska->cues_parsing_deferred > 0) { |
4326 | 3 | matroska->cues_parsing_deferred = 0; | |
4327 | 3 | matroska_parse_cues(matroska); | |
4328 | } | ||
4329 | |||
4330 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 55 times.
|
55 | if (!sti->nb_index_entries) |
4331 | ✗ | goto err; | |
4332 | 55 | timestamp = FFMAX(timestamp, sti->index_entries[0].timestamp); | |
4333 | |||
4334 |
2/2✓ Branch 1 taken 45 times.
✓ Branch 2 taken 10 times.
|
55 | if ((index = av_index_search_timestamp(st, timestamp, flags)) < 0 || |
4335 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 28 times.
|
45 | index == sti->nb_index_entries - 1) { |
4336 | 27 | matroska_reset_status(matroska, 0, sti->index_entries[sti->nb_index_entries - 1].pos); | |
4337 |
2/2✓ Branch 1 taken 285 times.
✓ Branch 2 taken 410 times.
|
695 | while ((index = av_index_search_timestamp(st, timestamp, flags)) < 0 || |
4338 |
2/2✓ Branch 0 taken 409 times.
✓ Branch 1 taken 1 times.
|
410 | index == sti->nb_index_entries - 1) { |
4339 | 694 | matroska_clear_queue(matroska); | |
4340 |
2/2✓ Branch 1 taken 26 times.
✓ Branch 2 taken 668 times.
|
694 | if (matroska_parse_cluster(matroska) < 0) |
4341 | 26 | break; | |
4342 | } | ||
4343 | } | ||
4344 | |||
4345 | 55 | matroska_clear_queue(matroska); | |
4346 |
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 && |
4347 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
|
3 | index == sti->nb_index_entries - 1)) |
4348 | 10 | goto err; | |
4349 | |||
4350 | 45 | tracks = matroska->tracks.elem; | |
4351 |
2/2✓ Branch 0 taken 69 times.
✓ Branch 1 taken 45 times.
|
114 | for (i = 0; i < matroska->tracks.nb_elem; i++) { |
4352 | 69 | tracks[i].audio.pkt_cnt = 0; | |
4353 | 69 | tracks[i].audio.sub_packet_cnt = 0; | |
4354 | 69 | tracks[i].audio.buf_timecode = AV_NOPTS_VALUE; | |
4355 | 69 | tracks[i].end_timecode = 0; | |
4356 | } | ||
4357 | |||
4358 | /* We seek to a level 1 element, so set the appropriate status. */ | ||
4359 | 45 | matroska_reset_status(matroska, 0, sti->index_entries[index].pos); | |
4360 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 45 times.
|
45 | if (flags & AVSEEK_FLAG_ANY) { |
4361 | ✗ | sti->skip_to_keyframe = 0; | |
4362 | ✗ | matroska->skip_to_timecode = timestamp; | |
4363 | } else { | ||
4364 | 45 | sti->skip_to_keyframe = 1; | |
4365 | 45 | matroska->skip_to_timecode = sti->index_entries[index].timestamp; | |
4366 | } | ||
4367 | 45 | matroska->skip_to_keyframe = 1; | |
4368 | 45 | matroska->done = 0; | |
4369 | 45 | avpriv_update_cur_dts(s, st, sti->index_entries[index].timestamp); | |
4370 | 45 | return 0; | |
4371 | 10 | err: | |
4372 | // slightly hackish but allows proper fallback to | ||
4373 | // the generic seeking code. | ||
4374 | 10 | matroska_reset_status(matroska, 0, -1); | |
4375 | 10 | matroska->resync_pos = -1; | |
4376 | 10 | matroska_clear_queue(matroska); | |
4377 | 10 | sti->skip_to_keyframe = | |
4378 | 10 | matroska->skip_to_keyframe = 0; | |
4379 | 10 | matroska->done = 0; | |
4380 | 10 | return -1; | |
4381 | } | ||
4382 | |||
4383 | 370 | static int matroska_read_close(AVFormatContext *s) | |
4384 | { | ||
4385 | 370 | MatroskaDemuxContext *matroska = s->priv_data; | |
4386 | 370 | MatroskaTrack *tracks = matroska->tracks.elem; | |
4387 | int n; | ||
4388 | |||
4389 | 370 | matroska_clear_queue(matroska); | |
4390 | |||
4391 |
2/2✓ Branch 0 taken 441 times.
✓ Branch 1 taken 370 times.
|
811 | for (n = 0; n < matroska->tracks.nb_elem; n++) |
4392 |
2/2✓ Branch 0 taken 84 times.
✓ Branch 1 taken 357 times.
|
441 | if (tracks[n].type == MATROSKA_TRACK_TYPE_AUDIO) |
4393 | 84 | av_freep(&tracks[n].audio.buf); | |
4394 | 370 | ebml_free(matroska_segment, matroska); | |
4395 | |||
4396 | 370 | return 0; | |
4397 | } | ||
4398 | |||
4399 | #if CONFIG_WEBM_DASH_MANIFEST_DEMUXER | ||
4400 | typedef struct { | ||
4401 | int64_t start_time_ns; | ||
4402 | int64_t end_time_ns; | ||
4403 | int64_t start_offset; | ||
4404 | int64_t end_offset; | ||
4405 | } CueDesc; | ||
4406 | |||
4407 | /* This function searches all the Cues and returns the CueDesc corresponding to | ||
4408 | * the timestamp ts. Returned CueDesc will be such that start_time_ns <= ts < | ||
4409 | * end_time_ns. All 4 fields will be set to -1 if ts >= file's duration or | ||
4410 | * if an error occurred. | ||
4411 | */ | ||
4412 | 4051 | static CueDesc get_cue_desc(AVFormatContext *s, int64_t ts, int64_t cues_start) { | |
4413 | 4051 | MatroskaDemuxContext *matroska = s->priv_data; | |
4414 | 4051 | FFStream *const sti = ffstream(s->streams[0]); | |
4415 | 4051 | AVIndexEntry *const index_entries = sti->index_entries; | |
4416 | 4051 | int nb_index_entries = sti->nb_index_entries; | |
4417 | CueDesc cue_desc; | ||
4418 | int i; | ||
4419 | |||
4420 |
2/2✓ Branch 0 taken 101 times.
✓ Branch 1 taken 3950 times.
|
4051 | if (ts >= (int64_t)(matroska->duration * matroska->time_scale)) |
4421 | 101 | return (CueDesc) {-1, -1, -1, -1}; | |
4422 |
2/2✓ Branch 0 taken 45235 times.
✓ Branch 1 taken 156 times.
|
45391 | for (i = 1; i < nb_index_entries; i++) { |
4423 |
1/2✓ Branch 0 taken 45235 times.
✗ Branch 1 not taken.
|
45235 | if (index_entries[i - 1].timestamp * matroska->time_scale <= ts && |
4424 |
2/2✓ Branch 0 taken 3794 times.
✓ Branch 1 taken 41441 times.
|
45235 | index_entries[i].timestamp * matroska->time_scale > ts) { |
4425 | 3794 | break; | |
4426 | } | ||
4427 | } | ||
4428 | 3950 | --i; | |
4429 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 3950 times.
|
3950 | if (index_entries[i].timestamp > matroska->duration) |
4430 | ✗ | return (CueDesc) {-1, -1, -1, -1}; | |
4431 | 3950 | cue_desc.start_time_ns = index_entries[i].timestamp * matroska->time_scale; | |
4432 | 3950 | cue_desc.start_offset = index_entries[i].pos - matroska->segment_start; | |
4433 |
2/2✓ Branch 0 taken 3794 times.
✓ Branch 1 taken 156 times.
|
3950 | if (i != nb_index_entries - 1) { |
4434 | 3794 | cue_desc.end_time_ns = index_entries[i + 1].timestamp * matroska->time_scale; | |
4435 | 3794 | cue_desc.end_offset = index_entries[i + 1].pos - matroska->segment_start; | |
4436 | } else { | ||
4437 | 156 | cue_desc.end_time_ns = matroska->duration * matroska->time_scale; | |
4438 | // FIXME: this needs special handling for files where Cues appear | ||
4439 | // before Clusters. the current logic assumes Cues appear after | ||
4440 | // Clusters. | ||
4441 | 156 | cue_desc.end_offset = cues_start - matroska->segment_start; | |
4442 | } | ||
4443 | 3950 | return cue_desc; | |
4444 | } | ||
4445 | |||
4446 | 10 | static int webm_clusters_start_with_keyframe(AVFormatContext *s) | |
4447 | { | ||
4448 | 10 | MatroskaDemuxContext *matroska = s->priv_data; | |
4449 | 10 | AVStream *const st = s->streams[0]; | |
4450 | 10 | FFStream *const sti = ffstream(st); | |
4451 | 10 | uint32_t id = matroska->current_id; | |
4452 | int64_t cluster_pos, before_pos; | ||
4453 | 10 | int index, rv = 1; | |
4454 | |||
4455 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (sti->nb_index_entries <= 0) |
4456 | ✗ | return 0; | |
4457 | |||
4458 | // seek to the first cluster using cues. | ||
4459 | 10 | index = av_index_search_timestamp(st, 0, 0); | |
4460 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (index < 0) |
4461 | ✗ | return 0; | |
4462 | 10 | cluster_pos = sti->index_entries[index].pos; | |
4463 | 10 | before_pos = avio_tell(s->pb); | |
4464 | 78 | while (1) { | |
4465 | uint64_t cluster_id, cluster_length; | ||
4466 | int read; | ||
4467 | AVPacket *pkt; | ||
4468 | 88 | avio_seek(s->pb, cluster_pos, SEEK_SET); | |
4469 | // read cluster id and length | ||
4470 | 88 | read = ebml_read_num(matroska, matroska->ctx->pb, 4, &cluster_id, 1); | |
4471 |
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 |
4472 | break; | ||
4473 | 79 | read = ebml_read_length(matroska, matroska->ctx->pb, &cluster_length); | |
4474 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 79 times.
|
79 | if (read < 0) |
4475 | ✗ | break; | |
4476 | |||
4477 | 79 | matroska_reset_status(matroska, 0, cluster_pos); | |
4478 | 79 | matroska_clear_queue(matroska); | |
4479 |
1/2✓ Branch 1 taken 79 times.
✗ Branch 2 not taken.
|
79 | if (matroska_parse_cluster(matroska) < 0 || |
4480 |
1/2✓ Branch 0 taken 79 times.
✗ Branch 1 not taken.
|
79 | !matroska->queue.head) { |
4481 | break; | ||
4482 | } | ||
4483 | 79 | pkt = &matroska->queue.head->pkt; | |
4484 | // 4 + read is the length of the cluster id and the cluster length field. | ||
4485 | 79 | cluster_pos += 4 + read + cluster_length; | |
4486 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 78 times.
|
79 | if (!(pkt->flags & AV_PKT_FLAG_KEY)) { |
4487 | 1 | rv = 0; | |
4488 | 1 | break; | |
4489 | } | ||
4490 | } | ||
4491 | |||
4492 | /* Restore the status after matroska_read_header: */ | ||
4493 | 10 | matroska_reset_status(matroska, id, before_pos); | |
4494 | |||
4495 | 10 | return rv; | |
4496 | } | ||
4497 | |||
4498 | 555 | static int buffer_size_after_time_downloaded(int64_t time_ns, double search_sec, int64_t bps, | |
4499 | double min_buffer, double* buffer, | ||
4500 | double* sec_to_download, AVFormatContext *s, | ||
4501 | int64_t cues_start) | ||
4502 | { | ||
4503 | 555 | double nano_seconds_per_second = 1000000000.0; | |
4504 | 555 | double time_sec = time_ns / nano_seconds_per_second; | |
4505 | 555 | int rv = 0; | |
4506 | 555 | int64_t time_to_search_ns = (int64_t)(search_sec * nano_seconds_per_second); | |
4507 | 555 | int64_t end_time_ns = time_ns + time_to_search_ns; | |
4508 | 555 | double sec_downloaded = 0.0; | |
4509 | 555 | CueDesc desc_curr = get_cue_desc(s, time_ns, cues_start); | |
4510 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 555 times.
|
555 | if (desc_curr.start_time_ns == -1) |
4511 | ✗ | return -1; | |
4512 | 555 | *sec_to_download = 0.0; | |
4513 | |||
4514 | // Check for non cue start time. | ||
4515 |
2/2✓ Branch 0 taken 513 times.
✓ Branch 1 taken 42 times.
|
555 | if (time_ns > desc_curr.start_time_ns) { |
4516 | 513 | int64_t cue_nano = desc_curr.end_time_ns - time_ns; | |
4517 | 513 | double percent = (double)(cue_nano) / (desc_curr.end_time_ns - desc_curr.start_time_ns); | |
4518 | 513 | double cueBytes = (desc_curr.end_offset - desc_curr.start_offset) * percent; | |
4519 | 513 | double timeToDownload = (cueBytes * 8.0) / bps; | |
4520 | |||
4521 | 513 | sec_downloaded += (cue_nano / nano_seconds_per_second) - timeToDownload; | |
4522 | 513 | *sec_to_download += timeToDownload; | |
4523 | |||
4524 | // Check if the search ends within the first cue. | ||
4525 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 513 times.
|
513 | if (desc_curr.end_time_ns >= end_time_ns) { |
4526 | ✗ | double desc_end_time_sec = desc_curr.end_time_ns / nano_seconds_per_second; | |
4527 | ✗ | double percent_to_sub = search_sec / (desc_end_time_sec - time_sec); | |
4528 | ✗ | sec_downloaded = percent_to_sub * sec_downloaded; | |
4529 | ✗ | *sec_to_download = percent_to_sub * *sec_to_download; | |
4530 | } | ||
4531 | |||
4532 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 509 times.
|
513 | if ((sec_downloaded + *buffer) <= min_buffer) { |
4533 | 4 | return 1; | |
4534 | } | ||
4535 | |||
4536 | // Get the next Cue. | ||
4537 | 509 | desc_curr = get_cue_desc(s, desc_curr.end_time_ns, cues_start); | |
4538 | } | ||
4539 | |||
4540 |
2/2✓ Branch 0 taken 2856 times.
✓ Branch 1 taken 100 times.
|
2956 | while (desc_curr.start_time_ns != -1) { |
4541 | 2856 | int64_t desc_bytes = desc_curr.end_offset - desc_curr.start_offset; | |
4542 | 2856 | int64_t desc_ns = desc_curr.end_time_ns - desc_curr.start_time_ns; | |
4543 | 2856 | double desc_sec = desc_ns / nano_seconds_per_second; | |
4544 | 2856 | double bits = (desc_bytes * 8.0); | |
4545 | 2856 | double time_to_download = bits / bps; | |
4546 | |||
4547 | 2856 | sec_downloaded += desc_sec - time_to_download; | |
4548 | 2856 | *sec_to_download += time_to_download; | |
4549 | |||
4550 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2856 times.
|
2856 | if (desc_curr.end_time_ns >= end_time_ns) { |
4551 | ✗ | double desc_end_time_sec = desc_curr.end_time_ns / nano_seconds_per_second; | |
4552 | ✗ | double percent_to_sub = search_sec / (desc_end_time_sec - time_sec); | |
4553 | ✗ | sec_downloaded = percent_to_sub * sec_downloaded; | |
4554 | ✗ | *sec_to_download = percent_to_sub * *sec_to_download; | |
4555 | |||
4556 | ✗ | if ((sec_downloaded + *buffer) <= min_buffer) | |
4557 | ✗ | rv = 1; | |
4558 | ✗ | break; | |
4559 | } | ||
4560 | |||
4561 |
2/2✓ Branch 0 taken 451 times.
✓ Branch 1 taken 2405 times.
|
2856 | if ((sec_downloaded + *buffer) <= min_buffer) { |
4562 | 451 | rv = 1; | |
4563 | 451 | break; | |
4564 | } | ||
4565 | |||
4566 | 2405 | desc_curr = get_cue_desc(s, desc_curr.end_time_ns, cues_start); | |
4567 | } | ||
4568 | 551 | *buffer = *buffer + sec_downloaded; | |
4569 | 551 | return rv; | |
4570 | } | ||
4571 | |||
4572 | /* This function computes the bandwidth of the WebM file with the help of | ||
4573 | * buffer_size_after_time_downloaded() function. Both of these functions are | ||
4574 | * adapted from WebM Tools project and are adapted to work with FFmpeg's | ||
4575 | * Matroska parsing mechanism. | ||
4576 | * | ||
4577 | * Returns the bandwidth of the file on success; -1 on error. | ||
4578 | * */ | ||
4579 | 10 | static int64_t webm_dash_manifest_compute_bandwidth(AVFormatContext *s, int64_t cues_start) | |
4580 | { | ||
4581 | 10 | MatroskaDemuxContext *matroska = s->priv_data; | |
4582 | 10 | AVStream *st = s->streams[0]; | |
4583 | 10 | FFStream *const sti = ffstream(st); | |
4584 | 10 | double bandwidth = 0.0; | |
4585 | |||
4586 |
2/2✓ Branch 0 taken 101 times.
✓ Branch 1 taken 10 times.
|
111 | for (int i = 0; i < sti->nb_index_entries; i++) { |
4587 | 101 | int64_t prebuffer_ns = 1000000000; | |
4588 | 101 | int64_t time_ns = sti->index_entries[i].timestamp * matroska->time_scale; | |
4589 | 101 | double nano_seconds_per_second = 1000000000.0; | |
4590 | int64_t prebuffered_ns; | ||
4591 | 101 | double prebuffer_bytes = 0.0; | |
4592 | 101 | int64_t temp_prebuffer_ns = prebuffer_ns; | |
4593 | int64_t pre_bytes, pre_ns; | ||
4594 | double pre_sec, prebuffer, bits_per_second; | ||
4595 | 101 | CueDesc desc_beg = get_cue_desc(s, time_ns, cues_start); | |
4596 | // Start with the first Cue. | ||
4597 | 101 | CueDesc desc_end = desc_beg; | |
4598 | |||
4599 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 101 times.
|
101 | if (time_ns > INT64_MAX - prebuffer_ns) |
4600 | ✗ | return -1; | |
4601 | 101 | prebuffered_ns = time_ns + prebuffer_ns; | |
4602 | |||
4603 | // Figure out how much data we have downloaded for the prebuffer. This will | ||
4604 | // be used later to adjust the bits per sample to try. | ||
4605 |
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) { |
4606 | // Prebuffered the entire Cue. | ||
4607 | 21 | prebuffer_bytes += desc_end.end_offset - desc_end.start_offset; | |
4608 | 21 | temp_prebuffer_ns -= desc_end.end_time_ns - desc_end.start_time_ns; | |
4609 | 21 | desc_end = get_cue_desc(s, desc_end.end_time_ns, cues_start); | |
4610 | } | ||
4611 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 100 times.
|
101 | if (desc_end.start_time_ns == -1) { |
4612 | // The prebuffer is larger than the duration. | ||
4613 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (matroska->duration * matroska->time_scale >= prebuffered_ns) |
4614 | ✗ | return -1; | |
4615 | 1 | bits_per_second = 0.0; | |
4616 | } else { | ||
4617 | // The prebuffer ends in the last Cue. Estimate how much data was | ||
4618 | // prebuffered. | ||
4619 | 100 | pre_bytes = desc_end.end_offset - desc_end.start_offset; | |
4620 |
1/2✓ Branch 0 taken 100 times.
✗ Branch 1 not taken.
|
100 | if (desc_end.end_time_ns <= desc_end.start_time_ns || |
4621 |
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) |
4622 | ✗ | return -1; | |
4623 | 100 | pre_ns = desc_end.end_time_ns - desc_end.start_time_ns; | |
4624 | 100 | pre_sec = pre_ns / nano_seconds_per_second; | |
4625 | 100 | prebuffer_bytes += | |
4626 | 100 | pre_bytes * ((temp_prebuffer_ns / nano_seconds_per_second) / pre_sec); | |
4627 | |||
4628 | 100 | prebuffer = prebuffer_ns / nano_seconds_per_second; | |
4629 | |||
4630 | // Set this to 0.0 in case our prebuffer buffers the entire video. | ||
4631 | 100 | bits_per_second = 0.0; | |
4632 | do { | ||
4633 | 560 | int64_t desc_bytes = desc_end.end_offset - desc_beg.start_offset; | |
4634 | 560 | int64_t desc_ns = desc_end.end_time_ns - desc_beg.start_time_ns; | |
4635 | double desc_sec, calc_bits_per_second, percent, mod_bits_per_second; | ||
4636 |
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) |
4637 | ✗ | return -1; | |
4638 | |||
4639 | 560 | desc_sec = desc_ns / nano_seconds_per_second; | |
4640 | 560 | calc_bits_per_second = (desc_bytes * 8) / desc_sec; | |
4641 | |||
4642 | // Drop the bps by the percentage of bytes buffered. | ||
4643 | 560 | percent = (desc_bytes - prebuffer_bytes) / desc_bytes; | |
4644 | 560 | mod_bits_per_second = calc_bits_per_second * percent; | |
4645 | |||
4646 |
2/2✓ Branch 0 taken 555 times.
✓ Branch 1 taken 5 times.
|
560 | if (prebuffer < desc_sec) { |
4647 | 555 | double search_sec = | |
4648 | 555 | (double)(matroska->duration * matroska->time_scale) / nano_seconds_per_second; | |
4649 | |||
4650 | // Add 1 so the bits per second should be a little bit greater than file | ||
4651 | // datarate. | ||
4652 | 555 | int64_t bps = (int64_t)(mod_bits_per_second) + 1; | |
4653 | 555 | const double min_buffer = 0.0; | |
4654 | 555 | double buffer = prebuffer; | |
4655 | 555 | double sec_to_download = 0.0; | |
4656 | |||
4657 | 555 | int rv = buffer_size_after_time_downloaded(prebuffered_ns, search_sec, bps, | |
4658 | min_buffer, &buffer, &sec_to_download, | ||
4659 | s, cues_start); | ||
4660 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 555 times.
|
555 | if (rv < 0) { |
4661 | ✗ | return -1; | |
4662 |
2/2✓ Branch 0 taken 100 times.
✓ Branch 1 taken 455 times.
|
555 | } else if (rv == 0) { |
4663 | 100 | bits_per_second = (double)(bps); | |
4664 | 100 | break; | |
4665 | } | ||
4666 | } | ||
4667 | |||
4668 | 460 | desc_end = get_cue_desc(s, desc_end.end_time_ns, cues_start); | |
4669 |
1/2✓ Branch 0 taken 460 times.
✗ Branch 1 not taken.
|
460 | } while (desc_end.start_time_ns != -1); |
4670 | } | ||
4671 |
2/2✓ Branch 0 taken 38 times.
✓ Branch 1 taken 63 times.
|
101 | if (bandwidth < bits_per_second) bandwidth = bits_per_second; |
4672 | } | ||
4673 | 10 | return (int64_t)bandwidth; | |
4674 | } | ||
4675 | |||
4676 | 10 | static int webm_dash_manifest_cues(AVFormatContext *s, int64_t init_range) | |
4677 | { | ||
4678 | 10 | MatroskaDemuxContext *matroska = s->priv_data; | |
4679 | 10 | EbmlList *seekhead_list = &matroska->seekhead; | |
4680 | 10 | MatroskaSeekhead *seekhead = seekhead_list->elem; | |
4681 | 10 | AVStream *const st = s->streams[0]; | |
4682 | 10 | FFStream *const sti = ffstream(st); | |
4683 | AVBPrint bprint; | ||
4684 | char *buf; | ||
4685 | 10 | int64_t cues_start = -1, cues_end = -1, before_pos, bandwidth; | |
4686 | int i; | ||
4687 | int ret; | ||
4688 | |||
4689 | // determine cues start and end positions | ||
4690 |
1/2✓ Branch 0 taken 34 times.
✗ Branch 1 not taken.
|
34 | for (i = 0; i < seekhead_list->nb_elem; i++) |
4691 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 24 times.
|
34 | if (seekhead[i].id == MATROSKA_ID_CUES) |
4692 | 10 | break; | |
4693 | |||
4694 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (i >= seekhead_list->nb_elem) return -1; |
4695 | |||
4696 | 10 | before_pos = avio_tell(matroska->ctx->pb); | |
4697 | 10 | cues_start = seekhead[i].pos + matroska->segment_start; | |
4698 |
1/2✓ Branch 1 taken 10 times.
✗ Branch 2 not taken.
|
10 | if (avio_seek(matroska->ctx->pb, cues_start, SEEK_SET) == cues_start) { |
4699 | // cues_end is computed as cues_start + cues_length + length of the | ||
4700 | // Cues element ID (i.e. 4) + EBML length of the Cues element. | ||
4701 | // cues_end is inclusive and the above sum is reduced by 1. | ||
4702 | uint64_t cues_length, cues_id; | ||
4703 | int bytes_read; | ||
4704 | 10 | bytes_read = ebml_read_num (matroska, matroska->ctx->pb, 4, &cues_id, 1); | |
4705 |
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)) |
4706 | ✗ | return bytes_read < 0 ? bytes_read : AVERROR_INVALIDDATA; | |
4707 | 10 | bytes_read = ebml_read_length(matroska, matroska->ctx->pb, &cues_length); | |
4708 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (bytes_read < 0) |
4709 | ✗ | return bytes_read; | |
4710 | 10 | cues_end = cues_start + 4 + bytes_read + cues_length - 1; | |
4711 | } | ||
4712 | 10 | avio_seek(matroska->ctx->pb, before_pos, SEEK_SET); | |
4713 |
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; |
4714 | |||
4715 | // parse the cues | ||
4716 | 10 | matroska_parse_cues(matroska); | |
4717 | |||
4718 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (!sti->nb_index_entries) |
4719 | ✗ | return AVERROR_INVALIDDATA; | |
4720 | |||
4721 | // cues start | ||
4722 | 10 | av_dict_set_int(&s->streams[0]->metadata, CUES_START, cues_start, 0); | |
4723 | |||
4724 | // cues end | ||
4725 | 10 | av_dict_set_int(&s->streams[0]->metadata, CUES_END, cues_end, 0); | |
4726 | |||
4727 | // if the file has cues at the start, fix up the init range so that | ||
4728 | // it does not include it | ||
4729 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (cues_start <= init_range) |
4730 | ✗ | av_dict_set_int(&s->streams[0]->metadata, INITIALIZATION_RANGE, cues_start - 1, 0); | |
4731 | |||
4732 | // bandwidth | ||
4733 | 10 | bandwidth = webm_dash_manifest_compute_bandwidth(s, cues_start); | |
4734 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (bandwidth < 0) return -1; |
4735 | 10 | av_dict_set_int(&s->streams[0]->metadata, BANDWIDTH, bandwidth, 0); | |
4736 | |||
4737 | // check if all clusters start with key frames | ||
4738 | 10 | av_dict_set_int(&s->streams[0]->metadata, CLUSTER_KEYFRAME, webm_clusters_start_with_keyframe(s), 0); | |
4739 | |||
4740 | // Store cue point timestamps as a comma separated list | ||
4741 | // for checking subsegment alignment in the muxer. | ||
4742 | 10 | av_bprint_init(&bprint, 0, AV_BPRINT_SIZE_UNLIMITED); | |
4743 |
2/2✓ Branch 0 taken 101 times.
✓ Branch 1 taken 10 times.
|
111 | for (int i = 0; i < sti->nb_index_entries; i++) |
4744 | 101 | av_bprintf(&bprint, "%" PRId64",", sti->index_entries[i].timestamp); | |
4745 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
|
10 | if (!av_bprint_is_complete(&bprint)) { |
4746 | ✗ | av_bprint_finalize(&bprint, NULL); | |
4747 | ✗ | return AVERROR(ENOMEM); | |
4748 | } | ||
4749 | // Remove the trailing ',' | ||
4750 | 10 | bprint.str[--bprint.len] = '\0'; | |
4751 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 10 times.
|
10 | if ((ret = av_bprint_finalize(&bprint, &buf)) < 0) |
4752 | ✗ | return ret; | |
4753 | 10 | av_dict_set(&s->streams[0]->metadata, CUE_TIMESTAMPS, | |
4754 | buf, AV_DICT_DONT_STRDUP_VAL); | ||
4755 | |||
4756 | 10 | return 0; | |
4757 | } | ||
4758 | |||
4759 | 14 | static int webm_dash_manifest_read_header(AVFormatContext *s) | |
4760 | { | ||
4761 | char *buf; | ||
4762 | 14 | int ret = matroska_read_header(s); | |
4763 | int64_t init_range; | ||
4764 | MatroskaTrack *tracks; | ||
4765 | 14 | MatroskaDemuxContext *matroska = s->priv_data; | |
4766 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 14 times.
|
14 | if (ret) { |
4767 | ✗ | av_log(s, AV_LOG_ERROR, "Failed to read file headers\n"); | |
4768 | ✗ | return -1; | |
4769 | } | ||
4770 |
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) { |
4771 | ✗ | av_log(s, AV_LOG_ERROR, "No track found\n"); | |
4772 | ✗ | return AVERROR_INVALIDDATA; | |
4773 | } | ||
4774 | |||
4775 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
|
14 | if (!matroska->is_live) { |
4776 | 10 | buf = av_asprintf("%g", matroska->duration); | |
4777 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (!buf) |
4778 | ✗ | return AVERROR(ENOMEM); | |
4779 | 10 | av_dict_set(&s->streams[0]->metadata, DURATION, | |
4780 | buf, AV_DICT_DONT_STRDUP_VAL); | ||
4781 | |||
4782 | // initialization range | ||
4783 | // 5 is the offset of Cluster ID. | ||
4784 | 10 | init_range = avio_tell(s->pb) - 5; | |
4785 | 10 | av_dict_set_int(&s->streams[0]->metadata, INITIALIZATION_RANGE, init_range, 0); | |
4786 | } | ||
4787 | |||
4788 | // basename of the file | ||
4789 | 14 | buf = strrchr(s->url, '/'); | |
4790 |
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); |
4791 | |||
4792 | // track number | ||
4793 | 14 | tracks = matroska->tracks.elem; | |
4794 | 14 | av_dict_set_int(&s->streams[0]->metadata, TRACK_NUMBER, tracks[0].num, 0); | |
4795 | |||
4796 | // parse the cues and populate Cue related fields | ||
4797 |
2/2✓ Branch 0 taken 10 times.
✓ Branch 1 taken 4 times.
|
14 | if (!matroska->is_live) { |
4798 | 10 | ret = webm_dash_manifest_cues(s, init_range); | |
4799 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 10 times.
|
10 | if (ret < 0) { |
4800 | ✗ | av_log(s, AV_LOG_ERROR, "Error parsing Cues\n"); | |
4801 | ✗ | return ret; | |
4802 | } | ||
4803 | } | ||
4804 | |||
4805 | // use the bandwidth from the command line if it was provided | ||
4806 |
2/2✓ Branch 0 taken 2 times.
✓ Branch 1 taken 12 times.
|
14 | if (matroska->bandwidth > 0) { |
4807 | 2 | av_dict_set_int(&s->streams[0]->metadata, BANDWIDTH, | |
4808 | 2 | matroska->bandwidth, 0); | |
4809 | } | ||
4810 | 14 | return 0; | |
4811 | } | ||
4812 | |||
4813 | 28 | static int webm_dash_manifest_read_packet(AVFormatContext *s, AVPacket *pkt) | |
4814 | { | ||
4815 | 28 | return AVERROR_EOF; | |
4816 | } | ||
4817 | |||
4818 | #define OFFSET(x) offsetof(MatroskaDemuxContext, x) | ||
4819 | static const AVOption options[] = { | ||
4820 | { "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 }, | ||
4821 | { "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 }, | ||
4822 | { NULL }, | ||
4823 | }; | ||
4824 | |||
4825 | static const AVClass webm_dash_class = { | ||
4826 | .class_name = "WebM DASH Manifest demuxer", | ||
4827 | .item_name = av_default_item_name, | ||
4828 | .option = options, | ||
4829 | .version = LIBAVUTIL_VERSION_INT, | ||
4830 | }; | ||
4831 | |||
4832 | const FFInputFormat ff_webm_dash_manifest_demuxer = { | ||
4833 | .p.name = "webm_dash_manifest", | ||
4834 | .p.long_name = NULL_IF_CONFIG_SMALL("WebM DASH Manifest"), | ||
4835 | .p.priv_class = &webm_dash_class, | ||
4836 | .priv_data_size = sizeof(MatroskaDemuxContext), | ||
4837 | .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP, | ||
4838 | .read_header = webm_dash_manifest_read_header, | ||
4839 | .read_packet = webm_dash_manifest_read_packet, | ||
4840 | .read_close = matroska_read_close, | ||
4841 | }; | ||
4842 | #endif | ||
4843 | |||
4844 | const FFInputFormat ff_matroska_demuxer = { | ||
4845 | .p.name = "matroska,webm", | ||
4846 | .p.long_name = NULL_IF_CONFIG_SMALL("Matroska / WebM"), | ||
4847 | .p.extensions = "mkv,mk3d,mka,mks,webm", | ||
4848 | .p.mime_type = "audio/webm,audio/x-matroska,video/webm,video/x-matroska", | ||
4849 | .priv_data_size = sizeof(MatroskaDemuxContext), | ||
4850 | .flags_internal = FF_INFMT_FLAG_INIT_CLEANUP, | ||
4851 | .read_probe = matroska_probe, | ||
4852 | .read_header = matroska_read_header, | ||
4853 | .read_packet = matroska_read_packet, | ||
4854 | .read_close = matroska_read_close, | ||
4855 | .read_seek = matroska_read_seek, | ||
4856 | }; | ||
4857 |