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