1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/media/libnestegg/src/nestegg.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2418 @@ 1.4 +/* 1.5 + * Copyright © 2010 Mozilla Foundation 1.6 + * 1.7 + * This program is made available under an ISC-style license. See the 1.8 + * accompanying file LICENSE for details. 1.9 + */ 1.10 +#include <assert.h> 1.11 +#include <stdlib.h> 1.12 +#include <string.h> 1.13 + 1.14 +#include "halloc.h" 1.15 +#include "nestegg/nestegg.h" 1.16 + 1.17 +/* EBML Elements */ 1.18 +#define ID_EBML 0x1a45dfa3 1.19 +#define ID_EBML_VERSION 0x4286 1.20 +#define ID_EBML_READ_VERSION 0x42f7 1.21 +#define ID_EBML_MAX_ID_LENGTH 0x42f2 1.22 +#define ID_EBML_MAX_SIZE_LENGTH 0x42f3 1.23 +#define ID_DOCTYPE 0x4282 1.24 +#define ID_DOCTYPE_VERSION 0x4287 1.25 +#define ID_DOCTYPE_READ_VERSION 0x4285 1.26 + 1.27 +/* Global Elements */ 1.28 +#define ID_VOID 0xec 1.29 +#define ID_CRC32 0xbf 1.30 + 1.31 +/* WebM Elements */ 1.32 +#define ID_SEGMENT 0x18538067 1.33 + 1.34 +/* Seek Head Elements */ 1.35 +#define ID_SEEK_HEAD 0x114d9b74 1.36 +#define ID_SEEK 0x4dbb 1.37 +#define ID_SEEK_ID 0x53ab 1.38 +#define ID_SEEK_POSITION 0x53ac 1.39 + 1.40 +/* Info Elements */ 1.41 +#define ID_INFO 0x1549a966 1.42 +#define ID_TIMECODE_SCALE 0x2ad7b1 1.43 +#define ID_DURATION 0x4489 1.44 + 1.45 +/* Cluster Elements */ 1.46 +#define ID_CLUSTER 0x1f43b675 1.47 +#define ID_TIMECODE 0xe7 1.48 +#define ID_BLOCK_GROUP 0xa0 1.49 +#define ID_SIMPLE_BLOCK 0xa3 1.50 + 1.51 +/* BlockGroup Elements */ 1.52 +#define ID_BLOCK 0xa1 1.53 +#define ID_BLOCK_DURATION 0x9b 1.54 +#define ID_REFERENCE_BLOCK 0xfb 1.55 +#define ID_DISCARD_PADDING 0x75a2 1.56 + 1.57 +/* Tracks Elements */ 1.58 +#define ID_TRACKS 0x1654ae6b 1.59 +#define ID_TRACK_ENTRY 0xae 1.60 +#define ID_TRACK_NUMBER 0xd7 1.61 +#define ID_TRACK_UID 0x73c5 1.62 +#define ID_TRACK_TYPE 0x83 1.63 +#define ID_FLAG_ENABLED 0xb9 1.64 +#define ID_FLAG_DEFAULT 0x88 1.65 +#define ID_FLAG_LACING 0x9c 1.66 +#define ID_TRACK_TIMECODE_SCALE 0x23314f 1.67 +#define ID_LANGUAGE 0x22b59c 1.68 +#define ID_CODEC_ID 0x86 1.69 +#define ID_CODEC_PRIVATE 0x63a2 1.70 +#define ID_CODEC_DELAY 0x56aa 1.71 +#define ID_SEEK_PREROLL 0x56bb 1.72 +#define ID_DEFAULT_DURATION 0x23e383 1.73 + 1.74 +/* Video Elements */ 1.75 +#define ID_VIDEO 0xe0 1.76 +#define ID_STEREO_MODE 0x53b8 1.77 +#define ID_PIXEL_WIDTH 0xb0 1.78 +#define ID_PIXEL_HEIGHT 0xba 1.79 +#define ID_PIXEL_CROP_BOTTOM 0x54aa 1.80 +#define ID_PIXEL_CROP_TOP 0x54bb 1.81 +#define ID_PIXEL_CROP_LEFT 0x54cc 1.82 +#define ID_PIXEL_CROP_RIGHT 0x54dd 1.83 +#define ID_DISPLAY_WIDTH 0x54b0 1.84 +#define ID_DISPLAY_HEIGHT 0x54ba 1.85 + 1.86 +/* Audio Elements */ 1.87 +#define ID_AUDIO 0xe1 1.88 +#define ID_SAMPLING_FREQUENCY 0xb5 1.89 +#define ID_CHANNELS 0x9f 1.90 +#define ID_BIT_DEPTH 0x6264 1.91 + 1.92 +/* Cues Elements */ 1.93 +#define ID_CUES 0x1c53bb6b 1.94 +#define ID_CUE_POINT 0xbb 1.95 +#define ID_CUE_TIME 0xb3 1.96 +#define ID_CUE_TRACK_POSITIONS 0xb7 1.97 +#define ID_CUE_TRACK 0xf7 1.98 +#define ID_CUE_CLUSTER_POSITION 0xf1 1.99 +#define ID_CUE_BLOCK_NUMBER 0x5378 1.100 + 1.101 +/* EBML Types */ 1.102 +enum ebml_type_enum { 1.103 + TYPE_UNKNOWN, 1.104 + TYPE_MASTER, 1.105 + TYPE_UINT, 1.106 + TYPE_FLOAT, 1.107 + TYPE_INT, 1.108 + TYPE_STRING, 1.109 + TYPE_BINARY 1.110 +}; 1.111 + 1.112 +#define LIMIT_STRING (1 << 20) 1.113 +#define LIMIT_BINARY (1 << 24) 1.114 +#define LIMIT_BLOCK (1 << 30) 1.115 +#define LIMIT_FRAME (1 << 28) 1.116 + 1.117 +/* Field Flags */ 1.118 +#define DESC_FLAG_NONE 0 1.119 +#define DESC_FLAG_MULTI (1 << 0) 1.120 +#define DESC_FLAG_SUSPEND (1 << 1) 1.121 +#define DESC_FLAG_OFFSET (1 << 2) 1.122 + 1.123 +/* Block Header Flags */ 1.124 +#define BLOCK_FLAGS_LACING 6 1.125 + 1.126 +/* Lacing Constants */ 1.127 +#define LACING_NONE 0 1.128 +#define LACING_XIPH 1 1.129 +#define LACING_FIXED 2 1.130 +#define LACING_EBML 3 1.131 + 1.132 +/* Track Types */ 1.133 +#define TRACK_TYPE_VIDEO 1 1.134 +#define TRACK_TYPE_AUDIO 2 1.135 + 1.136 +/* Track IDs */ 1.137 +#define TRACK_ID_VP8 "V_VP8" 1.138 +#define TRACK_ID_VP9 "V_VP9" 1.139 +#define TRACK_ID_VORBIS "A_VORBIS" 1.140 +#define TRACK_ID_OPUS "A_OPUS" 1.141 + 1.142 +enum vint_mask { 1.143 + MASK_NONE, 1.144 + MASK_FIRST_BIT 1.145 +}; 1.146 + 1.147 +struct ebml_binary { 1.148 + unsigned char * data; 1.149 + size_t length; 1.150 +}; 1.151 + 1.152 +struct ebml_list_node { 1.153 + struct ebml_list_node * next; 1.154 + uint64_t id; 1.155 + void * data; 1.156 +}; 1.157 + 1.158 +struct ebml_list { 1.159 + struct ebml_list_node * head; 1.160 + struct ebml_list_node * tail; 1.161 +}; 1.162 + 1.163 +struct ebml_type { 1.164 + union ebml_value { 1.165 + uint64_t u; 1.166 + double f; 1.167 + int64_t i; 1.168 + char * s; 1.169 + struct ebml_binary b; 1.170 + } v; 1.171 + enum ebml_type_enum type; 1.172 + int read; 1.173 +}; 1.174 + 1.175 +/* EBML Definitions */ 1.176 +struct ebml { 1.177 + struct ebml_type ebml_version; 1.178 + struct ebml_type ebml_read_version; 1.179 + struct ebml_type ebml_max_id_length; 1.180 + struct ebml_type ebml_max_size_length; 1.181 + struct ebml_type doctype; 1.182 + struct ebml_type doctype_version; 1.183 + struct ebml_type doctype_read_version; 1.184 +}; 1.185 + 1.186 +/* Matroksa Definitions */ 1.187 +struct seek { 1.188 + struct ebml_type id; 1.189 + struct ebml_type position; 1.190 +}; 1.191 + 1.192 +struct seek_head { 1.193 + struct ebml_list seek; 1.194 +}; 1.195 + 1.196 +struct info { 1.197 + struct ebml_type timecode_scale; 1.198 + struct ebml_type duration; 1.199 +}; 1.200 + 1.201 +struct block_group { 1.202 + struct ebml_type duration; 1.203 + struct ebml_type reference_block; 1.204 + struct ebml_type discard_padding; 1.205 +}; 1.206 + 1.207 +struct cluster { 1.208 + struct ebml_type timecode; 1.209 + struct ebml_list block_group; 1.210 +}; 1.211 + 1.212 +struct video { 1.213 + struct ebml_type stereo_mode; 1.214 + struct ebml_type pixel_width; 1.215 + struct ebml_type pixel_height; 1.216 + struct ebml_type pixel_crop_bottom; 1.217 + struct ebml_type pixel_crop_top; 1.218 + struct ebml_type pixel_crop_left; 1.219 + struct ebml_type pixel_crop_right; 1.220 + struct ebml_type display_width; 1.221 + struct ebml_type display_height; 1.222 +}; 1.223 + 1.224 +struct audio { 1.225 + struct ebml_type sampling_frequency; 1.226 + struct ebml_type channels; 1.227 + struct ebml_type bit_depth; 1.228 +}; 1.229 + 1.230 +struct track_entry { 1.231 + struct ebml_type number; 1.232 + struct ebml_type uid; 1.233 + struct ebml_type type; 1.234 + struct ebml_type flag_enabled; 1.235 + struct ebml_type flag_default; 1.236 + struct ebml_type flag_lacing; 1.237 + struct ebml_type track_timecode_scale; 1.238 + struct ebml_type language; 1.239 + struct ebml_type codec_id; 1.240 + struct ebml_type codec_private; 1.241 + struct ebml_type codec_delay; 1.242 + struct ebml_type seek_preroll; 1.243 + struct ebml_type default_duration; 1.244 + struct video video; 1.245 + struct audio audio; 1.246 +}; 1.247 + 1.248 +struct tracks { 1.249 + struct ebml_list track_entry; 1.250 +}; 1.251 + 1.252 +struct cue_track_positions { 1.253 + struct ebml_type track; 1.254 + struct ebml_type cluster_position; 1.255 + struct ebml_type block_number; 1.256 +}; 1.257 + 1.258 +struct cue_point { 1.259 + struct ebml_type time; 1.260 + struct ebml_list cue_track_positions; 1.261 +}; 1.262 + 1.263 +struct cues { 1.264 + struct ebml_list cue_point; 1.265 +}; 1.266 + 1.267 +struct segment { 1.268 + struct ebml_list seek_head; 1.269 + struct info info; 1.270 + struct ebml_list cluster; 1.271 + struct tracks tracks; 1.272 + struct cues cues; 1.273 +}; 1.274 + 1.275 +/* Misc. */ 1.276 +struct pool_ctx { 1.277 + char dummy; 1.278 +}; 1.279 + 1.280 +struct list_node { 1.281 + struct list_node * previous; 1.282 + struct ebml_element_desc * node; 1.283 + unsigned char * data; 1.284 +}; 1.285 + 1.286 +struct saved_state { 1.287 + int64_t stream_offset; 1.288 + struct list_node * ancestor; 1.289 + uint64_t last_id; 1.290 + uint64_t last_size; 1.291 + int last_valid; 1.292 +}; 1.293 + 1.294 +struct frame { 1.295 + unsigned char * data; 1.296 + size_t length; 1.297 + struct frame * next; 1.298 +}; 1.299 + 1.300 +/* Public (opaque) Structures */ 1.301 +struct nestegg { 1.302 + nestegg_io * io; 1.303 + nestegg_log log; 1.304 + struct pool_ctx * alloc_pool; 1.305 + uint64_t last_id; 1.306 + uint64_t last_size; 1.307 + int last_valid; 1.308 + struct list_node * ancestor; 1.309 + struct ebml ebml; 1.310 + struct segment segment; 1.311 + int64_t segment_offset; 1.312 + unsigned int track_count; 1.313 +}; 1.314 + 1.315 +struct nestegg_packet { 1.316 + uint64_t track; 1.317 + uint64_t timecode; 1.318 + uint64_t duration; 1.319 + struct frame * frame; 1.320 + int64_t discard_padding; 1.321 +}; 1.322 + 1.323 +/* Element Descriptor */ 1.324 +struct ebml_element_desc { 1.325 + char const * name; 1.326 + uint64_t id; 1.327 + enum ebml_type_enum type; 1.328 + size_t offset; 1.329 + unsigned int flags; 1.330 + struct ebml_element_desc * children; 1.331 + size_t size; 1.332 + size_t data_offset; 1.333 +}; 1.334 + 1.335 +#define E_FIELD(ID, TYPE, STRUCT, FIELD) \ 1.336 + { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_NONE, NULL, 0, 0 } 1.337 +#define E_MASTER(ID, TYPE, STRUCT, FIELD) \ 1.338 + { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_MULTI, ne_ ## FIELD ## _elements, \ 1.339 + sizeof(struct FIELD), 0 } 1.340 +#define E_SINGLE_MASTER_O(ID, TYPE, STRUCT, FIELD) \ 1.341 + { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_OFFSET, ne_ ## FIELD ## _elements, 0, \ 1.342 + offsetof(STRUCT, FIELD ## _offset) } 1.343 +#define E_SINGLE_MASTER(ID, TYPE, STRUCT, FIELD) \ 1.344 + { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_NONE, ne_ ## FIELD ## _elements, 0, 0 } 1.345 +#define E_SUSPEND(ID, TYPE) \ 1.346 + { #ID, ID, TYPE, 0, DESC_FLAG_SUSPEND, NULL, 0, 0 } 1.347 +#define E_LAST \ 1.348 + { NULL, 0, 0, 0, DESC_FLAG_NONE, NULL, 0, 0 } 1.349 + 1.350 +/* EBML Element Lists */ 1.351 +static struct ebml_element_desc ne_ebml_elements[] = { 1.352 + E_FIELD(ID_EBML_VERSION, TYPE_UINT, struct ebml, ebml_version), 1.353 + E_FIELD(ID_EBML_READ_VERSION, TYPE_UINT, struct ebml, ebml_read_version), 1.354 + E_FIELD(ID_EBML_MAX_ID_LENGTH, TYPE_UINT, struct ebml, ebml_max_id_length), 1.355 + E_FIELD(ID_EBML_MAX_SIZE_LENGTH, TYPE_UINT, struct ebml, ebml_max_size_length), 1.356 + E_FIELD(ID_DOCTYPE, TYPE_STRING, struct ebml, doctype), 1.357 + E_FIELD(ID_DOCTYPE_VERSION, TYPE_UINT, struct ebml, doctype_version), 1.358 + E_FIELD(ID_DOCTYPE_READ_VERSION, TYPE_UINT, struct ebml, doctype_read_version), 1.359 + E_LAST 1.360 +}; 1.361 + 1.362 +/* WebM Element Lists */ 1.363 +static struct ebml_element_desc ne_seek_elements[] = { 1.364 + E_FIELD(ID_SEEK_ID, TYPE_BINARY, struct seek, id), 1.365 + E_FIELD(ID_SEEK_POSITION, TYPE_UINT, struct seek, position), 1.366 + E_LAST 1.367 +}; 1.368 + 1.369 +static struct ebml_element_desc ne_seek_head_elements[] = { 1.370 + E_MASTER(ID_SEEK, TYPE_MASTER, struct seek_head, seek), 1.371 + E_LAST 1.372 +}; 1.373 + 1.374 +static struct ebml_element_desc ne_info_elements[] = { 1.375 + E_FIELD(ID_TIMECODE_SCALE, TYPE_UINT, struct info, timecode_scale), 1.376 + E_FIELD(ID_DURATION, TYPE_FLOAT, struct info, duration), 1.377 + E_LAST 1.378 +}; 1.379 + 1.380 +static struct ebml_element_desc ne_block_group_elements[] = { 1.381 + E_SUSPEND(ID_BLOCK, TYPE_BINARY), 1.382 + E_FIELD(ID_BLOCK_DURATION, TYPE_UINT, struct block_group, duration), 1.383 + E_FIELD(ID_REFERENCE_BLOCK, TYPE_INT, struct block_group, reference_block), 1.384 + E_FIELD(ID_DISCARD_PADDING, TYPE_INT, struct block_group, discard_padding), 1.385 + E_LAST 1.386 +}; 1.387 + 1.388 +static struct ebml_element_desc ne_cluster_elements[] = { 1.389 + E_FIELD(ID_TIMECODE, TYPE_UINT, struct cluster, timecode), 1.390 + E_MASTER(ID_BLOCK_GROUP, TYPE_MASTER, struct cluster, block_group), 1.391 + E_SUSPEND(ID_SIMPLE_BLOCK, TYPE_BINARY), 1.392 + E_LAST 1.393 +}; 1.394 + 1.395 +static struct ebml_element_desc ne_video_elements[] = { 1.396 + E_FIELD(ID_STEREO_MODE, TYPE_UINT, struct video, stereo_mode), 1.397 + E_FIELD(ID_PIXEL_WIDTH, TYPE_UINT, struct video, pixel_width), 1.398 + E_FIELD(ID_PIXEL_HEIGHT, TYPE_UINT, struct video, pixel_height), 1.399 + E_FIELD(ID_PIXEL_CROP_BOTTOM, TYPE_UINT, struct video, pixel_crop_bottom), 1.400 + E_FIELD(ID_PIXEL_CROP_TOP, TYPE_UINT, struct video, pixel_crop_top), 1.401 + E_FIELD(ID_PIXEL_CROP_LEFT, TYPE_UINT, struct video, pixel_crop_left), 1.402 + E_FIELD(ID_PIXEL_CROP_RIGHT, TYPE_UINT, struct video, pixel_crop_right), 1.403 + E_FIELD(ID_DISPLAY_WIDTH, TYPE_UINT, struct video, display_width), 1.404 + E_FIELD(ID_DISPLAY_HEIGHT, TYPE_UINT, struct video, display_height), 1.405 + E_LAST 1.406 +}; 1.407 + 1.408 +static struct ebml_element_desc ne_audio_elements[] = { 1.409 + E_FIELD(ID_SAMPLING_FREQUENCY, TYPE_FLOAT, struct audio, sampling_frequency), 1.410 + E_FIELD(ID_CHANNELS, TYPE_UINT, struct audio, channels), 1.411 + E_FIELD(ID_BIT_DEPTH, TYPE_UINT, struct audio, bit_depth), 1.412 + E_LAST 1.413 +}; 1.414 + 1.415 +static struct ebml_element_desc ne_track_entry_elements[] = { 1.416 + E_FIELD(ID_TRACK_NUMBER, TYPE_UINT, struct track_entry, number), 1.417 + E_FIELD(ID_TRACK_UID, TYPE_UINT, struct track_entry, uid), 1.418 + E_FIELD(ID_TRACK_TYPE, TYPE_UINT, struct track_entry, type), 1.419 + E_FIELD(ID_FLAG_ENABLED, TYPE_UINT, struct track_entry, flag_enabled), 1.420 + E_FIELD(ID_FLAG_DEFAULT, TYPE_UINT, struct track_entry, flag_default), 1.421 + E_FIELD(ID_FLAG_LACING, TYPE_UINT, struct track_entry, flag_lacing), 1.422 + E_FIELD(ID_TRACK_TIMECODE_SCALE, TYPE_FLOAT, struct track_entry, track_timecode_scale), 1.423 + E_FIELD(ID_LANGUAGE, TYPE_STRING, struct track_entry, language), 1.424 + E_FIELD(ID_CODEC_ID, TYPE_STRING, struct track_entry, codec_id), 1.425 + E_FIELD(ID_CODEC_PRIVATE, TYPE_BINARY, struct track_entry, codec_private), 1.426 + E_FIELD(ID_CODEC_DELAY, TYPE_UINT, struct track_entry, codec_delay), 1.427 + E_FIELD(ID_SEEK_PREROLL, TYPE_UINT, struct track_entry, seek_preroll), 1.428 + E_FIELD(ID_DEFAULT_DURATION, TYPE_UINT, struct track_entry, default_duration), 1.429 + E_SINGLE_MASTER(ID_VIDEO, TYPE_MASTER, struct track_entry, video), 1.430 + E_SINGLE_MASTER(ID_AUDIO, TYPE_MASTER, struct track_entry, audio), 1.431 + E_LAST 1.432 +}; 1.433 + 1.434 +static struct ebml_element_desc ne_tracks_elements[] = { 1.435 + E_MASTER(ID_TRACK_ENTRY, TYPE_MASTER, struct tracks, track_entry), 1.436 + E_LAST 1.437 +}; 1.438 + 1.439 +static struct ebml_element_desc ne_cue_track_positions_elements[] = { 1.440 + E_FIELD(ID_CUE_TRACK, TYPE_UINT, struct cue_track_positions, track), 1.441 + E_FIELD(ID_CUE_CLUSTER_POSITION, TYPE_UINT, struct cue_track_positions, cluster_position), 1.442 + E_FIELD(ID_CUE_BLOCK_NUMBER, TYPE_UINT, struct cue_track_positions, block_number), 1.443 + E_LAST 1.444 +}; 1.445 + 1.446 +static struct ebml_element_desc ne_cue_point_elements[] = { 1.447 + E_FIELD(ID_CUE_TIME, TYPE_UINT, struct cue_point, time), 1.448 + E_MASTER(ID_CUE_TRACK_POSITIONS, TYPE_MASTER, struct cue_point, cue_track_positions), 1.449 + E_LAST 1.450 +}; 1.451 + 1.452 +static struct ebml_element_desc ne_cues_elements[] = { 1.453 + E_MASTER(ID_CUE_POINT, TYPE_MASTER, struct cues, cue_point), 1.454 + E_LAST 1.455 +}; 1.456 + 1.457 +static struct ebml_element_desc ne_segment_elements[] = { 1.458 + E_MASTER(ID_SEEK_HEAD, TYPE_MASTER, struct segment, seek_head), 1.459 + E_SINGLE_MASTER(ID_INFO, TYPE_MASTER, struct segment, info), 1.460 + E_MASTER(ID_CLUSTER, TYPE_MASTER, struct segment, cluster), 1.461 + E_SINGLE_MASTER(ID_TRACKS, TYPE_MASTER, struct segment, tracks), 1.462 + E_SINGLE_MASTER(ID_CUES, TYPE_MASTER, struct segment, cues), 1.463 + E_LAST 1.464 +}; 1.465 + 1.466 +static struct ebml_element_desc ne_top_level_elements[] = { 1.467 + E_SINGLE_MASTER(ID_EBML, TYPE_MASTER, nestegg, ebml), 1.468 + E_SINGLE_MASTER_O(ID_SEGMENT, TYPE_MASTER, nestegg, segment), 1.469 + E_LAST 1.470 +}; 1.471 + 1.472 +#undef E_FIELD 1.473 +#undef E_MASTER 1.474 +#undef E_SINGLE_MASTER_O 1.475 +#undef E_SINGLE_MASTER 1.476 +#undef E_SUSPEND 1.477 +#undef E_LAST 1.478 + 1.479 +static struct pool_ctx * 1.480 +ne_pool_init(void) 1.481 +{ 1.482 + return h_malloc(sizeof(struct pool_ctx)); 1.483 +} 1.484 + 1.485 +static void 1.486 +ne_pool_destroy(struct pool_ctx * pool) 1.487 +{ 1.488 + h_free(pool); 1.489 +} 1.490 + 1.491 +static void * 1.492 +ne_pool_alloc(size_t size, struct pool_ctx * pool) 1.493 +{ 1.494 + void * p; 1.495 + 1.496 + p = h_malloc(size); 1.497 + if (!p) 1.498 + return NULL; 1.499 + hattach(p, pool); 1.500 + memset(p, 0, size); 1.501 + return p; 1.502 +} 1.503 + 1.504 +static void * 1.505 +ne_alloc(size_t size) 1.506 +{ 1.507 + return calloc(1, size); 1.508 +} 1.509 + 1.510 +static int 1.511 +ne_io_read(nestegg_io * io, void * buffer, size_t length) 1.512 +{ 1.513 + return io->read(buffer, length, io->userdata); 1.514 +} 1.515 + 1.516 +static int 1.517 +ne_io_seek(nestegg_io * io, int64_t offset, int whence) 1.518 +{ 1.519 + return io->seek(offset, whence, io->userdata); 1.520 +} 1.521 + 1.522 +static int 1.523 +ne_io_read_skip(nestegg_io * io, size_t length) 1.524 +{ 1.525 + size_t get; 1.526 + unsigned char buf[8192]; 1.527 + int r = 1; 1.528 + 1.529 + while (length > 0) { 1.530 + get = length < sizeof(buf) ? length : sizeof(buf); 1.531 + r = ne_io_read(io, buf, get); 1.532 + if (r != 1) 1.533 + break; 1.534 + length -= get; 1.535 + } 1.536 + 1.537 + return r; 1.538 +} 1.539 + 1.540 +static int64_t 1.541 +ne_io_tell(nestegg_io * io) 1.542 +{ 1.543 + return io->tell(io->userdata); 1.544 +} 1.545 + 1.546 +static int 1.547 +ne_bare_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length, enum vint_mask maskflag) 1.548 +{ 1.549 + int r; 1.550 + unsigned char b; 1.551 + size_t maxlen = 8; 1.552 + unsigned int count = 1, mask = 1 << 7; 1.553 + 1.554 + r = ne_io_read(io, &b, 1); 1.555 + if (r != 1) 1.556 + return r; 1.557 + 1.558 + while (count < maxlen) { 1.559 + if ((b & mask) != 0) 1.560 + break; 1.561 + mask >>= 1; 1.562 + count += 1; 1.563 + } 1.564 + 1.565 + if (length) 1.566 + *length = count; 1.567 + *value = b; 1.568 + 1.569 + if (maskflag == MASK_FIRST_BIT) 1.570 + *value = b & ~mask; 1.571 + 1.572 + while (--count) { 1.573 + r = ne_io_read(io, &b, 1); 1.574 + if (r != 1) 1.575 + return r; 1.576 + *value <<= 8; 1.577 + *value |= b; 1.578 + } 1.579 + 1.580 + return 1; 1.581 +} 1.582 + 1.583 +static int 1.584 +ne_read_id(nestegg_io * io, uint64_t * value, uint64_t * length) 1.585 +{ 1.586 + return ne_bare_read_vint(io, value, length, MASK_NONE); 1.587 +} 1.588 + 1.589 +static int 1.590 +ne_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length) 1.591 +{ 1.592 + return ne_bare_read_vint(io, value, length, MASK_FIRST_BIT); 1.593 +} 1.594 + 1.595 +static int 1.596 +ne_read_svint(nestegg_io * io, int64_t * value, uint64_t * length) 1.597 +{ 1.598 + int r; 1.599 + uint64_t uvalue; 1.600 + uint64_t ulength; 1.601 + int64_t svint_subtr[] = { 1.602 + 0x3f, 0x1fff, 1.603 + 0xfffff, 0x7ffffff, 1.604 + 0x3ffffffffLL, 0x1ffffffffffLL, 1.605 + 0xffffffffffffLL, 0x7fffffffffffffLL 1.606 + }; 1.607 + 1.608 + r = ne_bare_read_vint(io, &uvalue, &ulength, MASK_FIRST_BIT); 1.609 + if (r != 1) 1.610 + return r; 1.611 + *value = uvalue - svint_subtr[ulength - 1]; 1.612 + if (length) 1.613 + *length = ulength; 1.614 + return r; 1.615 +} 1.616 + 1.617 +static int 1.618 +ne_read_uint(nestegg_io * io, uint64_t * val, uint64_t length) 1.619 +{ 1.620 + unsigned char b; 1.621 + int r; 1.622 + 1.623 + if (length == 0 || length > 8) 1.624 + return -1; 1.625 + r = ne_io_read(io, &b, 1); 1.626 + if (r != 1) 1.627 + return r; 1.628 + *val = b; 1.629 + while (--length) { 1.630 + r = ne_io_read(io, &b, 1); 1.631 + if (r != 1) 1.632 + return r; 1.633 + *val <<= 8; 1.634 + *val |= b; 1.635 + } 1.636 + return 1; 1.637 +} 1.638 + 1.639 +static int 1.640 +ne_read_int(nestegg_io * io, int64_t * val, uint64_t length) 1.641 +{ 1.642 + int r; 1.643 + uint64_t uval, base; 1.644 + 1.645 + r = ne_read_uint(io, &uval, length); 1.646 + if (r != 1) 1.647 + return r; 1.648 + 1.649 + if (length < sizeof(int64_t)) { 1.650 + base = 1; 1.651 + base <<= length * 8 - 1; 1.652 + if (uval >= base) { 1.653 + base = 1; 1.654 + base <<= length * 8; 1.655 + } else { 1.656 + base = 0; 1.657 + } 1.658 + *val = uval - base; 1.659 + } else { 1.660 + *val = (int64_t) uval; 1.661 + } 1.662 + 1.663 + return 1; 1.664 +} 1.665 + 1.666 +static int 1.667 +ne_read_float(nestegg_io * io, double * val, uint64_t length) 1.668 +{ 1.669 + union { 1.670 + uint64_t u; 1.671 + float f; 1.672 + double d; 1.673 + } value; 1.674 + int r; 1.675 + 1.676 + /* Length == 10 not implemented. */ 1.677 + if (length != 4 && length != 8) 1.678 + return -1; 1.679 + r = ne_read_uint(io, &value.u, length); 1.680 + if (r != 1) 1.681 + return r; 1.682 + if (length == 4) 1.683 + *val = value.f; 1.684 + else 1.685 + *val = value.d; 1.686 + return 1; 1.687 +} 1.688 + 1.689 +static int 1.690 +ne_read_string(nestegg * ctx, char ** val, uint64_t length) 1.691 +{ 1.692 + char * str; 1.693 + int r; 1.694 + 1.695 + if (length == 0 || length > LIMIT_STRING) 1.696 + return -1; 1.697 + str = ne_pool_alloc(length + 1, ctx->alloc_pool); 1.698 + if (!str) 1.699 + return -1; 1.700 + r = ne_io_read(ctx->io, (unsigned char *) str, length); 1.701 + if (r != 1) 1.702 + return r; 1.703 + str[length] = '\0'; 1.704 + *val = str; 1.705 + return 1; 1.706 +} 1.707 + 1.708 +static int 1.709 +ne_read_binary(nestegg * ctx, struct ebml_binary * val, uint64_t length) 1.710 +{ 1.711 + if (length == 0 || length > LIMIT_BINARY) 1.712 + return -1; 1.713 + val->data = ne_pool_alloc(length, ctx->alloc_pool); 1.714 + if (!val->data) 1.715 + return -1; 1.716 + val->length = length; 1.717 + return ne_io_read(ctx->io, val->data, length); 1.718 +} 1.719 + 1.720 +static int 1.721 +ne_get_uint(struct ebml_type type, uint64_t * value) 1.722 +{ 1.723 + if (!type.read) 1.724 + return -1; 1.725 + 1.726 + assert(type.type == TYPE_UINT); 1.727 + 1.728 + *value = type.v.u; 1.729 + 1.730 + return 0; 1.731 +} 1.732 + 1.733 +static int 1.734 +ne_get_float(struct ebml_type type, double * value) 1.735 +{ 1.736 + if (!type.read) 1.737 + return -1; 1.738 + 1.739 + assert(type.type == TYPE_FLOAT); 1.740 + 1.741 + *value = type.v.f; 1.742 + 1.743 + return 0; 1.744 +} 1.745 + 1.746 +static int 1.747 +ne_get_string(struct ebml_type type, char ** value) 1.748 +{ 1.749 + if (!type.read) 1.750 + return -1; 1.751 + 1.752 + assert(type.type == TYPE_STRING); 1.753 + 1.754 + *value = type.v.s; 1.755 + 1.756 + return 0; 1.757 +} 1.758 + 1.759 +static int 1.760 +ne_get_binary(struct ebml_type type, struct ebml_binary * value) 1.761 +{ 1.762 + if (!type.read) 1.763 + return -1; 1.764 + 1.765 + assert(type.type == TYPE_BINARY); 1.766 + 1.767 + *value = type.v.b; 1.768 + 1.769 + return 0; 1.770 +} 1.771 + 1.772 +static int 1.773 +ne_is_ancestor_element(uint64_t id, struct list_node * ancestor) 1.774 +{ 1.775 + struct ebml_element_desc * element; 1.776 + 1.777 + for (; ancestor; ancestor = ancestor->previous) 1.778 + for (element = ancestor->node; element->id; ++element) 1.779 + if (element->id == id) 1.780 + return 1; 1.781 + 1.782 + return 0; 1.783 +} 1.784 + 1.785 +static struct ebml_element_desc * 1.786 +ne_find_element(uint64_t id, struct ebml_element_desc * elements) 1.787 +{ 1.788 + struct ebml_element_desc * element; 1.789 + 1.790 + for (element = elements; element->id; ++element) 1.791 + if (element->id == id) 1.792 + return element; 1.793 + 1.794 + return NULL; 1.795 +} 1.796 + 1.797 +static int 1.798 +ne_ctx_push(nestegg * ctx, struct ebml_element_desc * ancestor, void * data) 1.799 +{ 1.800 + struct list_node * item; 1.801 + 1.802 + item = ne_alloc(sizeof(*item)); 1.803 + if (!item) 1.804 + return -1; 1.805 + item->previous = ctx->ancestor; 1.806 + item->node = ancestor; 1.807 + item->data = data; 1.808 + ctx->ancestor = item; 1.809 + return 0; 1.810 +} 1.811 + 1.812 +static void 1.813 +ne_ctx_pop(nestegg * ctx) 1.814 +{ 1.815 + struct list_node * item; 1.816 + 1.817 + item = ctx->ancestor; 1.818 + ctx->ancestor = item->previous; 1.819 + free(item); 1.820 +} 1.821 + 1.822 +static int 1.823 +ne_ctx_save(nestegg * ctx, struct saved_state * s) 1.824 +{ 1.825 + s->stream_offset = ne_io_tell(ctx->io); 1.826 + if (s->stream_offset < 0) 1.827 + return -1; 1.828 + s->ancestor = ctx->ancestor; 1.829 + s->last_id = ctx->last_id; 1.830 + s->last_size = ctx->last_size; 1.831 + s->last_valid = ctx->last_valid; 1.832 + return 0; 1.833 +} 1.834 + 1.835 +static int 1.836 +ne_ctx_restore(nestegg * ctx, struct saved_state * s) 1.837 +{ 1.838 + int r; 1.839 + 1.840 + r = ne_io_seek(ctx->io, s->stream_offset, NESTEGG_SEEK_SET); 1.841 + if (r != 0) 1.842 + return -1; 1.843 + ctx->ancestor = s->ancestor; 1.844 + ctx->last_id = s->last_id; 1.845 + ctx->last_size = s->last_size; 1.846 + ctx->last_valid = s->last_valid; 1.847 + return 0; 1.848 +} 1.849 + 1.850 +static int 1.851 +ne_peek_element(nestegg * ctx, uint64_t * id, uint64_t * size) 1.852 +{ 1.853 + int r; 1.854 + 1.855 + if (ctx->last_valid) { 1.856 + if (id) 1.857 + *id = ctx->last_id; 1.858 + if (size) 1.859 + *size = ctx->last_size; 1.860 + return 1; 1.861 + } 1.862 + 1.863 + r = ne_read_id(ctx->io, &ctx->last_id, NULL); 1.864 + if (r != 1) 1.865 + return r; 1.866 + 1.867 + r = ne_read_vint(ctx->io, &ctx->last_size, NULL); 1.868 + if (r != 1) 1.869 + return r; 1.870 + 1.871 + if (id) 1.872 + *id = ctx->last_id; 1.873 + if (size) 1.874 + *size = ctx->last_size; 1.875 + 1.876 + ctx->last_valid = 1; 1.877 + 1.878 + return 1; 1.879 +} 1.880 + 1.881 +static int 1.882 +ne_read_element(nestegg * ctx, uint64_t * id, uint64_t * size) 1.883 +{ 1.884 + int r; 1.885 + 1.886 + r = ne_peek_element(ctx, id, size); 1.887 + if (r != 1) 1.888 + return r; 1.889 + 1.890 + ctx->last_valid = 0; 1.891 + 1.892 + return 1; 1.893 +} 1.894 + 1.895 +static int 1.896 +ne_read_master(nestegg * ctx, struct ebml_element_desc * desc) 1.897 +{ 1.898 + struct ebml_list * list; 1.899 + struct ebml_list_node * node, * oldtail; 1.900 + 1.901 + assert(desc->type == TYPE_MASTER && desc->flags & DESC_FLAG_MULTI); 1.902 + 1.903 + ctx->log(ctx, NESTEGG_LOG_DEBUG, "multi master element %llx (%s)", 1.904 + desc->id, desc->name); 1.905 + 1.906 + list = (struct ebml_list *) (ctx->ancestor->data + desc->offset); 1.907 + 1.908 + node = ne_pool_alloc(sizeof(*node), ctx->alloc_pool); 1.909 + if (!node) 1.910 + return -1; 1.911 + node->id = desc->id; 1.912 + node->data = ne_pool_alloc(desc->size, ctx->alloc_pool); 1.913 + if (!node->data) 1.914 + return -1; 1.915 + 1.916 + oldtail = list->tail; 1.917 + if (oldtail) 1.918 + oldtail->next = node; 1.919 + list->tail = node; 1.920 + if (!list->head) 1.921 + list->head = node; 1.922 + 1.923 + ctx->log(ctx, NESTEGG_LOG_DEBUG, " -> using data %p", node->data); 1.924 + 1.925 + if (ne_ctx_push(ctx, desc->children, node->data) < 0) 1.926 + return -1; 1.927 + 1.928 + return 0; 1.929 +} 1.930 + 1.931 +static int 1.932 +ne_read_single_master(nestegg * ctx, struct ebml_element_desc * desc) 1.933 +{ 1.934 + assert(desc->type == TYPE_MASTER && !(desc->flags & DESC_FLAG_MULTI)); 1.935 + 1.936 + ctx->log(ctx, NESTEGG_LOG_DEBUG, "single master element %llx (%s)", 1.937 + desc->id, desc->name); 1.938 + ctx->log(ctx, NESTEGG_LOG_DEBUG, " -> using data %p (%u)", 1.939 + ctx->ancestor->data + desc->offset, desc->offset); 1.940 + 1.941 + return ne_ctx_push(ctx, desc->children, ctx->ancestor->data + desc->offset); 1.942 +} 1.943 + 1.944 +static int 1.945 +ne_read_simple(nestegg * ctx, struct ebml_element_desc * desc, size_t length) 1.946 +{ 1.947 + struct ebml_type * storage; 1.948 + int r; 1.949 + 1.950 + storage = (struct ebml_type *) (ctx->ancestor->data + desc->offset); 1.951 + 1.952 + if (storage->read) { 1.953 + ctx->log(ctx, NESTEGG_LOG_DEBUG, "element %llx (%s) already read, skipping", 1.954 + desc->id, desc->name); 1.955 + return 0; 1.956 + } 1.957 + 1.958 + storage->type = desc->type; 1.959 + 1.960 + ctx->log(ctx, NESTEGG_LOG_DEBUG, "element %llx (%s) -> %p (%u)", 1.961 + desc->id, desc->name, storage, desc->offset); 1.962 + 1.963 + switch (desc->type) { 1.964 + case TYPE_UINT: 1.965 + r = ne_read_uint(ctx->io, &storage->v.u, length); 1.966 + break; 1.967 + case TYPE_FLOAT: 1.968 + r = ne_read_float(ctx->io, &storage->v.f, length); 1.969 + break; 1.970 + case TYPE_INT: 1.971 + r = ne_read_int(ctx->io, &storage->v.i, length); 1.972 + break; 1.973 + case TYPE_STRING: 1.974 + r = ne_read_string(ctx, &storage->v.s, length); 1.975 + break; 1.976 + case TYPE_BINARY: 1.977 + r = ne_read_binary(ctx, &storage->v.b, length); 1.978 + break; 1.979 + case TYPE_MASTER: 1.980 + case TYPE_UNKNOWN: 1.981 + assert(0); 1.982 + r = 0; 1.983 + break; 1.984 + } 1.985 + 1.986 + if (r == 1) 1.987 + storage->read = 1; 1.988 + 1.989 + return r; 1.990 +} 1.991 + 1.992 +static int 1.993 +ne_parse(nestegg * ctx, struct ebml_element_desc * top_level, int64_t max_offset) 1.994 +{ 1.995 + int r; 1.996 + int64_t * data_offset; 1.997 + uint64_t id, size, peeked_id; 1.998 + struct ebml_element_desc * element; 1.999 + 1.1000 + if (!ctx->ancestor) 1.1001 + return -1; 1.1002 + 1.1003 + for (;;) { 1.1004 + if (max_offset > 0 && ne_io_tell(ctx->io) >= max_offset) { 1.1005 + /* Reached end of offset allowed for parsing - return gracefully */ 1.1006 + r = 1; 1.1007 + break; 1.1008 + } 1.1009 + r = ne_peek_element(ctx, &id, &size); 1.1010 + if (r != 1) 1.1011 + break; 1.1012 + peeked_id = id; 1.1013 + 1.1014 + element = ne_find_element(id, ctx->ancestor->node); 1.1015 + if (element) { 1.1016 + if (element->flags & DESC_FLAG_SUSPEND) { 1.1017 + assert(element->type == TYPE_BINARY); 1.1018 + ctx->log(ctx, NESTEGG_LOG_DEBUG, "suspend parse at %llx", id); 1.1019 + r = 1; 1.1020 + break; 1.1021 + } 1.1022 + 1.1023 + r = ne_read_element(ctx, &id, &size); 1.1024 + if (r != 1) 1.1025 + break; 1.1026 + assert(id == peeked_id); 1.1027 + 1.1028 + if (element->flags & DESC_FLAG_OFFSET) { 1.1029 + data_offset = (int64_t *) (ctx->ancestor->data + element->data_offset); 1.1030 + *data_offset = ne_io_tell(ctx->io); 1.1031 + if (*data_offset < 0) { 1.1032 + r = -1; 1.1033 + break; 1.1034 + } 1.1035 + } 1.1036 + 1.1037 + if (element->type == TYPE_MASTER) { 1.1038 + if (element->flags & DESC_FLAG_MULTI) { 1.1039 + if (ne_read_master(ctx, element) < 0) 1.1040 + break; 1.1041 + } else { 1.1042 + if (ne_read_single_master(ctx, element) < 0) 1.1043 + break; 1.1044 + } 1.1045 + continue; 1.1046 + } else { 1.1047 + r = ne_read_simple(ctx, element, size); 1.1048 + if (r < 0) 1.1049 + break; 1.1050 + } 1.1051 + } else if (ne_is_ancestor_element(id, ctx->ancestor->previous)) { 1.1052 + ctx->log(ctx, NESTEGG_LOG_DEBUG, "parent element %llx", id); 1.1053 + if (top_level && ctx->ancestor->node == top_level) { 1.1054 + ctx->log(ctx, NESTEGG_LOG_DEBUG, "*** parse about to back up past top_level"); 1.1055 + r = 1; 1.1056 + break; 1.1057 + } 1.1058 + ne_ctx_pop(ctx); 1.1059 + } else { 1.1060 + r = ne_read_element(ctx, &id, &size); 1.1061 + if (r != 1) 1.1062 + break; 1.1063 + 1.1064 + if (id != ID_VOID && id != ID_CRC32) 1.1065 + ctx->log(ctx, NESTEGG_LOG_DEBUG, "unknown element %llx", id); 1.1066 + r = ne_io_read_skip(ctx->io, size); 1.1067 + if (r != 1) 1.1068 + break; 1.1069 + } 1.1070 + } 1.1071 + 1.1072 + if (r != 1) 1.1073 + while (ctx->ancestor) 1.1074 + ne_ctx_pop(ctx); 1.1075 + 1.1076 + return r; 1.1077 +} 1.1078 + 1.1079 +static uint64_t 1.1080 +ne_xiph_lace_value(unsigned char ** np) 1.1081 +{ 1.1082 + uint64_t lace; 1.1083 + uint64_t value; 1.1084 + unsigned char * p = *np; 1.1085 + 1.1086 + lace = *p++; 1.1087 + value = lace; 1.1088 + while (lace == 255) { 1.1089 + lace = *p++; 1.1090 + value += lace; 1.1091 + } 1.1092 + 1.1093 + *np = p; 1.1094 + 1.1095 + return value; 1.1096 +} 1.1097 + 1.1098 +static int 1.1099 +ne_read_xiph_lace_value(nestegg_io * io, uint64_t * value, size_t * consumed) 1.1100 +{ 1.1101 + int r; 1.1102 + uint64_t lace; 1.1103 + 1.1104 + r = ne_read_uint(io, &lace, 1); 1.1105 + if (r != 1) 1.1106 + return r; 1.1107 + *consumed += 1; 1.1108 + 1.1109 + *value = lace; 1.1110 + while (lace == 255) { 1.1111 + r = ne_read_uint(io, &lace, 1); 1.1112 + if (r != 1) 1.1113 + return r; 1.1114 + *consumed += 1; 1.1115 + *value += lace; 1.1116 + } 1.1117 + 1.1118 + return 1; 1.1119 +} 1.1120 + 1.1121 +static int 1.1122 +ne_read_xiph_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes) 1.1123 +{ 1.1124 + int r; 1.1125 + size_t i = 0; 1.1126 + uint64_t sum = 0; 1.1127 + 1.1128 + while (--n) { 1.1129 + r = ne_read_xiph_lace_value(io, &sizes[i], read); 1.1130 + if (r != 1) 1.1131 + return r; 1.1132 + sum += sizes[i]; 1.1133 + i += 1; 1.1134 + } 1.1135 + 1.1136 + if (*read + sum > block) 1.1137 + return -1; 1.1138 + 1.1139 + /* Last frame is the remainder of the block. */ 1.1140 + sizes[i] = block - *read - sum; 1.1141 + return 1; 1.1142 +} 1.1143 + 1.1144 +static int 1.1145 +ne_read_ebml_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes) 1.1146 +{ 1.1147 + int r; 1.1148 + uint64_t lace, sum, length; 1.1149 + int64_t slace; 1.1150 + size_t i = 0; 1.1151 + 1.1152 + r = ne_read_vint(io, &lace, &length); 1.1153 + if (r != 1) 1.1154 + return r; 1.1155 + *read += length; 1.1156 + 1.1157 + sizes[i] = lace; 1.1158 + sum = sizes[i]; 1.1159 + 1.1160 + i += 1; 1.1161 + n -= 1; 1.1162 + 1.1163 + while (--n) { 1.1164 + r = ne_read_svint(io, &slace, &length); 1.1165 + if (r != 1) 1.1166 + return r; 1.1167 + *read += length; 1.1168 + sizes[i] = sizes[i - 1] + slace; 1.1169 + sum += sizes[i]; 1.1170 + i += 1; 1.1171 + } 1.1172 + 1.1173 + if (*read + sum > block) 1.1174 + return -1; 1.1175 + 1.1176 + /* Last frame is the remainder of the block. */ 1.1177 + sizes[i] = block - *read - sum; 1.1178 + return 1; 1.1179 +} 1.1180 + 1.1181 +static uint64_t 1.1182 +ne_get_timecode_scale(nestegg * ctx) 1.1183 +{ 1.1184 + uint64_t scale; 1.1185 + 1.1186 + if (ne_get_uint(ctx->segment.info.timecode_scale, &scale) != 0) 1.1187 + scale = 1000000; 1.1188 + 1.1189 + return scale; 1.1190 +} 1.1191 + 1.1192 +static int 1.1193 +ne_map_track_number_to_index(nestegg * ctx, 1.1194 + unsigned int track_number, 1.1195 + unsigned int * track_index) 1.1196 +{ 1.1197 + struct ebml_list_node * node; 1.1198 + struct track_entry * t_entry; 1.1199 + uint64_t t_number = 0; 1.1200 + 1.1201 + if (!track_index) 1.1202 + return -1; 1.1203 + *track_index = 0; 1.1204 + 1.1205 + if (track_number == 0) 1.1206 + return -1; 1.1207 + 1.1208 + node = ctx->segment.tracks.track_entry.head; 1.1209 + while (node) { 1.1210 + assert(node->id == ID_TRACK_ENTRY); 1.1211 + t_entry = node->data; 1.1212 + if (ne_get_uint(t_entry->number, &t_number) != 0) 1.1213 + return -1; 1.1214 + if (t_number == track_number) 1.1215 + return 0; 1.1216 + *track_index += 1; 1.1217 + node = node->next; 1.1218 + } 1.1219 + 1.1220 + return -1; 1.1221 +} 1.1222 + 1.1223 +static struct track_entry * 1.1224 +ne_find_track_entry(nestegg * ctx, unsigned int track) 1.1225 +{ 1.1226 + struct ebml_list_node * node; 1.1227 + unsigned int tracks = 0; 1.1228 + 1.1229 + node = ctx->segment.tracks.track_entry.head; 1.1230 + while (node) { 1.1231 + assert(node->id == ID_TRACK_ENTRY); 1.1232 + if (track == tracks) 1.1233 + return node->data; 1.1234 + tracks += 1; 1.1235 + node = node->next; 1.1236 + } 1.1237 + 1.1238 + return NULL; 1.1239 +} 1.1240 + 1.1241 +static int 1.1242 +ne_read_block(nestegg * ctx, uint64_t block_id, uint64_t block_size, nestegg_packet ** data) 1.1243 +{ 1.1244 + int r; 1.1245 + int64_t timecode, abs_timecode; 1.1246 + nestegg_packet * pkt; 1.1247 + struct cluster * cluster; 1.1248 + struct frame * f, * last; 1.1249 + struct track_entry * entry; 1.1250 + double track_scale; 1.1251 + uint64_t track_number, length, frame_sizes[256], cluster_tc, flags, frames, tc_scale, total; 1.1252 + unsigned int i, lacing, track; 1.1253 + size_t consumed = 0; 1.1254 + 1.1255 + *data = NULL; 1.1256 + 1.1257 + if (block_size > LIMIT_BLOCK) 1.1258 + return -1; 1.1259 + 1.1260 + r = ne_read_vint(ctx->io, &track_number, &length); 1.1261 + if (r != 1) 1.1262 + return r; 1.1263 + 1.1264 + if (track_number == 0) 1.1265 + return -1; 1.1266 + 1.1267 + consumed += length; 1.1268 + 1.1269 + r = ne_read_int(ctx->io, &timecode, 2); 1.1270 + if (r != 1) 1.1271 + return r; 1.1272 + 1.1273 + consumed += 2; 1.1274 + 1.1275 + r = ne_read_uint(ctx->io, &flags, 1); 1.1276 + if (r != 1) 1.1277 + return r; 1.1278 + 1.1279 + consumed += 1; 1.1280 + 1.1281 + frames = 0; 1.1282 + 1.1283 + /* Flags are different between Block and SimpleBlock, but lacing is 1.1284 + encoded the same way. */ 1.1285 + lacing = (flags & BLOCK_FLAGS_LACING) >> 1; 1.1286 + 1.1287 + switch (lacing) { 1.1288 + case LACING_NONE: 1.1289 + frames = 1; 1.1290 + break; 1.1291 + case LACING_XIPH: 1.1292 + case LACING_FIXED: 1.1293 + case LACING_EBML: 1.1294 + r = ne_read_uint(ctx->io, &frames, 1); 1.1295 + if (r != 1) 1.1296 + return r; 1.1297 + consumed += 1; 1.1298 + frames += 1; 1.1299 + } 1.1300 + 1.1301 + if (frames > 256) 1.1302 + return -1; 1.1303 + 1.1304 + switch (lacing) { 1.1305 + case LACING_NONE: 1.1306 + frame_sizes[0] = block_size - consumed; 1.1307 + break; 1.1308 + case LACING_XIPH: 1.1309 + if (frames == 1) 1.1310 + return -1; 1.1311 + r = ne_read_xiph_lacing(ctx->io, block_size, &consumed, frames, frame_sizes); 1.1312 + if (r != 1) 1.1313 + return r; 1.1314 + break; 1.1315 + case LACING_FIXED: 1.1316 + if ((block_size - consumed) % frames) 1.1317 + return -1; 1.1318 + for (i = 0; i < frames; ++i) 1.1319 + frame_sizes[i] = (block_size - consumed) / frames; 1.1320 + break; 1.1321 + case LACING_EBML: 1.1322 + if (frames == 1) 1.1323 + return -1; 1.1324 + r = ne_read_ebml_lacing(ctx->io, block_size, &consumed, frames, frame_sizes); 1.1325 + if (r != 1) 1.1326 + return r; 1.1327 + break; 1.1328 + } 1.1329 + 1.1330 + /* Sanity check unlaced frame sizes against total block size. */ 1.1331 + total = consumed; 1.1332 + for (i = 0; i < frames; ++i) 1.1333 + total += frame_sizes[i]; 1.1334 + if (total > block_size) 1.1335 + return -1; 1.1336 + 1.1337 + if (ne_map_track_number_to_index(ctx, track_number, &track) != 0) 1.1338 + return -1; 1.1339 + 1.1340 + entry = ne_find_track_entry(ctx, track); 1.1341 + if (!entry) 1.1342 + return -1; 1.1343 + 1.1344 + track_scale = 1.0; 1.1345 + 1.1346 + tc_scale = ne_get_timecode_scale(ctx); 1.1347 + 1.1348 + assert(ctx->segment.cluster.tail->id == ID_CLUSTER); 1.1349 + cluster = ctx->segment.cluster.tail->data; 1.1350 + if (ne_get_uint(cluster->timecode, &cluster_tc) != 0) 1.1351 + return -1; 1.1352 + 1.1353 + abs_timecode = timecode + cluster_tc; 1.1354 + if (abs_timecode < 0) 1.1355 + return -1; 1.1356 + 1.1357 + pkt = ne_alloc(sizeof(*pkt)); 1.1358 + if (!pkt) 1.1359 + return -1; 1.1360 + pkt->track = track; 1.1361 + pkt->timecode = abs_timecode * tc_scale * track_scale; 1.1362 + 1.1363 + ctx->log(ctx, NESTEGG_LOG_DEBUG, "%sblock t %lld pts %f f %llx frames: %llu", 1.1364 + block_id == ID_BLOCK ? "" : "simple", pkt->track, pkt->timecode / 1e9, flags, frames); 1.1365 + 1.1366 + last = NULL; 1.1367 + for (i = 0; i < frames; ++i) { 1.1368 + if (frame_sizes[i] > LIMIT_FRAME) { 1.1369 + nestegg_free_packet(pkt); 1.1370 + return -1; 1.1371 + } 1.1372 + f = ne_alloc(sizeof(*f)); 1.1373 + if (!f) { 1.1374 + nestegg_free_packet(pkt); 1.1375 + return -1; 1.1376 + } 1.1377 + f->data = ne_alloc(frame_sizes[i]); 1.1378 + if (!f->data) { 1.1379 + free(f); 1.1380 + nestegg_free_packet(pkt); 1.1381 + return -1; 1.1382 + } 1.1383 + f->length = frame_sizes[i]; 1.1384 + r = ne_io_read(ctx->io, f->data, frame_sizes[i]); 1.1385 + if (r != 1) { 1.1386 + free(f->data); 1.1387 + free(f); 1.1388 + nestegg_free_packet(pkt); 1.1389 + return -1; 1.1390 + } 1.1391 + 1.1392 + if (!last) 1.1393 + pkt->frame = f; 1.1394 + else 1.1395 + last->next = f; 1.1396 + last = f; 1.1397 + } 1.1398 + 1.1399 + *data = pkt; 1.1400 + 1.1401 + return 1; 1.1402 +} 1.1403 + 1.1404 +static int 1.1405 +ne_read_block_duration(nestegg * ctx, nestegg_packet * pkt) 1.1406 +{ 1.1407 + int r; 1.1408 + uint64_t id, size; 1.1409 + struct ebml_element_desc * element; 1.1410 + struct ebml_type * storage; 1.1411 + 1.1412 + r = ne_peek_element(ctx, &id, &size); 1.1413 + if (r != 1) 1.1414 + return r; 1.1415 + 1.1416 + if (id != ID_BLOCK_DURATION) 1.1417 + return 1; 1.1418 + 1.1419 + element = ne_find_element(id, ctx->ancestor->node); 1.1420 + if (!element) 1.1421 + return 1; 1.1422 + 1.1423 + r = ne_read_simple(ctx, element, size); 1.1424 + if (r != 1) 1.1425 + return r; 1.1426 + storage = (struct ebml_type *) (ctx->ancestor->data + element->offset); 1.1427 + pkt->duration = storage->v.i * ne_get_timecode_scale(ctx); 1.1428 + 1.1429 + return 1; 1.1430 +} 1.1431 + 1.1432 +static int 1.1433 +ne_read_discard_padding(nestegg * ctx, nestegg_packet * pkt) 1.1434 +{ 1.1435 + int r; 1.1436 + uint64_t id, size; 1.1437 + struct ebml_element_desc * element; 1.1438 + struct ebml_type * storage; 1.1439 + 1.1440 + r = ne_peek_element(ctx, &id, &size); 1.1441 + if (r != 1) 1.1442 + return r; 1.1443 + 1.1444 + if (id != ID_DISCARD_PADDING) 1.1445 + return 1; 1.1446 + 1.1447 + element = ne_find_element(id, ctx->ancestor->node); 1.1448 + if (!element) 1.1449 + return 1; 1.1450 + 1.1451 + r = ne_read_simple(ctx, element, size); 1.1452 + if (r != 1) 1.1453 + return r; 1.1454 + storage = (struct ebml_type *) (ctx->ancestor->data + element->offset); 1.1455 + pkt->discard_padding = storage->v.i; 1.1456 + 1.1457 + return 1; 1.1458 +} 1.1459 + 1.1460 + 1.1461 +static uint64_t 1.1462 +ne_buf_read_id(unsigned char const * p, size_t length) 1.1463 +{ 1.1464 + uint64_t id = 0; 1.1465 + 1.1466 + while (length--) { 1.1467 + id <<= 8; 1.1468 + id |= *p++; 1.1469 + } 1.1470 + 1.1471 + return id; 1.1472 +} 1.1473 + 1.1474 +static struct seek * 1.1475 +ne_find_seek_for_id(struct ebml_list_node * seek_head, uint64_t id) 1.1476 +{ 1.1477 + struct ebml_list * head; 1.1478 + struct ebml_list_node * seek; 1.1479 + struct ebml_binary binary_id; 1.1480 + struct seek * s; 1.1481 + 1.1482 + while (seek_head) { 1.1483 + assert(seek_head->id == ID_SEEK_HEAD); 1.1484 + head = seek_head->data; 1.1485 + seek = head->head; 1.1486 + 1.1487 + while (seek) { 1.1488 + assert(seek->id == ID_SEEK); 1.1489 + s = seek->data; 1.1490 + 1.1491 + if (ne_get_binary(s->id, &binary_id) == 0 && 1.1492 + ne_buf_read_id(binary_id.data, binary_id.length) == id) 1.1493 + return s; 1.1494 + 1.1495 + seek = seek->next; 1.1496 + } 1.1497 + 1.1498 + seek_head = seek_head->next; 1.1499 + } 1.1500 + 1.1501 + return NULL; 1.1502 +} 1.1503 + 1.1504 +static struct cue_track_positions * 1.1505 +ne_find_cue_position_for_track(nestegg * ctx, struct ebml_list_node * node, unsigned int track) 1.1506 +{ 1.1507 + struct cue_track_positions * pos = NULL; 1.1508 + uint64_t track_number; 1.1509 + unsigned int t; 1.1510 + 1.1511 + while (node) { 1.1512 + assert(node->id == ID_CUE_TRACK_POSITIONS); 1.1513 + pos = node->data; 1.1514 + if (ne_get_uint(pos->track, &track_number) != 0) 1.1515 + return NULL; 1.1516 + 1.1517 + if (ne_map_track_number_to_index(ctx, track_number, &t) != 0) 1.1518 + return NULL; 1.1519 + 1.1520 + if (t == track) 1.1521 + return pos; 1.1522 + 1.1523 + node = node->next; 1.1524 + } 1.1525 + 1.1526 + return NULL; 1.1527 +} 1.1528 + 1.1529 +static struct cue_point * 1.1530 +ne_find_cue_point_for_tstamp(nestegg * ctx, struct ebml_list_node * cue_point, unsigned int track, uint64_t scale, uint64_t tstamp) 1.1531 +{ 1.1532 + uint64_t time; 1.1533 + struct cue_point * c, * prev = NULL; 1.1534 + 1.1535 + while (cue_point) { 1.1536 + assert(cue_point->id == ID_CUE_POINT); 1.1537 + c = cue_point->data; 1.1538 + 1.1539 + if (!prev) 1.1540 + prev = c; 1.1541 + 1.1542 + if (ne_get_uint(c->time, &time) == 0 && time * scale > tstamp) 1.1543 + break; 1.1544 + 1.1545 + if (ne_find_cue_position_for_track(ctx, c->cue_track_positions.head, track) != NULL) 1.1546 + prev = c; 1.1547 + 1.1548 + cue_point = cue_point->next; 1.1549 + } 1.1550 + 1.1551 + return prev; 1.1552 +} 1.1553 + 1.1554 +static int 1.1555 +ne_is_suspend_element(uint64_t id) 1.1556 +{ 1.1557 + if (id == ID_SIMPLE_BLOCK || id == ID_BLOCK) 1.1558 + return 1; 1.1559 + return 0; 1.1560 +} 1.1561 + 1.1562 +static void 1.1563 +ne_null_log_callback(nestegg * ctx, unsigned int severity, char const * fmt, ...) 1.1564 +{ 1.1565 + if (ctx && severity && fmt) 1.1566 + return; 1.1567 +} 1.1568 + 1.1569 +static int 1.1570 +ne_init_cue_points(nestegg * ctx, int64_t max_offset) 1.1571 +{ 1.1572 + int r; 1.1573 + struct ebml_list_node * node = ctx->segment.cues.cue_point.head; 1.1574 + struct seek * found; 1.1575 + uint64_t seek_pos, id; 1.1576 + struct saved_state state; 1.1577 + 1.1578 + /* If there are no cues loaded, check for cues element in the seek head 1.1579 + and load it. */ 1.1580 + if (!node) { 1.1581 + found = ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES); 1.1582 + if (!found) 1.1583 + return -1; 1.1584 + 1.1585 + if (ne_get_uint(found->position, &seek_pos) != 0) 1.1586 + return -1; 1.1587 + 1.1588 + /* Save old parser state. */ 1.1589 + r = ne_ctx_save(ctx, &state); 1.1590 + if (r != 0) 1.1591 + return -1; 1.1592 + 1.1593 + /* Seek and set up parser state for segment-level element (Cues). */ 1.1594 + r = ne_io_seek(ctx->io, ctx->segment_offset + seek_pos, NESTEGG_SEEK_SET); 1.1595 + if (r != 0) 1.1596 + return -1; 1.1597 + ctx->last_valid = 0; 1.1598 + 1.1599 + r = ne_read_element(ctx, &id, NULL); 1.1600 + if (r != 1) 1.1601 + return -1; 1.1602 + 1.1603 + if (id != ID_CUES) 1.1604 + return -1; 1.1605 + 1.1606 + ctx->ancestor = NULL; 1.1607 + if (ne_ctx_push(ctx, ne_top_level_elements, ctx) < 0) 1.1608 + return -1; 1.1609 + if (ne_ctx_push(ctx, ne_segment_elements, &ctx->segment) < 0) 1.1610 + return -1; 1.1611 + if (ne_ctx_push(ctx, ne_cues_elements, &ctx->segment.cues) < 0) 1.1612 + return -1; 1.1613 + /* parser will run until end of cues element. */ 1.1614 + ctx->log(ctx, NESTEGG_LOG_DEBUG, "seek: parsing cue elements"); 1.1615 + r = ne_parse(ctx, ne_cues_elements, max_offset); 1.1616 + while (ctx->ancestor) 1.1617 + ne_ctx_pop(ctx); 1.1618 + 1.1619 + /* Reset parser state to original state and seek back to old position. */ 1.1620 + if (ne_ctx_restore(ctx, &state) != 0) 1.1621 + return -1; 1.1622 + 1.1623 + if (r < 0) 1.1624 + return -1; 1.1625 + 1.1626 + node = ctx->segment.cues.cue_point.head; 1.1627 + if (!node) 1.1628 + return -1; 1.1629 + } 1.1630 + 1.1631 + return 0; 1.1632 +} 1.1633 + 1.1634 +/* Three functions that implement the nestegg_io interface, operating on a 1.1635 + * sniff_buffer. */ 1.1636 +struct sniff_buffer { 1.1637 + unsigned char const * buffer; 1.1638 + size_t length; 1.1639 + int64_t offset; 1.1640 +}; 1.1641 + 1.1642 +static int 1.1643 +ne_buffer_read(void * buffer, size_t length, void * user_data) 1.1644 +{ 1.1645 + struct sniff_buffer * sb = user_data; 1.1646 + 1.1647 + int rv = 1; 1.1648 + size_t available = sb->length - sb->offset; 1.1649 + 1.1650 + if (available < length) 1.1651 + return 0; 1.1652 + 1.1653 + memcpy(buffer, sb->buffer + sb->offset, length); 1.1654 + sb->offset += length; 1.1655 + 1.1656 + return rv; 1.1657 +} 1.1658 + 1.1659 +static int 1.1660 +ne_buffer_seek(int64_t offset, int whence, void * user_data) 1.1661 +{ 1.1662 + struct sniff_buffer * sb = user_data; 1.1663 + int64_t o = sb->offset; 1.1664 + 1.1665 + switch(whence) { 1.1666 + case NESTEGG_SEEK_SET: 1.1667 + o = offset; 1.1668 + break; 1.1669 + case NESTEGG_SEEK_CUR: 1.1670 + o += offset; 1.1671 + break; 1.1672 + case NESTEGG_SEEK_END: 1.1673 + o = sb->length + offset; 1.1674 + break; 1.1675 + } 1.1676 + 1.1677 + if (o < 0 || o > (int64_t) sb->length) 1.1678 + return -1; 1.1679 + 1.1680 + sb->offset = o; 1.1681 + return 0; 1.1682 +} 1.1683 + 1.1684 +static int64_t 1.1685 +ne_buffer_tell(void * user_data) 1.1686 +{ 1.1687 + struct sniff_buffer * sb = user_data; 1.1688 + return sb->offset; 1.1689 +} 1.1690 + 1.1691 +static int 1.1692 +ne_match_webm(nestegg_io io, int64_t max_offset) 1.1693 +{ 1.1694 + int r; 1.1695 + uint64_t id; 1.1696 + char * doctype; 1.1697 + nestegg * ctx; 1.1698 + 1.1699 + if (!(io.read && io.seek && io.tell)) 1.1700 + return -1; 1.1701 + 1.1702 + ctx = ne_alloc(sizeof(*ctx)); 1.1703 + if (!ctx) 1.1704 + return -1; 1.1705 + 1.1706 + ctx->io = ne_alloc(sizeof(*ctx->io)); 1.1707 + if (!ctx->io) { 1.1708 + nestegg_destroy(ctx); 1.1709 + return -1; 1.1710 + } 1.1711 + *ctx->io = io; 1.1712 + ctx->alloc_pool = ne_pool_init(); 1.1713 + if (!ctx->alloc_pool) { 1.1714 + nestegg_destroy(ctx); 1.1715 + return -1; 1.1716 + } 1.1717 + ctx->log = ne_null_log_callback; 1.1718 + 1.1719 + r = ne_peek_element(ctx, &id, NULL); 1.1720 + if (r != 1) { 1.1721 + nestegg_destroy(ctx); 1.1722 + return 0; 1.1723 + } 1.1724 + 1.1725 + if (id != ID_EBML) { 1.1726 + nestegg_destroy(ctx); 1.1727 + return 0; 1.1728 + } 1.1729 + 1.1730 + ne_ctx_push(ctx, ne_top_level_elements, ctx); 1.1731 + 1.1732 + /* we don't check the return value of ne_parse, that might fail because 1.1733 + * max_offset is not on a valid element end point. We only want to check 1.1734 + * the EBML ID and that the doctype is "webm". */ 1.1735 + ne_parse(ctx, NULL, max_offset); 1.1736 + 1.1737 + if (ne_get_string(ctx->ebml.doctype, &doctype) != 0 || 1.1738 + strcmp(doctype, "webm") != 0) { 1.1739 + nestegg_destroy(ctx); 1.1740 + return 0; 1.1741 + } 1.1742 + 1.1743 + nestegg_destroy(ctx); 1.1744 + 1.1745 + return 1; 1.1746 +} 1.1747 + 1.1748 +int 1.1749 +nestegg_init(nestegg ** context, nestegg_io io, nestegg_log callback, int64_t max_offset) 1.1750 +{ 1.1751 + int r; 1.1752 + uint64_t id, version, docversion; 1.1753 + struct ebml_list_node * track; 1.1754 + char * doctype; 1.1755 + nestegg * ctx; 1.1756 + 1.1757 + if (!(io.read && io.seek && io.tell)) 1.1758 + return -1; 1.1759 + 1.1760 + ctx = ne_alloc(sizeof(*ctx)); 1.1761 + if (!ctx) 1.1762 + return -1; 1.1763 + 1.1764 + ctx->io = ne_alloc(sizeof(*ctx->io)); 1.1765 + if (!ctx->io) { 1.1766 + nestegg_destroy(ctx); 1.1767 + return -1; 1.1768 + } 1.1769 + *ctx->io = io; 1.1770 + ctx->log = callback; 1.1771 + ctx->alloc_pool = ne_pool_init(); 1.1772 + if (!ctx->alloc_pool) { 1.1773 + nestegg_destroy(ctx); 1.1774 + return -1; 1.1775 + } 1.1776 + 1.1777 + if (!ctx->log) 1.1778 + ctx->log = ne_null_log_callback; 1.1779 + 1.1780 + r = ne_peek_element(ctx, &id, NULL); 1.1781 + if (r != 1) { 1.1782 + nestegg_destroy(ctx); 1.1783 + return -1; 1.1784 + } 1.1785 + 1.1786 + if (id != ID_EBML) { 1.1787 + nestegg_destroy(ctx); 1.1788 + return -1; 1.1789 + } 1.1790 + 1.1791 + ctx->log(ctx, NESTEGG_LOG_DEBUG, "ctx %p", ctx); 1.1792 + 1.1793 + ne_ctx_push(ctx, ne_top_level_elements, ctx); 1.1794 + 1.1795 + r = ne_parse(ctx, NULL, max_offset); 1.1796 + 1.1797 + if (r != 1) { 1.1798 + nestegg_destroy(ctx); 1.1799 + return -1; 1.1800 + } 1.1801 + 1.1802 + if (ne_get_uint(ctx->ebml.ebml_read_version, &version) != 0) 1.1803 + version = 1; 1.1804 + if (version != 1) { 1.1805 + nestegg_destroy(ctx); 1.1806 + return -1; 1.1807 + } 1.1808 + 1.1809 + if (ne_get_string(ctx->ebml.doctype, &doctype) != 0) 1.1810 + doctype = "matroska"; 1.1811 + if (strcmp(doctype, "webm") != 0) { 1.1812 + nestegg_destroy(ctx); 1.1813 + return -1; 1.1814 + } 1.1815 + 1.1816 + if (ne_get_uint(ctx->ebml.doctype_read_version, &docversion) != 0) 1.1817 + docversion = 1; 1.1818 + if (docversion < 1 || docversion > 2) { 1.1819 + nestegg_destroy(ctx); 1.1820 + return -1; 1.1821 + } 1.1822 + 1.1823 + if (!ctx->segment.tracks.track_entry.head) { 1.1824 + nestegg_destroy(ctx); 1.1825 + return -1; 1.1826 + } 1.1827 + 1.1828 + track = ctx->segment.tracks.track_entry.head; 1.1829 + ctx->track_count = 0; 1.1830 + 1.1831 + while (track) { 1.1832 + ctx->track_count += 1; 1.1833 + track = track->next; 1.1834 + } 1.1835 + 1.1836 + *context = ctx; 1.1837 + 1.1838 + return 0; 1.1839 +} 1.1840 + 1.1841 +void 1.1842 +nestegg_destroy(nestegg * ctx) 1.1843 +{ 1.1844 + while (ctx->ancestor) 1.1845 + ne_ctx_pop(ctx); 1.1846 + ne_pool_destroy(ctx->alloc_pool); 1.1847 + free(ctx->io); 1.1848 + free(ctx); 1.1849 +} 1.1850 + 1.1851 +int 1.1852 +nestegg_duration(nestegg * ctx, uint64_t * duration) 1.1853 +{ 1.1854 + uint64_t tc_scale; 1.1855 + double unscaled_duration; 1.1856 + 1.1857 + if (ne_get_float(ctx->segment.info.duration, &unscaled_duration) != 0) 1.1858 + return -1; 1.1859 + 1.1860 + tc_scale = ne_get_timecode_scale(ctx); 1.1861 + 1.1862 + *duration = (uint64_t) (unscaled_duration * tc_scale); 1.1863 + return 0; 1.1864 +} 1.1865 + 1.1866 +int 1.1867 +nestegg_tstamp_scale(nestegg * ctx, uint64_t * scale) 1.1868 +{ 1.1869 + *scale = ne_get_timecode_scale(ctx); 1.1870 + return 0; 1.1871 +} 1.1872 + 1.1873 +int 1.1874 +nestegg_track_count(nestegg * ctx, unsigned int * tracks) 1.1875 +{ 1.1876 + *tracks = ctx->track_count; 1.1877 + return 0; 1.1878 +} 1.1879 + 1.1880 +int 1.1881 +nestegg_get_cue_point(nestegg * ctx, unsigned int cluster_num, int64_t max_offset, 1.1882 + int64_t * start_pos, int64_t * end_pos, uint64_t * tstamp) 1.1883 +{ 1.1884 + int range_obtained = 0; 1.1885 + unsigned int cluster_count = 0; 1.1886 + struct cue_point * cue_point; 1.1887 + struct cue_track_positions * pos; 1.1888 + uint64_t seek_pos, track_number, tc_scale, time; 1.1889 + struct ebml_list_node * cues_node = ctx->segment.cues.cue_point.head; 1.1890 + struct ebml_list_node * cue_pos_node = NULL; 1.1891 + unsigned int track = 0, track_count = 0, track_index; 1.1892 + 1.1893 + if (!start_pos || !end_pos || !tstamp) 1.1894 + return -1; 1.1895 + 1.1896 + /* Initialise return values */ 1.1897 + *start_pos = -1; 1.1898 + *end_pos = -1; 1.1899 + *tstamp = 0; 1.1900 + 1.1901 + if (!cues_node) { 1.1902 + ne_init_cue_points(ctx, max_offset); 1.1903 + cues_node = ctx->segment.cues.cue_point.head; 1.1904 + /* Verify cues have been added to context. */ 1.1905 + if (!cues_node) 1.1906 + return -1; 1.1907 + } 1.1908 + 1.1909 + nestegg_track_count(ctx, &track_count); 1.1910 + 1.1911 + tc_scale = ne_get_timecode_scale(ctx); 1.1912 + 1.1913 + while (cues_node && !range_obtained) { 1.1914 + assert(cues_node->id == ID_CUE_POINT); 1.1915 + cue_point = cues_node->data; 1.1916 + cue_pos_node = cue_point->cue_track_positions.head; 1.1917 + while (cue_pos_node) { 1.1918 + assert(cue_pos_node->id == ID_CUE_TRACK_POSITIONS); 1.1919 + pos = cue_pos_node->data; 1.1920 + for (track = 0; track < track_count; track++) { 1.1921 + if (ne_get_uint(pos->track, &track_number) != 0) 1.1922 + return -1; 1.1923 + 1.1924 + if (ne_map_track_number_to_index(ctx, track_number, &track_index) != 0) 1.1925 + return -1; 1.1926 + 1.1927 + if (track_index == track) { 1.1928 + if (ne_get_uint(pos->cluster_position, &seek_pos) != 0) 1.1929 + return -1; 1.1930 + if (cluster_count == cluster_num) { 1.1931 + *start_pos = ctx->segment_offset+seek_pos; 1.1932 + if (ne_get_uint(cue_point->time, &time) != 0) 1.1933 + return -1; 1.1934 + *tstamp = time * tc_scale; 1.1935 + } else if (cluster_count == cluster_num+1) { 1.1936 + *end_pos = (ctx->segment_offset+seek_pos)-1; 1.1937 + range_obtained = 1; 1.1938 + break; 1.1939 + } 1.1940 + cluster_count++; 1.1941 + } 1.1942 + } 1.1943 + cue_pos_node = cue_pos_node->next; 1.1944 + } 1.1945 + cues_node = cues_node->next; 1.1946 + } 1.1947 + 1.1948 + return 0; 1.1949 +} 1.1950 + 1.1951 +int 1.1952 +nestegg_offset_seek(nestegg * ctx, uint64_t offset) 1.1953 +{ 1.1954 + int r; 1.1955 + 1.1956 + if (offset > INT64_MAX) 1.1957 + return -1; 1.1958 + 1.1959 + /* Seek and set up parser state for segment-level element (Cluster). */ 1.1960 + r = ne_io_seek(ctx->io, offset, NESTEGG_SEEK_SET); 1.1961 + if (r != 0) 1.1962 + return -1; 1.1963 + ctx->last_valid = 0; 1.1964 + 1.1965 + while (ctx->ancestor) 1.1966 + ne_ctx_pop(ctx); 1.1967 + 1.1968 + ne_ctx_push(ctx, ne_top_level_elements, ctx); 1.1969 + ne_ctx_push(ctx, ne_segment_elements, &ctx->segment); 1.1970 + 1.1971 + ctx->log(ctx, NESTEGG_LOG_DEBUG, "seek: parsing cluster elements"); 1.1972 + r = ne_parse(ctx, NULL, -1); 1.1973 + if (r != 1) 1.1974 + return -1; 1.1975 + 1.1976 + return 0; 1.1977 +} 1.1978 + 1.1979 +int 1.1980 +nestegg_track_seek(nestegg * ctx, unsigned int track, uint64_t tstamp) 1.1981 +{ 1.1982 + int r; 1.1983 + struct cue_point * cue_point; 1.1984 + struct cue_track_positions * pos; 1.1985 + uint64_t seek_pos, tc_scale; 1.1986 + 1.1987 + /* If there are no cues loaded, check for cues element in the seek head 1.1988 + and load it. */ 1.1989 + if (!ctx->segment.cues.cue_point.head) { 1.1990 + r = ne_init_cue_points(ctx, -1); 1.1991 + if (r != 0) 1.1992 + return -1; 1.1993 + } 1.1994 + 1.1995 + tc_scale = ne_get_timecode_scale(ctx); 1.1996 + 1.1997 + cue_point = ne_find_cue_point_for_tstamp(ctx, ctx->segment.cues.cue_point.head, 1.1998 + track, tc_scale, tstamp); 1.1999 + if (!cue_point) 1.2000 + return -1; 1.2001 + 1.2002 + pos = ne_find_cue_position_for_track(ctx, cue_point->cue_track_positions.head, track); 1.2003 + if (pos == NULL) 1.2004 + return -1; 1.2005 + 1.2006 + if (ne_get_uint(pos->cluster_position, &seek_pos) != 0) 1.2007 + return -1; 1.2008 + 1.2009 + /* Seek and set up parser state for segment-level element (Cluster). */ 1.2010 + r = nestegg_offset_seek(ctx, ctx->segment_offset + seek_pos); 1.2011 + 1.2012 + if (!ne_is_suspend_element(ctx->last_id)) 1.2013 + return -1; 1.2014 + 1.2015 + return 0; 1.2016 +} 1.2017 + 1.2018 +int 1.2019 +nestegg_track_type(nestegg * ctx, unsigned int track) 1.2020 +{ 1.2021 + struct track_entry * entry; 1.2022 + uint64_t type; 1.2023 + 1.2024 + entry = ne_find_track_entry(ctx, track); 1.2025 + if (!entry) 1.2026 + return -1; 1.2027 + 1.2028 + if (ne_get_uint(entry->type, &type) != 0) 1.2029 + return -1; 1.2030 + 1.2031 + if (type & TRACK_TYPE_VIDEO) 1.2032 + return NESTEGG_TRACK_VIDEO; 1.2033 + 1.2034 + if (type & TRACK_TYPE_AUDIO) 1.2035 + return NESTEGG_TRACK_AUDIO; 1.2036 + 1.2037 + return -1; 1.2038 +} 1.2039 + 1.2040 +int 1.2041 +nestegg_track_codec_id(nestegg * ctx, unsigned int track) 1.2042 +{ 1.2043 + char * codec_id; 1.2044 + struct track_entry * entry; 1.2045 + 1.2046 + entry = ne_find_track_entry(ctx, track); 1.2047 + if (!entry) 1.2048 + return -1; 1.2049 + 1.2050 + if (ne_get_string(entry->codec_id, &codec_id) != 0) 1.2051 + return -1; 1.2052 + 1.2053 + if (strcmp(codec_id, TRACK_ID_VP8) == 0) 1.2054 + return NESTEGG_CODEC_VP8; 1.2055 + 1.2056 + if (strcmp(codec_id, TRACK_ID_VP9) == 0) 1.2057 + return NESTEGG_CODEC_VP9; 1.2058 + 1.2059 + if (strcmp(codec_id, TRACK_ID_VORBIS) == 0) 1.2060 + return NESTEGG_CODEC_VORBIS; 1.2061 + 1.2062 + if (strcmp(codec_id, TRACK_ID_OPUS) == 0) 1.2063 + return NESTEGG_CODEC_OPUS; 1.2064 + 1.2065 + return -1; 1.2066 +} 1.2067 + 1.2068 +int 1.2069 +nestegg_track_codec_data_count(nestegg * ctx, unsigned int track, 1.2070 + unsigned int * count) 1.2071 +{ 1.2072 + struct track_entry * entry; 1.2073 + struct ebml_binary codec_private; 1.2074 + unsigned char * p; 1.2075 + 1.2076 + *count = 0; 1.2077 + 1.2078 + entry = ne_find_track_entry(ctx, track); 1.2079 + if (!entry) 1.2080 + return -1; 1.2081 + 1.2082 + if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS) 1.2083 + return -1; 1.2084 + 1.2085 + if (ne_get_binary(entry->codec_private, &codec_private) != 0) 1.2086 + return -1; 1.2087 + 1.2088 + if (codec_private.length < 1) 1.2089 + return -1; 1.2090 + 1.2091 + p = codec_private.data; 1.2092 + *count = *p + 1; 1.2093 + 1.2094 + if (*count > 3) 1.2095 + return -1; 1.2096 + 1.2097 + return 0; 1.2098 +} 1.2099 + 1.2100 +int 1.2101 +nestegg_track_codec_data(nestegg * ctx, unsigned int track, unsigned int item, 1.2102 + unsigned char ** data, size_t * length) 1.2103 +{ 1.2104 + struct track_entry * entry; 1.2105 + struct ebml_binary codec_private; 1.2106 + uint64_t sizes[3], total; 1.2107 + unsigned char * p; 1.2108 + unsigned int count, i; 1.2109 + 1.2110 + *data = NULL; 1.2111 + *length = 0; 1.2112 + 1.2113 + entry = ne_find_track_entry(ctx, track); 1.2114 + if (!entry) 1.2115 + return -1; 1.2116 + 1.2117 + if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS 1.2118 + && nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_OPUS) 1.2119 + return -1; 1.2120 + 1.2121 + if (ne_get_binary(entry->codec_private, &codec_private) != 0) 1.2122 + return -1; 1.2123 + 1.2124 + if (nestegg_track_codec_id(ctx, track) == NESTEGG_CODEC_VORBIS) { 1.2125 + p = codec_private.data; 1.2126 + count = *p++ + 1; 1.2127 + 1.2128 + if (count > 3) 1.2129 + return -1; 1.2130 + 1.2131 + i = 0; 1.2132 + total = 0; 1.2133 + while (--count) { 1.2134 + sizes[i] = ne_xiph_lace_value(&p); 1.2135 + total += sizes[i]; 1.2136 + i += 1; 1.2137 + } 1.2138 + sizes[i] = codec_private.length - total - (p - codec_private.data); 1.2139 + 1.2140 + for (i = 0; i < item; ++i) { 1.2141 + if (sizes[i] > LIMIT_FRAME) 1.2142 + return -1; 1.2143 + p += sizes[i]; 1.2144 + } 1.2145 + *data = p; 1.2146 + *length = sizes[item]; 1.2147 + } else { 1.2148 + *data = codec_private.data; 1.2149 + *length = codec_private.length; 1.2150 + } 1.2151 + 1.2152 + return 0; 1.2153 +} 1.2154 + 1.2155 +int 1.2156 +nestegg_track_video_params(nestegg * ctx, unsigned int track, 1.2157 + nestegg_video_params * params) 1.2158 +{ 1.2159 + struct track_entry * entry; 1.2160 + uint64_t value; 1.2161 + 1.2162 + memset(params, 0, sizeof(*params)); 1.2163 + 1.2164 + entry = ne_find_track_entry(ctx, track); 1.2165 + if (!entry) 1.2166 + return -1; 1.2167 + 1.2168 + if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_VIDEO) 1.2169 + return -1; 1.2170 + 1.2171 + value = 0; 1.2172 + ne_get_uint(entry->video.stereo_mode, &value); 1.2173 + if (value <= NESTEGG_VIDEO_STEREO_TOP_BOTTOM || 1.2174 + value == NESTEGG_VIDEO_STEREO_RIGHT_LEFT) 1.2175 + params->stereo_mode = value; 1.2176 + 1.2177 + if (ne_get_uint(entry->video.pixel_width, &value) != 0) 1.2178 + return -1; 1.2179 + params->width = value; 1.2180 + 1.2181 + if (ne_get_uint(entry->video.pixel_height, &value) != 0) 1.2182 + return -1; 1.2183 + params->height = value; 1.2184 + 1.2185 + value = 0; 1.2186 + ne_get_uint(entry->video.pixel_crop_bottom, &value); 1.2187 + params->crop_bottom = value; 1.2188 + 1.2189 + value = 0; 1.2190 + ne_get_uint(entry->video.pixel_crop_top, &value); 1.2191 + params->crop_top = value; 1.2192 + 1.2193 + value = 0; 1.2194 + ne_get_uint(entry->video.pixel_crop_left, &value); 1.2195 + params->crop_left = value; 1.2196 + 1.2197 + value = 0; 1.2198 + ne_get_uint(entry->video.pixel_crop_right, &value); 1.2199 + params->crop_right = value; 1.2200 + 1.2201 + value = params->width; 1.2202 + ne_get_uint(entry->video.display_width, &value); 1.2203 + params->display_width = value; 1.2204 + 1.2205 + value = params->height; 1.2206 + ne_get_uint(entry->video.display_height, &value); 1.2207 + params->display_height = value; 1.2208 + 1.2209 + return 0; 1.2210 +} 1.2211 + 1.2212 +int 1.2213 +nestegg_track_audio_params(nestegg * ctx, unsigned int track, 1.2214 + nestegg_audio_params * params) 1.2215 +{ 1.2216 + struct track_entry * entry; 1.2217 + uint64_t value; 1.2218 + 1.2219 + memset(params, 0, sizeof(*params)); 1.2220 + 1.2221 + entry = ne_find_track_entry(ctx, track); 1.2222 + if (!entry) 1.2223 + return -1; 1.2224 + 1.2225 + if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_AUDIO) 1.2226 + return -1; 1.2227 + 1.2228 + params->rate = 8000; 1.2229 + ne_get_float(entry->audio.sampling_frequency, ¶ms->rate); 1.2230 + 1.2231 + value = 1; 1.2232 + ne_get_uint(entry->audio.channels, &value); 1.2233 + params->channels = value; 1.2234 + 1.2235 + value = 16; 1.2236 + ne_get_uint(entry->audio.bit_depth, &value); 1.2237 + params->depth = value; 1.2238 + 1.2239 + value = 0; 1.2240 + ne_get_uint(entry->codec_delay, &value); 1.2241 + params->codec_delay = value; 1.2242 + 1.2243 + value = 0; 1.2244 + ne_get_uint(entry->seek_preroll, &value); 1.2245 + params->seek_preroll = value; 1.2246 + 1.2247 + return 0; 1.2248 +} 1.2249 + 1.2250 +int 1.2251 +nestegg_track_default_duration(nestegg * ctx, unsigned int track, 1.2252 + uint64_t * duration) 1.2253 +{ 1.2254 + struct track_entry * entry; 1.2255 + uint64_t value; 1.2256 + 1.2257 + entry = ne_find_track_entry(ctx, track); 1.2258 + if (!entry) 1.2259 + return -1; 1.2260 + 1.2261 + if (ne_get_uint(entry->default_duration, &value) != 0) 1.2262 + return -1; 1.2263 + *duration = value; 1.2264 + 1.2265 + return 0; 1.2266 +} 1.2267 + 1.2268 +int 1.2269 +nestegg_read_packet(nestegg * ctx, nestegg_packet ** pkt) 1.2270 +{ 1.2271 + int r; 1.2272 + uint64_t id, size; 1.2273 + 1.2274 + *pkt = NULL; 1.2275 + 1.2276 + for (;;) { 1.2277 + r = ne_peek_element(ctx, &id, &size); 1.2278 + if (r != 1) 1.2279 + return r; 1.2280 + 1.2281 + /* Any DESC_FLAG_SUSPEND fields must be handled here. */ 1.2282 + if (ne_is_suspend_element(id)) { 1.2283 + r = ne_read_element(ctx, &id, &size); 1.2284 + if (r != 1) 1.2285 + return r; 1.2286 + 1.2287 + /* The only DESC_FLAG_SUSPEND fields are Blocks and SimpleBlocks, which we 1.2288 + handle directly. */ 1.2289 + r = ne_read_block(ctx, id, size, pkt); 1.2290 + if (r != 1) 1.2291 + return r; 1.2292 + 1.2293 + r = ne_read_block_duration(ctx, *pkt); 1.2294 + if (r != 1) 1.2295 + return r; 1.2296 + 1.2297 + r = ne_read_discard_padding(ctx, *pkt); 1.2298 + if (r != 1) 1.2299 + return r; 1.2300 + 1.2301 + return r; 1.2302 + } 1.2303 + 1.2304 + r = ne_parse(ctx, NULL, -1); 1.2305 + if (r != 1) 1.2306 + return r; 1.2307 + } 1.2308 + 1.2309 + return 1; 1.2310 +} 1.2311 + 1.2312 +void 1.2313 +nestegg_free_packet(nestegg_packet * pkt) 1.2314 +{ 1.2315 + struct frame * frame; 1.2316 + 1.2317 + while (pkt->frame) { 1.2318 + frame = pkt->frame; 1.2319 + pkt->frame = frame->next; 1.2320 + free(frame->data); 1.2321 + free(frame); 1.2322 + } 1.2323 + 1.2324 + free(pkt); 1.2325 +} 1.2326 + 1.2327 +int 1.2328 +nestegg_packet_track(nestegg_packet * pkt, unsigned int * track) 1.2329 +{ 1.2330 + *track = pkt->track; 1.2331 + return 0; 1.2332 +} 1.2333 + 1.2334 +int 1.2335 +nestegg_packet_tstamp(nestegg_packet * pkt, uint64_t * tstamp) 1.2336 +{ 1.2337 + *tstamp = pkt->timecode; 1.2338 + return 0; 1.2339 +} 1.2340 + 1.2341 +int 1.2342 +nestegg_packet_duration(nestegg_packet * pkt, uint64_t * duration) 1.2343 +{ 1.2344 + *duration = pkt->duration; 1.2345 + return 0; 1.2346 +} 1.2347 + 1.2348 +int 1.2349 +nestegg_packet_discard_padding(nestegg_packet * pkt, int64_t * discard_padding) 1.2350 +{ 1.2351 + *discard_padding = pkt->discard_padding; 1.2352 + return 0; 1.2353 +} 1.2354 + 1.2355 +int 1.2356 +nestegg_packet_count(nestegg_packet * pkt, unsigned int * count) 1.2357 +{ 1.2358 + struct frame * f = pkt->frame; 1.2359 + 1.2360 + *count = 0; 1.2361 + 1.2362 + while (f) { 1.2363 + *count += 1; 1.2364 + f = f->next; 1.2365 + } 1.2366 + 1.2367 + return 0; 1.2368 +} 1.2369 + 1.2370 +int 1.2371 +nestegg_packet_data(nestegg_packet * pkt, unsigned int item, 1.2372 + unsigned char ** data, size_t * length) 1.2373 +{ 1.2374 + struct frame * f = pkt->frame; 1.2375 + unsigned int count = 0; 1.2376 + 1.2377 + *data = NULL; 1.2378 + *length = 0; 1.2379 + 1.2380 + while (f) { 1.2381 + if (count == item) { 1.2382 + *data = f->data; 1.2383 + *length = f->length; 1.2384 + return 0; 1.2385 + } 1.2386 + count += 1; 1.2387 + f = f->next; 1.2388 + } 1.2389 + 1.2390 + return -1; 1.2391 +} 1.2392 + 1.2393 +int 1.2394 +nestegg_has_cues(nestegg * ctx) 1.2395 +{ 1.2396 + return ctx->segment.cues.cue_point.head || 1.2397 + ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES); 1.2398 +} 1.2399 + 1.2400 +int 1.2401 +nestegg_sniff(unsigned char const * buffer, size_t length) 1.2402 +{ 1.2403 + nestegg_io io; 1.2404 + struct sniff_buffer user_data; 1.2405 + 1.2406 + user_data.buffer = buffer; 1.2407 + user_data.length = length; 1.2408 + user_data.offset = 0; 1.2409 + 1.2410 + io.read = ne_buffer_read; 1.2411 + io.seek = ne_buffer_seek; 1.2412 + io.tell = ne_buffer_tell; 1.2413 + io.userdata = &user_data; 1.2414 + return ne_match_webm(io, length); 1.2415 +} 1.2416 + 1.2417 +void 1.2418 +nestegg_set_halloc_func(void * (* realloc_func)(void *, size_t)) 1.2419 +{ 1.2420 + halloc_allocator = realloc_func; 1.2421 +}