1538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/*
2538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber * Copyright © 2010 Mozilla Foundation
3538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber *
4538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber * This program is made available under an ISC-style license.  See the
5538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber * accompanying file LICENSE for details.
6538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber */
7538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include <assert.h>
8538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include <stdlib.h>
9538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include <string.h>
10538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
11b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include "third_party/nestegg/halloc/halloc.h"
12b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#include "third_party/nestegg/include/nestegg/nestegg.h"
13538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
14538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* EBML Elements */
15538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_EBML                 0x1a45dfa3
16538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_EBML_VERSION         0x4286
17538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_EBML_READ_VERSION    0x42f7
18538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_EBML_MAX_ID_LENGTH   0x42f2
19538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_EBML_MAX_SIZE_LENGTH 0x42f3
20538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_DOCTYPE              0x4282
21538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_DOCTYPE_VERSION      0x4287
22538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_DOCTYPE_READ_VERSION 0x4285
23538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
24538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Global Elements */
25538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_VOID                 0xec
26538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CRC32                0xbf
27538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
28b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian/* WebM Elements */
29538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_SEGMENT              0x18538067
30538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
31538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Seek Head Elements */
32538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_SEEK_HEAD            0x114d9b74
33538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_SEEK                 0x4dbb
34538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_SEEK_ID              0x53ab
35538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_SEEK_POSITION        0x53ac
36538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
37538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Info Elements */
38538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_INFO                 0x1549a966
39538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_TIMECODE_SCALE       0x2ad7b1
40538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_DURATION             0x4489
41538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
42538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Cluster Elements */
43538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CLUSTER              0x1f43b675
44538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_TIMECODE             0xe7
45538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_BLOCK_GROUP          0xa0
46538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_SIMPLE_BLOCK         0xa3
47538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
48538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* BlockGroup Elements */
49538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_BLOCK                0xa1
50538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_BLOCK_DURATION       0x9b
51538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_REFERENCE_BLOCK      0xfb
52b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#define ID_DISCARD_PADDING      0x75a2
53538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
54538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Tracks Elements */
55538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_TRACKS               0x1654ae6b
56538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_TRACK_ENTRY          0xae
57538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_TRACK_NUMBER         0xd7
58538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_TRACK_UID            0x73c5
59538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_TRACK_TYPE           0x83
60538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_FLAG_ENABLED         0xb9
61538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_FLAG_DEFAULT         0x88
62538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_FLAG_LACING          0x9c
63538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_TRACK_TIMECODE_SCALE 0x23314f
64538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_LANGUAGE             0x22b59c
65538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CODEC_ID             0x86
66538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CODEC_PRIVATE        0x63a2
67b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#define ID_CODEC_DELAY          0x56aa
68b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#define ID_SEEK_PREROLL         0x56bb
69538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
70538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Video Elements */
71538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_VIDEO                0xe0
72b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#define ID_STEREO_MODE          0x53b8
73538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_PIXEL_WIDTH          0xb0
74538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_PIXEL_HEIGHT         0xba
75538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_PIXEL_CROP_BOTTOM    0x54aa
76538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_PIXEL_CROP_TOP       0x54bb
77538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_PIXEL_CROP_LEFT      0x54cc
78538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_PIXEL_CROP_RIGHT     0x54dd
79538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_DISPLAY_WIDTH        0x54b0
80538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_DISPLAY_HEIGHT       0x54ba
81538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
82538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Audio Elements */
83538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_AUDIO                0xe1
84538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_SAMPLING_FREQUENCY   0xb5
85538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CHANNELS             0x9f
86538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_BIT_DEPTH            0x6264
87538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
88538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Cues Elements */
89538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CUES                 0x1c53bb6b
90538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CUE_POINT            0xbb
91538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CUE_TIME             0xb3
92538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CUE_TRACK_POSITIONS  0xb7
93538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CUE_TRACK            0xf7
94538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CUE_CLUSTER_POSITION 0xf1
95538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CUE_BLOCK_NUMBER     0x5378
96538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
97538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* EBML Types */
98538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberenum ebml_type_enum {
99538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  TYPE_UNKNOWN,
100538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  TYPE_MASTER,
101538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  TYPE_UINT,
102538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  TYPE_FLOAT,
103538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  TYPE_INT,
104538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  TYPE_STRING,
105538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  TYPE_BINARY
106538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
107538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
108538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define LIMIT_STRING            (1 << 20)
109538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define LIMIT_BINARY            (1 << 24)
110538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define LIMIT_BLOCK             (1 << 30)
111538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define LIMIT_FRAME             (1 << 28)
112538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
113538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Field Flags */
114538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define DESC_FLAG_NONE          0
115538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define DESC_FLAG_MULTI         (1 << 0)
116538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define DESC_FLAG_SUSPEND       (1 << 1)
117538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define DESC_FLAG_OFFSET        (1 << 2)
118538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
119538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Block Header Flags */
120538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define BLOCK_FLAGS_LACING      6
121538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
122538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Lacing Constants */
123538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define LACING_NONE             0
124538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define LACING_XIPH             1
125538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define LACING_FIXED            2
126538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define LACING_EBML             3
127538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
128538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Track Types */
129538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define TRACK_TYPE_VIDEO        1
130538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define TRACK_TYPE_AUDIO        2
131538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
132538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Track IDs */
133538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define TRACK_ID_VP8            "V_VP8"
134ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang#define TRACK_ID_VP9            "V_VP9"
135538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define TRACK_ID_VORBIS         "A_VORBIS"
136b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian#define TRACK_ID_OPUS           "A_OPUS"
137538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
138538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberenum vint_mask {
139538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  MASK_NONE,
140538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  MASK_FIRST_BIT
141538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
142538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
143538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct ebml_binary {
144538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char * data;
145538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t length;
146538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
147538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
148538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct ebml_list_node {
149538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list_node * next;
150538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t id;
151538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  void * data;
152538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
153538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
154538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct ebml_list {
155538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list_node * head;
156538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list_node * tail;
157538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
158538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
159538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct ebml_type {
160538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  union ebml_value {
161538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    uint64_t u;
162538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    double f;
163538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    int64_t i;
164538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    char * s;
165538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    struct ebml_binary b;
166538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  } v;
167538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  enum ebml_type_enum type;
168538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int read;
169538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
170538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
171538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* EBML Definitions */
172538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct ebml {
173538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type ebml_version;
174538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type ebml_read_version;
175538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type ebml_max_id_length;
176538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type ebml_max_size_length;
177538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type doctype;
178538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type doctype_version;
179538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type doctype_read_version;
180538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
181538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
182538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Matroksa Definitions */
183538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct seek {
184538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type id;
185538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type position;
186538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
187538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
188538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct seek_head {
189538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list seek;
190538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
191538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
192538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct info {
193538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type timecode_scale;
194538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type duration;
195538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
196538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
197538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct block_group {
198538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type duration;
199538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type reference_block;
200b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct ebml_type discard_padding;
201538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
202538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
203538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct cluster {
204538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type timecode;
205538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list block_group;
206538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
207538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
208538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct video {
209b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct ebml_type stereo_mode;
210538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type pixel_width;
211538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type pixel_height;
212538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type pixel_crop_bottom;
213538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type pixel_crop_top;
214538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type pixel_crop_left;
215538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type pixel_crop_right;
216538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type display_width;
217538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type display_height;
218538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
219538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
220538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct audio {
221538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type sampling_frequency;
222538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type channels;
223538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type bit_depth;
224538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
225538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
226538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct track_entry {
227538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type number;
228538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type uid;
229538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type type;
230538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type flag_enabled;
231538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type flag_default;
232538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type flag_lacing;
233538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type track_timecode_scale;
234538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type language;
235538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type codec_id;
236538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type codec_private;
237b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct ebml_type codec_delay;
238b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct ebml_type seek_preroll;
239538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct video video;
240538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct audio audio;
241538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
242538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
243538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct tracks {
244538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list track_entry;
245538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
246538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
247538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct cue_track_positions {
248538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type track;
249538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type cluster_position;
250538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type block_number;
251538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
252538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
253538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct cue_point {
254538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type time;
255538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list cue_track_positions;
256538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
257538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
258538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct cues {
259538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list cue_point;
260538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
261538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
262538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct segment {
263538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list seek_head;
264538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct info info;
265538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list cluster;
266538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct tracks tracks;
267538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct cues cues;
268538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
269538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
270538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Misc. */
271538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct pool_ctx {
272538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  char dummy;
273538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
274538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
275538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct list_node {
276538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct list_node * previous;
277538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_element_desc * node;
278538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char * data;
279538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
280538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
281538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct saved_state {
282538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int64_t stream_offset;
283538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct list_node * ancestor;
284538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t last_id;
285538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t last_size;
286b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  int last_valid;
287538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
288538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
289538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct frame {
290538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char * data;
291538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t length;
292538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct frame * next;
293538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
294538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
295538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Public (opaque) Structures */
296538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct nestegg {
297538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  nestegg_io * io;
298538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  nestegg_log log;
299538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct pool_ctx * alloc_pool;
300538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t last_id;
301538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t last_size;
302b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  int last_valid;
303538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct list_node * ancestor;
304538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml ebml;
305538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct segment segment;
306538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int64_t segment_offset;
307538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned int track_count;
308538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
309538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
310538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct nestegg_packet {
311538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t track;
312538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t timecode;
313538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct frame * frame;
314b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  int64_t discard_padding;
315538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
316538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
317538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Element Descriptor */
318538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct ebml_element_desc {
319538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  char const * name;
320538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t id;
321538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  enum ebml_type_enum type;
322538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t offset;
323538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned int flags;
324538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_element_desc * children;
325538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t size;
326538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t data_offset;
327538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
328538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
329538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define E_FIELD(ID, TYPE, STRUCT, FIELD) \
330538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_NONE, NULL, 0, 0 }
331538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define E_MASTER(ID, TYPE, STRUCT, FIELD) \
332538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_MULTI, ne_ ## FIELD ## _elements, \
333538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      sizeof(struct FIELD), 0 }
334538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define E_SINGLE_MASTER_O(ID, TYPE, STRUCT, FIELD) \
335538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_OFFSET, ne_ ## FIELD ## _elements, 0, \
336538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      offsetof(STRUCT, FIELD ## _offset) }
337538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define E_SINGLE_MASTER(ID, TYPE, STRUCT, FIELD) \
338538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_NONE, ne_ ## FIELD ## _elements, 0, 0 }
339538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define E_SUSPEND(ID, TYPE) \
340538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  { #ID, ID, TYPE, 0, DESC_FLAG_SUSPEND, NULL, 0, 0 }
341538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define E_LAST \
342538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  { NULL, 0, 0, 0, DESC_FLAG_NONE, NULL, 0, 0 }
343538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
344538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* EBML Element Lists */
345538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_ebml_elements[] = {
346538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_EBML_VERSION, TYPE_UINT, struct ebml, ebml_version),
347538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_EBML_READ_VERSION, TYPE_UINT, struct ebml, ebml_read_version),
348538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_EBML_MAX_ID_LENGTH, TYPE_UINT, struct ebml, ebml_max_id_length),
349538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_EBML_MAX_SIZE_LENGTH, TYPE_UINT, struct ebml, ebml_max_size_length),
350538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_DOCTYPE, TYPE_STRING, struct ebml, doctype),
351538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_DOCTYPE_VERSION, TYPE_UINT, struct ebml, doctype_version),
352538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_DOCTYPE_READ_VERSION, TYPE_UINT, struct ebml, doctype_read_version),
353538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
354538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
355538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
356b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian/* WebM Element Lists */
357538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_seek_elements[] = {
358538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_SEEK_ID, TYPE_BINARY, struct seek, id),
359538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_SEEK_POSITION, TYPE_UINT, struct seek, position),
360538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
361538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
362538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
363538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_seek_head_elements[] = {
364538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_MASTER(ID_SEEK, TYPE_MASTER, struct seek_head, seek),
365538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
366538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
367538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
368538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_info_elements[] = {
369538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_TIMECODE_SCALE, TYPE_UINT, struct info, timecode_scale),
370538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_DURATION, TYPE_FLOAT, struct info, duration),
371538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
372538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
373538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
374538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_block_group_elements[] = {
375538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SUSPEND(ID_BLOCK, TYPE_BINARY),
376538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_BLOCK_DURATION, TYPE_UINT, struct block_group, duration),
377538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_REFERENCE_BLOCK, TYPE_INT, struct block_group, reference_block),
378b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  E_FIELD(ID_DISCARD_PADDING, TYPE_INT, struct block_group, discard_padding),
379538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
380538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
381538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
382538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_cluster_elements[] = {
383538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_TIMECODE, TYPE_UINT, struct cluster, timecode),
384538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_MASTER(ID_BLOCK_GROUP, TYPE_MASTER, struct cluster, block_group),
385538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SUSPEND(ID_SIMPLE_BLOCK, TYPE_BINARY),
386538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
387538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
388538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
389538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_video_elements[] = {
390b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  E_FIELD(ID_STEREO_MODE, TYPE_UINT, struct video, stereo_mode),
391538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_PIXEL_WIDTH, TYPE_UINT, struct video, pixel_width),
392538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_PIXEL_HEIGHT, TYPE_UINT, struct video, pixel_height),
393538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_PIXEL_CROP_BOTTOM, TYPE_UINT, struct video, pixel_crop_bottom),
394538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_PIXEL_CROP_TOP, TYPE_UINT, struct video, pixel_crop_top),
395538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_PIXEL_CROP_LEFT, TYPE_UINT, struct video, pixel_crop_left),
396538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_PIXEL_CROP_RIGHT, TYPE_UINT, struct video, pixel_crop_right),
397538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_DISPLAY_WIDTH, TYPE_UINT, struct video, display_width),
398538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_DISPLAY_HEIGHT, TYPE_UINT, struct video, display_height),
399538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
400538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
401538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
402538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_audio_elements[] = {
403538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_SAMPLING_FREQUENCY, TYPE_FLOAT, struct audio, sampling_frequency),
404538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_CHANNELS, TYPE_UINT, struct audio, channels),
405538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_BIT_DEPTH, TYPE_UINT, struct audio, bit_depth),
406538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
407538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
408538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
409538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_track_entry_elements[] = {
410538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_TRACK_NUMBER, TYPE_UINT, struct track_entry, number),
411538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_TRACK_UID, TYPE_UINT, struct track_entry, uid),
412538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_TRACK_TYPE, TYPE_UINT, struct track_entry, type),
413538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_FLAG_ENABLED, TYPE_UINT, struct track_entry, flag_enabled),
414538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_FLAG_DEFAULT, TYPE_UINT, struct track_entry, flag_default),
415538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_FLAG_LACING, TYPE_UINT, struct track_entry, flag_lacing),
416538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_TRACK_TIMECODE_SCALE, TYPE_FLOAT, struct track_entry, track_timecode_scale),
417538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_LANGUAGE, TYPE_STRING, struct track_entry, language),
418538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_CODEC_ID, TYPE_STRING, struct track_entry, codec_id),
419538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_CODEC_PRIVATE, TYPE_BINARY, struct track_entry, codec_private),
420b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  E_FIELD(ID_CODEC_DELAY, TYPE_UINT, struct track_entry, codec_delay),
421b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  E_FIELD(ID_SEEK_PREROLL, TYPE_UINT, struct track_entry, seek_preroll),
422538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SINGLE_MASTER(ID_VIDEO, TYPE_MASTER, struct track_entry, video),
423538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SINGLE_MASTER(ID_AUDIO, TYPE_MASTER, struct track_entry, audio),
424538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
425538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
426538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
427538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_tracks_elements[] = {
428538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_MASTER(ID_TRACK_ENTRY, TYPE_MASTER, struct tracks, track_entry),
429538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
430538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
431538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
432538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_cue_track_positions_elements[] = {
433538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_CUE_TRACK, TYPE_UINT, struct cue_track_positions, track),
434538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_CUE_CLUSTER_POSITION, TYPE_UINT, struct cue_track_positions, cluster_position),
435538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_CUE_BLOCK_NUMBER, TYPE_UINT, struct cue_track_positions, block_number),
436538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
437538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
438538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
439538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_cue_point_elements[] = {
440538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_CUE_TIME, TYPE_UINT, struct cue_point, time),
441538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_MASTER(ID_CUE_TRACK_POSITIONS, TYPE_MASTER, struct cue_point, cue_track_positions),
442538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
443538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
444538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
445538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_cues_elements[] = {
446538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_MASTER(ID_CUE_POINT, TYPE_MASTER, struct cues, cue_point),
447538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
448538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
449538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
450538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_segment_elements[] = {
451538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_MASTER(ID_SEEK_HEAD, TYPE_MASTER, struct segment, seek_head),
452538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SINGLE_MASTER(ID_INFO, TYPE_MASTER, struct segment, info),
453538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_MASTER(ID_CLUSTER, TYPE_MASTER, struct segment, cluster),
454538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SINGLE_MASTER(ID_TRACKS, TYPE_MASTER, struct segment, tracks),
455538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SINGLE_MASTER(ID_CUES, TYPE_MASTER, struct segment, cues),
456538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
457538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
458538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
459538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_top_level_elements[] = {
460538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SINGLE_MASTER(ID_EBML, TYPE_MASTER, nestegg, ebml),
461538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SINGLE_MASTER_O(ID_SEGMENT, TYPE_MASTER, nestegg, segment),
462538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
463538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
464538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
465538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#undef E_FIELD
466538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#undef E_MASTER
467538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#undef E_SINGLE_MASTER_O
468538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#undef E_SINGLE_MASTER
469538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#undef E_SUSPEND
470538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#undef E_LAST
471538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
472538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct pool_ctx *
473538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_pool_init(void)
474538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
475538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct pool_ctx * pool;
476538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
477538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  pool = h_malloc(sizeof(*pool));
478538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!pool)
479538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    abort();
480538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return pool;
481538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
482538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
483538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void
484538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_pool_destroy(struct pool_ctx * pool)
485538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
486538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  h_free(pool);
487538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
488538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
489538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void *
490538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_pool_alloc(size_t size, struct pool_ctx * pool)
491538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
492538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  void * p;
493538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
494538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  p = h_malloc(size);
495538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!p)
496538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    abort();
497538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  hattach(p, pool);
498538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  memset(p, 0, size);
499538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return p;
500538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
501538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
502538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void *
503538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_alloc(size_t size)
504538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
505538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  void * p;
506538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
507538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  p = calloc(1, size);
508538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!p)
509538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    abort();
510538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return p;
511538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
512538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
513538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
514538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_io_read(nestegg_io * io, void * buffer, size_t length)
515538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
516538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return io->read(buffer, length, io->userdata);
517538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
518538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
519538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
520538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_io_seek(nestegg_io * io, int64_t offset, int whence)
521538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
522538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return io->seek(offset, whence, io->userdata);
523538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
524538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
525538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
526538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_io_read_skip(nestegg_io * io, size_t length)
527538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
528538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t get;
529538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char buf[8192];
530538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r = 1;
531538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
532538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (length > 0) {
533538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    get = length < sizeof(buf) ? length : sizeof(buf);
534538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_io_read(io, buf, get);
535538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
536538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      break;
537538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    length -= get;
538538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
539538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
540538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return r;
541538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
542538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
543538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int64_t
544538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_io_tell(nestegg_io * io)
545538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
546538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return io->tell(io->userdata);
547538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
548538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
549538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
550538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_bare_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length, enum vint_mask maskflag)
551538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
552538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
553538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char b;
554538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t maxlen = 8;
555538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned int count = 1, mask = 1 << 7;
556538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
557538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_io_read(io, &b, 1);
558538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
559538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
560538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
561538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (count < maxlen) {
562538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if ((b & mask) != 0)
563538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      break;
564538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    mask >>= 1;
565538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    count += 1;
566538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
567538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
568538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (length)
569538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *length = count;
570538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *value = b;
571538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
572538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (maskflag == MASK_FIRST_BIT)
573538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *value = b & ~mask;
574538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
575538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (--count) {
576538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_io_read(io, &b, 1);
577538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
578538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
579538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *value <<= 8;
580538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *value |= b;
581538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
582538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
583538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
584538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
585538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
586538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
587538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_id(nestegg_io * io, uint64_t * value, uint64_t * length)
588538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
589538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return ne_bare_read_vint(io, value, length, MASK_NONE);
590538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
591538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
592538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
593538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length)
594538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
595538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return ne_bare_read_vint(io, value, length, MASK_FIRST_BIT);
596538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
597538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
598538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
599538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_svint(nestegg_io * io, int64_t * value, uint64_t * length)
600538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
601538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
602538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t uvalue;
603538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t ulength;
604538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int64_t svint_subtr[] = {
605538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    0x3f, 0x1fff,
606538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    0xfffff, 0x7ffffff,
607538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    0x3ffffffffLL, 0x1ffffffffffLL,
608538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    0xffffffffffffLL, 0x7fffffffffffffLL
609538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  };
610538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
611538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_bare_read_vint(io, &uvalue, &ulength, MASK_FIRST_BIT);
612538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
613538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
614538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *value = uvalue - svint_subtr[ulength - 1];
615538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (length)
616538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *length = ulength;
617538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return r;
618538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
619538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
620538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
621538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_uint(nestegg_io * io, uint64_t * val, uint64_t length)
622538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
623538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char b;
624538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
625538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
626538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (length == 0 || length > 8)
627538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
628538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_io_read(io, &b, 1);
629538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
630538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
631538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *val = b;
632538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (--length) {
633538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_io_read(io, &b, 1);
634538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
635538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
636538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *val <<= 8;
637538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *val |= b;
638538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
639538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
640538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
641538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
642538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
643538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_int(nestegg_io * io, int64_t * val, uint64_t length)
644538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
645538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
646538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t uval, base;
647538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
648538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_uint(io, &uval, length);
649538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
650538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
651538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
652538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (length < sizeof(int64_t)) {
653538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    base = 1;
654538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    base <<= length * 8 - 1;
655538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (uval >= base) {
656538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        base = 1;
657538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        base <<= length * 8;
658538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    } else {
659538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      base = 0;
660538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    }
661538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *val = uval - base;
662538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  } else {
663538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *val = (int64_t) uval;
664538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
665538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
666538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
667538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
668538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
669538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
670538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_float(nestegg_io * io, double * val, uint64_t length)
671538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
672538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  union {
673538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    uint64_t u;
674538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    float f;
675538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    double d;
676538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  } value;
677538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
678538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
679b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  /* Length == 10 not implemented. */
680538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (length != 4 && length != 8)
681538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
682538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_uint(io, &value.u, length);
683538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
684538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
685538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (length == 4)
686538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *val = value.f;
687538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  else
688538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *val = value.d;
689538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
690538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
691538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
692538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
693538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_string(nestegg * ctx, char ** val, uint64_t length)
694538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
695538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  char * str;
696538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
697b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  const size_t alloc_size = (size_t)length + 1;
698538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
699538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (length == 0 || length > LIMIT_STRING)
700538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
701b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  str = ne_pool_alloc(alloc_size, ctx->alloc_pool);
702b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  r = ne_io_read(ctx->io, (unsigned char *) str, alloc_size - 1);
703538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
704538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
705b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  str[alloc_size - 1] = '\0';
706538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *val = str;
707538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
708538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
709538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
710538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
711538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_binary(nestegg * ctx, struct ebml_binary * val, uint64_t length)
712538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
713538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (length == 0 || length > LIMIT_BINARY)
714538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
715b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  val->length = (size_t)length;
716b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  val->data = ne_pool_alloc(val->length, ctx->alloc_pool);
717b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return ne_io_read(ctx->io, val->data, val->length);
718538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
719538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
720538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
721538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_get_uint(struct ebml_type type, uint64_t * value)
722538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
723538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!type.read)
724538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
725538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
726538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  assert(type.type == TYPE_UINT);
727538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
728538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *value = type.v.u;
729538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
730538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
731538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
732538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
733538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
734b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianne_get_uint32(struct ebml_type type, unsigned int * value)
735b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
736b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  uint64_t v;
737b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (ne_get_uint(type, &v))
738b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return -1;
739b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
740b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  assert((unsigned int)v == v);
741b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
742b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  *value = (unsigned int)v;
743b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
744b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return 0;
745b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
746b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
747b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic int
748538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_get_float(struct ebml_type type, double * value)
749538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
750538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!type.read)
751538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
752538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
753538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  assert(type.type == TYPE_FLOAT);
754538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
755538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *value = type.v.f;
756538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
757538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
758538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
759538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
760538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
761538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_get_string(struct ebml_type type, char ** value)
762538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
763538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!type.read)
764538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
765538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
766538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  assert(type.type == TYPE_STRING);
767538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
768538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *value = type.v.s;
769538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
770538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
771538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
772538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
773538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
774538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_get_binary(struct ebml_type type, struct ebml_binary * value)
775538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
776538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!type.read)
777538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
778538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
779538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  assert(type.type == TYPE_BINARY);
780538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
781538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *value = type.v.b;
782538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
783538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
784538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
785538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
786538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
787538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_is_ancestor_element(uint64_t id, struct list_node * ancestor)
788538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
789538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_element_desc * element;
790538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
791538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  for (; ancestor; ancestor = ancestor->previous)
792538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    for (element = ancestor->node; element->id; ++element)
793538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (element->id == id)
794538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        return 1;
795538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
796538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
797538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
798538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
799538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc *
800538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_find_element(uint64_t id, struct ebml_element_desc * elements)
801538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
802538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_element_desc * element;
803538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
804538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  for (element = elements; element->id; ++element)
805538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (element->id == id)
806538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return element;
807538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
808538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return NULL;
809538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
810538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
811538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void
812538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_ctx_push(nestegg * ctx, struct ebml_element_desc * ancestor, void * data)
813538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
814538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct list_node * item;
815538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
816538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  item = ne_alloc(sizeof(*item));
817538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  item->previous = ctx->ancestor;
818538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  item->node = ancestor;
819538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  item->data = data;
820538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->ancestor = item;
821538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
822538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
823538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void
824538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_ctx_pop(nestegg * ctx)
825538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
826538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct list_node * item;
827538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
828538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  item = ctx->ancestor;
829538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->ancestor = item->previous;
830538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  free(item);
831538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
832538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
833538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
834538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_ctx_save(nestegg * ctx, struct saved_state * s)
835538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
836538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  s->stream_offset = ne_io_tell(ctx->io);
837538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (s->stream_offset < 0)
838538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
839538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  s->ancestor = ctx->ancestor;
840538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  s->last_id = ctx->last_id;
841538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  s->last_size = ctx->last_size;
842b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  s->last_valid = ctx->last_valid;
843538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
844538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
845538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
846538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
847538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_ctx_restore(nestegg * ctx, struct saved_state * s)
848538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
849538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
850538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
851538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_io_seek(ctx->io, s->stream_offset, NESTEGG_SEEK_SET);
852538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 0)
853538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
854538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->ancestor = s->ancestor;
855538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->last_id = s->last_id;
856538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->last_size = s->last_size;
857b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ctx->last_valid = s->last_valid;
858538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
859538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
860538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
861538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
862538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_peek_element(nestegg * ctx, uint64_t * id, uint64_t * size)
863538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
864538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
865538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
866b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (ctx->last_valid) {
867538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (id)
868538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      *id = ctx->last_id;
869538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (size)
870538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      *size = ctx->last_size;
871538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return 1;
872538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
873538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
874538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_id(ctx->io, &ctx->last_id, NULL);
875538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
876538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
877538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
878538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_vint(ctx->io, &ctx->last_size, NULL);
879538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
880538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
881538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
882538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (id)
883538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *id = ctx->last_id;
884538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (size)
885538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *size = ctx->last_size;
886538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
887b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ctx->last_valid = 1;
888b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
889538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
890538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
891538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
892538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
893538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_element(nestegg * ctx, uint64_t * id, uint64_t * size)
894538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
895538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
896538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
897538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_peek_element(ctx, id, size);
898538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
899538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
900538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
901b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ctx->last_valid = 0;
902538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
903538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
904538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
905538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
906538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void
907538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_master(nestegg * ctx, struct ebml_element_desc * desc)
908538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
909538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list * list;
910538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list_node * node, * oldtail;
911538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
912538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  assert(desc->type == TYPE_MASTER && desc->flags & DESC_FLAG_MULTI);
913538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
914538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log(ctx, NESTEGG_LOG_DEBUG, "multi master element %llx (%s)",
915538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber           desc->id, desc->name);
916538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
917538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  list = (struct ebml_list *) (ctx->ancestor->data + desc->offset);
918538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
919538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  node = ne_pool_alloc(sizeof(*node), ctx->alloc_pool);
920538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  node->id = desc->id;
921538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  node->data = ne_pool_alloc(desc->size, ctx->alloc_pool);
922538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
923538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  oldtail = list->tail;
924538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (oldtail)
925538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    oldtail->next = node;
926538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  list->tail = node;
927538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!list->head)
928538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    list->head = node;
929538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
930538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log(ctx, NESTEGG_LOG_DEBUG, " -> using data %p", node->data);
931538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
932538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_ctx_push(ctx, desc->children, node->data);
933538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
934538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
935538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void
936538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_single_master(nestegg * ctx, struct ebml_element_desc * desc)
937538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
938538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  assert(desc->type == TYPE_MASTER && !(desc->flags & DESC_FLAG_MULTI));
939538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
940538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log(ctx, NESTEGG_LOG_DEBUG, "single master element %llx (%s)",
941538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber           desc->id, desc->name);
942538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log(ctx, NESTEGG_LOG_DEBUG, " -> using data %p (%u)",
943538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber           ctx->ancestor->data + desc->offset, desc->offset);
944538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
945538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_ctx_push(ctx, desc->children, ctx->ancestor->data + desc->offset);
946538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
947538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
948538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
949538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_simple(nestegg * ctx, struct ebml_element_desc * desc, size_t length)
950538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
951538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type * storage;
952b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  int r = 0;
953538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
954538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  storage = (struct ebml_type *) (ctx->ancestor->data + desc->offset);
955538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
956538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (storage->read) {
957538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    ctx->log(ctx, NESTEGG_LOG_DEBUG, "element %llx (%s) already read, skipping",
958538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber             desc->id, desc->name);
959538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return 0;
960538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
961538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
962538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  storage->type = desc->type;
963538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
964538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log(ctx, NESTEGG_LOG_DEBUG, "element %llx (%s) -> %p (%u)",
965538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber           desc->id, desc->name, storage, desc->offset);
966538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
967538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  switch (desc->type) {
968538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case TYPE_UINT:
969538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_uint(ctx->io, &storage->v.u, length);
970538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
971538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case TYPE_FLOAT:
972538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_float(ctx->io, &storage->v.f, length);
973538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
974538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case TYPE_INT:
975538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_int(ctx->io, &storage->v.i, length);
976538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
977538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case TYPE_STRING:
978538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_string(ctx, &storage->v.s, length);
979538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
980538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case TYPE_BINARY:
981538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_binary(ctx, &storage->v.b, length);
982538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
983538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case TYPE_MASTER:
984538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case TYPE_UNKNOWN:
985538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    assert(0);
986538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
987538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
988538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
989538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r == 1)
990538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    storage->read = 1;
991538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
992538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return r;
993538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
994538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
995538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
996b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianne_parse(nestegg * ctx, struct ebml_element_desc * top_level, int64_t max_offset)
997538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
998538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
999538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int64_t * data_offset;
1000b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  uint64_t id, size, peeked_id;
1001538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_element_desc * element;
1002538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1003538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!ctx->ancestor)
1004538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1005538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1006538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  for (;;) {
1007b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (max_offset > 0 && ne_io_tell(ctx->io) >= max_offset) {
1008b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      /* Reached end of offset allowed for parsing - return gracefully */
1009b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      r = 1;
1010b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      break;
1011b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    }
1012538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_peek_element(ctx, &id, &size);
1013538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
1014538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      break;
1015b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    peeked_id = id;
1016538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1017538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    element = ne_find_element(id, ctx->ancestor->node);
1018538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (element) {
1019538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (element->flags & DESC_FLAG_SUSPEND) {
1020538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        assert(element->type == TYPE_BINARY);
1021538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        ctx->log(ctx, NESTEGG_LOG_DEBUG, "suspend parse at %llx", id);
1022538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        r = 1;
1023538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        break;
1024538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      }
1025538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1026538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      r = ne_read_element(ctx, &id, &size);
1027538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (r != 1)
1028538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        break;
1029b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      assert(id == peeked_id);
1030538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1031538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (element->flags & DESC_FLAG_OFFSET) {
1032538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        data_offset = (int64_t *) (ctx->ancestor->data + element->data_offset);
1033538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        *data_offset = ne_io_tell(ctx->io);
1034538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        if (*data_offset < 0) {
1035538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber          r = -1;
1036538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber          break;
1037538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        }
1038538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      }
1039538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1040538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (element->type == TYPE_MASTER) {
1041538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        if (element->flags & DESC_FLAG_MULTI)
1042538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber          ne_read_master(ctx, element);
1043538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        else
1044538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber          ne_read_single_master(ctx, element);
1045538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        continue;
1046538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      } else {
1047b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        r = ne_read_simple(ctx, element, (size_t)size);
1048538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        if (r < 0)
1049538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber          break;
1050538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      }
1051538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    } else if (ne_is_ancestor_element(id, ctx->ancestor->previous)) {
1052538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      ctx->log(ctx, NESTEGG_LOG_DEBUG, "parent element %llx", id);
1053538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (top_level && ctx->ancestor->node == top_level) {
1054538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        ctx->log(ctx, NESTEGG_LOG_DEBUG, "*** parse about to back up past top_level");
1055538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        r = 1;
1056538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        break;
1057538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      }
1058538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      ne_ctx_pop(ctx);
1059538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    } else {
1060538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      r = ne_read_element(ctx, &id, &size);
1061538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (r != 1)
1062538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        break;
1063538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1064538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (id != ID_VOID && id != ID_CRC32)
1065538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        ctx->log(ctx, NESTEGG_LOG_DEBUG, "unknown element %llx", id);
1066b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      r = ne_io_read_skip(ctx->io, (size_t)size);
1067538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (r != 1)
1068538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        break;
1069538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    }
1070538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1071538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1072538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
1073538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    while (ctx->ancestor)
1074538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      ne_ctx_pop(ctx);
1075538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1076538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return r;
1077538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1078538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1079538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic uint64_t
1080538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_xiph_lace_value(unsigned char ** np)
1081538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1082538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t lace;
1083538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t value;
1084538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char * p = *np;
1085538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1086538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  lace = *p++;
1087538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = lace;
1088538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (lace == 255) {
1089538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    lace = *p++;
1090538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    value += lace;
1091538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1092538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1093538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *np = p;
1094538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1095538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return value;
1096538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1097538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1098538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
1099538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_xiph_lace_value(nestegg_io * io, uint64_t * value, size_t * consumed)
1100538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1101538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
1102538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t lace;
1103538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1104538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_uint(io, &lace, 1);
1105538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
1106538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
1107538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *consumed += 1;
1108538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1109538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *value = lace;
1110538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (lace == 255) {
1111538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_uint(io, &lace, 1);
1112538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
1113538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
1114538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *consumed += 1;
1115538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *value += lace;
1116538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1117538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1118538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
1119538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1120538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1121538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
1122538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_xiph_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
1123538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1124538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
1125538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t i = 0;
1126538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t sum = 0;
1127538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1128538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (--n) {
1129538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_xiph_lace_value(io, &sizes[i], read);
1130538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
1131538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
1132538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    sum += sizes[i];
1133538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    i += 1;
1134538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1135538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1136538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (*read + sum > block)
1137538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1138538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1139b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  /* Last frame is the remainder of the block. */
1140538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  sizes[i] = block - *read - sum;
1141538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
1142538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1143538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1144538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
1145538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_ebml_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
1146538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1147538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
1148538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t lace, sum, length;
1149538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int64_t slace;
1150538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t i = 0;
1151538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1152538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_vint(io, &lace, &length);
1153538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
1154538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
1155b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  assert(length <= 8);
1156b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  *read += (size_t)length;
1157538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1158538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  sizes[i] = lace;
1159538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  sum = sizes[i];
1160538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1161538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  i += 1;
1162538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  n -= 1;
1163538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1164538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (--n) {
1165538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_svint(io, &slace, &length);
1166538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
1167538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
1168b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    assert(length <= 8);
1169b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    *read += (size_t)length;
1170538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    sizes[i] = sizes[i - 1] + slace;
1171538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    sum += sizes[i];
1172538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    i += 1;
1173538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1174538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1175538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (*read + sum > block)
1176538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1177538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1178b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  /* Last frame is the remainder of the block. */
1179538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  sizes[i] = block - *read - sum;
1180538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
1181538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1182538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1183538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic uint64_t
1184538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_get_timecode_scale(nestegg * ctx)
1185538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1186538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t scale;
1187538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1188538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_uint(ctx->segment.info.timecode_scale, &scale) != 0)
1189538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    scale = 1000000;
1190538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1191538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return scale;
1192538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1193538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1194b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic int
1195b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianne_map_track_number_to_index(nestegg * ctx,
1196b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                             unsigned int track_number,
1197b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                             unsigned int * track_index)
1198b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
1199b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct ebml_list_node * node;
1200b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct track_entry * t_entry;
1201b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  uint64_t t_number = 0;
1202b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1203b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (!track_index)
1204b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return -1;
1205b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  *track_index = 0;
1206b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1207b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (track_number == 0)
1208b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return -1;
1209b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1210b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  node = ctx->segment.tracks.track_entry.head;
1211b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  while (node) {
1212b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    assert(node->id == ID_TRACK_ENTRY);
1213b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    t_entry = node->data;
1214b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (ne_get_uint(t_entry->number, &t_number) != 0)
1215b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return -1;
1216b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (t_number == track_number)
1217b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return 0;
1218b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    *track_index += 1;
1219b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    node = node->next;
1220b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  }
1221b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1222b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return -1;
1223b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
1224b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1225538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct track_entry *
1226538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_find_track_entry(nestegg * ctx, unsigned int track)
1227538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1228538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list_node * node;
1229538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned int tracks = 0;
1230538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1231538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  node = ctx->segment.tracks.track_entry.head;
1232538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (node) {
1233538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    assert(node->id == ID_TRACK_ENTRY);
1234538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (track == tracks)
1235538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return node->data;
1236538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    tracks += 1;
1237538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    node = node->next;
1238538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1239538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1240538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return NULL;
1241538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1242538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1243538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
1244538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_block(nestegg * ctx, uint64_t block_id, uint64_t block_size, nestegg_packet ** data)
1245538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1246538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
1247538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int64_t timecode, abs_timecode;
1248538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  nestegg_packet * pkt;
1249538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct cluster * cluster;
1250538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct frame * f, * last;
1251538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct track_entry * entry;
1252b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  const int track_scale = 1;
1253b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  uint64_t track_number, length, frame_sizes[256], cluster_tc, flags, frames, tc_scale, total;
1254b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  unsigned int i, lacing, track;
1255538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t consumed = 0;
1256538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1257538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *data = NULL;
1258538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1259538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (block_size > LIMIT_BLOCK)
1260538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1261538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1262b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  r = ne_read_vint(ctx->io, &track_number, &length);
1263538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
1264538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
1265538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1266b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (track_number == 0 || (unsigned int)track_number != track_number)
1267538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1268538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1269b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  assert(length <= 8);
1270b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  consumed += (size_t)length;
1271538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1272538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_int(ctx->io, &timecode, 2);
1273538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
1274538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
1275538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1276538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  consumed += 2;
1277538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1278538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_uint(ctx->io, &flags, 1);
1279538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
1280538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
1281538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1282538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  consumed += 1;
1283538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1284538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  frames = 0;
1285538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1286b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  /* Flags are different between Block and SimpleBlock, but lacing is
1287b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian     encoded the same way. */
1288538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  lacing = (flags & BLOCK_FLAGS_LACING) >> 1;
1289538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1290538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  switch (lacing) {
1291538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case LACING_NONE:
1292538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    frames = 1;
1293538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
1294538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case LACING_XIPH:
1295538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case LACING_FIXED:
1296538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case LACING_EBML:
1297538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_uint(ctx->io, &frames, 1);
1298538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
1299538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
1300538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    consumed += 1;
1301538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    frames += 1;
1302538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1303538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1304538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (frames > 256)
1305538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1306538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1307538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  switch (lacing) {
1308538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case LACING_NONE:
1309538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    frame_sizes[0] = block_size - consumed;
1310538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
1311538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case LACING_XIPH:
1312538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (frames == 1)
1313538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1314b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r = ne_read_xiph_lacing(ctx->io, (size_t)block_size, &consumed, frames, frame_sizes);
1315538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
1316538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
1317538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
1318538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case LACING_FIXED:
1319538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if ((block_size - consumed) % frames)
1320538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1321538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    for (i = 0; i < frames; ++i)
1322538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      frame_sizes[i] = (block_size - consumed) / frames;
1323538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
1324538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case LACING_EBML:
1325538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (frames == 1)
1326538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1327b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r = ne_read_ebml_lacing(ctx->io, (size_t)block_size, &consumed, frames, frame_sizes);
1328538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
1329538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
1330538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
1331538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1332538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1333b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  /* Sanity check unlaced frame sizes against total block size. */
1334538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  total = consumed;
1335538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  for (i = 0; i < frames; ++i)
1336538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    total += frame_sizes[i];
1337538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (total > block_size)
1338538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1339538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1340b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (ne_map_track_number_to_index(ctx, (unsigned int)track_number, &track) != 0)
1341538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1342538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1343b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  entry = ne_find_track_entry(ctx, track);
1344b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (!entry)
1345b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return -1;
1346538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1347538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  tc_scale = ne_get_timecode_scale(ctx);
1348538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1349538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  assert(ctx->segment.cluster.tail->id == ID_CLUSTER);
1350538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  cluster = ctx->segment.cluster.tail->data;
1351538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_uint(cluster->timecode, &cluster_tc) != 0)
1352538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1353538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1354538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  abs_timecode = timecode + cluster_tc;
1355538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (abs_timecode < 0)
1356538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1357538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1358538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  pkt = ne_alloc(sizeof(*pkt));
1359b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  pkt->track = track;
1360b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  pkt->timecode = abs_timecode * tc_scale * track_scale;
1361538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1362538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log(ctx, NESTEGG_LOG_DEBUG, "%sblock t %lld pts %f f %llx frames: %llu",
1363538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber           block_id == ID_BLOCK ? "" : "simple", pkt->track, pkt->timecode / 1e9, flags, frames);
1364538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1365538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  last = NULL;
1366538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  for (i = 0; i < frames; ++i) {
1367538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (frame_sizes[i] > LIMIT_FRAME) {
1368538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      nestegg_free_packet(pkt);
1369538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1370538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    }
1371538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    f = ne_alloc(sizeof(*f));
1372b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    f->length = (size_t)frame_sizes[i];
1373b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    f->data = ne_alloc(f->length);
1374b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r = ne_io_read(ctx->io, f->data, f->length);
1375538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1) {
1376538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      free(f->data);
1377538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      free(f);
1378538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      nestegg_free_packet(pkt);
1379538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1380538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    }
1381538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1382538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (!last)
1383538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      pkt->frame = f;
1384538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    else
1385538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      last->next = f;
1386538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    last = f;
1387538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1388538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1389538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *data = pkt;
1390538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1391538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
1392538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1393538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1394b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic int
1395b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianne_read_discard_padding(nestegg * ctx, nestegg_packet * pkt)
1396b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
1397b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  int r;
1398b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  uint64_t id, size;
1399b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct ebml_element_desc * element;
1400b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct ebml_type * storage;
1401b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1402b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  r = ne_peek_element(ctx, &id, &size);
1403b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (r != 1)
1404b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return r;
1405b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1406b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (id != ID_DISCARD_PADDING)
1407b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return 1;
1408b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1409b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  element = ne_find_element(id, ctx->ancestor->node);
1410b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (!element)
1411b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return 1;
1412b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1413b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  assert((size_t)size == size);
1414b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  r = ne_read_simple(ctx, element, (size_t)size);
1415b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (r != 1)
1416b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return r;
1417b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  storage = (struct ebml_type *) (ctx->ancestor->data + element->offset);
1418b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  pkt->discard_padding = storage->v.i;
1419b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1420b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return 1;
1421b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
1422b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1423b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1424538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic uint64_t
1425538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_buf_read_id(unsigned char const * p, size_t length)
1426538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1427538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t id = 0;
1428538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1429538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (length--) {
1430538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    id <<= 8;
1431538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    id |= *p++;
1432538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1433538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1434538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return id;
1435538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1436538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1437538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct seek *
1438538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_find_seek_for_id(struct ebml_list_node * seek_head, uint64_t id)
1439538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1440538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list * head;
1441538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list_node * seek;
1442538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_binary binary_id;
1443538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct seek * s;
1444538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1445538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (seek_head) {
1446538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    assert(seek_head->id == ID_SEEK_HEAD);
1447538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    head = seek_head->data;
1448538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    seek = head->head;
1449538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1450538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    while (seek) {
1451538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      assert(seek->id == ID_SEEK);
1452538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      s = seek->data;
1453538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1454538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (ne_get_binary(s->id, &binary_id) == 0 &&
1455538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber          ne_buf_read_id(binary_id.data, binary_id.length) == id)
1456538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        return s;
1457538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1458538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      seek = seek->next;
1459538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    }
1460538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1461538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    seek_head = seek_head->next;
1462538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1463538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1464538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return NULL;
1465538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1466538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1467b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic struct cue_track_positions *
1468b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianne_find_cue_position_for_track(nestegg * ctx, struct ebml_list_node * node, unsigned int track)
1469b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
1470b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct cue_track_positions * pos = NULL;
1471b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  unsigned int track_number;
1472b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  unsigned int t;
1473b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1474b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  while (node) {
1475b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    assert(node->id == ID_CUE_TRACK_POSITIONS);
1476b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    pos = node->data;
1477b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (ne_get_uint32(pos->track, &track_number) != 0)
1478b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return NULL;
1479b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1480b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (ne_map_track_number_to_index(ctx, track_number, &t) != 0)
1481b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return NULL;
1482b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1483b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (t == track)
1484b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return pos;
1485b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1486b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    node = node->next;
1487b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  }
1488b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1489b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return NULL;
1490b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
1491b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1492538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct cue_point *
1493b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianne_find_cue_point_for_tstamp(nestegg * ctx, struct ebml_list_node * cue_point, unsigned int track, uint64_t scale, uint64_t tstamp)
1494538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1495538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t time;
1496538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct cue_point * c, * prev = NULL;
1497538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1498538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (cue_point) {
1499538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    assert(cue_point->id == ID_CUE_POINT);
1500538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    c = cue_point->data;
1501538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1502538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (!prev)
1503538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      prev = c;
1504538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1505538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (ne_get_uint(c->time, &time) == 0 && time * scale > tstamp)
1506538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      break;
1507538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1508b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (ne_find_cue_position_for_track(ctx, c->cue_track_positions.head, track) != NULL)
1509b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      prev = c;
1510b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1511538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    cue_point = cue_point->next;
1512538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1513538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1514538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return prev;
1515538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1516538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1517538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
1518538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_is_suspend_element(uint64_t id)
1519538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1520538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (id == ID_SIMPLE_BLOCK || id == ID_BLOCK)
1521538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return 1;
1522538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1523538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1524538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1525538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void
1526538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_null_log_callback(nestegg * ctx, unsigned int severity, char const * fmt, ...)
1527538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1528538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ctx && severity && fmt)
1529538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return;
1530538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1531538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1532b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic int
1533b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianne_init_cue_points(nestegg * ctx, int64_t max_offset)
1534b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
1535b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  int r;
1536b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct ebml_list_node * node = ctx->segment.cues.cue_point.head;
1537b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct seek * found;
1538b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  uint64_t seek_pos, id;
1539b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct saved_state state;
1540b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1541b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  /* If there are no cues loaded, check for cues element in the seek head
1542b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian     and load it. */
1543b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (!node) {
1544b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    found = ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES);
1545b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (!found)
1546b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return -1;
1547b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1548b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (ne_get_uint(found->position, &seek_pos) != 0)
1549b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return -1;
1550b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1551b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    /* Save old parser state. */
1552b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r = ne_ctx_save(ctx, &state);
1553b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (r != 0)
1554b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return -1;
1555b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1556b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    /* Seek and set up parser state for segment-level element (Cues). */
1557b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r = ne_io_seek(ctx->io, ctx->segment_offset + seek_pos, NESTEGG_SEEK_SET);
1558b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (r != 0)
1559b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return -1;
1560b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    ctx->last_valid = 0;
1561b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1562b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r = ne_read_element(ctx, &id, NULL);
1563b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (r != 1)
1564b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return -1;
1565b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1566b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (id != ID_CUES)
1567b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return -1;
1568b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1569b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    ctx->ancestor = NULL;
1570b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    ne_ctx_push(ctx, ne_top_level_elements, ctx);
1571b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    ne_ctx_push(ctx, ne_segment_elements, &ctx->segment);
1572b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    ne_ctx_push(ctx, ne_cues_elements, &ctx->segment.cues);
1573b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    /* parser will run until end of cues element. */
1574b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    ctx->log(ctx, NESTEGG_LOG_DEBUG, "seek: parsing cue elements");
1575b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r = ne_parse(ctx, ne_cues_elements, max_offset);
1576b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    while (ctx->ancestor)
1577b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      ne_ctx_pop(ctx);
1578b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1579b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    /* Reset parser state to original state and seek back to old position. */
1580b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (ne_ctx_restore(ctx, &state) != 0)
1581b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return -1;
1582b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1583b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (r < 0)
1584b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return -1;
1585b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1586b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    node = ctx->segment.cues.cue_point.head;
1587b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (!node)
1588b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      return -1;
1589b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  }
1590b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1591b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return 0;
1592b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
1593b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1594b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian/* Three functions that implement the nestegg_io interface, operating on a
1595b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian * sniff_buffer. */
1596b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstruct sniff_buffer {
1597b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  unsigned char const * buffer;
1598b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  size_t length;
1599b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  int64_t offset;
1600b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian};
1601b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1602b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic int
1603b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianne_buffer_read(void * buffer, size_t length, void * user_data)
1604b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
1605b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct sniff_buffer * sb = user_data;
1606b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1607b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  int rv = 1;
1608b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  size_t available = sb->length - (size_t)sb->offset;
1609b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1610b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (available < length)
1611b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return 0;
1612b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1613b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  memcpy(buffer, sb->buffer + sb->offset, length);
1614b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  sb->offset += length;
1615b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1616b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return rv;
1617b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
1618b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1619b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic int
1620b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianne_buffer_seek(int64_t offset, int whence, void * user_data)
1621b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
1622b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct sniff_buffer * sb = user_data;
1623b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  int64_t o = sb->offset;
1624b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1625b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  switch(whence) {
1626b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    case NESTEGG_SEEK_SET:
1627b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      o = offset;
1628b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      break;
1629b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    case NESTEGG_SEEK_CUR:
1630b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      o += offset;
1631b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      break;
1632b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    case NESTEGG_SEEK_END:
1633b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      o = sb->length + offset;
1634b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      break;
1635b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  }
1636b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1637b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (o < 0 || o > (int64_t) sb->length)
1638b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return -1;
1639b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1640b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  sb->offset = o;
1641b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return 0;
1642b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
1643b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1644b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic int64_t
1645b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianne_buffer_tell(void * user_data)
1646b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
1647b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct sniff_buffer * sb = user_data;
1648b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return sb->offset;
1649b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
1650b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1651b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianstatic int
1652b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianne_match_webm(nestegg_io io, int64_t max_offset)
1653b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
1654b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  int r;
1655b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  uint64_t id;
1656b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  char * doctype;
1657b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  nestegg * ctx;
1658b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1659b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (!(io.read && io.seek && io.tell))
1660b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return -1;
1661b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1662b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ctx = ne_alloc(sizeof(*ctx));
1663b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1664b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ctx->io = ne_alloc(sizeof(*ctx->io));
1665b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  *ctx->io = io;
1666b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ctx->alloc_pool = ne_pool_init();
1667b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ctx->log = ne_null_log_callback;
1668b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1669b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  r = ne_peek_element(ctx, &id, NULL);
1670b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (r != 1) {
1671b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    nestegg_destroy(ctx);
1672b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return 0;
1673b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  }
1674b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1675b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (id != ID_EBML) {
1676b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    nestegg_destroy(ctx);
1677b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return 0;
1678b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  }
1679b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1680b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ne_ctx_push(ctx, ne_top_level_elements, ctx);
1681b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1682b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  /* we don't check the return value of ne_parse, that might fail because
1683b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian   * max_offset is not on a valid element end point. We only want to check
1684b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian   * the EBML ID and that the doctype is "webm". */
1685b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ne_parse(ctx, NULL, max_offset);
1686b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1687b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (ne_get_string(ctx->ebml.doctype, &doctype) != 0 ||
1688b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      strcmp(doctype, "webm") != 0) {
1689b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    nestegg_destroy(ctx);
1690b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return 0;
1691b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  }
1692b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1693b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  nestegg_destroy(ctx);
1694b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1695b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return 1;
1696b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
1697b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1698538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1699b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramaniannestegg_init(nestegg ** context, nestegg_io io, nestegg_log callback, int64_t max_offset)
1700538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1701538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
1702538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t id, version, docversion;
1703538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list_node * track;
1704538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  char * doctype;
1705b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  nestegg * ctx;
1706538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1707538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!(io.read && io.seek && io.tell))
1708538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1709538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1710538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx = ne_alloc(sizeof(*ctx));
1711538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1712538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->io = ne_alloc(sizeof(*ctx->io));
1713538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *ctx->io = io;
1714538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log = callback;
1715538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->alloc_pool = ne_pool_init();
1716538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1717538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!ctx->log)
1718538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    ctx->log = ne_null_log_callback;
1719538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1720538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_peek_element(ctx, &id, NULL);
1721538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1) {
1722538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    nestegg_destroy(ctx);
1723538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1724538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1725538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1726538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (id != ID_EBML) {
1727538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    nestegg_destroy(ctx);
1728538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1729538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1730538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1731538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log(ctx, NESTEGG_LOG_DEBUG, "ctx %p", ctx);
1732538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1733538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_ctx_push(ctx, ne_top_level_elements, ctx);
1734538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1735b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  r = ne_parse(ctx, NULL, max_offset);
1736538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1737538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1) {
1738538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    nestegg_destroy(ctx);
1739538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1740538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1741538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1742538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_uint(ctx->ebml.ebml_read_version, &version) != 0)
1743538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    version = 1;
1744538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (version != 1) {
1745538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    nestegg_destroy(ctx);
1746538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1747538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1748538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1749538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_string(ctx->ebml.doctype, &doctype) != 0)
1750538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    doctype = "matroska";
1751538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (strcmp(doctype, "webm") != 0) {
1752538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    nestegg_destroy(ctx);
1753538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1754538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1755538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1756538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_uint(ctx->ebml.doctype_read_version, &docversion) != 0)
1757538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    docversion = 1;
1758538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (docversion < 1 || docversion > 2) {
1759538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    nestegg_destroy(ctx);
1760538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1761538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1762538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1763538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!ctx->segment.tracks.track_entry.head) {
1764538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    nestegg_destroy(ctx);
1765538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1766538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1767538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1768538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  track = ctx->segment.tracks.track_entry.head;
1769538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->track_count = 0;
1770538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1771538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (track) {
1772538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    ctx->track_count += 1;
1773538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    track = track->next;
1774538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1775538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1776538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *context = ctx;
1777538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1778538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1779538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1780538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1781538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubervoid
1782538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_destroy(nestegg * ctx)
1783538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1784538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (ctx->ancestor)
1785538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    ne_ctx_pop(ctx);
1786538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_pool_destroy(ctx->alloc_pool);
1787538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  free(ctx->io);
1788538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  free(ctx);
1789538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1790538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1791538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1792538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_duration(nestegg * ctx, uint64_t * duration)
1793538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1794538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t tc_scale;
1795538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  double unscaled_duration;
1796538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1797538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_float(ctx->segment.info.duration, &unscaled_duration) != 0)
1798538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1799538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1800538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  tc_scale = ne_get_timecode_scale(ctx);
1801538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1802538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *duration = (uint64_t) (unscaled_duration * tc_scale);
1803538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1804538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1805538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1806538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1807538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_tstamp_scale(nestegg * ctx, uint64_t * scale)
1808538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1809538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *scale = ne_get_timecode_scale(ctx);
1810538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1811538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1812538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1813538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1814538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_track_count(nestegg * ctx, unsigned int * tracks)
1815538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1816538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *tracks = ctx->track_count;
1817538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1818538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1819538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1820538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1821b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramaniannestegg_get_cue_point(nestegg * ctx, unsigned int cluster_num, int64_t max_offset,
1822b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                      int64_t * start_pos, int64_t * end_pos, uint64_t * tstamp)
1823538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1824b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  int range_obtained = 0;
1825b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  unsigned int cluster_count = 0;
1826538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct cue_point * cue_point;
1827538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct cue_track_positions * pos;
1828b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  uint64_t seek_pos, track_number, tc_scale, time;
1829b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct ebml_list_node * cues_node = ctx->segment.cues.cue_point.head;
1830b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct ebml_list_node * cue_pos_node = NULL;
1831b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  unsigned int track = 0, track_count = 0, track_index;
1832538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1833b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (!start_pos || !end_pos || !tstamp)
1834b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return -1;
1835538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1836b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  /* Initialise return values */
1837b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  *start_pos = -1;
1838b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  *end_pos = -1;
1839b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  *tstamp = 0;
1840538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1841b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (!cues_node) {
1842b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    ne_init_cue_points(ctx, max_offset);
1843b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    cues_node = ctx->segment.cues.cue_point.head;
1844b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    /* Verify cues have been added to context. */
1845b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (!cues_node)
1846538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1847b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  }
1848538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1849b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  nestegg_track_count(ctx, &track_count);
1850538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1851b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  tc_scale = ne_get_timecode_scale(ctx);
1852538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1853b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  while (cues_node && !range_obtained) {
1854b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    assert(cues_node->id == ID_CUE_POINT);
1855b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    cue_point = cues_node->data;
1856b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    cue_pos_node = cue_point->cue_track_positions.head;
1857b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    while (cue_pos_node) {
1858b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      assert(cue_pos_node->id == ID_CUE_TRACK_POSITIONS);
1859b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      pos = cue_pos_node->data;
1860b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      for (track = 0; track < track_count; track++) {
1861b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if (ne_get_uint(pos->track, &track_number) != 0)
1862b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          return -1;
1863b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1864b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if (ne_map_track_number_to_index(ctx, (unsigned int)track_number, &track_index) != 0)
1865b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          return -1;
1866b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1867b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if (track_index == track) {
1868b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          if (ne_get_uint(pos->cluster_position, &seek_pos) != 0)
1869b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            return -1;
1870b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          if (cluster_count == cluster_num) {
1871b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            *start_pos = ctx->segment_offset+seek_pos;
1872b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            if (ne_get_uint(cue_point->time, &time) != 0)
1873b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian              return -1;
1874b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            *tstamp = time * tc_scale;
1875b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          } else if (cluster_count == cluster_num+1) {
1876b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            *end_pos = (ctx->segment_offset+seek_pos)-1;
1877b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            range_obtained = 1;
1878b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian            break;
1879b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          }
1880b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          cluster_count++;
1881b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        }
1882b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      }
1883b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      cue_pos_node = cue_pos_node->next;
1884b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    }
1885b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    cues_node = cues_node->next;
1886b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  }
1887538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1888b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return 0;
1889b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
1890538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1891b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianint
1892b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramaniannestegg_offset_seek(nestegg * ctx, uint64_t offset)
1893b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
1894b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  int r;
1895538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1896b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  /* Seek and set up parser state for segment-level element (Cluster). */
1897b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  r = ne_io_seek(ctx->io, offset, NESTEGG_SEEK_SET);
1898b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (r != 0)
1899b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return -1;
1900b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ctx->last_valid = 0;
1901b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1902b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  while (ctx->ancestor)
1903b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    ne_ctx_pop(ctx);
1904b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1905b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ne_ctx_push(ctx, ne_top_level_elements, ctx);
1906b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ne_ctx_push(ctx, ne_segment_elements, &ctx->segment);
1907b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1908b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return 0;
1909b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
1910b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1911b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianint
1912b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramaniannestegg_track_seek(nestegg * ctx, unsigned int track, uint64_t tstamp)
1913b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
1914b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  int r;
1915b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct cue_point * cue_point;
1916b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct cue_track_positions * pos;
1917b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  uint64_t seek_pos, tc_scale;
1918b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
1919b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  /* If there are no cues loaded, check for cues element in the seek head
1920b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian     and load it. */
1921b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (!ctx->segment.cues.cue_point.head) {
1922b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r = ne_init_cue_points(ctx, -1);
1923b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    if (r != 0)
1924538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1925538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1926538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1927538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  tc_scale = ne_get_timecode_scale(ctx);
1928538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1929b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  cue_point = ne_find_cue_point_for_tstamp(ctx, ctx->segment.cues.cue_point.head,
1930b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian                                           track, tc_scale, tstamp);
1931538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!cue_point)
1932538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1933538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1934b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  pos = ne_find_cue_position_for_track(ctx, cue_point->cue_track_positions.head, track);
1935b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (pos == NULL)
1936538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1937538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1938b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (ne_get_uint(pos->cluster_position, &seek_pos) != 0)
1939b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return -1;
1940538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1941b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  /* Seek and set up parser state for segment-level element (Cluster). */
1942b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  r = nestegg_offset_seek(ctx, ctx->segment_offset + seek_pos);
1943538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log(ctx, NESTEGG_LOG_DEBUG, "seek: parsing cluster elements");
1944b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  r = ne_parse(ctx, NULL, -1);
1945538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
1946538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1947538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1948538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!ne_is_suspend_element(ctx->last_id))
1949538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1950538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1951538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1952538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1953538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1954538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1955538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_track_type(nestegg * ctx, unsigned int track)
1956538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1957538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct track_entry * entry;
1958538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t type;
1959538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1960538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  entry = ne_find_track_entry(ctx, track);
1961538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!entry)
1962538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1963538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1964538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_uint(entry->type, &type) != 0)
1965538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1966538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1967538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (type & TRACK_TYPE_VIDEO)
1968538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return NESTEGG_TRACK_VIDEO;
1969538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1970538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (type & TRACK_TYPE_AUDIO)
1971538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return NESTEGG_TRACK_AUDIO;
1972538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1973538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return -1;
1974538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1975538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1976538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1977538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_track_codec_id(nestegg * ctx, unsigned int track)
1978538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1979538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  char * codec_id;
1980538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct track_entry * entry;
1981538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1982538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  entry = ne_find_track_entry(ctx, track);
1983538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!entry)
1984538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1985538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1986538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_string(entry->codec_id, &codec_id) != 0)
1987538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1988538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1989538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (strcmp(codec_id, TRACK_ID_VP8) == 0)
1990538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return NESTEGG_CODEC_VP8;
1991538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1992ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang  if (strcmp(codec_id, TRACK_ID_VP9) == 0)
1993ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang    return NESTEGG_CODEC_VP9;
1994ba164dffc5a6795bce97fae02b51ccf3330e15e4hkuang
1995538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (strcmp(codec_id, TRACK_ID_VORBIS) == 0)
1996538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return NESTEGG_CODEC_VORBIS;
1997538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1998b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (strcmp(codec_id, TRACK_ID_OPUS) == 0)
1999b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    return NESTEGG_CODEC_OPUS;
2000b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
2001538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return -1;
2002538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
2003538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2004538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
2005538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_track_codec_data_count(nestegg * ctx, unsigned int track,
2006538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber                               unsigned int * count)
2007538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
2008538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct track_entry * entry;
2009538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_binary codec_private;
2010538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char * p;
2011538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2012538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *count = 0;
2013538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2014538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  entry = ne_find_track_entry(ctx, track);
2015538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!entry)
2016538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
2017538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2018538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS)
2019538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
2020538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2021538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_binary(entry->codec_private, &codec_private) != 0)
2022538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
2023538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2024538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (codec_private.length < 1)
2025538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
2026538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2027538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  p = codec_private.data;
2028538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *count = *p + 1;
2029538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2030538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (*count > 3)
2031538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
2032538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2033538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
2034538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
2035538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2036538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
2037538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_track_codec_data(nestegg * ctx, unsigned int track, unsigned int item,
2038538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber                         unsigned char ** data, size_t * length)
2039538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
2040538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct track_entry * entry;
2041538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_binary codec_private;
2042538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t sizes[3], total;
2043538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char * p;
2044538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned int count, i;
2045538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2046538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *data = NULL;
2047538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *length = 0;
2048538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2049538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  entry = ne_find_track_entry(ctx, track);
2050538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!entry)
2051538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
2052538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2053b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS
2054b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    && nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_OPUS)
2055538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
2056538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2057538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_binary(entry->codec_private, &codec_private) != 0)
2058538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
2059538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2060b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (nestegg_track_codec_id(ctx, track) == NESTEGG_CODEC_VORBIS) {
2061b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      p = codec_private.data;
2062b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      count = *p++ + 1;
2063538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2064b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if (count > 3)
2065b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        return -1;
2066538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2067b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      i = 0;
2068b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      total = 0;
2069b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      while (--count) {
2070b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        sizes[i] = ne_xiph_lace_value(&p);
2071b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        total += sizes[i];
2072b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        i += 1;
2073b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      }
2074b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      sizes[i] = codec_private.length - total - (p - codec_private.data);
2075538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2076b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      for (i = 0; i < item; ++i) {
2077b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        if (sizes[i] > LIMIT_FRAME)
2078b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian          return -1;
2079b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        p += sizes[i];
2080b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      }
2081b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      *data = p;
2082b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      *length = (size_t)sizes[item];
2083b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  } else {
2084b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    *data = codec_private.data;
2085b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    *length = codec_private.length;
2086538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
2087538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2088538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
2089538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
2090538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2091538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
2092538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_track_video_params(nestegg * ctx, unsigned int track,
2093538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber                           nestegg_video_params * params)
2094538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
2095538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct track_entry * entry;
2096b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  unsigned int value;
2097538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2098538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  memset(params, 0, sizeof(*params));
2099538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2100538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  entry = ne_find_track_entry(ctx, track);
2101538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!entry)
2102538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
2103538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2104538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_VIDEO)
2105538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
2106538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2107b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  value = 0;
2108b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ne_get_uint32(entry->video.stereo_mode, &value);
2109b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (value <= NESTEGG_VIDEO_STEREO_TOP_BOTTOM ||
2110b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      value == NESTEGG_VIDEO_STEREO_RIGHT_LEFT)
2111b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    params->stereo_mode = value;
2112b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
2113b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (ne_get_uint32(entry->video.pixel_width, &value) != 0)
2114538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
2115b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  params->width = value;
2116538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2117b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  if (ne_get_uint32(entry->video.pixel_height, &value) != 0)
2118538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
2119b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  params->height = value;
2120538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2121538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = 0;
2122b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ne_get_uint32(entry->video.pixel_crop_bottom, &value);
2123b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  params->crop_bottom = value;
2124538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2125538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = 0;
2126b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ne_get_uint32(entry->video.pixel_crop_top, &value);
2127b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  params->crop_top = value;
2128538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2129538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = 0;
2130b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ne_get_uint32(entry->video.pixel_crop_left, &value);
2131b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  params->crop_left = value;
2132538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2133538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = 0;
2134b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ne_get_uint32(entry->video.pixel_crop_right, &value);
2135b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  params->crop_right = value;
2136538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2137538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = params->width;
2138b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ne_get_uint32(entry->video.display_width, &value);
2139b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  params->display_width = value;
2140538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2141538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = params->height;
2142b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ne_get_uint32(entry->video.display_height, &value);
2143b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  params->display_height = value;
2144538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2145538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
2146538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
2147538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2148538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
2149538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_track_audio_params(nestegg * ctx, unsigned int track,
2150538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber                           nestegg_audio_params * params)
2151538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
2152538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct track_entry * entry;
2153b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  unsigned int value;
2154538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2155538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  memset(params, 0, sizeof(*params));
2156538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2157538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  entry = ne_find_track_entry(ctx, track);
2158538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!entry)
2159538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
2160538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2161538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_AUDIO)
2162538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
2163538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2164538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  params->rate = 8000;
2165538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_get_float(entry->audio.sampling_frequency, &params->rate);
2166538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2167538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = 1;
2168b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ne_get_uint32(entry->audio.channels, &value);
2169b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  params->channels = value;
2170538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2171538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = 16;
2172b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ne_get_uint32(entry->audio.bit_depth, &value);
2173b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  params->depth = value;
2174b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
2175b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  value = 0;
2176b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ne_get_uint32(entry->codec_delay, &value);
2177b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  params->codec_delay = value;
2178b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
2179b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  value = 0;
2180b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  ne_get_uint32(entry->seek_preroll, &value);
2181b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  params->seek_preroll = value;
2182538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2183538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
2184538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
2185538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2186538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
2187538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_read_packet(nestegg * ctx, nestegg_packet ** pkt)
2188538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
2189538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
2190538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t id, size;
2191538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2192538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *pkt = NULL;
2193538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2194538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  for (;;) {
2195538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_peek_element(ctx, &id, &size);
2196538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
2197538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
2198538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2199b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    /* Any DESC_FLAG_SUSPEND fields must be handled here. */
2200538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (ne_is_suspend_element(id)) {
2201538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      r = ne_read_element(ctx, &id, &size);
2202538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (r != 1)
2203538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        return r;
2204538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2205b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      /* The only DESC_FLAG_SUSPEND fields are Blocks and SimpleBlocks, which we
2206538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber         handle directly. */
2207538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      r = ne_read_block(ctx, id, size, pkt);
2208b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if (r != 1)
2209b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        return r;
2210b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
2211b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      r = ne_read_discard_padding(ctx, *pkt);
2212b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian      if (r != 1)
2213b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian        return r;
2214b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
2215538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
2216538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    }
2217538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2218b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian    r =  ne_parse(ctx, NULL, -1);
2219538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
2220538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
2221538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
2222538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2223538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
2224538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
2225538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2226538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubervoid
2227538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_free_packet(nestegg_packet * pkt)
2228538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
2229538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct frame * frame;
2230538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2231538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (pkt->frame) {
2232538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    frame = pkt->frame;
2233538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    pkt->frame = frame->next;
2234538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    free(frame->data);
2235538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    free(frame);
2236538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
2237538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2238538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber free(pkt);
2239538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
2240538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2241538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
2242538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_packet_track(nestegg_packet * pkt, unsigned int * track)
2243538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
22441b362b15af34006e6a11974088a46d42b903418eJohann  *track = (unsigned int)pkt->track;
2245538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
2246538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
2247538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2248538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
2249538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_packet_tstamp(nestegg_packet * pkt, uint64_t * tstamp)
2250538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
2251538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *tstamp = pkt->timecode;
2252538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
2253538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
2254538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2255538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
2256b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramaniannestegg_packet_discard_padding(nestegg_packet * pkt, int64_t * discard_padding)
2257b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
2258b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  *discard_padding = pkt->discard_padding;
2259b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return 0;
2260b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
2261b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
2262b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianint
2263538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_packet_count(nestegg_packet * pkt, unsigned int * count)
2264538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
2265538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct frame * f = pkt->frame;
2266538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2267538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *count = 0;
2268538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2269538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (f) {
2270538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *count += 1;
2271538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    f = f->next;
2272538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
2273538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2274538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
2275538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
2276538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2277538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
2278538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_packet_data(nestegg_packet * pkt, unsigned int item,
2279538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber                    unsigned char ** data, size_t * length)
2280538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
2281538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct frame * f = pkt->frame;
2282538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned int count = 0;
2283538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2284538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *data = NULL;
2285538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *length = 0;
2286538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2287538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (f) {
2288538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (count == item) {
2289538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      *data = f->data;
2290538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      *length = f->length;
2291538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return 0;
2292538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    }
2293538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    count += 1;
2294538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    f = f->next;
2295538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
2296538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
2297538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return -1;
2298538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
2299b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
2300b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianint
2301b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramaniannestegg_has_cues(nestegg * ctx)
2302b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
2303b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return ctx->segment.cues.cue_point.head ||
2304b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian         ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES);
2305b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
2306b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
2307b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanianint
2308b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramaniannestegg_sniff(unsigned char const * buffer, size_t length)
2309b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian{
2310b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  nestegg_io io;
2311b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  struct sniff_buffer user_data;
2312b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
2313b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  user_data.buffer = buffer;
2314b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  user_data.length = length;
2315b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  user_data.offset = 0;
2316b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
2317b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  io.read = ne_buffer_read;
2318b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  io.seek = ne_buffer_seek;
2319b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  io.tell = ne_buffer_tell;
2320b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  io.userdata = &user_data;
2321b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian  return ne_match_webm(io, length);
2322b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian}
2323b08e2e23eec181e9951df33cd704ac294c5407b6Vignesh Venkatasubramanian
2324