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