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