LCOV - code coverage report
Current view: top level - media/libnestegg/src - nestegg.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 1455 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 90 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright © 2010 Mozilla Foundation
       3             :  *
       4             :  * This program is made available under an ISC-style license.  See the
       5             :  * accompanying file LICENSE for details.
       6             :  */
       7             : #include <assert.h>
       8             : #include <stddef.h>
       9             : #include <stdlib.h>
      10             : #include <string.h>
      11             : 
      12             : #include "nestegg/nestegg.h"
      13             : 
      14             : /* EBML Elements */
      15             : #define ID_EBML                     0x1a45dfa3
      16             : #define ID_EBML_VERSION             0x4286
      17             : #define ID_EBML_READ_VERSION        0x42f7
      18             : #define ID_EBML_MAX_ID_LENGTH       0x42f2
      19             : #define ID_EBML_MAX_SIZE_LENGTH     0x42f3
      20             : #define ID_DOCTYPE                  0x4282
      21             : #define ID_DOCTYPE_VERSION          0x4287
      22             : #define ID_DOCTYPE_READ_VERSION     0x4285
      23             : 
      24             : /* Global Elements */
      25             : #define ID_VOID                     0xec
      26             : #define ID_CRC32                    0xbf
      27             : 
      28             : /* WebM Elements */
      29             : #define ID_SEGMENT                  0x18538067
      30             : 
      31             : /* Seek Head Elements */
      32             : #define ID_SEEK_HEAD                0x114d9b74
      33             : #define ID_SEEK                     0x4dbb
      34             : #define ID_SEEK_ID                  0x53ab
      35             : #define ID_SEEK_POSITION            0x53ac
      36             : 
      37             : /* Info Elements */
      38             : #define ID_INFO                     0x1549a966
      39             : #define ID_TIMECODE_SCALE           0x2ad7b1
      40             : #define ID_DURATION                 0x4489
      41             : 
      42             : /* Cluster Elements */
      43             : #define ID_CLUSTER                  0x1f43b675
      44             : #define ID_TIMECODE                 0xe7
      45             : #define ID_BLOCK_GROUP              0xa0
      46             : #define ID_SIMPLE_BLOCK             0xa3
      47             : 
      48             : /* BlockGroup Elements */
      49             : #define ID_BLOCK                    0xa1
      50             : #define ID_BLOCK_ADDITIONS          0x75a1
      51             : #define ID_BLOCK_DURATION           0x9b
      52             : #define ID_REFERENCE_BLOCK          0xfb
      53             : #define ID_DISCARD_PADDING          0x75a2
      54             : 
      55             : /* BlockAdditions Elements */
      56             : #define ID_BLOCK_MORE               0xa6
      57             : 
      58             : /* BlockMore Elements */
      59             : #define ID_BLOCK_ADD_ID             0xee
      60             : #define ID_BLOCK_ADDITIONAL         0xa5
      61             : 
      62             : /* Tracks Elements */
      63             : #define ID_TRACKS                   0x1654ae6b
      64             : #define ID_TRACK_ENTRY              0xae
      65             : #define ID_TRACK_NUMBER             0xd7
      66             : #define ID_TRACK_UID                0x73c5
      67             : #define ID_TRACK_TYPE               0x83
      68             : #define ID_FLAG_ENABLED             0xb9
      69             : #define ID_FLAG_DEFAULT             0x88
      70             : #define ID_FLAG_LACING              0x9c
      71             : #define ID_TRACK_TIMECODE_SCALE     0x23314f
      72             : #define ID_LANGUAGE                 0x22b59c
      73             : #define ID_CODEC_ID                 0x86
      74             : #define ID_CODEC_PRIVATE            0x63a2
      75             : #define ID_CODEC_DELAY              0x56aa
      76             : #define ID_SEEK_PREROLL             0x56bb
      77             : #define ID_DEFAULT_DURATION         0x23e383
      78             : 
      79             : /* Video Elements */
      80             : #define ID_VIDEO                    0xe0
      81             : #define ID_STEREO_MODE              0x53b8
      82             : #define ID_ALPHA_MODE               0x53c0
      83             : #define ID_PIXEL_WIDTH              0xb0
      84             : #define ID_PIXEL_HEIGHT             0xba
      85             : #define ID_PIXEL_CROP_BOTTOM        0x54aa
      86             : #define ID_PIXEL_CROP_TOP           0x54bb
      87             : #define ID_PIXEL_CROP_LEFT          0x54cc
      88             : #define ID_PIXEL_CROP_RIGHT         0x54dd
      89             : #define ID_DISPLAY_WIDTH            0x54b0
      90             : #define ID_DISPLAY_HEIGHT           0x54ba
      91             : 
      92             : /* Audio Elements */
      93             : #define ID_AUDIO                    0xe1
      94             : #define ID_SAMPLING_FREQUENCY       0xb5
      95             : #define ID_CHANNELS                 0x9f
      96             : #define ID_BIT_DEPTH                0x6264
      97             : 
      98             : /* Cues Elements */
      99             : #define ID_CUES                     0x1c53bb6b
     100             : #define ID_CUE_POINT                0xbb
     101             : #define ID_CUE_TIME                 0xb3
     102             : #define ID_CUE_TRACK_POSITIONS      0xb7
     103             : #define ID_CUE_TRACK                0xf7
     104             : #define ID_CUE_CLUSTER_POSITION     0xf1
     105             : #define ID_CUE_BLOCK_NUMBER         0x5378
     106             : 
     107             : /* Encoding Elements */
     108             : #define ID_CONTENT_ENCODINGS        0x6d80
     109             : #define ID_CONTENT_ENCODING         0x6240
     110             : #define ID_CONTENT_ENCODING_TYPE    0x5033
     111             : 
     112             : /* Encryption Elements */
     113             : #define ID_CONTENT_ENCRYPTION       0x5035
     114             : #define ID_CONTENT_ENC_ALGO         0x47e1
     115             : #define ID_CONTENT_ENC_KEY_ID       0x47e2
     116             : #define ID_CONTENT_ENC_AES_SETTINGS 0x47e7
     117             : #define ID_AES_SETTINGS_CIPHER_MODE 0x47e8
     118             : 
     119             : /* EBML Types */
     120             : enum ebml_type_enum {
     121             :   TYPE_UNKNOWN,
     122             :   TYPE_MASTER,
     123             :   TYPE_UINT,
     124             :   TYPE_FLOAT,
     125             :   TYPE_STRING,
     126             :   TYPE_BINARY
     127             : };
     128             : 
     129             : #define LIMIT_STRING                (1 << 20)
     130             : #define LIMIT_BINARY                (1 << 24)
     131             : #define LIMIT_BLOCK                 (1 << 30)
     132             : #define LIMIT_FRAME                 (1 << 28)
     133             : 
     134             : /* Field Flags */
     135             : #define DESC_FLAG_NONE              0
     136             : #define DESC_FLAG_MULTI             (1 << 0)
     137             : #define DESC_FLAG_SUSPEND           (1 << 1)
     138             : #define DESC_FLAG_OFFSET            (1 << 2)
     139             : 
     140             : /* Block Header Flags */
     141             : #define SIMPLE_BLOCK_FLAGS_KEYFRAME (1 << 7)
     142             : #define BLOCK_FLAGS_LACING          6
     143             : 
     144             : /* Lacing Constants */
     145             : #define LACING_NONE                 0
     146             : #define LACING_XIPH                 1
     147             : #define LACING_FIXED                2
     148             : #define LACING_EBML                 3
     149             : 
     150             : /* Track Types */
     151             : #define TRACK_TYPE_VIDEO            1
     152             : #define TRACK_TYPE_AUDIO            2
     153             : 
     154             : /* Track IDs */
     155             : #define TRACK_ID_VP8                "V_VP8"
     156             : #define TRACK_ID_VP9                "V_VP9"
     157             : #define TRACK_ID_AV1                "V_AV1"
     158             : #define TRACK_ID_VORBIS             "A_VORBIS"
     159             : #define TRACK_ID_OPUS               "A_OPUS"
     160             : 
     161             : /* Track Encryption */
     162             : #define CONTENT_ENC_ALGO_AES        5
     163             : #define AES_SETTINGS_CIPHER_CTR     1
     164             : 
     165             : /* Packet Encryption */
     166             : #define SIGNAL_BYTE_SIZE            1
     167             : #define IV_SIZE                     8
     168             : #define NUM_PACKETS_SIZE            1
     169             : #define PACKET_OFFSET_SIZE          4
     170             : 
     171             : /* Signal Byte */
     172             : #define PACKET_ENCRYPTED            1
     173             : #define ENCRYPTED_BIT_MASK          (1 << 0)
     174             : 
     175             : #define PACKET_PARTITIONED          2
     176             : #define PARTITIONED_BIT_MASK        (1 << 1)
     177             : 
     178             : enum vint_mask {
     179             :   MASK_NONE,
     180             :   MASK_FIRST_BIT
     181             : };
     182             : 
     183             : struct ebml_binary {
     184             :   unsigned char * data;
     185             :   size_t length;
     186             : };
     187             : 
     188             : struct ebml_list_node {
     189             :   struct ebml_list_node * next;
     190             :   uint64_t id;
     191             :   void * data;
     192             : };
     193             : 
     194             : struct ebml_list {
     195             :   struct ebml_list_node * head;
     196             :   struct ebml_list_node * tail;
     197             : };
     198             : 
     199             : struct ebml_type {
     200             :   union ebml_value {
     201             :     uint64_t u;
     202             :     double f;
     203             :     int64_t i;
     204             :     char * s;
     205             :     struct ebml_binary b;
     206             :   } v;
     207             :   enum ebml_type_enum type;
     208             :   int read;
     209             : };
     210             : 
     211             : /* EBML Definitions */
     212             : struct ebml {
     213             :   struct ebml_type ebml_version;
     214             :   struct ebml_type ebml_read_version;
     215             :   struct ebml_type ebml_max_id_length;
     216             :   struct ebml_type ebml_max_size_length;
     217             :   struct ebml_type doctype;
     218             :   struct ebml_type doctype_version;
     219             :   struct ebml_type doctype_read_version;
     220             : };
     221             : 
     222             : /* Matroksa Definitions */
     223             : struct seek {
     224             :   struct ebml_type id;
     225             :   struct ebml_type position;
     226             : };
     227             : 
     228             : struct seek_head {
     229             :   struct ebml_list seek;
     230             : };
     231             : 
     232             : struct info {
     233             :   struct ebml_type timecode_scale;
     234             :   struct ebml_type duration;
     235             : };
     236             : 
     237             : struct video {
     238             :   struct ebml_type stereo_mode;
     239             :   struct ebml_type alpha_mode;
     240             :   struct ebml_type pixel_width;
     241             :   struct ebml_type pixel_height;
     242             :   struct ebml_type pixel_crop_bottom;
     243             :   struct ebml_type pixel_crop_top;
     244             :   struct ebml_type pixel_crop_left;
     245             :   struct ebml_type pixel_crop_right;
     246             :   struct ebml_type display_width;
     247             :   struct ebml_type display_height;
     248             : };
     249             : 
     250             : struct audio {
     251             :   struct ebml_type sampling_frequency;
     252             :   struct ebml_type channels;
     253             :   struct ebml_type bit_depth;
     254             : };
     255             : 
     256             : struct content_enc_aes_settings {
     257             :   struct ebml_type aes_settings_cipher_mode;
     258             : };
     259             : 
     260             : struct content_encryption {
     261             :   struct ebml_type content_enc_algo;
     262             :   struct ebml_type content_enc_key_id;
     263             :   struct ebml_list content_enc_aes_settings;
     264             : };
     265             : 
     266             : struct content_encoding {
     267             :   struct ebml_type content_encoding_type;
     268             :   struct ebml_list content_encryption;
     269             : };
     270             : 
     271             : struct content_encodings {
     272             :   struct ebml_list content_encoding;
     273             : };
     274             : 
     275             : struct track_entry {
     276             :   struct ebml_type number;
     277             :   struct ebml_type uid;
     278             :   struct ebml_type type;
     279             :   struct ebml_type flag_enabled;
     280             :   struct ebml_type flag_default;
     281             :   struct ebml_type flag_lacing;
     282             :   struct ebml_type track_timecode_scale;
     283             :   struct ebml_type language;
     284             :   struct ebml_type codec_id;
     285             :   struct ebml_type codec_private;
     286             :   struct ebml_type codec_delay;
     287             :   struct ebml_type seek_preroll;
     288             :   struct ebml_type default_duration;
     289             :   struct video video;
     290             :   struct audio audio;
     291             :   struct content_encodings content_encodings;
     292             : };
     293             : 
     294             : struct tracks {
     295             :   struct ebml_list track_entry;
     296             : };
     297             : 
     298             : struct cue_track_positions {
     299             :   struct ebml_type track;
     300             :   struct ebml_type cluster_position;
     301             :   struct ebml_type block_number;
     302             : };
     303             : 
     304             : struct cue_point {
     305             :   struct ebml_type time;
     306             :   struct ebml_list cue_track_positions;
     307             : };
     308             : 
     309             : struct cues {
     310             :   struct ebml_list cue_point;
     311             : };
     312             : 
     313             : struct segment {
     314             :   struct ebml_list seek_head;
     315             :   struct info info;
     316             :   struct tracks tracks;
     317             :   struct cues cues;
     318             : };
     319             : 
     320             : /* Misc. */
     321             : struct pool_node {
     322             :   struct pool_node * next;
     323             :   void * data;
     324             : };
     325             : 
     326             : struct pool_ctx {
     327             :   struct pool_node * head;
     328             : };
     329             : 
     330             : struct list_node {
     331             :   struct list_node * previous;
     332             :   struct ebml_element_desc * node;
     333             :   unsigned char * data;
     334             : };
     335             : 
     336             : struct saved_state {
     337             :   int64_t stream_offset;
     338             :   uint64_t last_id;
     339             :   uint64_t last_size;
     340             :   int last_valid;
     341             : };
     342             : 
     343             : struct frame_encryption {
     344             :   unsigned char * iv;
     345             :   size_t length;
     346             :   uint8_t signal_byte;
     347             :   uint8_t num_partitions;
     348             :   uint32_t * partition_offsets;
     349             : };
     350             : 
     351             : struct frame {
     352             :   unsigned char * data;
     353             :   size_t length;
     354             :   struct frame_encryption * frame_encryption;
     355             :   struct frame * next;
     356             : };
     357             : 
     358             : struct block_additional {
     359             :   unsigned int id;
     360             :   unsigned char * data;
     361             :   size_t length;
     362             :   struct block_additional * next;
     363             : };
     364             : 
     365             : /* Public (opaque) Structures */
     366             : struct nestegg {
     367             :   nestegg_io * io;
     368             :   nestegg_log log;
     369             :   struct pool_ctx * alloc_pool;
     370             :   uint64_t last_id;
     371             :   uint64_t last_size;
     372             :   int last_valid;
     373             :   struct list_node * ancestor;
     374             :   struct ebml ebml;
     375             :   struct segment segment;
     376             :   int64_t segment_offset;
     377             :   unsigned int track_count;
     378             :   /* Last read cluster. */
     379             :   uint64_t cluster_timecode;
     380             :   int read_cluster_timecode;
     381             :   struct saved_state saved;
     382             : };
     383             : 
     384             : struct nestegg_packet {
     385             :   uint64_t track;
     386             :   uint64_t timecode;
     387             :   uint64_t duration;
     388             :   int read_duration;
     389             :   struct frame * frame;
     390             :   struct block_additional * block_additional;
     391             :   int64_t discard_padding;
     392             :   int read_discard_padding;
     393             :   int64_t reference_block;
     394             :   int read_reference_block;
     395             :   uint8_t keyframe;
     396             : };
     397             : 
     398             : /* Element Descriptor */
     399             : struct ebml_element_desc {
     400             :   char const * name;
     401             :   uint64_t id;
     402             :   enum ebml_type_enum type;
     403             :   size_t offset;
     404             :   unsigned int flags;
     405             :   struct ebml_element_desc * children;
     406             :   size_t size;
     407             :   size_t data_offset;
     408             : };
     409             : 
     410             : #define E_FIELD(ID, TYPE, STRUCT, FIELD) \
     411             :   { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_NONE, NULL, 0, 0 }
     412             : #define E_MASTER(ID, TYPE, STRUCT, FIELD) \
     413             :   { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_MULTI, ne_ ## FIELD ## _elements, \
     414             :       sizeof(struct FIELD), 0 }
     415             : #define E_SINGLE_MASTER_O(ID, TYPE, STRUCT, FIELD) \
     416             :   { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_OFFSET, ne_ ## FIELD ## _elements, 0, \
     417             :       offsetof(STRUCT, FIELD ## _offset) }
     418             : #define E_SINGLE_MASTER(ID, TYPE, STRUCT, FIELD) \
     419             :   { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_NONE, ne_ ## FIELD ## _elements, 0, 0 }
     420             : #define E_SUSPEND(ID, TYPE) \
     421             :   { #ID, ID, TYPE, 0, DESC_FLAG_SUSPEND, NULL, 0, 0 }
     422             : #define E_LAST \
     423             :   { NULL, 0, 0, 0, DESC_FLAG_NONE, NULL, 0, 0 }
     424             : 
     425             : /* EBML Element Lists */
     426             : static struct ebml_element_desc ne_ebml_elements[] = {
     427             :   E_FIELD(ID_EBML_VERSION, TYPE_UINT, struct ebml, ebml_version),
     428             :   E_FIELD(ID_EBML_READ_VERSION, TYPE_UINT, struct ebml, ebml_read_version),
     429             :   E_FIELD(ID_EBML_MAX_ID_LENGTH, TYPE_UINT, struct ebml, ebml_max_id_length),
     430             :   E_FIELD(ID_EBML_MAX_SIZE_LENGTH, TYPE_UINT, struct ebml, ebml_max_size_length),
     431             :   E_FIELD(ID_DOCTYPE, TYPE_STRING, struct ebml, doctype),
     432             :   E_FIELD(ID_DOCTYPE_VERSION, TYPE_UINT, struct ebml, doctype_version),
     433             :   E_FIELD(ID_DOCTYPE_READ_VERSION, TYPE_UINT, struct ebml, doctype_read_version),
     434             :   E_LAST
     435             : };
     436             : 
     437             : /* WebM Element Lists */
     438             : static struct ebml_element_desc ne_seek_elements[] = {
     439             :   E_FIELD(ID_SEEK_ID, TYPE_BINARY, struct seek, id),
     440             :   E_FIELD(ID_SEEK_POSITION, TYPE_UINT, struct seek, position),
     441             :   E_LAST
     442             : };
     443             : 
     444             : static struct ebml_element_desc ne_seek_head_elements[] = {
     445             :   E_MASTER(ID_SEEK, TYPE_MASTER, struct seek_head, seek),
     446             :   E_LAST
     447             : };
     448             : 
     449             : static struct ebml_element_desc ne_info_elements[] = {
     450             :   E_FIELD(ID_TIMECODE_SCALE, TYPE_UINT, struct info, timecode_scale),
     451             :   E_FIELD(ID_DURATION, TYPE_FLOAT, struct info, duration),
     452             :   E_LAST
     453             : };
     454             : 
     455             : static struct ebml_element_desc ne_video_elements[] = {
     456             :   E_FIELD(ID_STEREO_MODE, TYPE_UINT, struct video, stereo_mode),
     457             :   E_FIELD(ID_ALPHA_MODE, TYPE_UINT, struct video, alpha_mode),
     458             :   E_FIELD(ID_PIXEL_WIDTH, TYPE_UINT, struct video, pixel_width),
     459             :   E_FIELD(ID_PIXEL_HEIGHT, TYPE_UINT, struct video, pixel_height),
     460             :   E_FIELD(ID_PIXEL_CROP_BOTTOM, TYPE_UINT, struct video, pixel_crop_bottom),
     461             :   E_FIELD(ID_PIXEL_CROP_TOP, TYPE_UINT, struct video, pixel_crop_top),
     462             :   E_FIELD(ID_PIXEL_CROP_LEFT, TYPE_UINT, struct video, pixel_crop_left),
     463             :   E_FIELD(ID_PIXEL_CROP_RIGHT, TYPE_UINT, struct video, pixel_crop_right),
     464             :   E_FIELD(ID_DISPLAY_WIDTH, TYPE_UINT, struct video, display_width),
     465             :   E_FIELD(ID_DISPLAY_HEIGHT, TYPE_UINT, struct video, display_height),
     466             :   E_LAST
     467             : };
     468             : 
     469             : static struct ebml_element_desc ne_audio_elements[] = {
     470             :   E_FIELD(ID_SAMPLING_FREQUENCY, TYPE_FLOAT, struct audio, sampling_frequency),
     471             :   E_FIELD(ID_CHANNELS, TYPE_UINT, struct audio, channels),
     472             :   E_FIELD(ID_BIT_DEPTH, TYPE_UINT, struct audio, bit_depth),
     473             :   E_LAST
     474             : };
     475             : 
     476             : static struct ebml_element_desc ne_content_enc_aes_settings_elements[] = {
     477             :   E_FIELD(ID_AES_SETTINGS_CIPHER_MODE, TYPE_UINT, struct content_enc_aes_settings, aes_settings_cipher_mode),
     478             :   E_LAST
     479             : };
     480             : 
     481             : static struct ebml_element_desc ne_content_encryption_elements[] = {
     482             :   E_FIELD(ID_CONTENT_ENC_ALGO, TYPE_UINT, struct content_encryption, content_enc_algo),
     483             :   E_FIELD(ID_CONTENT_ENC_KEY_ID, TYPE_BINARY, struct content_encryption, content_enc_key_id),
     484             :   E_MASTER(ID_CONTENT_ENC_AES_SETTINGS, TYPE_MASTER, struct content_encryption, content_enc_aes_settings),
     485             :   E_LAST
     486             : };
     487             : 
     488             : static struct ebml_element_desc ne_content_encoding_elements[] = {
     489             :   E_FIELD(ID_CONTENT_ENCODING_TYPE, TYPE_UINT, struct content_encoding, content_encoding_type),
     490             :   E_MASTER(ID_CONTENT_ENCRYPTION, TYPE_MASTER, struct content_encoding, content_encryption),
     491             :   E_LAST
     492             : };
     493             : 
     494             : static struct ebml_element_desc ne_content_encodings_elements[] = {
     495             :   E_MASTER(ID_CONTENT_ENCODING, TYPE_MASTER, struct content_encodings, content_encoding),
     496             :   E_LAST
     497             : };
     498             : 
     499             : static struct ebml_element_desc ne_track_entry_elements[] = {
     500             :   E_FIELD(ID_TRACK_NUMBER, TYPE_UINT, struct track_entry, number),
     501             :   E_FIELD(ID_TRACK_UID, TYPE_UINT, struct track_entry, uid),
     502             :   E_FIELD(ID_TRACK_TYPE, TYPE_UINT, struct track_entry, type),
     503             :   E_FIELD(ID_FLAG_ENABLED, TYPE_UINT, struct track_entry, flag_enabled),
     504             :   E_FIELD(ID_FLAG_DEFAULT, TYPE_UINT, struct track_entry, flag_default),
     505             :   E_FIELD(ID_FLAG_LACING, TYPE_UINT, struct track_entry, flag_lacing),
     506             :   E_FIELD(ID_TRACK_TIMECODE_SCALE, TYPE_FLOAT, struct track_entry, track_timecode_scale),
     507             :   E_FIELD(ID_LANGUAGE, TYPE_STRING, struct track_entry, language),
     508             :   E_FIELD(ID_CODEC_ID, TYPE_STRING, struct track_entry, codec_id),
     509             :   E_FIELD(ID_CODEC_PRIVATE, TYPE_BINARY, struct track_entry, codec_private),
     510             :   E_FIELD(ID_CODEC_DELAY, TYPE_UINT, struct track_entry, codec_delay),
     511             :   E_FIELD(ID_SEEK_PREROLL, TYPE_UINT, struct track_entry, seek_preroll),
     512             :   E_FIELD(ID_DEFAULT_DURATION, TYPE_UINT, struct track_entry, default_duration),
     513             :   E_SINGLE_MASTER(ID_VIDEO, TYPE_MASTER, struct track_entry, video),
     514             :   E_SINGLE_MASTER(ID_AUDIO, TYPE_MASTER, struct track_entry, audio),
     515             :   E_SINGLE_MASTER(ID_CONTENT_ENCODINGS, TYPE_MASTER, struct track_entry, content_encodings),
     516             :   E_LAST
     517             : };
     518             : 
     519             : static struct ebml_element_desc ne_tracks_elements[] = {
     520             :   E_MASTER(ID_TRACK_ENTRY, TYPE_MASTER, struct tracks, track_entry),
     521             :   E_LAST
     522             : };
     523             : 
     524             : static struct ebml_element_desc ne_cue_track_positions_elements[] = {
     525             :   E_FIELD(ID_CUE_TRACK, TYPE_UINT, struct cue_track_positions, track),
     526             :   E_FIELD(ID_CUE_CLUSTER_POSITION, TYPE_UINT, struct cue_track_positions, cluster_position),
     527             :   E_FIELD(ID_CUE_BLOCK_NUMBER, TYPE_UINT, struct cue_track_positions, block_number),
     528             :   E_LAST
     529             : };
     530             : 
     531             : static struct ebml_element_desc ne_cue_point_elements[] = {
     532             :   E_FIELD(ID_CUE_TIME, TYPE_UINT, struct cue_point, time),
     533             :   E_MASTER(ID_CUE_TRACK_POSITIONS, TYPE_MASTER, struct cue_point, cue_track_positions),
     534             :   E_LAST
     535             : };
     536             : 
     537             : static struct ebml_element_desc ne_cues_elements[] = {
     538             :   E_MASTER(ID_CUE_POINT, TYPE_MASTER, struct cues, cue_point),
     539             :   E_LAST
     540             : };
     541             : 
     542             : static struct ebml_element_desc ne_segment_elements[] = {
     543             :   E_MASTER(ID_SEEK_HEAD, TYPE_MASTER, struct segment, seek_head),
     544             :   E_SINGLE_MASTER(ID_INFO, TYPE_MASTER, struct segment, info),
     545             :   E_SUSPEND(ID_CLUSTER, TYPE_MASTER),
     546             :   E_SINGLE_MASTER(ID_TRACKS, TYPE_MASTER, struct segment, tracks),
     547             :   E_SINGLE_MASTER(ID_CUES, TYPE_MASTER, struct segment, cues),
     548             :   E_LAST
     549             : };
     550             : 
     551             : static struct ebml_element_desc ne_top_level_elements[] = {
     552             :   E_SINGLE_MASTER(ID_EBML, TYPE_MASTER, nestegg, ebml),
     553             :   E_SINGLE_MASTER_O(ID_SEGMENT, TYPE_MASTER, nestegg, segment),
     554             :   E_LAST
     555             : };
     556             : 
     557             : #undef E_FIELD
     558             : #undef E_MASTER
     559             : #undef E_SINGLE_MASTER_O
     560             : #undef E_SINGLE_MASTER
     561             : #undef E_SUSPEND
     562             : #undef E_LAST
     563             : 
     564             : static struct pool_ctx *
     565           0 : ne_pool_init(void)
     566             : {
     567           0 :   return calloc(1, sizeof(struct pool_ctx));
     568             : }
     569             : 
     570             : static void
     571           0 : ne_pool_destroy(struct pool_ctx * pool)
     572             : {
     573           0 :   struct pool_node * node = pool->head;
     574           0 :   while (node) {
     575           0 :     struct pool_node * old = node;
     576           0 :     node = node->next;
     577           0 :     free(old->data);
     578           0 :     free(old);
     579             :   }
     580           0 :   free(pool);
     581           0 : }
     582             : 
     583             : static void *
     584           0 : ne_pool_alloc(size_t size, struct pool_ctx * pool)
     585             : {
     586             :   struct pool_node * node;
     587             : 
     588           0 :   node = calloc(1, sizeof(*node));
     589           0 :   if (!node)
     590           0 :     return NULL;
     591             : 
     592           0 :   node->data = calloc(1, size);
     593           0 :   if (!node->data) {
     594           0 :     free(node);
     595           0 :     return NULL;
     596             :   }
     597             : 
     598           0 :   node->next = pool->head;
     599           0 :   pool->head = node;
     600             : 
     601           0 :   return node->data;
     602             : }
     603             : 
     604             : static void *
     605           0 : ne_alloc(size_t size)
     606             : {
     607           0 :   return calloc(1, size);
     608             : }
     609             : 
     610             : static int
     611           0 : ne_io_read(nestegg_io * io, void * buffer, size_t length)
     612             : {
     613           0 :   return io->read(buffer, length, io->userdata);
     614             : }
     615             : 
     616             : static int
     617           0 : ne_io_seek(nestegg_io * io, int64_t offset, int whence)
     618             : {
     619           0 :   return io->seek(offset, whence, io->userdata);
     620             : }
     621             : 
     622             : static int
     623           0 : ne_io_read_skip(nestegg_io * io, size_t length)
     624             : {
     625             :   size_t get;
     626             :   unsigned char buf[8192];
     627           0 :   int r = 1;
     628             : 
     629           0 :   while (length > 0) {
     630           0 :     get = length < sizeof(buf) ? length : sizeof(buf);
     631           0 :     r = ne_io_read(io, buf, get);
     632           0 :     if (r != 1)
     633           0 :       break;
     634           0 :     length -= get;
     635             :   }
     636             : 
     637           0 :   return r;
     638             : }
     639             : 
     640             : static int64_t
     641           0 : ne_io_tell(nestegg_io * io)
     642             : {
     643           0 :   return io->tell(io->userdata);
     644             : }
     645             : 
     646             : static int
     647           0 : ne_bare_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length, enum vint_mask maskflag)
     648             : {
     649             :   int r;
     650             :   unsigned char b;
     651           0 :   size_t maxlen = 8;
     652           0 :   unsigned int count = 1, mask = 1 << 7;
     653             : 
     654           0 :   r = ne_io_read(io, &b, 1);
     655           0 :   if (r != 1)
     656           0 :     return r;
     657             : 
     658           0 :   while (count < maxlen) {
     659           0 :     if ((b & mask) != 0)
     660           0 :       break;
     661           0 :     mask >>= 1;
     662           0 :     count += 1;
     663             :   }
     664             : 
     665           0 :   if (length)
     666           0 :     *length = count;
     667           0 :   *value = b;
     668             : 
     669           0 :   if (maskflag == MASK_FIRST_BIT)
     670           0 :     *value = b & ~mask;
     671             : 
     672           0 :   while (--count) {
     673           0 :     r = ne_io_read(io, &b, 1);
     674           0 :     if (r != 1)
     675           0 :       return r;
     676           0 :     *value <<= 8;
     677           0 :     *value |= b;
     678             :   }
     679             : 
     680           0 :   return 1;
     681             : }
     682             : 
     683             : static int
     684           0 : ne_read_id(nestegg_io * io, uint64_t * value, uint64_t * length)
     685             : {
     686           0 :   return ne_bare_read_vint(io, value, length, MASK_NONE);
     687             : }
     688             : 
     689             : static int
     690           0 : ne_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length)
     691             : {
     692           0 :   return ne_bare_read_vint(io, value, length, MASK_FIRST_BIT);
     693             : }
     694             : 
     695             : static int
     696           0 : ne_read_svint(nestegg_io * io, int64_t * value, uint64_t * length)
     697             : {
     698             :   int r;
     699             :   uint64_t uvalue;
     700             :   uint64_t ulength;
     701           0 :   int64_t svint_subtr[] = {
     702             :     0x3f, 0x1fff,
     703             :     0xfffff, 0x7ffffff,
     704             :     0x3ffffffffLL, 0x1ffffffffffLL,
     705             :     0xffffffffffffLL, 0x7fffffffffffffLL
     706             :   };
     707             : 
     708           0 :   r = ne_bare_read_vint(io, &uvalue, &ulength, MASK_FIRST_BIT);
     709           0 :   if (r != 1)
     710           0 :     return r;
     711           0 :   *value = uvalue - svint_subtr[ulength - 1];
     712           0 :   if (length)
     713           0 :     *length = ulength;
     714           0 :   return r;
     715             : }
     716             : 
     717             : static int
     718           0 : ne_read_uint(nestegg_io * io, uint64_t * val, uint64_t length)
     719             : {
     720             :   unsigned char b;
     721             :   int r;
     722             : 
     723           0 :   if (length == 0 || length > 8)
     724           0 :     return -1;
     725           0 :   r = ne_io_read(io, &b, 1);
     726           0 :   if (r != 1)
     727           0 :     return r;
     728           0 :   *val = b;
     729           0 :   while (--length) {
     730           0 :     r = ne_io_read(io, &b, 1);
     731           0 :     if (r != 1)
     732           0 :       return r;
     733           0 :     *val <<= 8;
     734           0 :     *val |= b;
     735             :   }
     736           0 :   return 1;
     737             : }
     738             : 
     739             : static int
     740           0 : ne_read_int(nestegg_io * io, int64_t * val, uint64_t length)
     741             : {
     742             :   int r;
     743             :   uint64_t uval, base;
     744             : 
     745           0 :   r = ne_read_uint(io, &uval, length);
     746           0 :   if (r != 1)
     747           0 :     return r;
     748             : 
     749           0 :   if (length < sizeof(int64_t)) {
     750           0 :     base = 1;
     751           0 :     base <<= length * 8 - 1;
     752           0 :     if (uval >= base) {
     753           0 :       base = 1;
     754           0 :       base <<= length * 8;
     755             :     } else {
     756           0 :       base = 0;
     757             :     }
     758           0 :     *val = uval - base;
     759             :   } else {
     760           0 :     *val = (int64_t) uval;
     761             :   }
     762             : 
     763           0 :   return 1;
     764             : }
     765             : 
     766             : static int
     767           0 : ne_read_float(nestegg_io * io, double * val, uint64_t length)
     768             : {
     769             :   union {
     770             :     uint64_t u;
     771             :     float f;
     772             :     double d;
     773             :   } value;
     774             :   int r;
     775             : 
     776             :   /* Length == 10 not implemented. */
     777           0 :   if (length != 4 && length != 8)
     778           0 :     return -1;
     779           0 :   r = ne_read_uint(io, &value.u, length);
     780           0 :   if (r != 1)
     781           0 :     return r;
     782           0 :   if (length == 4)
     783           0 :     *val = value.f;
     784             :   else
     785           0 :     *val = value.d;
     786           0 :   return 1;
     787             : }
     788             : 
     789             : static int
     790           0 : ne_read_string(nestegg * ctx, char ** val, uint64_t length)
     791             : {
     792             :   char * str;
     793             :   int r;
     794             : 
     795           0 :   if (length > LIMIT_STRING)
     796           0 :     return -1;
     797           0 :   str = ne_pool_alloc(length + 1, ctx->alloc_pool);
     798           0 :   if (!str)
     799           0 :     return -1;
     800           0 :   if (length) {
     801           0 :     r = ne_io_read(ctx->io, (unsigned char *) str, length);
     802           0 :     if (r != 1)
     803           0 :       return r;
     804             :   }
     805           0 :   str[length] = '\0';
     806           0 :   *val = str;
     807           0 :   return 1;
     808             : }
     809             : 
     810             : static int
     811           0 : ne_read_binary(nestegg * ctx, struct ebml_binary * val, uint64_t length)
     812             : {
     813           0 :   if (length == 0 || length > LIMIT_BINARY)
     814           0 :     return -1;
     815           0 :   val->data = ne_pool_alloc(length, ctx->alloc_pool);
     816           0 :   if (!val->data)
     817           0 :     return -1;
     818           0 :   val->length = length;
     819           0 :   return ne_io_read(ctx->io, val->data, length);
     820             : }
     821             : 
     822             : static int
     823           0 : ne_get_uint(struct ebml_type type, uint64_t * value)
     824             : {
     825           0 :   if (!type.read)
     826           0 :     return -1;
     827             : 
     828           0 :   assert(type.type == TYPE_UINT);
     829             : 
     830           0 :   *value = type.v.u;
     831             : 
     832           0 :   return 0;
     833             : }
     834             : 
     835             : static int
     836           0 : ne_get_float(struct ebml_type type, double * value)
     837             : {
     838           0 :   if (!type.read)
     839           0 :     return -1;
     840             : 
     841           0 :   assert(type.type == TYPE_FLOAT);
     842             : 
     843           0 :   *value = type.v.f;
     844             : 
     845           0 :   return 0;
     846             : }
     847             : 
     848             : static int
     849           0 : ne_get_string(struct ebml_type type, char ** value)
     850             : {
     851           0 :   if (!type.read)
     852           0 :     return -1;
     853             : 
     854           0 :   assert(type.type == TYPE_STRING);
     855             : 
     856           0 :   *value = type.v.s;
     857             : 
     858           0 :   return 0;
     859             : }
     860             : 
     861             : static int
     862           0 : ne_get_binary(struct ebml_type type, struct ebml_binary * value)
     863             : {
     864           0 :   if (!type.read)
     865           0 :     return -1;
     866             : 
     867           0 :   assert(type.type == TYPE_BINARY);
     868             : 
     869           0 :   *value = type.v.b;
     870             : 
     871           0 :   return 0;
     872             : }
     873             : 
     874             : static int
     875           0 : ne_is_ancestor_element(uint64_t id, struct list_node * ancestor)
     876             : {
     877             :   struct ebml_element_desc * element;
     878             : 
     879           0 :   for (; ancestor; ancestor = ancestor->previous)
     880           0 :     for (element = ancestor->node; element->id; ++element)
     881           0 :       if (element->id == id)
     882           0 :         return 1;
     883             : 
     884           0 :   return 0;
     885             : }
     886             : 
     887             : static struct ebml_element_desc *
     888           0 : ne_find_element(uint64_t id, struct ebml_element_desc * elements)
     889             : {
     890             :   struct ebml_element_desc * element;
     891             : 
     892           0 :   for (element = elements; element->id; ++element)
     893           0 :     if (element->id == id)
     894           0 :       return element;
     895             : 
     896           0 :   return NULL;
     897             : }
     898             : 
     899             : static int
     900           0 : ne_ctx_push(nestegg * ctx, struct ebml_element_desc * ancestor, void * data)
     901             : {
     902             :   struct list_node * item;
     903             : 
     904           0 :   item = ne_alloc(sizeof(*item));
     905           0 :   if (!item)
     906           0 :     return -1;
     907           0 :   item->previous = ctx->ancestor;
     908           0 :   item->node = ancestor;
     909           0 :   item->data = data;
     910           0 :   ctx->ancestor = item;
     911           0 :   return 0;
     912             : }
     913             : 
     914             : static void
     915           0 : ne_ctx_pop(nestegg * ctx)
     916             : {
     917             :   struct list_node * item;
     918             : 
     919           0 :   item = ctx->ancestor;
     920           0 :   ctx->ancestor = item->previous;
     921           0 :   free(item);
     922           0 : }
     923             : 
     924             : static int
     925           0 : ne_ctx_save(nestegg * ctx, struct saved_state * s)
     926             : {
     927           0 :   s->stream_offset = ne_io_tell(ctx->io);
     928           0 :   if (s->stream_offset < 0)
     929           0 :     return -1;
     930           0 :   s->last_id = ctx->last_id;
     931           0 :   s->last_size = ctx->last_size;
     932           0 :   s->last_valid = ctx->last_valid;
     933           0 :   return 0;
     934             : }
     935             : 
     936             : static int
     937           0 : ne_ctx_restore(nestegg * ctx, struct saved_state * s)
     938             : {
     939             :   int r;
     940             : 
     941           0 :   if (s->stream_offset < 0)
     942           0 :     return -1;
     943           0 :   r = ne_io_seek(ctx->io, s->stream_offset, NESTEGG_SEEK_SET);
     944           0 :   if (r != 0)
     945           0 :     return -1;
     946           0 :   ctx->last_id = s->last_id;
     947           0 :   ctx->last_size = s->last_size;
     948           0 :   ctx->last_valid = s->last_valid;
     949           0 :   return 0;
     950             : }
     951             : 
     952             : static int
     953           0 : ne_peek_element(nestegg * ctx, uint64_t * id, uint64_t * size)
     954             : {
     955             :   int r;
     956             : 
     957           0 :   if (ctx->last_valid) {
     958           0 :     if (id)
     959           0 :       *id = ctx->last_id;
     960           0 :     if (size)
     961           0 :       *size = ctx->last_size;
     962           0 :     return 1;
     963             :   }
     964             : 
     965           0 :   r = ne_read_id(ctx->io, &ctx->last_id, NULL);
     966           0 :   if (r != 1)
     967           0 :     return r;
     968             : 
     969           0 :   r = ne_read_vint(ctx->io, &ctx->last_size, NULL);
     970           0 :   if (r != 1)
     971           0 :     return r;
     972             : 
     973           0 :   if (id)
     974           0 :     *id = ctx->last_id;
     975           0 :   if (size)
     976           0 :     *size = ctx->last_size;
     977             : 
     978           0 :   ctx->last_valid = 1;
     979             : 
     980           0 :   return 1;
     981             : }
     982             : 
     983             : static int
     984           0 : ne_read_element(nestegg * ctx, uint64_t * id, uint64_t * size)
     985             : {
     986             :   int r;
     987             : 
     988           0 :   r = ne_peek_element(ctx, id, size);
     989           0 :   if (r != 1)
     990           0 :     return r;
     991             : 
     992           0 :   ctx->last_valid = 0;
     993             : 
     994           0 :   return 1;
     995             : }
     996             : 
     997             : static int
     998           0 : ne_read_master(nestegg * ctx, struct ebml_element_desc * desc)
     999             : {
    1000             :   struct ebml_list * list;
    1001             :   struct ebml_list_node * node, * oldtail;
    1002             : 
    1003           0 :   assert(desc->type == TYPE_MASTER && desc->flags & DESC_FLAG_MULTI);
    1004             : 
    1005           0 :   ctx->log(ctx, NESTEGG_LOG_DEBUG, "multi master element %llx (%s)",
    1006             :            desc->id, desc->name);
    1007             : 
    1008           0 :   list = (struct ebml_list *) (ctx->ancestor->data + desc->offset);
    1009             : 
    1010           0 :   node = ne_pool_alloc(sizeof(*node), ctx->alloc_pool);
    1011           0 :   if (!node)
    1012           0 :     return -1;
    1013           0 :   node->id = desc->id;
    1014           0 :   node->data = ne_pool_alloc(desc->size, ctx->alloc_pool);
    1015           0 :   if (!node->data)
    1016           0 :     return -1;
    1017             : 
    1018           0 :   oldtail = list->tail;
    1019           0 :   if (oldtail)
    1020           0 :     oldtail->next = node;
    1021           0 :   list->tail = node;
    1022           0 :   if (!list->head)
    1023           0 :     list->head = node;
    1024             : 
    1025           0 :   ctx->log(ctx, NESTEGG_LOG_DEBUG, " -> using data %p", node->data);
    1026             : 
    1027           0 :   if (ne_ctx_push(ctx, desc->children, node->data) < 0)
    1028           0 :     return -1;
    1029             : 
    1030           0 :   return 0;
    1031             : }
    1032             : 
    1033             : static int
    1034           0 : ne_read_single_master(nestegg * ctx, struct ebml_element_desc * desc)
    1035             : {
    1036           0 :   assert(desc->type == TYPE_MASTER && !(desc->flags & DESC_FLAG_MULTI));
    1037             : 
    1038           0 :   ctx->log(ctx, NESTEGG_LOG_DEBUG, "single master element %llx (%s)",
    1039             :            desc->id, desc->name);
    1040           0 :   ctx->log(ctx, NESTEGG_LOG_DEBUG, " -> using data %p (%u)",
    1041           0 :            ctx->ancestor->data + desc->offset, desc->offset);
    1042             : 
    1043           0 :   return ne_ctx_push(ctx, desc->children, ctx->ancestor->data + desc->offset);
    1044             : }
    1045             : 
    1046             : static int
    1047           0 : ne_read_simple(nestegg * ctx, struct ebml_element_desc * desc, size_t length)
    1048             : {
    1049             :   struct ebml_type * storage;
    1050           0 :   int r = -1;
    1051             : 
    1052           0 :   storage = (struct ebml_type *) (ctx->ancestor->data + desc->offset);
    1053             : 
    1054           0 :   if (storage->read) {
    1055           0 :     ctx->log(ctx, NESTEGG_LOG_DEBUG, "element %llx (%s) already read, skipping",
    1056             :              desc->id, desc->name);
    1057           0 :     return 0;
    1058             :   }
    1059             : 
    1060           0 :   storage->type = desc->type;
    1061             : 
    1062           0 :   ctx->log(ctx, NESTEGG_LOG_DEBUG, "element %llx (%s) -> %p (%u)",
    1063             :            desc->id, desc->name, storage, desc->offset);
    1064             : 
    1065           0 :   switch (desc->type) {
    1066             :   case TYPE_UINT:
    1067           0 :     r = ne_read_uint(ctx->io, &storage->v.u, length);
    1068           0 :     break;
    1069             :   case TYPE_FLOAT:
    1070           0 :     r = ne_read_float(ctx->io, &storage->v.f, length);
    1071           0 :     break;
    1072             :   case TYPE_STRING:
    1073           0 :     r = ne_read_string(ctx, &storage->v.s, length);
    1074           0 :     break;
    1075             :   case TYPE_BINARY:
    1076           0 :     r = ne_read_binary(ctx, &storage->v.b, length);
    1077           0 :     break;
    1078             :   case TYPE_MASTER:
    1079             :   case TYPE_UNKNOWN:
    1080             :   default:
    1081           0 :     assert(0);
    1082             :     break;
    1083             :   }
    1084             : 
    1085           0 :   if (r == 1)
    1086           0 :     storage->read = 1;
    1087             : 
    1088           0 :   return r;
    1089             : }
    1090             : 
    1091             : static int
    1092           0 : ne_parse(nestegg * ctx, struct ebml_element_desc * top_level, int64_t max_offset)
    1093             : {
    1094             :   int r;
    1095             :   int64_t * data_offset;
    1096             :   uint64_t id, size, peeked_id;
    1097             :   struct ebml_element_desc * element;
    1098             : 
    1099           0 :   assert(ctx->ancestor);
    1100             : 
    1101             :   for (;;) {
    1102           0 :     if (max_offset > 0 && ne_io_tell(ctx->io) >= max_offset) {
    1103             :       /* Reached end of offset allowed for parsing - return gracefully */
    1104           0 :       r = 1;
    1105           0 :       break;
    1106             :     }
    1107           0 :     r = ne_peek_element(ctx, &id, &size);
    1108           0 :     if (r != 1)
    1109           0 :       break;
    1110           0 :     peeked_id = id;
    1111             : 
    1112           0 :     element = ne_find_element(id, ctx->ancestor->node);
    1113           0 :     if (element) {
    1114           0 :       if (element->flags & DESC_FLAG_SUSPEND) {
    1115           0 :         assert(element->id == ID_CLUSTER && element->type == TYPE_MASTER);
    1116           0 :         ctx->log(ctx, NESTEGG_LOG_DEBUG, "suspend parse at %llx", id);
    1117           0 :         r = 1;
    1118           0 :         break;
    1119             :       }
    1120             : 
    1121           0 :       r = ne_read_element(ctx, &id, &size);
    1122           0 :       if (r != 1)
    1123           0 :         break;
    1124           0 :       assert(id == peeked_id);
    1125             : 
    1126           0 :       if (element->flags & DESC_FLAG_OFFSET) {
    1127           0 :         data_offset = (int64_t *) (ctx->ancestor->data + element->data_offset);
    1128           0 :         *data_offset = ne_io_tell(ctx->io);
    1129           0 :         if (*data_offset < 0) {
    1130           0 :           r = -1;
    1131           0 :           break;
    1132             :         }
    1133             :       }
    1134             : 
    1135           0 :       if (element->type == TYPE_MASTER) {
    1136           0 :         if (element->flags & DESC_FLAG_MULTI) {
    1137           0 :           if (ne_read_master(ctx, element) < 0)
    1138           0 :             break;
    1139             :         } else {
    1140           0 :           if (ne_read_single_master(ctx, element) < 0)
    1141           0 :             break;
    1142             :         }
    1143           0 :         continue;
    1144             :       } else {
    1145           0 :         r = ne_read_simple(ctx, element, size);
    1146           0 :         if (r < 0)
    1147           0 :           break;
    1148             :       }
    1149           0 :     } else if (ne_is_ancestor_element(id, ctx->ancestor->previous)) {
    1150           0 :       ctx->log(ctx, NESTEGG_LOG_DEBUG, "parent element %llx", id);
    1151           0 :       if (top_level && ctx->ancestor->node == top_level) {
    1152           0 :         ctx->log(ctx, NESTEGG_LOG_DEBUG, "*** parse about to back up past top_level");
    1153           0 :         r = 1;
    1154           0 :         break;
    1155             :       }
    1156           0 :       ne_ctx_pop(ctx);
    1157             :     } else {
    1158           0 :       r = ne_read_element(ctx, &id, &size);
    1159           0 :       if (r != 1)
    1160           0 :         break;
    1161             : 
    1162           0 :       if (id != ID_VOID && id != ID_CRC32)
    1163           0 :         ctx->log(ctx, NESTEGG_LOG_DEBUG, "unknown element %llx", id);
    1164           0 :       r = ne_io_read_skip(ctx->io, size);
    1165           0 :       if (r != 1)
    1166           0 :         break;
    1167             :     }
    1168             :   }
    1169             : 
    1170           0 :   if (r != 1)
    1171           0 :     while (ctx->ancestor)
    1172           0 :       ne_ctx_pop(ctx);
    1173             : 
    1174           0 :   return r;
    1175             : }
    1176             : 
    1177             : static int
    1178           0 : ne_read_block_encryption(nestegg * ctx, struct track_entry const * entry,
    1179             :                          uint64_t * encoding_type, uint64_t * encryption_algo,
    1180             :                          uint64_t * encryption_mode)
    1181             : {
    1182             :   struct content_encoding * encoding;
    1183             :   struct content_encryption * encryption;
    1184             :   struct content_enc_aes_settings * aes_settings;
    1185             : 
    1186           0 :   *encoding_type = 0;
    1187           0 :   if (entry->content_encodings.content_encoding.head) {
    1188           0 :     encoding = entry->content_encodings.content_encoding.head->data;
    1189           0 :     if (ne_get_uint(encoding->content_encoding_type, encoding_type) != 0)
    1190           0 :       return -1;
    1191             : 
    1192           0 :     if (*encoding_type == NESTEGG_ENCODING_ENCRYPTION) {
    1193             :       /* Metadata states content is encrypted */
    1194           0 :       if (!encoding->content_encryption.head)
    1195           0 :         return -1;
    1196             : 
    1197           0 :       encryption = encoding->content_encryption.head->data;
    1198           0 :       if (ne_get_uint(encryption->content_enc_algo, encryption_algo) != 0) {
    1199           0 :         ctx->log(ctx, NESTEGG_LOG_ERROR, "No ContentEncAlgo element found");
    1200           0 :         return -1;
    1201             :       }
    1202             : 
    1203           0 :       if (*encryption_algo != CONTENT_ENC_ALGO_AES) {
    1204           0 :         ctx->log(ctx, NESTEGG_LOG_ERROR, "Disallowed ContentEncAlgo used");
    1205           0 :         return -1;
    1206             :       }
    1207             : 
    1208           0 :       if (!encryption->content_enc_aes_settings.head) {
    1209           0 :         ctx->log(ctx, NESTEGG_LOG_ERROR, "No ContentEncAESSettings element found");
    1210           0 :         return -1;
    1211             :       }
    1212             : 
    1213           0 :       aes_settings = encryption->content_enc_aes_settings.head->data;
    1214           0 :       *encryption_mode = AES_SETTINGS_CIPHER_CTR;
    1215           0 :       ne_get_uint(aes_settings->aes_settings_cipher_mode, encryption_mode);
    1216             : 
    1217           0 :       if (*encryption_mode != AES_SETTINGS_CIPHER_CTR) {
    1218           0 :         ctx->log(ctx, NESTEGG_LOG_ERROR, "Disallowed AESSettingsCipherMode used");
    1219           0 :         return -1;
    1220             :       }
    1221             :     }
    1222             :   }
    1223           0 :   return 1;
    1224             : }
    1225             : 
    1226             : static int
    1227           0 : ne_read_xiph_lace_value(nestegg_io * io, uint64_t * value, size_t * consumed)
    1228             : {
    1229             :   int r;
    1230             :   uint64_t lace;
    1231             : 
    1232           0 :   r = ne_read_uint(io, &lace, 1);
    1233           0 :   if (r != 1)
    1234           0 :     return r;
    1235           0 :   *consumed += 1;
    1236             : 
    1237           0 :   *value = lace;
    1238           0 :   while (lace == 255) {
    1239           0 :     r = ne_read_uint(io, &lace, 1);
    1240           0 :     if (r != 1)
    1241           0 :       return r;
    1242           0 :     *consumed += 1;
    1243           0 :     *value += lace;
    1244             :   }
    1245             : 
    1246           0 :   return 1;
    1247             : }
    1248             : 
    1249             : static int
    1250           0 : ne_read_xiph_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
    1251             : {
    1252             :   int r;
    1253           0 :   size_t i = 0;
    1254           0 :   uint64_t sum = 0;
    1255             : 
    1256           0 :   while (--n) {
    1257           0 :     r = ne_read_xiph_lace_value(io, &sizes[i], read);
    1258           0 :     if (r != 1)
    1259           0 :       return r;
    1260           0 :     sum += sizes[i];
    1261           0 :     i += 1;
    1262             :   }
    1263             : 
    1264           0 :   if (*read + sum > block)
    1265           0 :     return -1;
    1266             : 
    1267             :   /* Last frame is the remainder of the block. */
    1268           0 :   sizes[i] = block - *read - sum;
    1269           0 :   return 1;
    1270             : }
    1271             : 
    1272             : static int
    1273           0 : ne_read_ebml_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
    1274             : {
    1275             :   int r;
    1276             :   uint64_t lace, sum, length;
    1277             :   int64_t slace;
    1278           0 :   size_t i = 0;
    1279             : 
    1280           0 :   r = ne_read_vint(io, &lace, &length);
    1281           0 :   if (r != 1)
    1282           0 :     return r;
    1283           0 :   *read += length;
    1284             : 
    1285           0 :   sizes[i] = lace;
    1286           0 :   sum = sizes[i];
    1287             : 
    1288           0 :   i += 1;
    1289           0 :   n -= 1;
    1290             : 
    1291           0 :   while (--n) {
    1292           0 :     r = ne_read_svint(io, &slace, &length);
    1293           0 :     if (r != 1)
    1294           0 :       return r;
    1295           0 :     *read += length;
    1296           0 :     sizes[i] = sizes[i - 1] + slace;
    1297           0 :     sum += sizes[i];
    1298           0 :     i += 1;
    1299             :   }
    1300             : 
    1301           0 :   if (*read + sum > block)
    1302           0 :     return -1;
    1303             : 
    1304             :   /* Last frame is the remainder of the block. */
    1305           0 :   sizes[i] = block - *read - sum;
    1306           0 :   return 1;
    1307             : }
    1308             : 
    1309             : static uint64_t
    1310           0 : ne_get_timecode_scale(nestegg * ctx)
    1311             : {
    1312             :   uint64_t scale;
    1313             : 
    1314           0 :   if (ne_get_uint(ctx->segment.info.timecode_scale, &scale) != 0)
    1315           0 :     scale = 1000000;
    1316             : 
    1317           0 :   return scale;
    1318             : }
    1319             : 
    1320             : static int
    1321           0 : ne_map_track_number_to_index(nestegg * ctx,
    1322             :                              unsigned int track_number,
    1323             :                              unsigned int * track_index)
    1324             : {
    1325             :   struct ebml_list_node * node;
    1326             :   struct track_entry * t_entry;
    1327           0 :   uint64_t t_number = 0;
    1328             : 
    1329           0 :   if (!track_index)
    1330           0 :     return -1;
    1331           0 :   *track_index = 0;
    1332             : 
    1333           0 :   if (track_number == 0)
    1334           0 :     return -1;
    1335             : 
    1336           0 :   node = ctx->segment.tracks.track_entry.head;
    1337           0 :   while (node) {
    1338           0 :     assert(node->id == ID_TRACK_ENTRY);
    1339           0 :     t_entry = node->data;
    1340           0 :     if (ne_get_uint(t_entry->number, &t_number) != 0)
    1341           0 :       return -1;
    1342           0 :     if (t_number == track_number)
    1343           0 :       return 0;
    1344           0 :     *track_index += 1;
    1345           0 :     node = node->next;
    1346             :   }
    1347             : 
    1348           0 :   return -1;
    1349             : }
    1350             : 
    1351             : static struct track_entry *
    1352           0 : ne_find_track_entry(nestegg * ctx, unsigned int track)
    1353             : {
    1354             :   struct ebml_list_node * node;
    1355           0 :   unsigned int tracks = 0;
    1356             : 
    1357           0 :   node = ctx->segment.tracks.track_entry.head;
    1358           0 :   while (node) {
    1359           0 :     assert(node->id == ID_TRACK_ENTRY);
    1360           0 :     if (track == tracks)
    1361           0 :       return node->data;
    1362           0 :     tracks += 1;
    1363           0 :     node = node->next;
    1364             :   }
    1365             : 
    1366           0 :   return NULL;
    1367             : }
    1368             : 
    1369             : static struct frame *
    1370           0 : ne_alloc_frame(void)
    1371             : {
    1372           0 :   struct frame * f = ne_alloc(sizeof(*f));
    1373             : 
    1374           0 :   if (!f)
    1375           0 :     return NULL;
    1376             : 
    1377           0 :   f->data = NULL;
    1378           0 :   f->length = 0;
    1379           0 :   f->frame_encryption = NULL;
    1380           0 :   f->next = NULL;
    1381             : 
    1382           0 :   return f;
    1383             : }
    1384             : 
    1385             : static struct frame_encryption *
    1386           0 : ne_alloc_frame_encryption(void)
    1387             : {
    1388           0 :   struct frame_encryption * f = ne_alloc(sizeof(*f));
    1389             : 
    1390           0 :   if (!f)
    1391           0 :     return NULL;
    1392             : 
    1393           0 :   f->iv = NULL;
    1394           0 :   f->length = 0;
    1395           0 :   f->signal_byte = 0;
    1396           0 :   f->num_partitions = 0;
    1397           0 :   f->partition_offsets = NULL;
    1398             : 
    1399           0 :   return f;
    1400             : }
    1401             : 
    1402             : static void
    1403           0 : ne_free_frame(struct frame * f)
    1404             : {
    1405           0 :   if (f->frame_encryption) {
    1406           0 :     free(f->frame_encryption->iv);
    1407           0 :     free(f->frame_encryption->partition_offsets);
    1408             :   }
    1409             : 
    1410           0 :   free(f->frame_encryption);
    1411           0 :   free(f->data);
    1412           0 :   free(f);
    1413           0 : }
    1414             : 
    1415             : static int
    1416           0 : ne_read_block(nestegg * ctx, uint64_t block_id, uint64_t block_size, nestegg_packet ** data)
    1417             : {
    1418             :   int r;
    1419             :   int64_t timecode, abs_timecode;
    1420             :   nestegg_packet * pkt;
    1421             :   struct frame * f, * last;
    1422             :   struct track_entry * entry;
    1423             :   double track_scale;
    1424             :   uint64_t track_number, length, frame_sizes[256], cluster_tc, flags, frames, tc_scale, total,
    1425             :            encoding_type, encryption_algo, encryption_mode;
    1426             :   unsigned int i, lacing, track;
    1427           0 :   uint8_t signal_byte, keyframe = NESTEGG_PACKET_HAS_KEYFRAME_UNKNOWN, j = 0;
    1428           0 :   size_t consumed = 0, data_size, encryption_size;
    1429             : 
    1430           0 :   *data = NULL;
    1431             : 
    1432           0 :   if (block_size > LIMIT_BLOCK)
    1433           0 :     return -1;
    1434             : 
    1435           0 :   r = ne_read_vint(ctx->io, &track_number, &length);
    1436           0 :   if (r != 1)
    1437           0 :     return r;
    1438             : 
    1439           0 :   if (track_number == 0)
    1440           0 :     return -1;
    1441             : 
    1442           0 :   consumed += length;
    1443             : 
    1444           0 :   r = ne_read_int(ctx->io, &timecode, 2);
    1445           0 :   if (r != 1)
    1446           0 :     return r;
    1447             : 
    1448           0 :   consumed += 2;
    1449             : 
    1450           0 :   r = ne_read_uint(ctx->io, &flags, 1);
    1451           0 :   if (r != 1)
    1452           0 :     return r;
    1453             : 
    1454           0 :   consumed += 1;
    1455             : 
    1456           0 :   frames = 0;
    1457             : 
    1458             :   /* Simple blocks have an explicit flag for if the contents a keyframes*/
    1459           0 :   if (block_id == ID_SIMPLE_BLOCK)
    1460           0 :     keyframe = (flags & SIMPLE_BLOCK_FLAGS_KEYFRAME) == SIMPLE_BLOCK_FLAGS_KEYFRAME ?
    1461           0 :                                                         NESTEGG_PACKET_HAS_KEYFRAME_TRUE :
    1462             :                                                         NESTEGG_PACKET_HAS_KEYFRAME_FALSE;
    1463             : 
    1464             :   /* Flags are different between Block and SimpleBlock, but lacing is
    1465             :      encoded the same way. */
    1466           0 :   lacing = (flags & BLOCK_FLAGS_LACING) >> 1;
    1467             : 
    1468           0 :   switch (lacing) {
    1469             :   case LACING_NONE:
    1470           0 :     frames = 1;
    1471           0 :     break;
    1472             :   case LACING_XIPH:
    1473             :   case LACING_FIXED:
    1474             :   case LACING_EBML:
    1475           0 :     r = ne_read_uint(ctx->io, &frames, 1);
    1476           0 :     if (r != 1)
    1477           0 :       return r;
    1478           0 :     consumed += 1;
    1479           0 :     frames += 1;
    1480           0 :     break;
    1481             :   default:
    1482           0 :     assert(0);
    1483             :     return -1;
    1484             :   }
    1485             : 
    1486           0 :   if (frames > 256)
    1487           0 :     return -1;
    1488             : 
    1489           0 :   switch (lacing) {
    1490             :   case LACING_NONE:
    1491           0 :     frame_sizes[0] = block_size - consumed;
    1492           0 :     break;
    1493             :   case LACING_XIPH:
    1494           0 :     if (frames == 1)
    1495           0 :       return -1;
    1496           0 :     r = ne_read_xiph_lacing(ctx->io, block_size, &consumed, frames, frame_sizes);
    1497           0 :     if (r != 1)
    1498           0 :       return r;
    1499           0 :     break;
    1500             :   case LACING_FIXED:
    1501           0 :     if ((block_size - consumed) % frames)
    1502           0 :       return -1;
    1503           0 :     for (i = 0; i < frames; ++i)
    1504           0 :       frame_sizes[i] = (block_size - consumed) / frames;
    1505           0 :     break;
    1506             :   case LACING_EBML:
    1507           0 :     if (frames == 1)
    1508           0 :       return -1;
    1509           0 :     r = ne_read_ebml_lacing(ctx->io, block_size, &consumed, frames, frame_sizes);
    1510           0 :     if (r != 1)
    1511           0 :       return r;
    1512           0 :     break;
    1513             :   default:
    1514           0 :     assert(0);
    1515             :     return -1;
    1516             :   }
    1517             : 
    1518             :   /* Sanity check unlaced frame sizes against total block size. */
    1519           0 :   total = consumed;
    1520           0 :   for (i = 0; i < frames; ++i)
    1521           0 :     total += frame_sizes[i];
    1522           0 :   if (total > block_size)
    1523           0 :     return -1;
    1524             : 
    1525           0 :   if (ne_map_track_number_to_index(ctx, track_number, &track) != 0)
    1526           0 :     return -1;
    1527             : 
    1528           0 :   entry = ne_find_track_entry(ctx, track);
    1529           0 :   if (!entry)
    1530           0 :     return -1;
    1531             : 
    1532           0 :   r = ne_read_block_encryption(ctx, entry, &encoding_type, &encryption_algo, &encryption_mode);
    1533           0 :   if (r != 1)
    1534           0 :     return r;
    1535             : 
    1536             :   /* Encryption does not support lacing */
    1537           0 :   if (lacing != LACING_NONE && encoding_type == NESTEGG_ENCODING_ENCRYPTION) {
    1538           0 :     ctx->log(ctx, NESTEGG_LOG_ERROR, "Encrypted blocks may not also be laced");
    1539           0 :     return -1;
    1540             :   }
    1541             : 
    1542           0 :   track_scale = 1.0;
    1543             : 
    1544           0 :   tc_scale = ne_get_timecode_scale(ctx);
    1545           0 :   if (tc_scale == 0)
    1546           0 :     return -1;
    1547             : 
    1548           0 :   if (!ctx->read_cluster_timecode)
    1549           0 :     return -1;
    1550           0 :   cluster_tc = ctx->cluster_timecode;
    1551             : 
    1552           0 :   abs_timecode = timecode + cluster_tc;
    1553           0 :   if (abs_timecode < 0)
    1554           0 :     return -1;
    1555             : 
    1556           0 :   pkt = ne_alloc(sizeof(*pkt));
    1557           0 :   if (!pkt)
    1558           0 :     return -1;
    1559           0 :   pkt->track = track;
    1560           0 :   pkt->timecode = abs_timecode * tc_scale * track_scale;
    1561           0 :   pkt->keyframe = keyframe;
    1562             : 
    1563           0 :   ctx->log(ctx, NESTEGG_LOG_DEBUG, "%sblock t %lld pts %f f %llx frames: %llu",
    1564           0 :            block_id == ID_BLOCK ? "" : "simple", pkt->track, pkt->timecode / 1e9, flags, frames);
    1565             : 
    1566           0 :   last = NULL;
    1567           0 :   for (i = 0; i < frames; ++i) {
    1568           0 :     if (frame_sizes[i] > LIMIT_FRAME) {
    1569           0 :       nestegg_free_packet(pkt);
    1570           0 :       return -1;
    1571             :     }
    1572           0 :     f = ne_alloc_frame();
    1573           0 :     if (!f) {
    1574           0 :       nestegg_free_packet(pkt);
    1575           0 :       return -1;
    1576             :     }
    1577             :     /* Parse encryption */
    1578           0 :     if (encoding_type == NESTEGG_ENCODING_ENCRYPTION) {
    1579           0 :       r = ne_io_read(ctx->io, &signal_byte, SIGNAL_BYTE_SIZE);
    1580           0 :       if (r != 1) {
    1581           0 :         ne_free_frame(f);
    1582           0 :         nestegg_free_packet(pkt);
    1583           0 :         return r;
    1584             :       }
    1585           0 :       f->frame_encryption = ne_alloc_frame_encryption();
    1586           0 :       if (!f->frame_encryption) {
    1587           0 :         ne_free_frame(f);
    1588           0 :         nestegg_free_packet(pkt);
    1589           0 :         return -1;
    1590             :       }
    1591           0 :       f->frame_encryption->signal_byte = signal_byte;
    1592           0 :       if ((signal_byte & ENCRYPTED_BIT_MASK) == PACKET_ENCRYPTED) {
    1593           0 :         f->frame_encryption->iv = ne_alloc(IV_SIZE);
    1594           0 :         if (!f->frame_encryption->iv) {
    1595           0 :           ne_free_frame(f);
    1596           0 :           nestegg_free_packet(pkt);
    1597           0 :           return -1;
    1598             :         }
    1599           0 :         r = ne_io_read(ctx->io, f->frame_encryption->iv, IV_SIZE);
    1600           0 :         if (r != 1) {
    1601           0 :           ne_free_frame(f);
    1602           0 :           nestegg_free_packet(pkt);
    1603           0 :           return r;
    1604             :         }
    1605           0 :         f->frame_encryption->length = IV_SIZE;
    1606           0 :         encryption_size = SIGNAL_BYTE_SIZE + IV_SIZE;
    1607             : 
    1608           0 :         if ((signal_byte & PARTITIONED_BIT_MASK) == PACKET_PARTITIONED) {
    1609           0 :           r = ne_io_read(ctx->io, &f->frame_encryption->num_partitions, NUM_PACKETS_SIZE);
    1610           0 :           if (r != 1) {
    1611           0 :             ne_free_frame(f);
    1612           0 :             nestegg_free_packet(pkt);
    1613           0 :             return r;
    1614             :           }
    1615             : 
    1616           0 :           encryption_size += NUM_PACKETS_SIZE + f->frame_encryption->num_partitions * PACKET_OFFSET_SIZE;
    1617           0 :           f->frame_encryption->partition_offsets = ne_alloc(f->frame_encryption->num_partitions * PACKET_OFFSET_SIZE);
    1618             : 
    1619           0 :           for (j = 0; j < f->frame_encryption->num_partitions; ++j) {
    1620           0 :             uint64_t value = 0;
    1621           0 :             r = ne_read_uint(ctx->io, &value, PACKET_OFFSET_SIZE);
    1622           0 :             if (r != 1) {
    1623           0 :               break;
    1624             :             }
    1625             : 
    1626           0 :             f->frame_encryption->partition_offsets[j] = (uint32_t) value;
    1627             :           }
    1628             : 
    1629             :           /* If any of the partition offsets did not return 1, then fail. */
    1630           0 :           if (j != f->frame_encryption->num_partitions) {
    1631           0 :             ne_free_frame(f);
    1632           0 :             nestegg_free_packet(pkt);
    1633           0 :             return r;
    1634             :           }
    1635             :         }
    1636             :       } else {
    1637           0 :         encryption_size = SIGNAL_BYTE_SIZE;
    1638             :       }
    1639             :     } else {
    1640           0 :       encryption_size = 0;
    1641             :     }
    1642           0 :     data_size = frame_sizes[i] - encryption_size;
    1643             :     /* Encryption parsed */
    1644           0 :     f->data = ne_alloc(data_size);
    1645           0 :     if (!f->data) {
    1646           0 :       ne_free_frame(f);
    1647           0 :       nestegg_free_packet(pkt);
    1648           0 :       return -1;
    1649             :     }
    1650           0 :     f->length = data_size;
    1651           0 :     r = ne_io_read(ctx->io, f->data, data_size);
    1652           0 :     if (r != 1) {
    1653           0 :       ne_free_frame(f);
    1654           0 :       nestegg_free_packet(pkt);
    1655           0 :       return r;
    1656             :     }
    1657             : 
    1658           0 :     if (!last)
    1659           0 :       pkt->frame = f;
    1660             :     else
    1661           0 :       last->next = f;
    1662           0 :     last = f;
    1663             :   }
    1664             : 
    1665           0 :   *data = pkt;
    1666             : 
    1667           0 :   return 1;
    1668             : }
    1669             : 
    1670             : static int
    1671           0 : ne_read_block_additions(nestegg * ctx, uint64_t block_size, struct block_additional ** pkt_block_additional)
    1672             : {
    1673             :   int r;
    1674             :   uint64_t id, size, data_size;
    1675             :   int64_t block_additions_end, block_more_end;
    1676             :   void * data;
    1677             :   int has_data;
    1678             :   struct block_additional * block_additional;
    1679             :   uint64_t add_id;
    1680             : 
    1681           0 :   assert(*pkt_block_additional == NULL);
    1682             : 
    1683           0 :   block_additions_end = ne_io_tell(ctx->io) + block_size;
    1684             : 
    1685           0 :   while (ne_io_tell(ctx->io) < block_additions_end) {
    1686           0 :     add_id = 1;
    1687           0 :     data = NULL;
    1688           0 :     has_data = 0;
    1689           0 :     r = ne_read_element(ctx, &id, &size);
    1690           0 :     if (r != 1)
    1691           0 :       return r;
    1692             : 
    1693           0 :     if (id != ID_BLOCK_MORE) {
    1694             :       /* We don't know what this element is, so skip over it */
    1695           0 :       if (id != ID_VOID && id != ID_CRC32)
    1696           0 :         ctx->log(ctx, NESTEGG_LOG_DEBUG,
    1697             :                  "unknown element %llx in BlockAdditions", id);
    1698           0 :       r = ne_io_read_skip(ctx->io, size);
    1699           0 :       if (r != 1)
    1700           0 :         return r;
    1701           0 :       continue;
    1702             :     }
    1703             : 
    1704           0 :     block_more_end = ne_io_tell(ctx->io) + size;
    1705             : 
    1706           0 :     while (ne_io_tell(ctx->io) < block_more_end) {
    1707           0 :       r = ne_read_element(ctx, &id, &size);
    1708           0 :       if (r != 1) {
    1709           0 :         free(data);
    1710           0 :         return r;
    1711             :       }
    1712             : 
    1713           0 :       if (id == ID_BLOCK_ADD_ID) {
    1714           0 :         r = ne_read_uint(ctx->io, &add_id, size);
    1715           0 :         if (r != 1) {
    1716           0 :           free(data);
    1717           0 :           return r;
    1718             :         }
    1719             : 
    1720           0 :         if (add_id == 0) {
    1721           0 :           ctx->log(ctx, NESTEGG_LOG_ERROR, "Disallowed BlockAddId 0 used");
    1722           0 :           free(data);
    1723           0 :           return -1;
    1724             :         }
    1725           0 :       } else if (id == ID_BLOCK_ADDITIONAL) {
    1726           0 :         if (has_data) {
    1727             :           /* BlockAdditional is supposed to only occur once in a
    1728             :              BlockMore. */
    1729           0 :           ctx->log(ctx, NESTEGG_LOG_ERROR,
    1730             :                    "Multiple BlockAdditional elements in a BlockMore");
    1731           0 :           free(data);
    1732           0 :           return -1;
    1733             :         }
    1734             : 
    1735           0 :         has_data = 1;
    1736           0 :         data_size = size;
    1737           0 :         if (data_size != 0 && data_size < LIMIT_FRAME) {
    1738           0 :           data = ne_alloc(data_size);
    1739           0 :           if (!data)
    1740           0 :             return -1;
    1741           0 :           r = ne_io_read(ctx->io, data, data_size);
    1742           0 :           if (r != 1) {
    1743           0 :             free(data);
    1744           0 :             return r;
    1745             :           }
    1746             :         }
    1747             :       } else {
    1748             :         /* We don't know what this element is, so skip over it */
    1749           0 :         if (id != ID_VOID && id != ID_CRC32)
    1750           0 :           ctx->log(ctx, NESTEGG_LOG_DEBUG,
    1751             :                    "unknown element %llx in BlockMore", id);
    1752           0 :         r = ne_io_read_skip(ctx->io, size);
    1753           0 :         if (r != 1) {
    1754           0 :           free(data);
    1755           0 :           return r;
    1756             :         }
    1757             :       }
    1758             :     }
    1759             : 
    1760           0 :     if (has_data == 0) {
    1761           0 :       ctx->log(ctx, NESTEGG_LOG_ERROR,
    1762             :                "No BlockAdditional element in a BlockMore");
    1763           0 :       return -1;
    1764             :     }
    1765             : 
    1766           0 :     block_additional = ne_alloc(sizeof(*block_additional));
    1767           0 :     block_additional->next = *pkt_block_additional;
    1768           0 :     block_additional->id = add_id;
    1769           0 :     block_additional->data = data;
    1770           0 :     block_additional->length = data_size;
    1771           0 :     *pkt_block_additional = block_additional;
    1772             :   }
    1773             : 
    1774           0 :   return 1;
    1775             : }
    1776             : 
    1777             : static uint64_t
    1778           0 : ne_buf_read_id(unsigned char const * p, size_t length)
    1779             : {
    1780           0 :   uint64_t id = 0;
    1781             : 
    1782           0 :   while (length--) {
    1783           0 :     id <<= 8;
    1784           0 :     id |= *p++;
    1785             :   }
    1786             : 
    1787           0 :   return id;
    1788             : }
    1789             : 
    1790             : static struct seek *
    1791           0 : ne_find_seek_for_id(struct ebml_list_node * seek_head, uint64_t id)
    1792             : {
    1793             :   struct ebml_list * head;
    1794             :   struct ebml_list_node * seek;
    1795             :   struct ebml_binary binary_id;
    1796             :   struct seek * s;
    1797             : 
    1798           0 :   while (seek_head) {
    1799           0 :     assert(seek_head->id == ID_SEEK_HEAD);
    1800           0 :     head = seek_head->data;
    1801           0 :     seek = head->head;
    1802             : 
    1803           0 :     while (seek) {
    1804           0 :       assert(seek->id == ID_SEEK);
    1805           0 :       s = seek->data;
    1806             : 
    1807           0 :       if (ne_get_binary(s->id, &binary_id) == 0 &&
    1808           0 :           ne_buf_read_id(binary_id.data, binary_id.length) == id)
    1809           0 :         return s;
    1810             : 
    1811           0 :       seek = seek->next;
    1812             :     }
    1813             : 
    1814           0 :     seek_head = seek_head->next;
    1815             :   }
    1816             : 
    1817           0 :   return NULL;
    1818             : }
    1819             : 
    1820             : static struct cue_track_positions *
    1821           0 : ne_find_cue_position_for_track(nestegg * ctx, struct ebml_list_node * node, unsigned int track)
    1822             : {
    1823           0 :   struct cue_track_positions * pos = NULL;
    1824             :   uint64_t track_number;
    1825             :   unsigned int t;
    1826             : 
    1827           0 :   while (node) {
    1828           0 :     assert(node->id == ID_CUE_TRACK_POSITIONS);
    1829           0 :     pos = node->data;
    1830           0 :     if (ne_get_uint(pos->track, &track_number) != 0)
    1831           0 :       return NULL;
    1832             : 
    1833           0 :     if (ne_map_track_number_to_index(ctx, track_number, &t) != 0)
    1834           0 :       return NULL;
    1835             : 
    1836           0 :     if (t == track)
    1837           0 :       return pos;
    1838             : 
    1839           0 :     node = node->next;
    1840             :   }
    1841             : 
    1842           0 :   return NULL;
    1843             : }
    1844             : 
    1845             : static struct cue_point *
    1846           0 : ne_find_cue_point_for_tstamp(nestegg * ctx, struct ebml_list_node * cue_point, unsigned int track, uint64_t scale, uint64_t tstamp)
    1847             : {
    1848             :   uint64_t time;
    1849           0 :   struct cue_point * c, * prev = NULL;
    1850             : 
    1851           0 :   while (cue_point) {
    1852           0 :     assert(cue_point->id == ID_CUE_POINT);
    1853           0 :     c = cue_point->data;
    1854             : 
    1855           0 :     if (!prev)
    1856           0 :       prev = c;
    1857             : 
    1858           0 :     if (ne_get_uint(c->time, &time) == 0 && time * scale > tstamp)
    1859           0 :       break;
    1860             : 
    1861           0 :     if (ne_find_cue_position_for_track(ctx, c->cue_track_positions.head, track) != NULL)
    1862           0 :       prev = c;
    1863             : 
    1864           0 :     cue_point = cue_point->next;
    1865             :   }
    1866             : 
    1867           0 :   return prev;
    1868             : }
    1869             : 
    1870             : static void
    1871           0 : ne_null_log_callback(nestegg * ctx, unsigned int severity, char const * fmt, ...)
    1872             : {
    1873           0 :   if (ctx && severity && fmt)
    1874           0 :     return;
    1875             : }
    1876             : 
    1877             : static int
    1878           0 : ne_init_cue_points(nestegg * ctx, int64_t max_offset)
    1879             : {
    1880             :   int r;
    1881           0 :   struct ebml_list_node * node = ctx->segment.cues.cue_point.head;
    1882             :   struct seek * found;
    1883             :   uint64_t seek_pos, id;
    1884             :   struct saved_state state;
    1885             : 
    1886             :   /* If there are no cues loaded, check for cues element in the seek head
    1887             :      and load it. */
    1888           0 :   if (!node) {
    1889           0 :     found = ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES);
    1890           0 :     if (!found)
    1891           0 :       return -1;
    1892             : 
    1893           0 :     if (ne_get_uint(found->position, &seek_pos) != 0)
    1894           0 :       return -1;
    1895             : 
    1896             :     /* Save old parser state. */
    1897           0 :     r = ne_ctx_save(ctx, &state);
    1898           0 :     if (r != 0)
    1899           0 :       return -1;
    1900             : 
    1901             :     /* Seek and set up parser state for segment-level element (Cues). */
    1902           0 :     r = ne_io_seek(ctx->io, ctx->segment_offset + seek_pos, NESTEGG_SEEK_SET);
    1903           0 :     if (r != 0)
    1904           0 :       return -1;
    1905           0 :     ctx->last_valid = 0;
    1906             : 
    1907           0 :     r = ne_read_element(ctx, &id, NULL);
    1908           0 :     if (r != 1)
    1909           0 :       return -1;
    1910             : 
    1911           0 :     if (id != ID_CUES)
    1912           0 :       return -1;
    1913             : 
    1914           0 :     assert(ctx->ancestor == NULL);
    1915           0 :     if (ne_ctx_push(ctx, ne_top_level_elements, ctx) < 0)
    1916           0 :       return -1;
    1917           0 :     if (ne_ctx_push(ctx, ne_segment_elements, &ctx->segment) < 0)
    1918           0 :       return -1;
    1919           0 :     if (ne_ctx_push(ctx, ne_cues_elements, &ctx->segment.cues) < 0)
    1920           0 :       return -1;
    1921             :     /* parser will run until end of cues element. */
    1922           0 :     ctx->log(ctx, NESTEGG_LOG_DEBUG, "seek: parsing cue elements");
    1923           0 :     r = ne_parse(ctx, ne_cues_elements, max_offset);
    1924           0 :     while (ctx->ancestor)
    1925           0 :       ne_ctx_pop(ctx);
    1926             : 
    1927             :     /* Reset parser state to original state and seek back to old position. */
    1928           0 :     if (ne_ctx_restore(ctx, &state) != 0)
    1929           0 :       return -1;
    1930             : 
    1931           0 :     if (r < 0)
    1932           0 :       return -1;
    1933             : 
    1934           0 :     node = ctx->segment.cues.cue_point.head;
    1935           0 :     if (!node)
    1936           0 :       return -1;
    1937             :   }
    1938             : 
    1939           0 :   return 0;
    1940             : }
    1941             : 
    1942             : /* Three functions that implement the nestegg_io interface, operating on a
    1943             :    io_buffer. */
    1944             : struct io_buffer {
    1945             :   unsigned char const * buffer;
    1946             :   size_t length;
    1947             :   int64_t offset;
    1948             : };
    1949             : 
    1950             : static int
    1951           0 : ne_buffer_read(void * buffer, size_t length, void * userdata)
    1952             : {
    1953           0 :   struct io_buffer * iob = userdata;
    1954             : 
    1955           0 :   int rv = 1;
    1956           0 :   size_t available = iob->length - iob->offset;
    1957             : 
    1958           0 :   if (available < length)
    1959           0 :     return 0;
    1960             : 
    1961           0 :   memcpy(buffer, iob->buffer + iob->offset, length);
    1962           0 :   iob->offset += length;
    1963             : 
    1964           0 :   return rv;
    1965             : }
    1966             : 
    1967             : static int
    1968           0 : ne_buffer_seek(int64_t offset, int whence, void * userdata)
    1969             : {
    1970           0 :   struct io_buffer * iob = userdata;
    1971           0 :   int64_t o = iob->offset;
    1972             : 
    1973           0 :   switch(whence) {
    1974             :   case NESTEGG_SEEK_SET:
    1975           0 :     o = offset;
    1976           0 :     break;
    1977             :   case NESTEGG_SEEK_CUR:
    1978           0 :     o += offset;
    1979           0 :     break;
    1980             :   case NESTEGG_SEEK_END:
    1981           0 :     o = iob->length + offset;
    1982           0 :     break;
    1983             :   }
    1984             : 
    1985           0 :   if (o < 0 || o > (int64_t) iob->length)
    1986           0 :     return -1;
    1987             : 
    1988           0 :   iob->offset = o;
    1989           0 :   return 0;
    1990             : }
    1991             : 
    1992             : static int64_t
    1993           0 : ne_buffer_tell(void * userdata)
    1994             : {
    1995           0 :   struct io_buffer * iob = userdata;
    1996           0 :   return iob->offset;
    1997             : }
    1998             : 
    1999             : static int
    2000           0 : ne_context_new(nestegg ** context, nestegg_io io, nestegg_log callback)
    2001             : {
    2002             :   nestegg * ctx;
    2003             : 
    2004           0 :   if (!(io.read && io.seek && io.tell))
    2005           0 :     return -1;
    2006             : 
    2007           0 :   ctx = ne_alloc(sizeof(*ctx));
    2008           0 :   if (!ctx)
    2009           0 :     return -1;
    2010             : 
    2011           0 :   ctx->io = ne_alloc(sizeof(*ctx->io));
    2012           0 :   if (!ctx->io) {
    2013           0 :     nestegg_destroy(ctx);
    2014           0 :     return -1;
    2015             :   }
    2016           0 :   *ctx->io = io;
    2017           0 :   ctx->log = callback;
    2018           0 :   ctx->alloc_pool = ne_pool_init();
    2019           0 :   if (!ctx->alloc_pool) {
    2020           0 :     nestegg_destroy(ctx);
    2021           0 :     return -1;
    2022             :   }
    2023             : 
    2024           0 :   if (!ctx->log)
    2025           0 :     ctx->log = ne_null_log_callback;
    2026             : 
    2027           0 :   *context = ctx;
    2028           0 :   return 0;
    2029             : }
    2030             : 
    2031             : static int
    2032           0 : ne_match_webm(nestegg_io io, int64_t max_offset)
    2033             : {
    2034             :   int r;
    2035             :   uint64_t id;
    2036             :   char * doctype;
    2037             :   nestegg * ctx;
    2038             : 
    2039           0 :   if (ne_context_new(&ctx, io, NULL) != 0)
    2040           0 :     return -1;
    2041             : 
    2042           0 :   r = ne_peek_element(ctx, &id, NULL);
    2043           0 :   if (r != 1) {
    2044           0 :     nestegg_destroy(ctx);
    2045           0 :     return 0;
    2046             :   }
    2047             : 
    2048           0 :   if (id != ID_EBML) {
    2049           0 :     nestegg_destroy(ctx);
    2050           0 :     return 0;
    2051             :   }
    2052             : 
    2053           0 :   ne_ctx_push(ctx, ne_top_level_elements, ctx);
    2054             : 
    2055             :   /* we don't check the return value of ne_parse, that might fail because
    2056             :      max_offset is not on a valid element end point. We only want to check
    2057             :      the EBML ID and that the doctype is "webm". */
    2058           0 :   ne_parse(ctx, NULL, max_offset);
    2059           0 :   while (ctx->ancestor)
    2060           0 :     ne_ctx_pop(ctx);
    2061             : 
    2062           0 :   if (ne_get_string(ctx->ebml.doctype, &doctype) != 0 ||
    2063           0 :       strcmp(doctype, "webm") != 0) {
    2064           0 :     nestegg_destroy(ctx);
    2065           0 :     return 0;
    2066             :   }
    2067             : 
    2068           0 :   nestegg_destroy(ctx);
    2069             : 
    2070           0 :   return 1;
    2071             : }
    2072             : 
    2073             : int
    2074           0 : nestegg_init(nestegg ** context, nestegg_io io, nestegg_log callback, int64_t max_offset)
    2075             : {
    2076             :   int r;
    2077             :   uint64_t id, version, docversion;
    2078             :   struct ebml_list_node * track;
    2079             :   char * doctype;
    2080             :   nestegg * ctx;
    2081             : 
    2082           0 :   if (ne_context_new(&ctx, io, callback) != 0)
    2083           0 :     return -1;
    2084             : 
    2085           0 :   r = ne_peek_element(ctx, &id, NULL);
    2086           0 :   if (r != 1) {
    2087           0 :     nestegg_destroy(ctx);
    2088           0 :     return -1;
    2089             :   }
    2090             : 
    2091           0 :   if (id != ID_EBML) {
    2092           0 :     nestegg_destroy(ctx);
    2093           0 :     return -1;
    2094             :   }
    2095             : 
    2096           0 :   ctx->log(ctx, NESTEGG_LOG_DEBUG, "ctx %p", ctx);
    2097             : 
    2098           0 :   ne_ctx_push(ctx, ne_top_level_elements, ctx);
    2099             : 
    2100           0 :   r = ne_parse(ctx, NULL, max_offset);
    2101           0 :   while (ctx->ancestor)
    2102           0 :     ne_ctx_pop(ctx);
    2103             : 
    2104           0 :   if (r != 1) {
    2105           0 :     nestegg_destroy(ctx);
    2106           0 :     return -1;
    2107             :   }
    2108             : 
    2109           0 :   if (ne_get_uint(ctx->ebml.ebml_read_version, &version) != 0)
    2110           0 :     version = 1;
    2111           0 :   if (version != 1) {
    2112           0 :     nestegg_destroy(ctx);
    2113           0 :     return -1;
    2114             :   }
    2115             : 
    2116           0 :   if (ne_get_string(ctx->ebml.doctype, &doctype) != 0)
    2117           0 :     doctype = "matroska";
    2118           0 :   if (strcmp(doctype, "webm") != 0) {
    2119           0 :     nestegg_destroy(ctx);
    2120           0 :     return -1;
    2121             :   }
    2122             : 
    2123           0 :   if (ne_get_uint(ctx->ebml.doctype_read_version, &docversion) != 0)
    2124           0 :     docversion = 1;
    2125           0 :   if (docversion < 1 || docversion > 2) {
    2126           0 :     nestegg_destroy(ctx);
    2127           0 :     return -1;
    2128             :   }
    2129             : 
    2130           0 :   if (!ctx->segment.tracks.track_entry.head) {
    2131           0 :     nestegg_destroy(ctx);
    2132           0 :     return -1;
    2133             :   }
    2134             : 
    2135           0 :   track = ctx->segment.tracks.track_entry.head;
    2136           0 :   ctx->track_count = 0;
    2137             : 
    2138           0 :   while (track) {
    2139           0 :     ctx->track_count += 1;
    2140           0 :     track = track->next;
    2141             :   }
    2142             : 
    2143           0 :   r = ne_ctx_save(ctx, &ctx->saved);
    2144           0 :   if (r != 0) {
    2145           0 :     nestegg_destroy(ctx);
    2146           0 :     return -1;
    2147             :   }
    2148             : 
    2149           0 :   *context = ctx;
    2150             : 
    2151           0 :   return 0;
    2152             : }
    2153             : 
    2154             : void
    2155           0 : nestegg_destroy(nestegg * ctx)
    2156             : {
    2157           0 :   assert(ctx->ancestor == NULL);
    2158           0 :   ne_pool_destroy(ctx->alloc_pool);
    2159           0 :   free(ctx->io);
    2160           0 :   free(ctx);
    2161           0 : }
    2162             : 
    2163             : int
    2164           0 : nestegg_duration(nestegg * ctx, uint64_t * duration)
    2165             : {
    2166             :   uint64_t tc_scale;
    2167             :   double unscaled_duration;
    2168             : 
    2169           0 :   if (ne_get_float(ctx->segment.info.duration, &unscaled_duration) != 0)
    2170           0 :     return -1;
    2171             : 
    2172           0 :   tc_scale = ne_get_timecode_scale(ctx);
    2173           0 :   if (tc_scale == 0)
    2174           0 :     return -1;
    2175             : 
    2176           0 :   if (unscaled_duration != unscaled_duration ||
    2177           0 :       unscaled_duration < 0 || unscaled_duration > (double) UINT64_MAX ||
    2178           0 :       (uint64_t) unscaled_duration > UINT64_MAX / tc_scale)
    2179           0 :     return -1;
    2180             : 
    2181           0 :   *duration = (uint64_t) (unscaled_duration * tc_scale);
    2182           0 :   return 0;
    2183             : }
    2184             : 
    2185             : int
    2186           0 : nestegg_tstamp_scale(nestegg * ctx, uint64_t * scale)
    2187             : {
    2188           0 :   *scale = ne_get_timecode_scale(ctx);
    2189           0 :   if (*scale == 0)
    2190           0 :     return -1;
    2191           0 :   return 0;
    2192             : }
    2193             : 
    2194             : int
    2195           0 : nestegg_track_count(nestegg * ctx, unsigned int * tracks)
    2196             : {
    2197           0 :   *tracks = ctx->track_count;
    2198           0 :   return 0;
    2199             : }
    2200             : 
    2201             : int
    2202           0 : nestegg_get_cue_point(nestegg * ctx, unsigned int cluster_num, int64_t max_offset,
    2203             :                       int64_t * start_pos, int64_t * end_pos, uint64_t * tstamp)
    2204             : {
    2205           0 :   int range_obtained = 0;
    2206           0 :   unsigned int cluster_count = 0;
    2207             :   struct cue_point * cue_point;
    2208             :   struct cue_track_positions * pos;
    2209             :   uint64_t seek_pos, track_number, tc_scale, time;
    2210           0 :   struct ebml_list_node * cues_node = ctx->segment.cues.cue_point.head;
    2211           0 :   struct ebml_list_node * cue_pos_node = NULL;
    2212           0 :   unsigned int track = 0, track_count = 0, track_index;
    2213             : 
    2214           0 :   if (!start_pos || !end_pos || !tstamp)
    2215           0 :     return -1;
    2216             : 
    2217             :   /* Initialise return values */
    2218           0 :   *start_pos = -1;
    2219           0 :   *end_pos = -1;
    2220           0 :   *tstamp = 0;
    2221             : 
    2222           0 :   if (!cues_node) {
    2223           0 :     ne_init_cue_points(ctx, max_offset);
    2224           0 :     cues_node = ctx->segment.cues.cue_point.head;
    2225             :     /* Verify cues have been added to context. */
    2226           0 :     if (!cues_node)
    2227           0 :       return -1;
    2228             :   }
    2229             : 
    2230           0 :   nestegg_track_count(ctx, &track_count);
    2231             : 
    2232           0 :   tc_scale = ne_get_timecode_scale(ctx);
    2233           0 :   if (tc_scale == 0)
    2234           0 :     return -1;
    2235             : 
    2236           0 :   while (cues_node && !range_obtained) {
    2237           0 :     assert(cues_node->id == ID_CUE_POINT);
    2238           0 :     cue_point = cues_node->data;
    2239           0 :     cue_pos_node = cue_point->cue_track_positions.head;
    2240           0 :     while (cue_pos_node) {
    2241           0 :       assert(cue_pos_node->id == ID_CUE_TRACK_POSITIONS);
    2242           0 :       pos = cue_pos_node->data;
    2243           0 :       for (track = 0; track < track_count; ++track) {
    2244           0 :         if (ne_get_uint(pos->track, &track_number) != 0)
    2245           0 :           return -1;
    2246             : 
    2247           0 :         if (ne_map_track_number_to_index(ctx, track_number, &track_index) != 0)
    2248           0 :           return -1;
    2249             : 
    2250           0 :         if (track_index == track) {
    2251           0 :           if (ne_get_uint(pos->cluster_position, &seek_pos) != 0)
    2252           0 :             return -1;
    2253           0 :           if (cluster_count == cluster_num) {
    2254           0 :             *start_pos = ctx->segment_offset + seek_pos;
    2255           0 :             if (ne_get_uint(cue_point->time, &time) != 0)
    2256           0 :               return -1;
    2257           0 :             *tstamp = time * tc_scale;
    2258           0 :           } else if (cluster_count == cluster_num + 1) {
    2259           0 :             *end_pos = ctx->segment_offset + seek_pos - 1;
    2260           0 :             range_obtained = 1;
    2261           0 :             break;
    2262             :           }
    2263           0 :           cluster_count++;
    2264             :         }
    2265             :       }
    2266           0 :       cue_pos_node = cue_pos_node->next;
    2267             :     }
    2268           0 :     cues_node = cues_node->next;
    2269             :   }
    2270             : 
    2271           0 :   return 0;
    2272             : }
    2273             : 
    2274             : int
    2275           0 : nestegg_offset_seek(nestegg * ctx, uint64_t offset)
    2276             : {
    2277             :   int r;
    2278             : 
    2279           0 :   if (offset > INT64_MAX)
    2280           0 :     return -1;
    2281             : 
    2282             :   /* Seek and set up parser state for segment-level element (Cluster). */
    2283           0 :   r = ne_io_seek(ctx->io, offset, NESTEGG_SEEK_SET);
    2284           0 :   if (r != 0)
    2285           0 :     return -1;
    2286           0 :   ctx->last_valid = 0;
    2287             : 
    2288           0 :   assert(ctx->ancestor == NULL);
    2289             : 
    2290           0 :   return 0;
    2291             : }
    2292             : 
    2293             : int
    2294           0 : nestegg_track_seek(nestegg * ctx, unsigned int track, uint64_t tstamp)
    2295             : {
    2296             :   int r;
    2297             :   struct cue_point * cue_point;
    2298             :   struct cue_track_positions * pos;
    2299             :   uint64_t seek_pos, tc_scale;
    2300             : 
    2301             :   /* If there are no cues loaded, check for cues element in the seek head
    2302             :      and load it. */
    2303           0 :   if (!ctx->segment.cues.cue_point.head) {
    2304           0 :     r = ne_init_cue_points(ctx, -1);
    2305           0 :     if (r != 0)
    2306           0 :       return -1;
    2307             :   }
    2308             : 
    2309           0 :   tc_scale = ne_get_timecode_scale(ctx);
    2310           0 :   if (tc_scale == 0)
    2311           0 :     return -1;
    2312             : 
    2313           0 :   cue_point = ne_find_cue_point_for_tstamp(ctx, ctx->segment.cues.cue_point.head,
    2314             :                                            track, tc_scale, tstamp);
    2315           0 :   if (!cue_point)
    2316           0 :     return -1;
    2317             : 
    2318           0 :   pos = ne_find_cue_position_for_track(ctx, cue_point->cue_track_positions.head, track);
    2319           0 :   if (pos == NULL)
    2320           0 :     return -1;
    2321             : 
    2322           0 :   if (ne_get_uint(pos->cluster_position, &seek_pos) != 0)
    2323           0 :     return -1;
    2324             : 
    2325             :   /* Seek to (we assume) the start of a Cluster element. */
    2326           0 :   r = nestegg_offset_seek(ctx, ctx->segment_offset + seek_pos);
    2327           0 :   if (r != 0)
    2328           0 :     return -1;
    2329             : 
    2330           0 :   return 0;
    2331             : }
    2332             : 
    2333             : int
    2334           0 : nestegg_track_type(nestegg * ctx, unsigned int track)
    2335             : {
    2336             :   struct track_entry * entry;
    2337             :   uint64_t type;
    2338             : 
    2339           0 :   entry = ne_find_track_entry(ctx, track);
    2340           0 :   if (!entry)
    2341           0 :     return -1;
    2342             : 
    2343           0 :   if (ne_get_uint(entry->type, &type) != 0)
    2344           0 :     return -1;
    2345             : 
    2346           0 :   if (type & TRACK_TYPE_VIDEO)
    2347           0 :     return NESTEGG_TRACK_VIDEO;
    2348             : 
    2349           0 :   if (type & TRACK_TYPE_AUDIO)
    2350           0 :     return NESTEGG_TRACK_AUDIO;
    2351             : 
    2352           0 :   return NESTEGG_TRACK_UNKNOWN;
    2353             : }
    2354             : 
    2355             : int
    2356           0 : nestegg_track_codec_id(nestegg * ctx, unsigned int track)
    2357             : {
    2358             :   char * codec_id;
    2359             :   struct track_entry * entry;
    2360             : 
    2361           0 :   entry = ne_find_track_entry(ctx, track);
    2362           0 :   if (!entry)
    2363           0 :     return -1;
    2364             : 
    2365           0 :   if (ne_get_string(entry->codec_id, &codec_id) != 0)
    2366           0 :     return -1;
    2367             : 
    2368           0 :   if (strcmp(codec_id, TRACK_ID_VP8) == 0)
    2369           0 :     return NESTEGG_CODEC_VP8;
    2370             : 
    2371           0 :   if (strcmp(codec_id, TRACK_ID_VP9) == 0)
    2372           0 :     return NESTEGG_CODEC_VP9;
    2373             : 
    2374           0 :   if (strcmp(codec_id, TRACK_ID_AV1) == 0)
    2375           0 :     return NESTEGG_CODEC_AV1;
    2376             : 
    2377           0 :   if (strcmp(codec_id, TRACK_ID_VORBIS) == 0)
    2378           0 :     return NESTEGG_CODEC_VORBIS;
    2379             : 
    2380           0 :   if (strcmp(codec_id, TRACK_ID_OPUS) == 0)
    2381           0 :     return NESTEGG_CODEC_OPUS;
    2382             : 
    2383           0 :   return NESTEGG_CODEC_UNKNOWN;
    2384             : }
    2385             : 
    2386             : int
    2387           0 : nestegg_track_codec_data_count(nestegg * ctx, unsigned int track,
    2388             :                                unsigned int * count)
    2389             : {
    2390             :   struct track_entry * entry;
    2391             :   struct ebml_binary codec_private;
    2392             :   int codec_id;
    2393             :   unsigned char * p;
    2394             : 
    2395           0 :   *count = 0;
    2396             : 
    2397           0 :   entry = ne_find_track_entry(ctx, track);
    2398           0 :   if (!entry)
    2399           0 :     return -1;
    2400             : 
    2401           0 :   codec_id = nestegg_track_codec_id(ctx, track);
    2402             : 
    2403           0 :   if (codec_id == NESTEGG_CODEC_OPUS) {
    2404           0 :     *count = 1;
    2405           0 :     return 0;
    2406             :   }
    2407             : 
    2408           0 :   if (codec_id != NESTEGG_CODEC_VORBIS)
    2409           0 :     return -1;
    2410             : 
    2411           0 :   if (ne_get_binary(entry->codec_private, &codec_private) != 0)
    2412           0 :     return -1;
    2413             : 
    2414           0 :   if (codec_private.length < 1)
    2415           0 :     return -1;
    2416             : 
    2417           0 :   p = codec_private.data;
    2418           0 :   *count = *p + 1;
    2419             : 
    2420           0 :   if (*count > 3)
    2421           0 :     return -1;
    2422             : 
    2423           0 :   return 0;
    2424             : }
    2425             : 
    2426             : int
    2427           0 : nestegg_track_codec_data(nestegg * ctx, unsigned int track, unsigned int item,
    2428             :                          unsigned char ** data, size_t * length)
    2429             : {
    2430             :   struct track_entry * entry;
    2431             :   struct ebml_binary codec_private;
    2432             : 
    2433           0 :   *data = NULL;
    2434           0 :   *length = 0;
    2435             : 
    2436           0 :   entry = ne_find_track_entry(ctx, track);
    2437           0 :   if (!entry)
    2438           0 :     return -1;
    2439             : 
    2440           0 :   if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS &&
    2441           0 :       nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_OPUS)
    2442           0 :     return -1;
    2443             : 
    2444           0 :   if (ne_get_binary(entry->codec_private, &codec_private) != 0)
    2445           0 :     return -1;
    2446             : 
    2447           0 :   if (nestegg_track_codec_id(ctx, track) == NESTEGG_CODEC_VORBIS) {
    2448             :     uint64_t count;
    2449             :     uint64_t sizes[3];
    2450             :     size_t total;
    2451             :     unsigned char * p;
    2452             :     unsigned int i;
    2453             :     int r;
    2454             : 
    2455             :     nestegg_io io;
    2456             :     struct io_buffer userdata;
    2457           0 :     userdata.buffer = codec_private.data;
    2458           0 :     userdata.length = codec_private.length;
    2459           0 :     userdata.offset = 0;
    2460             : 
    2461           0 :     io.read = ne_buffer_read;
    2462           0 :     io.seek = ne_buffer_seek;
    2463           0 :     io.tell = ne_buffer_tell;
    2464           0 :     io.userdata = &userdata;
    2465             : 
    2466           0 :     total = 0;
    2467             : 
    2468           0 :     r = ne_read_uint(&io, &count, 1);
    2469           0 :     if (r != 1)
    2470           0 :       return r;
    2471           0 :     total += 1;
    2472           0 :     count += 1;
    2473             : 
    2474           0 :     if (count > 3)
    2475           0 :       return -1;
    2476           0 :     r = ne_read_xiph_lacing(&io, codec_private.length, &total, count, sizes);
    2477           0 :     if (r != 1)
    2478           0 :       return r;
    2479             : 
    2480           0 :     if (item >= count)
    2481           0 :       return -1;
    2482             : 
    2483           0 :     p = codec_private.data + total;
    2484           0 :     for (i = 0; i < item; ++i) {
    2485           0 :       p += sizes[i];
    2486             :     }
    2487           0 :     assert((size_t) (p - codec_private.data) <= codec_private.length &&
    2488             :            codec_private.length - (p - codec_private.data) >= sizes[item]);
    2489           0 :     *data = p;
    2490           0 :     *length = sizes[item];
    2491             :   } else {
    2492           0 :     if (item >= 1)
    2493           0 :       return -1;
    2494             : 
    2495           0 :     *data = codec_private.data;
    2496           0 :     *length = codec_private.length;
    2497             :   }
    2498             : 
    2499           0 :   return 0;
    2500             : }
    2501             : 
    2502             : int
    2503           0 : nestegg_track_video_params(nestegg * ctx, unsigned int track,
    2504             :                            nestegg_video_params * params)
    2505             : {
    2506             :   struct track_entry * entry;
    2507             :   uint64_t value;
    2508             : 
    2509           0 :   memset(params, 0, sizeof(*params));
    2510             : 
    2511           0 :   entry = ne_find_track_entry(ctx, track);
    2512           0 :   if (!entry)
    2513           0 :     return -1;
    2514             : 
    2515           0 :   if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_VIDEO)
    2516           0 :     return -1;
    2517             : 
    2518           0 :   value = 0;
    2519           0 :   ne_get_uint(entry->video.stereo_mode, &value);
    2520           0 :   if (value <= NESTEGG_VIDEO_STEREO_TOP_BOTTOM ||
    2521           0 :       value == NESTEGG_VIDEO_STEREO_RIGHT_LEFT)
    2522           0 :     params->stereo_mode = value;
    2523             : 
    2524           0 :   value = 0;
    2525           0 :   ne_get_uint(entry->video.alpha_mode, &value);
    2526           0 :   params->alpha_mode = value;
    2527             : 
    2528           0 :   if (ne_get_uint(entry->video.pixel_width, &value) != 0)
    2529           0 :     return -1;
    2530           0 :   params->width = value;
    2531             : 
    2532           0 :   if (ne_get_uint(entry->video.pixel_height, &value) != 0)
    2533           0 :     return -1;
    2534           0 :   params->height = value;
    2535             : 
    2536           0 :   value = 0;
    2537           0 :   ne_get_uint(entry->video.pixel_crop_bottom, &value);
    2538           0 :   params->crop_bottom = value;
    2539             : 
    2540           0 :   value = 0;
    2541           0 :   ne_get_uint(entry->video.pixel_crop_top, &value);
    2542           0 :   params->crop_top = value;
    2543             : 
    2544           0 :   value = 0;
    2545           0 :   ne_get_uint(entry->video.pixel_crop_left, &value);
    2546           0 :   params->crop_left = value;
    2547             : 
    2548           0 :   value = 0;
    2549           0 :   ne_get_uint(entry->video.pixel_crop_right, &value);
    2550           0 :   params->crop_right = value;
    2551             : 
    2552           0 :   value = params->width;
    2553           0 :   ne_get_uint(entry->video.display_width, &value);
    2554           0 :   params->display_width = value;
    2555             : 
    2556           0 :   value = params->height;
    2557           0 :   ne_get_uint(entry->video.display_height, &value);
    2558           0 :   params->display_height = value;
    2559             : 
    2560           0 :   return 0;
    2561             : }
    2562             : 
    2563             : int
    2564           0 : nestegg_track_audio_params(nestegg * ctx, unsigned int track,
    2565             :                            nestegg_audio_params * params)
    2566             : {
    2567             :   struct track_entry * entry;
    2568             :   uint64_t value;
    2569             : 
    2570           0 :   memset(params, 0, sizeof(*params));
    2571             : 
    2572           0 :   entry = ne_find_track_entry(ctx, track);
    2573           0 :   if (!entry)
    2574           0 :     return -1;
    2575             : 
    2576           0 :   if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_AUDIO)
    2577           0 :     return -1;
    2578             : 
    2579           0 :   params->rate = 8000;
    2580           0 :   ne_get_float(entry->audio.sampling_frequency, &params->rate);
    2581             : 
    2582           0 :   value = 1;
    2583           0 :   ne_get_uint(entry->audio.channels, &value);
    2584           0 :   params->channels = value;
    2585             : 
    2586           0 :   value = 16;
    2587           0 :   ne_get_uint(entry->audio.bit_depth, &value);
    2588           0 :   params->depth = value;
    2589             : 
    2590           0 :   value = 0;
    2591           0 :   ne_get_uint(entry->codec_delay, &value);
    2592           0 :   params->codec_delay = value;
    2593             : 
    2594           0 :   value = 0;
    2595           0 :   ne_get_uint(entry->seek_preroll, &value);
    2596           0 :   params->seek_preroll = value;
    2597             : 
    2598           0 :   return 0;
    2599             : }
    2600             : 
    2601             : int
    2602           0 : nestegg_track_encoding(nestegg * ctx, unsigned int track)
    2603             : {
    2604             :   struct track_entry * entry;
    2605             :   struct content_encoding * encoding;
    2606             :   uint64_t encoding_value;
    2607             : 
    2608           0 :   entry = ne_find_track_entry(ctx, track);
    2609           0 :   if (!entry) {
    2610           0 :     ctx->log(ctx, NESTEGG_LOG_ERROR, "No track entry found");
    2611           0 :     return -1;
    2612             :   }
    2613             : 
    2614           0 :   if (!entry->content_encodings.content_encoding.head) {
    2615             :     /* Default encoding is compression */
    2616           0 :     return NESTEGG_ENCODING_COMPRESSION;
    2617             :   }
    2618             : 
    2619           0 :   encoding = entry->content_encodings.content_encoding.head->data;
    2620             : 
    2621           0 :   encoding_value = NESTEGG_ENCODING_COMPRESSION;
    2622           0 :   ne_get_uint(encoding->content_encoding_type, &encoding_value);
    2623           0 :   if (encoding_value != NESTEGG_ENCODING_COMPRESSION && encoding_value != NESTEGG_ENCODING_ENCRYPTION) {
    2624           0 :     ctx->log(ctx, NESTEGG_LOG_ERROR, "Invalid ContentEncoding element found");
    2625           0 :     return -1;
    2626             :   }
    2627             : 
    2628           0 :   return encoding_value;
    2629             : }
    2630             : 
    2631             : int
    2632           0 : nestegg_track_content_enc_key_id(nestegg * ctx, unsigned int track, unsigned char const ** content_enc_key_id,
    2633             :                                  size_t * content_enc_key_id_length)
    2634             : {
    2635             :   struct track_entry * entry;
    2636             :   struct content_encoding * encoding;
    2637             :   struct content_encryption * encryption;
    2638             :   struct content_enc_aes_settings * aes_settings;
    2639             :   struct nestegg_encryption_params;
    2640             :   uint64_t value;
    2641             :   struct ebml_binary enc_key_id;
    2642             : 
    2643           0 :   entry = ne_find_track_entry(ctx, track);
    2644           0 :   if (!entry) {
    2645           0 :     ctx->log(ctx, NESTEGG_LOG_ERROR, "No track entry found");
    2646           0 :     return -1;
    2647             :   }
    2648             : 
    2649           0 :   if (!entry->content_encodings.content_encoding.head) {
    2650           0 :     ctx->log(ctx, NESTEGG_LOG_ERROR, "No ContentEncoding element found");
    2651           0 :     return -1;
    2652             :   }
    2653             : 
    2654           0 :   encoding = entry->content_encodings.content_encoding.head->data;
    2655             : 
    2656           0 :   value = 0;
    2657           0 :   ne_get_uint(encoding->content_encoding_type, &value);
    2658           0 :   if (value != NESTEGG_ENCODING_ENCRYPTION) {
    2659           0 :     ctx->log(ctx, NESTEGG_LOG_ERROR, "Disallowed ContentEncodingType found");
    2660           0 :     return -1;
    2661             :   }
    2662             : 
    2663           0 :   if (!encoding->content_encryption.head) {
    2664           0 :     ctx->log(ctx, NESTEGG_LOG_ERROR, "No ContentEncryption element found");
    2665           0 :     return -1;
    2666             :   }
    2667             : 
    2668           0 :   encryption = encoding->content_encryption.head->data;
    2669             : 
    2670           0 :   value = 0;
    2671           0 :   ne_get_uint(encryption->content_enc_algo, &value);
    2672             : 
    2673           0 :   if (value != CONTENT_ENC_ALGO_AES) {
    2674           0 :     ctx->log(ctx, NESTEGG_LOG_ERROR, "Disallowed ContentEncAlgo found");
    2675           0 :     return -1;
    2676             :   }
    2677             : 
    2678           0 :   if (!encryption->content_enc_aes_settings.head) {
    2679           0 :     ctx->log(ctx, NESTEGG_LOG_ERROR, "No ContentEncAesSettings element found");
    2680           0 :     return -1;
    2681             :   }
    2682             : 
    2683           0 :   aes_settings = encryption->content_enc_aes_settings.head->data;
    2684           0 :   value = AES_SETTINGS_CIPHER_CTR;
    2685           0 :   ne_get_uint(aes_settings->aes_settings_cipher_mode, &value);
    2686             : 
    2687           0 :   if (value != AES_SETTINGS_CIPHER_CTR) {
    2688           0 :     ctx->log(ctx, NESTEGG_LOG_ERROR, "Disallowed AESSettingCipherMode used");
    2689           0 :     return -1;
    2690             :   }
    2691             : 
    2692           0 :   if (ne_get_binary(encryption->content_enc_key_id, &enc_key_id) != 0) {
    2693           0 :     ctx->log(ctx, NESTEGG_LOG_ERROR, "Could not retrieve track ContentEncKeyId");
    2694           0 :     return -1;
    2695             :   }
    2696             : 
    2697           0 :   *content_enc_key_id = enc_key_id.data;
    2698           0 :   *content_enc_key_id_length = enc_key_id.length;
    2699             : 
    2700           0 :   return 0;
    2701             : }
    2702             : 
    2703             : int
    2704           0 : nestegg_track_default_duration(nestegg * ctx, unsigned int track,
    2705             :                                uint64_t * duration)
    2706             : {
    2707             :   struct track_entry * entry;
    2708             :   uint64_t value;
    2709             : 
    2710           0 :   entry = ne_find_track_entry(ctx, track);
    2711           0 :   if (!entry)
    2712           0 :     return -1;
    2713             : 
    2714           0 :   if (ne_get_uint(entry->default_duration, &value) != 0)
    2715           0 :     return -1;
    2716           0 :   *duration = value;
    2717             : 
    2718           0 :   return 0;
    2719             : }
    2720             : 
    2721             : int
    2722           0 : nestegg_read_reset(nestegg * ctx)
    2723             : {
    2724           0 :   assert(ctx->ancestor == NULL);
    2725           0 :   return ne_ctx_restore(ctx, &ctx->saved);
    2726             : }
    2727             : 
    2728             : int
    2729           0 : nestegg_read_packet(nestegg * ctx, nestegg_packet ** pkt)
    2730             : {
    2731           0 :   int r, read_block = 0;
    2732             :   uint64_t id, size;
    2733             : 
    2734           0 :   *pkt = NULL;
    2735             : 
    2736           0 :   assert(ctx->ancestor == NULL);
    2737             : 
    2738             :   /* Prepare for read_reset to resume parsing from this point upon error. */
    2739           0 :   r = ne_ctx_save(ctx, &ctx->saved);
    2740           0 :   if (r != 0)
    2741           0 :     return -1;
    2742             : 
    2743           0 :   while (!read_block) {
    2744           0 :     r = ne_read_element(ctx, &id, &size);
    2745           0 :     if (r != 1)
    2746           0 :       return r;
    2747             : 
    2748           0 :     switch (id) {
    2749             :     case ID_CLUSTER: {
    2750           0 :       r = ne_read_element(ctx, &id, &size);
    2751           0 :       if (r != 1)
    2752           0 :         return r;
    2753             : 
    2754             :       /* Timecode must be the first element in a Cluster, per spec. */
    2755           0 :       if (id != ID_TIMECODE)
    2756           0 :         return -1;
    2757             : 
    2758           0 :       r = ne_read_uint(ctx->io, &ctx->cluster_timecode, size);
    2759           0 :       if (r != 1)
    2760           0 :         return r;
    2761           0 :       ctx->read_cluster_timecode = 1;
    2762           0 :       break;
    2763             :     }
    2764             :     case ID_SIMPLE_BLOCK:
    2765           0 :       r = ne_read_block(ctx, id, size, pkt);
    2766           0 :       if (r != 1)
    2767           0 :         return r;
    2768             : 
    2769           0 :       read_block = 1;
    2770           0 :       break;
    2771             :     case ID_BLOCK_GROUP: {
    2772             :       int64_t block_group_end;
    2773           0 :       uint64_t block_duration = 0;
    2774           0 :       int read_block_duration = 0;
    2775           0 :       int64_t discard_padding = 0;
    2776           0 :       int read_discard_padding = 0;
    2777           0 :       int64_t reference_block = 0;
    2778           0 :       int read_reference_block = 0;
    2779           0 :       struct block_additional * block_additional = NULL;
    2780             :       uint64_t tc_scale;
    2781             : 
    2782           0 :       block_group_end = ne_io_tell(ctx->io) + size;
    2783             : 
    2784             :       /* Read the entire BlockGroup manually. */
    2785           0 :       while (ne_io_tell(ctx->io) < block_group_end) {
    2786           0 :         r = ne_read_element(ctx, &id, &size);
    2787           0 :         if (r != 1) {
    2788           0 :           free(block_additional);
    2789           0 :           if (*pkt) {
    2790           0 :             nestegg_free_packet(*pkt);
    2791           0 :             *pkt = NULL;
    2792             :           }
    2793           0 :           return r;
    2794             :         }
    2795             : 
    2796           0 :         switch (id) {
    2797             :         case ID_BLOCK: {
    2798           0 :           r = ne_read_block(ctx, id, size, pkt);
    2799           0 :           if (r != 1) {
    2800           0 :             free(block_additional);
    2801           0 :             if (*pkt) {
    2802           0 :               nestegg_free_packet(*pkt);
    2803           0 :               *pkt = NULL;
    2804             :             }
    2805           0 :             return r;
    2806             :           }
    2807             : 
    2808           0 :           read_block = 1;
    2809           0 :           break;
    2810             :         }
    2811             :         case ID_BLOCK_DURATION: {
    2812           0 :           r = ne_read_uint(ctx->io, &block_duration, size);
    2813           0 :           if (r != 1) {
    2814           0 :             free(block_additional);
    2815           0 :             if (*pkt) {
    2816           0 :               nestegg_free_packet(*pkt);
    2817           0 :               *pkt = NULL;
    2818             :             }
    2819           0 :             return r;
    2820             :           }
    2821           0 :           tc_scale = ne_get_timecode_scale(ctx);
    2822           0 :           if (tc_scale == 0) {
    2823           0 :             free(block_additional);
    2824           0 :             if (*pkt) {
    2825           0 :               nestegg_free_packet(*pkt);
    2826           0 :               *pkt = NULL;
    2827             :             }
    2828           0 :             return -1;
    2829             :           }
    2830           0 :           block_duration *= tc_scale;
    2831           0 :           read_block_duration = 1;
    2832           0 :           break;
    2833             :         }
    2834             :         case ID_DISCARD_PADDING: {
    2835           0 :           r = ne_read_int(ctx->io, &discard_padding, size);
    2836           0 :           if (r != 1) {
    2837           0 :             free(block_additional);
    2838           0 :             if (*pkt) {
    2839           0 :               nestegg_free_packet(*pkt);
    2840           0 :               *pkt = NULL;
    2841             :             }
    2842           0 :             return r;
    2843             :           }
    2844           0 :           read_discard_padding = 1;
    2845           0 :           break;
    2846             :         }
    2847             :         case ID_BLOCK_ADDITIONS: {
    2848             :           /* There should only be one BlockAdditions; treat multiple as an error. */
    2849           0 :           if (block_additional) {
    2850           0 :             free(block_additional);
    2851           0 :             if (*pkt) {
    2852           0 :               nestegg_free_packet(*pkt);
    2853           0 :               *pkt = NULL;
    2854             :             }
    2855           0 :             return -1;
    2856             :           }
    2857           0 :           r = ne_read_block_additions(ctx, size, &block_additional);
    2858           0 :           if (r != 1) {
    2859           0 :             free(block_additional);
    2860           0 :             if (*pkt) {
    2861           0 :               nestegg_free_packet(*pkt);
    2862           0 :               *pkt = NULL;
    2863             :             }
    2864           0 :             return r;
    2865             :           }
    2866           0 :           break;
    2867             :         }
    2868             :         case ID_REFERENCE_BLOCK: {
    2869           0 :           r = ne_read_int(ctx->io, &reference_block, size);
    2870           0 :           if (r != 1) {
    2871           0 :             free(block_additional);
    2872           0 :             if (*pkt) {
    2873           0 :               nestegg_free_packet(*pkt);
    2874           0 :               *pkt = NULL;
    2875             :             }
    2876           0 :             return r;
    2877             :           }
    2878           0 :           read_reference_block = 1;
    2879           0 :           break;
    2880             :         }
    2881             :         default:
    2882             :           /* We don't know what this element is, so skip over it */
    2883           0 :           if (id != ID_VOID && id != ID_CRC32)
    2884           0 :             ctx->log(ctx, NESTEGG_LOG_DEBUG,
    2885             :                      "read_packet: unknown element %llx in BlockGroup", id);
    2886           0 :           r = ne_io_read_skip(ctx->io, size);
    2887           0 :           if (r != 1) {
    2888           0 :             free(block_additional);
    2889           0 :             if (*pkt) {
    2890           0 :               nestegg_free_packet(*pkt);
    2891           0 :               *pkt = NULL;
    2892             :             }
    2893           0 :             return r;
    2894             :           }
    2895             :         }
    2896             :       }
    2897             : 
    2898           0 :       assert(read_block == (*pkt != NULL));
    2899           0 :       if (*pkt) {
    2900           0 :         (*pkt)->duration = block_duration;
    2901           0 :         (*pkt)->read_duration = read_block_duration;
    2902           0 :         (*pkt)->discard_padding = discard_padding;
    2903           0 :         (*pkt)->read_discard_padding = read_discard_padding;
    2904           0 :         (*pkt)->reference_block = reference_block;
    2905           0 :         (*pkt)->read_reference_block = read_reference_block;
    2906           0 :         (*pkt)->block_additional = block_additional;
    2907           0 :         if ((*pkt)->read_reference_block)
    2908             :           /* If a packet has a reference block it contains
    2909             :              predictive frames and no keyframes */
    2910           0 :           (*pkt)->keyframe = NESTEGG_PACKET_HAS_KEYFRAME_FALSE;
    2911             :       } else {
    2912           0 :         free(block_additional);
    2913             :       }
    2914           0 :       break;
    2915             :     }
    2916             :     default:
    2917           0 :       ctx->log(ctx, NESTEGG_LOG_DEBUG, "read_packet: unknown element %llx", id);
    2918           0 :       r = ne_io_read_skip(ctx->io, size);
    2919           0 :       if (r != 1)
    2920           0 :         return r;
    2921             :     }
    2922             :   }
    2923             : 
    2924           0 :   return 1;
    2925             : }
    2926             : 
    2927             : void
    2928           0 : nestegg_free_packet(nestegg_packet * pkt)
    2929             : {
    2930             :   struct frame * frame;
    2931             :   struct block_additional * block_additional;
    2932             : 
    2933           0 :   while (pkt->frame) {
    2934           0 :     frame = pkt->frame;
    2935           0 :     pkt->frame = frame->next;
    2936             : 
    2937           0 :     ne_free_frame(frame);
    2938             :   }
    2939             : 
    2940           0 :   while (pkt->block_additional) {
    2941           0 :     block_additional = pkt->block_additional;
    2942           0 :     pkt->block_additional = block_additional->next;
    2943           0 :     free(block_additional->data);
    2944           0 :     free(block_additional);
    2945             :   }
    2946             : 
    2947           0 :   free(pkt);
    2948           0 : }
    2949             : 
    2950             : int
    2951           0 : nestegg_packet_has_keyframe(nestegg_packet * pkt)
    2952             : {
    2953           0 :   return pkt->keyframe;
    2954             : }
    2955             : 
    2956             : int
    2957           0 : nestegg_packet_track(nestegg_packet * pkt, unsigned int * track)
    2958             : {
    2959           0 :   *track = pkt->track;
    2960           0 :   return 0;
    2961             : }
    2962             : 
    2963             : int
    2964           0 : nestegg_packet_tstamp(nestegg_packet * pkt, uint64_t * tstamp)
    2965             : {
    2966           0 :   *tstamp = pkt->timecode;
    2967           0 :   return 0;
    2968             : }
    2969             : 
    2970             : int
    2971           0 : nestegg_packet_duration(nestegg_packet * pkt, uint64_t * duration)
    2972             : {
    2973           0 :   if (!pkt->read_duration)
    2974           0 :     return -1;
    2975           0 :   *duration = pkt->duration;
    2976           0 :   return 0;
    2977             : }
    2978             : 
    2979             : int
    2980           0 : nestegg_packet_discard_padding(nestegg_packet * pkt, int64_t * discard_padding)
    2981             : {
    2982           0 :   if (!pkt->read_discard_padding)
    2983           0 :     return -1;
    2984           0 :   *discard_padding = pkt->discard_padding;
    2985           0 :   return 0;
    2986             : }
    2987             : 
    2988             : int
    2989           0 : nestegg_packet_reference_block(nestegg_packet * pkt, int64_t * reference_block)
    2990             : {
    2991           0 :   if (!pkt->read_reference_block)
    2992           0 :     return -1;
    2993           0 :   *reference_block = pkt->reference_block;
    2994           0 :   return 0;
    2995             : }
    2996             : 
    2997             : int
    2998           0 : nestegg_packet_count(nestegg_packet * pkt, unsigned int * count)
    2999             : {
    3000           0 :   struct frame * f = pkt->frame;
    3001             : 
    3002           0 :   *count = 0;
    3003             : 
    3004           0 :   while (f) {
    3005           0 :     *count += 1;
    3006           0 :     f = f->next;
    3007             :   }
    3008             : 
    3009           0 :   return 0;
    3010             : }
    3011             : 
    3012             : int
    3013           0 : nestegg_packet_data(nestegg_packet * pkt, unsigned int item,
    3014             :                     unsigned char ** data, size_t * length)
    3015             : {
    3016           0 :   struct frame * f = pkt->frame;
    3017           0 :   unsigned int count = 0;
    3018             : 
    3019           0 :   *data = NULL;
    3020           0 :   *length = 0;
    3021             : 
    3022           0 :   while (f) {
    3023           0 :     if (count == item) {
    3024           0 :       *data = f->data;
    3025           0 :       *length = f->length;
    3026           0 :       return 0;
    3027             :     }
    3028           0 :     count += 1;
    3029           0 :     f = f->next;
    3030             :   }
    3031             : 
    3032           0 :   return -1;
    3033             : }
    3034             : 
    3035             : int
    3036           0 : nestegg_packet_additional_data(nestegg_packet * pkt, unsigned int id,
    3037             :                                unsigned char ** data, size_t * length)
    3038             : {
    3039           0 :   struct block_additional * a = pkt->block_additional;
    3040             : 
    3041           0 :   *data = NULL;
    3042           0 :   *length = 0;
    3043             : 
    3044           0 :   while (a) {
    3045           0 :     if (a->id == id) {
    3046           0 :       *data = a->data;
    3047           0 :       *length = a->length;
    3048           0 :       return 0;
    3049             :     }
    3050           0 :     a = a->next;
    3051             :   }
    3052             : 
    3053           0 :   return -1;
    3054             : }
    3055             : 
    3056             : int
    3057           0 : nestegg_packet_encryption(nestegg_packet * pkt)
    3058             : {
    3059           0 :   struct frame * f = pkt->frame;
    3060             :   unsigned char encrypted_bit;
    3061             :   unsigned char partitioned_bit;
    3062             : 
    3063           0 :   if (!f->frame_encryption)
    3064           0 :     return NESTEGG_PACKET_HAS_SIGNAL_BYTE_FALSE;
    3065             : 
    3066             :   /* Should never have parsed blocks with both encryption and lacing */
    3067           0 :   assert(f->next == NULL);
    3068             : 
    3069           0 :   encrypted_bit = f->frame_encryption->signal_byte & ENCRYPTED_BIT_MASK;
    3070           0 :   partitioned_bit = f->frame_encryption->signal_byte & PARTITIONED_BIT_MASK;
    3071             : 
    3072           0 :   if (encrypted_bit != PACKET_ENCRYPTED)
    3073           0 :     return NESTEGG_PACKET_HAS_SIGNAL_BYTE_UNENCRYPTED;
    3074             : 
    3075           0 :   if (partitioned_bit == PACKET_PARTITIONED)
    3076           0 :     return NESTEGG_PACKET_HAS_SIGNAL_BYTE_PARTITIONED;
    3077             : 
    3078           0 :   return NESTEGG_PACKET_HAS_SIGNAL_BYTE_ENCRYPTED;
    3079             : }
    3080             : 
    3081             : int
    3082           0 : nestegg_packet_iv(nestegg_packet * pkt, unsigned char const ** iv, size_t * length)
    3083             : {
    3084           0 :   struct frame * f = pkt->frame;
    3085             :   unsigned char encrypted_bit;
    3086             : 
    3087           0 :   *iv = NULL;
    3088           0 :   *length = 0;
    3089           0 :   if (!f->frame_encryption)
    3090           0 :     return -1;
    3091             : 
    3092             :   /* Should never have parsed blocks with both encryption and lacing */
    3093           0 :   assert(f->next == NULL);
    3094             : 
    3095           0 :   encrypted_bit = f->frame_encryption->signal_byte & ENCRYPTED_BIT_MASK;
    3096             : 
    3097           0 :   if (encrypted_bit != PACKET_ENCRYPTED)
    3098           0 :     return 0;
    3099             : 
    3100           0 :   *iv = f->frame_encryption->iv;
    3101           0 :   *length = f->frame_encryption->length;
    3102           0 :   return 0;
    3103             : }
    3104             : 
    3105             : int
    3106           0 : nestegg_packet_offsets(nestegg_packet * pkt,
    3107             :                        uint32_t const ** partition_offsets,
    3108             :                        uint8_t * num_partitions)
    3109             : {
    3110           0 :   struct frame * f = pkt->frame;
    3111             :   unsigned char encrypted_bit;
    3112             :   unsigned char partitioned_bit;
    3113             : 
    3114           0 :   *partition_offsets = NULL;
    3115           0 :   *num_partitions = 0;
    3116             : 
    3117           0 :   if (!f->frame_encryption)
    3118           0 :     return -1;
    3119             : 
    3120             :   /* Should never have parsed blocks with both encryption and lacing */
    3121           0 :   assert(f->next == NULL);
    3122             : 
    3123           0 :   encrypted_bit = f->frame_encryption->signal_byte & ENCRYPTED_BIT_MASK;
    3124           0 :   partitioned_bit = f->frame_encryption->signal_byte & PARTITIONED_BIT_MASK;
    3125             : 
    3126           0 :   if (encrypted_bit != PACKET_ENCRYPTED || partitioned_bit != PACKET_PARTITIONED)
    3127           0 :     return -1;
    3128             : 
    3129           0 :   *num_partitions = f->frame_encryption->num_partitions;
    3130           0 :   *partition_offsets = f->frame_encryption->partition_offsets;
    3131           0 :   return 0;
    3132             : }
    3133             : 
    3134             : int
    3135           0 : nestegg_has_cues(nestegg * ctx)
    3136             : {
    3137           0 :   return ctx->segment.cues.cue_point.head ||
    3138           0 :     ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES);
    3139             : }
    3140             : 
    3141             : int
    3142           0 : nestegg_sniff(unsigned char const * buffer, size_t length)
    3143             : {
    3144             :   nestegg_io io;
    3145             :   struct io_buffer userdata;
    3146             : 
    3147           0 :   userdata.buffer = buffer;
    3148           0 :   userdata.length = length;
    3149           0 :   userdata.offset = 0;
    3150             : 
    3151           0 :   io.read = ne_buffer_read;
    3152           0 :   io.seek = ne_buffer_seek;
    3153           0 :   io.tell = ne_buffer_tell;
    3154           0 :   io.userdata = &userdata;
    3155           0 :   return ne_match_webm(io, length);
    3156             : }

Generated by: LCOV version 1.13