1233d2500723e5594f3e7c70896ffeeef32b9c950ywan/*
2233d2500723e5594f3e7c70896ffeeef32b9c950ywan * Copyright © 2010 Mozilla Foundation
3233d2500723e5594f3e7c70896ffeeef32b9c950ywan *
4233d2500723e5594f3e7c70896ffeeef32b9c950ywan * This program is made available under an ISC-style license.  See the
5233d2500723e5594f3e7c70896ffeeef32b9c950ywan * accompanying file LICENSE for details.
6233d2500723e5594f3e7c70896ffeeef32b9c950ywan */
7233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <assert.h>
8233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <stdlib.h>
9233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include <string.h>
10233d2500723e5594f3e7c70896ffeeef32b9c950ywan
11233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "third_party/nestegg/halloc/halloc.h"
12233d2500723e5594f3e7c70896ffeeef32b9c950ywan#include "third_party/nestegg/include/nestegg/nestegg.h"
13233d2500723e5594f3e7c70896ffeeef32b9c950ywan
14233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* EBML Elements */
15233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_EBML                 0x1a45dfa3
16233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_EBML_VERSION         0x4286
17233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_EBML_READ_VERSION    0x42f7
18233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_EBML_MAX_ID_LENGTH   0x42f2
19233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_EBML_MAX_SIZE_LENGTH 0x42f3
20233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_DOCTYPE              0x4282
21233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_DOCTYPE_VERSION      0x4287
22233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_DOCTYPE_READ_VERSION 0x4285
23233d2500723e5594f3e7c70896ffeeef32b9c950ywan
24233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Global Elements */
25233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_VOID                 0xec
26233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_CRC32                0xbf
27233d2500723e5594f3e7c70896ffeeef32b9c950ywan
28233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* WebM Elements */
29233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_SEGMENT              0x18538067
30233d2500723e5594f3e7c70896ffeeef32b9c950ywan
31233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Seek Head Elements */
32233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_SEEK_HEAD            0x114d9b74
33233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_SEEK                 0x4dbb
34233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_SEEK_ID              0x53ab
35233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_SEEK_POSITION        0x53ac
36233d2500723e5594f3e7c70896ffeeef32b9c950ywan
37233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Info Elements */
38233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_INFO                 0x1549a966
39233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_TIMECODE_SCALE       0x2ad7b1
40233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_DURATION             0x4489
41233d2500723e5594f3e7c70896ffeeef32b9c950ywan
42233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Cluster Elements */
43233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_CLUSTER              0x1f43b675
44233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_TIMECODE             0xe7
45233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_BLOCK_GROUP          0xa0
46233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_SIMPLE_BLOCK         0xa3
47233d2500723e5594f3e7c70896ffeeef32b9c950ywan
48233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* BlockGroup Elements */
49233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_BLOCK                0xa1
50233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_BLOCK_DURATION       0x9b
51233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_REFERENCE_BLOCK      0xfb
52233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_DISCARD_PADDING      0x75a2
53233d2500723e5594f3e7c70896ffeeef32b9c950ywan
54233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Tracks Elements */
55233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_TRACKS               0x1654ae6b
56233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_TRACK_ENTRY          0xae
57233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_TRACK_NUMBER         0xd7
58233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_TRACK_UID            0x73c5
59233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_TRACK_TYPE           0x83
60233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_FLAG_ENABLED         0xb9
61233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_FLAG_DEFAULT         0x88
62233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_FLAG_LACING          0x9c
63233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_TRACK_TIMECODE_SCALE 0x23314f
64233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_LANGUAGE             0x22b59c
65233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_CODEC_ID             0x86
66233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_CODEC_PRIVATE        0x63a2
67233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_CODEC_DELAY          0x56aa
68233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_SEEK_PREROLL         0x56bb
69233d2500723e5594f3e7c70896ffeeef32b9c950ywan
70233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Video Elements */
71233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_VIDEO                0xe0
72233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_STEREO_MODE          0x53b8
73233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_PIXEL_WIDTH          0xb0
74233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_PIXEL_HEIGHT         0xba
75233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_PIXEL_CROP_BOTTOM    0x54aa
76233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_PIXEL_CROP_TOP       0x54bb
77233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_PIXEL_CROP_LEFT      0x54cc
78233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_PIXEL_CROP_RIGHT     0x54dd
79233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_DISPLAY_WIDTH        0x54b0
80233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_DISPLAY_HEIGHT       0x54ba
81233d2500723e5594f3e7c70896ffeeef32b9c950ywan
82233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Audio Elements */
83233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_AUDIO                0xe1
84233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_SAMPLING_FREQUENCY   0xb5
85233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_CHANNELS             0x9f
86233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_BIT_DEPTH            0x6264
87233d2500723e5594f3e7c70896ffeeef32b9c950ywan
88233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Cues Elements */
89233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_CUES                 0x1c53bb6b
90233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_CUE_POINT            0xbb
91233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_CUE_TIME             0xb3
92233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_CUE_TRACK_POSITIONS  0xb7
93233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_CUE_TRACK            0xf7
94233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_CUE_CLUSTER_POSITION 0xf1
95233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define ID_CUE_BLOCK_NUMBER     0x5378
96233d2500723e5594f3e7c70896ffeeef32b9c950ywan
97233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* EBML Types */
98233d2500723e5594f3e7c70896ffeeef32b9c950ywanenum ebml_type_enum {
99233d2500723e5594f3e7c70896ffeeef32b9c950ywan  TYPE_UNKNOWN,
100233d2500723e5594f3e7c70896ffeeef32b9c950ywan  TYPE_MASTER,
101233d2500723e5594f3e7c70896ffeeef32b9c950ywan  TYPE_UINT,
102233d2500723e5594f3e7c70896ffeeef32b9c950ywan  TYPE_FLOAT,
103233d2500723e5594f3e7c70896ffeeef32b9c950ywan  TYPE_INT,
104233d2500723e5594f3e7c70896ffeeef32b9c950ywan  TYPE_STRING,
105233d2500723e5594f3e7c70896ffeeef32b9c950ywan  TYPE_BINARY
106233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
107233d2500723e5594f3e7c70896ffeeef32b9c950ywan
108233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define LIMIT_STRING            (1 << 20)
109233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define LIMIT_BINARY            (1 << 24)
110233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define LIMIT_BLOCK             (1 << 30)
111233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define LIMIT_FRAME             (1 << 28)
112233d2500723e5594f3e7c70896ffeeef32b9c950ywan
113233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Field Flags */
114233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define DESC_FLAG_NONE          0
115233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define DESC_FLAG_MULTI         (1 << 0)
116233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define DESC_FLAG_SUSPEND       (1 << 1)
117233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define DESC_FLAG_OFFSET        (1 << 2)
118233d2500723e5594f3e7c70896ffeeef32b9c950ywan
119233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Block Header Flags */
120233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define BLOCK_FLAGS_LACING      6
121233d2500723e5594f3e7c70896ffeeef32b9c950ywan
122233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Lacing Constants */
123233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define LACING_NONE             0
124233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define LACING_XIPH             1
125233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define LACING_FIXED            2
126233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define LACING_EBML             3
127233d2500723e5594f3e7c70896ffeeef32b9c950ywan
128233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Track Types */
129233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define TRACK_TYPE_VIDEO        1
130233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define TRACK_TYPE_AUDIO        2
131233d2500723e5594f3e7c70896ffeeef32b9c950ywan
132233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Track IDs */
133233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define TRACK_ID_VP8            "V_VP8"
134233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define TRACK_ID_VP9            "V_VP9"
135233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define TRACK_ID_VORBIS         "A_VORBIS"
136233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define TRACK_ID_OPUS           "A_OPUS"
137233d2500723e5594f3e7c70896ffeeef32b9c950ywan
138233d2500723e5594f3e7c70896ffeeef32b9c950ywanenum vint_mask {
139233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MASK_NONE,
140233d2500723e5594f3e7c70896ffeeef32b9c950ywan  MASK_FIRST_BIT
141233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
142233d2500723e5594f3e7c70896ffeeef32b9c950ywan
143233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct ebml_binary {
144233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned char * data;
145233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size_t length;
146233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
147233d2500723e5594f3e7c70896ffeeef32b9c950ywan
148233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct ebml_list_node {
149233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list_node * next;
150233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t id;
151233d2500723e5594f3e7c70896ffeeef32b9c950ywan  void * data;
152233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
153233d2500723e5594f3e7c70896ffeeef32b9c950ywan
154233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct ebml_list {
155233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list_node * head;
156233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list_node * tail;
157233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
158233d2500723e5594f3e7c70896ffeeef32b9c950ywan
159233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct ebml_type {
160233d2500723e5594f3e7c70896ffeeef32b9c950ywan  union ebml_value {
161233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64_t u;
162233d2500723e5594f3e7c70896ffeeef32b9c950ywan    double f;
163233d2500723e5594f3e7c70896ffeeef32b9c950ywan    int64_t i;
164233d2500723e5594f3e7c70896ffeeef32b9c950ywan    char * s;
165233d2500723e5594f3e7c70896ffeeef32b9c950ywan    struct ebml_binary b;
166233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } v;
167233d2500723e5594f3e7c70896ffeeef32b9c950ywan  enum ebml_type_enum type;
168233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int read;
169233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
170233d2500723e5594f3e7c70896ffeeef32b9c950ywan
171233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* EBML Definitions */
172233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct ebml {
173233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type ebml_version;
174233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type ebml_read_version;
175233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type ebml_max_id_length;
176233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type ebml_max_size_length;
177233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type doctype;
178233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type doctype_version;
179233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type doctype_read_version;
180233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
181233d2500723e5594f3e7c70896ffeeef32b9c950ywan
182233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Matroksa Definitions */
183233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct seek {
184233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type id;
185233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type position;
186233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
187233d2500723e5594f3e7c70896ffeeef32b9c950ywan
188233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct seek_head {
189233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list seek;
190233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
191233d2500723e5594f3e7c70896ffeeef32b9c950ywan
192233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct info {
193233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type timecode_scale;
194233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type duration;
195233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
196233d2500723e5594f3e7c70896ffeeef32b9c950ywan
197233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct block_group {
198233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type duration;
199233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type reference_block;
200233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type discard_padding;
201233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
202233d2500723e5594f3e7c70896ffeeef32b9c950ywan
203233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct cluster {
204233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type timecode;
205233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list block_group;
206233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
207233d2500723e5594f3e7c70896ffeeef32b9c950ywan
208233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct video {
209233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type stereo_mode;
210233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type pixel_width;
211233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type pixel_height;
212233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type pixel_crop_bottom;
213233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type pixel_crop_top;
214233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type pixel_crop_left;
215233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type pixel_crop_right;
216233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type display_width;
217233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type display_height;
218233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
219233d2500723e5594f3e7c70896ffeeef32b9c950ywan
220233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct audio {
221233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type sampling_frequency;
222233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type channels;
223233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type bit_depth;
224233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
225233d2500723e5594f3e7c70896ffeeef32b9c950ywan
226233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct track_entry {
227233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type number;
228233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type uid;
229233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type type;
230233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type flag_enabled;
231233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type flag_default;
232233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type flag_lacing;
233233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type track_timecode_scale;
234233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type language;
235233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type codec_id;
236233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type codec_private;
237233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type codec_delay;
238233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type seek_preroll;
239233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct video video;
240233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct audio audio;
241233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
242233d2500723e5594f3e7c70896ffeeef32b9c950ywan
243233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct tracks {
244233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list track_entry;
245233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
246233d2500723e5594f3e7c70896ffeeef32b9c950ywan
247233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct cue_track_positions {
248233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type track;
249233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type cluster_position;
250233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type block_number;
251233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
252233d2500723e5594f3e7c70896ffeeef32b9c950ywan
253233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct cue_point {
254233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type time;
255233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list cue_track_positions;
256233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
257233d2500723e5594f3e7c70896ffeeef32b9c950ywan
258233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct cues {
259233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list cue_point;
260233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
261233d2500723e5594f3e7c70896ffeeef32b9c950ywan
262233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct segment {
263233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list seek_head;
264233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct info info;
265233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list cluster;
266233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct tracks tracks;
267233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct cues cues;
268233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
269233d2500723e5594f3e7c70896ffeeef32b9c950ywan
270233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Misc. */
271233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct pool_ctx {
272233d2500723e5594f3e7c70896ffeeef32b9c950ywan  char dummy;
273233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
274233d2500723e5594f3e7c70896ffeeef32b9c950ywan
275233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct list_node {
276233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct list_node * previous;
277233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_element_desc * node;
278233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned char * data;
279233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
280233d2500723e5594f3e7c70896ffeeef32b9c950ywan
281233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct saved_state {
282233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t stream_offset;
283233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct list_node * ancestor;
284233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t last_id;
285233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t last_size;
286233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int last_valid;
287233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
288233d2500723e5594f3e7c70896ffeeef32b9c950ywan
289233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct frame {
290233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned char * data;
291233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size_t length;
292233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct frame * next;
293233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
294233d2500723e5594f3e7c70896ffeeef32b9c950ywan
295233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Public (opaque) Structures */
296233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct nestegg {
297233d2500723e5594f3e7c70896ffeeef32b9c950ywan  nestegg_io * io;
298233d2500723e5594f3e7c70896ffeeef32b9c950ywan  nestegg_log log;
299233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct pool_ctx * alloc_pool;
300233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t last_id;
301233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t last_size;
302233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int last_valid;
303233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct list_node * ancestor;
304233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml ebml;
305233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct segment segment;
306233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t segment_offset;
307233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int track_count;
308233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
309233d2500723e5594f3e7c70896ffeeef32b9c950ywan
310233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct nestegg_packet {
311233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t track;
312233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t timecode;
313233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct frame * frame;
314233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t discard_padding;
315233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
316233d2500723e5594f3e7c70896ffeeef32b9c950ywan
317233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Element Descriptor */
318233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct ebml_element_desc {
319233d2500723e5594f3e7c70896ffeeef32b9c950ywan  char const * name;
320233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t id;
321233d2500723e5594f3e7c70896ffeeef32b9c950ywan  enum ebml_type_enum type;
322233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size_t offset;
323233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int flags;
324233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_element_desc * children;
325233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size_t size;
326233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size_t data_offset;
327233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
328233d2500723e5594f3e7c70896ffeeef32b9c950ywan
329233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define E_FIELD(ID, TYPE, STRUCT, FIELD) \
330233d2500723e5594f3e7c70896ffeeef32b9c950ywan  { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_NONE, NULL, 0, 0 }
331233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define E_MASTER(ID, TYPE, STRUCT, FIELD) \
332233d2500723e5594f3e7c70896ffeeef32b9c950ywan  { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_MULTI, ne_ ## FIELD ## _elements, \
333233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sizeof(struct FIELD), 0 }
334233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define E_SINGLE_MASTER_O(ID, TYPE, STRUCT, FIELD) \
335233d2500723e5594f3e7c70896ffeeef32b9c950ywan  { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_OFFSET, ne_ ## FIELD ## _elements, 0, \
336233d2500723e5594f3e7c70896ffeeef32b9c950ywan      offsetof(STRUCT, FIELD ## _offset) }
337233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define E_SINGLE_MASTER(ID, TYPE, STRUCT, FIELD) \
338233d2500723e5594f3e7c70896ffeeef32b9c950ywan  { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_NONE, ne_ ## FIELD ## _elements, 0, 0 }
339233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define E_SUSPEND(ID, TYPE) \
340233d2500723e5594f3e7c70896ffeeef32b9c950ywan  { #ID, ID, TYPE, 0, DESC_FLAG_SUSPEND, NULL, 0, 0 }
341233d2500723e5594f3e7c70896ffeeef32b9c950ywan#define E_LAST \
342233d2500723e5594f3e7c70896ffeeef32b9c950ywan  { NULL, 0, 0, 0, DESC_FLAG_NONE, NULL, 0, 0 }
343233d2500723e5594f3e7c70896ffeeef32b9c950ywan
344233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* EBML Element Lists */
345233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct ebml_element_desc ne_ebml_elements[] = {
346233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_EBML_VERSION, TYPE_UINT, struct ebml, ebml_version),
347233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_EBML_READ_VERSION, TYPE_UINT, struct ebml, ebml_read_version),
348233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_EBML_MAX_ID_LENGTH, TYPE_UINT, struct ebml, ebml_max_id_length),
349233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_EBML_MAX_SIZE_LENGTH, TYPE_UINT, struct ebml, ebml_max_size_length),
350233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_DOCTYPE, TYPE_STRING, struct ebml, doctype),
351233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_DOCTYPE_VERSION, TYPE_UINT, struct ebml, doctype_version),
352233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_DOCTYPE_READ_VERSION, TYPE_UINT, struct ebml, doctype_read_version),
353233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_LAST
354233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
355233d2500723e5594f3e7c70896ffeeef32b9c950ywan
356233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* WebM Element Lists */
357233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct ebml_element_desc ne_seek_elements[] = {
358233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_SEEK_ID, TYPE_BINARY, struct seek, id),
359233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_SEEK_POSITION, TYPE_UINT, struct seek, position),
360233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_LAST
361233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
362233d2500723e5594f3e7c70896ffeeef32b9c950ywan
363233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct ebml_element_desc ne_seek_head_elements[] = {
364233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_MASTER(ID_SEEK, TYPE_MASTER, struct seek_head, seek),
365233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_LAST
366233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
367233d2500723e5594f3e7c70896ffeeef32b9c950ywan
368233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct ebml_element_desc ne_info_elements[] = {
369233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_TIMECODE_SCALE, TYPE_UINT, struct info, timecode_scale),
370233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_DURATION, TYPE_FLOAT, struct info, duration),
371233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_LAST
372233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
373233d2500723e5594f3e7c70896ffeeef32b9c950ywan
374233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct ebml_element_desc ne_block_group_elements[] = {
375233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_SUSPEND(ID_BLOCK, TYPE_BINARY),
376233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_BLOCK_DURATION, TYPE_UINT, struct block_group, duration),
377233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_REFERENCE_BLOCK, TYPE_INT, struct block_group, reference_block),
378233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_DISCARD_PADDING, TYPE_INT, struct block_group, discard_padding),
379233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_LAST
380233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
381233d2500723e5594f3e7c70896ffeeef32b9c950ywan
382233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct ebml_element_desc ne_cluster_elements[] = {
383233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_TIMECODE, TYPE_UINT, struct cluster, timecode),
384233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_MASTER(ID_BLOCK_GROUP, TYPE_MASTER, struct cluster, block_group),
385233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_SUSPEND(ID_SIMPLE_BLOCK, TYPE_BINARY),
386233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_LAST
387233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
388233d2500723e5594f3e7c70896ffeeef32b9c950ywan
389233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct ebml_element_desc ne_video_elements[] = {
390233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_STEREO_MODE, TYPE_UINT, struct video, stereo_mode),
391233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_PIXEL_WIDTH, TYPE_UINT, struct video, pixel_width),
392233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_PIXEL_HEIGHT, TYPE_UINT, struct video, pixel_height),
393233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_PIXEL_CROP_BOTTOM, TYPE_UINT, struct video, pixel_crop_bottom),
394233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_PIXEL_CROP_TOP, TYPE_UINT, struct video, pixel_crop_top),
395233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_PIXEL_CROP_LEFT, TYPE_UINT, struct video, pixel_crop_left),
396233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_PIXEL_CROP_RIGHT, TYPE_UINT, struct video, pixel_crop_right),
397233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_DISPLAY_WIDTH, TYPE_UINT, struct video, display_width),
398233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_DISPLAY_HEIGHT, TYPE_UINT, struct video, display_height),
399233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_LAST
400233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
401233d2500723e5594f3e7c70896ffeeef32b9c950ywan
402233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct ebml_element_desc ne_audio_elements[] = {
403233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_SAMPLING_FREQUENCY, TYPE_FLOAT, struct audio, sampling_frequency),
404233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_CHANNELS, TYPE_UINT, struct audio, channels),
405233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_BIT_DEPTH, TYPE_UINT, struct audio, bit_depth),
406233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_LAST
407233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
408233d2500723e5594f3e7c70896ffeeef32b9c950ywan
409233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct ebml_element_desc ne_track_entry_elements[] = {
410233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_TRACK_NUMBER, TYPE_UINT, struct track_entry, number),
411233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_TRACK_UID, TYPE_UINT, struct track_entry, uid),
412233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_TRACK_TYPE, TYPE_UINT, struct track_entry, type),
413233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_FLAG_ENABLED, TYPE_UINT, struct track_entry, flag_enabled),
414233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_FLAG_DEFAULT, TYPE_UINT, struct track_entry, flag_default),
415233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_FLAG_LACING, TYPE_UINT, struct track_entry, flag_lacing),
416233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_TRACK_TIMECODE_SCALE, TYPE_FLOAT, struct track_entry, track_timecode_scale),
417233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_LANGUAGE, TYPE_STRING, struct track_entry, language),
418233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_CODEC_ID, TYPE_STRING, struct track_entry, codec_id),
419233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_CODEC_PRIVATE, TYPE_BINARY, struct track_entry, codec_private),
420233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_CODEC_DELAY, TYPE_UINT, struct track_entry, codec_delay),
421233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_SEEK_PREROLL, TYPE_UINT, struct track_entry, seek_preroll),
422233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_SINGLE_MASTER(ID_VIDEO, TYPE_MASTER, struct track_entry, video),
423233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_SINGLE_MASTER(ID_AUDIO, TYPE_MASTER, struct track_entry, audio),
424233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_LAST
425233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
426233d2500723e5594f3e7c70896ffeeef32b9c950ywan
427233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct ebml_element_desc ne_tracks_elements[] = {
428233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_MASTER(ID_TRACK_ENTRY, TYPE_MASTER, struct tracks, track_entry),
429233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_LAST
430233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
431233d2500723e5594f3e7c70896ffeeef32b9c950ywan
432233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct ebml_element_desc ne_cue_track_positions_elements[] = {
433233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_CUE_TRACK, TYPE_UINT, struct cue_track_positions, track),
434233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_CUE_CLUSTER_POSITION, TYPE_UINT, struct cue_track_positions, cluster_position),
435233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_CUE_BLOCK_NUMBER, TYPE_UINT, struct cue_track_positions, block_number),
436233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_LAST
437233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
438233d2500723e5594f3e7c70896ffeeef32b9c950ywan
439233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct ebml_element_desc ne_cue_point_elements[] = {
440233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_FIELD(ID_CUE_TIME, TYPE_UINT, struct cue_point, time),
441233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_MASTER(ID_CUE_TRACK_POSITIONS, TYPE_MASTER, struct cue_point, cue_track_positions),
442233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_LAST
443233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
444233d2500723e5594f3e7c70896ffeeef32b9c950ywan
445233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct ebml_element_desc ne_cues_elements[] = {
446233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_MASTER(ID_CUE_POINT, TYPE_MASTER, struct cues, cue_point),
447233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_LAST
448233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
449233d2500723e5594f3e7c70896ffeeef32b9c950ywan
450233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct ebml_element_desc ne_segment_elements[] = {
451233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_MASTER(ID_SEEK_HEAD, TYPE_MASTER, struct segment, seek_head),
452233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_SINGLE_MASTER(ID_INFO, TYPE_MASTER, struct segment, info),
453233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_MASTER(ID_CLUSTER, TYPE_MASTER, struct segment, cluster),
454233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_SINGLE_MASTER(ID_TRACKS, TYPE_MASTER, struct segment, tracks),
455233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_SINGLE_MASTER(ID_CUES, TYPE_MASTER, struct segment, cues),
456233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_LAST
457233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
458233d2500723e5594f3e7c70896ffeeef32b9c950ywan
459233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct ebml_element_desc ne_top_level_elements[] = {
460233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_SINGLE_MASTER(ID_EBML, TYPE_MASTER, nestegg, ebml),
461233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_SINGLE_MASTER_O(ID_SEGMENT, TYPE_MASTER, nestegg, segment),
462233d2500723e5594f3e7c70896ffeeef32b9c950ywan  E_LAST
463233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
464233d2500723e5594f3e7c70896ffeeef32b9c950ywan
465233d2500723e5594f3e7c70896ffeeef32b9c950ywan#undef E_FIELD
466233d2500723e5594f3e7c70896ffeeef32b9c950ywan#undef E_MASTER
467233d2500723e5594f3e7c70896ffeeef32b9c950ywan#undef E_SINGLE_MASTER_O
468233d2500723e5594f3e7c70896ffeeef32b9c950ywan#undef E_SINGLE_MASTER
469233d2500723e5594f3e7c70896ffeeef32b9c950ywan#undef E_SUSPEND
470233d2500723e5594f3e7c70896ffeeef32b9c950ywan#undef E_LAST
471233d2500723e5594f3e7c70896ffeeef32b9c950ywan
472233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct pool_ctx *
473233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_pool_init(void)
474233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
475233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct pool_ctx * pool;
476233d2500723e5594f3e7c70896ffeeef32b9c950ywan
477233d2500723e5594f3e7c70896ffeeef32b9c950ywan  pool = h_malloc(sizeof(*pool));
478233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!pool)
479233d2500723e5594f3e7c70896ffeeef32b9c950ywan    abort();
480233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return pool;
481233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
482233d2500723e5594f3e7c70896ffeeef32b9c950ywan
483233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void
484233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_pool_destroy(struct pool_ctx * pool)
485233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
486233d2500723e5594f3e7c70896ffeeef32b9c950ywan  h_free(pool);
487233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
488233d2500723e5594f3e7c70896ffeeef32b9c950ywan
489233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void *
490233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_pool_alloc(size_t size, struct pool_ctx * pool)
491233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
492233d2500723e5594f3e7c70896ffeeef32b9c950ywan  void * p;
493233d2500723e5594f3e7c70896ffeeef32b9c950ywan
494233d2500723e5594f3e7c70896ffeeef32b9c950ywan  p = h_malloc(size);
495233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!p)
496233d2500723e5594f3e7c70896ffeeef32b9c950ywan    abort();
497233d2500723e5594f3e7c70896ffeeef32b9c950ywan  hattach(p, pool);
498233d2500723e5594f3e7c70896ffeeef32b9c950ywan  memset(p, 0, size);
499233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return p;
500233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
501233d2500723e5594f3e7c70896ffeeef32b9c950ywan
502233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void *
503233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_alloc(size_t size)
504233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
505233d2500723e5594f3e7c70896ffeeef32b9c950ywan  void * p;
506233d2500723e5594f3e7c70896ffeeef32b9c950ywan
507233d2500723e5594f3e7c70896ffeeef32b9c950ywan  p = calloc(1, size);
508233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!p)
509233d2500723e5594f3e7c70896ffeeef32b9c950ywan    abort();
510233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return p;
511233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
512233d2500723e5594f3e7c70896ffeeef32b9c950ywan
513233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
514233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_io_read(nestegg_io * io, void * buffer, size_t length)
515233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
516233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return io->read(buffer, length, io->userdata);
517233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
518233d2500723e5594f3e7c70896ffeeef32b9c950ywan
519233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
520233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_io_seek(nestegg_io * io, int64_t offset, int whence)
521233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
522233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return io->seek(offset, whence, io->userdata);
523233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
524233d2500723e5594f3e7c70896ffeeef32b9c950ywan
525233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
526233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_io_read_skip(nestegg_io * io, size_t length)
527233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
528233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size_t get;
529233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned char buf[8192];
530233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r = 1;
531233d2500723e5594f3e7c70896ffeeef32b9c950ywan
532233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (length > 0) {
533233d2500723e5594f3e7c70896ffeeef32b9c950ywan    get = length < sizeof(buf) ? length : sizeof(buf);
534233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_io_read(io, buf, get);
535233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 1)
536233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
537233d2500723e5594f3e7c70896ffeeef32b9c950ywan    length -= get;
538233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
539233d2500723e5594f3e7c70896ffeeef32b9c950ywan
540233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return r;
541233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
542233d2500723e5594f3e7c70896ffeeef32b9c950ywan
543233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int64_t
544233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_io_tell(nestegg_io * io)
545233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
546233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return io->tell(io->userdata);
547233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
548233d2500723e5594f3e7c70896ffeeef32b9c950ywan
549233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
550233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_bare_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length, enum vint_mask maskflag)
551233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
552233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
553233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned char b;
554233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size_t maxlen = 8;
555233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int count = 1, mask = 1 << 7;
556233d2500723e5594f3e7c70896ffeeef32b9c950ywan
557233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_io_read(io, &b, 1);
558233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
559233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return r;
560233d2500723e5594f3e7c70896ffeeef32b9c950ywan
561233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (count < maxlen) {
562233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((b & mask) != 0)
563233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
564233d2500723e5594f3e7c70896ffeeef32b9c950ywan    mask >>= 1;
565233d2500723e5594f3e7c70896ffeeef32b9c950ywan    count += 1;
566233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
567233d2500723e5594f3e7c70896ffeeef32b9c950ywan
568233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (length)
569233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *length = count;
570233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *value = b;
571233d2500723e5594f3e7c70896ffeeef32b9c950ywan
572233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (maskflag == MASK_FIRST_BIT)
573233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *value = b & ~mask;
574233d2500723e5594f3e7c70896ffeeef32b9c950ywan
575233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (--count) {
576233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_io_read(io, &b, 1);
577233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 1)
578233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return r;
579233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *value <<= 8;
580233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *value |= b;
581233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
582233d2500723e5594f3e7c70896ffeeef32b9c950ywan
583233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 1;
584233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
585233d2500723e5594f3e7c70896ffeeef32b9c950ywan
586233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
587233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_id(nestegg_io * io, uint64_t * value, uint64_t * length)
588233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
589233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return ne_bare_read_vint(io, value, length, MASK_NONE);
590233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
591233d2500723e5594f3e7c70896ffeeef32b9c950ywan
592233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
593233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length)
594233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
595233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return ne_bare_read_vint(io, value, length, MASK_FIRST_BIT);
596233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
597233d2500723e5594f3e7c70896ffeeef32b9c950ywan
598233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
599233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_svint(nestegg_io * io, int64_t * value, uint64_t * length)
600233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
601233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
602233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t uvalue;
603233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t ulength;
604233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t svint_subtr[] = {
605233d2500723e5594f3e7c70896ffeeef32b9c950ywan    0x3f, 0x1fff,
606233d2500723e5594f3e7c70896ffeeef32b9c950ywan    0xfffff, 0x7ffffff,
607233d2500723e5594f3e7c70896ffeeef32b9c950ywan    0x3ffffffffLL, 0x1ffffffffffLL,
608233d2500723e5594f3e7c70896ffeeef32b9c950ywan    0xffffffffffffLL, 0x7fffffffffffffLL
609233d2500723e5594f3e7c70896ffeeef32b9c950ywan  };
610233d2500723e5594f3e7c70896ffeeef32b9c950ywan
611233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_bare_read_vint(io, &uvalue, &ulength, MASK_FIRST_BIT);
612233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
613233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return r;
614233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *value = uvalue - svint_subtr[ulength - 1];
615233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (length)
616233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *length = ulength;
617233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return r;
618233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
619233d2500723e5594f3e7c70896ffeeef32b9c950ywan
620233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
621233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_uint(nestegg_io * io, uint64_t * val, uint64_t length)
622233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
623233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned char b;
624233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
625233d2500723e5594f3e7c70896ffeeef32b9c950ywan
626233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (length == 0 || length > 8)
627233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
628233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_io_read(io, &b, 1);
629233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
630233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return r;
631233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *val = b;
632233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (--length) {
633233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_io_read(io, &b, 1);
634233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 1)
635233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return r;
636233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *val <<= 8;
637233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *val |= b;
638233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
639233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 1;
640233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
641233d2500723e5594f3e7c70896ffeeef32b9c950ywan
642233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
643233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_int(nestegg_io * io, int64_t * val, uint64_t length)
644233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
645233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
646233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t uval, base;
647233d2500723e5594f3e7c70896ffeeef32b9c950ywan
648233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_read_uint(io, &uval, length);
649233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
650233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return r;
651233d2500723e5594f3e7c70896ffeeef32b9c950ywan
652233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (length < sizeof(int64_t)) {
653233d2500723e5594f3e7c70896ffeeef32b9c950ywan    base = 1;
654233d2500723e5594f3e7c70896ffeeef32b9c950ywan    base <<= length * 8 - 1;
655233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (uval >= base) {
656233d2500723e5594f3e7c70896ffeeef32b9c950ywan        base = 1;
657233d2500723e5594f3e7c70896ffeeef32b9c950ywan        base <<= length * 8;
658233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else {
659233d2500723e5594f3e7c70896ffeeef32b9c950ywan      base = 0;
660233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
661233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *val = uval - base;
662233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
663233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *val = (int64_t) uval;
664233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
665233d2500723e5594f3e7c70896ffeeef32b9c950ywan
666233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 1;
667233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
668233d2500723e5594f3e7c70896ffeeef32b9c950ywan
669233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
670233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_float(nestegg_io * io, double * val, uint64_t length)
671233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
672233d2500723e5594f3e7c70896ffeeef32b9c950ywan  union {
673233d2500723e5594f3e7c70896ffeeef32b9c950ywan    uint64_t u;
674233d2500723e5594f3e7c70896ffeeef32b9c950ywan    float f;
675233d2500723e5594f3e7c70896ffeeef32b9c950ywan    double d;
676233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } value;
677233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
678233d2500723e5594f3e7c70896ffeeef32b9c950ywan
679233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Length == 10 not implemented. */
680233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (length != 4 && length != 8)
681233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
682233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_read_uint(io, &value.u, length);
683233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
684233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return r;
685233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (length == 4)
686233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *val = value.f;
687233d2500723e5594f3e7c70896ffeeef32b9c950ywan  else
688233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *val = value.d;
689233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 1;
690233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
691233d2500723e5594f3e7c70896ffeeef32b9c950ywan
692233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
693233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_string(nestegg * ctx, char ** val, uint64_t length)
694233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
695233d2500723e5594f3e7c70896ffeeef32b9c950ywan  char * str;
696233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
697233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const size_t alloc_size = (size_t)length + 1;
698233d2500723e5594f3e7c70896ffeeef32b9c950ywan
699233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (length == 0 || length > LIMIT_STRING)
700233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
701233d2500723e5594f3e7c70896ffeeef32b9c950ywan  str = ne_pool_alloc(alloc_size, ctx->alloc_pool);
702233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_io_read(ctx->io, (unsigned char *) str, alloc_size - 1);
703233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
704233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return r;
705233d2500723e5594f3e7c70896ffeeef32b9c950ywan  str[alloc_size - 1] = '\0';
706233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *val = str;
707233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 1;
708233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
709233d2500723e5594f3e7c70896ffeeef32b9c950ywan
710233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
711233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_binary(nestegg * ctx, struct ebml_binary * val, uint64_t length)
712233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
713233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (length == 0 || length > LIMIT_BINARY)
714233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
715233d2500723e5594f3e7c70896ffeeef32b9c950ywan  val->length = (size_t)length;
716233d2500723e5594f3e7c70896ffeeef32b9c950ywan  val->data = ne_pool_alloc(val->length, ctx->alloc_pool);
717233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return ne_io_read(ctx->io, val->data, val->length);
718233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
719233d2500723e5594f3e7c70896ffeeef32b9c950ywan
720233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
721233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_get_uint(struct ebml_type type, uint64_t * value)
722233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
723233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!type.read)
724233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
725233d2500723e5594f3e7c70896ffeeef32b9c950ywan
726233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(type.type == TYPE_UINT);
727233d2500723e5594f3e7c70896ffeeef32b9c950ywan
728233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *value = type.v.u;
729233d2500723e5594f3e7c70896ffeeef32b9c950ywan
730233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
731233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
732233d2500723e5594f3e7c70896ffeeef32b9c950ywan
733233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
734233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_get_uint32(struct ebml_type type, unsigned int * value)
735233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
736233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t v;
737233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ne_get_uint(type, &v))
738233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
739233d2500723e5594f3e7c70896ffeeef32b9c950ywan
740233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert((unsigned int)v == v);
741233d2500723e5594f3e7c70896ffeeef32b9c950ywan
742233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *value = (unsigned int)v;
743233d2500723e5594f3e7c70896ffeeef32b9c950ywan
744233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
745233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
746233d2500723e5594f3e7c70896ffeeef32b9c950ywan
747233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
748233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_get_float(struct ebml_type type, double * value)
749233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
750233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!type.read)
751233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
752233d2500723e5594f3e7c70896ffeeef32b9c950ywan
753233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(type.type == TYPE_FLOAT);
754233d2500723e5594f3e7c70896ffeeef32b9c950ywan
755233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *value = type.v.f;
756233d2500723e5594f3e7c70896ffeeef32b9c950ywan
757233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
758233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
759233d2500723e5594f3e7c70896ffeeef32b9c950ywan
760233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
761233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_get_string(struct ebml_type type, char ** value)
762233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
763233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!type.read)
764233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
765233d2500723e5594f3e7c70896ffeeef32b9c950ywan
766233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(type.type == TYPE_STRING);
767233d2500723e5594f3e7c70896ffeeef32b9c950ywan
768233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *value = type.v.s;
769233d2500723e5594f3e7c70896ffeeef32b9c950ywan
770233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
771233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
772233d2500723e5594f3e7c70896ffeeef32b9c950ywan
773233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
774233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_get_binary(struct ebml_type type, struct ebml_binary * value)
775233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
776233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!type.read)
777233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
778233d2500723e5594f3e7c70896ffeeef32b9c950ywan
779233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(type.type == TYPE_BINARY);
780233d2500723e5594f3e7c70896ffeeef32b9c950ywan
781233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *value = type.v.b;
782233d2500723e5594f3e7c70896ffeeef32b9c950ywan
783233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
784233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
785233d2500723e5594f3e7c70896ffeeef32b9c950ywan
786233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
787233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_is_ancestor_element(uint64_t id, struct list_node * ancestor)
788233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
789233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_element_desc * element;
790233d2500723e5594f3e7c70896ffeeef32b9c950ywan
791233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (; ancestor; ancestor = ancestor->previous)
792233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (element = ancestor->node; element->id; ++element)
793233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (element->id == id)
794233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return 1;
795233d2500723e5594f3e7c70896ffeeef32b9c950ywan
796233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
797233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
798233d2500723e5594f3e7c70896ffeeef32b9c950ywan
799233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct ebml_element_desc *
800233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_find_element(uint64_t id, struct ebml_element_desc * elements)
801233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
802233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_element_desc * element;
803233d2500723e5594f3e7c70896ffeeef32b9c950ywan
804233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (element = elements; element->id; ++element)
805233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (element->id == id)
806233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return element;
807233d2500723e5594f3e7c70896ffeeef32b9c950ywan
808233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return NULL;
809233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
810233d2500723e5594f3e7c70896ffeeef32b9c950ywan
811233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void
812233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_ctx_push(nestegg * ctx, struct ebml_element_desc * ancestor, void * data)
813233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
814233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct list_node * item;
815233d2500723e5594f3e7c70896ffeeef32b9c950ywan
816233d2500723e5594f3e7c70896ffeeef32b9c950ywan  item = ne_alloc(sizeof(*item));
817233d2500723e5594f3e7c70896ffeeef32b9c950ywan  item->previous = ctx->ancestor;
818233d2500723e5594f3e7c70896ffeeef32b9c950ywan  item->node = ancestor;
819233d2500723e5594f3e7c70896ffeeef32b9c950ywan  item->data = data;
820233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->ancestor = item;
821233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
822233d2500723e5594f3e7c70896ffeeef32b9c950ywan
823233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void
824233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_ctx_pop(nestegg * ctx)
825233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
826233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct list_node * item;
827233d2500723e5594f3e7c70896ffeeef32b9c950ywan
828233d2500723e5594f3e7c70896ffeeef32b9c950ywan  item = ctx->ancestor;
829233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->ancestor = item->previous;
830233d2500723e5594f3e7c70896ffeeef32b9c950ywan  free(item);
831233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
832233d2500723e5594f3e7c70896ffeeef32b9c950ywan
833233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
834233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_ctx_save(nestegg * ctx, struct saved_state * s)
835233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
836233d2500723e5594f3e7c70896ffeeef32b9c950ywan  s->stream_offset = ne_io_tell(ctx->io);
837233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (s->stream_offset < 0)
838233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
839233d2500723e5594f3e7c70896ffeeef32b9c950ywan  s->ancestor = ctx->ancestor;
840233d2500723e5594f3e7c70896ffeeef32b9c950ywan  s->last_id = ctx->last_id;
841233d2500723e5594f3e7c70896ffeeef32b9c950ywan  s->last_size = ctx->last_size;
842233d2500723e5594f3e7c70896ffeeef32b9c950ywan  s->last_valid = ctx->last_valid;
843233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
844233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
845233d2500723e5594f3e7c70896ffeeef32b9c950ywan
846233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
847233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_ctx_restore(nestegg * ctx, struct saved_state * s)
848233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
849233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
850233d2500723e5594f3e7c70896ffeeef32b9c950ywan
851233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_io_seek(ctx->io, s->stream_offset, NESTEGG_SEEK_SET);
852233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 0)
853233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
854233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->ancestor = s->ancestor;
855233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->last_id = s->last_id;
856233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->last_size = s->last_size;
857233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->last_valid = s->last_valid;
858233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
859233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
860233d2500723e5594f3e7c70896ffeeef32b9c950ywan
861233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
862233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_peek_element(nestegg * ctx, uint64_t * id, uint64_t * size)
863233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
864233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
865233d2500723e5594f3e7c70896ffeeef32b9c950ywan
866233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ctx->last_valid) {
867233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (id)
868233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *id = ctx->last_id;
869233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (size)
870233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *size = ctx->last_size;
871233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
872233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
873233d2500723e5594f3e7c70896ffeeef32b9c950ywan
874233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_read_id(ctx->io, &ctx->last_id, NULL);
875233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
876233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return r;
877233d2500723e5594f3e7c70896ffeeef32b9c950ywan
878233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_read_vint(ctx->io, &ctx->last_size, NULL);
879233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
880233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return r;
881233d2500723e5594f3e7c70896ffeeef32b9c950ywan
882233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (id)
883233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *id = ctx->last_id;
884233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (size)
885233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *size = ctx->last_size;
886233d2500723e5594f3e7c70896ffeeef32b9c950ywan
887233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->last_valid = 1;
888233d2500723e5594f3e7c70896ffeeef32b9c950ywan
889233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 1;
890233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
891233d2500723e5594f3e7c70896ffeeef32b9c950ywan
892233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
893233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_element(nestegg * ctx, uint64_t * id, uint64_t * size)
894233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
895233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
896233d2500723e5594f3e7c70896ffeeef32b9c950ywan
897233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_peek_element(ctx, id, size);
898233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
899233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return r;
900233d2500723e5594f3e7c70896ffeeef32b9c950ywan
901233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->last_valid = 0;
902233d2500723e5594f3e7c70896ffeeef32b9c950ywan
903233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 1;
904233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
905233d2500723e5594f3e7c70896ffeeef32b9c950ywan
906233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void
907233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_master(nestegg * ctx, struct ebml_element_desc * desc)
908233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
909233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list * list;
910233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list_node * node, * oldtail;
911233d2500723e5594f3e7c70896ffeeef32b9c950ywan
912233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(desc->type == TYPE_MASTER && desc->flags & DESC_FLAG_MULTI);
913233d2500723e5594f3e7c70896ffeeef32b9c950ywan
914233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->log(ctx, NESTEGG_LOG_DEBUG, "multi master element %llx (%s)",
915233d2500723e5594f3e7c70896ffeeef32b9c950ywan           desc->id, desc->name);
916233d2500723e5594f3e7c70896ffeeef32b9c950ywan
917233d2500723e5594f3e7c70896ffeeef32b9c950ywan  list = (struct ebml_list *) (ctx->ancestor->data + desc->offset);
918233d2500723e5594f3e7c70896ffeeef32b9c950ywan
919233d2500723e5594f3e7c70896ffeeef32b9c950ywan  node = ne_pool_alloc(sizeof(*node), ctx->alloc_pool);
920233d2500723e5594f3e7c70896ffeeef32b9c950ywan  node->id = desc->id;
921233d2500723e5594f3e7c70896ffeeef32b9c950ywan  node->data = ne_pool_alloc(desc->size, ctx->alloc_pool);
922233d2500723e5594f3e7c70896ffeeef32b9c950ywan
923233d2500723e5594f3e7c70896ffeeef32b9c950ywan  oldtail = list->tail;
924233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (oldtail)
925233d2500723e5594f3e7c70896ffeeef32b9c950ywan    oldtail->next = node;
926233d2500723e5594f3e7c70896ffeeef32b9c950ywan  list->tail = node;
927233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!list->head)
928233d2500723e5594f3e7c70896ffeeef32b9c950ywan    list->head = node;
929233d2500723e5594f3e7c70896ffeeef32b9c950ywan
930233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->log(ctx, NESTEGG_LOG_DEBUG, " -> using data %p", node->data);
931233d2500723e5594f3e7c70896ffeeef32b9c950ywan
932233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_ctx_push(ctx, desc->children, node->data);
933233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
934233d2500723e5594f3e7c70896ffeeef32b9c950ywan
935233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void
936233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_single_master(nestegg * ctx, struct ebml_element_desc * desc)
937233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
938233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(desc->type == TYPE_MASTER && !(desc->flags & DESC_FLAG_MULTI));
939233d2500723e5594f3e7c70896ffeeef32b9c950ywan
940233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->log(ctx, NESTEGG_LOG_DEBUG, "single master element %llx (%s)",
941233d2500723e5594f3e7c70896ffeeef32b9c950ywan           desc->id, desc->name);
942233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->log(ctx, NESTEGG_LOG_DEBUG, " -> using data %p (%u)",
943233d2500723e5594f3e7c70896ffeeef32b9c950ywan           ctx->ancestor->data + desc->offset, desc->offset);
944233d2500723e5594f3e7c70896ffeeef32b9c950ywan
945233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_ctx_push(ctx, desc->children, ctx->ancestor->data + desc->offset);
946233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
947233d2500723e5594f3e7c70896ffeeef32b9c950ywan
948233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
949233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_simple(nestegg * ctx, struct ebml_element_desc * desc, size_t length)
950233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
951233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type * storage;
952233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r = 0;
953233d2500723e5594f3e7c70896ffeeef32b9c950ywan
954233d2500723e5594f3e7c70896ffeeef32b9c950ywan  storage = (struct ebml_type *) (ctx->ancestor->data + desc->offset);
955233d2500723e5594f3e7c70896ffeeef32b9c950ywan
956233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (storage->read) {
957233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx->log(ctx, NESTEGG_LOG_DEBUG, "element %llx (%s) already read, skipping",
958233d2500723e5594f3e7c70896ffeeef32b9c950ywan             desc->id, desc->name);
959233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
960233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
961233d2500723e5594f3e7c70896ffeeef32b9c950ywan
962233d2500723e5594f3e7c70896ffeeef32b9c950ywan  storage->type = desc->type;
963233d2500723e5594f3e7c70896ffeeef32b9c950ywan
964233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->log(ctx, NESTEGG_LOG_DEBUG, "element %llx (%s) -> %p (%u)",
965233d2500723e5594f3e7c70896ffeeef32b9c950ywan           desc->id, desc->name, storage, desc->offset);
966233d2500723e5594f3e7c70896ffeeef32b9c950ywan
967233d2500723e5594f3e7c70896ffeeef32b9c950ywan  switch (desc->type) {
968233d2500723e5594f3e7c70896ffeeef32b9c950ywan  case TYPE_UINT:
969233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_read_uint(ctx->io, &storage->v.u, length);
970233d2500723e5594f3e7c70896ffeeef32b9c950ywan    break;
971233d2500723e5594f3e7c70896ffeeef32b9c950ywan  case TYPE_FLOAT:
972233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_read_float(ctx->io, &storage->v.f, length);
973233d2500723e5594f3e7c70896ffeeef32b9c950ywan    break;
974233d2500723e5594f3e7c70896ffeeef32b9c950ywan  case TYPE_INT:
975233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_read_int(ctx->io, &storage->v.i, length);
976233d2500723e5594f3e7c70896ffeeef32b9c950ywan    break;
977233d2500723e5594f3e7c70896ffeeef32b9c950ywan  case TYPE_STRING:
978233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_read_string(ctx, &storage->v.s, length);
979233d2500723e5594f3e7c70896ffeeef32b9c950ywan    break;
980233d2500723e5594f3e7c70896ffeeef32b9c950ywan  case TYPE_BINARY:
981233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_read_binary(ctx, &storage->v.b, length);
982233d2500723e5594f3e7c70896ffeeef32b9c950ywan    break;
983233d2500723e5594f3e7c70896ffeeef32b9c950ywan  case TYPE_MASTER:
984233d2500723e5594f3e7c70896ffeeef32b9c950ywan  case TYPE_UNKNOWN:
985233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(0);
986233d2500723e5594f3e7c70896ffeeef32b9c950ywan    break;
987233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
988233d2500723e5594f3e7c70896ffeeef32b9c950ywan
989233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r == 1)
990233d2500723e5594f3e7c70896ffeeef32b9c950ywan    storage->read = 1;
991233d2500723e5594f3e7c70896ffeeef32b9c950ywan
992233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return r;
993233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
994233d2500723e5594f3e7c70896ffeeef32b9c950ywan
995233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
996233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_parse(nestegg * ctx, struct ebml_element_desc * top_level, int64_t max_offset)
997233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
998233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
999233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t * data_offset;
1000233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t id, size, peeked_id;
1001233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_element_desc * element;
1002233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1003233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!ctx->ancestor)
1004233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1005233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1006233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (;;) {
1007233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (max_offset > 0 && ne_io_tell(ctx->io) >= max_offset) {
1008233d2500723e5594f3e7c70896ffeeef32b9c950ywan      /* Reached end of offset allowed for parsing - return gracefully */
1009233d2500723e5594f3e7c70896ffeeef32b9c950ywan      r = 1;
1010233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1011233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1012233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_peek_element(ctx, &id, &size);
1013233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 1)
1014233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1015233d2500723e5594f3e7c70896ffeeef32b9c950ywan    peeked_id = id;
1016233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1017233d2500723e5594f3e7c70896ffeeef32b9c950ywan    element = ne_find_element(id, ctx->ancestor->node);
1018233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (element) {
1019233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (element->flags & DESC_FLAG_SUSPEND) {
1020233d2500723e5594f3e7c70896ffeeef32b9c950ywan        assert(element->type == TYPE_BINARY);
1021233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ctx->log(ctx, NESTEGG_LOG_DEBUG, "suspend parse at %llx", id);
1022233d2500723e5594f3e7c70896ffeeef32b9c950ywan        r = 1;
1023233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
1024233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1025233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1026233d2500723e5594f3e7c70896ffeeef32b9c950ywan      r = ne_read_element(ctx, &id, &size);
1027233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (r != 1)
1028233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
1029233d2500723e5594f3e7c70896ffeeef32b9c950ywan      assert(id == peeked_id);
1030233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1031233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (element->flags & DESC_FLAG_OFFSET) {
1032233d2500723e5594f3e7c70896ffeeef32b9c950ywan        data_offset = (int64_t *) (ctx->ancestor->data + element->data_offset);
1033233d2500723e5594f3e7c70896ffeeef32b9c950ywan        *data_offset = ne_io_tell(ctx->io);
1034233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (*data_offset < 0) {
1035233d2500723e5594f3e7c70896ffeeef32b9c950ywan          r = -1;
1036233d2500723e5594f3e7c70896ffeeef32b9c950ywan          break;
1037233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1038233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1039233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1040233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (element->type == TYPE_MASTER) {
1041233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (element->flags & DESC_FLAG_MULTI)
1042233d2500723e5594f3e7c70896ffeeef32b9c950ywan          ne_read_master(ctx, element);
1043233d2500723e5594f3e7c70896ffeeef32b9c950ywan        else
1044233d2500723e5594f3e7c70896ffeeef32b9c950ywan          ne_read_single_master(ctx, element);
1045233d2500723e5594f3e7c70896ffeeef32b9c950ywan        continue;
1046233d2500723e5594f3e7c70896ffeeef32b9c950ywan      } else {
1047233d2500723e5594f3e7c70896ffeeef32b9c950ywan        r = ne_read_simple(ctx, element, (size_t)size);
1048233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (r < 0)
1049233d2500723e5594f3e7c70896ffeeef32b9c950ywan          break;
1050233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1051233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else if (ne_is_ancestor_element(id, ctx->ancestor->previous)) {
1052233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ctx->log(ctx, NESTEGG_LOG_DEBUG, "parent element %llx", id);
1053233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (top_level && ctx->ancestor->node == top_level) {
1054233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ctx->log(ctx, NESTEGG_LOG_DEBUG, "*** parse about to back up past top_level");
1055233d2500723e5594f3e7c70896ffeeef32b9c950ywan        r = 1;
1056233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
1057233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1058233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ne_ctx_pop(ctx);
1059233d2500723e5594f3e7c70896ffeeef32b9c950ywan    } else {
1060233d2500723e5594f3e7c70896ffeeef32b9c950ywan      r = ne_read_element(ctx, &id, &size);
1061233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (r != 1)
1062233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
1063233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1064233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (id != ID_VOID && id != ID_CRC32)
1065233d2500723e5594f3e7c70896ffeeef32b9c950ywan        ctx->log(ctx, NESTEGG_LOG_DEBUG, "unknown element %llx", id);
1066233d2500723e5594f3e7c70896ffeeef32b9c950ywan      r = ne_io_read_skip(ctx->io, (size_t)size);
1067233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (r != 1)
1068233d2500723e5594f3e7c70896ffeeef32b9c950ywan        break;
1069233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1070233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1071233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1072233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
1073233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (ctx->ancestor)
1074233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ne_ctx_pop(ctx);
1075233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1076233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return r;
1077233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1078233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1079233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic uint64_t
1080233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_xiph_lace_value(unsigned char ** np)
1081233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1082233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t lace;
1083233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t value;
1084233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned char * p = *np;
1085233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1086233d2500723e5594f3e7c70896ffeeef32b9c950ywan  lace = *p++;
1087233d2500723e5594f3e7c70896ffeeef32b9c950ywan  value = lace;
1088233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (lace == 255) {
1089233d2500723e5594f3e7c70896ffeeef32b9c950ywan    lace = *p++;
1090233d2500723e5594f3e7c70896ffeeef32b9c950ywan    value += lace;
1091233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1092233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1093233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *np = p;
1094233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1095233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return value;
1096233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1097233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1098233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
1099233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_xiph_lace_value(nestegg_io * io, uint64_t * value, size_t * consumed)
1100233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1101233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
1102233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t lace;
1103233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1104233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_read_uint(io, &lace, 1);
1105233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
1106233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return r;
1107233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *consumed += 1;
1108233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1109233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *value = lace;
1110233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (lace == 255) {
1111233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_read_uint(io, &lace, 1);
1112233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 1)
1113233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return r;
1114233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *consumed += 1;
1115233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *value += lace;
1116233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1117233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1118233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 1;
1119233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1120233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1121233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
1122233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_xiph_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
1123233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1124233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
1125233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size_t i = 0;
1126233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t sum = 0;
1127233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1128233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (--n) {
1129233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_read_xiph_lace_value(io, &sizes[i], read);
1130233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 1)
1131233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return r;
1132233d2500723e5594f3e7c70896ffeeef32b9c950ywan    sum += sizes[i];
1133233d2500723e5594f3e7c70896ffeeef32b9c950ywan    i += 1;
1134233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1135233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1136233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (*read + sum > block)
1137233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1138233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1139233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Last frame is the remainder of the block. */
1140233d2500723e5594f3e7c70896ffeeef32b9c950ywan  sizes[i] = block - *read - sum;
1141233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 1;
1142233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1143233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1144233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
1145233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_ebml_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
1146233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1147233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
1148233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t lace, sum, length;
1149233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t slace;
1150233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size_t i = 0;
1151233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1152233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_read_vint(io, &lace, &length);
1153233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
1154233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return r;
1155233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(length <= 8);
1156233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *read += (size_t)length;
1157233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1158233d2500723e5594f3e7c70896ffeeef32b9c950ywan  sizes[i] = lace;
1159233d2500723e5594f3e7c70896ffeeef32b9c950ywan  sum = sizes[i];
1160233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1161233d2500723e5594f3e7c70896ffeeef32b9c950ywan  i += 1;
1162233d2500723e5594f3e7c70896ffeeef32b9c950ywan  n -= 1;
1163233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1164233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (--n) {
1165233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_read_svint(io, &slace, &length);
1166233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 1)
1167233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return r;
1168233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(length <= 8);
1169233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *read += (size_t)length;
1170233d2500723e5594f3e7c70896ffeeef32b9c950ywan    sizes[i] = sizes[i - 1] + slace;
1171233d2500723e5594f3e7c70896ffeeef32b9c950ywan    sum += sizes[i];
1172233d2500723e5594f3e7c70896ffeeef32b9c950ywan    i += 1;
1173233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1174233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1175233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (*read + sum > block)
1176233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1177233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1178233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Last frame is the remainder of the block. */
1179233d2500723e5594f3e7c70896ffeeef32b9c950ywan  sizes[i] = block - *read - sum;
1180233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 1;
1181233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1182233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1183233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic uint64_t
1184233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_get_timecode_scale(nestegg * ctx)
1185233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1186233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t scale;
1187233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1188233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ne_get_uint(ctx->segment.info.timecode_scale, &scale) != 0)
1189233d2500723e5594f3e7c70896ffeeef32b9c950ywan    scale = 1000000;
1190233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1191233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return scale;
1192233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1193233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1194233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
1195233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_map_track_number_to_index(nestegg * ctx,
1196233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             unsigned int track_number,
1197233d2500723e5594f3e7c70896ffeeef32b9c950ywan                             unsigned int * track_index)
1198233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1199233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list_node * node;
1200233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct track_entry * t_entry;
1201233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t t_number = 0;
1202233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1203233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!track_index)
1204233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1205233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *track_index = 0;
1206233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1207233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (track_number == 0)
1208233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1209233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1210233d2500723e5594f3e7c70896ffeeef32b9c950ywan  node = ctx->segment.tracks.track_entry.head;
1211233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (node) {
1212233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(node->id == ID_TRACK_ENTRY);
1213233d2500723e5594f3e7c70896ffeeef32b9c950ywan    t_entry = node->data;
1214233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (ne_get_uint(t_entry->number, &t_number) != 0)
1215233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1216233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (t_number == track_number)
1217233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return 0;
1218233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *track_index += 1;
1219233d2500723e5594f3e7c70896ffeeef32b9c950ywan    node = node->next;
1220233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1221233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1222233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return -1;
1223233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1224233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1225233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct track_entry *
1226233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_find_track_entry(nestegg * ctx, unsigned int track)
1227233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1228233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list_node * node;
1229233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int tracks = 0;
1230233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1231233d2500723e5594f3e7c70896ffeeef32b9c950ywan  node = ctx->segment.tracks.track_entry.head;
1232233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (node) {
1233233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(node->id == ID_TRACK_ENTRY);
1234233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (track == tracks)
1235233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return node->data;
1236233d2500723e5594f3e7c70896ffeeef32b9c950ywan    tracks += 1;
1237233d2500723e5594f3e7c70896ffeeef32b9c950ywan    node = node->next;
1238233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1239233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1240233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return NULL;
1241233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1242233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1243233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
1244233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_block(nestegg * ctx, uint64_t block_id, uint64_t block_size, nestegg_packet ** data)
1245233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1246233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
1247233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t timecode, abs_timecode;
1248233d2500723e5594f3e7c70896ffeeef32b9c950ywan  nestegg_packet * pkt;
1249233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct cluster * cluster;
1250233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct frame * f, * last;
1251233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct track_entry * entry;
1252233d2500723e5594f3e7c70896ffeeef32b9c950ywan  const int track_scale = 1;
1253233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t track_number, length, frame_sizes[256], cluster_tc, flags, frames, tc_scale, total;
1254233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int i, lacing, track;
1255233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size_t consumed = 0;
1256233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1257233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *data = NULL;
1258233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1259233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (block_size > LIMIT_BLOCK)
1260233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1261233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1262233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_read_vint(ctx->io, &track_number, &length);
1263233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
1264233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return r;
1265233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1266233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (track_number == 0 || (unsigned int)track_number != track_number)
1267233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1268233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1269233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(length <= 8);
1270233d2500723e5594f3e7c70896ffeeef32b9c950ywan  consumed += (size_t)length;
1271233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1272233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_read_int(ctx->io, &timecode, 2);
1273233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
1274233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return r;
1275233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1276233d2500723e5594f3e7c70896ffeeef32b9c950ywan  consumed += 2;
1277233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1278233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_read_uint(ctx->io, &flags, 1);
1279233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
1280233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return r;
1281233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1282233d2500723e5594f3e7c70896ffeeef32b9c950ywan  consumed += 1;
1283233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1284233d2500723e5594f3e7c70896ffeeef32b9c950ywan  frames = 0;
1285233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1286233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Flags are different between Block and SimpleBlock, but lacing is
1287233d2500723e5594f3e7c70896ffeeef32b9c950ywan     encoded the same way. */
1288233d2500723e5594f3e7c70896ffeeef32b9c950ywan  lacing = (flags & BLOCK_FLAGS_LACING) >> 1;
1289233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1290233d2500723e5594f3e7c70896ffeeef32b9c950ywan  switch (lacing) {
1291233d2500723e5594f3e7c70896ffeeef32b9c950ywan  case LACING_NONE:
1292233d2500723e5594f3e7c70896ffeeef32b9c950ywan    frames = 1;
1293233d2500723e5594f3e7c70896ffeeef32b9c950ywan    break;
1294233d2500723e5594f3e7c70896ffeeef32b9c950ywan  case LACING_XIPH:
1295233d2500723e5594f3e7c70896ffeeef32b9c950ywan  case LACING_FIXED:
1296233d2500723e5594f3e7c70896ffeeef32b9c950ywan  case LACING_EBML:
1297233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_read_uint(ctx->io, &frames, 1);
1298233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 1)
1299233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return r;
1300233d2500723e5594f3e7c70896ffeeef32b9c950ywan    consumed += 1;
1301233d2500723e5594f3e7c70896ffeeef32b9c950ywan    frames += 1;
1302233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1303233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1304233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (frames > 256)
1305233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1306233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1307233d2500723e5594f3e7c70896ffeeef32b9c950ywan  switch (lacing) {
1308233d2500723e5594f3e7c70896ffeeef32b9c950ywan  case LACING_NONE:
1309233d2500723e5594f3e7c70896ffeeef32b9c950ywan    frame_sizes[0] = block_size - consumed;
1310233d2500723e5594f3e7c70896ffeeef32b9c950ywan    break;
1311233d2500723e5594f3e7c70896ffeeef32b9c950ywan  case LACING_XIPH:
1312233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (frames == 1)
1313233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1314233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_read_xiph_lacing(ctx->io, (size_t)block_size, &consumed, frames, frame_sizes);
1315233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 1)
1316233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return r;
1317233d2500723e5594f3e7c70896ffeeef32b9c950ywan    break;
1318233d2500723e5594f3e7c70896ffeeef32b9c950ywan  case LACING_FIXED:
1319233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if ((block_size - consumed) % frames)
1320233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1321233d2500723e5594f3e7c70896ffeeef32b9c950ywan    for (i = 0; i < frames; ++i)
1322233d2500723e5594f3e7c70896ffeeef32b9c950ywan      frame_sizes[i] = (block_size - consumed) / frames;
1323233d2500723e5594f3e7c70896ffeeef32b9c950ywan    break;
1324233d2500723e5594f3e7c70896ffeeef32b9c950ywan  case LACING_EBML:
1325233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (frames == 1)
1326233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1327233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_read_ebml_lacing(ctx->io, (size_t)block_size, &consumed, frames, frame_sizes);
1328233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 1)
1329233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return r;
1330233d2500723e5594f3e7c70896ffeeef32b9c950ywan    break;
1331233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1332233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1333233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Sanity check unlaced frame sizes against total block size. */
1334233d2500723e5594f3e7c70896ffeeef32b9c950ywan  total = consumed;
1335233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0; i < frames; ++i)
1336233d2500723e5594f3e7c70896ffeeef32b9c950ywan    total += frame_sizes[i];
1337233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (total > block_size)
1338233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1339233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1340233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ne_map_track_number_to_index(ctx, (unsigned int)track_number, &track) != 0)
1341233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1342233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1343233d2500723e5594f3e7c70896ffeeef32b9c950ywan  entry = ne_find_track_entry(ctx, track);
1344233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!entry)
1345233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1346233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1347233d2500723e5594f3e7c70896ffeeef32b9c950ywan  tc_scale = ne_get_timecode_scale(ctx);
1348233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1349233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert(ctx->segment.cluster.tail->id == ID_CLUSTER);
1350233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cluster = ctx->segment.cluster.tail->data;
1351233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ne_get_uint(cluster->timecode, &cluster_tc) != 0)
1352233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1353233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1354233d2500723e5594f3e7c70896ffeeef32b9c950ywan  abs_timecode = timecode + cluster_tc;
1355233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (abs_timecode < 0)
1356233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1357233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1358233d2500723e5594f3e7c70896ffeeef32b9c950ywan  pkt = ne_alloc(sizeof(*pkt));
1359233d2500723e5594f3e7c70896ffeeef32b9c950ywan  pkt->track = track;
1360233d2500723e5594f3e7c70896ffeeef32b9c950ywan  pkt->timecode = abs_timecode * tc_scale * track_scale;
1361233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1362233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->log(ctx, NESTEGG_LOG_DEBUG, "%sblock t %lld pts %f f %llx frames: %llu",
1363233d2500723e5594f3e7c70896ffeeef32b9c950ywan           block_id == ID_BLOCK ? "" : "simple", pkt->track, pkt->timecode / 1e9, flags, frames);
1364233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1365233d2500723e5594f3e7c70896ffeeef32b9c950ywan  last = NULL;
1366233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (i = 0; i < frames; ++i) {
1367233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (frame_sizes[i] > LIMIT_FRAME) {
1368233d2500723e5594f3e7c70896ffeeef32b9c950ywan      nestegg_free_packet(pkt);
1369233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1370233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1371233d2500723e5594f3e7c70896ffeeef32b9c950ywan    f = ne_alloc(sizeof(*f));
1372233d2500723e5594f3e7c70896ffeeef32b9c950ywan    f->length = (size_t)frame_sizes[i];
1373233d2500723e5594f3e7c70896ffeeef32b9c950ywan    f->data = ne_alloc(f->length);
1374233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_io_read(ctx->io, f->data, f->length);
1375233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 1) {
1376233d2500723e5594f3e7c70896ffeeef32b9c950ywan      free(f->data);
1377233d2500723e5594f3e7c70896ffeeef32b9c950ywan      free(f);
1378233d2500723e5594f3e7c70896ffeeef32b9c950ywan      nestegg_free_packet(pkt);
1379233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1380233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1381233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1382233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!last)
1383233d2500723e5594f3e7c70896ffeeef32b9c950ywan      pkt->frame = f;
1384233d2500723e5594f3e7c70896ffeeef32b9c950ywan    else
1385233d2500723e5594f3e7c70896ffeeef32b9c950ywan      last->next = f;
1386233d2500723e5594f3e7c70896ffeeef32b9c950ywan    last = f;
1387233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1388233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1389233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *data = pkt;
1390233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1391233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 1;
1392233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1393233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1394233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
1395233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_read_discard_padding(nestegg * ctx, nestegg_packet * pkt)
1396233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1397233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
1398233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t id, size;
1399233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_element_desc * element;
1400233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_type * storage;
1401233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1402233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_peek_element(ctx, &id, &size);
1403233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
1404233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return r;
1405233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1406233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (id != ID_DISCARD_PADDING)
1407233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
1408233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1409233d2500723e5594f3e7c70896ffeeef32b9c950ywan  element = ne_find_element(id, ctx->ancestor->node);
1410233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!element)
1411233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
1412233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1413233d2500723e5594f3e7c70896ffeeef32b9c950ywan  assert((size_t)size == size);
1414233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_read_simple(ctx, element, (size_t)size);
1415233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
1416233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return r;
1417233d2500723e5594f3e7c70896ffeeef32b9c950ywan  storage = (struct ebml_type *) (ctx->ancestor->data + element->offset);
1418233d2500723e5594f3e7c70896ffeeef32b9c950ywan  pkt->discard_padding = storage->v.i;
1419233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1420233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 1;
1421233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1422233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1423233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1424233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic uint64_t
1425233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_buf_read_id(unsigned char const * p, size_t length)
1426233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1427233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t id = 0;
1428233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1429233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (length--) {
1430233d2500723e5594f3e7c70896ffeeef32b9c950ywan    id <<= 8;
1431233d2500723e5594f3e7c70896ffeeef32b9c950ywan    id |= *p++;
1432233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1433233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1434233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return id;
1435233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1436233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1437233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct seek *
1438233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_find_seek_for_id(struct ebml_list_node * seek_head, uint64_t id)
1439233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1440233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list * head;
1441233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list_node * seek;
1442233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_binary binary_id;
1443233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct seek * s;
1444233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1445233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (seek_head) {
1446233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(seek_head->id == ID_SEEK_HEAD);
1447233d2500723e5594f3e7c70896ffeeef32b9c950ywan    head = seek_head->data;
1448233d2500723e5594f3e7c70896ffeeef32b9c950ywan    seek = head->head;
1449233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1450233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (seek) {
1451233d2500723e5594f3e7c70896ffeeef32b9c950ywan      assert(seek->id == ID_SEEK);
1452233d2500723e5594f3e7c70896ffeeef32b9c950ywan      s = seek->data;
1453233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1454233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (ne_get_binary(s->id, &binary_id) == 0 &&
1455233d2500723e5594f3e7c70896ffeeef32b9c950ywan          ne_buf_read_id(binary_id.data, binary_id.length) == id)
1456233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return s;
1457233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1458233d2500723e5594f3e7c70896ffeeef32b9c950ywan      seek = seek->next;
1459233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1460233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1461233d2500723e5594f3e7c70896ffeeef32b9c950ywan    seek_head = seek_head->next;
1462233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1463233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1464233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return NULL;
1465233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1466233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1467233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct cue_track_positions *
1468233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_find_cue_position_for_track(nestegg * ctx, struct ebml_list_node * node, unsigned int track)
1469233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1470233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct cue_track_positions * pos = NULL;
1471233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int track_number;
1472233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int t;
1473233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1474233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (node) {
1475233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(node->id == ID_CUE_TRACK_POSITIONS);
1476233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pos = node->data;
1477233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (ne_get_uint32(pos->track, &track_number) != 0)
1478233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return NULL;
1479233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1480233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (ne_map_track_number_to_index(ctx, track_number, &t) != 0)
1481233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return NULL;
1482233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1483233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (t == track)
1484233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return pos;
1485233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1486233d2500723e5594f3e7c70896ffeeef32b9c950ywan    node = node->next;
1487233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1488233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1489233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return NULL;
1490233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1491233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1492233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic struct cue_point *
1493233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_find_cue_point_for_tstamp(nestegg * ctx, struct ebml_list_node * cue_point, unsigned int track, uint64_t scale, uint64_t tstamp)
1494233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1495233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t time;
1496233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct cue_point * c, * prev = NULL;
1497233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1498233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (cue_point) {
1499233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(cue_point->id == ID_CUE_POINT);
1500233d2500723e5594f3e7c70896ffeeef32b9c950ywan    c = cue_point->data;
1501233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1502233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!prev)
1503233d2500723e5594f3e7c70896ffeeef32b9c950ywan      prev = c;
1504233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1505233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (ne_get_uint(c->time, &time) == 0 && time * scale > tstamp)
1506233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1507233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1508233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (ne_find_cue_position_for_track(ctx, c->cue_track_positions.head, track) != NULL)
1509233d2500723e5594f3e7c70896ffeeef32b9c950ywan      prev = c;
1510233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1511233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cue_point = cue_point->next;
1512233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1513233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1514233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return prev;
1515233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1516233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1517233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
1518233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_is_suspend_element(uint64_t id)
1519233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1520233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (id == ID_SIMPLE_BLOCK || id == ID_BLOCK)
1521233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 1;
1522233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
1523233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1524233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1525233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic void
1526233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_null_log_callback(nestegg * ctx, unsigned int severity, char const * fmt, ...)
1527233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1528233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ctx && severity && fmt)
1529233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return;
1530233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1531233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1532233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
1533233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_init_cue_points(nestegg * ctx, int64_t max_offset)
1534233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1535233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
1536233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list_node * node = ctx->segment.cues.cue_point.head;
1537233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct seek * found;
1538233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t seek_pos, id;
1539233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct saved_state state;
1540233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1541233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* If there are no cues loaded, check for cues element in the seek head
1542233d2500723e5594f3e7c70896ffeeef32b9c950ywan     and load it. */
1543233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!node) {
1544233d2500723e5594f3e7c70896ffeeef32b9c950ywan    found = ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES);
1545233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!found)
1546233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1547233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1548233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (ne_get_uint(found->position, &seek_pos) != 0)
1549233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1550233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1551233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Save old parser state. */
1552233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_ctx_save(ctx, &state);
1553233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 0)
1554233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1555233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1556233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Seek and set up parser state for segment-level element (Cues). */
1557233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_io_seek(ctx->io, ctx->segment_offset + seek_pos, NESTEGG_SEEK_SET);
1558233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 0)
1559233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1560233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx->last_valid = 0;
1561233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1562233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_read_element(ctx, &id, NULL);
1563233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 1)
1564233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1565233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1566233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (id != ID_CUES)
1567233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1568233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1569233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx->ancestor = NULL;
1570233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ne_ctx_push(ctx, ne_top_level_elements, ctx);
1571233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ne_ctx_push(ctx, ne_segment_elements, &ctx->segment);
1572233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ne_ctx_push(ctx, ne_cues_elements, &ctx->segment.cues);
1573233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* parser will run until end of cues element. */
1574233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx->log(ctx, NESTEGG_LOG_DEBUG, "seek: parsing cue elements");
1575233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_parse(ctx, ne_cues_elements, max_offset);
1576233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (ctx->ancestor)
1577233d2500723e5594f3e7c70896ffeeef32b9c950ywan      ne_ctx_pop(ctx);
1578233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1579233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Reset parser state to original state and seek back to old position. */
1580233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (ne_ctx_restore(ctx, &state) != 0)
1581233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1582233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1583233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r < 0)
1584233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1585233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1586233d2500723e5594f3e7c70896ffeeef32b9c950ywan    node = ctx->segment.cues.cue_point.head;
1587233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!node)
1588233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1589233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1590233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1591233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
1592233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1593233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1594233d2500723e5594f3e7c70896ffeeef32b9c950ywan/* Three functions that implement the nestegg_io interface, operating on a
1595233d2500723e5594f3e7c70896ffeeef32b9c950ywan * sniff_buffer. */
1596233d2500723e5594f3e7c70896ffeeef32b9c950ywanstruct sniff_buffer {
1597233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned char const * buffer;
1598233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size_t length;
1599233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t offset;
1600233d2500723e5594f3e7c70896ffeeef32b9c950ywan};
1601233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1602233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
1603233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_buffer_read(void * buffer, size_t length, void * user_data)
1604233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1605233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct sniff_buffer * sb = user_data;
1606233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1607233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int rv = 1;
1608233d2500723e5594f3e7c70896ffeeef32b9c950ywan  size_t available = sb->length - (size_t)sb->offset;
1609233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1610233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (available < length)
1611233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
1612233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1613233d2500723e5594f3e7c70896ffeeef32b9c950ywan  memcpy(buffer, sb->buffer + sb->offset, length);
1614233d2500723e5594f3e7c70896ffeeef32b9c950ywan  sb->offset += length;
1615233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1616233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return rv;
1617233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1618233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1619233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
1620233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_buffer_seek(int64_t offset, int whence, void * user_data)
1621233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1622233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct sniff_buffer * sb = user_data;
1623233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int64_t o = sb->offset;
1624233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1625233d2500723e5594f3e7c70896ffeeef32b9c950ywan  switch(whence) {
1626233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case NESTEGG_SEEK_SET:
1627233d2500723e5594f3e7c70896ffeeef32b9c950ywan      o = offset;
1628233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1629233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case NESTEGG_SEEK_CUR:
1630233d2500723e5594f3e7c70896ffeeef32b9c950ywan      o += offset;
1631233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1632233d2500723e5594f3e7c70896ffeeef32b9c950ywan    case NESTEGG_SEEK_END:
1633233d2500723e5594f3e7c70896ffeeef32b9c950ywan      o = sb->length + offset;
1634233d2500723e5594f3e7c70896ffeeef32b9c950ywan      break;
1635233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1636233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1637233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (o < 0 || o > (int64_t) sb->length)
1638233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1639233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1640233d2500723e5594f3e7c70896ffeeef32b9c950ywan  sb->offset = o;
1641233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
1642233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1643233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1644233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int64_t
1645233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_buffer_tell(void * user_data)
1646233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1647233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct sniff_buffer * sb = user_data;
1648233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return sb->offset;
1649233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1650233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1651233d2500723e5594f3e7c70896ffeeef32b9c950ywanstatic int
1652233d2500723e5594f3e7c70896ffeeef32b9c950ywanne_match_webm(nestegg_io io, int64_t max_offset)
1653233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1654233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
1655233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t id;
1656233d2500723e5594f3e7c70896ffeeef32b9c950ywan  char * doctype;
1657233d2500723e5594f3e7c70896ffeeef32b9c950ywan  nestegg * ctx;
1658233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1659233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!(io.read && io.seek && io.tell))
1660233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1661233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1662233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx = ne_alloc(sizeof(*ctx));
1663233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1664233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->io = ne_alloc(sizeof(*ctx->io));
1665233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *ctx->io = io;
1666233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->alloc_pool = ne_pool_init();
1667233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->log = ne_null_log_callback;
1668233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1669233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_peek_element(ctx, &id, NULL);
1670233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1) {
1671233d2500723e5594f3e7c70896ffeeef32b9c950ywan    nestegg_destroy(ctx);
1672233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
1673233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1674233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1675233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (id != ID_EBML) {
1676233d2500723e5594f3e7c70896ffeeef32b9c950ywan    nestegg_destroy(ctx);
1677233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
1678233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1679233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1680233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_ctx_push(ctx, ne_top_level_elements, ctx);
1681233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1682233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* we don't check the return value of ne_parse, that might fail because
1683233d2500723e5594f3e7c70896ffeeef32b9c950ywan   * max_offset is not on a valid element end point. We only want to check
1684233d2500723e5594f3e7c70896ffeeef32b9c950ywan   * the EBML ID and that the doctype is "webm". */
1685233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_parse(ctx, NULL, max_offset);
1686233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1687233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ne_get_string(ctx->ebml.doctype, &doctype) != 0 ||
1688233d2500723e5594f3e7c70896ffeeef32b9c950ywan      strcmp(doctype, "webm") != 0) {
1689233d2500723e5594f3e7c70896ffeeef32b9c950ywan    nestegg_destroy(ctx);
1690233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return 0;
1691233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1692233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1693233d2500723e5594f3e7c70896ffeeef32b9c950ywan  nestegg_destroy(ctx);
1694233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1695233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 1;
1696233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1697233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1698233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
1699233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_init(nestegg ** context, nestegg_io io, nestegg_log callback, int64_t max_offset)
1700233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1701233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
1702233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t id, version, docversion;
1703233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list_node * track;
1704233d2500723e5594f3e7c70896ffeeef32b9c950ywan  char * doctype;
1705233d2500723e5594f3e7c70896ffeeef32b9c950ywan  nestegg * ctx;
1706233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1707233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!(io.read && io.seek && io.tell))
1708233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1709233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1710233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx = ne_alloc(sizeof(*ctx));
1711233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1712233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->io = ne_alloc(sizeof(*ctx->io));
1713233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *ctx->io = io;
1714233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->log = callback;
1715233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->alloc_pool = ne_pool_init();
1716233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1717233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!ctx->log)
1718233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx->log = ne_null_log_callback;
1719233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1720233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_peek_element(ctx, &id, NULL);
1721233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1) {
1722233d2500723e5594f3e7c70896ffeeef32b9c950ywan    nestegg_destroy(ctx);
1723233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1724233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1725233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1726233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (id != ID_EBML) {
1727233d2500723e5594f3e7c70896ffeeef32b9c950ywan    nestegg_destroy(ctx);
1728233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1729233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1730233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1731233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->log(ctx, NESTEGG_LOG_DEBUG, "ctx %p", ctx);
1732233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1733233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_ctx_push(ctx, ne_top_level_elements, ctx);
1734233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1735233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_parse(ctx, NULL, max_offset);
1736233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1737233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1) {
1738233d2500723e5594f3e7c70896ffeeef32b9c950ywan    nestegg_destroy(ctx);
1739233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1740233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1741233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1742233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ne_get_uint(ctx->ebml.ebml_read_version, &version) != 0)
1743233d2500723e5594f3e7c70896ffeeef32b9c950ywan    version = 1;
1744233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (version != 1) {
1745233d2500723e5594f3e7c70896ffeeef32b9c950ywan    nestegg_destroy(ctx);
1746233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1747233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1748233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1749233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ne_get_string(ctx->ebml.doctype, &doctype) != 0)
1750233d2500723e5594f3e7c70896ffeeef32b9c950ywan    doctype = "matroska";
1751233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (strcmp(doctype, "webm") != 0) {
1752233d2500723e5594f3e7c70896ffeeef32b9c950ywan    nestegg_destroy(ctx);
1753233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1754233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1755233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1756233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ne_get_uint(ctx->ebml.doctype_read_version, &docversion) != 0)
1757233d2500723e5594f3e7c70896ffeeef32b9c950ywan    docversion = 1;
1758233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (docversion < 1 || docversion > 2) {
1759233d2500723e5594f3e7c70896ffeeef32b9c950ywan    nestegg_destroy(ctx);
1760233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1761233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1762233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1763233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!ctx->segment.tracks.track_entry.head) {
1764233d2500723e5594f3e7c70896ffeeef32b9c950ywan    nestegg_destroy(ctx);
1765233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1766233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1767233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1768233d2500723e5594f3e7c70896ffeeef32b9c950ywan  track = ctx->segment.tracks.track_entry.head;
1769233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->track_count = 0;
1770233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1771233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (track) {
1772233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ctx->track_count += 1;
1773233d2500723e5594f3e7c70896ffeeef32b9c950ywan    track = track->next;
1774233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1775233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1776233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *context = ctx;
1777233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1778233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
1779233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1780233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1781233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid
1782233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_destroy(nestegg * ctx)
1783233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1784233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (ctx->ancestor)
1785233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ne_ctx_pop(ctx);
1786233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_pool_destroy(ctx->alloc_pool);
1787233d2500723e5594f3e7c70896ffeeef32b9c950ywan  free(ctx->io);
1788233d2500723e5594f3e7c70896ffeeef32b9c950ywan  free(ctx);
1789233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1790233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1791233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
1792233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_duration(nestegg * ctx, uint64_t * duration)
1793233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1794233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t tc_scale;
1795233d2500723e5594f3e7c70896ffeeef32b9c950ywan  double unscaled_duration;
1796233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1797233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ne_get_float(ctx->segment.info.duration, &unscaled_duration) != 0)
1798233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1799233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1800233d2500723e5594f3e7c70896ffeeef32b9c950ywan  tc_scale = ne_get_timecode_scale(ctx);
1801233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1802233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *duration = (uint64_t) (unscaled_duration * tc_scale);
1803233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
1804233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1805233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1806233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
1807233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_tstamp_scale(nestegg * ctx, uint64_t * scale)
1808233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1809233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *scale = ne_get_timecode_scale(ctx);
1810233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
1811233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1812233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1813233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
1814233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_track_count(nestegg * ctx, unsigned int * tracks)
1815233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1816233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *tracks = ctx->track_count;
1817233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
1818233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1819233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1820233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
1821233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_get_cue_point(nestegg * ctx, unsigned int cluster_num, int64_t max_offset,
1822233d2500723e5594f3e7c70896ffeeef32b9c950ywan                      int64_t * start_pos, int64_t * end_pos, uint64_t * tstamp)
1823233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1824233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int range_obtained = 0;
1825233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int cluster_count = 0;
1826233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct cue_point * cue_point;
1827233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct cue_track_positions * pos;
1828233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t seek_pos, track_number, tc_scale, time;
1829233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list_node * cues_node = ctx->segment.cues.cue_point.head;
1830233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_list_node * cue_pos_node = NULL;
1831233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int track = 0, track_count = 0, track_index;
1832233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1833233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!start_pos || !end_pos || !tstamp)
1834233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1835233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1836233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Initialise return values */
1837233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *start_pos = -1;
1838233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *end_pos = -1;
1839233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *tstamp = 0;
1840233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1841233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cues_node) {
1842233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ne_init_cue_points(ctx, max_offset);
1843233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cues_node = ctx->segment.cues.cue_point.head;
1844233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Verify cues have been added to context. */
1845233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (!cues_node)
1846233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1847233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1848233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1849233d2500723e5594f3e7c70896ffeeef32b9c950ywan  nestegg_track_count(ctx, &track_count);
1850233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1851233d2500723e5594f3e7c70896ffeeef32b9c950ywan  tc_scale = ne_get_timecode_scale(ctx);
1852233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1853233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (cues_node && !range_obtained) {
1854233d2500723e5594f3e7c70896ffeeef32b9c950ywan    assert(cues_node->id == ID_CUE_POINT);
1855233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cue_point = cues_node->data;
1856233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cue_pos_node = cue_point->cue_track_positions.head;
1857233d2500723e5594f3e7c70896ffeeef32b9c950ywan    while (cue_pos_node) {
1858233d2500723e5594f3e7c70896ffeeef32b9c950ywan      assert(cue_pos_node->id == ID_CUE_TRACK_POSITIONS);
1859233d2500723e5594f3e7c70896ffeeef32b9c950ywan      pos = cue_pos_node->data;
1860233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (track = 0; track < track_count; track++) {
1861233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (ne_get_uint(pos->track, &track_number) != 0)
1862233d2500723e5594f3e7c70896ffeeef32b9c950ywan          return -1;
1863233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1864233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (ne_map_track_number_to_index(ctx, (unsigned int)track_number, &track_index) != 0)
1865233d2500723e5594f3e7c70896ffeeef32b9c950ywan          return -1;
1866233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1867233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (track_index == track) {
1868233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (ne_get_uint(pos->cluster_position, &seek_pos) != 0)
1869233d2500723e5594f3e7c70896ffeeef32b9c950ywan            return -1;
1870233d2500723e5594f3e7c70896ffeeef32b9c950ywan          if (cluster_count == cluster_num) {
1871233d2500723e5594f3e7c70896ffeeef32b9c950ywan            *start_pos = ctx->segment_offset+seek_pos;
1872233d2500723e5594f3e7c70896ffeeef32b9c950ywan            if (ne_get_uint(cue_point->time, &time) != 0)
1873233d2500723e5594f3e7c70896ffeeef32b9c950ywan              return -1;
1874233d2500723e5594f3e7c70896ffeeef32b9c950ywan            *tstamp = time * tc_scale;
1875233d2500723e5594f3e7c70896ffeeef32b9c950ywan          } else if (cluster_count == cluster_num+1) {
1876233d2500723e5594f3e7c70896ffeeef32b9c950ywan            *end_pos = (ctx->segment_offset+seek_pos)-1;
1877233d2500723e5594f3e7c70896ffeeef32b9c950ywan            range_obtained = 1;
1878233d2500723e5594f3e7c70896ffeeef32b9c950ywan            break;
1879233d2500723e5594f3e7c70896ffeeef32b9c950ywan          }
1880233d2500723e5594f3e7c70896ffeeef32b9c950ywan          cluster_count++;
1881233d2500723e5594f3e7c70896ffeeef32b9c950ywan        }
1882233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
1883233d2500723e5594f3e7c70896ffeeef32b9c950ywan      cue_pos_node = cue_pos_node->next;
1884233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
1885233d2500723e5594f3e7c70896ffeeef32b9c950ywan    cues_node = cues_node->next;
1886233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1887233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1888233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
1889233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1890233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1891233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
1892233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_offset_seek(nestegg * ctx, uint64_t offset)
1893233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1894233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
1895233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1896233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Seek and set up parser state for segment-level element (Cluster). */
1897233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_io_seek(ctx->io, offset, NESTEGG_SEEK_SET);
1898233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 0)
1899233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1900233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->last_valid = 0;
1901233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1902233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (ctx->ancestor)
1903233d2500723e5594f3e7c70896ffeeef32b9c950ywan    ne_ctx_pop(ctx);
1904233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1905233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_ctx_push(ctx, ne_top_level_elements, ctx);
1906233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_ctx_push(ctx, ne_segment_elements, &ctx->segment);
1907233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1908233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
1909233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1910233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1911233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
1912233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_track_seek(nestegg * ctx, unsigned int track, uint64_t tstamp)
1913233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1914233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
1915233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct cue_point * cue_point;
1916233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct cue_track_positions * pos;
1917233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t seek_pos, tc_scale;
1918233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1919233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* If there are no cues loaded, check for cues element in the seek head
1920233d2500723e5594f3e7c70896ffeeef32b9c950ywan     and load it. */
1921233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!ctx->segment.cues.cue_point.head) {
1922233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_init_cue_points(ctx, -1);
1923233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 0)
1924233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return -1;
1925233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
1926233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1927233d2500723e5594f3e7c70896ffeeef32b9c950ywan  tc_scale = ne_get_timecode_scale(ctx);
1928233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1929233d2500723e5594f3e7c70896ffeeef32b9c950ywan  cue_point = ne_find_cue_point_for_tstamp(ctx, ctx->segment.cues.cue_point.head,
1930233d2500723e5594f3e7c70896ffeeef32b9c950ywan                                           track, tc_scale, tstamp);
1931233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!cue_point)
1932233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1933233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1934233d2500723e5594f3e7c70896ffeeef32b9c950ywan  pos = ne_find_cue_position_for_track(ctx, cue_point->cue_track_positions.head, track);
1935233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (pos == NULL)
1936233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1937233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1938233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ne_get_uint(pos->cluster_position, &seek_pos) != 0)
1939233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1940233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1941233d2500723e5594f3e7c70896ffeeef32b9c950ywan  /* Seek and set up parser state for segment-level element (Cluster). */
1942233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = nestegg_offset_seek(ctx, ctx->segment_offset + seek_pos);
1943233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ctx->log(ctx, NESTEGG_LOG_DEBUG, "seek: parsing cluster elements");
1944233d2500723e5594f3e7c70896ffeeef32b9c950ywan  r = ne_parse(ctx, NULL, -1);
1945233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (r != 1)
1946233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1947233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1948233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!ne_is_suspend_element(ctx->last_id))
1949233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1950233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1951233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
1952233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1953233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1954233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
1955233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_track_type(nestegg * ctx, unsigned int track)
1956233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1957233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct track_entry * entry;
1958233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t type;
1959233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1960233d2500723e5594f3e7c70896ffeeef32b9c950ywan  entry = ne_find_track_entry(ctx, track);
1961233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!entry)
1962233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1963233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1964233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ne_get_uint(entry->type, &type) != 0)
1965233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1966233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1967233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (type & TRACK_TYPE_VIDEO)
1968233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NESTEGG_TRACK_VIDEO;
1969233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1970233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (type & TRACK_TYPE_AUDIO)
1971233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NESTEGG_TRACK_AUDIO;
1972233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1973233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return -1;
1974233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
1975233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1976233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
1977233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_track_codec_id(nestegg * ctx, unsigned int track)
1978233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
1979233d2500723e5594f3e7c70896ffeeef32b9c950ywan  char * codec_id;
1980233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct track_entry * entry;
1981233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1982233d2500723e5594f3e7c70896ffeeef32b9c950ywan  entry = ne_find_track_entry(ctx, track);
1983233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!entry)
1984233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1985233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1986233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ne_get_string(entry->codec_id, &codec_id) != 0)
1987233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
1988233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1989233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (strcmp(codec_id, TRACK_ID_VP8) == 0)
1990233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NESTEGG_CODEC_VP8;
1991233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1992233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (strcmp(codec_id, TRACK_ID_VP9) == 0)
1993233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NESTEGG_CODEC_VP9;
1994233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1995233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (strcmp(codec_id, TRACK_ID_VORBIS) == 0)
1996233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NESTEGG_CODEC_VORBIS;
1997233d2500723e5594f3e7c70896ffeeef32b9c950ywan
1998233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (strcmp(codec_id, TRACK_ID_OPUS) == 0)
1999233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return NESTEGG_CODEC_OPUS;
2000233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2001233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return -1;
2002233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2003233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2004233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
2005233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_track_codec_data_count(nestegg * ctx, unsigned int track,
2006233d2500723e5594f3e7c70896ffeeef32b9c950ywan                               unsigned int * count)
2007233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2008233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct track_entry * entry;
2009233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_binary codec_private;
2010233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned char * p;
2011233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2012233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *count = 0;
2013233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2014233d2500723e5594f3e7c70896ffeeef32b9c950ywan  entry = ne_find_track_entry(ctx, track);
2015233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!entry)
2016233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
2017233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2018233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS)
2019233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
2020233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2021233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ne_get_binary(entry->codec_private, &codec_private) != 0)
2022233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
2023233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2024233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (codec_private.length < 1)
2025233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
2026233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2027233d2500723e5594f3e7c70896ffeeef32b9c950ywan  p = codec_private.data;
2028233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *count = *p + 1;
2029233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2030233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (*count > 3)
2031233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
2032233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2033233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
2034233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2035233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2036233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
2037233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_track_codec_data(nestegg * ctx, unsigned int track, unsigned int item,
2038233d2500723e5594f3e7c70896ffeeef32b9c950ywan                         unsigned char ** data, size_t * length)
2039233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2040233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct track_entry * entry;
2041233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct ebml_binary codec_private;
2042233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t sizes[3], total;
2043233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned char * p;
2044233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int count, i;
2045233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2046233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *data = NULL;
2047233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *length = 0;
2048233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2049233d2500723e5594f3e7c70896ffeeef32b9c950ywan  entry = ne_find_track_entry(ctx, track);
2050233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!entry)
2051233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
2052233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2053233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS
2054233d2500723e5594f3e7c70896ffeeef32b9c950ywan    && nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_OPUS)
2055233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
2056233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2057233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ne_get_binary(entry->codec_private, &codec_private) != 0)
2058233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
2059233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2060233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (nestegg_track_codec_id(ctx, track) == NESTEGG_CODEC_VORBIS) {
2061233d2500723e5594f3e7c70896ffeeef32b9c950ywan      p = codec_private.data;
2062233d2500723e5594f3e7c70896ffeeef32b9c950ywan      count = *p++ + 1;
2063233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2064233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (count > 3)
2065233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return -1;
2066233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2067233d2500723e5594f3e7c70896ffeeef32b9c950ywan      i = 0;
2068233d2500723e5594f3e7c70896ffeeef32b9c950ywan      total = 0;
2069233d2500723e5594f3e7c70896ffeeef32b9c950ywan      while (--count) {
2070233d2500723e5594f3e7c70896ffeeef32b9c950ywan        sizes[i] = ne_xiph_lace_value(&p);
2071233d2500723e5594f3e7c70896ffeeef32b9c950ywan        total += sizes[i];
2072233d2500723e5594f3e7c70896ffeeef32b9c950ywan        i += 1;
2073233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2074233d2500723e5594f3e7c70896ffeeef32b9c950ywan      sizes[i] = codec_private.length - total - (p - codec_private.data);
2075233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2076233d2500723e5594f3e7c70896ffeeef32b9c950ywan      for (i = 0; i < item; ++i) {
2077233d2500723e5594f3e7c70896ffeeef32b9c950ywan        if (sizes[i] > LIMIT_FRAME)
2078233d2500723e5594f3e7c70896ffeeef32b9c950ywan          return -1;
2079233d2500723e5594f3e7c70896ffeeef32b9c950ywan        p += sizes[i];
2080233d2500723e5594f3e7c70896ffeeef32b9c950ywan      }
2081233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *data = p;
2082233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *length = (size_t)sizes[item];
2083233d2500723e5594f3e7c70896ffeeef32b9c950ywan  } else {
2084233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *data = codec_private.data;
2085233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *length = codec_private.length;
2086233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2087233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2088233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
2089233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2090233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2091233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
2092233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_track_video_params(nestegg * ctx, unsigned int track,
2093233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           nestegg_video_params * params)
2094233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2095233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct track_entry * entry;
2096233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int value;
2097233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2098233d2500723e5594f3e7c70896ffeeef32b9c950ywan  memset(params, 0, sizeof(*params));
2099233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2100233d2500723e5594f3e7c70896ffeeef32b9c950ywan  entry = ne_find_track_entry(ctx, track);
2101233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!entry)
2102233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
2103233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2104233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_VIDEO)
2105233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
2106233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2107233d2500723e5594f3e7c70896ffeeef32b9c950ywan  value = 0;
2108233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_get_uint32(entry->video.stereo_mode, &value);
2109233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (value <= NESTEGG_VIDEO_STEREO_TOP_BOTTOM ||
2110233d2500723e5594f3e7c70896ffeeef32b9c950ywan      value == NESTEGG_VIDEO_STEREO_RIGHT_LEFT)
2111233d2500723e5594f3e7c70896ffeeef32b9c950ywan    params->stereo_mode = value;
2112233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2113233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ne_get_uint32(entry->video.pixel_width, &value) != 0)
2114233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
2115233d2500723e5594f3e7c70896ffeeef32b9c950ywan  params->width = value;
2116233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2117233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (ne_get_uint32(entry->video.pixel_height, &value) != 0)
2118233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
2119233d2500723e5594f3e7c70896ffeeef32b9c950ywan  params->height = value;
2120233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2121233d2500723e5594f3e7c70896ffeeef32b9c950ywan  value = 0;
2122233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_get_uint32(entry->video.pixel_crop_bottom, &value);
2123233d2500723e5594f3e7c70896ffeeef32b9c950ywan  params->crop_bottom = value;
2124233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2125233d2500723e5594f3e7c70896ffeeef32b9c950ywan  value = 0;
2126233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_get_uint32(entry->video.pixel_crop_top, &value);
2127233d2500723e5594f3e7c70896ffeeef32b9c950ywan  params->crop_top = value;
2128233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2129233d2500723e5594f3e7c70896ffeeef32b9c950ywan  value = 0;
2130233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_get_uint32(entry->video.pixel_crop_left, &value);
2131233d2500723e5594f3e7c70896ffeeef32b9c950ywan  params->crop_left = value;
2132233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2133233d2500723e5594f3e7c70896ffeeef32b9c950ywan  value = 0;
2134233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_get_uint32(entry->video.pixel_crop_right, &value);
2135233d2500723e5594f3e7c70896ffeeef32b9c950ywan  params->crop_right = value;
2136233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2137233d2500723e5594f3e7c70896ffeeef32b9c950ywan  value = params->width;
2138233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_get_uint32(entry->video.display_width, &value);
2139233d2500723e5594f3e7c70896ffeeef32b9c950ywan  params->display_width = value;
2140233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2141233d2500723e5594f3e7c70896ffeeef32b9c950ywan  value = params->height;
2142233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_get_uint32(entry->video.display_height, &value);
2143233d2500723e5594f3e7c70896ffeeef32b9c950ywan  params->display_height = value;
2144233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2145233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
2146233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2147233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2148233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
2149233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_track_audio_params(nestegg * ctx, unsigned int track,
2150233d2500723e5594f3e7c70896ffeeef32b9c950ywan                           nestegg_audio_params * params)
2151233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2152233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct track_entry * entry;
2153233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int value;
2154233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2155233d2500723e5594f3e7c70896ffeeef32b9c950ywan  memset(params, 0, sizeof(*params));
2156233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2157233d2500723e5594f3e7c70896ffeeef32b9c950ywan  entry = ne_find_track_entry(ctx, track);
2158233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (!entry)
2159233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
2160233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2161233d2500723e5594f3e7c70896ffeeef32b9c950ywan  if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_AUDIO)
2162233d2500723e5594f3e7c70896ffeeef32b9c950ywan    return -1;
2163233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2164233d2500723e5594f3e7c70896ffeeef32b9c950ywan  params->rate = 8000;
2165233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_get_float(entry->audio.sampling_frequency, &params->rate);
2166233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2167233d2500723e5594f3e7c70896ffeeef32b9c950ywan  value = 1;
2168233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_get_uint32(entry->audio.channels, &value);
2169233d2500723e5594f3e7c70896ffeeef32b9c950ywan  params->channels = value;
2170233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2171233d2500723e5594f3e7c70896ffeeef32b9c950ywan  value = 16;
2172233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_get_uint32(entry->audio.bit_depth, &value);
2173233d2500723e5594f3e7c70896ffeeef32b9c950ywan  params->depth = value;
2174233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2175233d2500723e5594f3e7c70896ffeeef32b9c950ywan  value = 0;
2176233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_get_uint32(entry->codec_delay, &value);
2177233d2500723e5594f3e7c70896ffeeef32b9c950ywan  params->codec_delay = value;
2178233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2179233d2500723e5594f3e7c70896ffeeef32b9c950ywan  value = 0;
2180233d2500723e5594f3e7c70896ffeeef32b9c950ywan  ne_get_uint32(entry->seek_preroll, &value);
2181233d2500723e5594f3e7c70896ffeeef32b9c950ywan  params->seek_preroll = value;
2182233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2183233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
2184233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2185233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2186233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
2187233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_read_packet(nestegg * ctx, nestegg_packet ** pkt)
2188233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2189233d2500723e5594f3e7c70896ffeeef32b9c950ywan  int r;
2190233d2500723e5594f3e7c70896ffeeef32b9c950ywan  uint64_t id, size;
2191233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2192233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *pkt = NULL;
2193233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2194233d2500723e5594f3e7c70896ffeeef32b9c950ywan  for (;;) {
2195233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r = ne_peek_element(ctx, &id, &size);
2196233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 1)
2197233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return r;
2198233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2199233d2500723e5594f3e7c70896ffeeef32b9c950ywan    /* Any DESC_FLAG_SUSPEND fields must be handled here. */
2200233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (ne_is_suspend_element(id)) {
2201233d2500723e5594f3e7c70896ffeeef32b9c950ywan      r = ne_read_element(ctx, &id, &size);
2202233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (r != 1)
2203233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return r;
2204233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2205233d2500723e5594f3e7c70896ffeeef32b9c950ywan      /* The only DESC_FLAG_SUSPEND fields are Blocks and SimpleBlocks, which we
2206233d2500723e5594f3e7c70896ffeeef32b9c950ywan         handle directly. */
2207233d2500723e5594f3e7c70896ffeeef32b9c950ywan      r = ne_read_block(ctx, id, size, pkt);
2208233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (r != 1)
2209233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return r;
2210233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2211233d2500723e5594f3e7c70896ffeeef32b9c950ywan      r = ne_read_discard_padding(ctx, *pkt);
2212233d2500723e5594f3e7c70896ffeeef32b9c950ywan      if (r != 1)
2213233d2500723e5594f3e7c70896ffeeef32b9c950ywan        return r;
2214233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2215233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return r;
2216233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2217233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2218233d2500723e5594f3e7c70896ffeeef32b9c950ywan    r =  ne_parse(ctx, NULL, -1);
2219233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (r != 1)
2220233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return r;
2221233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2222233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2223233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 1;
2224233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2225233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2226233d2500723e5594f3e7c70896ffeeef32b9c950ywanvoid
2227233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_free_packet(nestegg_packet * pkt)
2228233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2229233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct frame * frame;
2230233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2231233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (pkt->frame) {
2232233d2500723e5594f3e7c70896ffeeef32b9c950ywan    frame = pkt->frame;
2233233d2500723e5594f3e7c70896ffeeef32b9c950ywan    pkt->frame = frame->next;
2234233d2500723e5594f3e7c70896ffeeef32b9c950ywan    free(frame->data);
2235233d2500723e5594f3e7c70896ffeeef32b9c950ywan    free(frame);
2236233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2237233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2238233d2500723e5594f3e7c70896ffeeef32b9c950ywan free(pkt);
2239233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2240233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2241233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
2242233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_packet_track(nestegg_packet * pkt, unsigned int * track)
2243233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2244233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *track = (unsigned int)pkt->track;
2245233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
2246233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2247233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2248233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
2249233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_packet_tstamp(nestegg_packet * pkt, uint64_t * tstamp)
2250233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2251233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *tstamp = pkt->timecode;
2252233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
2253233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2254233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2255233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
2256233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_packet_discard_padding(nestegg_packet * pkt, int64_t * discard_padding)
2257233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2258233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *discard_padding = pkt->discard_padding;
2259233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
2260233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2261233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2262233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
2263233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_packet_count(nestegg_packet * pkt, unsigned int * count)
2264233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2265233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct frame * f = pkt->frame;
2266233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2267233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *count = 0;
2268233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2269233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (f) {
2270233d2500723e5594f3e7c70896ffeeef32b9c950ywan    *count += 1;
2271233d2500723e5594f3e7c70896ffeeef32b9c950ywan    f = f->next;
2272233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2273233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2274233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return 0;
2275233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2276233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2277233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
2278233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_packet_data(nestegg_packet * pkt, unsigned int item,
2279233d2500723e5594f3e7c70896ffeeef32b9c950ywan                    unsigned char ** data, size_t * length)
2280233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2281233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct frame * f = pkt->frame;
2282233d2500723e5594f3e7c70896ffeeef32b9c950ywan  unsigned int count = 0;
2283233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2284233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *data = NULL;
2285233d2500723e5594f3e7c70896ffeeef32b9c950ywan  *length = 0;
2286233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2287233d2500723e5594f3e7c70896ffeeef32b9c950ywan  while (f) {
2288233d2500723e5594f3e7c70896ffeeef32b9c950ywan    if (count == item) {
2289233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *data = f->data;
2290233d2500723e5594f3e7c70896ffeeef32b9c950ywan      *length = f->length;
2291233d2500723e5594f3e7c70896ffeeef32b9c950ywan      return 0;
2292233d2500723e5594f3e7c70896ffeeef32b9c950ywan    }
2293233d2500723e5594f3e7c70896ffeeef32b9c950ywan    count += 1;
2294233d2500723e5594f3e7c70896ffeeef32b9c950ywan    f = f->next;
2295233d2500723e5594f3e7c70896ffeeef32b9c950ywan  }
2296233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2297233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return -1;
2298233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2299233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2300233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
2301233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_has_cues(nestegg * ctx)
2302233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2303233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return ctx->segment.cues.cue_point.head ||
2304233d2500723e5594f3e7c70896ffeeef32b9c950ywan         ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES);
2305233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2306233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2307233d2500723e5594f3e7c70896ffeeef32b9c950ywanint
2308233d2500723e5594f3e7c70896ffeeef32b9c950ywannestegg_sniff(unsigned char const * buffer, size_t length)
2309233d2500723e5594f3e7c70896ffeeef32b9c950ywan{
2310233d2500723e5594f3e7c70896ffeeef32b9c950ywan  nestegg_io io;
2311233d2500723e5594f3e7c70896ffeeef32b9c950ywan  struct sniff_buffer user_data;
2312233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2313233d2500723e5594f3e7c70896ffeeef32b9c950ywan  user_data.buffer = buffer;
2314233d2500723e5594f3e7c70896ffeeef32b9c950ywan  user_data.length = length;
2315233d2500723e5594f3e7c70896ffeeef32b9c950ywan  user_data.offset = 0;
2316233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2317233d2500723e5594f3e7c70896ffeeef32b9c950ywan  io.read = ne_buffer_read;
2318233d2500723e5594f3e7c70896ffeeef32b9c950ywan  io.seek = ne_buffer_seek;
2319233d2500723e5594f3e7c70896ffeeef32b9c950ywan  io.tell = ne_buffer_tell;
2320233d2500723e5594f3e7c70896ffeeef32b9c950ywan  io.userdata = &user_data;
2321233d2500723e5594f3e7c70896ffeeef32b9c950ywan  return ne_match_webm(io, length);
2322233d2500723e5594f3e7c70896ffeeef32b9c950ywan}
2323233d2500723e5594f3e7c70896ffeeef32b9c950ywan
2324