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
11538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include "nestegg/halloc/halloc.h"
12538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#include "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
28538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* WebMedia 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
52538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
53538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Tracks Elements */
54538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_TRACKS               0x1654ae6b
55538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_TRACK_ENTRY          0xae
56538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_TRACK_NUMBER         0xd7
57538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_TRACK_UID            0x73c5
58538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_TRACK_TYPE           0x83
59538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_FLAG_ENABLED         0xb9
60538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_FLAG_DEFAULT         0x88
61538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_FLAG_LACING          0x9c
62538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_TRACK_TIMECODE_SCALE 0x23314f
63538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_LANGUAGE             0x22b59c
64538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CODEC_ID             0x86
65538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CODEC_PRIVATE        0x63a2
66538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
67538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Video Elements */
68538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_VIDEO                0xe0
69538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_PIXEL_WIDTH          0xb0
70538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_PIXEL_HEIGHT         0xba
71538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_PIXEL_CROP_BOTTOM    0x54aa
72538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_PIXEL_CROP_TOP       0x54bb
73538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_PIXEL_CROP_LEFT      0x54cc
74538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_PIXEL_CROP_RIGHT     0x54dd
75538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_DISPLAY_WIDTH        0x54b0
76538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_DISPLAY_HEIGHT       0x54ba
77538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
78538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Audio Elements */
79538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_AUDIO                0xe1
80538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_SAMPLING_FREQUENCY   0xb5
81538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CHANNELS             0x9f
82538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_BIT_DEPTH            0x6264
83538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
84538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Cues Elements */
85538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CUES                 0x1c53bb6b
86538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CUE_POINT            0xbb
87538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CUE_TIME             0xb3
88538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CUE_TRACK_POSITIONS  0xb7
89538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CUE_TRACK            0xf7
90538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CUE_CLUSTER_POSITION 0xf1
91538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define ID_CUE_BLOCK_NUMBER     0x5378
92538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
93538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* EBML Types */
94538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberenum ebml_type_enum {
95538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  TYPE_UNKNOWN,
96538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  TYPE_MASTER,
97538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  TYPE_UINT,
98538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  TYPE_FLOAT,
99538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  TYPE_INT,
100538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  TYPE_STRING,
101538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  TYPE_BINARY
102538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
103538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
104538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define LIMIT_STRING            (1 << 20)
105538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define LIMIT_BINARY            (1 << 24)
106538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define LIMIT_BLOCK             (1 << 30)
107538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define LIMIT_FRAME             (1 << 28)
108538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
109538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Field Flags */
110538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define DESC_FLAG_NONE          0
111538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define DESC_FLAG_MULTI         (1 << 0)
112538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define DESC_FLAG_SUSPEND       (1 << 1)
113538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define DESC_FLAG_OFFSET        (1 << 2)
114538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
115538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Block Header Flags */
116538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define BLOCK_FLAGS_LACING      6
117538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
118538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Lacing Constants */
119538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define LACING_NONE             0
120538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define LACING_XIPH             1
121538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define LACING_FIXED            2
122538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define LACING_EBML             3
123538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
124538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Track Types */
125538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define TRACK_TYPE_VIDEO        1
126538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define TRACK_TYPE_AUDIO        2
127538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
128538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Track IDs */
129538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define TRACK_ID_VP8            "V_VP8"
130538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define TRACK_ID_VORBIS         "A_VORBIS"
131538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
132538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberenum vint_mask {
133538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  MASK_NONE,
134538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  MASK_FIRST_BIT
135538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
136538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
137538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct ebml_binary {
138538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char * data;
139538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t length;
140538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
141538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
142538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct ebml_list_node {
143538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list_node * next;
144538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t id;
145538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  void * data;
146538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
147538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
148538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct ebml_list {
149538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list_node * head;
150538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list_node * tail;
151538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
152538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
153538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct ebml_type {
154538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  union ebml_value {
155538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    uint64_t u;
156538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    double f;
157538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    int64_t i;
158538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    char * s;
159538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    struct ebml_binary b;
160538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  } v;
161538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  enum ebml_type_enum type;
162538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int read;
163538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
164538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
165538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* EBML Definitions */
166538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct ebml {
167538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type ebml_version;
168538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type ebml_read_version;
169538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type ebml_max_id_length;
170538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type ebml_max_size_length;
171538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type doctype;
172538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type doctype_version;
173538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type doctype_read_version;
174538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
175538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
176538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Matroksa Definitions */
177538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct seek {
178538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type id;
179538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type position;
180538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
181538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
182538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct seek_head {
183538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list seek;
184538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
185538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
186538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct info {
187538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type timecode_scale;
188538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type duration;
189538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
190538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
191538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct block_group {
192538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type duration;
193538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type reference_block;
194538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
195538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
196538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct cluster {
197538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type timecode;
198538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list block_group;
199538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
200538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
201538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct video {
202538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type pixel_width;
203538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type pixel_height;
204538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type pixel_crop_bottom;
205538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type pixel_crop_top;
206538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type pixel_crop_left;
207538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type pixel_crop_right;
208538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type display_width;
209538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type display_height;
210538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
211538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
212538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct audio {
213538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type sampling_frequency;
214538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type channels;
215538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type bit_depth;
216538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
217538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
218538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct track_entry {
219538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type number;
220538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type uid;
221538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type type;
222538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type flag_enabled;
223538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type flag_default;
224538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type flag_lacing;
225538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type track_timecode_scale;
226538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type language;
227538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type codec_id;
228538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type codec_private;
229538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct video video;
230538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct audio audio;
231538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
232538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
233538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct tracks {
234538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list track_entry;
235538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
236538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
237538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct cue_track_positions {
238538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type track;
239538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type cluster_position;
240538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type block_number;
241538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
242538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
243538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct cue_point {
244538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type time;
245538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list cue_track_positions;
246538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
247538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
248538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct cues {
249538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list cue_point;
250538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
251538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
252538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct segment {
253538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list seek_head;
254538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct info info;
255538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list cluster;
256538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct tracks tracks;
257538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct cues cues;
258538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
259538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
260538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Misc. */
261538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct pool_ctx {
262538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  char dummy;
263538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
264538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
265538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct list_node {
266538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct list_node * previous;
267538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_element_desc * node;
268538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char * data;
269538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
270538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
271538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct saved_state {
272538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int64_t stream_offset;
273538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct list_node * ancestor;
274538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t last_id;
275538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t last_size;
276538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
277538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
278538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct frame {
279538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char * data;
280538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t length;
281538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct frame * next;
282538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
283538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
284538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Public (opaque) Structures */
285538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct nestegg {
286538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  nestegg_io * io;
287538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  nestegg_log log;
288538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct pool_ctx * alloc_pool;
289538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t last_id;
290538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t last_size;
291538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct list_node * ancestor;
292538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml ebml;
293538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct segment segment;
294538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int64_t segment_offset;
295538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned int track_count;
296538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
297538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
298538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct nestegg_packet {
299538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t track;
300538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t timecode;
301538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct frame * frame;
302538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
303538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
304538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* Element Descriptor */
305538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstruct ebml_element_desc {
306538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  char const * name;
307538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t id;
308538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  enum ebml_type_enum type;
309538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t offset;
310538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned int flags;
311538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_element_desc * children;
312538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t size;
313538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t data_offset;
314538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
315538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
316538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define E_FIELD(ID, TYPE, STRUCT, FIELD) \
317538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_NONE, NULL, 0, 0 }
318538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define E_MASTER(ID, TYPE, STRUCT, FIELD) \
319538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_MULTI, ne_ ## FIELD ## _elements, \
320538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      sizeof(struct FIELD), 0 }
321538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define E_SINGLE_MASTER_O(ID, TYPE, STRUCT, FIELD) \
322538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_OFFSET, ne_ ## FIELD ## _elements, 0, \
323538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      offsetof(STRUCT, FIELD ## _offset) }
324538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define E_SINGLE_MASTER(ID, TYPE, STRUCT, FIELD) \
325538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_NONE, ne_ ## FIELD ## _elements, 0, 0 }
326538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define E_SUSPEND(ID, TYPE) \
327538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  { #ID, ID, TYPE, 0, DESC_FLAG_SUSPEND, NULL, 0, 0 }
328538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#define E_LAST \
329538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  { NULL, 0, 0, 0, DESC_FLAG_NONE, NULL, 0, 0 }
330538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
331538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* EBML Element Lists */
332538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_ebml_elements[] = {
333538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_EBML_VERSION, TYPE_UINT, struct ebml, ebml_version),
334538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_EBML_READ_VERSION, TYPE_UINT, struct ebml, ebml_read_version),
335538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_EBML_MAX_ID_LENGTH, TYPE_UINT, struct ebml, ebml_max_id_length),
336538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_EBML_MAX_SIZE_LENGTH, TYPE_UINT, struct ebml, ebml_max_size_length),
337538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_DOCTYPE, TYPE_STRING, struct ebml, doctype),
338538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_DOCTYPE_VERSION, TYPE_UINT, struct ebml, doctype_version),
339538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_DOCTYPE_READ_VERSION, TYPE_UINT, struct ebml, doctype_read_version),
340538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
341538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
342538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
343538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber/* WebMedia Element Lists */
344538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_seek_elements[] = {
345538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_SEEK_ID, TYPE_BINARY, struct seek, id),
346538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_SEEK_POSITION, TYPE_UINT, struct seek, position),
347538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
348538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
349538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
350538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_seek_head_elements[] = {
351538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_MASTER(ID_SEEK, TYPE_MASTER, struct seek_head, seek),
352538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
353538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
354538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
355538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_info_elements[] = {
356538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_TIMECODE_SCALE, TYPE_UINT, struct info, timecode_scale),
357538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_DURATION, TYPE_FLOAT, struct info, duration),
358538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
359538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
360538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
361538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_block_group_elements[] = {
362538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SUSPEND(ID_BLOCK, TYPE_BINARY),
363538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_BLOCK_DURATION, TYPE_UINT, struct block_group, duration),
364538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_REFERENCE_BLOCK, TYPE_INT, struct block_group, reference_block),
365538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
366538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
367538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
368538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_cluster_elements[] = {
369538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_TIMECODE, TYPE_UINT, struct cluster, timecode),
370538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_MASTER(ID_BLOCK_GROUP, TYPE_MASTER, struct cluster, block_group),
371538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SUSPEND(ID_SIMPLE_BLOCK, TYPE_BINARY),
372538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
373538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
374538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
375538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_video_elements[] = {
376538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_PIXEL_WIDTH, TYPE_UINT, struct video, pixel_width),
377538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_PIXEL_HEIGHT, TYPE_UINT, struct video, pixel_height),
378538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_PIXEL_CROP_BOTTOM, TYPE_UINT, struct video, pixel_crop_bottom),
379538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_PIXEL_CROP_TOP, TYPE_UINT, struct video, pixel_crop_top),
380538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_PIXEL_CROP_LEFT, TYPE_UINT, struct video, pixel_crop_left),
381538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_PIXEL_CROP_RIGHT, TYPE_UINT, struct video, pixel_crop_right),
382538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_DISPLAY_WIDTH, TYPE_UINT, struct video, display_width),
383538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_DISPLAY_HEIGHT, TYPE_UINT, struct video, display_height),
384538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
385538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
386538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
387538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_audio_elements[] = {
388538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_SAMPLING_FREQUENCY, TYPE_FLOAT, struct audio, sampling_frequency),
389538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_CHANNELS, TYPE_UINT, struct audio, channels),
390538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_BIT_DEPTH, TYPE_UINT, struct audio, bit_depth),
391538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
392538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
393538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
394538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_track_entry_elements[] = {
395538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_TRACK_NUMBER, TYPE_UINT, struct track_entry, number),
396538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_TRACK_UID, TYPE_UINT, struct track_entry, uid),
397538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_TRACK_TYPE, TYPE_UINT, struct track_entry, type),
398538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_FLAG_ENABLED, TYPE_UINT, struct track_entry, flag_enabled),
399538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_FLAG_DEFAULT, TYPE_UINT, struct track_entry, flag_default),
400538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_FLAG_LACING, TYPE_UINT, struct track_entry, flag_lacing),
401538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_TRACK_TIMECODE_SCALE, TYPE_FLOAT, struct track_entry, track_timecode_scale),
402538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_LANGUAGE, TYPE_STRING, struct track_entry, language),
403538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_CODEC_ID, TYPE_STRING, struct track_entry, codec_id),
404538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_CODEC_PRIVATE, TYPE_BINARY, struct track_entry, codec_private),
405538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SINGLE_MASTER(ID_VIDEO, TYPE_MASTER, struct track_entry, video),
406538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SINGLE_MASTER(ID_AUDIO, TYPE_MASTER, struct track_entry, audio),
407538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
408538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
409538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
410538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_tracks_elements[] = {
411538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_MASTER(ID_TRACK_ENTRY, TYPE_MASTER, struct tracks, track_entry),
412538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
413538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
414538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
415538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_cue_track_positions_elements[] = {
416538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_CUE_TRACK, TYPE_UINT, struct cue_track_positions, track),
417538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_CUE_CLUSTER_POSITION, TYPE_UINT, struct cue_track_positions, cluster_position),
418538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_CUE_BLOCK_NUMBER, TYPE_UINT, struct cue_track_positions, block_number),
419538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
420538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
421538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
422538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_cue_point_elements[] = {
423538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_FIELD(ID_CUE_TIME, TYPE_UINT, struct cue_point, time),
424538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_MASTER(ID_CUE_TRACK_POSITIONS, TYPE_MASTER, struct cue_point, cue_track_positions),
425538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
426538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
427538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
428538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_cues_elements[] = {
429538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_MASTER(ID_CUE_POINT, TYPE_MASTER, struct cues, cue_point),
430538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
431538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
432538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
433538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_segment_elements[] = {
434538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_MASTER(ID_SEEK_HEAD, TYPE_MASTER, struct segment, seek_head),
435538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SINGLE_MASTER(ID_INFO, TYPE_MASTER, struct segment, info),
436538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_MASTER(ID_CLUSTER, TYPE_MASTER, struct segment, cluster),
437538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SINGLE_MASTER(ID_TRACKS, TYPE_MASTER, struct segment, tracks),
438538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SINGLE_MASTER(ID_CUES, TYPE_MASTER, struct segment, cues),
439538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
440538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
441538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
442538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc ne_top_level_elements[] = {
443538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SINGLE_MASTER(ID_EBML, TYPE_MASTER, nestegg, ebml),
444538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_SINGLE_MASTER_O(ID_SEGMENT, TYPE_MASTER, nestegg, segment),
445538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  E_LAST
446538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber};
447538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
448538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#undef E_FIELD
449538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#undef E_MASTER
450538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#undef E_SINGLE_MASTER_O
451538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#undef E_SINGLE_MASTER
452538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#undef E_SUSPEND
453538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber#undef E_LAST
454538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
455538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct pool_ctx *
456538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_pool_init(void)
457538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
458538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct pool_ctx * pool;
459538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
460538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  pool = h_malloc(sizeof(*pool));
461538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!pool)
462538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    abort();
463538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return pool;
464538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
465538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
466538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void
467538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_pool_destroy(struct pool_ctx * pool)
468538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
469538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  h_free(pool);
470538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
471538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
472538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void *
473538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_pool_alloc(size_t size, struct pool_ctx * pool)
474538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
475538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  void * p;
476538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
477538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  p = h_malloc(size);
478538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!p)
479538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    abort();
480538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  hattach(p, pool);
481538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  memset(p, 0, size);
482538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return p;
483538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
484538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
485538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void *
486538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_alloc(size_t size)
487538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
488538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  void * p;
489538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
490538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  p = calloc(1, size);
491538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!p)
492538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    abort();
493538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return p;
494538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
495538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
496538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
497538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_io_read(nestegg_io * io, void * buffer, size_t length)
498538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
499538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return io->read(buffer, length, io->userdata);
500538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
501538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
502538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
503538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_io_seek(nestegg_io * io, int64_t offset, int whence)
504538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
505538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return io->seek(offset, whence, io->userdata);
506538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
507538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
508538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
509538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_io_read_skip(nestegg_io * io, size_t length)
510538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
511538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t get;
512538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char buf[8192];
513538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r = 1;
514538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
515538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (length > 0) {
516538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    get = length < sizeof(buf) ? length : sizeof(buf);
517538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_io_read(io, buf, get);
518538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
519538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      break;
520538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    length -= get;
521538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
522538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
523538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return r;
524538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
525538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
526538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int64_t
527538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_io_tell(nestegg_io * io)
528538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
529538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return io->tell(io->userdata);
530538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
531538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
532538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
533538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_bare_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length, enum vint_mask maskflag)
534538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
535538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
536538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char b;
537538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t maxlen = 8;
538538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned int count = 1, mask = 1 << 7;
539538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
540538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_io_read(io, &b, 1);
541538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
542538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
543538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
544538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (count < maxlen) {
545538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if ((b & mask) != 0)
546538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      break;
547538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    mask >>= 1;
548538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    count += 1;
549538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
550538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
551538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (length)
552538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *length = count;
553538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *value = b;
554538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
555538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (maskflag == MASK_FIRST_BIT)
556538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *value = b & ~mask;
557538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
558538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (--count) {
559538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_io_read(io, &b, 1);
560538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
561538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
562538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *value <<= 8;
563538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *value |= b;
564538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
565538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
566538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
567538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
568538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
569538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
570538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_id(nestegg_io * io, uint64_t * value, uint64_t * length)
571538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
572538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return ne_bare_read_vint(io, value, length, MASK_NONE);
573538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
574538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
575538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
576538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length)
577538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
578538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return ne_bare_read_vint(io, value, length, MASK_FIRST_BIT);
579538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
580538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
581538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
582538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_svint(nestegg_io * io, int64_t * value, uint64_t * length)
583538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
584538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
585538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t uvalue;
586538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t ulength;
587538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int64_t svint_subtr[] = {
588538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    0x3f, 0x1fff,
589538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    0xfffff, 0x7ffffff,
590538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    0x3ffffffffLL, 0x1ffffffffffLL,
591538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    0xffffffffffffLL, 0x7fffffffffffffLL
592538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  };
593538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
594538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_bare_read_vint(io, &uvalue, &ulength, MASK_FIRST_BIT);
595538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
596538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
597538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *value = uvalue - svint_subtr[ulength - 1];
598538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (length)
599538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *length = ulength;
600538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return r;
601538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
602538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
603538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
604538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_uint(nestegg_io * io, uint64_t * val, uint64_t length)
605538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
606538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char b;
607538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
608538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
609538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (length == 0 || length > 8)
610538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
611538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_io_read(io, &b, 1);
612538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
613538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
614538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *val = b;
615538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (--length) {
616538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_io_read(io, &b, 1);
617538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
618538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
619538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *val <<= 8;
620538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *val |= b;
621538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
622538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
623538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
624538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
625538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
626538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_int(nestegg_io * io, int64_t * val, uint64_t length)
627538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
628538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
629538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t uval, base;
630538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
631538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_uint(io, &uval, length);
632538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
633538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
634538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
635538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (length < sizeof(int64_t)) {
636538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    base = 1;
637538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    base <<= length * 8 - 1;
638538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (uval >= base) {
639538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        base = 1;
640538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        base <<= length * 8;
641538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    } else {
642538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      base = 0;
643538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    }
644538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *val = uval - base;
645538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  } else {
646538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *val = (int64_t) uval;
647538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
648538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
649538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
650538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
651538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
652538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
653538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_float(nestegg_io * io, double * val, uint64_t length)
654538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
655538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  union {
656538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    uint64_t u;
657538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    float f;
658538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    double d;
659538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  } value;
660538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
661538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
662538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  /* length == 10 not implemented */
663538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (length != 4 && length != 8)
664538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
665538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_uint(io, &value.u, length);
666538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
667538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
668538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (length == 4)
669538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *val = value.f;
670538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  else
671538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *val = value.d;
672538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
673538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
674538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
675538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
676538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_string(nestegg * ctx, char ** val, uint64_t length)
677538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
678538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  char * str;
679538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
680538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
681538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (length == 0 || length > LIMIT_STRING)
682538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
683538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  str = ne_pool_alloc(length + 1, ctx->alloc_pool);
684538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_io_read(ctx->io, (unsigned char *) str, length);
685538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
686538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
687538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  str[length] = '\0';
688538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *val = str;
689538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
690538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
691538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
692538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
693538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_binary(nestegg * ctx, struct ebml_binary * val, uint64_t length)
694538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
695538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (length == 0 || length > LIMIT_BINARY)
696538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
697538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  val->data = ne_pool_alloc(length, ctx->alloc_pool);
698538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  val->length = length;
699538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return ne_io_read(ctx->io, val->data, length);
700538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
701538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
702538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
703538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_get_uint(struct ebml_type type, uint64_t * value)
704538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
705538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!type.read)
706538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
707538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
708538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  assert(type.type == TYPE_UINT);
709538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
710538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *value = type.v.u;
711538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
712538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
713538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
714538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
715538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
716538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_get_float(struct ebml_type type, double * value)
717538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
718538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!type.read)
719538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
720538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
721538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  assert(type.type == TYPE_FLOAT);
722538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
723538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *value = type.v.f;
724538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
725538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
726538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
727538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
728538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
729538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_get_string(struct ebml_type type, char ** value)
730538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
731538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!type.read)
732538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
733538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
734538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  assert(type.type == TYPE_STRING);
735538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
736538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *value = type.v.s;
737538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
738538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
739538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
740538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
741538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
742538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_get_binary(struct ebml_type type, struct ebml_binary * value)
743538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
744538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!type.read)
745538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
746538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
747538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  assert(type.type == TYPE_BINARY);
748538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
749538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *value = type.v.b;
750538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
751538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
752538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
753538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
754538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
755538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_is_ancestor_element(uint64_t id, struct list_node * ancestor)
756538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
757538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_element_desc * element;
758538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
759538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  for (; ancestor; ancestor = ancestor->previous)
760538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    for (element = ancestor->node; element->id; ++element)
761538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (element->id == id)
762538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        return 1;
763538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
764538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
765538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
766538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
767538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct ebml_element_desc *
768538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_find_element(uint64_t id, struct ebml_element_desc * elements)
769538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
770538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_element_desc * element;
771538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
772538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  for (element = elements; element->id; ++element)
773538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (element->id == id)
774538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return element;
775538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
776538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return NULL;
777538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
778538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
779538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void
780538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_ctx_push(nestegg * ctx, struct ebml_element_desc * ancestor, void * data)
781538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
782538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct list_node * item;
783538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
784538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  item = ne_alloc(sizeof(*item));
785538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  item->previous = ctx->ancestor;
786538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  item->node = ancestor;
787538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  item->data = data;
788538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->ancestor = item;
789538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
790538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
791538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void
792538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_ctx_pop(nestegg * ctx)
793538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
794538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct list_node * item;
795538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
796538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  item = ctx->ancestor;
797538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->ancestor = item->previous;
798538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  free(item);
799538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
800538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
801538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
802538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_ctx_save(nestegg * ctx, struct saved_state * s)
803538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
804538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  s->stream_offset = ne_io_tell(ctx->io);
805538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (s->stream_offset < 0)
806538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
807538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  s->ancestor = ctx->ancestor;
808538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  s->last_id = ctx->last_id;
809538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  s->last_size = ctx->last_size;
810538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
811538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
812538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
813538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
814538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_ctx_restore(nestegg * ctx, struct saved_state * s)
815538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
816538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
817538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
818538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_io_seek(ctx->io, s->stream_offset, NESTEGG_SEEK_SET);
819538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 0)
820538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
821538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->ancestor = s->ancestor;
822538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->last_id = s->last_id;
823538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->last_size = s->last_size;
824538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
825538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
826538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
827538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
828538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_peek_element(nestegg * ctx, uint64_t * id, uint64_t * size)
829538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
830538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
831538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
832538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ctx->last_id && ctx->last_size) {
833538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (id)
834538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      *id = ctx->last_id;
835538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (size)
836538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      *size = ctx->last_size;
837538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return 1;
838538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
839538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
840538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_id(ctx->io, &ctx->last_id, NULL);
841538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
842538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
843538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
844538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_vint(ctx->io, &ctx->last_size, NULL);
845538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
846538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
847538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
848538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (id)
849538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *id = ctx->last_id;
850538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (size)
851538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *size = ctx->last_size;
852538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
853538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
854538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
855538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
856538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
857538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_element(nestegg * ctx, uint64_t * id, uint64_t * size)
858538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
859538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
860538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
861538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_peek_element(ctx, id, size);
862538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
863538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
864538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
865538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->last_id = 0;
866538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->last_size = 0;
867538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
868538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
869538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
870538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
871538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void
872538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_master(nestegg * ctx, struct ebml_element_desc * desc)
873538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
874538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list * list;
875538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list_node * node, * oldtail;
876538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
877538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  assert(desc->type == TYPE_MASTER && desc->flags & DESC_FLAG_MULTI);
878538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
879538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log(ctx, NESTEGG_LOG_DEBUG, "multi master element %llx (%s)",
880538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber           desc->id, desc->name);
881538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
882538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  list = (struct ebml_list *) (ctx->ancestor->data + desc->offset);
883538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
884538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  node = ne_pool_alloc(sizeof(*node), ctx->alloc_pool);
885538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  node->id = desc->id;
886538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  node->data = ne_pool_alloc(desc->size, ctx->alloc_pool);
887538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
888538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  oldtail = list->tail;
889538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (oldtail)
890538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    oldtail->next = node;
891538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  list->tail = node;
892538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!list->head)
893538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    list->head = node;
894538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
895538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log(ctx, NESTEGG_LOG_DEBUG, " -> using data %p", node->data);
896538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
897538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_ctx_push(ctx, desc->children, node->data);
898538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
899538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
900538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void
901538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_single_master(nestegg * ctx, struct ebml_element_desc * desc)
902538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
903538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  assert(desc->type == TYPE_MASTER && !(desc->flags & DESC_FLAG_MULTI));
904538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
905538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log(ctx, NESTEGG_LOG_DEBUG, "single master element %llx (%s)",
906538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber           desc->id, desc->name);
907538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log(ctx, NESTEGG_LOG_DEBUG, " -> using data %p (%u)",
908538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber           ctx->ancestor->data + desc->offset, desc->offset);
909538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
910538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_ctx_push(ctx, desc->children, ctx->ancestor->data + desc->offset);
911538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
912538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
913538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
914538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_simple(nestegg * ctx, struct ebml_element_desc * desc, size_t length)
915538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
916538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_type * storage;
917538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
918538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
919538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  storage = (struct ebml_type *) (ctx->ancestor->data + desc->offset);
920538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
921538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (storage->read) {
922538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    ctx->log(ctx, NESTEGG_LOG_DEBUG, "element %llx (%s) already read, skipping",
923538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber             desc->id, desc->name);
924538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return 0;
925538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
926538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
927538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  storage->type = desc->type;
928538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
929538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log(ctx, NESTEGG_LOG_DEBUG, "element %llx (%s) -> %p (%u)",
930538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber           desc->id, desc->name, storage, desc->offset);
931538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
932538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = -1;
933538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
934538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  switch (desc->type) {
935538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case TYPE_UINT:
936538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_uint(ctx->io, &storage->v.u, length);
937538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
938538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case TYPE_FLOAT:
939538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_float(ctx->io, &storage->v.f, length);
940538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
941538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case TYPE_INT:
942538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_int(ctx->io, &storage->v.i, length);
943538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
944538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case TYPE_STRING:
945538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_string(ctx, &storage->v.s, length);
946538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
947538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case TYPE_BINARY:
948538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_binary(ctx, &storage->v.b, length);
949538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
950538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case TYPE_MASTER:
951538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case TYPE_UNKNOWN:
952538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    assert(0);
953538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
954538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
955538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
956538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r == 1)
957538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    storage->read = 1;
958538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
959538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return r;
960538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
961538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
962538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
963538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_parse(nestegg * ctx, struct ebml_element_desc * top_level)
964538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
965538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
966538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int64_t * data_offset;
967538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t id, size;
968538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_element_desc * element;
969538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
970538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  /* loop until we need to return:
971538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber     - hit suspend point
972538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber     - parse complete
973538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber     - error occurred */
974538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
975538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  /* loop over elements at current level reading them if sublevel found,
976538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber     push ctx onto stack and continue if sublevel ended, pop ctx off stack
977538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber     and continue */
978538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
979538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!ctx->ancestor)
980538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
981538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
982538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  for (;;) {
983538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_peek_element(ctx, &id, &size);
984538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
985538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      break;
986538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
987538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    element = ne_find_element(id, ctx->ancestor->node);
988538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (element) {
989538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (element->flags & DESC_FLAG_SUSPEND) {
990538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        assert(element->type == TYPE_BINARY);
991538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        ctx->log(ctx, NESTEGG_LOG_DEBUG, "suspend parse at %llx", id);
992538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        r = 1;
993538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        break;
994538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      }
995538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
996538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      r = ne_read_element(ctx, &id, &size);
997538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (r != 1)
998538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        break;
999538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1000538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (element->flags & DESC_FLAG_OFFSET) {
1001538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        data_offset = (int64_t *) (ctx->ancestor->data + element->data_offset);
1002538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        *data_offset = ne_io_tell(ctx->io);
1003538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        if (*data_offset < 0) {
1004538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber          r = -1;
1005538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber          break;
1006538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        }
1007538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      }
1008538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1009538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (element->type == TYPE_MASTER) {
1010538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        if (element->flags & DESC_FLAG_MULTI)
1011538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber          ne_read_master(ctx, element);
1012538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        else
1013538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber          ne_read_single_master(ctx, element);
1014538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        continue;
1015538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      } else {
1016538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        r = ne_read_simple(ctx, element, size);
1017538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        if (r < 0)
1018538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber          break;
1019538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      }
1020538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    } else if (ne_is_ancestor_element(id, ctx->ancestor->previous)) {
1021538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      ctx->log(ctx, NESTEGG_LOG_DEBUG, "parent element %llx", id);
1022538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (top_level && ctx->ancestor->node == top_level) {
1023538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        ctx->log(ctx, NESTEGG_LOG_DEBUG, "*** parse about to back up past top_level");
1024538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        r = 1;
1025538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        break;
1026538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      }
1027538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      ne_ctx_pop(ctx);
1028538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    } else {
1029538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      r = ne_read_element(ctx, &id, &size);
1030538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (r != 1)
1031538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        break;
1032538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1033538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (id != ID_VOID && id != ID_CRC32)
1034538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        ctx->log(ctx, NESTEGG_LOG_DEBUG, "unknown element %llx", id);
1035538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      r = ne_io_read_skip(ctx->io, size);
1036538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (r != 1)
1037538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        break;
1038538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    }
1039538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1040538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1041538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
1042538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    while (ctx->ancestor)
1043538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      ne_ctx_pop(ctx);
1044538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1045538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return r;
1046538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1047538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1048538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic uint64_t
1049538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_xiph_lace_value(unsigned char ** np)
1050538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1051538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t lace;
1052538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t value;
1053538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char * p = *np;
1054538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1055538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  lace = *p++;
1056538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = lace;
1057538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (lace == 255) {
1058538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    lace = *p++;
1059538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    value += lace;
1060538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1061538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1062538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *np = p;
1063538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1064538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return value;
1065538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1066538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1067538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
1068538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_xiph_lace_value(nestegg_io * io, uint64_t * value, size_t * consumed)
1069538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1070538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
1071538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t lace;
1072538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1073538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_uint(io, &lace, 1);
1074538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
1075538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
1076538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *consumed += 1;
1077538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1078538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *value = lace;
1079538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (lace == 255) {
1080538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_uint(io, &lace, 1);
1081538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
1082538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
1083538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *consumed += 1;
1084538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *value += lace;
1085538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1086538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1087538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
1088538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1089538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1090538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
1091538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_xiph_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
1092538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1093538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
1094538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t i = 0;
1095538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t sum = 0;
1096538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1097538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (--n) {
1098538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_xiph_lace_value(io, &sizes[i], read);
1099538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
1100538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
1101538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    sum += sizes[i];
1102538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    i += 1;
1103538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1104538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1105538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (*read + sum > block)
1106538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1107538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1108538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  /* last frame is the remainder of the block */
1109538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  sizes[i] = block - *read - sum;
1110538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
1111538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1112538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1113538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
1114538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_ebml_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
1115538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1116538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
1117538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t lace, sum, length;
1118538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int64_t slace;
1119538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t i = 0;
1120538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1121538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_vint(io, &lace, &length);
1122538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
1123538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
1124538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *read += length;
1125538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1126538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  sizes[i] = lace;
1127538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  sum = sizes[i];
1128538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1129538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  i += 1;
1130538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  n -= 1;
1131538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1132538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (--n) {
1133538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_svint(io, &slace, &length);
1134538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
1135538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
1136538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *read += length;
1137538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    sizes[i] = sizes[i - 1] + slace;
1138538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    sum += sizes[i];
1139538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    i += 1;
1140538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1141538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1142538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (*read + sum > block)
1143538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1144538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1145538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  /* last frame is the remainder of the block */
1146538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  sizes[i] = block - *read - sum;
1147538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
1148538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1149538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1150538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic uint64_t
1151538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_get_timecode_scale(nestegg * ctx)
1152538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1153538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t scale;
1154538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1155538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_uint(ctx->segment.info.timecode_scale, &scale) != 0)
1156538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    scale = 1000000;
1157538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1158538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return scale;
1159538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1160538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1161538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct track_entry *
1162538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_find_track_entry(nestegg * ctx, unsigned int track)
1163538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1164538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list_node * node;
1165538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned int tracks = 0;
1166538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1167538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  node = ctx->segment.tracks.track_entry.head;
1168538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (node) {
1169538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    assert(node->id == ID_TRACK_ENTRY);
1170538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (track == tracks)
1171538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return node->data;
1172538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    tracks += 1;
1173538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    node = node->next;
1174538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1175538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1176538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return NULL;
1177538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1178538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1179538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
1180538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_read_block(nestegg * ctx, uint64_t block_id, uint64_t block_size, nestegg_packet ** data)
1181538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1182538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
1183538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int64_t timecode, abs_timecode;
1184538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  nestegg_packet * pkt;
1185538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct cluster * cluster;
1186538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct frame * f, * last;
1187538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct track_entry * entry;
1188538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  double track_scale;
1189538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t track, length, frame_sizes[256], cluster_tc, flags, frames, tc_scale, total;
1190538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned int i, lacing;
1191538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  size_t consumed = 0;
1192538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1193538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *data = NULL;
1194538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1195538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (block_size > LIMIT_BLOCK)
1196538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1197538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1198538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_vint(ctx->io, &track, &length);
1199538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
1200538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
1201538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1202538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (track == 0 || track > ctx->track_count)
1203538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1204538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1205538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  consumed += length;
1206538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1207538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_int(ctx->io, &timecode, 2);
1208538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
1209538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
1210538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1211538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  consumed += 2;
1212538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1213538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_read_uint(ctx->io, &flags, 1);
1214538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
1215538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return r;
1216538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1217538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  consumed += 1;
1218538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1219538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  frames = 0;
1220538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1221538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  /* flags are different between block and simpleblock, but lacing is
1222538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber     encoded the same way */
1223538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  lacing = (flags & BLOCK_FLAGS_LACING) >> 1;
1224538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1225538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  switch (lacing) {
1226538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case LACING_NONE:
1227538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    frames = 1;
1228538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
1229538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case LACING_XIPH:
1230538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case LACING_FIXED:
1231538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case LACING_EBML:
1232538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_uint(ctx->io, &frames, 1);
1233538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
1234538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
1235538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    consumed += 1;
1236538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    frames += 1;
1237538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1238538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1239538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (frames > 256)
1240538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1241538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1242538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  switch (lacing) {
1243538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case LACING_NONE:
1244538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    frame_sizes[0] = block_size - consumed;
1245538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
1246538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case LACING_XIPH:
1247538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (frames == 1)
1248538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1249538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_xiph_lacing(ctx->io, block_size, &consumed, frames, frame_sizes);
1250538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
1251538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
1252538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
1253538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case LACING_FIXED:
1254538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if ((block_size - consumed) % frames)
1255538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1256538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    for (i = 0; i < frames; ++i)
1257538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      frame_sizes[i] = (block_size - consumed) / frames;
1258538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
1259538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  case LACING_EBML:
1260538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (frames == 1)
1261538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1262538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_ebml_lacing(ctx->io, block_size, &consumed, frames, frame_sizes);
1263538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
1264538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
1265538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    break;
1266538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1267538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1268538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  /* sanity check unlaced frame sizes against total block size. */
1269538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  total = consumed;
1270538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  for (i = 0; i < frames; ++i)
1271538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    total += frame_sizes[i];
1272538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (total > block_size)
1273538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1274538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1275538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  entry = ne_find_track_entry(ctx, track - 1);
1276538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!entry)
1277538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1278538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1279538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  track_scale = 1.0;
1280538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1281538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  tc_scale = ne_get_timecode_scale(ctx);
1282538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1283538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  assert(ctx->segment.cluster.tail->id == ID_CLUSTER);
1284538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  cluster = ctx->segment.cluster.tail->data;
1285538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_uint(cluster->timecode, &cluster_tc) != 0)
1286538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1287538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1288538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  abs_timecode = timecode + cluster_tc;
1289538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (abs_timecode < 0)
1290538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1291538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1292538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  pkt = ne_alloc(sizeof(*pkt));
1293538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  pkt->track = track - 1;
1294538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  pkt->timecode = abs_timecode * tc_scale * track_scale;
1295538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1296538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log(ctx, NESTEGG_LOG_DEBUG, "%sblock t %lld pts %f f %llx frames: %llu",
1297538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber           block_id == ID_BLOCK ? "" : "simple", pkt->track, pkt->timecode / 1e9, flags, frames);
1298538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1299538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  last = NULL;
1300538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  for (i = 0; i < frames; ++i) {
1301538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (frame_sizes[i] > LIMIT_FRAME) {
1302538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      nestegg_free_packet(pkt);
1303538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1304538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    }
1305538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    f = ne_alloc(sizeof(*f));
1306538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    f->data = ne_alloc(frame_sizes[i]);
1307538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    f->length = frame_sizes[i];
1308538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_io_read(ctx->io, f->data, frame_sizes[i]);
1309538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1) {
1310538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      free(f->data);
1311538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      free(f);
1312538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      nestegg_free_packet(pkt);
1313538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1314538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    }
1315538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1316538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (!last)
1317538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      pkt->frame = f;
1318538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    else
1319538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      last->next = f;
1320538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    last = f;
1321538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1322538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1323538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *data = pkt;
1324538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1325538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
1326538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1327538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1328538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic uint64_t
1329538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_buf_read_id(unsigned char const * p, size_t length)
1330538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1331538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t id = 0;
1332538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1333538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (length--) {
1334538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    id <<= 8;
1335538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    id |= *p++;
1336538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1337538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1338538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return id;
1339538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1340538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1341538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct seek *
1342538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_find_seek_for_id(struct ebml_list_node * seek_head, uint64_t id)
1343538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1344538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list * head;
1345538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list_node * seek;
1346538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_binary binary_id;
1347538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct seek * s;
1348538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1349538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (seek_head) {
1350538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    assert(seek_head->id == ID_SEEK_HEAD);
1351538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    head = seek_head->data;
1352538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    seek = head->head;
1353538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1354538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    while (seek) {
1355538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      assert(seek->id == ID_SEEK);
1356538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      s = seek->data;
1357538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1358538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (ne_get_binary(s->id, &binary_id) == 0 &&
1359538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber          ne_buf_read_id(binary_id.data, binary_id.length) == id)
1360538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        return s;
1361538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1362538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      seek = seek->next;
1363538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    }
1364538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1365538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    seek_head = seek_head->next;
1366538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1367538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1368538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return NULL;
1369538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1370538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1371538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic struct cue_point *
1372538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_find_cue_point_for_tstamp(struct ebml_list_node * cue_point, uint64_t scale, uint64_t tstamp)
1373538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1374538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t time;
1375538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct cue_point * c, * prev = NULL;
1376538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1377538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (cue_point) {
1378538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    assert(cue_point->id == ID_CUE_POINT);
1379538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    c = cue_point->data;
1380538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1381538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (!prev)
1382538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      prev = c;
1383538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1384538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (ne_get_uint(c->time, &time) == 0 && time * scale > tstamp)
1385538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      break;
1386538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1387538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    prev = cue_point->data;
1388538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    cue_point = cue_point->next;
1389538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1390538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1391538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return prev;
1392538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1393538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1394538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic int
1395538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_is_suspend_element(uint64_t id)
1396538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1397538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  /* this could search the tree of elements for DESC_FLAG_SUSPEND */
1398538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (id == ID_SIMPLE_BLOCK || id == ID_BLOCK)
1399538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return 1;
1400538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1401538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1402538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1403538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberstatic void
1404538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberne_null_log_callback(nestegg * ctx, unsigned int severity, char const * fmt, ...)
1405538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1406538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ctx && severity && fmt)
1407538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return;
1408538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1409538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1410538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1411538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_init(nestegg ** context, nestegg_io io, nestegg_log callback)
1412538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1413538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
1414538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t id, version, docversion;
1415538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list_node * track;
1416538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  char * doctype;
1417538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  nestegg * ctx = NULL;
1418538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1419538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!(io.read && io.seek && io.tell))
1420538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1421538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1422538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx = ne_alloc(sizeof(*ctx));
1423538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1424538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->io = ne_alloc(sizeof(*ctx->io));
1425538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *ctx->io = io;
1426538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log = callback;
1427538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->alloc_pool = ne_pool_init();
1428538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1429538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!ctx->log)
1430538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    ctx->log = ne_null_log_callback;
1431538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1432538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_peek_element(ctx, &id, NULL);
1433538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1) {
1434538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    nestegg_destroy(ctx);
1435538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1436538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1437538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1438538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (id != ID_EBML) {
1439538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    nestegg_destroy(ctx);
1440538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1441538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1442538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1443538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log(ctx, NESTEGG_LOG_DEBUG, "ctx %p", ctx);
1444538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1445538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_ctx_push(ctx, ne_top_level_elements, ctx);
1446538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1447538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_parse(ctx, NULL);
1448538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1449538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1) {
1450538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    nestegg_destroy(ctx);
1451538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1452538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1453538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1454538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_uint(ctx->ebml.ebml_read_version, &version) != 0)
1455538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    version = 1;
1456538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (version != 1) {
1457538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    nestegg_destroy(ctx);
1458538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1459538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1460538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1461538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_string(ctx->ebml.doctype, &doctype) != 0)
1462538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    doctype = "matroska";
1463538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (strcmp(doctype, "webm") != 0) {
1464538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    nestegg_destroy(ctx);
1465538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1466538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1467538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1468538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_uint(ctx->ebml.doctype_read_version, &docversion) != 0)
1469538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    docversion = 1;
1470538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (docversion < 1 || docversion > 2) {
1471538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    nestegg_destroy(ctx);
1472538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1473538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1474538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1475538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!ctx->segment.tracks.track_entry.head) {
1476538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    nestegg_destroy(ctx);
1477538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1478538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1479538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1480538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  track = ctx->segment.tracks.track_entry.head;
1481538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->track_count = 0;
1482538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1483538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (track) {
1484538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    ctx->track_count += 1;
1485538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    track = track->next;
1486538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1487538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1488538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *context = ctx;
1489538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1490538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1491538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1492538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1493538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubervoid
1494538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_destroy(nestegg * ctx)
1495538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1496538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (ctx->ancestor)
1497538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    ne_ctx_pop(ctx);
1498538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_pool_destroy(ctx->alloc_pool);
1499538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  free(ctx->io);
1500538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  free(ctx);
1501538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1502538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1503538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1504538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_duration(nestegg * ctx, uint64_t * duration)
1505538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1506538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t tc_scale;
1507538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  double unscaled_duration;
1508538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1509538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_float(ctx->segment.info.duration, &unscaled_duration) != 0)
1510538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1511538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1512538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  tc_scale = ne_get_timecode_scale(ctx);
1513538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1514538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *duration = (uint64_t) (unscaled_duration * tc_scale);
1515538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1516538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1517538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1518538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1519538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_tstamp_scale(nestegg * ctx, uint64_t * scale)
1520538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1521538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *scale = ne_get_timecode_scale(ctx);
1522538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1523538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1524538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1525538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1526538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_track_count(nestegg * ctx, unsigned int * tracks)
1527538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1528538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *tracks = ctx->track_count;
1529538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1530538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1531538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1532538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1533538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_track_seek(nestegg * ctx, unsigned int track, uint64_t tstamp)
1534538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1535538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
1536538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct cue_point * cue_point;
1537538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct cue_track_positions * pos;
1538538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct saved_state state;
1539538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct seek * found;
1540538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t seek_pos, tc_scale, t, id;
1541538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_list_node * node = ctx->segment.cues.cue_point.head;
1542538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1543538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  /* If there are no cues loaded, check for cues element in the seek head
1544538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber     and load it. */
1545538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!node) {
1546538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    found = ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES);
1547538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (!found)
1548538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1549538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1550538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (ne_get_uint(found->position, &seek_pos) != 0)
1551538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1552538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1553538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    /* Save old parser state. */
1554538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_ctx_save(ctx, &state);
1555538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 0)
1556538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1557538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1558538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    /* Seek and set up parser state for segment-level element (Cues). */
1559538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_io_seek(ctx->io, ctx->segment_offset + seek_pos, NESTEGG_SEEK_SET);
1560538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 0)
1561538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1562538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    ctx->last_id = 0;
1563538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    ctx->last_size = 0;
1564538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1565538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_read_element(ctx, &id, NULL);
1566538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
1567538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1568538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1569538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (id != ID_CUES)
1570538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1571538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1572538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    ctx->ancestor = NULL;
1573538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    ne_ctx_push(ctx, ne_top_level_elements, ctx);
1574538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    ne_ctx_push(ctx, ne_segment_elements, &ctx->segment);
1575538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    ne_ctx_push(ctx, ne_cues_elements, &ctx->segment.cues);
1576538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    /* parser will run until end of cues element. */
1577538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    ctx->log(ctx, NESTEGG_LOG_DEBUG, "seek: parsing cue elements");
1578538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_parse(ctx, ne_cues_elements);
1579538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    while (ctx->ancestor)
1580538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      ne_ctx_pop(ctx);
1581538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1582538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    /* Reset parser state to original state and seek back to old position. */
1583538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (ne_ctx_restore(ctx, &state) != 0)
1584538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1585538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1586538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r < 0)
1587538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1588538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1589538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1590538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  tc_scale = ne_get_timecode_scale(ctx);
1591538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1592538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  cue_point = ne_find_cue_point_for_tstamp(ctx->segment.cues.cue_point.head, tc_scale, tstamp);
1593538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!cue_point)
1594538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1595538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1596538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  node = cue_point->cue_track_positions.head;
1597538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1598538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  seek_pos = 0;
1599538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1600538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (node) {
1601538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    assert(node->id == ID_CUE_TRACK_POSITIONS);
1602538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    pos = node->data;
1603538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (ne_get_uint(pos->track, &t) == 0 && t - 1 == track) {
1604538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (ne_get_uint(pos->cluster_position, &seek_pos) != 0)
1605538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        return -1;
1606538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      break;
1607538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    }
1608538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    node = node->next;
1609538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1610538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1611538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  /* Seek and set up parser state for segment-level element (Cluster). */
1612538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_io_seek(ctx->io, ctx->segment_offset + seek_pos, NESTEGG_SEEK_SET);
1613538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 0)
1614538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1615538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->last_id = 0;
1616538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->last_size = 0;
1617538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1618538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (ctx->ancestor)
1619538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    ne_ctx_pop(ctx);
1620538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1621538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_ctx_push(ctx, ne_top_level_elements, ctx);
1622538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_ctx_push(ctx, ne_segment_elements, &ctx->segment);
1623538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ctx->log(ctx, NESTEGG_LOG_DEBUG, "seek: parsing cluster elements");
1624538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  r = ne_parse(ctx, NULL);
1625538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (r != 1)
1626538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1627538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1628538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!ne_is_suspend_element(ctx->last_id))
1629538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1630538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1631538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1632538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1633538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1634538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1635538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_track_type(nestegg * ctx, unsigned int track)
1636538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1637538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct track_entry * entry;
1638538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t type;
1639538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1640538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  entry = ne_find_track_entry(ctx, track);
1641538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!entry)
1642538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1643538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1644538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_uint(entry->type, &type) != 0)
1645538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1646538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1647538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (type & TRACK_TYPE_VIDEO)
1648538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return NESTEGG_TRACK_VIDEO;
1649538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1650538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (type & TRACK_TYPE_AUDIO)
1651538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return NESTEGG_TRACK_AUDIO;
1652538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1653538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return -1;
1654538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1655538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1656538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1657538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_track_codec_id(nestegg * ctx, unsigned int track)
1658538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1659538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  char * codec_id;
1660538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct track_entry * entry;
1661538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1662538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  entry = ne_find_track_entry(ctx, track);
1663538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!entry)
1664538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1665538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1666538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_string(entry->codec_id, &codec_id) != 0)
1667538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1668538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1669538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (strcmp(codec_id, TRACK_ID_VP8) == 0)
1670538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return NESTEGG_CODEC_VP8;
1671538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1672538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (strcmp(codec_id, TRACK_ID_VORBIS) == 0)
1673538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return NESTEGG_CODEC_VORBIS;
1674538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1675538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return -1;
1676538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1677538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1678538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1679538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_track_codec_data_count(nestegg * ctx, unsigned int track,
1680538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber                               unsigned int * count)
1681538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1682538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct track_entry * entry;
1683538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_binary codec_private;
1684538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char * p;
1685538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1686538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *count = 0;
1687538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1688538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  entry = ne_find_track_entry(ctx, track);
1689538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!entry)
1690538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1691538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1692538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS)
1693538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1694538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1695538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_binary(entry->codec_private, &codec_private) != 0)
1696538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1697538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1698538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (codec_private.length < 1)
1699538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1700538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1701538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  p = codec_private.data;
1702538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *count = *p + 1;
1703538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1704538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (*count > 3)
1705538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1706538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1707538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1708538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1709538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1710538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1711538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_track_codec_data(nestegg * ctx, unsigned int track, unsigned int item,
1712538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber                         unsigned char ** data, size_t * length)
1713538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1714538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct track_entry * entry;
1715538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct ebml_binary codec_private;
1716538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t sizes[3], total;
1717538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned char * p;
1718538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned int count, i;
1719538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1720538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *data = NULL;
1721538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *length = 0;
1722538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1723538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  entry = ne_find_track_entry(ctx, track);
1724538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!entry)
1725538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1726538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1727538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS)
1728538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1729538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1730538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_binary(entry->codec_private, &codec_private) != 0)
1731538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1732538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1733538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  p = codec_private.data;
1734538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  count = *p++ + 1;
1735538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1736538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (count > 3)
1737538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1738538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1739538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  i = 0;
1740538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  total = 0;
1741538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (--count) {
1742538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    sizes[i] = ne_xiph_lace_value(&p);
1743538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    total += sizes[i];
1744538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    i += 1;
1745538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1746538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  sizes[i] = codec_private.length - total - (p - codec_private.data);
1747538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1748538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  for (i = 0; i < item; ++i) {
1749538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (sizes[i] > LIMIT_FRAME)
1750538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return -1;
1751538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    p += sizes[i];
1752538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1753538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *data = p;
1754538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *length = sizes[item];
1755538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1756538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1757538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1758538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1759538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1760538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_track_video_params(nestegg * ctx, unsigned int track,
1761538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber                           nestegg_video_params * params)
1762538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1763538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct track_entry * entry;
1764538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t value;
1765538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1766538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  memset(params, 0, sizeof(*params));
1767538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1768538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  entry = ne_find_track_entry(ctx, track);
1769538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!entry)
1770538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1771538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1772538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_VIDEO)
1773538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1774538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1775538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_uint(entry->video.pixel_width, &value) != 0)
1776538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1777538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  params->width = value;
1778538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1779538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (ne_get_uint(entry->video.pixel_height, &value) != 0)
1780538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1781538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  params->height = value;
1782538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1783538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = 0;
1784538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_get_uint(entry->video.pixel_crop_bottom, &value);
1785538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  params->crop_bottom = value;
1786538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1787538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = 0;
1788538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_get_uint(entry->video.pixel_crop_top, &value);
1789538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  params->crop_top = value;
1790538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1791538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = 0;
1792538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_get_uint(entry->video.pixel_crop_left, &value);
1793538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  params->crop_left = value;
1794538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1795538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = 0;
1796538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_get_uint(entry->video.pixel_crop_right, &value);
1797538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  params->crop_right = value;
1798538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1799538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = params->width;
1800538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_get_uint(entry->video.display_width, &value);
1801538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  params->display_width = value;
1802538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1803538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = params->height;
1804538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_get_uint(entry->video.display_height, &value);
1805538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  params->display_height = value;
1806538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1807538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1808538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1809538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1810538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1811538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_track_audio_params(nestegg * ctx, unsigned int track,
1812538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber                           nestegg_audio_params * params)
1813538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1814538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct track_entry * entry;
1815538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t value;
1816538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1817538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  memset(params, 0, sizeof(*params));
1818538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1819538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  entry = ne_find_track_entry(ctx, track);
1820538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (!entry)
1821538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1822538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1823538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_AUDIO)
1824538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    return -1;
1825538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1826538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  params->rate = 8000;
1827538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_get_float(entry->audio.sampling_frequency, &params->rate);
1828538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1829538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = 1;
1830538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_get_uint(entry->audio.channels, &value);
1831538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  params->channels = value;
1832538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1833538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  value = 16;
1834538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  ne_get_uint(entry->audio.bit_depth, &value);
1835538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  params->depth = value;
1836538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1837538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1838538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1839538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1840538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1841538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_read_packet(nestegg * ctx, nestegg_packet ** pkt)
1842538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1843538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  int r;
1844538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  uint64_t id, size;
1845538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1846538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *pkt = NULL;
1847538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1848538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  for (;;) {
1849538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r = ne_peek_element(ctx, &id, &size);
1850538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
1851538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
1852538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1853538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    /* any suspend fields must be handled here */
1854538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (ne_is_suspend_element(id)) {
1855538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      r = ne_read_element(ctx, &id, &size);
1856538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      if (r != 1)
1857538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber        return r;
1858538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1859538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      /* the only suspend fields are blocks and simple blocks, which we
1860538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber         handle directly. */
1861538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      r = ne_read_block(ctx, id, size, pkt);
1862538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
1863538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    }
1864538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1865538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    r =  ne_parse(ctx, NULL);
1866538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (r != 1)
1867538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return r;
1868538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1869538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1870538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 1;
1871538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1872538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1873538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubervoid
1874538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_free_packet(nestegg_packet * pkt)
1875538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1876538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct frame * frame;
1877538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1878538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (pkt->frame) {
1879538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    frame = pkt->frame;
1880538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    pkt->frame = frame->next;
1881538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    free(frame->data);
1882538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    free(frame);
1883538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1884538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1885538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber free(pkt);
1886538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1887538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1888538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1889538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_packet_track(nestegg_packet * pkt, unsigned int * track)
1890538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1891538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *track = pkt->track;
1892538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1893538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1894538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1895538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1896538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_packet_tstamp(nestegg_packet * pkt, uint64_t * tstamp)
1897538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1898538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *tstamp = pkt->timecode;
1899538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1900538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1901538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1902538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1903538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_packet_count(nestegg_packet * pkt, unsigned int * count)
1904538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1905538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct frame * f = pkt->frame;
1906538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1907538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *count = 0;
1908538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1909538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (f) {
1910538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    *count += 1;
1911538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    f = f->next;
1912538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1913538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1914538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return 0;
1915538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1916538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1917538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huberint
1918538f6170b788de7408b06efc6613dc98579aa6a6Andreas Hubernestegg_packet_data(nestegg_packet * pkt, unsigned int item,
1919538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber                    unsigned char ** data, size_t * length)
1920538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber{
1921538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  struct frame * f = pkt->frame;
1922538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  unsigned int count = 0;
1923538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1924538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *data = NULL;
1925538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  *length = 0;
1926538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1927538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  while (f) {
1928538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    if (count == item) {
1929538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      *data = f->data;
1930538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      *length = f->length;
1931538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber      return 0;
1932538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    }
1933538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    count += 1;
1934538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber    f = f->next;
1935538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  }
1936538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber
1937538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber  return -1;
1938538f6170b788de7408b06efc6613dc98579aa6a6Andreas Huber}
1939