From patchwork Sun Nov 6 15:08:47 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve Lhomme X-Patchwork-Id: 39204 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a21:999a:b0:a4:2148:650a with SMTP id ve26csp1600004pzb; Sun, 6 Nov 2022 07:10:33 -0800 (PST) X-Google-Smtp-Source: AMsMyM7uVwMF/gw+bbBjceHM6SRlQK8e8s+zztSlrkfsq3UmyBR8LBuzI+Ps+AwJNXMrR08X4VcK X-Received: by 2002:a17:906:846b:b0:7ad:88f8:469a with SMTP id hx11-20020a170906846b00b007ad88f8469amr43547786ejc.519.1667747433165; Sun, 06 Nov 2022 07:10:33 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1667747433; cv=none; d=google.com; s=arc-20160816; b=iIPHI54sEpEU4QL5yXMhTXAxADclO8JBSFT38+icLEg0WMYYb56riauDYijMVMN6OX ZP2Dyyy8GuR9us1lh6vMIqH73H8rAvU05r6qSpZIhhGVGzVnoHghuNWWs7EzQFbfwP9e pfZGci5lXbcDkpliV1fFiloLzRQFx7t+jZbFoMmF1Ln+aWEuTJDdU3Inh6k/9DvZBeFY 7W+uxww4DNsdrd603vRo2e81JJkuwYsMfAOPUquP7NIGzOfBpWrSciamGl4V4X5rSlN4 HG7epTkKDK5tMmwas/OnlCi1Oo1YEGbwYNLxmDyt5GXPPsNrA4EAtpkywCjQHD/ETxjp wovQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:reply-to:list-subscribe :list-help:list-post:list-archive:list-unsubscribe:list-id :precedence:subject:mime-version:references:in-reply-to:message-id :date:to:from:delivered-to; bh=PQVPOyjbG8TXdXAVCiCGwlryq3r4C4JahavG6R8QwCQ=; b=Y/MN0oOLX0jgpQXmyB57qrUjKWjkbRWg5AT6K/CfM9EPFbjHDfI7KQZBSpCJn3M7tZ 7erSFvBIef6YULY2nAGKt5K7IuC8rAc+ixxNitaHBVILWhlOvdhsmaevojQKrvo8CYzU 44Z/202mbN6Z5d6daHeMYQLurRkz5nKBw6LpqRlDKP7+y5cgwJgfE88P9ATp0Y9pEler pIk69JWXntZw8KXYdkXfLEhYYEOvGgS8eU2tZXr2s5TvMPaTzZY5fAbMBKYyzs0p2HKJ 0wKYenoWo8ufxOtNv7iE2T5VpotjgMNxqkqcPDeaB6Ou6FECunB2e9sYvOK9QzFkaKf4 UVZQ== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id di19-20020a170906731300b0078200e81b92si7495112ejc.758.2022.11.06.07.10.32; Sun, 06 Nov 2022 07:10:33 -0800 (PST) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 6EA1668B937; Sun, 6 Nov 2022 17:09:16 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mout-p-102.mailbox.org (mout-p-102.mailbox.org [80.241.56.152]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 6E76B68B773 for ; Sun, 6 Nov 2022 17:09:01 +0200 (EET) Received: from smtp2.mailbox.org (smtp2.mailbox.org [10.196.197.2]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-384) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mout-p-102.mailbox.org (Postfix) with ESMTPS id 4N4ySC0m2nz9sT8 for ; Sun, 6 Nov 2022 16:08:59 +0100 (CET) From: Steve Lhomme To: ffmpeg-devel@ffmpeg.org Date: Sun, 6 Nov 2022 16:08:47 +0100 Message-Id: <20221106150854.9528-6-robux4@ycbcr.xyz> In-Reply-To: <20221106150854.9528-1-robux4@ycbcr.xyz> References: <20221106150854.9528-1-robux4@ycbcr.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 05/12] avformat/matroskadec: move the elements semantic in a separate file X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: fPWKgvDZiz+C So the file can be generated from the Matroska Schema. The EbmlSyntax structures are not shared between files. matroska_segments and matroska_cluster_enter also have their size predefined. No functional changes. --- libavformat/Makefile | 2 +- libavformat/matroskadec.c | 712 +------------------------------------- libavformat/matroskasem.c | 397 +++++++++++++++++++++ libavformat/matroskasem.h | 394 +++++++++++++++++++++ 4 files changed, 793 insertions(+), 712 deletions(-) create mode 100644 libavformat/matroskasem.c create mode 100644 libavformat/matroskasem.h diff --git a/libavformat/Makefile b/libavformat/Makefile index d7f198bf39..982fcc326f 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -331,7 +331,7 @@ OBJS-$(CONFIG_LVF_DEMUXER) += lvfdec.o OBJS-$(CONFIG_LXF_DEMUXER) += lxfdec.o OBJS-$(CONFIG_M4V_DEMUXER) += m4vdec.o rawdec.o OBJS-$(CONFIG_M4V_MUXER) += rawenc.o -OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroska.o \ +OBJS-$(CONFIG_MATROSKA_DEMUXER) += matroskadec.o matroskasem.o matroska.o \ flac_picture.o rmsipr.o \ oggparsevorbis.o vorbiscomment.o \ qtpalette.o replaygain.o dovi_isom.o diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 5a083acd75..9475ff4674 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -53,7 +53,6 @@ #include "libavcodec/bytestream.h" #include "libavcodec/flac.h" #include "libavcodec/mpeg4audio.h" -#include "libavcodec/packet_internal.h" #include "avformat.h" #include "avio_internal.h" @@ -62,6 +61,7 @@ #include "internal.h" #include "isom.h" #include "matroska.h" +#include "matroskasem.h" #include "oggdec.h" /* For ff_codec_get_id(). */ #include "riff.h" @@ -88,716 +88,6 @@ * to this many bytes of unknown data for the * SKIP_THRESHOLD check. */ -typedef enum { - EBML_NONE, - EBML_UINT, - EBML_SINT, - EBML_FLOAT, - EBML_STR, - EBML_UTF8, - EBML_BIN, - EBML_NEST, - EBML_LEVEL1, - EBML_STOP, - EBML_TYPE_COUNT -} EbmlType; - -typedef struct CountedElement { - union { - uint64_t u; - int64_t i; - double f; - char *s; - } el; - unsigned count; -} CountedElement; - -typedef const struct EbmlSyntax { - uint32_t id; - uint8_t type; - uint8_t is_counted; - size_t list_elem_size; - size_t data_offset; - union { - int64_t i; - uint64_t u; - double f; - const char *s; - const struct EbmlSyntax *n; - } def; -} EbmlSyntax; - -typedef struct EbmlList { - int nb_elem; - unsigned int alloc_elem_size; - void *elem; -} EbmlList; - -typedef struct EbmlBin { - int size; - AVBufferRef *buf; - uint8_t *data; - int64_t pos; -} EbmlBin; - -typedef struct Ebml { - uint64_t version; - uint64_t max_size; - uint64_t id_length; - char *doctype; - uint64_t doctype_version; -} Ebml; - -typedef struct MatroskaTrackCompression { - uint64_t algo; - EbmlBin settings; -} MatroskaTrackCompression; - -typedef struct MatroskaTrackEncryption { - uint64_t algo; - EbmlBin key_id; -} MatroskaTrackEncryption; - -typedef struct MatroskaTrackEncoding { - uint64_t scope; - uint64_t type; - MatroskaTrackCompression compression; - MatroskaTrackEncryption encryption; -} MatroskaTrackEncoding; - -typedef struct MatroskaMasteringMeta { - double r_x; - double r_y; - double g_x; - double g_y; - double b_x; - double b_y; - double white_x; - double white_y; - double max_luminance; - CountedElement min_luminance; -} MatroskaMasteringMeta; - -typedef struct MatroskaTrackVideoColor { - uint64_t matrix_coefficients; - uint64_t bits_per_channel; - uint64_t chroma_sub_horz; - uint64_t chroma_sub_vert; - uint64_t cb_sub_horz; - uint64_t cb_sub_vert; - uint64_t chroma_siting_horz; - uint64_t chroma_siting_vert; - uint64_t range; - uint64_t transfer_characteristics; - uint64_t primaries; - uint64_t max_cll; - uint64_t max_fall; - MatroskaMasteringMeta mastering_meta; -} MatroskaTrackVideoColor; - -typedef struct MatroskaTrackVideoProjection { - uint64_t type; - EbmlBin private; - double yaw; - double pitch; - double roll; -} MatroskaTrackVideoProjection; - -typedef struct MatroskaTrackVideo { - double frame_rate; - uint64_t display_width; - uint64_t display_height; - uint64_t pixel_width; - uint64_t pixel_height; - EbmlBin color_space; - uint64_t display_unit; - uint64_t interlaced; - uint64_t field_order; - uint64_t stereo_mode; - uint64_t alpha_mode; - EbmlList color; - MatroskaTrackVideoProjection projection; -} MatroskaTrackVideo; - -typedef struct MatroskaTrackAudio { - double samplerate; - double out_samplerate; - uint64_t bitdepth; - uint64_t channels; - - /* real audio header (extracted from extradata) */ - int coded_framesize; - int sub_packet_h; - int frame_size; - int sub_packet_size; - int sub_packet_cnt; - int pkt_cnt; - uint64_t buf_timecode; - uint8_t *buf; -} MatroskaTrackAudio; - -typedef struct MatroskaTrackPlane { - uint64_t uid; - uint64_t type; -} MatroskaTrackPlane; - -typedef struct MatroskaTrackOperation { - EbmlList combine_planes; -} MatroskaTrackOperation; - -typedef struct MatroskaBlockAdditionMapping { - uint64_t value; - char *name; - uint64_t type; - EbmlBin extradata; -} MatroskaBlockAdditionMapping; - -typedef struct MatroskaTrack { - uint64_t num; - uint64_t uid; - uint64_t type; - char *name; - char *codec_id; - EbmlBin codec_priv; - char *language; - double time_scale; - uint64_t default_duration; - uint64_t flag_default; - uint64_t flag_forced; - uint64_t flag_comment; - uint64_t flag_hearingimpaired; - uint64_t flag_visualimpaired; - uint64_t flag_textdescriptions; - CountedElement flag_original; - uint64_t seek_preroll; - MatroskaTrackVideo video; - MatroskaTrackAudio audio; - MatroskaTrackOperation operation; - EbmlList encodings; - uint64_t codec_delay; - uint64_t codec_delay_in_track_tb; - - AVStream *stream; - int64_t end_timecode; - int ms_compat; - int needs_decoding; - uint64_t max_block_additional_id; - EbmlList block_addition_mappings; - - uint32_t palette[AVPALETTE_COUNT]; - int has_palette; -} MatroskaTrack; - -typedef struct MatroskaAttachment { - uint64_t uid; - char *filename; - char *description; - char *mime; - EbmlBin bin; - - AVStream *stream; -} MatroskaAttachment; - -typedef struct MatroskaChapter { - uint64_t start; - uint64_t end; - uint64_t uid; - char *title; - - AVChapter *chapter; -} MatroskaChapter; - -typedef struct MatroskaIndexPos { - uint64_t track; - uint64_t pos; -} MatroskaIndexPos; - -typedef struct MatroskaIndex { - uint64_t time; - EbmlList pos; -} MatroskaIndex; - -typedef struct MatroskaTag { - char *name; - char *string; - char *lang; - uint64_t def; - EbmlList sub; -} MatroskaTag; - -typedef struct MatroskaTagTarget { - char *type; - uint64_t typevalue; - uint64_t trackuid; - uint64_t chapteruid; - uint64_t attachuid; -} MatroskaTagTarget; - -typedef struct MatroskaTags { - MatroskaTagTarget target; - EbmlList tag; -} MatroskaTags; - -typedef struct MatroskaSeekhead { - uint64_t id; - uint64_t pos; -} MatroskaSeekhead; - -typedef struct MatroskaLevel { - uint64_t start; - uint64_t length; -} MatroskaLevel; - -typedef struct MatroskaBlock { - uint64_t duration; - CountedElement reference; - uint64_t non_simple; - EbmlBin bin; - uint64_t additional_id; - EbmlBin additional; - int64_t discard_padding; -} MatroskaBlock; - -typedef struct MatroskaCluster { - MatroskaBlock block; - uint64_t timecode; - int64_t pos; -} MatroskaCluster; - -typedef struct MatroskaLevel1Element { - int64_t pos; - uint32_t id; - int parsed; -} MatroskaLevel1Element; - -typedef struct MatroskaDemuxContext { - const AVClass *class; - AVFormatContext *ctx; - - /* EBML stuff */ - MatroskaLevel levels[EBML_MAX_DEPTH]; - int num_levels; - uint32_t current_id; - int64_t resync_pos; - int unknown_count; - - uint64_t time_scale; - double duration; - char *title; - char *muxingapp; - EbmlBin date_utc; - EbmlList tracks; - EbmlList attachments; - EbmlList chapters; - EbmlList index; - EbmlList tags; - EbmlList seekhead; - - /* byte position of the segment inside the stream */ - int64_t segment_start; - - /* This packet coincides with FFFormatContext.parse_pkt - * and is not owned by us. */ - AVPacket *pkt; - - /* the packet queue */ - PacketList queue; - - int done; - - /* What to skip before effectively reading a packet. */ - int skip_to_keyframe; - uint64_t skip_to_timecode; - - /* File has a CUES element, but we defer parsing until it is needed. */ - int cues_parsing_deferred; - - /* Level1 elements and whether they were read yet */ - MatroskaLevel1Element level1_elems[64]; - int num_level1_elems; - - MatroskaCluster current_cluster; - - /* WebM DASH Manifest live flag */ - int is_live; - - /* Bandwidth value for WebM DASH Manifest */ - int bandwidth; -} MatroskaDemuxContext; - -#define CHILD_OF(parent) { .def = { .n = parent } } - -// The following forward declarations need their size because -// a tentative definition with internal linkage must not be an -// incomplete type (6.7.2 in C90, 6.9.2 in C99). -// Removing the sizes breaks MSVC. -static EbmlSyntax ebml_syntax[3], matroska_segment[9], matroska_track_video_color[15], matroska_track_video[19], - matroska_track[33], matroska_track_encoding[6], matroska_track_encodings[2], - matroska_track_combine_planes[2], matroska_track_operation[2], matroska_block_addition_mapping[5], matroska_tracks[2], - matroska_attachments[2], matroska_chapter_entry[9], matroska_chapter[6], matroska_chapters[2], - matroska_index_entry[3], matroska_index[2], matroska_tag[3], matroska_tags[2], matroska_seekhead[2], - matroska_blockadditions[2], matroska_blockgroup[8], matroska_cluster_parsing[8]; - -static EbmlSyntax ebml_header[] = { - { EBML_ID_EBMLREADVERSION, EBML_UINT, 0, 0, offsetof(Ebml, version), { .u = EBML_VERSION } }, - { EBML_ID_EBMLMAXSIZELENGTH, EBML_UINT, 0, 0, offsetof(Ebml, max_size), { .u = 8 } }, - { EBML_ID_EBMLMAXIDLENGTH, EBML_UINT, 0, 0, offsetof(Ebml, id_length), { .u = 4 } }, - { EBML_ID_DOCTYPE, EBML_STR, 0, 0, offsetof(Ebml, doctype), { .s = "(none)" } }, - { EBML_ID_DOCTYPEREADVERSION, EBML_UINT, 0, 0, offsetof(Ebml, doctype_version), { .u = 1 } }, - { EBML_ID_EBMLVERSION, EBML_NONE }, - { EBML_ID_DOCTYPEVERSION, EBML_NONE }, - CHILD_OF(ebml_syntax) -}; - -static EbmlSyntax ebml_syntax[] = { - { EBML_ID_HEADER, EBML_NEST, 0, 0, 0, { .n = ebml_header } }, - { MATROSKA_ID_SEGMENT, EBML_STOP }, - { 0 } -}; - -static EbmlSyntax matroska_info[] = { - { MATROSKA_ID_TIMECODESCALE, EBML_UINT, 0, 0, offsetof(MatroskaDemuxContext, time_scale), { .u = 1000000 } }, - { MATROSKA_ID_DURATION, EBML_FLOAT, 0, 0, offsetof(MatroskaDemuxContext, duration) }, - { MATROSKA_ID_TITLE, EBML_UTF8, 0, 0, offsetof(MatroskaDemuxContext, title) }, - { MATROSKA_ID_WRITINGAPP, EBML_NONE }, - { MATROSKA_ID_MUXINGAPP, EBML_UTF8, 0, 0, offsetof(MatroskaDemuxContext, muxingapp) }, - { MATROSKA_ID_DATEUTC, EBML_BIN, 0, 0, offsetof(MatroskaDemuxContext, date_utc) }, - { MATROSKA_ID_SEGMENTUID, EBML_NONE }, - CHILD_OF(matroska_segment) -}; - -static EbmlSyntax matroska_mastering_meta[] = { - { MATROSKA_ID_VIDEOCOLOR_RX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, r_x) }, - { MATROSKA_ID_VIDEOCOLOR_RY, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, r_y) }, - { MATROSKA_ID_VIDEOCOLOR_GX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, g_x) }, - { MATROSKA_ID_VIDEOCOLOR_GY, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, g_y) }, - { MATROSKA_ID_VIDEOCOLOR_BX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, b_x) }, - { MATROSKA_ID_VIDEOCOLOR_BY, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, b_y) }, - { MATROSKA_ID_VIDEOCOLOR_WHITEX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, white_x) }, - { MATROSKA_ID_VIDEOCOLOR_WHITEY, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, white_y) }, - { MATROSKA_ID_VIDEOCOLOR_LUMINANCEMIN, EBML_FLOAT, 1, 0, offsetof(MatroskaMasteringMeta, min_luminance) }, - { MATROSKA_ID_VIDEOCOLOR_LUMINANCEMAX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, max_luminance) }, - CHILD_OF(matroska_track_video_color) -}; - -static EbmlSyntax matroska_track_video_color[] = { - { MATROSKA_ID_VIDEOCOLORMATRIXCOEFF, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, matrix_coefficients), { .u = AVCOL_SPC_UNSPECIFIED } }, - { MATROSKA_ID_VIDEOCOLORBITSPERCHANNEL, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, bits_per_channel) }, - { MATROSKA_ID_VIDEOCOLORCHROMASUBHORZ, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, chroma_sub_horz) }, - { MATROSKA_ID_VIDEOCOLORCHROMASUBVERT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, chroma_sub_vert) }, - { MATROSKA_ID_VIDEOCOLORCBSUBHORZ, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, cb_sub_horz) }, - { MATROSKA_ID_VIDEOCOLORCBSUBVERT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, cb_sub_vert) }, - { MATROSKA_ID_VIDEOCOLORCHROMASITINGHORZ, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, chroma_siting_horz), { .u = MATROSKA_COLOUR_CHROMASITINGHORZ_UNDETERMINED } }, - { MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, chroma_siting_vert), { .u = MATROSKA_COLOUR_CHROMASITINGVERT_UNDETERMINED } }, - { MATROSKA_ID_VIDEOCOLORRANGE, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, range), { .u = AVCOL_RANGE_UNSPECIFIED } }, - { MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, transfer_characteristics), { .u = AVCOL_TRC_UNSPECIFIED } }, - { MATROSKA_ID_VIDEOCOLORPRIMARIES, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, primaries), { .u = AVCOL_PRI_UNSPECIFIED } }, - { MATROSKA_ID_VIDEOCOLORMAXCLL, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, max_cll) }, - { MATROSKA_ID_VIDEOCOLORMAXFALL, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, max_fall) }, - { MATROSKA_ID_VIDEOCOLORMASTERINGMETA, EBML_NEST, 0, 0, offsetof(MatroskaTrackVideoColor, mastering_meta), { .n = matroska_mastering_meta } }, - CHILD_OF(matroska_track_video) -}; - -static EbmlSyntax matroska_track_video_projection[] = { - { MATROSKA_ID_VIDEOPROJECTIONTYPE, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoProjection, type), { .u = MATROSKA_VIDEO_PROJECTION_TYPE_RECTANGULAR } }, - { MATROSKA_ID_VIDEOPROJECTIONPRIVATE, EBML_BIN, 0, 0, offsetof(MatroskaTrackVideoProjection, private) }, - { MATROSKA_ID_VIDEOPROJECTIONPOSEYAW, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackVideoProjection, yaw), { .f = 0.0 } }, - { MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackVideoProjection, pitch), { .f = 0.0 } }, - { MATROSKA_ID_VIDEOPROJECTIONPOSEROLL, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackVideoProjection, roll), { .f = 0.0 } }, - CHILD_OF(matroska_track_video) -}; - -static EbmlSyntax matroska_track_video[] = { - { MATROSKA_ID_VIDEOFRAMERATE, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackVideo, frame_rate) }, - { MATROSKA_ID_VIDEODISPLAYWIDTH, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, display_width), { .u=-1 } }, - { MATROSKA_ID_VIDEODISPLAYHEIGHT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, display_height), { .u=-1 } }, - { MATROSKA_ID_VIDEOPIXELWIDTH, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, pixel_width) }, - { MATROSKA_ID_VIDEOPIXELHEIGHT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, pixel_height) }, - { MATROSKA_ID_VIDEOCOLORSPACE, EBML_BIN, 0, 0, offsetof(MatroskaTrackVideo, color_space) }, - { MATROSKA_ID_VIDEOALPHAMODE, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, alpha_mode) }, - { MATROSKA_ID_VIDEOCOLOR, EBML_NEST, 0, sizeof(MatroskaTrackVideoColor), offsetof(MatroskaTrackVideo, color), { .n = matroska_track_video_color } }, - { MATROSKA_ID_VIDEOPROJECTION, EBML_NEST, 0, 0, offsetof(MatroskaTrackVideo, projection), { .n = matroska_track_video_projection } }, - { MATROSKA_ID_VIDEOPIXELCROPB, EBML_NONE }, - { MATROSKA_ID_VIDEOPIXELCROPT, EBML_NONE }, - { MATROSKA_ID_VIDEOPIXELCROPL, EBML_NONE }, - { MATROSKA_ID_VIDEOPIXELCROPR, EBML_NONE }, - { MATROSKA_ID_VIDEODISPLAYUNIT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, display_unit), { .u= MATROSKA_VIDEO_DISPLAYUNIT_PIXELS } }, - { MATROSKA_ID_VIDEOFLAGINTERLACED, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, interlaced), { .u = MATROSKA_VIDEO_INTERLACE_FLAG_UNDETERMINED } }, - { MATROSKA_ID_VIDEOFIELDORDER, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, field_order), { .u = MATROSKA_VIDEO_FIELDORDER_UNDETERMINED } }, - { MATROSKA_ID_VIDEOSTEREOMODE, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, stereo_mode), { .u = MATROSKA_VIDEO_STEREOMODE_TYPE_NB } }, - { MATROSKA_ID_VIDEOASPECTRATIO, EBML_NONE }, - CHILD_OF(matroska_track) -}; - -static EbmlSyntax matroska_track_audio[] = { - { MATROSKA_ID_AUDIOSAMPLINGFREQ, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackAudio, samplerate), { .f = 8000.0 } }, - { MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackAudio, out_samplerate) }, - { MATROSKA_ID_AUDIOBITDEPTH, EBML_UINT, 0, 0, offsetof(MatroskaTrackAudio, bitdepth) }, - { MATROSKA_ID_AUDIOCHANNELS, EBML_UINT, 0, 0, offsetof(MatroskaTrackAudio, channels), { .u = 1 } }, - CHILD_OF(matroska_track) -}; - -static EbmlSyntax matroska_track_encoding_compression[] = { - { MATROSKA_ID_ENCODINGCOMPALGO, EBML_UINT, 0, 0, offsetof(MatroskaTrackCompression, algo), { .u = MATROSKA_TRACK_ENCODING_COMP_ZLIB } }, - { MATROSKA_ID_ENCODINGCOMPSETTINGS, EBML_BIN, 0, 0, offsetof(MatroskaTrackCompression, settings) }, - CHILD_OF(matroska_track_encoding) -}; - -static EbmlSyntax matroska_track_encoding_encryption[] = { - { MATROSKA_ID_ENCODINGENCALGO, EBML_UINT, 0, 0, offsetof(MatroskaTrackEncryption,algo) }, - { MATROSKA_ID_ENCODINGENCKEYID, EBML_BIN, 0, 0, offsetof(MatroskaTrackEncryption,key_id) }, - { MATROSKA_ID_ENCODINGENCAESSETTINGS, EBML_NONE }, - { MATROSKA_ID_ENCODINGSIGALGO, EBML_NONE }, - { MATROSKA_ID_ENCODINGSIGHASHALGO, EBML_NONE }, - { MATROSKA_ID_ENCODINGSIGKEYID, EBML_NONE }, - { MATROSKA_ID_ENCODINGSIGNATURE, EBML_NONE }, - CHILD_OF(matroska_track_encoding) -}; -static EbmlSyntax matroska_track_encoding[] = { - { MATROSKA_ID_ENCODINGSCOPE, EBML_UINT, 0, 0, offsetof(MatroskaTrackEncoding, scope), { .u = 1 } }, - { MATROSKA_ID_ENCODINGTYPE, EBML_UINT, 0, 0, offsetof(MatroskaTrackEncoding, type) }, - { MATROSKA_ID_ENCODINGCOMPRESSION, EBML_NEST, 0, 0, offsetof(MatroskaTrackEncoding, compression), { .n = matroska_track_encoding_compression } }, - { MATROSKA_ID_ENCODINGENCRYPTION, EBML_NEST, 0, 0, offsetof(MatroskaTrackEncoding, encryption), { .n = matroska_track_encoding_encryption } }, - { MATROSKA_ID_ENCODINGORDER, EBML_NONE }, - CHILD_OF(matroska_track_encodings) -}; - -static EbmlSyntax matroska_track_encodings[] = { - { MATROSKA_ID_TRACKCONTENTENCODING, EBML_NEST, 0, sizeof(MatroskaTrackEncoding), offsetof(MatroskaTrack, encodings), { .n = matroska_track_encoding } }, - CHILD_OF(matroska_track) -}; - -static EbmlSyntax matroska_track_plane[] = { - { MATROSKA_ID_TRACKPLANEUID, EBML_UINT, 0, 0, offsetof(MatroskaTrackPlane,uid) }, - { MATROSKA_ID_TRACKPLANETYPE, EBML_UINT, 0, 0, offsetof(MatroskaTrackPlane,type) }, - CHILD_OF(matroska_track_combine_planes) -}; - -static EbmlSyntax matroska_track_combine_planes[] = { - { MATROSKA_ID_TRACKPLANE, EBML_NEST, 0, sizeof(MatroskaTrackPlane), offsetof(MatroskaTrackOperation,combine_planes), {.n = matroska_track_plane} }, - CHILD_OF(matroska_track_operation) -}; - -static EbmlSyntax matroska_track_operation[] = { - { MATROSKA_ID_TRACKCOMBINEPLANES, EBML_NEST, 0, 0, 0, {.n = matroska_track_combine_planes} }, - CHILD_OF(matroska_track) -}; - -static EbmlSyntax matroska_block_addition_mapping[] = { - { MATROSKA_ID_BLKADDIDVALUE, EBML_UINT, 0, 0, offsetof(MatroskaBlockAdditionMapping, value) }, - { MATROSKA_ID_BLKADDIDNAME, EBML_STR, 0, 0, offsetof(MatroskaBlockAdditionMapping, name) }, - { MATROSKA_ID_BLKADDIDTYPE, EBML_UINT, 0, 0, offsetof(MatroskaBlockAdditionMapping, type) }, - { MATROSKA_ID_BLKADDIDEXTRADATA, EBML_BIN, 0, 0, offsetof(MatroskaBlockAdditionMapping, extradata) }, - CHILD_OF(matroska_track) -}; - -static EbmlSyntax matroska_track[] = { - { MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, 0, offsetof(MatroskaTrack, num) }, - { MATROSKA_ID_TRACKNAME, EBML_UTF8, 0, 0, offsetof(MatroskaTrack, name) }, - { MATROSKA_ID_TRACKUID, EBML_UINT, 0, 0, offsetof(MatroskaTrack, uid) }, - { MATROSKA_ID_TRACKTYPE, EBML_UINT, 0, 0, offsetof(MatroskaTrack, type) }, - { MATROSKA_ID_CODECID, EBML_STR, 0, 0, offsetof(MatroskaTrack, codec_id) }, - { MATROSKA_ID_CODECPRIVATE, EBML_BIN, 0, 0, offsetof(MatroskaTrack, codec_priv) }, - { MATROSKA_ID_CODECDELAY, EBML_UINT, 0, 0, offsetof(MatroskaTrack, codec_delay) }, - { MATROSKA_ID_TRACKLANGUAGE, EBML_STR, 0, 0, offsetof(MatroskaTrack, language), { .s = "eng" } }, - { MATROSKA_ID_TRACKDEFAULTDURATION, EBML_UINT, 0, 0, offsetof(MatroskaTrack, default_duration) }, - { MATROSKA_ID_TRACKTIMECODESCALE, EBML_FLOAT, 0, 0, offsetof(MatroskaTrack, time_scale), { .f = 1.0 } }, - { MATROSKA_ID_TRACKFLAGCOMMENTARY, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_comment) }, - { MATROSKA_ID_TRACKFLAGDEFAULT, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_default), { .u = 1 } }, - { MATROSKA_ID_TRACKFLAGFORCED, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_forced) }, - { MATROSKA_ID_TRACKFLAGHEARINGIMPAIRED, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_hearingimpaired) }, - { MATROSKA_ID_TRACKFLAGVISUALIMPAIRED, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_visualimpaired) }, - { MATROSKA_ID_TRACKFLAGTEXTDESCRIPTIONS, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_textdescriptions) }, - { MATROSKA_ID_TRACKFLAGORIGINAL, EBML_UINT, 1, 0, offsetof(MatroskaTrack, flag_original) }, - { MATROSKA_ID_TRACKVIDEO, EBML_NEST, 0, 0, offsetof(MatroskaTrack, video), { .n = matroska_track_video } }, - { MATROSKA_ID_TRACKAUDIO, EBML_NEST, 0, 0, offsetof(MatroskaTrack, audio), { .n = matroska_track_audio } }, - { MATROSKA_ID_TRACKOPERATION, EBML_NEST, 0, 0, offsetof(MatroskaTrack, operation), { .n = matroska_track_operation } }, - { MATROSKA_ID_TRACKCONTENTENCODINGS, EBML_NEST, 0, 0, 0, { .n = matroska_track_encodings } }, - { MATROSKA_ID_TRACKMAXBLKADDID, EBML_UINT, 0, 0, offsetof(MatroskaTrack, max_block_additional_id) }, - { MATROSKA_ID_TRACKBLKADDMAPPING, EBML_NEST, 0, sizeof(MatroskaBlockAdditionMapping), offsetof(MatroskaTrack, block_addition_mappings), { .n = matroska_block_addition_mapping } }, - { MATROSKA_ID_SEEKPREROLL, EBML_UINT, 0, 0, offsetof(MatroskaTrack, seek_preroll) }, - { MATROSKA_ID_TRACKFLAGENABLED, EBML_NONE }, - { MATROSKA_ID_TRACKFLAGLACING, EBML_NONE }, - { MATROSKA_ID_CODECNAME, EBML_NONE }, - { MATROSKA_ID_CODECDECODEALL, EBML_NONE }, - { MATROSKA_ID_CODECINFOURL, EBML_NONE }, - { MATROSKA_ID_CODECDOWNLOADURL, EBML_NONE }, - { MATROSKA_ID_TRACKMINCACHE, EBML_NONE }, - { MATROSKA_ID_TRACKMAXCACHE, EBML_NONE }, - CHILD_OF(matroska_tracks) -}; - -static EbmlSyntax matroska_tracks[] = { - { MATROSKA_ID_TRACKENTRY, EBML_NEST, 0, sizeof(MatroskaTrack), offsetof(MatroskaDemuxContext, tracks), { .n = matroska_track } }, - CHILD_OF(matroska_segment) -}; - -static EbmlSyntax matroska_attachment[] = { - { MATROSKA_ID_FILEUID, EBML_UINT, 0, 0, offsetof(MatroskaAttachment, uid) }, - { MATROSKA_ID_FILENAME, EBML_UTF8, 0, 0, offsetof(MatroskaAttachment, filename) }, - { MATROSKA_ID_FILEMIMETYPE, EBML_STR, 0, 0, offsetof(MatroskaAttachment, mime) }, - { MATROSKA_ID_FILEDATA, EBML_BIN, 0, 0, offsetof(MatroskaAttachment, bin) }, - { MATROSKA_ID_FILEDESC, EBML_UTF8, 0, 0, offsetof(MatroskaAttachment, description) }, - CHILD_OF(matroska_attachments) -}; - -static EbmlSyntax matroska_attachments[] = { - { MATROSKA_ID_ATTACHEDFILE, EBML_NEST, 0, sizeof(MatroskaAttachment), offsetof(MatroskaDemuxContext, attachments), { .n = matroska_attachment } }, - CHILD_OF(matroska_segment) -}; - -static EbmlSyntax matroska_chapter_display[] = { - { MATROSKA_ID_CHAPSTRING, EBML_UTF8, 0, 0, offsetof(MatroskaChapter, title) }, - { MATROSKA_ID_CHAPLANG, EBML_NONE }, - { MATROSKA_ID_CHAPCOUNTRY, EBML_NONE }, - CHILD_OF(matroska_chapter_entry) -}; - -static EbmlSyntax matroska_chapter_entry[] = { - { MATROSKA_ID_CHAPTERTIMESTART, EBML_UINT, 0, 0, offsetof(MatroskaChapter, start), { .u = AV_NOPTS_VALUE } }, - { MATROSKA_ID_CHAPTERTIMEEND, EBML_UINT, 0, 0, offsetof(MatroskaChapter, end), { .u = AV_NOPTS_VALUE } }, - { MATROSKA_ID_CHAPTERUID, EBML_UINT, 0, 0, offsetof(MatroskaChapter, uid) }, - { MATROSKA_ID_CHAPTERDISPLAY, EBML_NEST, 0, 0, 0, { .n = matroska_chapter_display } }, - { MATROSKA_ID_CHAPTERFLAGHIDDEN, EBML_NONE }, - { MATROSKA_ID_CHAPTERFLAGENABLED, EBML_NONE }, - { MATROSKA_ID_CHAPTERPHYSEQUIV, EBML_NONE }, - { MATROSKA_ID_CHAPTERATOM, EBML_NONE }, - CHILD_OF(matroska_chapter) -}; - -static EbmlSyntax matroska_chapter[] = { - { MATROSKA_ID_CHAPTERATOM, EBML_NEST, 0, sizeof(MatroskaChapter), offsetof(MatroskaDemuxContext, chapters), { .n = matroska_chapter_entry } }, - { MATROSKA_ID_EDITIONUID, EBML_NONE }, - { MATROSKA_ID_EDITIONFLAGHIDDEN, EBML_NONE }, - { MATROSKA_ID_EDITIONFLAGDEFAULT, EBML_NONE }, - { MATROSKA_ID_EDITIONFLAGORDERED, EBML_NONE }, - CHILD_OF(matroska_chapters) -}; - -static EbmlSyntax matroska_chapters[] = { - { MATROSKA_ID_EDITIONENTRY, EBML_NEST, 0, 0, 0, { .n = matroska_chapter } }, - CHILD_OF(matroska_segment) -}; - -static EbmlSyntax matroska_index_pos[] = { - { MATROSKA_ID_CUETRACK, EBML_UINT, 0, 0, offsetof(MatroskaIndexPos, track) }, - { MATROSKA_ID_CUECLUSTERPOSITION, EBML_UINT, 0, 0, offsetof(MatroskaIndexPos, pos) }, - { MATROSKA_ID_CUERELATIVEPOSITION,EBML_NONE }, - { MATROSKA_ID_CUEDURATION, EBML_NONE }, - { MATROSKA_ID_CUEBLOCKNUMBER, EBML_NONE }, - CHILD_OF(matroska_index_entry) -}; - -static EbmlSyntax matroska_index_entry[] = { - { MATROSKA_ID_CUETIME, EBML_UINT, 0, 0, offsetof(MatroskaIndex, time) }, - { MATROSKA_ID_CUETRACKPOSITION, EBML_NEST, 0, sizeof(MatroskaIndexPos), offsetof(MatroskaIndex, pos), { .n = matroska_index_pos } }, - CHILD_OF(matroska_index) -}; - -static EbmlSyntax matroska_index[] = { - { MATROSKA_ID_POINTENTRY, EBML_NEST, 0, sizeof(MatroskaIndex), offsetof(MatroskaDemuxContext, index), { .n = matroska_index_entry } }, - CHILD_OF(matroska_segment) -}; - -static EbmlSyntax matroska_simpletag[] = { - { MATROSKA_ID_TAGNAME, EBML_UTF8, 0, 0, offsetof(MatroskaTag, name) }, - { MATROSKA_ID_TAGSTRING, EBML_UTF8, 0, 0, offsetof(MatroskaTag, string) }, - { MATROSKA_ID_TAGLANG, EBML_STR, 0, 0, offsetof(MatroskaTag, lang), { .s = "und" } }, - { MATROSKA_ID_TAGDEFAULT, EBML_UINT, 0, 0, offsetof(MatroskaTag, def), { .u = 1 } }, - { MATROSKA_ID_TAGDEFAULT_BUG, EBML_UINT, 0, 0, offsetof(MatroskaTag, def), { .u = 1 } }, - { MATROSKA_ID_SIMPLETAG, EBML_NEST, 0, sizeof(MatroskaTag), offsetof(MatroskaTag, sub), { .n = matroska_simpletag } }, - CHILD_OF(matroska_tag) -}; - -static EbmlSyntax matroska_tagtargets[] = { - { MATROSKA_ID_TAGTARGETS_TYPE, EBML_STR, 0, 0, offsetof(MatroskaTagTarget, type) }, - { MATROSKA_ID_TAGTARGETS_TYPEVALUE, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, typevalue), { .u = 50 } }, - { MATROSKA_ID_TAGTARGETS_TRACKUID, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, trackuid) }, - { MATROSKA_ID_TAGTARGETS_CHAPTERUID, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, chapteruid) }, - { MATROSKA_ID_TAGTARGETS_ATTACHUID, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, attachuid) }, - CHILD_OF(matroska_tag) -}; - -static EbmlSyntax matroska_tag[] = { - { MATROSKA_ID_SIMPLETAG, EBML_NEST, 0, sizeof(MatroskaTag), offsetof(MatroskaTags, tag), { .n = matroska_simpletag } }, - { MATROSKA_ID_TAGTARGETS, EBML_NEST, 0, 0, offsetof(MatroskaTags, target), { .n = matroska_tagtargets } }, - CHILD_OF(matroska_tags) -}; - -static EbmlSyntax matroska_tags[] = { - { MATROSKA_ID_TAG, EBML_NEST, 0, sizeof(MatroskaTags), offsetof(MatroskaDemuxContext, tags), { .n = matroska_tag } }, - CHILD_OF(matroska_segment) -}; - -static EbmlSyntax matroska_seekhead_entry[] = { - { MATROSKA_ID_SEEKID, EBML_UINT, 0, 0, offsetof(MatroskaSeekhead, id) }, - { MATROSKA_ID_SEEKPOSITION, EBML_UINT, 0, 0, offsetof(MatroskaSeekhead, pos), { .u = -1 } }, - CHILD_OF(matroska_seekhead) -}; - -static EbmlSyntax matroska_seekhead[] = { - { MATROSKA_ID_SEEKENTRY, EBML_NEST, 0, sizeof(MatroskaSeekhead), offsetof(MatroskaDemuxContext, seekhead), { .n = matroska_seekhead_entry } }, - CHILD_OF(matroska_segment) -}; - -static EbmlSyntax matroska_segment[] = { - { MATROSKA_ID_CLUSTER, EBML_STOP }, - { MATROSKA_ID_INFO, EBML_LEVEL1, 0, 0, 0, { .n = matroska_info } }, - { MATROSKA_ID_TRACKS, EBML_LEVEL1, 0, 0, 0, { .n = matroska_tracks } }, - { MATROSKA_ID_ATTACHMENTS, EBML_LEVEL1, 0, 0, 0, { .n = matroska_attachments } }, - { MATROSKA_ID_CHAPTERS, EBML_LEVEL1, 0, 0, 0, { .n = matroska_chapters } }, - { MATROSKA_ID_CUES, EBML_LEVEL1, 0, 0, 0, { .n = matroska_index } }, - { MATROSKA_ID_TAGS, EBML_LEVEL1, 0, 0, 0, { .n = matroska_tags } }, - { MATROSKA_ID_SEEKHEAD, EBML_LEVEL1, 0, 0, 0, { .n = matroska_seekhead } }, - { 0 } /* We don't want to go back to level 0, so don't add the parent. */ -}; - -static EbmlSyntax matroska_segments[] = { - { MATROSKA_ID_SEGMENT, EBML_NEST, 0, 0, 0, { .n = matroska_segment } }, - { 0 } -}; - -static EbmlSyntax matroska_blockmore[] = { - { MATROSKA_ID_BLOCKADDID, EBML_UINT, 0, 0, offsetof(MatroskaBlock,additional_id), { .u = 1 } }, - { MATROSKA_ID_BLOCKADDITIONAL, EBML_BIN, 0, 0, offsetof(MatroskaBlock,additional) }, - CHILD_OF(matroska_blockadditions) -}; - -static EbmlSyntax matroska_blockadditions[] = { - { MATROSKA_ID_BLOCKMORE, EBML_NEST, 0, 0, 0, {.n = matroska_blockmore} }, - CHILD_OF(matroska_blockgroup) -}; - -static EbmlSyntax matroska_blockgroup[] = { - { MATROSKA_ID_BLOCK, EBML_BIN, 0, 0, offsetof(MatroskaBlock, bin) }, - { MATROSKA_ID_BLOCKADDITIONS, EBML_NEST, 0, 0, 0, { .n = matroska_blockadditions} }, - { MATROSKA_ID_BLOCKDURATION, EBML_UINT, 0, 0, offsetof(MatroskaBlock, duration) }, - { MATROSKA_ID_DISCARDPADDING, EBML_SINT, 0, 0, offsetof(MatroskaBlock, discard_padding) }, - { MATROSKA_ID_BLOCKREFERENCE, EBML_SINT, 1, 0, offsetof(MatroskaBlock, reference) }, - { MATROSKA_ID_CODECSTATE, EBML_NONE }, - { 1, EBML_UINT, 0, 0, offsetof(MatroskaBlock, non_simple), { .u = 1 } }, - CHILD_OF(matroska_cluster_parsing) -}; - -// The following array contains SimpleBlock and BlockGroup twice -// in order to reuse the other values for matroska_cluster_enter. -static EbmlSyntax matroska_cluster_parsing[] = { - { MATROSKA_ID_SIMPLEBLOCK, EBML_BIN, 0, 0, offsetof(MatroskaBlock, bin) }, - { MATROSKA_ID_BLOCKGROUP, EBML_NEST, 0, 0, 0, { .n = matroska_blockgroup } }, - { MATROSKA_ID_CLUSTERTIMECODE, EBML_UINT, 0, 0, offsetof(MatroskaCluster, timecode) }, - { MATROSKA_ID_SIMPLEBLOCK, EBML_STOP }, - { MATROSKA_ID_BLOCKGROUP, EBML_STOP }, - { MATROSKA_ID_CLUSTERPOSITION, EBML_NONE }, - { MATROSKA_ID_CLUSTERPREVSIZE, EBML_NONE }, - CHILD_OF(matroska_segment) -}; - -static EbmlSyntax matroska_cluster_enter[] = { - { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, 0, { .n = &matroska_cluster_parsing[2] } }, - { 0 } -}; -#undef CHILD_OF - static const CodecMime mkv_image_mime_tags[] = { {"image/gif" , AV_CODEC_ID_GIF}, {"image/jpeg" , AV_CODEC_ID_MJPEG}, diff --git a/libavformat/matroskasem.c b/libavformat/matroskasem.c new file mode 100644 index 0000000000..978d7f0281 --- /dev/null +++ b/libavformat/matroskasem.c @@ -0,0 +1,397 @@ +/* + * Matroska file semantic definition + * Copyright (c) 2003-2022 The FFmpeg Project + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Matroska file semantic element definitions + * @author Ronald Bultje + * @author with a little help from Moritz Bunkus + * @author totally reworked by Aurelien Jacobs + * @author Split from decoder by Steve Lhomme + * @see specs available on the Matroska project page: http://www.matroska.org/ + */ + +#include "config.h" + +#include + +#include "matroskasem.h" + +#define CHILD_OF(parent) { .def = { .n = parent } } + +static EbmlSyntax ebml_header[] = { + { EBML_ID_EBMLREADVERSION, EBML_UINT, 0, 0, offsetof(Ebml, version), { .u = EBML_VERSION } }, + { EBML_ID_EBMLMAXSIZELENGTH, EBML_UINT, 0, 0, offsetof(Ebml, max_size), { .u = 8 } }, + { EBML_ID_EBMLMAXIDLENGTH, EBML_UINT, 0, 0, offsetof(Ebml, id_length), { .u = 4 } }, + { EBML_ID_DOCTYPE, EBML_STR, 0, 0, offsetof(Ebml, doctype), { .s = "(none)" } }, + { EBML_ID_DOCTYPEREADVERSION, EBML_UINT, 0, 0, offsetof(Ebml, doctype_version), { .u = 1 } }, + { EBML_ID_EBMLVERSION, EBML_NONE }, + { EBML_ID_DOCTYPEVERSION, EBML_NONE }, + CHILD_OF(ebml_syntax) +}; + +EbmlSyntax ebml_syntax[] = { + { EBML_ID_HEADER, EBML_NEST, 0, 0, 0, { .n = ebml_header } }, + { MATROSKA_ID_SEGMENT, EBML_STOP }, + { 0 } +}; + +static EbmlSyntax matroska_info[] = { + { MATROSKA_ID_TIMECODESCALE, EBML_UINT, 0, 0, offsetof(MatroskaDemuxContext, time_scale), { .u = 1000000 } }, + { MATROSKA_ID_DURATION, EBML_FLOAT, 0, 0, offsetof(MatroskaDemuxContext, duration) }, + { MATROSKA_ID_TITLE, EBML_UTF8, 0, 0, offsetof(MatroskaDemuxContext, title) }, + { MATROSKA_ID_WRITINGAPP, EBML_NONE }, + { MATROSKA_ID_MUXINGAPP, EBML_UTF8, 0, 0, offsetof(MatroskaDemuxContext, muxingapp) }, + { MATROSKA_ID_DATEUTC, EBML_BIN, 0, 0, offsetof(MatroskaDemuxContext, date_utc) }, + { MATROSKA_ID_SEGMENTUID, EBML_NONE }, + CHILD_OF(matroska_segment) +}; + +static EbmlSyntax matroska_mastering_meta[] = { + { MATROSKA_ID_VIDEOCOLOR_RX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, r_x) }, + { MATROSKA_ID_VIDEOCOLOR_RY, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, r_y) }, + { MATROSKA_ID_VIDEOCOLOR_GX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, g_x) }, + { MATROSKA_ID_VIDEOCOLOR_GY, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, g_y) }, + { MATROSKA_ID_VIDEOCOLOR_BX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, b_x) }, + { MATROSKA_ID_VIDEOCOLOR_BY, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, b_y) }, + { MATROSKA_ID_VIDEOCOLOR_WHITEX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, white_x) }, + { MATROSKA_ID_VIDEOCOLOR_WHITEY, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, white_y) }, + { MATROSKA_ID_VIDEOCOLOR_LUMINANCEMIN, EBML_FLOAT, 1, 0, offsetof(MatroskaMasteringMeta, min_luminance) }, + { MATROSKA_ID_VIDEOCOLOR_LUMINANCEMAX, EBML_FLOAT, 0, 0, offsetof(MatroskaMasteringMeta, max_luminance) }, + CHILD_OF(matroska_track_video_color) +}; + +EbmlSyntax matroska_track_video_color[] = { + { MATROSKA_ID_VIDEOCOLORMATRIXCOEFF, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, matrix_coefficients), { .u = AVCOL_SPC_UNSPECIFIED } }, + { MATROSKA_ID_VIDEOCOLORBITSPERCHANNEL, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, bits_per_channel) }, + { MATROSKA_ID_VIDEOCOLORCHROMASUBHORZ, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, chroma_sub_horz) }, + { MATROSKA_ID_VIDEOCOLORCHROMASUBVERT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, chroma_sub_vert) }, + { MATROSKA_ID_VIDEOCOLORCBSUBHORZ, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, cb_sub_horz) }, + { MATROSKA_ID_VIDEOCOLORCBSUBVERT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, cb_sub_vert) }, + { MATROSKA_ID_VIDEOCOLORCHROMASITINGHORZ, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, chroma_siting_horz), { .u = MATROSKA_COLOUR_CHROMASITINGHORZ_UNDETERMINED } }, + { MATROSKA_ID_VIDEOCOLORCHROMASITINGVERT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, chroma_siting_vert), { .u = MATROSKA_COLOUR_CHROMASITINGVERT_UNDETERMINED } }, + { MATROSKA_ID_VIDEOCOLORRANGE, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, range), { .u = AVCOL_RANGE_UNSPECIFIED } }, + { MATROSKA_ID_VIDEOCOLORTRANSFERCHARACTERISTICS, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, transfer_characteristics), { .u = AVCOL_TRC_UNSPECIFIED } }, + { MATROSKA_ID_VIDEOCOLORPRIMARIES, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, primaries), { .u = AVCOL_PRI_UNSPECIFIED } }, + { MATROSKA_ID_VIDEOCOLORMAXCLL, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, max_cll) }, + { MATROSKA_ID_VIDEOCOLORMAXFALL, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoColor, max_fall) }, + { MATROSKA_ID_VIDEOCOLORMASTERINGMETA, EBML_NEST, 0, 0, offsetof(MatroskaTrackVideoColor, mastering_meta), { .n = matroska_mastering_meta } }, + CHILD_OF(matroska_track_video) +}; + +static EbmlSyntax matroska_track_video_projection[] = { + { MATROSKA_ID_VIDEOPROJECTIONTYPE, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideoProjection, type), { .u = MATROSKA_VIDEO_PROJECTION_TYPE_RECTANGULAR } }, + { MATROSKA_ID_VIDEOPROJECTIONPRIVATE, EBML_BIN, 0, 0, offsetof(MatroskaTrackVideoProjection, private) }, + { MATROSKA_ID_VIDEOPROJECTIONPOSEYAW, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackVideoProjection, yaw), { .f = 0.0 } }, + { MATROSKA_ID_VIDEOPROJECTIONPOSEPITCH, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackVideoProjection, pitch), { .f = 0.0 } }, + { MATROSKA_ID_VIDEOPROJECTIONPOSEROLL, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackVideoProjection, roll), { .f = 0.0 } }, + CHILD_OF(matroska_track_video) +}; + +EbmlSyntax matroska_track_video[] = { + { MATROSKA_ID_VIDEOFRAMERATE, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackVideo, frame_rate) }, + { MATROSKA_ID_VIDEODISPLAYWIDTH, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, display_width), { .u=-1 } }, + { MATROSKA_ID_VIDEODISPLAYHEIGHT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, display_height), { .u=-1 } }, + { MATROSKA_ID_VIDEOPIXELWIDTH, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, pixel_width) }, + { MATROSKA_ID_VIDEOPIXELHEIGHT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, pixel_height) }, + { MATROSKA_ID_VIDEOCOLORSPACE, EBML_BIN, 0, 0, offsetof(MatroskaTrackVideo, color_space) }, + { MATROSKA_ID_VIDEOALPHAMODE, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, alpha_mode) }, + { MATROSKA_ID_VIDEOCOLOR, EBML_NEST, 0, sizeof(MatroskaTrackVideoColor), offsetof(MatroskaTrackVideo, color), { .n = matroska_track_video_color } }, + { MATROSKA_ID_VIDEOPROJECTION, EBML_NEST, 0, 0, offsetof(MatroskaTrackVideo, projection), { .n = matroska_track_video_projection } }, + { MATROSKA_ID_VIDEOPIXELCROPB, EBML_NONE }, + { MATROSKA_ID_VIDEOPIXELCROPT, EBML_NONE }, + { MATROSKA_ID_VIDEOPIXELCROPL, EBML_NONE }, + { MATROSKA_ID_VIDEOPIXELCROPR, EBML_NONE }, + { MATROSKA_ID_VIDEODISPLAYUNIT, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, display_unit), { .u= MATROSKA_VIDEO_DISPLAYUNIT_PIXELS } }, + { MATROSKA_ID_VIDEOFLAGINTERLACED, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, interlaced), { .u = MATROSKA_VIDEO_INTERLACE_FLAG_UNDETERMINED } }, + { MATROSKA_ID_VIDEOFIELDORDER, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, field_order), { .u = MATROSKA_VIDEO_FIELDORDER_UNDETERMINED } }, + { MATROSKA_ID_VIDEOSTEREOMODE, EBML_UINT, 0, 0, offsetof(MatroskaTrackVideo, stereo_mode), { .u = MATROSKA_VIDEO_STEREOMODE_TYPE_NB } }, + { MATROSKA_ID_VIDEOASPECTRATIO, EBML_NONE }, + CHILD_OF(matroska_track) +}; + +static EbmlSyntax matroska_track_audio[] = { + { MATROSKA_ID_AUDIOSAMPLINGFREQ, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackAudio, samplerate), { .f = 8000.0 } }, + { MATROSKA_ID_AUDIOOUTSAMPLINGFREQ, EBML_FLOAT, 0, 0, offsetof(MatroskaTrackAudio, out_samplerate) }, + { MATROSKA_ID_AUDIOBITDEPTH, EBML_UINT, 0, 0, offsetof(MatroskaTrackAudio, bitdepth) }, + { MATROSKA_ID_AUDIOCHANNELS, EBML_UINT, 0, 0, offsetof(MatroskaTrackAudio, channels), { .u = 1 } }, + CHILD_OF(matroska_track) +}; + +static EbmlSyntax matroska_track_encoding_compression[] = { + { MATROSKA_ID_ENCODINGCOMPALGO, EBML_UINT, 0, 0, offsetof(MatroskaTrackCompression, algo), { .u = MATROSKA_TRACK_ENCODING_COMP_ZLIB } }, + { MATROSKA_ID_ENCODINGCOMPSETTINGS, EBML_BIN, 0, 0, offsetof(MatroskaTrackCompression, settings) }, + CHILD_OF(matroska_track_encoding) +}; + +static EbmlSyntax matroska_track_encoding_encryption[] = { + { MATROSKA_ID_ENCODINGENCALGO, EBML_UINT, 0, 0, offsetof(MatroskaTrackEncryption,algo) }, + { MATROSKA_ID_ENCODINGENCKEYID, EBML_BIN, 0, 0, offsetof(MatroskaTrackEncryption,key_id) }, + { MATROSKA_ID_ENCODINGENCAESSETTINGS, EBML_NONE }, + { MATROSKA_ID_ENCODINGSIGALGO, EBML_NONE }, + { MATROSKA_ID_ENCODINGSIGHASHALGO, EBML_NONE }, + { MATROSKA_ID_ENCODINGSIGKEYID, EBML_NONE }, + { MATROSKA_ID_ENCODINGSIGNATURE, EBML_NONE }, + CHILD_OF(matroska_track_encoding) +}; +EbmlSyntax matroska_track_encoding[] = { + { MATROSKA_ID_ENCODINGSCOPE, EBML_UINT, 0, 0, offsetof(MatroskaTrackEncoding, scope), { .u = 1 } }, + { MATROSKA_ID_ENCODINGTYPE, EBML_UINT, 0, 0, offsetof(MatroskaTrackEncoding, type) }, + { MATROSKA_ID_ENCODINGCOMPRESSION, EBML_NEST, 0, 0, offsetof(MatroskaTrackEncoding, compression), { .n = matroska_track_encoding_compression } }, + { MATROSKA_ID_ENCODINGENCRYPTION, EBML_NEST, 0, 0, offsetof(MatroskaTrackEncoding, encryption), { .n = matroska_track_encoding_encryption } }, + { MATROSKA_ID_ENCODINGORDER, EBML_NONE }, + CHILD_OF(matroska_track_encodings) +}; + +EbmlSyntax matroska_track_encodings[] = { + { MATROSKA_ID_TRACKCONTENTENCODING, EBML_NEST, 0, sizeof(MatroskaTrackEncoding), offsetof(MatroskaTrack, encodings), { .n = matroska_track_encoding } }, + CHILD_OF(matroska_track) +}; + +static EbmlSyntax matroska_track_plane[] = { + { MATROSKA_ID_TRACKPLANEUID, EBML_UINT, 0, 0, offsetof(MatroskaTrackPlane,uid) }, + { MATROSKA_ID_TRACKPLANETYPE, EBML_UINT, 0, 0, offsetof(MatroskaTrackPlane,type) }, + CHILD_OF(matroska_track_combine_planes) +}; + +EbmlSyntax matroska_track_combine_planes[] = { + { MATROSKA_ID_TRACKPLANE, EBML_NEST, 0, sizeof(MatroskaTrackPlane), offsetof(MatroskaTrackOperation,combine_planes), {.n = matroska_track_plane} }, + CHILD_OF(matroska_track_operation) +}; + +EbmlSyntax matroska_track_operation[] = { + { MATROSKA_ID_TRACKCOMBINEPLANES, EBML_NEST, 0, 0, 0, {.n = matroska_track_combine_planes} }, + CHILD_OF(matroska_track) +}; + +EbmlSyntax matroska_block_addition_mapping[] = { + { MATROSKA_ID_BLKADDIDVALUE, EBML_UINT, 0, 0, offsetof(MatroskaBlockAdditionMapping, value) }, + { MATROSKA_ID_BLKADDIDNAME, EBML_STR, 0, 0, offsetof(MatroskaBlockAdditionMapping, name) }, + { MATROSKA_ID_BLKADDIDTYPE, EBML_UINT, 0, 0, offsetof(MatroskaBlockAdditionMapping, type) }, + { MATROSKA_ID_BLKADDIDEXTRADATA, EBML_BIN, 0, 0, offsetof(MatroskaBlockAdditionMapping, extradata) }, + CHILD_OF(matroska_track) +}; + +EbmlSyntax matroska_track[] = { + { MATROSKA_ID_TRACKNUMBER, EBML_UINT, 0, 0, offsetof(MatroskaTrack, num) }, + { MATROSKA_ID_TRACKNAME, EBML_UTF8, 0, 0, offsetof(MatroskaTrack, name) }, + { MATROSKA_ID_TRACKUID, EBML_UINT, 0, 0, offsetof(MatroskaTrack, uid) }, + { MATROSKA_ID_TRACKTYPE, EBML_UINT, 0, 0, offsetof(MatroskaTrack, type) }, + { MATROSKA_ID_CODECID, EBML_STR, 0, 0, offsetof(MatroskaTrack, codec_id) }, + { MATROSKA_ID_CODECPRIVATE, EBML_BIN, 0, 0, offsetof(MatroskaTrack, codec_priv) }, + { MATROSKA_ID_CODECDELAY, EBML_UINT, 0, 0, offsetof(MatroskaTrack, codec_delay) }, + { MATROSKA_ID_TRACKLANGUAGE, EBML_STR, 0, 0, offsetof(MatroskaTrack, language), { .s = "eng" } }, + { MATROSKA_ID_TRACKDEFAULTDURATION, EBML_UINT, 0, 0, offsetof(MatroskaTrack, default_duration) }, + { MATROSKA_ID_TRACKTIMECODESCALE, EBML_FLOAT, 0, 0, offsetof(MatroskaTrack, time_scale), { .f = 1.0 } }, + { MATROSKA_ID_TRACKFLAGCOMMENTARY, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_comment) }, + { MATROSKA_ID_TRACKFLAGDEFAULT, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_default), { .u = 1 } }, + { MATROSKA_ID_TRACKFLAGFORCED, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_forced) }, + { MATROSKA_ID_TRACKFLAGHEARINGIMPAIRED, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_hearingimpaired) }, + { MATROSKA_ID_TRACKFLAGVISUALIMPAIRED, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_visualimpaired) }, + { MATROSKA_ID_TRACKFLAGTEXTDESCRIPTIONS, EBML_UINT, 0, 0, offsetof(MatroskaTrack, flag_textdescriptions) }, + { MATROSKA_ID_TRACKFLAGORIGINAL, EBML_UINT, 1, 0, offsetof(MatroskaTrack, flag_original) }, + { MATROSKA_ID_TRACKVIDEO, EBML_NEST, 0, 0, offsetof(MatroskaTrack, video), { .n = matroska_track_video } }, + { MATROSKA_ID_TRACKAUDIO, EBML_NEST, 0, 0, offsetof(MatroskaTrack, audio), { .n = matroska_track_audio } }, + { MATROSKA_ID_TRACKOPERATION, EBML_NEST, 0, 0, offsetof(MatroskaTrack, operation), { .n = matroska_track_operation } }, + { MATROSKA_ID_TRACKCONTENTENCODINGS, EBML_NEST, 0, 0, 0, { .n = matroska_track_encodings } }, + { MATROSKA_ID_TRACKMAXBLKADDID, EBML_UINT, 0, 0, offsetof(MatroskaTrack, max_block_additional_id) }, + { MATROSKA_ID_TRACKBLKADDMAPPING, EBML_NEST, 0, sizeof(MatroskaBlockAdditionMapping), offsetof(MatroskaTrack, block_addition_mappings), { .n = matroska_block_addition_mapping } }, + { MATROSKA_ID_SEEKPREROLL, EBML_UINT, 0, 0, offsetof(MatroskaTrack, seek_preroll) }, + { MATROSKA_ID_TRACKFLAGENABLED, EBML_NONE }, + { MATROSKA_ID_TRACKFLAGLACING, EBML_NONE }, + { MATROSKA_ID_CODECNAME, EBML_NONE }, + { MATROSKA_ID_CODECDECODEALL, EBML_NONE }, + { MATROSKA_ID_CODECINFOURL, EBML_NONE }, + { MATROSKA_ID_CODECDOWNLOADURL, EBML_NONE }, + { MATROSKA_ID_TRACKMINCACHE, EBML_NONE }, + { MATROSKA_ID_TRACKMAXCACHE, EBML_NONE }, + CHILD_OF(matroska_tracks) +}; + +EbmlSyntax matroska_tracks[] = { + { MATROSKA_ID_TRACKENTRY, EBML_NEST, 0, sizeof(MatroskaTrack), offsetof(MatroskaDemuxContext, tracks), { .n = matroska_track } }, + CHILD_OF(matroska_segment) +}; + +static EbmlSyntax matroska_attachment[] = { + { MATROSKA_ID_FILEUID, EBML_UINT, 0, 0, offsetof(MatroskaAttachment, uid) }, + { MATROSKA_ID_FILENAME, EBML_UTF8, 0, 0, offsetof(MatroskaAttachment, filename) }, + { MATROSKA_ID_FILEMIMETYPE, EBML_STR, 0, 0, offsetof(MatroskaAttachment, mime) }, + { MATROSKA_ID_FILEDATA, EBML_BIN, 0, 0, offsetof(MatroskaAttachment, bin) }, + { MATROSKA_ID_FILEDESC, EBML_UTF8, 0, 0, offsetof(MatroskaAttachment, description) }, + CHILD_OF(matroska_attachments) +}; + +EbmlSyntax matroska_attachments[] = { + { MATROSKA_ID_ATTACHEDFILE, EBML_NEST, 0, sizeof(MatroskaAttachment), offsetof(MatroskaDemuxContext, attachments), { .n = matroska_attachment } }, + CHILD_OF(matroska_segment) +}; + +static EbmlSyntax matroska_chapter_display[] = { + { MATROSKA_ID_CHAPSTRING, EBML_UTF8, 0, 0, offsetof(MatroskaChapter, title) }, + { MATROSKA_ID_CHAPLANG, EBML_NONE }, + { MATROSKA_ID_CHAPCOUNTRY, EBML_NONE }, + CHILD_OF(matroska_chapter_entry) +}; + +EbmlSyntax matroska_chapter_entry[] = { + { MATROSKA_ID_CHAPTERTIMESTART, EBML_UINT, 0, 0, offsetof(MatroskaChapter, start), { .u = AV_NOPTS_VALUE } }, + { MATROSKA_ID_CHAPTERTIMEEND, EBML_UINT, 0, 0, offsetof(MatroskaChapter, end), { .u = AV_NOPTS_VALUE } }, + { MATROSKA_ID_CHAPTERUID, EBML_UINT, 0, 0, offsetof(MatroskaChapter, uid) }, + { MATROSKA_ID_CHAPTERDISPLAY, EBML_NEST, 0, 0, 0, { .n = matroska_chapter_display } }, + { MATROSKA_ID_CHAPTERFLAGHIDDEN, EBML_NONE }, + { MATROSKA_ID_CHAPTERFLAGENABLED, EBML_NONE }, + { MATROSKA_ID_CHAPTERPHYSEQUIV, EBML_NONE }, + { MATROSKA_ID_CHAPTERATOM, EBML_NONE }, + CHILD_OF(matroska_chapter) +}; + +EbmlSyntax matroska_chapter[] = { + { MATROSKA_ID_CHAPTERATOM, EBML_NEST, 0, sizeof(MatroskaChapter), offsetof(MatroskaDemuxContext, chapters), { .n = matroska_chapter_entry } }, + { MATROSKA_ID_EDITIONUID, EBML_NONE }, + { MATROSKA_ID_EDITIONFLAGHIDDEN, EBML_NONE }, + { MATROSKA_ID_EDITIONFLAGDEFAULT, EBML_NONE }, + { MATROSKA_ID_EDITIONFLAGORDERED, EBML_NONE }, + CHILD_OF(matroska_chapters) +}; + +EbmlSyntax matroska_chapters[] = { + { MATROSKA_ID_EDITIONENTRY, EBML_NEST, 0, 0, 0, { .n = matroska_chapter } }, + CHILD_OF(matroska_segment) +}; + +static EbmlSyntax matroska_index_pos[] = { + { MATROSKA_ID_CUETRACK, EBML_UINT, 0, 0, offsetof(MatroskaIndexPos, track) }, + { MATROSKA_ID_CUECLUSTERPOSITION, EBML_UINT, 0, 0, offsetof(MatroskaIndexPos, pos) }, + { MATROSKA_ID_CUERELATIVEPOSITION,EBML_NONE }, + { MATROSKA_ID_CUEDURATION, EBML_NONE }, + { MATROSKA_ID_CUEBLOCKNUMBER, EBML_NONE }, + CHILD_OF(matroska_index_entry) +}; + +EbmlSyntax matroska_index_entry[] = { + { MATROSKA_ID_CUETIME, EBML_UINT, 0, 0, offsetof(MatroskaIndex, time) }, + { MATROSKA_ID_CUETRACKPOSITION, EBML_NEST, 0, sizeof(MatroskaIndexPos), offsetof(MatroskaIndex, pos), { .n = matroska_index_pos } }, + CHILD_OF(matroska_index) +}; + +EbmlSyntax matroska_index[] = { + { MATROSKA_ID_POINTENTRY, EBML_NEST, 0, sizeof(MatroskaIndex), offsetof(MatroskaDemuxContext, index), { .n = matroska_index_entry } }, + CHILD_OF(matroska_segment) +}; + +static EbmlSyntax matroska_simpletag[] = { + { MATROSKA_ID_TAGNAME, EBML_UTF8, 0, 0, offsetof(MatroskaTag, name) }, + { MATROSKA_ID_TAGSTRING, EBML_UTF8, 0, 0, offsetof(MatroskaTag, string) }, + { MATROSKA_ID_TAGLANG, EBML_STR, 0, 0, offsetof(MatroskaTag, lang), { .s = "und" } }, + { MATROSKA_ID_TAGDEFAULT, EBML_UINT, 0, 0, offsetof(MatroskaTag, def), { .u = 1 } }, + { MATROSKA_ID_TAGDEFAULT_BUG, EBML_UINT, 0, 0, offsetof(MatroskaTag, def), { .u = 1 } }, + { MATROSKA_ID_SIMPLETAG, EBML_NEST, 0, sizeof(MatroskaTag), offsetof(MatroskaTag, sub), { .n = matroska_simpletag } }, + CHILD_OF(matroska_tag) +}; + +static EbmlSyntax matroska_tagtargets[] = { + { MATROSKA_ID_TAGTARGETS_TYPE, EBML_STR, 0, 0, offsetof(MatroskaTagTarget, type) }, + { MATROSKA_ID_TAGTARGETS_TYPEVALUE, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, typevalue), { .u = 50 } }, + { MATROSKA_ID_TAGTARGETS_TRACKUID, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, trackuid) }, + { MATROSKA_ID_TAGTARGETS_CHAPTERUID, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, chapteruid) }, + { MATROSKA_ID_TAGTARGETS_ATTACHUID, EBML_UINT, 0, 0, offsetof(MatroskaTagTarget, attachuid) }, + CHILD_OF(matroska_tag) +}; + +EbmlSyntax matroska_tag[] = { + { MATROSKA_ID_SIMPLETAG, EBML_NEST, 0, sizeof(MatroskaTag), offsetof(MatroskaTags, tag), { .n = matroska_simpletag } }, + { MATROSKA_ID_TAGTARGETS, EBML_NEST, 0, 0, offsetof(MatroskaTags, target), { .n = matroska_tagtargets } }, + CHILD_OF(matroska_tags) +}; + +EbmlSyntax matroska_tags[] = { + { MATROSKA_ID_TAG, EBML_NEST, 0, sizeof(MatroskaTags), offsetof(MatroskaDemuxContext, tags), { .n = matroska_tag } }, + CHILD_OF(matroska_segment) +}; + +static EbmlSyntax matroska_seekhead_entry[] = { + { MATROSKA_ID_SEEKID, EBML_UINT, 0, 0, offsetof(MatroskaSeekhead, id) }, + { MATROSKA_ID_SEEKPOSITION, EBML_UINT, 0, 0, offsetof(MatroskaSeekhead, pos), { .u = -1 } }, + CHILD_OF(matroska_seekhead) +}; + +EbmlSyntax matroska_seekhead[] = { + { MATROSKA_ID_SEEKENTRY, EBML_NEST, 0, sizeof(MatroskaSeekhead), offsetof(MatroskaDemuxContext, seekhead), { .n = matroska_seekhead_entry } }, + CHILD_OF(matroska_segment) +}; + +EbmlSyntax matroska_segment[] = { + { MATROSKA_ID_CLUSTER, EBML_STOP }, + { MATROSKA_ID_INFO, EBML_LEVEL1, 0, 0, 0, { .n = matroska_info } }, + { MATROSKA_ID_TRACKS, EBML_LEVEL1, 0, 0, 0, { .n = matroska_tracks } }, + { MATROSKA_ID_ATTACHMENTS, EBML_LEVEL1, 0, 0, 0, { .n = matroska_attachments } }, + { MATROSKA_ID_CHAPTERS, EBML_LEVEL1, 0, 0, 0, { .n = matroska_chapters } }, + { MATROSKA_ID_CUES, EBML_LEVEL1, 0, 0, 0, { .n = matroska_index } }, + { MATROSKA_ID_TAGS, EBML_LEVEL1, 0, 0, 0, { .n = matroska_tags } }, + { MATROSKA_ID_SEEKHEAD, EBML_LEVEL1, 0, 0, 0, { .n = matroska_seekhead } }, + { 0 } /* We don't want to go back to level 0, so don't add the parent. */ +}; + +EbmlSyntax matroska_segments[] = { + { MATROSKA_ID_SEGMENT, EBML_NEST, 0, 0, 0, { .n = matroska_segment } }, + { 0 } +}; + +static EbmlSyntax matroska_blockmore[] = { + { MATROSKA_ID_BLOCKADDID, EBML_UINT, 0, 0, offsetof(MatroskaBlock,additional_id), { .u = 1 } }, + { MATROSKA_ID_BLOCKADDITIONAL, EBML_BIN, 0, 0, offsetof(MatroskaBlock,additional) }, + CHILD_OF(matroska_blockadditions) +}; + +EbmlSyntax matroska_blockadditions[] = { + { MATROSKA_ID_BLOCKMORE, EBML_NEST, 0, 0, 0, {.n = matroska_blockmore} }, + CHILD_OF(matroska_blockgroup) +}; + +EbmlSyntax matroska_blockgroup[] = { + { MATROSKA_ID_BLOCK, EBML_BIN, 0, 0, offsetof(MatroskaBlock, bin) }, + { MATROSKA_ID_BLOCKADDITIONS, EBML_NEST, 0, 0, 0, { .n = matroska_blockadditions} }, + { MATROSKA_ID_BLOCKDURATION, EBML_UINT, 0, 0, offsetof(MatroskaBlock, duration) }, + { MATROSKA_ID_DISCARDPADDING, EBML_SINT, 0, 0, offsetof(MatroskaBlock, discard_padding) }, + { MATROSKA_ID_BLOCKREFERENCE, EBML_SINT, 1, 0, offsetof(MatroskaBlock, reference) }, + { MATROSKA_ID_CODECSTATE, EBML_NONE }, + { 1, EBML_UINT, 0, 0, offsetof(MatroskaBlock, non_simple), { .u = 1 } }, + CHILD_OF(matroska_cluster_parsing) +}; + +// The following array contains SimpleBlock and BlockGroup twice +// in order to reuse the other values for matroska_cluster_enter. +EbmlSyntax matroska_cluster_parsing[] = { + { MATROSKA_ID_SIMPLEBLOCK, EBML_BIN, 0, 0, offsetof(MatroskaBlock, bin) }, + { MATROSKA_ID_BLOCKGROUP, EBML_NEST, 0, 0, 0, { .n = matroska_blockgroup } }, + { MATROSKA_ID_CLUSTERTIMECODE, EBML_UINT, 0, 0, offsetof(MatroskaCluster, timecode) }, + { MATROSKA_ID_SIMPLEBLOCK, EBML_STOP }, + { MATROSKA_ID_BLOCKGROUP, EBML_STOP }, + { MATROSKA_ID_CLUSTERPOSITION, EBML_NONE }, + { MATROSKA_ID_CLUSTERPREVSIZE, EBML_NONE }, + CHILD_OF(matroska_segment) +}; + +EbmlSyntax matroska_cluster_enter[] = { + { MATROSKA_ID_CLUSTER, EBML_NEST, 0, 0, 0, { .n = &matroska_cluster_parsing[2] } }, + { 0 } +}; diff --git a/libavformat/matroskasem.h b/libavformat/matroskasem.h new file mode 100644 index 0000000000..01008b00bb --- /dev/null +++ b/libavformat/matroskasem.h @@ -0,0 +1,394 @@ +/* + * Matroska file semantic definition + * Copyright (c) 2003-2022 The FFmpeg project + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Matroska file demuxer + * @author Ronald Bultje + * @author with a little help from Moritz Bunkus + * @author totally reworked by Aurelien Jacobs + * @see specs available on the Matroska project page: http://www.matroska.org/ + */ + +#ifndef AVFORMAT_MATROSKASEM_H +#define AVFORMAT_MATROSKASEM_H + +#include + +#include "matroska.h" +#include "avformat.h" +#include "libavutil/frame.h" +#include "libavcodec/packet_internal.h" + +typedef enum { + EBML_NONE, + EBML_UINT, + EBML_SINT, + EBML_FLOAT, + EBML_STR, + EBML_UTF8, + EBML_BIN, + EBML_NEST, + EBML_LEVEL1, + EBML_STOP, + EBML_TYPE_COUNT +} EbmlType; + +typedef struct CountedElement { + union { + uint64_t u; + int64_t i; + double f; + char *s; + } el; + unsigned count; +} CountedElement; + +typedef const struct EbmlSyntax { + uint32_t id; + uint8_t type; + uint8_t is_counted; + size_t list_elem_size; + size_t data_offset; + union { + int64_t i; + uint64_t u; + double f; + const char *s; + const struct EbmlSyntax *n; + } def; +} EbmlSyntax; + +typedef struct EbmlList { + int nb_elem; + unsigned int alloc_elem_size; + void *elem; +} EbmlList; + +typedef struct EbmlBin { + int size; + AVBufferRef *buf; + uint8_t *data; + int64_t pos; +} EbmlBin; + +typedef struct Ebml { + uint64_t version; + uint64_t max_size; + uint64_t id_length; + char *doctype; + uint64_t doctype_version; +} Ebml; + +typedef struct MatroskaTrackCompression { + uint64_t algo; + EbmlBin settings; +} MatroskaTrackCompression; + +typedef struct MatroskaTrackEncryption { + uint64_t algo; + EbmlBin key_id; +} MatroskaTrackEncryption; + +typedef struct MatroskaTrackEncoding { + uint64_t scope; + uint64_t type; + MatroskaTrackCompression compression; + MatroskaTrackEncryption encryption; +} MatroskaTrackEncoding; + +typedef struct MatroskaMasteringMeta { + double r_x; + double r_y; + double g_x; + double g_y; + double b_x; + double b_y; + double white_x; + double white_y; + double max_luminance; + CountedElement min_luminance; +} MatroskaMasteringMeta; + +typedef struct MatroskaTrackVideoColor { + uint64_t matrix_coefficients; + uint64_t bits_per_channel; + uint64_t chroma_sub_horz; + uint64_t chroma_sub_vert; + uint64_t cb_sub_horz; + uint64_t cb_sub_vert; + uint64_t chroma_siting_horz; + uint64_t chroma_siting_vert; + uint64_t range; + uint64_t transfer_characteristics; + uint64_t primaries; + uint64_t max_cll; + uint64_t max_fall; + MatroskaMasteringMeta mastering_meta; +} MatroskaTrackVideoColor; + +typedef struct MatroskaTrackVideoProjection { + uint64_t type; + EbmlBin private; + double yaw; + double pitch; + double roll; +} MatroskaTrackVideoProjection; + +typedef struct MatroskaTrackVideo { + double frame_rate; + uint64_t display_width; + uint64_t display_height; + uint64_t pixel_width; + uint64_t pixel_height; + EbmlBin color_space; + uint64_t display_unit; + uint64_t interlaced; + uint64_t field_order; + uint64_t stereo_mode; + uint64_t alpha_mode; + EbmlList color; + MatroskaTrackVideoProjection projection; +} MatroskaTrackVideo; + +typedef struct MatroskaTrackAudio { + double samplerate; + double out_samplerate; + uint64_t bitdepth; + uint64_t channels; + + /* real audio header (extracted from extradata) */ + int coded_framesize; + int sub_packet_h; + int frame_size; + int sub_packet_size; + int sub_packet_cnt; + int pkt_cnt; + uint64_t buf_timecode; + uint8_t *buf; +} MatroskaTrackAudio; + +typedef struct MatroskaTrackPlane { + uint64_t uid; + uint64_t type; +} MatroskaTrackPlane; + +typedef struct MatroskaTrackOperation { + EbmlList combine_planes; +} MatroskaTrackOperation; + +typedef struct MatroskaBlockAdditionMapping { + uint64_t value; + char *name; + uint64_t type; + EbmlBin extradata; +} MatroskaBlockAdditionMapping; + +typedef struct MatroskaTrack { + uint64_t num; + uint64_t uid; + uint64_t type; + char *name; + char *codec_id; + EbmlBin codec_priv; + char *language; + double time_scale; + uint64_t default_duration; + uint64_t flag_default; + uint64_t flag_forced; + uint64_t flag_comment; + uint64_t flag_hearingimpaired; + uint64_t flag_visualimpaired; + uint64_t flag_textdescriptions; + CountedElement flag_original; + uint64_t seek_preroll; + MatroskaTrackVideo video; + MatroskaTrackAudio audio; + MatroskaTrackOperation operation; + EbmlList encodings; + uint64_t codec_delay; + uint64_t codec_delay_in_track_tb; + + AVStream *stream; + int64_t end_timecode; + int ms_compat; + int needs_decoding; + uint64_t max_block_additional_id; + EbmlList block_addition_mappings; + + uint32_t palette[AVPALETTE_COUNT]; + int has_palette; +} MatroskaTrack; + +typedef struct MatroskaAttachment { + uint64_t uid; + char *filename; + char *description; + char *mime; + EbmlBin bin; + + AVStream *stream; +} MatroskaAttachment; + +typedef struct MatroskaChapter { + uint64_t start; + uint64_t end; + uint64_t uid; + char *title; + + AVChapter *chapter; +} MatroskaChapter; + +typedef struct MatroskaIndexPos { + uint64_t track; + uint64_t pos; +} MatroskaIndexPos; + +typedef struct MatroskaIndex { + uint64_t time; + EbmlList pos; +} MatroskaIndex; + +typedef struct MatroskaTag { + char *name; + char *string; + char *lang; + uint64_t def; + EbmlList sub; +} MatroskaTag; + +typedef struct MatroskaTagTarget { + char *type; + uint64_t typevalue; + uint64_t trackuid; + uint64_t chapteruid; + uint64_t attachuid; +} MatroskaTagTarget; + +typedef struct MatroskaTags { + MatroskaTagTarget target; + EbmlList tag; +} MatroskaTags; + +typedef struct MatroskaSeekhead { + uint64_t id; + uint64_t pos; +} MatroskaSeekhead; + +typedef struct MatroskaLevel { + uint64_t start; + uint64_t length; +} MatroskaLevel; + +typedef struct MatroskaBlock { + uint64_t duration; + CountedElement reference; + uint64_t non_simple; + EbmlBin bin; + uint64_t additional_id; + EbmlBin additional; + int64_t discard_padding; +} MatroskaBlock; + +typedef struct MatroskaCluster { + MatroskaBlock block; + uint64_t timecode; + int64_t pos; +} MatroskaCluster; + +typedef struct MatroskaLevel1Element { + int64_t pos; + uint32_t id; + int parsed; +} MatroskaLevel1Element; + +typedef struct MatroskaDemuxContext { + const AVClass *class; + AVFormatContext *ctx; + + /* EBML stuff */ + MatroskaLevel levels[EBML_MAX_DEPTH]; + int num_levels; + uint32_t current_id; + int64_t resync_pos; + int unknown_count; + + uint64_t time_scale; + double duration; + char *title; + char *muxingapp; + EbmlBin date_utc; + EbmlList tracks; + EbmlList attachments; + EbmlList chapters; + EbmlList index; + EbmlList tags; + EbmlList seekhead; + + /* byte position of the segment inside the stream */ + int64_t segment_start; + + /* This packet coincides with FFFormatContext.parse_pkt + * and is not owned by us. */ + AVPacket *pkt; + + /* the packet queue */ + PacketList queue; + + int done; + + /* What to skip before effectively reading a packet. */ + int skip_to_keyframe; + uint64_t skip_to_timecode; + + /* File has a CUES element, but we defer parsing until it is needed. */ + int cues_parsing_deferred; + + /* Level1 elements and whether they were read yet */ + MatroskaLevel1Element level1_elems[64]; + int num_level1_elems; + + MatroskaCluster current_cluster; + + /* WebM DASH Manifest live flag */ + int is_live; + + /* Bandwidth value for WebM DASH Manifest */ + int bandwidth; +} MatroskaDemuxContext; + +#define CHILD_OF(parent) { .def = { .n = parent } } + +// The following forward declarations need their size because +// a tentative definition with internal linkage must not be an +// incomplete type (6.7.2 in C90, 6.9.2 in C99). +// Removing the sizes breaks MSVC. +EbmlSyntax ebml_syntax[3], matroska_segment[9], matroska_track_video_color[15], matroska_track_video[19], + matroska_track[33], matroska_track_encoding[6], matroska_track_encodings[2], + matroska_track_combine_planes[2], matroska_track_operation[2], matroska_block_addition_mapping[5], matroska_tracks[2], + matroska_attachments[2], matroska_chapter_entry[9], matroska_chapter[6], matroska_chapters[2], + matroska_index_entry[3], matroska_index[2], matroska_tag[3], matroska_tags[2], matroska_seekhead[2], + matroska_blockadditions[2], matroska_blockgroup[8], matroska_cluster_parsing[8]; + +EbmlSyntax matroska_segments[2]; +EbmlSyntax matroska_cluster_enter[2]; + +#endif /* AVFORMAT_MATROSKASEM_H */