Bug Summary

File:root/firefox-clang/obj-x86_64-pc-linux-gnu/media/libnestegg/src/./../../../../media/libnestegg/src/nestegg.c
Warning:line 516, column 8
Excessive padding in 'struct ebml_element_desc' (8 padding bytes, where 0 is optimal). Optimal fields order: name, id, offset, children, size, data_offset, default_uint, default_float, type, flags, consider reordering the fields or adding explicit padding members

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_c_media_libnestegg_src0.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/media/libnestegg/src -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/media/libnestegg/src -resource-dir /usr/lib/llvm-23/lib/clang/23 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D DEBUG=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/media/libnestegg/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/media/libnestegg/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/llvm-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-character-conversion -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c Unified_c_media_libnestegg_src0.c
1/*
2 * Copyright © 2010 Mozilla Foundation
3 *
4 * This program is made available under an ISC-style license. See the
5 * accompanying file LICENSE for details.
6 */
7#include <assert.h>
8#include <stddef.h>
9#include <stdlib.h>
10#include <string.h>
11
12#include "nestegg/nestegg.h"
13
14/* EBML Elements */
15#define ID_EBML0x1a45dfa3 0x1a45dfa3
16#define ID_EBML_VERSION0x4286 0x4286
17#define ID_EBML_READ_VERSION0x42f7 0x42f7
18#define ID_EBML_MAX_ID_LENGTH0x42f2 0x42f2
19#define ID_EBML_MAX_SIZE_LENGTH0x42f3 0x42f3
20#define ID_DOCTYPE0x4282 0x4282
21#define ID_DOCTYPE_VERSION0x4287 0x4287
22#define ID_DOCTYPE_READ_VERSION0x4285 0x4285
23
24/* Global Elements */
25#define ID_VOID0xec 0xec
26#define ID_CRC320xbf 0xbf
27
28/* WebM Elements */
29#define ID_SEGMENT0x18538067 0x18538067
30
31/* Seek Head Elements */
32#define ID_SEEK_HEAD0x114d9b74 0x114d9b74
33#define ID_SEEK0x4dbb 0x4dbb
34#define ID_SEEK_ID0x53ab 0x53ab
35#define ID_SEEK_POSITION0x53ac 0x53ac
36
37/* Info Elements */
38#define ID_INFO0x1549a966 0x1549a966
39#define ID_TIMECODE_SCALE0x2ad7b1 0x2ad7b1
40#define ID_DURATION0x4489 0x4489
41
42/* Cluster Elements */
43#define ID_CLUSTER0x1f43b675 0x1f43b675
44#define ID_TIMECODE0xe7 0xe7
45#define ID_BLOCK_GROUP0xa0 0xa0
46#define ID_SIMPLE_BLOCK0xa3 0xa3
47
48/* BlockGroup Elements */
49#define ID_BLOCK0xa1 0xa1
50#define ID_BLOCK_ADDITIONS0x75a1 0x75a1
51#define ID_BLOCK_DURATION0x9b 0x9b
52#define ID_REFERENCE_BLOCK0xfb 0xfb
53#define ID_DISCARD_PADDING0x75a2 0x75a2
54
55/* BlockAdditions Elements */
56#define ID_BLOCK_MORE0xa6 0xa6
57
58/* BlockMore Elements */
59#define ID_BLOCK_ADD_ID0xee 0xee
60#define ID_BLOCK_ADDITIONAL0xa5 0xa5
61
62/* Tracks Elements */
63#define ID_TRACKS0x1654ae6b 0x1654ae6b
64#define ID_TRACK_ENTRY0xae 0xae
65#define ID_TRACK_NUMBER0xd7 0xd7
66#define ID_TRACK_UID0x73c5 0x73c5
67#define ID_TRACK_TYPE0x83 0x83
68#define ID_FLAG_ENABLED0xb9 0xb9
69#define ID_FLAG_DEFAULT0x88 0x88
70#define ID_FLAG_LACING0x9c 0x9c
71#define ID_TRACK_TIMECODE_SCALE0x23314f 0x23314f
72#define ID_LANGUAGE0x22b59c 0x22b59c
73#define ID_CODEC_ID0x86 0x86
74#define ID_CODEC_PRIVATE0x63a2 0x63a2
75#define ID_CODEC_DELAY0x56aa 0x56aa
76#define ID_SEEK_PREROLL0x56bb 0x56bb
77#define ID_DEFAULT_DURATION0x23e383 0x23e383
78
79/* Video Elements */
80#define ID_VIDEO0xe0 0xe0
81#define ID_STEREO_MODE0x53b8 0x53b8
82#define ID_ALPHA_MODE0x53c0 0x53c0
83#define ID_PIXEL_WIDTH0xb0 0xb0
84#define ID_PIXEL_HEIGHT0xba 0xba
85#define ID_PIXEL_CROP_BOTTOM0x54aa 0x54aa
86#define ID_PIXEL_CROP_TOP0x54bb 0x54bb
87#define ID_PIXEL_CROP_LEFT0x54cc 0x54cc
88#define ID_PIXEL_CROP_RIGHT0x54dd 0x54dd
89#define ID_DISPLAY_WIDTH0x54b0 0x54b0
90#define ID_DISPLAY_HEIGHT0x54ba 0x54ba
91#define ID_COLOUR0x55b0 0x55b0
92#define ID_PROJECTION0x7670 0x7670
93
94/* Audio Elements */
95#define ID_AUDIO0xe1 0xe1
96#define ID_SAMPLING_FREQUENCY0xb5 0xb5
97#define ID_CHANNELS0x9f 0x9f
98#define ID_BIT_DEPTH0x6264 0x6264
99
100/* Cues Elements */
101#define ID_CUES0x1c53bb6b 0x1c53bb6b
102#define ID_CUE_POINT0xbb 0xbb
103#define ID_CUE_TIME0xb3 0xb3
104#define ID_CUE_TRACK_POSITIONS0xb7 0xb7
105#define ID_CUE_TRACK0xf7 0xf7
106#define ID_CUE_CLUSTER_POSITION0xf1 0xf1
107#define ID_CUE_BLOCK_NUMBER0x5378 0x5378
108
109/* Encoding Elements */
110#define ID_CONTENT_ENCODINGS0x6d80 0x6d80
111#define ID_CONTENT_ENCODING0x6240 0x6240
112#define ID_CONTENT_ENCODING_TYPE0x5033 0x5033
113
114/* Encryption Elements */
115#define ID_CONTENT_ENCRYPTION0x5035 0x5035
116#define ID_CONTENT_ENC_ALGO0x47e1 0x47e1
117#define ID_CONTENT_ENC_KEY_ID0x47e2 0x47e2
118#define ID_CONTENT_ENC_AES_SETTINGS0x47e7 0x47e7
119#define ID_AES_SETTINGS_CIPHER_MODE0x47e8 0x47e8
120
121/* Colour Elements */
122#define ID_MATRIX_COEFFICIENTS0x55b1 0x55b1
123#define ID_RANGE0x55b9 0x55b9
124#define ID_TRANSFER_CHARACTERISTICS0x55ba 0x55ba
125#define ID_PRIMARIES0x55bb 0x55bb
126#define ID_MAX_CLL0x55bc 0x55bc
127#define ID_MAX_FALL0x55bd 0x55bd
128#define ID_MASTERING_METADATA0x55d0 0x55d0
129
130/* MasteringMetadata Elements */
131#define ID_PRIMARY_R_CHROMATICITY_X0x55d1 0x55d1
132#define ID_PRIMARY_R_CHROMATICITY_Y0x55d2 0x55d2
133#define ID_PRIMARY_G_CHROMATICITY_X0x55d3 0x55d3
134#define ID_PRIMARY_G_CHROMATICITY_Y0x55d4 0x55d4
135#define ID_PRIMARY_B_CHROMATICITY_X0x55d5 0x55d5
136#define ID_PRIMARY_B_CHROMATICITY_Y0x55d6 0x55d6
137#define ID_WHITE_POINT_CHROMATICITY_X0x55d7 0x55d7
138#define ID_WHITE_POINT_CHROMATICITY_Y0x55d8 0x55d8
139#define ID_LUMINANCE_MAX0x55d9 0x55d9
140#define ID_LUMINANCE_MIN0x55da 0x55da
141
142/* Projection Elements */
143#define ID_PROJECTION_TYPE0x7671 0x7671
144#define ID_PROJECTION_POSE_YAW0x7673 0x7673
145#define ID_PROJECTION_POSE_PITCH0x7674 0x7674
146#define ID_PROJECTION_POSE_ROLL0x7675 0x7675
147
148/* Other Elements */
149#define ID_CHAPTERS0x1043a770 0x1043a770
150#define ID_ATTACHMENTS0x1941a469 0x1941a469
151#define ID_TAGS0x1254c367 0x1254c367
152
153/* EBML Types */
154enum ebml_type_enum {
155 TYPE_UNKNOWN,
156 TYPE_MASTER,
157 TYPE_UINT,
158 TYPE_FLOAT,
159 TYPE_STRING,
160 TYPE_BINARY
161};
162
163/* Read state of an element's storage. EBML_READ_DEFAULT is established
164 before parsing for elements with a schema-declared default, so it does not
165 mean the element was present in the file. EBML_READ_EMPTY marks an element
166 that was present with a zero length payload but whose default only the
167 accessor can supply: it counts as read, but holds no value. */
168enum ebml_read_state {
169 EBML_UNREAD = 0,
170 EBML_READ_VALUE,
171 EBML_READ_DEFAULT,
172 EBML_READ_EMPTY
173};
174
175#define LIMIT_STRING(1 << 20) (1 << 20)
176#define LIMIT_BINARY(1 << 24) (1 << 24)
177#define LIMIT_BLOCK(1 << 30) (1 << 30)
178#define LIMIT_FRAME(1 << 28) (1 << 28)
179#define LIMIT_TRACKS1000U 1000U
180#define IO_BUFFER_SIZE8192 8192
181
182/* Field Flags */
183#define DESC_FLAG_NONE0 0
184#define DESC_FLAG_MULTI(1 << 0) (1 << 0)
185#define DESC_FLAG_SUSPEND(1 << 1) (1 << 1)
186#define DESC_FLAG_OFFSET(1 << 2) (1 << 2)
187#define DESC_FLAG_HAS_DEFAULT(1 << 3) (1 << 3)
188#define DESC_FLAG_ACCESSOR_DEFAULT(1 << 4) (1 << 4)
189
190/* Block Header Flags */
191#define SIMPLE_BLOCK_FLAGS_KEYFRAME(1 << 7) (1 << 7)
192#define BLOCK_FLAGS_LACING6 6
193
194/* Lacing Constants */
195#define LACING_NONE0 0
196#define LACING_XIPH1 1
197#define LACING_FIXED2 2
198#define LACING_EBML3 3
199
200/* Track Types */
201#define TRACK_TYPE_VIDEO1 1
202#define TRACK_TYPE_AUDIO2 2
203
204/* Track IDs */
205#define TRACK_ID_VP8"V_VP8" "V_VP8"
206#define TRACK_ID_VP9"V_VP9" "V_VP9"
207#define TRACK_ID_AV1"V_AV1" "V_AV1"
208#define TRACK_ID_VORBIS"A_VORBIS" "A_VORBIS"
209#define TRACK_ID_OPUS"A_OPUS" "A_OPUS"
210#define TRACK_ID_AVC"V_MPEG4/ISO/AVC" "V_MPEG4/ISO/AVC"
211#define TRACK_ID_HEVC"V_MPEGH/ISO/HEVC" "V_MPEGH/ISO/HEVC"
212#define TRACK_ID_AAC"A_AAC" "A_AAC"
213#define TRACK_ID_AAC_MP4_LC"A_AAC/MPEG4/LC" "A_AAC/MPEG4/LC"
214#define TRACK_ID_AAC_MP4_LC_SBR"A_AAC/MPEG4/LC/SBR" "A_AAC/MPEG4/LC/SBR"
215#define TRACK_ID_AAC_MP4_LTP"A_AAC/MPEG4/LTP" "A_AAC/MPEG4/LTP"
216#define TRACK_ID_AAC_MP4_MAIN"A_AAC/MPEG4/MAIN" "A_AAC/MPEG4/MAIN"
217#define TRACK_ID_AAC_MP4_SSR"A_AAC/MPEG4/SSR" "A_AAC/MPEG4/SSR"
218#define TRACK_ID_FLAC"A_FLAC" "A_FLAC"
219#define TRACK_ID_MP3"A_MPEG/L3" "A_MPEG/L3"
220#define TRACK_ID_PCM_FLOAT"A_PCM/FLOAT/IEEE" "A_PCM/FLOAT/IEEE"
221#define TRACK_ID_PCM_INT_BE"A_PCM/INT/BIG" "A_PCM/INT/BIG"
222#define TRACK_ID_PCM_INT_LE"A_PCM/INT/LIT" "A_PCM/INT/LIT"
223
224/* Track Encryption */
225#define CONTENT_ENC_ALGO_AES5 5
226#define AES_SETTINGS_CIPHER_CTR1 1
227
228/* Packet Encryption */
229#define SIGNAL_BYTE_SIZE1 1
230#define IV_SIZE8 8
231#define NUM_PACKETS_SIZE1 1
232#define PACKET_OFFSET_SIZE4 4
233
234/* Signal Byte */
235#define PACKET_ENCRYPTED1 1
236#define ENCRYPTED_BIT_MASK(1 << 0) (1 << 0)
237
238#define PACKET_PARTITIONED2 2
239#define PARTITIONED_BIT_MASK(1 << 1) (1 << 1)
240
241enum vint_mask {
242 MASK_NONE,
243 MASK_FIRST_BIT
244};
245
246struct ebml_binary {
247 unsigned char * data;
248 size_t length;
249};
250
251struct ebml_list_node {
252 struct ebml_list_node * next;
253 uint64_t id;
254 void * data;
255};
256
257struct ebml_list {
258 struct ebml_list_node * head;
259 struct ebml_list_node * tail;
260 size_t count;
261};
262
263struct ebml_type {
264 union ebml_value {
265 uint64_t u;
266 double f;
267 int64_t i;
268 char * s;
269 struct ebml_binary b;
270 } v;
271 enum ebml_type_enum type;
272 enum ebml_read_state read;
273};
274
275/* EBML Definitions */
276struct ebml {
277 struct ebml_type ebml_version;
278 struct ebml_type ebml_read_version;
279 struct ebml_type ebml_max_id_length;
280 struct ebml_type ebml_max_size_length;
281 struct ebml_type doctype;
282 struct ebml_type doctype_version;
283 struct ebml_type doctype_read_version;
284};
285
286#define DOCTYPE_WEBM"webm" "webm"
287#define DOCTYPE_MKV"matroska" "matroska"
288
289/* Matroksa Definitions */
290struct seek {
291 struct ebml_type id;
292 struct ebml_type position;
293};
294
295struct seek_head {
296 struct ebml_list seek;
297};
298
299struct info {
300 struct ebml_type timecode_scale;
301 struct ebml_type duration;
302};
303
304struct mastering_metadata {
305 struct ebml_type primary_r_chromacity_x;
306 struct ebml_type primary_r_chromacity_y;
307 struct ebml_type primary_g_chromacity_x;
308 struct ebml_type primary_g_chromacity_y;
309 struct ebml_type primary_b_chromacity_x;
310 struct ebml_type primary_b_chromacity_y;
311 struct ebml_type white_point_chromaticity_x;
312 struct ebml_type white_point_chromaticity_y;
313 struct ebml_type luminance_max;
314 struct ebml_type luminance_min;
315};
316
317struct colour {
318 struct ebml_type matrix_coefficients;
319 struct ebml_type range;
320 struct ebml_type transfer_characteristics;
321 struct ebml_type primaries;
322 struct ebml_type max_cll;
323 struct ebml_type max_fall;
324 struct mastering_metadata mastering_metadata;
325};
326
327struct projection {
328 struct ebml_type type;
329 struct ebml_type pose_yaw;
330 struct ebml_type pose_pitch;
331 struct ebml_type pose_roll;
332};
333
334struct video {
335 struct ebml_type stereo_mode;
336 struct ebml_type alpha_mode;
337 struct ebml_type pixel_width;
338 struct ebml_type pixel_height;
339 struct ebml_type pixel_crop_bottom;
340 struct ebml_type pixel_crop_top;
341 struct ebml_type pixel_crop_left;
342 struct ebml_type pixel_crop_right;
343 struct ebml_type display_width;
344 struct ebml_type display_height;
345 struct colour colour;
346 struct projection projection;
347};
348
349struct audio {
350 struct ebml_type sampling_frequency;
351 struct ebml_type channels;
352 struct ebml_type bit_depth;
353};
354
355struct content_enc_aes_settings {
356 struct ebml_type aes_settings_cipher_mode;
357};
358
359struct content_encryption {
360 struct ebml_type content_enc_algo;
361 struct ebml_type content_enc_key_id;
362 struct ebml_list content_enc_aes_settings;
363};
364
365struct content_encoding {
366 struct ebml_type content_encoding_type;
367 struct ebml_list content_encryption;
368};
369
370struct content_encodings {
371 struct ebml_list content_encoding;
372};
373
374struct track_entry {
375 struct ebml_type number;
376 struct ebml_type uid;
377 struct ebml_type type;
378 struct ebml_type flag_enabled;
379 struct ebml_type flag_default;
380 struct ebml_type flag_lacing;
381 struct ebml_type track_timecode_scale;
382 struct ebml_type language;
383 struct ebml_type codec_id;
384 struct ebml_type codec_private;
385 struct ebml_type codec_delay;
386 struct ebml_type seek_preroll;
387 struct ebml_type default_duration;
388 struct video video;
389 struct audio audio;
390 struct content_encodings content_encodings;
391};
392
393struct tracks {
394 struct ebml_list track_entry;
395};
396
397struct track_number_index {
398 uint64_t number;
399 unsigned int index;
400};
401
402struct cue_track_positions {
403 struct ebml_type track;
404 struct ebml_type cluster_position;
405 struct ebml_type block_number;
406};
407
408struct cue_point {
409 struct ebml_type time;
410 struct ebml_list cue_track_positions;
411};
412
413struct cues {
414 struct ebml_list cue_point;
415};
416
417struct segment {
418 struct ebml_list seek_head;
419 struct info info;
420 struct tracks tracks;
421 struct cues cues;
422};
423
424/* Misc. */
425struct pool_node {
426 struct pool_node * next;
427 void * data;
428};
429
430struct pool_ctx {
431 struct pool_node * head;
432};
433
434struct list_node {
435 struct list_node * previous;
436 struct ebml_element_desc * node;
437 unsigned char * data;
438};
439
440struct saved_state {
441 int64_t stream_offset;
442 uint64_t last_id;
443 uint64_t last_size;
444 int last_valid;
445};
446
447struct frame_encryption {
448 unsigned char * iv;
449 size_t length;
450 uint8_t signal_byte;
451 uint8_t num_partitions;
452 uint32_t * partition_offsets;
453};
454
455struct frame {
456 unsigned char * data;
457 size_t length;
458 struct frame_encryption * frame_encryption;
459};
460
461struct block_additional {
462 unsigned int id;
463 unsigned char * data;
464 size_t length;
465 struct block_additional * next;
466};
467
468/* Internal I/O wrapper. */
469typedef struct {
470 nestegg_io * io;
471 unsigned char buf[IO_BUFFER_SIZE8192];
472 size_t buf_offset;
473 size_t buf_fill;
474 int64_t max_offset; /* <= 0: no limit */
475 int poisoned; /* logical position is unknown until a successful seek */
476} ne_io;
477
478/* Public (opaque) Structures */
479struct nestegg {
480 ne_io io;
481 nestegg_log log;
482 struct pool_ctx * alloc_pool;
483 uint64_t last_id;
484 uint64_t last_size;
485 int last_valid;
486 struct list_node * ancestor;
487 struct ebml ebml;
488 struct segment segment;
489 int64_t segment_offset;
490 struct track_entry ** track_by_index;
491 struct track_number_index * track_by_number;
492 unsigned int track_count;
493 /* Last read cluster. */
494 uint64_t cluster_timecode;
495 int read_cluster_timecode;
496 struct saved_state saved;
497};
498
499struct nestegg_packet {
500 uint64_t track;
501 uint64_t timecode;
502 uint64_t duration;
503 int read_duration;
504 struct frame ** frames;
505 unsigned int frame_count;
506 struct block_additional * block_additional;
507 int64_t discard_padding;
508 int read_discard_padding;
509 int64_t reference_block;
510 int read_reference_block;
511 uint8_t keyframe;
512 int64_t end_offset;
513};
514
515/* Element Descriptor */
516struct ebml_element_desc {
Excessive padding in 'struct ebml_element_desc' (8 padding bytes, where 0 is optimal). Optimal fields order: name, id, offset, children, size, data_offset, default_uint, default_float, type, flags, consider reordering the fields or adding explicit padding members
517 char const * name;
518 uint64_t id;
519 enum ebml_type_enum type;
520 size_t offset;
521 unsigned int flags;
522 struct ebml_element_desc * children;
523 size_t size;
524 size_t data_offset;
525 /* Schema-declared default value, valid if DESC_FLAG_HAS_DEFAULT is set.
526 Stored as two scalars rather than a union to allow static
527 initialization in C89. An element whose default can't be expressed
528 here instead carries DESC_FLAG_ACCESSOR_DEFAULT and is resolved by the
529 accessor. */
530 uint64_t default_uint;
531 double default_float;
532};
533
534#define E_FIELD(ID, TYPE, STRUCT, FIELD) \
535 { #ID, ID, TYPE, offsetof(STRUCT, FIELD)__builtin_offsetof(STRUCT, FIELD), DESC_FLAG_NONE0, NULL((void*)0), 0, 0, 0, 0.0 }
536#define E_FIELD_DEFAULT_UINT(ID, STRUCT, FIELD, DEFAULT) \
537 { #ID, ID, TYPE_UINT, offsetof(STRUCT, FIELD)__builtin_offsetof(STRUCT, FIELD), DESC_FLAG_HAS_DEFAULT(1 << 3), NULL((void*)0), 0, 0, DEFAULT, 0.0 }
538#define E_FIELD_DEFAULT_FLOAT(ID, STRUCT, FIELD, DEFAULT) \
539 { #ID, ID, TYPE_FLOAT, offsetof(STRUCT, FIELD)__builtin_offsetof(STRUCT, FIELD), DESC_FLAG_HAS_DEFAULT(1 << 3), NULL((void*)0), 0, 0, 0, DEFAULT }
540#define E_FIELD_ACCESSOR_DEFAULT(ID, TYPE, STRUCT, FIELD) \
541 { #ID, ID, TYPE, offsetof(STRUCT, FIELD)__builtin_offsetof(STRUCT, FIELD), DESC_FLAG_ACCESSOR_DEFAULT(1 << 4), NULL((void*)0), 0, 0, 0, 0.0 }
542#define E_MASTER(ID, TYPE, STRUCT, FIELD) \
543 { #ID, ID, TYPE, offsetof(STRUCT, FIELD)__builtin_offsetof(STRUCT, FIELD), DESC_FLAG_MULTI(1 << 0), ne_ ## FIELD ## _elements, \
544 sizeof(struct FIELD), 0, 0, 0.0 }
545#define E_SINGLE_MASTER_O(ID, TYPE, STRUCT, FIELD) \
546 { #ID, ID, TYPE, offsetof(STRUCT, FIELD)__builtin_offsetof(STRUCT, FIELD), DESC_FLAG_OFFSET(1 << 2), ne_ ## FIELD ## _elements, 0, \
547 offsetof(STRUCT, FIELD ## _offset)__builtin_offsetof(STRUCT, FIELD ## _offset), 0, 0.0 }
548#define E_SINGLE_MASTER(ID, TYPE, STRUCT, FIELD) \
549 { #ID, ID, TYPE, offsetof(STRUCT, FIELD)__builtin_offsetof(STRUCT, FIELD), DESC_FLAG_NONE0, ne_ ## FIELD ## _elements, 0, 0, 0, 0.0 }
550#define E_SUSPEND(ID, TYPE) \
551 { #ID, ID, TYPE, 0, DESC_FLAG_SUSPEND(1 << 1), NULL((void*)0), 0, 0, 0, 0.0 }
552#define E_LAST \
553 { NULL((void*)0), 0, 0, 0, DESC_FLAG_NONE0, NULL((void*)0), 0, 0, 0, 0.0 }
554
555/* EBML Element Lists */
556static struct ebml_element_desc ne_ebml_elements[] = {
557 E_FIELD_DEFAULT_UINT(ID_EBML_VERSION0x4286, struct ebml, ebml_version, 1),
558 E_FIELD_DEFAULT_UINT(ID_EBML_READ_VERSION0x42f7, struct ebml, ebml_read_version, 1),
559 E_FIELD_DEFAULT_UINT(ID_EBML_MAX_ID_LENGTH0x42f2, struct ebml, ebml_max_id_length, 4),
560 E_FIELD_DEFAULT_UINT(ID_EBML_MAX_SIZE_LENGTH0x42f3, struct ebml, ebml_max_size_length, 8),
561 E_FIELD(ID_DOCTYPE0x4282, TYPE_STRING, struct ebml, doctype),
562 E_FIELD_DEFAULT_UINT(ID_DOCTYPE_VERSION0x4287, struct ebml, doctype_version, 1),
563 E_FIELD_DEFAULT_UINT(ID_DOCTYPE_READ_VERSION0x4285, struct ebml, doctype_read_version, 1),
564 E_LAST
565};
566
567/* WebM Element Lists */
568static struct ebml_element_desc ne_seek_elements[] = {
569 E_FIELD(ID_SEEK_ID0x53ab, TYPE_BINARY, struct seek, id),
570 E_FIELD(ID_SEEK_POSITION0x53ac, TYPE_UINT, struct seek, position),
571 E_LAST
572};
573
574static struct ebml_element_desc ne_seek_head_elements[] = {
575 E_MASTER(ID_SEEK0x4dbb, TYPE_MASTER, struct seek_head, seek),
576 E_LAST
577};
578
579static struct ebml_element_desc ne_info_elements[] = {
580 E_FIELD_DEFAULT_UINT(ID_TIMECODE_SCALE0x2ad7b1, struct info, timecode_scale, 1000000),
581 E_FIELD(ID_DURATION0x4489, TYPE_FLOAT, struct info, duration),
582 E_LAST
583};
584
585static struct ebml_element_desc ne_mastering_metadata_elements[] = {
586 E_FIELD(ID_PRIMARY_R_CHROMATICITY_X0x55d1, TYPE_FLOAT, struct mastering_metadata, primary_r_chromacity_x),
587 E_FIELD(ID_PRIMARY_R_CHROMATICITY_Y0x55d2, TYPE_FLOAT, struct mastering_metadata, primary_r_chromacity_y),
588 E_FIELD(ID_PRIMARY_G_CHROMATICITY_X0x55d3, TYPE_FLOAT, struct mastering_metadata, primary_g_chromacity_x),
589 E_FIELD(ID_PRIMARY_G_CHROMATICITY_Y0x55d4, TYPE_FLOAT, struct mastering_metadata, primary_g_chromacity_y),
590 E_FIELD(ID_PRIMARY_B_CHROMATICITY_X0x55d5, TYPE_FLOAT, struct mastering_metadata, primary_b_chromacity_x),
591 E_FIELD(ID_PRIMARY_B_CHROMATICITY_Y0x55d6, TYPE_FLOAT, struct mastering_metadata, primary_b_chromacity_y),
592 E_FIELD(ID_WHITE_POINT_CHROMATICITY_X0x55d7, TYPE_FLOAT, struct mastering_metadata, white_point_chromaticity_x),
593 E_FIELD(ID_WHITE_POINT_CHROMATICITY_Y0x55d8, TYPE_FLOAT, struct mastering_metadata, white_point_chromaticity_y),
594 E_FIELD(ID_LUMINANCE_MAX0x55d9, TYPE_FLOAT, struct mastering_metadata, luminance_max),
595 E_FIELD(ID_LUMINANCE_MIN0x55da, TYPE_FLOAT, struct mastering_metadata, luminance_min),
596 E_LAST
597};
598
599static struct ebml_element_desc ne_colour_elements[] = {
600 E_FIELD_DEFAULT_UINT(ID_MATRIX_COEFFICIENTS0x55b1, struct colour, matrix_coefficients, 2),
601 E_FIELD_DEFAULT_UINT(ID_RANGE0x55b9, struct colour, range, 0),
602 E_FIELD_DEFAULT_UINT(ID_TRANSFER_CHARACTERISTICS0x55ba, struct colour, transfer_characteristics, 2),
603 E_FIELD_DEFAULT_UINT(ID_PRIMARIES0x55bb, struct colour, primaries, 2),
604 E_FIELD(ID_MAX_CLL0x55bc, TYPE_UINT, struct colour, max_cll),
605 E_FIELD(ID_MAX_FALL0x55bd, TYPE_UINT, struct colour, max_fall),
606 E_SINGLE_MASTER(ID_MASTERING_METADATA0x55d0, TYPE_MASTER, struct colour, mastering_metadata),
607 E_LAST
608};
609
610static struct ebml_element_desc ne_projection_elements[] = {
611 E_FIELD_DEFAULT_UINT(ID_PROJECTION_TYPE0x7671, struct projection, type, 0),
612 E_FIELD_DEFAULT_FLOAT(ID_PROJECTION_POSE_YAW0x7673, struct projection, pose_yaw, 0.0),
613 E_FIELD_DEFAULT_FLOAT(ID_PROJECTION_POSE_PITCH0x7674, struct projection, pose_pitch, 0.0),
614 E_FIELD_DEFAULT_FLOAT(ID_PROJECTION_POSE_ROLL0x7675, struct projection, pose_roll, 0.0),
615 E_LAST
616};
617
618static struct ebml_element_desc ne_video_elements[] = {
619 E_FIELD_DEFAULT_UINT(ID_STEREO_MODE0x53b8, struct video, stereo_mode, 0),
620 E_FIELD_DEFAULT_UINT(ID_ALPHA_MODE0x53c0, struct video, alpha_mode, 0),
621 E_FIELD(ID_PIXEL_WIDTH0xb0, TYPE_UINT, struct video, pixel_width),
622 E_FIELD(ID_PIXEL_HEIGHT0xba, TYPE_UINT, struct video, pixel_height),
623 E_FIELD_DEFAULT_UINT(ID_PIXEL_CROP_BOTTOM0x54aa, struct video, pixel_crop_bottom, 0),
624 E_FIELD_DEFAULT_UINT(ID_PIXEL_CROP_TOP0x54bb, struct video, pixel_crop_top, 0),
625 E_FIELD_DEFAULT_UINT(ID_PIXEL_CROP_LEFT0x54cc, struct video, pixel_crop_left, 0),
626 E_FIELD_DEFAULT_UINT(ID_PIXEL_CROP_RIGHT0x54dd, struct video, pixel_crop_right, 0),
627 E_FIELD_ACCESSOR_DEFAULT(ID_DISPLAY_WIDTH0x54b0, TYPE_UINT, struct video, display_width),
628 E_FIELD_ACCESSOR_DEFAULT(ID_DISPLAY_HEIGHT0x54ba, TYPE_UINT, struct video, display_height),
629 E_SINGLE_MASTER(ID_COLOUR0x55b0, TYPE_MASTER, struct video, colour),
630 E_SINGLE_MASTER(ID_PROJECTION0x7670, TYPE_MASTER, struct video, projection),
631 E_LAST
632};
633
634static struct ebml_element_desc ne_audio_elements[] = {
635 E_FIELD_DEFAULT_FLOAT(ID_SAMPLING_FREQUENCY0xb5, struct audio, sampling_frequency, 8000.0),
636 E_FIELD_DEFAULT_UINT(ID_CHANNELS0x9f, struct audio, channels, 1),
637 E_FIELD_ACCESSOR_DEFAULT(ID_BIT_DEPTH0x6264, TYPE_UINT, struct audio, bit_depth),
638 E_LAST
639};
640
641static struct ebml_element_desc ne_content_enc_aes_settings_elements[] = {
642 E_FIELD(ID_AES_SETTINGS_CIPHER_MODE0x47e8, TYPE_UINT, struct content_enc_aes_settings, aes_settings_cipher_mode),
643 E_LAST
644};
645
646static struct ebml_element_desc ne_content_encryption_elements[] = {
647 E_FIELD_DEFAULT_UINT(ID_CONTENT_ENC_ALGO0x47e1, struct content_encryption, content_enc_algo, 0),
648 E_FIELD(ID_CONTENT_ENC_KEY_ID0x47e2, TYPE_BINARY, struct content_encryption, content_enc_key_id),
649 E_MASTER(ID_CONTENT_ENC_AES_SETTINGS0x47e7, TYPE_MASTER, struct content_encryption, content_enc_aes_settings),
650 E_LAST
651};
652
653static struct ebml_element_desc ne_content_encoding_elements[] = {
654 E_FIELD_DEFAULT_UINT(ID_CONTENT_ENCODING_TYPE0x5033, struct content_encoding, content_encoding_type, 0),
655 E_MASTER(ID_CONTENT_ENCRYPTION0x5035, TYPE_MASTER, struct content_encoding, content_encryption),
656 E_LAST
657};
658
659static struct ebml_element_desc ne_content_encodings_elements[] = {
660 E_MASTER(ID_CONTENT_ENCODING0x6240, TYPE_MASTER, struct content_encodings, content_encoding),
661 E_LAST
662};
663
664static struct ebml_element_desc ne_track_entry_elements[] = {
665 E_FIELD(ID_TRACK_NUMBER0xd7, TYPE_UINT, struct track_entry, number),
666 E_FIELD(ID_TRACK_UID0x73c5, TYPE_UINT, struct track_entry, uid),
667 E_FIELD(ID_TRACK_TYPE0x83, TYPE_UINT, struct track_entry, type),
668 E_FIELD_DEFAULT_UINT(ID_FLAG_ENABLED0xb9, struct track_entry, flag_enabled, 1),
669 E_FIELD_DEFAULT_UINT(ID_FLAG_DEFAULT0x88, struct track_entry, flag_default, 1),
670 E_FIELD_DEFAULT_UINT(ID_FLAG_LACING0x9c, struct track_entry, flag_lacing, 1),
671 E_FIELD_DEFAULT_FLOAT(ID_TRACK_TIMECODE_SCALE0x23314f, struct track_entry, track_timecode_scale, 1.0),
672 E_FIELD(ID_LANGUAGE0x22b59c, TYPE_STRING, struct track_entry, language),
673 E_FIELD(ID_CODEC_ID0x86, TYPE_STRING, struct track_entry, codec_id),
674 E_FIELD(ID_CODEC_PRIVATE0x63a2, TYPE_BINARY, struct track_entry, codec_private),
675 E_FIELD_DEFAULT_UINT(ID_CODEC_DELAY0x56aa, struct track_entry, codec_delay, 0),
676 E_FIELD_DEFAULT_UINT(ID_SEEK_PREROLL0x56bb, struct track_entry, seek_preroll, 0),
677 E_FIELD(ID_DEFAULT_DURATION0x23e383, TYPE_UINT, struct track_entry, default_duration),
678 E_SINGLE_MASTER(ID_VIDEO0xe0, TYPE_MASTER, struct track_entry, video),
679 E_SINGLE_MASTER(ID_AUDIO0xe1, TYPE_MASTER, struct track_entry, audio),
680 E_SINGLE_MASTER(ID_CONTENT_ENCODINGS0x6d80, TYPE_MASTER, struct track_entry, content_encodings),
681 E_LAST
682};
683
684static struct ebml_element_desc ne_tracks_elements[] = {
685 E_MASTER(ID_TRACK_ENTRY0xae, TYPE_MASTER, struct tracks, track_entry),
686 E_LAST
687};
688
689static struct ebml_element_desc ne_cue_track_positions_elements[] = {
690 E_FIELD(ID_CUE_TRACK0xf7, TYPE_UINT, struct cue_track_positions, track),
691 E_FIELD(ID_CUE_CLUSTER_POSITION0xf1, TYPE_UINT, struct cue_track_positions, cluster_position),
692 E_FIELD(ID_CUE_BLOCK_NUMBER0x5378, TYPE_UINT, struct cue_track_positions, block_number),
693 E_LAST
694};
695
696static struct ebml_element_desc ne_cue_point_elements[] = {
697 E_FIELD(ID_CUE_TIME0xb3, TYPE_UINT, struct cue_point, time),
698 E_MASTER(ID_CUE_TRACK_POSITIONS0xb7, TYPE_MASTER, struct cue_point, cue_track_positions),
699 E_LAST
700};
701
702static struct ebml_element_desc ne_cues_elements[] = {
703 E_MASTER(ID_CUE_POINT0xbb, TYPE_MASTER, struct cues, cue_point),
704 E_LAST
705};
706
707static struct ebml_element_desc ne_segment_elements[] = {
708 E_MASTER(ID_SEEK_HEAD0x114d9b74, TYPE_MASTER, struct segment, seek_head),
709 E_SINGLE_MASTER(ID_INFO0x1549a966, TYPE_MASTER, struct segment, info),
710 E_SUSPEND(ID_CLUSTER0x1f43b675, TYPE_MASTER),
711 E_SINGLE_MASTER(ID_TRACKS0x1654ae6b, TYPE_MASTER, struct segment, tracks),
712 E_SINGLE_MASTER(ID_CUES0x1c53bb6b, TYPE_MASTER, struct segment, cues),
713 E_LAST
714};
715
716static struct ebml_element_desc ne_top_level_elements[] = {
717 E_SINGLE_MASTER(ID_EBML0x1a45dfa3, TYPE_MASTER, nestegg, ebml),
718 E_SINGLE_MASTER_O(ID_SEGMENT0x18538067, TYPE_MASTER, nestegg, segment),
719 E_LAST
720};
721
722#undef E_FIELD
723#undef E_FIELD_DEFAULT_UINT
724#undef E_FIELD_DEFAULT_FLOAT
725#undef E_FIELD_ACCESSOR_DEFAULT
726#undef E_MASTER
727#undef E_SINGLE_MASTER_O
728#undef E_SINGLE_MASTER
729#undef E_SUSPEND
730#undef E_LAST
731
732static struct pool_ctx *
733ne_pool_init(void)
734{
735 return calloc(1, sizeof(struct pool_ctx));
736}
737
738static void
739ne_pool_destroy(struct pool_ctx * pool)
740{
741 struct pool_node * node = pool->head;
742 while (node) {
743 struct pool_node * old = node;
744 node = node->next;
745 free(old->data);
746 free(old);
747 }
748 free(pool);
749}
750
751static void *
752ne_pool_alloc(size_t size, struct pool_ctx * pool)
753{
754 struct pool_node * node;
755
756 node = calloc(1, sizeof(*node));
757 if (!node)
758 return NULL((void*)0);
759
760 node->data = calloc(1, size);
761 if (!node->data) {
762 free(node);
763 return NULL((void*)0);
764 }
765
766 node->next = pool->head;
767 pool->head = node;
768
769 return node->data;
770}
771
772static void *
773ne_alloc(size_t size)
774{
775 return calloc(1, size);
776}
777
778static int
779ne_io_seek(ne_io * io, int64_t offset, int whence)
780{
781 int r;
782 assert(whence == NESTEGG_SEEK_SET)((void) sizeof ((whence == 0) ? 1 : 0), __extension__ ({ if (
whence == 0) ; else __assert_fail ("whence == NESTEGG_SEEK_SET"
, "./../../../../media/libnestegg/src/nestegg.c", 782, __extension__
__PRETTY_FUNCTION__); }))
;
783 r = io->io->seek(offset, whence, io->io->userdata);
784 io->buf_offset = 0;
785 io->buf_fill = 0;
786 io->poisoned = r != 0;
787 return r;
788}
789
790static int64_t
791ne_io_tell(ne_io * io)
792{
793 int64_t pos;
794
795 if (io->poisoned)
796 return -1;
797 pos = io->io->tell(io->io->userdata);
798 if (pos < 0)
799 return -1;
800 assert(io->buf_fill >= io->buf_offset)((void) sizeof ((io->buf_fill >= io->buf_offset) ? 1
: 0), __extension__ ({ if (io->buf_fill >= io->buf_offset
) ; else __assert_fail ("io->buf_fill >= io->buf_offset"
, "./../../../../media/libnestegg/src/nestegg.c", 800, __extension__
__PRETTY_FUNCTION__); }))
;
801 return pos - (int64_t) (io->buf_fill - io->buf_offset);
802}
803
804static size_t
805ne_io_clamp_request(size_t request, int64_t remaining)
806{
807 assert(remaining > 0)((void) sizeof ((remaining > 0) ? 1 : 0), __extension__ ({
if (remaining > 0) ; else __assert_fail ("remaining > 0"
, "./../../../../media/libnestegg/src/nestegg.c", 807, __extension__
__PRETTY_FUNCTION__); }))
;
808 /* Compare in 64 bits so large remaining values are not truncated on
809 32-bit builds before deciding whether to clamp the request. */
810 if ((uint64_t) remaining < (uint64_t) request)
811 return (size_t) remaining;
812 return request;
813}
814
815static int
816ne_io_read_from_buffer(ne_io * io, unsigned char * out, size_t length)
817{
818 memcpy(out, io->buf + io->buf_offset, length);
819 io->buf_offset += length;
820 assert(io->buf_fill >= io->buf_offset)((void) sizeof ((io->buf_fill >= io->buf_offset) ? 1
: 0), __extension__ ({ if (io->buf_fill >= io->buf_offset
) ; else __assert_fail ("io->buf_fill >= io->buf_offset"
, "./../../../../media/libnestegg/src/nestegg.c", 820, __extension__
__PRETTY_FUNCTION__); }))
;
821 return 1;
822}
823
824static int
825ne_io_rewind_to_logical_pos(ne_io * io)
826{
827 int64_t pos = ne_io_tell(io);
828 if (pos < 0)
829 return -1;
830 return ne_io_seek(io, pos, NESTEGG_SEEK_SET0);
831}
832
833static int
834ne_io_read_direct(ne_io * io, unsigned char * out, size_t length)
835{
836 int64_t saved_pos = ne_io_tell(io);
837 int64_t pos;
838 int64_t r;
839
840 if (saved_pos < 0)
841 return -1;
842 pos = saved_pos;
843 while (length > 0) {
844 size_t request = length;
845 if (io->max_offset > 0) {
846 int64_t remaining = io->max_offset - pos;
847 if (remaining <= 0) {
848 if (ne_io_seek(io, saved_pos, NESTEGG_SEEK_SET0) != 0)
849 return -1;
850 return 0;
851 }
852 request = ne_io_clamp_request(request, remaining);
853 }
854 r = io->io->read(out, request, io->io->userdata);
855 if (r <= 0) {
856 if (ne_io_seek(io, saved_pos, NESTEGG_SEEK_SET0) != 0)
857 return -1;
858 return r == 0 ? 0 : -1;
859 }
860 if ((size_t) r > request) {
861 ne_io_seek(io, saved_pos, NESTEGG_SEEK_SET0);
862 return -1;
863 }
864 out += r;
865 length -= r;
866 pos += r;
867 }
868
869 return 1;
870}
871
872static int
873ne_io_fill_buffer(ne_io * io, size_t length)
874{
875 int64_t saved_pos;
876 int64_t pos;
877 int64_t r;
878 int io_error = 0;
879
880 io->buf_offset = 0;
881 io->buf_fill = 0;
882
883 saved_pos = ne_io_tell(io);
884 if (saved_pos < 0)
885 return -1;
886 pos = saved_pos;
887 while (io->buf_fill < length) {
888 size_t request = IO_BUFFER_SIZE8192 - io->buf_fill;
889 if (io->max_offset > 0) {
890 int64_t remaining = io->max_offset - pos;
891 if (remaining <= 0)
892 break;
893 request = ne_io_clamp_request(request, remaining);
894 }
895 r = io->io->read(io->buf + io->buf_fill, request, io->io->userdata);
896 if (r <= 0) {
897 if (io->buf_fill == 0)
898 return r == 0 ? 0 : -1;
899 if (r < 0)
900 io_error = 1;
901 break;
902 }
903 if ((size_t) r > request) {
904 ne_io_seek(io, saved_pos, NESTEGG_SEEK_SET0);
905 return -1;
906 }
907 io->buf_fill += r;
908 assert(io->buf_fill <= IO_BUFFER_SIZE)((void) sizeof ((io->buf_fill <= 8192) ? 1 : 0), __extension__
({ if (io->buf_fill <= 8192) ; else __assert_fail ("io->buf_fill <= IO_BUFFER_SIZE"
, "./../../../../media/libnestegg/src/nestegg.c", 908, __extension__
__PRETTY_FUNCTION__); }))
;
909 pos += r;
910 }
911
912 if (length > io->buf_fill) {
913 if (ne_io_seek(io, saved_pos, NESTEGG_SEEK_SET0) != 0)
914 return -1;
915 return io_error ? -1 : 0;
916 }
917 if (io_error) {
918 /* The underlying stream position is unknown after the failed
919 read. Poison the IO so that ne_io_tell returns -1 until
920 a successful seek re-establishes the position invariant.
921 The buffered data is still valid and will be served below,
922 but any caller that needs a position must seek first. */
923 io->poisoned = 1;
924 }
925
926 return 1;
927}
928
929static int
930ne_io_read(ne_io * io, void * buffer, size_t length)
931{
932 size_t buffered;
933 unsigned char * out = buffer;
934
935 /* Fast path: request satisfied entirely from the buffer.
936 This is safe even when poisoned because the buffered bytes
937 were read before the error and are still valid. */
938 buffered = io->buf_fill - io->buf_offset;
939 if (length <= buffered)
940 return ne_io_read_from_buffer(io, out, length);
941
942 if (io->poisoned)
943 return -1;
944
945 /* The buffer cannot satisfy the full request. Seek back to the
946 logical position (before any buffered-but-unconsumed bytes),
947 invalidate the buffer, and read from the callback directly.
948 This avoids partially draining the buffer and then failing,
949 which would violate the all-or-nothing read contract. */
950 if (buffered > 0) {
951 if (ne_io_rewind_to_logical_pos(io) != 0)
952 return -1;
953 }
954
955 /* Large reads bypass the buffer. Save the position so we can
956 rewind on failure to preserve the all-or-nothing contract. */
957 if (length >= IO_BUFFER_SIZE8192)
958 return ne_io_read_direct(io, out, length);
959
960 /* Refill the buffer, looping to handle short reads. Cap the
961 request to max_offset to avoid reading past the parse fence.
962 Save position so we can rewind on failure, matching the
963 all-or-nothing contract of the large-read path above. */
964 {
965 int r = ne_io_fill_buffer(io, length);
966 if (r != 1)
967 return r;
968 }
969
970 return ne_io_read_from_buffer(io, out, length);
971}
972
973static int
974ne_io_read_skip(ne_io * io, size_t length)
975{
976 size_t get;
977 unsigned char buf[IO_BUFFER_SIZE8192];
978 int r = 1;
979
980 while (length > 0) {
981 get = length < sizeof(buf) ? length : sizeof(buf);
982 r = ne_io_read(io, buf, get);
983 if (r != 1)
984 break;
985 length -= get;
986 }
987
988 return r;
989}
990
991static int
992ne_bare_read_vint(ne_io * io, uint64_t * value, uint64_t * length, enum vint_mask maskflag)
993{
994 int r;
995 unsigned char b;
996 size_t maxlen = 8;
997 unsigned int count = 1, mask = 1 << 7;
998
999 r = ne_io_read(io, &b, 1);
1000 if (r != 1)
1001 return r;
1002
1003 while (count < maxlen) {
1004 if ((b & mask) != 0)
1005 break;
1006 mask >>= 1;
1007 count += 1;
1008 }
1009
1010 if (length)
1011 *length = count;
1012 *value = b;
1013
1014 if (maskflag == MASK_FIRST_BIT)
1015 *value = b & ~mask;
1016
1017 while (--count) {
1018 r = ne_io_read(io, &b, 1);
1019 if (r != 1)
1020 return r;
1021 *value <<= 8;
1022 *value |= b;
1023 }
1024
1025 return 1;
1026}
1027
1028static int
1029ne_read_id(ne_io * io, uint64_t * value, uint64_t * length)
1030{
1031 return ne_bare_read_vint(io, value, length, MASK_NONE);
1032}
1033
1034static int
1035ne_read_vint(ne_io * io, uint64_t * value, uint64_t * length)
1036{
1037 return ne_bare_read_vint(io, value, length, MASK_FIRST_BIT);
1038}
1039
1040static int
1041ne_read_svint(ne_io * io, int64_t * value, uint64_t * length)
1042{
1043 int r;
1044 uint64_t uvalue;
1045 uint64_t ulength;
1046 int64_t svint_subtr[] = {
1047 0x3f, 0x1fff,
1048 0xfffff, 0x7ffffff,
1049 0x3ffffffffLL, 0x1ffffffffffLL,
1050 0xffffffffffffLL, 0x7fffffffffffffLL
1051 };
1052
1053 r = ne_bare_read_vint(io, &uvalue, &ulength, MASK_FIRST_BIT);
1054 if (r != 1)
1055 return r;
1056 *value = (int64_t) uvalue - svint_subtr[ulength - 1];
1057 if (length)
1058 *length = ulength;
1059 return r;
1060}
1061
1062static int
1063ne_read_uint(ne_io * io, uint64_t * val, uint64_t length)
1064{
1065 unsigned char b;
1066 int r;
1067
1068 if (length > 8)
1069 return -1;
1070
1071 *val = 0;
1072 while (length--) {
1073 r = ne_io_read(io, &b, 1);
1074 if (r != 1)
1075 return r;
1076 *val <<= 8;
1077 *val |= b;
1078 }
1079 return 1;
1080}
1081
1082static int
1083ne_read_int(ne_io * io, int64_t * val, uint64_t length)
1084{
1085 int r;
1086 uint64_t uval, base;
1087
1088 r = ne_read_uint(io, &uval, length);
1089 if (r != 1)
1090 return r;
1091
1092 if (length == 0) {
1093 *val = 0;
1094 return 1;
1095 }
1096
1097 if (length < sizeof(int64_t)) {
1098 base = 1;
1099 base <<= length * 8 - 1;
1100 if (uval >= base) {
1101 base = 1;
1102 base <<= length * 8;
1103 } else {
1104 base = 0;
1105 }
1106 *val = (int64_t) uval - (int64_t) base;
1107 } else {
1108 *val = (int64_t) uval;
1109 }
1110
1111 return 1;
1112}
1113
1114static int
1115ne_read_float(ne_io * io, double * val, uint64_t length)
1116{
1117 union {
1118 uint64_t u;
1119 struct {
1120#if defined(__FLOAT_WORD_ORDER__) && __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__4321
1121 uint32_t _pad;
1122 float f;
1123#else
1124 float f;
1125 uint32_t _pad;
1126#endif
1127 } f;
1128 double d;
1129 } value;
1130 int r;
1131
1132 if (length != 0 && length != 4 && length != 8)
1133 return -1;
1134 r = ne_read_uint(io, &value.u, length);
1135 if (r != 1)
1136 return r;
1137 if (length == 0)
1138 *val = 0.;
1139 else if (length == 4)
1140 *val = value.f.f;
1141 else
1142 *val = value.d;
1143 return 1;
1144}
1145
1146static int
1147ne_read_string(nestegg * ctx, char ** val, uint64_t length)
1148{
1149 char * str;
1150 int r;
1151
1152 if (length > LIMIT_STRING(1 << 20))
1153 return -1;
1154 str = ne_pool_alloc(length + 1, ctx->alloc_pool);
1155 if (!str)
1156 return -1;
1157 if (length) {
1158 r = ne_io_read(&ctx->io, (unsigned char *) str, length);
1159 if (r != 1)
1160 return r;
1161 }
1162 str[length] = '\0';
1163 *val = str;
1164 return 1;
1165}
1166
1167static int
1168ne_read_binary(nestegg * ctx, struct ebml_binary * val, uint64_t length)
1169{
1170 if (length == 0 || length > LIMIT_BINARY(1 << 24))
1171 return -1;
1172 val->data = ne_pool_alloc(length, ctx->alloc_pool);
1173 if (!val->data)
1174 return -1;
1175 val->length = length;
1176 return ne_io_read(&ctx->io, val->data, length);
1177}
1178
1179/* True if this element's storage holds a value to report: one read from the
1180 file, or a schema-declared default. An element which is absent or was read
1181 empty holds nothing, and reads back as absent. */
1182static int
1183ne_type_is_set(struct ebml_type type)
1184{
1185 return type.read == EBML_READ_VALUE || type.read == EBML_READ_DEFAULT;
1186}
1187
1188static int
1189ne_get_uint(struct ebml_type type, uint64_t * value)
1190{
1191 if (!ne_type_is_set(type))
1192 return -1;
1193
1194 assert(type.type == TYPE_UINT)((void) sizeof ((type.type == TYPE_UINT) ? 1 : 0), __extension__
({ if (type.type == TYPE_UINT) ; else __assert_fail ("type.type == TYPE_UINT"
, "./../../../../media/libnestegg/src/nestegg.c", 1194, __extension__
__PRETTY_FUNCTION__); }))
;
1195
1196 *value = type.v.u;
1197
1198 return 0;
1199}
1200
1201static int
1202ne_get_float(struct ebml_type type, double * value)
1203{
1204 if (!ne_type_is_set(type))
1205 return -1;
1206
1207 assert(type.type == TYPE_FLOAT)((void) sizeof ((type.type == TYPE_FLOAT) ? 1 : 0), __extension__
({ if (type.type == TYPE_FLOAT) ; else __assert_fail ("type.type == TYPE_FLOAT"
, "./../../../../media/libnestegg/src/nestegg.c", 1207, __extension__
__PRETTY_FUNCTION__); }))
;
1208
1209 *value = type.v.f;
1210
1211 return 0;
1212}
1213
1214static int
1215ne_get_string(struct ebml_type type, char ** value)
1216{
1217 if (!ne_type_is_set(type))
1218 return -1;
1219
1220 assert(type.type == TYPE_STRING)((void) sizeof ((type.type == TYPE_STRING) ? 1 : 0), __extension__
({ if (type.type == TYPE_STRING) ; else __assert_fail ("type.type == TYPE_STRING"
, "./../../../../media/libnestegg/src/nestegg.c", 1220, __extension__
__PRETTY_FUNCTION__); }))
;
1221
1222 *value = type.v.s;
1223
1224 return 0;
1225}
1226
1227static int
1228ne_get_binary(struct ebml_type type, struct ebml_binary * value)
1229{
1230 if (!ne_type_is_set(type))
1231 return -1;
1232
1233 assert(type.type == TYPE_BINARY)((void) sizeof ((type.type == TYPE_BINARY) ? 1 : 0), __extension__
({ if (type.type == TYPE_BINARY) ; else __assert_fail ("type.type == TYPE_BINARY"
, "./../../../../media/libnestegg/src/nestegg.c", 1233, __extension__
__PRETTY_FUNCTION__); }))
;
1234
1235 *value = type.v.b;
1236
1237 return 0;
1238}
1239
1240static int
1241ne_is_ancestor_element(uint64_t id, struct list_node * ancestor)
1242{
1243 struct ebml_element_desc * element;
1244
1245 for (; ancestor; ancestor = ancestor->previous)
1246 for (element = ancestor->node; element->id; ++element)
1247 if (element->id == id)
1248 return 1;
1249
1250 return 0;
1251}
1252
1253static struct ebml_element_desc *
1254ne_find_element(uint64_t id, struct ebml_element_desc * elements)
1255{
1256 struct ebml_element_desc * element;
1257
1258 for (element = elements; element->id; ++element)
1259 if (element->id == id)
1260 return element;
1261
1262 return NULL((void*)0);
1263}
1264
1265/* Initialize storage for elements with schema-declared default values
1266 so that absent and (eventually) zero-length elements read back as their
1267 default (RFC 8794 Section 11.1.6.8). Multi instance master elements are
1268 initialized as each instance is allocated in ne_read_master. */
1269static void
1270ne_init_defaults(struct ebml_element_desc * elements, void * data)
1271{
1272 struct ebml_element_desc * element;
1273 struct ebml_type * storage;
1274
1275 for (element = elements; element->id; ++element) {
1276 if (element->type == TYPE_MASTER) {
1277 if (element->children && !(element->flags & DESC_FLAG_MULTI(1 << 0)))
1278 ne_init_defaults(element->children, (char *) data + element->offset);
1279 } else if (element->flags & DESC_FLAG_HAS_DEFAULT(1 << 3)) {
1280 storage = (struct ebml_type *) ((char *) data + element->offset);
1281 storage->type = element->type;
1282 if (element->type == TYPE_UINT)
1283 storage->v.u = element->default_uint;
1284 else
1285 storage->v.f = element->default_float;
1286 storage->read = EBML_READ_DEFAULT;
1287 }
1288 }
1289}
1290
1291static int
1292ne_ctx_push(nestegg * ctx, struct ebml_element_desc * ancestor, void * data)
1293{
1294 struct list_node * item;
1295
1296 item = ne_alloc(sizeof(*item));
1297 if (!item)
1298 return -1;
1299 item->previous = ctx->ancestor;
1300 item->node = ancestor;
1301 item->data = data;
1302 ctx->ancestor = item;
1303 return 0;
1304}
1305
1306static void
1307ne_ctx_pop(nestegg * ctx)
1308{
1309 struct list_node * item;
1310
1311 item = ctx->ancestor;
1312 ctx->ancestor = item->previous;
1313 free(item);
1314}
1315
1316static int
1317ne_ctx_save(nestegg * ctx, struct saved_state * s)
1318{
1319 s->stream_offset = ne_io_tell(&ctx->io);
1320 if (s->stream_offset < 0)
1321 return -1;
1322 s->last_id = ctx->last_id;
1323 s->last_size = ctx->last_size;
1324 s->last_valid = ctx->last_valid;
1325 return 0;
1326}
1327
1328static int
1329ne_ctx_restore(nestegg * ctx, struct saved_state * s)
1330{
1331 int r;
1332
1333 /* A failed restore leaves the logical stream position unknown, so any
1334 cached lookahead must be discarded as well. */
1335 ctx->last_valid = 0;
1336
1337 if (s->stream_offset < 0)
1338 return -1;
1339 r = ne_io_seek(&ctx->io, s->stream_offset, NESTEGG_SEEK_SET0);
1340 if (r != 0)
1341 return -1;
1342 ctx->last_id = s->last_id;
1343 ctx->last_size = s->last_size;
1344 ctx->last_valid = s->last_valid;
1345 return 0;
1346}
1347
1348static int
1349ne_peek_element(nestegg * ctx, uint64_t * id, uint64_t * size)
1350{
1351 int r;
1352
1353 if (ctx->last_valid) {
1354 if (id)
1355 *id = ctx->last_id;
1356 if (size)
1357 *size = ctx->last_size;
1358 return 1;
1359 }
1360
1361 r = ne_read_id(&ctx->io, &ctx->last_id, NULL((void*)0));
1362 if (r != 1)
1363 return r;
1364
1365 r = ne_read_vint(&ctx->io, &ctx->last_size, NULL((void*)0));
1366 if (r != 1)
1367 return r;
1368
1369 if (id)
1370 *id = ctx->last_id;
1371 if (size)
1372 *size = ctx->last_size;
1373
1374 ctx->last_valid = 1;
1375
1376 return 1;
1377}
1378
1379static int
1380ne_read_element(nestegg * ctx, uint64_t * id, uint64_t * size)
1381{
1382 int r;
1383
1384 r = ne_peek_element(ctx, id, size);
1385 if (r != 1)
1386 return r;
1387
1388 ctx->last_valid = 0;
1389
1390 return 1;
1391}
1392
1393static int
1394ne_read_master(nestegg * ctx, struct ebml_element_desc * desc)
1395{
1396 struct ebml_list * list;
1397 struct ebml_list_node * node, * oldtail;
1398
1399 assert(desc->type == TYPE_MASTER && desc->flags & DESC_FLAG_MULTI)((void) sizeof ((desc->type == TYPE_MASTER && desc
->flags & (1 << 0)) ? 1 : 0), __extension__ ({ if
(desc->type == TYPE_MASTER && desc->flags &
(1 << 0)) ; else __assert_fail ("desc->type == TYPE_MASTER && desc->flags & DESC_FLAG_MULTI"
, "./../../../../media/libnestegg/src/nestegg.c", 1399, __extension__
__PRETTY_FUNCTION__); }))
;
1400
1401 ctx->log(ctx, NESTEGG_LOG_DEBUG1, "multi master element %llx (%s)",
1402 desc->id, desc->name);
1403
1404 list = (struct ebml_list *) (ctx->ancestor->data + desc->offset);
1405
1406 if (desc->id == ID_TRACK_ENTRY0xae && list->count >= LIMIT_TRACKS1000U) {
1407 ctx->log(ctx, NESTEGG_LOG_ERROR1000,
1408 "TrackEntry count exceeds limit of %u", LIMIT_TRACKS1000U);
1409 return -1;
1410 }
1411
1412 node = ne_pool_alloc(sizeof(*node), ctx->alloc_pool);
1413 if (!node)
1414 return -1;
1415 node->id = desc->id;
1416 node->data = ne_pool_alloc(desc->size, ctx->alloc_pool);
1417 if (!node->data)
1418 return -1;
1419 ne_init_defaults(desc->children, node->data);
1420
1421 oldtail = list->tail;
1422 if (oldtail)
1423 oldtail->next = node;
1424 list->tail = node;
1425 if (!list->head)
1426 list->head = node;
1427 list->count += 1;
1428
1429 ctx->log(ctx, NESTEGG_LOG_DEBUG1, " -> using data %p", node->data);
1430
1431 if (ne_ctx_push(ctx, desc->children, node->data) < 0)
1432 return -1;
1433
1434 return 0;
1435}
1436
1437static int
1438ne_read_single_master(nestegg * ctx, struct ebml_element_desc * desc)
1439{
1440 assert(desc->type == TYPE_MASTER && !(desc->flags & DESC_FLAG_MULTI))((void) sizeof ((desc->type == TYPE_MASTER && !(desc
->flags & (1 << 0))) ? 1 : 0), __extension__ ({ if
(desc->type == TYPE_MASTER && !(desc->flags &
(1 << 0))) ; else __assert_fail ("desc->type == TYPE_MASTER && !(desc->flags & DESC_FLAG_MULTI)"
, "./../../../../media/libnestegg/src/nestegg.c", 1440, __extension__
__PRETTY_FUNCTION__); }))
;
1441
1442 ctx->log(ctx, NESTEGG_LOG_DEBUG1, "single master element %llx (%s)",
1443 desc->id, desc->name);
1444 ctx->log(ctx, NESTEGG_LOG_DEBUG1, " -> using data %p (%u)",
1445 ctx->ancestor->data + desc->offset, desc->offset);
1446
1447 return ne_ctx_push(ctx, desc->children, ctx->ancestor->data + desc->offset);
1448}
1449
1450static int
1451ne_read_simple(nestegg * ctx, struct ebml_element_desc * desc, size_t length)
1452{
1453 struct ebml_type * storage;
1454 int r = -1;
1455
1456 storage = (struct ebml_type *) (ctx->ancestor->data + desc->offset);
1457
1458 if (storage->read == EBML_READ_VALUE || storage->read == EBML_READ_EMPTY) {
1459 ctx->log(ctx, NESTEGG_LOG_DEBUG1, "element %llx (%s) already read, skipping %u",
1460 desc->id, desc->name, length);
1461 return ne_io_read_skip(&ctx->io, length);
1462 }
1463
1464 storage->type = desc->type;
1465
1466 ctx->log(ctx, NESTEGG_LOG_DEBUG1, "element %llx (%s) -> %p (%u)",
1467 desc->id, desc->name, storage, desc->offset);
1468
1469 /* Elements whose default the descriptor can't express are resolved by the
1470 accessor, so record a zero-length instance as read but valueless and let
1471 the accessor treat it as absent. RFC 8794 Section 6.1 defines the value
1472 of an empty element only for elements with a declared default (the
1473 default) and without one (zero); these have neither, and zero is outside
1474 the range RFC 9559 permits for each of them. */
1475 if (length == 0 && (desc->flags & DESC_FLAG_ACCESSOR_DEFAULT(1 << 4))) {
1476 storage->read = EBML_READ_EMPTY;
1477 return 1;
1478 }
1479
1480 switch (desc->type) {
1481 case TYPE_UINT:
1482 /* A zero-length element keeps the value established at init: the
1483 declared default (RFC 8794 section 6.1) or, for a field with no
1484 default, zero (RFC 8794 section 7.x). */
1485 if (length == 0)
1486 r = 1;
1487 else
1488 r = ne_read_uint(&ctx->io, &storage->v.u, length);
1489 break;
1490 case TYPE_FLOAT:
1491 if (length == 0)
1492 r = 1;
1493 else
1494 r = ne_read_float(&ctx->io, &storage->v.f, length);
1495 break;
1496 case TYPE_STRING:
1497 r = ne_read_string(ctx, &storage->v.s, length);
1498 break;
1499 case TYPE_BINARY:
1500 r = ne_read_binary(ctx, &storage->v.b, length);
1501 break;
1502 case TYPE_MASTER:
1503 case TYPE_UNKNOWN:
1504 default:
1505 assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "./../../../../media/libnestegg/src/nestegg.c", 1505, __extension__
__PRETTY_FUNCTION__); }))
;
1506 break;
1507 }
1508
1509 if (r == 1)
1510 storage->read = EBML_READ_VALUE;
1511
1512 return r;
1513}
1514
1515static int
1516ne_parse(nestegg * ctx, struct ebml_element_desc * top_level, int64_t max_offset)
1517{
1518 int r;
1519 int64_t * data_offset;
1520 uint64_t id, size, peeked_id;
1521 struct ebml_element_desc * element;
1522
1523 assert(ctx->ancestor)((void) sizeof ((ctx->ancestor) ? 1 : 0), __extension__ ({
if (ctx->ancestor) ; else __assert_fail ("ctx->ancestor"
, "./../../../../media/libnestegg/src/nestegg.c", 1523, __extension__
__PRETTY_FUNCTION__); }))
;
1524
1525 for (;;) {
1526 if (max_offset > 0) {
1527 int64_t offset = ne_io_tell(&ctx->io);
1528 if (offset < 0) {
1529 r = -1;
1530 break;
1531 }
1532 if (offset >= max_offset) {
1533 /* Reached end of offset allowed for parsing - return gracefully */
1534 r = 1;
1535 break;
1536 }
1537 }
1538 r = ne_peek_element(ctx, &id, &size);
1539 if (r != 1)
1540 break;
1541 peeked_id = id;
1542
1543 element = ne_find_element(id, ctx->ancestor->node);
1544 if (element) {
1545 if (element->flags & DESC_FLAG_SUSPEND(1 << 1)) {
1546 assert(element->id == ID_CLUSTER && element->type == TYPE_MASTER)((void) sizeof ((element->id == 0x1f43b675 && element
->type == TYPE_MASTER) ? 1 : 0), __extension__ ({ if (element
->id == 0x1f43b675 && element->type == TYPE_MASTER
) ; else __assert_fail ("element->id == ID_CLUSTER && element->type == TYPE_MASTER"
, "./../../../../media/libnestegg/src/nestegg.c", 1546, __extension__
__PRETTY_FUNCTION__); }))
;
1547 ctx->log(ctx, NESTEGG_LOG_DEBUG1, "suspend parse at %llx", id);
1548 r = 1;
1549 break;
1550 }
1551
1552 r = ne_read_element(ctx, &id, &size);
1553 if (r != 1)
1554 break;
1555 assert(id == peeked_id)((void) sizeof ((id == peeked_id) ? 1 : 0), __extension__ ({ if
(id == peeked_id) ; else __assert_fail ("id == peeked_id", "./../../../../media/libnestegg/src/nestegg.c"
, 1555, __extension__ __PRETTY_FUNCTION__); }))
;
1556
1557 if (element->flags & DESC_FLAG_OFFSET(1 << 2)) {
1558 data_offset = (int64_t *) (ctx->ancestor->data + element->data_offset);
1559 *data_offset = ne_io_tell(&ctx->io);
1560 if (*data_offset < 0) {
1561 r = -1;
1562 break;
1563 }
1564 }
1565
1566 if (element->type == TYPE_MASTER) {
1567 if (element->flags & DESC_FLAG_MULTI(1 << 0)) {
1568 r = ne_read_master(ctx, element);
1569 if (r < 0)
1570 break;
1571 } else {
1572 r = ne_read_single_master(ctx, element);
1573 if (r < 0)
1574 break;
1575 }
1576 continue;
1577 } else {
1578 r = ne_read_simple(ctx, element, size);
1579 if (r < 0)
1580 break;
1581 }
1582 } else if (ne_is_ancestor_element(id, ctx->ancestor->previous)) {
1583 ctx->log(ctx, NESTEGG_LOG_DEBUG1, "parent element %llx", id);
1584 if (top_level && ctx->ancestor->node == top_level) {
1585 ctx->log(ctx, NESTEGG_LOG_DEBUG1, "*** parse about to back up past top_level");
1586 r = 1;
1587 break;
1588 }
1589 ne_ctx_pop(ctx);
1590 } else {
1591 r = ne_read_element(ctx, &id, &size);
1592 if (r != 1)
1593 break;
1594
1595 if (id != ID_VOID0xec && id != ID_CRC320xbf)
1596 ctx->log(ctx, NESTEGG_LOG_DEBUG1, "unknown element %llx", id);
1597 r = ne_io_read_skip(&ctx->io, size);
1598 if (r != 1)
1599 break;
1600 }
1601 }
1602
1603 if (r != 1)
1604 while (ctx->ancestor)
1605 ne_ctx_pop(ctx);
1606
1607 return r;
1608}
1609
1610static int
1611ne_peek_element_id(nestegg * ctx, void * userdata)
1612{
1613 uint64_t * id = userdata;
1614 return ne_peek_element(ctx, id, NULL((void*)0));
1615}
1616
1617struct ne_parse_args {
1618 struct ebml_element_desc * top_level;
1619 int64_t max_offset;
1620};
1621
1622static int
1623ne_parse_call(nestegg * ctx, void * userdata)
1624{
1625 struct ne_parse_args * args = userdata;
1626 return ne_parse(ctx, args->top_level, args->max_offset);
1627}
1628
1629static int
1630ne_with_io_limit(nestegg * ctx,
1631 int64_t max_offset,
1632 int (* callback)(nestegg * ctx, void * userdata),
1633 void * userdata)
1634{
1635 int r;
1636 int64_t saved_max_offset = ctx->io.max_offset;
1637
1638 ctx->io.max_offset = max_offset;
1639 r = callback(ctx, userdata);
1640 ctx->io.max_offset = saved_max_offset;
1641
1642 return r;
1643}
1644
1645static int
1646ne_peek_element_with_io_limit(nestegg * ctx, uint64_t * id, int64_t max_offset)
1647{
1648 return ne_with_io_limit(ctx, max_offset, ne_peek_element_id, id);
1649}
1650
1651static int
1652ne_parse_with_io_limit(nestegg * ctx,
1653 struct ebml_element_desc * top_level,
1654 int64_t max_offset)
1655{
1656 struct ne_parse_args args;
1657 args.top_level = top_level;
1658 args.max_offset = max_offset;
1659 return ne_with_io_limit(ctx, max_offset, ne_parse_call, &args);
1660}
1661
1662static int
1663ne_read_block_encryption(nestegg * ctx, struct track_entry const * entry,
1664 uint64_t * encoding_type, uint64_t * encryption_algo,
1665 uint64_t * encryption_mode)
1666{
1667 struct content_encoding * encoding;
1668 struct content_encryption * encryption;
1669 struct content_enc_aes_settings * aes_settings;
1670
1671 *encoding_type = 0;
1672 if (entry->content_encodings.content_encoding.head) {
1673 encoding = entry->content_encodings.content_encoding.head->data;
1674 ne_get_uint(encoding->content_encoding_type, encoding_type);
1675
1676 if (*encoding_type == NESTEGG_ENCODING_ENCRYPTION1) {
1677 /* Metadata states content is encrypted */
1678 if (!encoding->content_encryption.head)
1679 return -1;
1680
1681 encryption = encoding->content_encryption.head->data;
1682 ne_get_uint(encryption->content_enc_algo, encryption_algo);
1683
1684 if (*encryption_algo != CONTENT_ENC_ALGO_AES5) {
1685 ctx->log(ctx, NESTEGG_LOG_ERROR1000, "Disallowed ContentEncAlgo used");
1686 return -1;
1687 }
1688
1689 if (!encryption->content_enc_aes_settings.head) {
1690 ctx->log(ctx, NESTEGG_LOG_ERROR1000, "No ContentEncAESSettings element found");
1691 return -1;
1692 }
1693
1694 aes_settings = encryption->content_enc_aes_settings.head->data;
1695 *encryption_mode = AES_SETTINGS_CIPHER_CTR1;
1696 ne_get_uint(aes_settings->aes_settings_cipher_mode, encryption_mode);
1697
1698 if (*encryption_mode != AES_SETTINGS_CIPHER_CTR1) {
1699 ctx->log(ctx, NESTEGG_LOG_ERROR1000, "Disallowed AESSettingsCipherMode used");
1700 return -1;
1701 }
1702 }
1703 }
1704 return 1;
1705}
1706
1707static int
1708ne_read_xiph_lace_value(ne_io * io, uint64_t * value, size_t * consumed)
1709{
1710 int r;
1711 uint64_t lace;
1712
1713 r = ne_read_uint(io, &lace, 1);
1714 if (r != 1)
1715 return r;
1716 *consumed += 1;
1717
1718 *value = lace;
1719 while (lace == 255) {
1720 r = ne_read_uint(io, &lace, 1);
1721 if (r != 1)
1722 return r;
1723 *consumed += 1;
1724 *value += lace;
1725 /* Check frame size limit early to defeat crafted lace values. */
1726 if (*value > LIMIT_FRAME(1 << 28))
1727 return -1;
1728 }
1729
1730 return 1;
1731}
1732
1733static int
1734ne_read_xiph_lacing(ne_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
1735{
1736 int r;
1737 size_t i = 0;
1738 uint64_t sum = 0;
1739
1740 while (--n) {
1741 r = ne_read_xiph_lace_value(io, &sizes[i], read);
1742 if (r != 1)
1743 return r;
1744 sum += sizes[i];
1745 i += 1;
1746 }
1747
1748 if (*read + sum > block)
1749 return -1;
1750
1751 /* Last frame is the remainder of the block. */
1752 sizes[i] = block - *read - sum;
1753 return 1;
1754}
1755
1756static int
1757ne_read_ebml_lacing(ne_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
1758{
1759 int r;
1760 uint64_t lace, sum, length;
1761 int64_t slace, frame_size;
1762 size_t i = 0;
1763
1764 r = ne_read_vint(io, &lace, &length);
1765 if (r != 1)
1766 return r;
1767 *read += length;
1768
1769 sizes[i] = lace;
1770 sum = sizes[i];
1771
1772 i += 1;
1773 n -= 1;
1774
1775 while (--n) {
1776 r = ne_read_svint(io, &slace, &length);
1777 if (r != 1)
1778 return r;
1779 *read += length;
1780 frame_size = (int64_t) sizes[i - 1] + slace;
1781 if (frame_size < 0)
1782 return -1;
1783 sizes[i] = frame_size;
1784 sum += sizes[i];
1785 i += 1;
1786 }
1787
1788 if (*read + sum > block)
1789 return -1;
1790
1791 /* Last frame is the remainder of the block. */
1792 sizes[i] = block - *read - sum;
1793 return 1;
1794}
1795
1796static uint64_t
1797ne_saturate_mul_uint64(uint64_t a, uint64_t b)
1798{
1799 if (b != 0 && a > UINT64_MAX(18446744073709551615UL) / b)
1800 return UINT64_MAX(18446744073709551615UL);
1801 return a * b;
1802}
1803
1804static uint64_t
1805ne_get_timecode_scale(nestegg * ctx)
1806{
1807 uint64_t scale;
1808
1809 if (ne_get_uint(ctx->segment.info.timecode_scale, &scale) != 0)
1810 return 0;
1811
1812 return scale;
1813}
1814
1815static int
1816ne_compare_track_number_index(void const * a, void const * b)
1817{
1818 struct track_number_index const * ta = a;
1819 struct track_number_index const * tb = b;
1820
1821 if (ta->number < tb->number)
1822 return -1;
1823 if (ta->number > tb->number)
1824 return 1;
1825 return 0;
1826}
1827
1828static int
1829ne_init_track_indexes(nestegg * ctx)
1830{
1831 struct ebml_list * tracks = &ctx->segment.tracks.track_entry;
1832 struct ebml_list_node * node;
1833 size_t i;
1834
1835 if (tracks->count == 0 || tracks->count > LIMIT_TRACKS1000U)
1836 return -1;
1837
1838 ctx->track_by_index =
1839 ne_pool_alloc(tracks->count * sizeof(*ctx->track_by_index),
1840 ctx->alloc_pool);
1841 if (!ctx->track_by_index)
1842 return -1;
1843
1844 ctx->track_by_number =
1845 ne_pool_alloc(tracks->count * sizeof(*ctx->track_by_number),
1846 ctx->alloc_pool);
1847 if (!ctx->track_by_number)
1848 return -1;
1849
1850 node = tracks->head;
1851 for (i = 0; i < tracks->count; ++i) {
1852 struct track_entry * entry;
1853 uint64_t number;
1854
1855 if (!node || node->id != ID_TRACK_ENTRY0xae)
1856 return -1;
1857
1858 entry = node->data;
1859 if (ne_get_uint(entry->number, &number) != 0 || number == 0)
1860 return -1;
1861
1862 ctx->track_by_index[i] = entry;
1863 ctx->track_by_number[i].number = number;
1864 ctx->track_by_number[i].index = (unsigned int) i;
1865 node = node->next;
1866 }
1867
1868 if (node)
1869 return -1;
1870
1871 qsort(ctx->track_by_number, tracks->count,
1872 sizeof(*ctx->track_by_number), ne_compare_track_number_index);
1873
1874 for (i = 1; i < tracks->count; ++i) {
1875 if (ctx->track_by_number[i - 1].number ==
1876 ctx->track_by_number[i].number)
1877 return -1;
1878 }
1879
1880 ctx->track_count = (unsigned int) tracks->count;
1881 return 0;
1882}
1883
1884static int
1885ne_map_track_number_to_index(nestegg * ctx,
1886 uint64_t track_number,
1887 unsigned int * track_index)
1888{
1889 size_t start = 0;
1890 size_t end = ctx->track_count;
1891
1892 if (track_number == 0)
1893 return -1;
1894
1895 while (start < end) {
1896 size_t middle = start + (end - start) / 2;
1897 struct track_number_index const * entry = &ctx->track_by_number[middle];
1898
1899 if (track_number < entry->number) {
1900 end = middle;
1901 } else if (track_number > entry->number) {
1902 start = middle + 1;
1903 } else {
1904 if (track_index)
1905 *track_index = entry->index;
1906 return 0;
1907 }
1908 }
1909
1910 return -1;
1911}
1912
1913static struct track_entry *
1914ne_find_track_entry(nestegg * ctx, unsigned int track)
1915{
1916 if (track >= ctx->track_count)
1917 return NULL((void*)0);
1918
1919 return ctx->track_by_index[track];
1920}
1921
1922static struct frame *
1923ne_alloc_frame(void)
1924{
1925 struct frame * f = ne_alloc(sizeof(*f));
1926
1927 if (!f)
1928 return NULL((void*)0);
1929
1930 f->data = NULL((void*)0);
1931 f->length = 0;
1932 f->frame_encryption = NULL((void*)0);
1933
1934 return f;
1935}
1936
1937static struct frame_encryption *
1938ne_alloc_frame_encryption(void)
1939{
1940 struct frame_encryption * f = ne_alloc(sizeof(*f));
1941
1942 if (!f)
1943 return NULL((void*)0);
1944
1945 f->iv = NULL((void*)0);
1946 f->length = 0;
1947 f->signal_byte = 0;
1948 f->num_partitions = 0;
1949 f->partition_offsets = NULL((void*)0);
1950
1951 return f;
1952}
1953
1954static void
1955ne_free_frame(struct frame * f)
1956{
1957 if (f->frame_encryption) {
1958 free(f->frame_encryption->iv);
1959 free(f->frame_encryption->partition_offsets);
1960 }
1961
1962 free(f->frame_encryption);
1963 free(f->data);
1964 free(f);
1965}
1966
1967static int
1968ne_read_block(nestegg * ctx, uint64_t block_id, uint64_t block_size, nestegg_packet ** data)
1969{
1970 int r;
1971 int64_t timecode, abs_timecode;
1972 nestegg_packet * pkt;
1973 struct frame * f;
1974 struct track_entry * entry;
1975 uint64_t track_number, length, frame_sizes[256], cluster_tc, flags, frames, tc_scale, total,
1976 encoding_type, encryption_algo, encryption_mode;
1977 unsigned int i, lacing, track;
1978 uint8_t signal_byte, keyframe = NESTEGG_PACKET_HAS_KEYFRAME_UNKNOWN2, j = 0;
1979 size_t consumed = 0, data_size, encryption_size;
1980
1981 *data = NULL((void*)0);
1982
1983 if (block_size > LIMIT_BLOCK(1 << 30))
1984 return -1;
1985
1986 r = ne_read_vint(&ctx->io, &track_number, &length);
1987 if (r != 1)
1988 return r;
1989
1990 if (track_number == 0)
1991 return -1;
1992
1993 consumed += length;
1994
1995 r = ne_read_int(&ctx->io, &timecode, 2);
1996 if (r != 1)
1997 return r;
1998
1999 consumed += 2;
2000
2001 r = ne_read_uint(&ctx->io, &flags, 1);
2002 if (r != 1)
2003 return r;
2004
2005 consumed += 1;
2006
2007 frames = 0;
2008
2009 /* Simple blocks have an explicit flag for if the contents a keyframes*/
2010 if (block_id == ID_SIMPLE_BLOCK0xa3)
2011 keyframe = (flags & SIMPLE_BLOCK_FLAGS_KEYFRAME(1 << 7)) == SIMPLE_BLOCK_FLAGS_KEYFRAME(1 << 7) ?
2012 NESTEGG_PACKET_HAS_KEYFRAME_TRUE1 :
2013 NESTEGG_PACKET_HAS_KEYFRAME_FALSE0;
2014
2015 /* Flags are different between Block and SimpleBlock, but lacing is
2016 encoded the same way. */
2017 lacing = (flags & BLOCK_FLAGS_LACING6) >> 1;
2018
2019 switch (lacing) {
2020 case LACING_NONE0:
2021 frames = 1;
2022 break;
2023 case LACING_XIPH1:
2024 case LACING_FIXED2:
2025 case LACING_EBML3:
2026 r = ne_read_uint(&ctx->io, &frames, 1);
2027 if (r != 1)
2028 return r;
2029 consumed += 1;
2030 frames += 1;
2031 break;
2032 default:
2033 assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "./../../../../media/libnestegg/src/nestegg.c", 2033, __extension__
__PRETTY_FUNCTION__); }))
;
2034 return -1;
2035 }
2036
2037 if (frames > 256)
2038 return -1;
2039
2040 switch (lacing) {
2041 case LACING_NONE0:
2042 frame_sizes[0] = block_size - consumed;
2043 break;
2044 case LACING_XIPH1:
2045 if (frames == 1)
2046 return -1;
2047 r = ne_read_xiph_lacing(&ctx->io, block_size, &consumed, frames, frame_sizes);
2048 if (r != 1)
2049 return r;
2050 break;
2051 case LACING_FIXED2:
2052 if ((block_size - consumed) % frames)
2053 return -1;
2054 for (i = 0; i < frames; ++i)
2055 frame_sizes[i] = (block_size - consumed) / frames;
2056 break;
2057 case LACING_EBML3:
2058 if (frames == 1)
2059 return -1;
2060 r = ne_read_ebml_lacing(&ctx->io, block_size, &consumed, frames, frame_sizes);
2061 if (r != 1)
2062 return r;
2063 break;
2064 default:
2065 assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "./../../../../media/libnestegg/src/nestegg.c", 2065, __extension__
__PRETTY_FUNCTION__); }))
;
2066 return -1;
2067 }
2068
2069 /* Sanity check unlaced frame sizes against total block size. */
2070 total = consumed;
2071 for (i = 0; i < frames; ++i)
2072 total += frame_sizes[i];
2073 if (total > block_size)
2074 return -1;
2075
2076 if (ne_map_track_number_to_index(ctx, track_number, &track) != 0)
2077 return -1;
2078
2079 entry = ne_find_track_entry(ctx, track);
2080 if (!entry)
2081 return -1;
2082
2083 r = ne_read_block_encryption(ctx, entry, &encoding_type, &encryption_algo, &encryption_mode);
2084 if (r != 1)
2085 return r;
2086
2087 /* Encryption does not support lacing */
2088 if (lacing != LACING_NONE0 && encoding_type == NESTEGG_ENCODING_ENCRYPTION1) {
2089 ctx->log(ctx, NESTEGG_LOG_ERROR1000, "Encrypted blocks may not also be laced");
2090 return -1;
2091 }
2092
2093 tc_scale = ne_get_timecode_scale(ctx);
2094 if (tc_scale == 0)
2095 return -1;
2096
2097 if (!ctx->read_cluster_timecode)
2098 return -1;
2099 cluster_tc = ctx->cluster_timecode;
2100
2101 abs_timecode = timecode + cluster_tc;
2102 if (abs_timecode < 0) {
2103 /* Ignore the spec and negative timestamps */
2104 ctx->log(ctx, NESTEGG_LOG_WARNING100, "ignoring negative timecode: %lld", abs_timecode);
2105 abs_timecode = 0;
2106 }
2107
2108 pkt = ne_alloc(sizeof(*pkt));
2109 if (!pkt)
2110 return -1;
2111 pkt->track = track;
2112 pkt->timecode = ne_saturate_mul_uint64((uint64_t) abs_timecode, tc_scale);
2113 pkt->keyframe = keyframe;
2114 pkt->frames = ne_alloc((size_t) frames * sizeof(*pkt->frames));
2115 if (!pkt->frames) {
2116 nestegg_free_packet(pkt);
2117 return -1;
2118 }
2119
2120 ctx->log(ctx, NESTEGG_LOG_DEBUG1, "%sblock t %lld pts %f f %llx frames: %llu",
2121 block_id == ID_BLOCK0xa1 ? "" : "simple", pkt->track, pkt->timecode / 1e9, flags, frames);
2122
2123 for (i = 0; i < frames; ++i) {
2124 if (frame_sizes[i] > LIMIT_FRAME(1 << 28)) {
2125 nestegg_free_packet(pkt);
2126 return -1;
2127 }
2128 f = ne_alloc_frame();
2129 if (!f) {
2130 nestegg_free_packet(pkt);
2131 return -1;
2132 }
2133 /* Parse encryption */
2134 if (encoding_type == NESTEGG_ENCODING_ENCRYPTION1) {
2135 r = ne_io_read(&ctx->io, &signal_byte, SIGNAL_BYTE_SIZE1);
2136 if (r != 1) {
2137 ne_free_frame(f);
2138 nestegg_free_packet(pkt);
2139 return r;
2140 }
2141 f->frame_encryption = ne_alloc_frame_encryption();
2142 if (!f->frame_encryption) {
2143 ne_free_frame(f);
2144 nestegg_free_packet(pkt);
2145 return -1;
2146 }
2147 f->frame_encryption->signal_byte = signal_byte;
2148 if ((signal_byte & ENCRYPTED_BIT_MASK(1 << 0)) == PACKET_ENCRYPTED1) {
2149 f->frame_encryption->iv = ne_alloc(IV_SIZE8);
2150 if (!f->frame_encryption->iv) {
2151 ne_free_frame(f);
2152 nestegg_free_packet(pkt);
2153 return -1;
2154 }
2155 r = ne_io_read(&ctx->io, f->frame_encryption->iv, IV_SIZE8);
2156 if (r != 1) {
2157 ne_free_frame(f);
2158 nestegg_free_packet(pkt);
2159 return r;
2160 }
2161 f->frame_encryption->length = IV_SIZE8;
2162 encryption_size = SIGNAL_BYTE_SIZE1 + IV_SIZE8;
2163
2164 if ((signal_byte & PARTITIONED_BIT_MASK(1 << 1)) == PACKET_PARTITIONED2) {
2165 r = ne_io_read(&ctx->io, &f->frame_encryption->num_partitions, NUM_PACKETS_SIZE1);
2166 if (r != 1) {
2167 ne_free_frame(f);
2168 nestegg_free_packet(pkt);
2169 return r;
2170 }
2171
2172 encryption_size += NUM_PACKETS_SIZE1 + f->frame_encryption->num_partitions * PACKET_OFFSET_SIZE4;
2173 f->frame_encryption->partition_offsets = ne_alloc(f->frame_encryption->num_partitions * PACKET_OFFSET_SIZE4);
2174
2175 for (j = 0; j < f->frame_encryption->num_partitions; ++j) {
2176 uint64_t value = 0;
2177 r = ne_read_uint(&ctx->io, &value, PACKET_OFFSET_SIZE4);
2178 if (r != 1) {
2179 break;
2180 }
2181
2182 f->frame_encryption->partition_offsets[j] = (uint32_t) value;
2183 }
2184
2185 /* If any of the partition offsets did not return 1, then fail. */
2186 if (j != f->frame_encryption->num_partitions) {
2187 ne_free_frame(f);
2188 nestegg_free_packet(pkt);
2189 return r;
2190 }
2191 }
2192 } else {
2193 encryption_size = SIGNAL_BYTE_SIZE1;
2194 }
2195 } else {
2196 encryption_size = 0;
2197 }
2198 if (encryption_size > frame_sizes[i]) {
2199 ne_free_frame(f);
2200 nestegg_free_packet(pkt);
2201 return -1;
2202 }
2203 data_size = frame_sizes[i] - encryption_size;
2204 /* Encryption parsed */
2205 f->data = ne_alloc(data_size);
2206 if (!f->data) {
2207 ne_free_frame(f);
2208 nestegg_free_packet(pkt);
2209 return -1;
2210 }
2211 f->length = data_size;
2212 r = ne_io_read(&ctx->io, f->data, data_size);
2213 if (r != 1) {
2214 ne_free_frame(f);
2215 nestegg_free_packet(pkt);
2216 return r;
2217 }
2218
2219 pkt->frames[pkt->frame_count++] = f;
2220 }
2221
2222 *data = pkt;
2223
2224 return 1;
2225}
2226
2227static int
2228ne_read_block_additions(nestegg * ctx, uint64_t block_size, struct block_additional ** pkt_block_additional)
2229{
2230 int r;
2231 uint64_t id, size, data_size;
2232 int64_t block_additions_end, block_more_end;
2233 void * data;
2234 int has_data;
2235 struct block_additional * block_additional;
2236 uint64_t add_id;
2237
2238 assert(*pkt_block_additional == NULL)((void) sizeof ((*pkt_block_additional == ((void*)0)) ? 1 : 0
), __extension__ ({ if (*pkt_block_additional == ((void*)0)) ;
else __assert_fail ("*pkt_block_additional == NULL", "./../../../../media/libnestegg/src/nestegg.c"
, 2238, __extension__ __PRETTY_FUNCTION__); }))
;
2239
2240 block_additions_end = ne_io_tell(&ctx->io);
2241 if (block_additions_end < 0)
2242 return -1;
2243 block_additions_end += block_size;
2244
2245 while (1) {
2246 int64_t pos = ne_io_tell(&ctx->io);
2247 if (pos < 0)
2248 return -1;
2249 if (pos >= block_additions_end)
2250 break;
2251 add_id = 1;
2252 data = NULL((void*)0);
2253 has_data = 0;
2254 data_size = 0;
2255 r = ne_read_element(ctx, &id, &size);
2256 if (r != 1)
2257 return r;
2258
2259 if (id != ID_BLOCK_MORE0xa6) {
2260 /* We don't know what this element is, so skip over it */
2261 if (id != ID_VOID0xec && id != ID_CRC320xbf)
2262 ctx->log(ctx, NESTEGG_LOG_DEBUG1,
2263 "unknown element %llx in BlockAdditions", id);
2264 r = ne_io_read_skip(&ctx->io, size);
2265 if (r != 1)
2266 return r;
2267 continue;
2268 }
2269
2270 block_more_end = ne_io_tell(&ctx->io);
2271 if (block_more_end < 0)
2272 return -1;
2273 block_more_end += size;
2274
2275 while (1) {
2276 int64_t pos = ne_io_tell(&ctx->io);
2277 if (pos < 0) {
2278 free(data);
2279 return -1;
2280 }
2281 if (pos >= block_more_end)
2282 break;
2283 r = ne_read_element(ctx, &id, &size);
2284 if (r != 1) {
2285 free(data);
2286 return r;
2287 }
2288
2289 if (id == ID_BLOCK_ADD_ID0xee) {
2290 /* A zero-length BlockAddID resolves to the default of 1 (RFC 9559
2291 Section 5.1.3.5.2.3), which add_id already holds. */
2292 if (size != 0) {
2293 r = ne_read_uint(&ctx->io, &add_id, size);
2294 if (r != 1) {
2295 free(data);
2296 return r;
2297 }
2298 }
2299
2300 if (add_id == 0) {
2301 ctx->log(ctx, NESTEGG_LOG_ERROR1000, "Disallowed BlockAddId 0 used");
2302 free(data);
2303 return -1;
2304 }
2305 } else if (id == ID_BLOCK_ADDITIONAL0xa5) {
2306 if (has_data) {
2307 /* BlockAdditional is supposed to only occur once in a
2308 BlockMore. */
2309 ctx->log(ctx, NESTEGG_LOG_ERROR1000,
2310 "Multiple BlockAdditional elements in a BlockMore");
2311 free(data);
2312 return -1;
2313 }
2314
2315 has_data = 1;
2316 data_size = size;
2317 if (data_size >= LIMIT_FRAME(1 << 28)) {
2318 return -1;
2319 }
2320 if (data_size != 0) {
2321 data = ne_alloc(data_size);
2322 if (!data)
2323 return -1;
2324 r = ne_io_read(&ctx->io, data, data_size);
2325 if (r != 1) {
2326 free(data);
2327 return r;
2328 }
2329 }
2330 } else {
2331 /* We don't know what this element is, so skip over it */
2332 if (id != ID_VOID0xec && id != ID_CRC320xbf)
2333 ctx->log(ctx, NESTEGG_LOG_DEBUG1,
2334 "unknown element %llx in BlockMore", id);
2335 r = ne_io_read_skip(&ctx->io, size);
2336 if (r != 1) {
2337 free(data);
2338 return r;
2339 }
2340 }
2341 }
2342
2343 if (has_data == 0) {
2344 ctx->log(ctx, NESTEGG_LOG_ERROR1000,
2345 "No BlockAdditional element in a BlockMore");
2346 return -1;
2347 }
2348
2349 block_additional = ne_alloc(sizeof(*block_additional));
2350 block_additional->next = *pkt_block_additional;
2351 block_additional->id = add_id;
2352 block_additional->data = data;
2353 block_additional->length = data_size;
2354 *pkt_block_additional = block_additional;
2355 }
2356
2357 return 1;
2358}
2359
2360static uint64_t
2361ne_buf_read_id(unsigned char const * p, size_t length)
2362{
2363 uint64_t id = 0;
2364
2365 while (length > 0) {
2366 length--;
2367 id <<= 8;
2368 id |= *p++;
2369 }
2370
2371 return id;
2372}
2373
2374static struct seek *
2375ne_find_seek_for_id(struct ebml_list_node * seek_head, uint64_t id)
2376{
2377 struct ebml_list * head;
2378 struct ebml_list_node * seek;
2379 struct ebml_binary binary_id;
2380 struct seek * s;
2381
2382 while (seek_head) {
2383 assert(seek_head->id == ID_SEEK_HEAD)((void) sizeof ((seek_head->id == 0x114d9b74) ? 1 : 0), __extension__
({ if (seek_head->id == 0x114d9b74) ; else __assert_fail (
"seek_head->id == ID_SEEK_HEAD", "./../../../../media/libnestegg/src/nestegg.c"
, 2383, __extension__ __PRETTY_FUNCTION__); }))
;
2384 head = seek_head->data;
2385 seek = head->head;
2386
2387 while (seek) {
2388 assert(seek->id == ID_SEEK)((void) sizeof ((seek->id == 0x4dbb) ? 1 : 0), __extension__
({ if (seek->id == 0x4dbb) ; else __assert_fail ("seek->id == ID_SEEK"
, "./../../../../media/libnestegg/src/nestegg.c", 2388, __extension__
__PRETTY_FUNCTION__); }))
;
2389 s = seek->data;
2390
2391 if (ne_get_binary(s->id, &binary_id) == 0 &&
2392 ne_buf_read_id(binary_id.data, binary_id.length) == id)
2393 return s;
2394
2395 seek = seek->next;
2396 }
2397
2398 seek_head = seek_head->next;
2399 }
2400
2401 return NULL((void*)0);
2402}
2403
2404static struct cue_track_positions *
2405ne_find_cue_position_for_track_number(struct ebml_list_node * node,
2406 uint64_t wanted_track_number)
2407{
2408 struct cue_track_positions * pos = NULL((void*)0);
2409 uint64_t track_number;
2410
2411 while (node) {
2412 assert(node->id == ID_CUE_TRACK_POSITIONS)((void) sizeof ((node->id == 0xb7) ? 1 : 0), __extension__
({ if (node->id == 0xb7) ; else __assert_fail ("node->id == ID_CUE_TRACK_POSITIONS"
, "./../../../../media/libnestegg/src/nestegg.c", 2412, __extension__
__PRETTY_FUNCTION__); }))
;
2413 pos = node->data;
2414 if (ne_get_uint(pos->track, &track_number) != 0)
2415 return NULL((void*)0);
2416
2417 if (track_number == wanted_track_number)
2418 return pos;
2419
2420 node = node->next;
2421 }
2422
2423 return NULL((void*)0);
2424}
2425
2426static struct cue_point *
2427ne_find_cue_point_for_tstamp(struct ebml_list_node * cue_point,
2428 uint64_t track_number, uint64_t scale,
2429 uint64_t tstamp)
2430{
2431 uint64_t time;
2432 struct cue_point * c, * prev = NULL((void*)0);
2433
2434 while (cue_point) {
2435 assert(cue_point->id == ID_CUE_POINT)((void) sizeof ((cue_point->id == 0xbb) ? 1 : 0), __extension__
({ if (cue_point->id == 0xbb) ; else __assert_fail ("cue_point->id == ID_CUE_POINT"
, "./../../../../media/libnestegg/src/nestegg.c", 2435, __extension__
__PRETTY_FUNCTION__); }))
;
2436 c = cue_point->data;
2437
2438 if (!prev)
2439 prev = c;
2440
2441 if (ne_get_uint(c->time, &time) == 0 && time * scale > tstamp)
2442 break;
2443
2444 if (ne_find_cue_position_for_track_number(c->cue_track_positions.head,
2445 track_number) != NULL((void*)0))
2446 prev = c;
2447
2448 cue_point = cue_point->next;
2449 }
2450
2451 return prev;
2452}
2453
2454static void
2455ne_null_log_callback(nestegg * ctx, unsigned int severity, char const * fmt, ...)
2456{
2457 if (ctx && severity && fmt)
2458 return;
2459}
2460
2461static int
2462ne_init_cue_points(nestegg * ctx, int64_t max_offset)
2463{
2464 int r;
2465 struct ebml_list_node * node = ctx->segment.cues.cue_point.head;
2466 struct seek * found;
2467 uint64_t seek_pos, id;
2468 struct saved_state state;
2469
2470 /* If there are no cues loaded, check for cues element in the seek head
2471 and load it. */
2472 if (!node) {
2473 found = ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES0x1c53bb6b);
2474 if (!found)
2475 return -1;
2476
2477 if (ne_get_uint(found->position, &seek_pos) != 0)
2478 return -1;
2479
2480 /* Save old parser state. */
2481 r = ne_ctx_save(ctx, &state);
2482 if (r != 0)
2483 return -1;
2484
2485 /* Seek and set up parser state for segment-level element (Cues). */
2486 r = ne_io_seek(&ctx->io, ctx->segment_offset + seek_pos, NESTEGG_SEEK_SET0);
2487 if (r != 0)
2488 return -1;
2489 ctx->last_valid = 0;
2490
2491 r = ne_read_element(ctx, &id, NULL((void*)0));
2492 if (r != 1)
2493 return -1;
2494
2495 if (id != ID_CUES0x1c53bb6b)
2496 return -1;
2497
2498 assert(ctx->ancestor == NULL)((void) sizeof ((ctx->ancestor == ((void*)0)) ? 1 : 0), __extension__
({ if (ctx->ancestor == ((void*)0)) ; else __assert_fail (
"ctx->ancestor == NULL", "./../../../../media/libnestegg/src/nestegg.c"
, 2498, __extension__ __PRETTY_FUNCTION__); }))
;
2499 if (ne_ctx_push(ctx, ne_top_level_elements, ctx) < 0)
2500 return -1;
2501 if (ne_ctx_push(ctx, ne_segment_elements, &ctx->segment) < 0)
2502 return -1;
2503 if (ne_ctx_push(ctx, ne_cues_elements, &ctx->segment.cues) < 0)
2504 return -1;
2505 /* parser will run until end of cues element. */
2506 ctx->log(ctx, NESTEGG_LOG_DEBUG1, "seek: parsing cue elements");
2507 r = ne_parse_with_io_limit(ctx, ne_cues_elements, max_offset);
2508 while (ctx->ancestor)
2509 ne_ctx_pop(ctx);
2510
2511 /* Reset parser state to original state and seek back to old position. */
2512 if (ne_ctx_restore(ctx, &state) != 0)
2513 return -1;
2514
2515 if (r < 0)
2516 return -1;
2517
2518 node = ctx->segment.cues.cue_point.head;
2519 if (!node)
2520 return -1;
2521 }
2522
2523 return 0;
2524}
2525
2526/* Three functions that implement the nestegg_io interface, operating on a
2527 io_buffer. */
2528struct io_buffer {
2529 unsigned char const * buffer;
2530 size_t length;
2531 int64_t offset;
2532};
2533
2534static int64_t
2535ne_buffer_read(void * buffer, size_t length, void * userdata)
2536{
2537 struct io_buffer * iob = userdata;
2538 size_t available = iob->length - iob->offset;
2539
2540 if (available == 0)
2541 return 0;
2542
2543 if (available < length)
2544 return -1;
2545
2546 memcpy(buffer, iob->buffer + iob->offset, length);
2547 iob->offset += length;
2548
2549 return (int64_t) length;
2550}
2551
2552static int
2553ne_buffer_seek(int64_t offset, int whence, void * userdata)
2554{
2555 struct io_buffer * iob = userdata;
2556 int64_t o = iob->offset;
2557
2558 switch(whence) {
2559 case NESTEGG_SEEK_SET0:
2560 o = offset;
2561 break;
2562 case NESTEGG_SEEK_CUR1:
2563 o += offset;
2564 break;
2565 case NESTEGG_SEEK_END2:
2566 o = iob->length + offset;
2567 break;
2568 }
2569
2570 if (o < 0 || o > (int64_t) iob->length)
2571 return -1;
2572
2573 iob->offset = o;
2574 return 0;
2575}
2576
2577static int64_t
2578ne_buffer_tell(void * userdata)
2579{
2580 struct io_buffer * iob = userdata;
2581 return iob->offset;
2582}
2583
2584static int
2585ne_context_new(nestegg ** context, nestegg_io io, nestegg_log callback)
2586{
2587 nestegg * ctx;
2588
2589 if (!(io.seek && io.tell && io.read))
2590 return -1;
2591
2592 ctx = ne_alloc(sizeof(*ctx));
2593 if (!ctx)
2594 return -1;
2595
2596 ctx->io.io = ne_alloc(sizeof(*ctx->io.io));
2597 if (!ctx->io.io) {
2598 nestegg_destroy(ctx);
2599 return -1;
2600 }
2601 memcpy(ctx->io.io, &io, sizeof(io));
2602 ctx->log = callback;
2603 ctx->alloc_pool = ne_pool_init();
2604 if (!ctx->alloc_pool) {
2605 nestegg_destroy(ctx);
2606 return -1;
2607 }
2608
2609 if (!ctx->log)
2610 ctx->log = ne_null_log_callback;
2611
2612 ne_init_defaults(ne_top_level_elements, ctx);
2613
2614 *context = ctx;
2615 return 0;
2616}
2617
2618static int
2619ne_match_doc_type(nestegg_io io, int64_t max_offset, const char* doc_type)
2620{
2621 int r;
2622 uint64_t id;
2623 char * doctype;
2624 nestegg * ctx;
2625
2626 if (ne_context_new(&ctx, io, NULL((void*)0)) != 0)
2627 return -1;
2628
2629 r = ne_peek_element_with_io_limit(ctx, &id, max_offset);
2630 if (r != 1) {
2631 nestegg_destroy(ctx);
2632 return 0;
2633 }
2634
2635 if (id != ID_EBML0x1a45dfa3) {
2636 nestegg_destroy(ctx);
2637 return 0;
2638 }
2639
2640 if (ne_ctx_push(ctx, ne_top_level_elements, ctx) < 0) {
2641 nestegg_destroy(ctx);
2642 return -1;
2643 }
2644
2645 /* we don't check the return value of ne_parse, that might fail because
2646 max_offset is not on a valid element end point. We only want to check
2647 the EBML ID and that the doctype is equal to given doc type. */
2648 ne_parse_with_io_limit(ctx, NULL((void*)0), max_offset);
2649 while (ctx->ancestor)
2650 ne_ctx_pop(ctx);
2651
2652 if (ne_get_string(ctx->ebml.doctype, &doctype) != 0 ||
2653 strcmp(doctype, doc_type) != 0) {
2654 nestegg_destroy(ctx);
2655 return 0;
2656 }
2657
2658 nestegg_destroy(ctx);
2659
2660 return 1;
2661}
2662
2663static void
2664ne_free_block_additions(struct block_additional * block_additional)
2665{
2666 while (block_additional) {
2667 struct block_additional * tmp = block_additional;
2668 block_additional = block_additional->next;
2669 free(tmp->data);
2670 free(tmp);
2671 }
2672}
2673
2674int
2675nestegg_init(nestegg ** context, nestegg_io io, nestegg_log callback, int64_t max_offset)
2676{
2677 int r;
2678 uint64_t id, version, docversion;
2679 char * doctype;
2680 nestegg * ctx;
2681
2682 if (ne_context_new(&ctx, io, callback) != 0)
2683 return -1;
2684
2685 r = ne_peek_element_with_io_limit(ctx, &id, max_offset);
2686 if (r != 1) {
2687 nestegg_destroy(ctx);
2688 return -1;
2689 }
2690
2691 if (id != ID_EBML0x1a45dfa3) {
2692 nestegg_destroy(ctx);
2693 return -1;
2694 }
2695
2696 ctx->log(ctx, NESTEGG_LOG_DEBUG1, "ctx %p", ctx);
2697
2698 if (ne_ctx_push(ctx, ne_top_level_elements, ctx) < 0) {
2699 nestegg_destroy(ctx);
2700 return -1;
2701 }
2702
2703 r = ne_parse_with_io_limit(ctx, NULL((void*)0), max_offset);
2704 while (ctx->ancestor)
2705 ne_ctx_pop(ctx);
2706
2707 if (r != 1) {
2708 nestegg_destroy(ctx);
2709 return -1;
2710 }
2711
2712 if (ne_get_uint(ctx->ebml.ebml_read_version, &version) != 0 ||
2713 version != 1) {
2714 nestegg_destroy(ctx);
2715 return -1;
2716 }
2717
2718 /* DocType's declared default is "matroska"; string defaults are not
2719 representable in the element descriptors, so apply it here. */
2720 if (ne_get_string(ctx->ebml.doctype, &doctype) != 0)
2721 doctype = DOCTYPE_MKV"matroska";
2722 if (!!strcmp(doctype, DOCTYPE_WEBM"webm") && !!strcmp(doctype, DOCTYPE_MKV"matroska")) {
2723 nestegg_destroy(ctx);
2724 return -1;
2725 }
2726
2727 if (ne_get_uint(ctx->ebml.doctype_read_version, &docversion) != 0 ||
2728 docversion < 1 || docversion > 2) {
2729 nestegg_destroy(ctx);
2730 return -1;
2731 }
2732
2733 if (!ctx->segment.tracks.track_entry.head) {
2734 nestegg_destroy(ctx);
2735 return -1;
2736 }
2737
2738 if (ne_init_track_indexes(ctx) != 0) {
2739 nestegg_destroy(ctx);
2740 return -1;
2741 }
2742
2743 r = ne_ctx_save(ctx, &ctx->saved);
2744 if (r != 0) {
2745 nestegg_destroy(ctx);
2746 return -1;
2747 }
2748
2749 *context = ctx;
2750
2751 return 0;
2752}
2753
2754void
2755nestegg_destroy(nestegg * ctx)
2756{
2757 assert(ctx->ancestor == NULL)((void) sizeof ((ctx->ancestor == ((void*)0)) ? 1 : 0), __extension__
({ if (ctx->ancestor == ((void*)0)) ; else __assert_fail (
"ctx->ancestor == NULL", "./../../../../media/libnestegg/src/nestegg.c"
, 2757, __extension__ __PRETTY_FUNCTION__); }))
;
2758 if (ctx->alloc_pool)
2759 ne_pool_destroy(ctx->alloc_pool);
2760 free(ctx->io.io);
2761 free(ctx);
2762}
2763
2764int
2765nestegg_duration(nestegg * ctx, uint64_t * duration)
2766{
2767 uint64_t tc_scale;
2768 double unscaled_duration;
2769
2770 if (ne_get_float(ctx->segment.info.duration, &unscaled_duration) != 0)
2771 return -1;
2772
2773 tc_scale = ne_get_timecode_scale(ctx);
2774 if (tc_scale == 0)
2775 return -1;
2776
2777 if (unscaled_duration != unscaled_duration ||
2778 unscaled_duration < 0 || unscaled_duration >= (double) UINT64_MAX(18446744073709551615UL) ||
2779 (uint64_t) unscaled_duration > UINT64_MAX(18446744073709551615UL) / tc_scale)
2780 return -1;
2781
2782 *duration = (uint64_t) (unscaled_duration * tc_scale);
2783 return 0;
2784}
2785
2786int
2787nestegg_tstamp_scale(nestegg * ctx, uint64_t * scale)
2788{
2789 *scale = ne_get_timecode_scale(ctx);
2790 if (*scale == 0)
2791 return -1;
2792 return 0;
2793}
2794
2795int
2796nestegg_track_count(nestegg * ctx, unsigned int * tracks)
2797{
2798 *tracks = ctx->track_count;
2799 return 0;
2800}
2801
2802int
2803nestegg_get_cue_point(nestegg * ctx, unsigned int cluster_num, int64_t max_offset,
2804 int64_t * start_pos, int64_t * end_pos, uint64_t * tstamp)
2805{
2806 int range_obtained = 0;
2807 unsigned int cluster_count = 0;
2808 struct cue_point * cue_point;
2809 struct cue_track_positions * pos;
2810 uint64_t seek_pos, track_number, tc_scale, time;
2811 struct ebml_list_node * cues_node = ctx->segment.cues.cue_point.head;
2812 struct ebml_list_node * cue_pos_node = NULL((void*)0);
2813
2814 if (!start_pos || !end_pos || !tstamp)
2815 return -1;
2816
2817 /* Initialise return values */
2818 *start_pos = -1;
2819 *end_pos = -1;
2820 *tstamp = 0;
2821
2822 if (!cues_node) {
2823 ne_init_cue_points(ctx, max_offset);
2824 cues_node = ctx->segment.cues.cue_point.head;
2825 /* Verify cues have been added to context. */
2826 if (!cues_node)
2827 return -1;
2828 }
2829
2830 tc_scale = ne_get_timecode_scale(ctx);
2831 if (tc_scale == 0)
2832 return -1;
2833
2834 while (cues_node && !range_obtained) {
2835 assert(cues_node->id == ID_CUE_POINT)((void) sizeof ((cues_node->id == 0xbb) ? 1 : 0), __extension__
({ if (cues_node->id == 0xbb) ; else __assert_fail ("cues_node->id == ID_CUE_POINT"
, "./../../../../media/libnestegg/src/nestegg.c", 2835, __extension__
__PRETTY_FUNCTION__); }))
;
2836 cue_point = cues_node->data;
2837 cue_pos_node = cue_point->cue_track_positions.head;
2838 while (cue_pos_node) {
2839 assert(cue_pos_node->id == ID_CUE_TRACK_POSITIONS)((void) sizeof ((cue_pos_node->id == 0xb7) ? 1 : 0), __extension__
({ if (cue_pos_node->id == 0xb7) ; else __assert_fail ("cue_pos_node->id == ID_CUE_TRACK_POSITIONS"
, "./../../../../media/libnestegg/src/nestegg.c", 2839, __extension__
__PRETTY_FUNCTION__); }))
;
2840 pos = cue_pos_node->data;
2841 if (ne_get_uint(pos->track, &track_number) != 0)
2842 return -1;
2843
2844 if (ne_map_track_number_to_index(ctx, track_number, NULL((void*)0)) != 0)
2845 return -1;
2846
2847 if (ne_get_uint(pos->cluster_position, &seek_pos) != 0)
2848 return -1;
2849 if (cluster_count == cluster_num) {
2850 *start_pos = ctx->segment_offset + seek_pos;
2851 if (ne_get_uint(cue_point->time, &time) != 0)
2852 return -1;
2853 *tstamp = time * tc_scale;
2854 } else if (cluster_count == cluster_num + 1) {
2855 *end_pos = ctx->segment_offset + seek_pos - 1;
2856 range_obtained = 1;
2857 break;
2858 }
2859 cluster_count++;
2860 cue_pos_node = cue_pos_node->next;
2861 }
2862 cues_node = cues_node->next;
2863 }
2864
2865 return 0;
2866}
2867
2868int
2869nestegg_offset_seek(nestegg * ctx, uint64_t offset)
2870{
2871 int r;
2872
2873 if (offset > INT64_MAX(9223372036854775807L))
2874 return -1;
2875
2876 /* Seek and set up parser state for segment-level element (Cluster). */
2877 r = ne_io_seek(&ctx->io, offset, NESTEGG_SEEK_SET0);
2878 if (r != 0)
2879 return -1;
2880 ctx->last_valid = 0;
2881
2882 assert(ctx->ancestor == NULL)((void) sizeof ((ctx->ancestor == ((void*)0)) ? 1 : 0), __extension__
({ if (ctx->ancestor == ((void*)0)) ; else __assert_fail (
"ctx->ancestor == NULL", "./../../../../media/libnestegg/src/nestegg.c"
, 2882, __extension__ __PRETTY_FUNCTION__); }))
;
2883
2884 return 0;
2885}
2886
2887int
2888nestegg_track_seek(nestegg * ctx, unsigned int track, uint64_t tstamp)
2889{
2890 int r;
2891 struct cue_point * cue_point;
2892 struct cue_track_positions * pos;
2893 struct track_entry * entry;
2894 uint64_t seek_pos, tc_scale, track_number;
2895
2896 entry = ne_find_track_entry(ctx, track);
2897 if (!entry || ne_get_uint(entry->number, &track_number) != 0)
2898 return -1;
2899
2900 /* If there are no cues loaded, check for cues element in the seek head
2901 and load it. */
2902 if (!ctx->segment.cues.cue_point.head) {
2903 r = ne_init_cue_points(ctx, -1);
2904 if (r != 0)
2905 return -1;
2906 }
2907
2908 tc_scale = ne_get_timecode_scale(ctx);
2909 if (tc_scale == 0)
2910 return -1;
2911
2912 cue_point = ne_find_cue_point_for_tstamp(ctx->segment.cues.cue_point.head,
2913 track_number, tc_scale, tstamp);
2914 if (!cue_point)
2915 return -1;
2916
2917 pos = ne_find_cue_position_for_track_number(
2918 cue_point->cue_track_positions.head, track_number);
2919 if (pos == NULL((void*)0))
2920 return -1;
2921
2922 if (ne_get_uint(pos->cluster_position, &seek_pos) != 0)
2923 return -1;
2924
2925 /* Seek to (we assume) the start of a Cluster element. */
2926 r = nestegg_offset_seek(ctx, ctx->segment_offset + seek_pos);
2927 if (r != 0)
2928 return -1;
2929
2930 return 0;
2931}
2932
2933int
2934nestegg_track_type(nestegg * ctx, unsigned int track)
2935{
2936 struct track_entry * entry;
2937 uint64_t type;
2938
2939 entry = ne_find_track_entry(ctx, track);
2940 if (!entry)
2941 return -1;
2942
2943 if (ne_get_uint(entry->type, &type) != 0)
2944 return -1;
2945
2946 if (type == TRACK_TYPE_VIDEO1)
2947 return NESTEGG_TRACK_VIDEO0;
2948
2949 if (type == TRACK_TYPE_AUDIO2)
2950 return NESTEGG_TRACK_AUDIO1;
2951
2952 return NESTEGG_TRACK_UNKNOWN2147483647;
2953}
2954
2955int
2956nestegg_track_codec_id(nestegg * ctx, unsigned int track)
2957{
2958 char * codec_id;
2959 struct track_entry * entry;
2960
2961 entry = ne_find_track_entry(ctx, track);
2962 if (!entry)
2963 return -1;
2964
2965 if (ne_get_string(entry->codec_id, &codec_id) != 0)
2966 return -1;
2967
2968 ctx->log(ctx, NESTEGG_LOG_DEBUG1, "nestegg_track_codec_id: %s\n", codec_id);
2969 if (strcmp(codec_id, TRACK_ID_VP8"V_VP8") == 0)
2970 return NESTEGG_CODEC_VP80;
2971
2972 if (strcmp(codec_id, TRACK_ID_VP9"V_VP9") == 0)
2973 return NESTEGG_CODEC_VP92;
2974
2975 if (strcmp(codec_id, TRACK_ID_AV1"V_AV1") == 0)
2976 return NESTEGG_CODEC_AV14;
2977
2978 if (strcmp(codec_id, TRACK_ID_VORBIS"A_VORBIS") == 0)
2979 return NESTEGG_CODEC_VORBIS1;
2980
2981 if (strcmp(codec_id, TRACK_ID_OPUS"A_OPUS") == 0)
2982 return NESTEGG_CODEC_OPUS3;
2983
2984 if (strcmp(codec_id, TRACK_ID_AVC"V_MPEG4/ISO/AVC") == 0)
2985 return NESTEGG_CODEC_AVC5;
2986
2987 if (strcmp(codec_id, TRACK_ID_HEVC"V_MPEGH/ISO/HEVC") == 0)
2988 return NESTEGG_CODEC_HEVC6;
2989
2990 if (strcmp(codec_id, TRACK_ID_AAC"A_AAC") == 0 ||
2991 strcmp(codec_id, TRACK_ID_AAC_MP4_LC"A_AAC/MPEG4/LC") == 0 ||
2992 strcmp(codec_id, TRACK_ID_AAC_MP4_LC_SBR"A_AAC/MPEG4/LC/SBR") == 0 ||
2993 strcmp(codec_id, TRACK_ID_AAC_MP4_LTP"A_AAC/MPEG4/LTP") == 0 ||
2994 strcmp(codec_id, TRACK_ID_AAC_MP4_MAIN"A_AAC/MPEG4/MAIN") == 0 ||
2995 strcmp(codec_id, TRACK_ID_AAC_MP4_SSR"A_AAC/MPEG4/SSR") == 0)
2996 return NESTEGG_CODEC_AAC7;
2997
2998 if (strcmp(codec_id, TRACK_ID_FLAC"A_FLAC") == 0)
2999 return NESTEGG_CODEC_FLAC8;
3000
3001 if (strcmp(codec_id, TRACK_ID_MP3"A_MPEG/L3") == 0)
3002 return NESTEGG_CODEC_MP39;
3003
3004 if (strcmp(codec_id, TRACK_ID_PCM_FLOAT"A_PCM/FLOAT/IEEE") == 0 ||
3005 strcmp(codec_id, TRACK_ID_PCM_INT_BE"A_PCM/INT/BIG") == 0 ||
3006 strcmp(codec_id, TRACK_ID_PCM_INT_LE"A_PCM/INT/LIT") == 0)
3007 return NESTEGG_CODEC_PCM10;
3008
3009 return NESTEGG_CODEC_UNKNOWN2147483647;
3010}
3011
3012int
3013nestegg_track_codec_data_count(nestegg * ctx, unsigned int track,
3014 unsigned int * count)
3015{
3016 struct track_entry * entry;
3017 struct ebml_binary codec_private;
3018 int codec_id;
3019 unsigned char * p;
3020
3021 *count = 0;
3022
3023 entry = ne_find_track_entry(ctx, track);
3024 if (!entry)
3025 return -1;
3026
3027 codec_id = nestegg_track_codec_id(ctx, track);
3028
3029 /* Usually don't have codec private */
3030 if (codec_id == NESTEGG_CODEC_MP39 || codec_id == NESTEGG_CODEC_VP80 ||
3031 codec_id == NESTEGG_CODEC_VP92) {
3032 *count = 0;
3033 return 0;
3034 }
3035
3036 /* Usually one codec private */
3037 if (codec_id == NESTEGG_CODEC_OPUS3 || codec_id == NESTEGG_CODEC_PCM10 ||
3038 codec_id == NESTEGG_CODEC_AAC7 || codec_id == NESTEGG_CODEC_FLAC8 ||
3039 codec_id == NESTEGG_CODEC_AVC5 || codec_id == NESTEGG_CODEC_HEVC6 ||
3040 codec_id == NESTEGG_CODEC_AV14) {
3041 *count = 1;
3042 return 0;
3043 }
3044
3045 /* Vorbis spec requires three headers in the codec private */
3046 if (codec_id != NESTEGG_CODEC_VORBIS1)
3047 return -1;
3048
3049 if (ne_get_binary(entry->codec_private, &codec_private) != 0)
3050 return -1;
3051
3052 if (codec_private.length < 1)
3053 return -1;
3054
3055 p = codec_private.data;
3056 *count = *p + 1;
3057
3058 if (*count > 3)
3059 return -1;
3060
3061 return 0;
3062}
3063
3064int
3065nestegg_track_codec_data(nestegg * ctx, unsigned int track, unsigned int item,
3066 unsigned char ** data, size_t * length)
3067{
3068 struct track_entry * entry;
3069 struct ebml_binary codec_private;
3070 unsigned int count = 0;
3071
3072 *data = NULL((void*)0);
3073 *length = 0;
3074
3075 entry = ne_find_track_entry(ctx, track);
3076 if (!entry)
3077 return -1;
3078
3079 if (nestegg_track_codec_data_count(ctx, track, &count) != 0 || count == 0)
3080 return -1;
3081
3082 if (ne_get_binary(entry->codec_private, &codec_private) != 0)
3083 return -1;
3084
3085 if (nestegg_track_codec_id(ctx, track) == NESTEGG_CODEC_VORBIS1) {
3086 uint64_t count;
3087 uint64_t sizes[3];
3088 size_t total;
3089 unsigned char * p;
3090 unsigned int i;
3091 int r;
3092
3093 nestegg_io buf_io;
3094 ne_io buf_io_ctx;
3095 struct io_buffer userdata;
3096 userdata.buffer = codec_private.data;
3097 userdata.length = codec_private.length;
3098 userdata.offset = 0;
3099
3100 buf_io.read = ne_buffer_read;
3101 buf_io.seek = ne_buffer_seek;
3102 buf_io.tell = ne_buffer_tell;
3103 buf_io.userdata = &userdata;
3104
3105 memset(&buf_io_ctx, 0, sizeof(buf_io_ctx));
3106 buf_io_ctx.io = &buf_io;
3107 buf_io_ctx.max_offset = codec_private.length;
3108
3109 total = 0;
3110
3111 r = ne_read_uint(&buf_io_ctx, &count, 1);
3112 if (r != 1)
3113 return r;
3114 total += 1;
3115 count += 1;
3116
3117 if (count > 3)
3118 return -1;
3119 r = ne_read_xiph_lacing(&buf_io_ctx, codec_private.length, &total, count, sizes);
3120 if (r != 1)
3121 return r;
3122
3123 if (item >= count)
3124 return -1;
3125
3126 p = codec_private.data + total;
3127 for (i = 0; i < item; ++i) {
3128 p += sizes[i];
3129 }
3130 assert((size_t) (p - codec_private.data) <= codec_private.length &&((void) sizeof (((size_t) (p - codec_private.data) <= codec_private
.length && codec_private.length - (p - codec_private.
data) >= sizes[item]) ? 1 : 0), __extension__ ({ if ((size_t
) (p - codec_private.data) <= codec_private.length &&
codec_private.length - (p - codec_private.data) >= sizes[
item]) ; else __assert_fail ("(size_t) (p - codec_private.data) <= codec_private.length && codec_private.length - (p - codec_private.data) >= sizes[item]"
, "./../../../../media/libnestegg/src/nestegg.c", 3131, __extension__
__PRETTY_FUNCTION__); }))
3131 codec_private.length - (p - codec_private.data) >= sizes[item])((void) sizeof (((size_t) (p - codec_private.data) <= codec_private
.length && codec_private.length - (p - codec_private.
data) >= sizes[item]) ? 1 : 0), __extension__ ({ if ((size_t
) (p - codec_private.data) <= codec_private.length &&
codec_private.length - (p - codec_private.data) >= sizes[
item]) ; else __assert_fail ("(size_t) (p - codec_private.data) <= codec_private.length && codec_private.length - (p - codec_private.data) >= sizes[item]"
, "./../../../../media/libnestegg/src/nestegg.c", 3131, __extension__
__PRETTY_FUNCTION__); }))
;
3132 *data = p;
3133 *length = sizes[item];
3134 } else {
3135 if (item >= 1)
3136 return -1;
3137
3138 *data = codec_private.data;
3139 *length = codec_private.length;
3140 }
3141
3142 return 0;
3143}
3144
3145int
3146nestegg_track_video_params(nestegg * ctx, unsigned int track,
3147 nestegg_video_params * params)
3148{
3149 struct track_entry * entry;
3150 uint64_t value;
3151 double fvalue;
3152
3153 memset(params, 0, sizeof(*params));
3154
3155 entry = ne_find_track_entry(ctx, track);
3156 if (!entry)
3157 return -1;
3158
3159 if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_VIDEO0)
3160 return -1;
3161
3162 if (ne_get_uint(entry->video.stereo_mode, &value) == 0 &&
3163 (value <= NESTEGG_VIDEO_STEREO_TOP_BOTTOM3 ||
3164 value == NESTEGG_VIDEO_STEREO_RIGHT_LEFT11))
3165 params->stereo_mode = value;
3166
3167 if (ne_get_uint(entry->video.alpha_mode, &value) == 0)
3168 params->alpha_mode = value;
3169
3170 if (ne_get_uint(entry->video.pixel_width, &value) != 0)
3171 return -1;
3172 params->width = value;
3173
3174 if (ne_get_uint(entry->video.pixel_height, &value) != 0)
3175 return -1;
3176 params->height = value;
3177
3178 if (ne_get_uint(entry->video.pixel_crop_bottom, &value) == 0)
3179 params->crop_bottom = value;
3180
3181 if (ne_get_uint(entry->video.pixel_crop_top, &value) == 0)
3182 params->crop_top = value;
3183
3184 if (ne_get_uint(entry->video.pixel_crop_left, &value) == 0)
3185 params->crop_left = value;
3186
3187 if (ne_get_uint(entry->video.pixel_crop_right, &value) == 0)
3188 params->crop_right = value;
3189
3190 /* DisplayWidth and DisplayHeight default to PixelWidth and PixelHeight. A
3191 derived default is not representable in the element descriptors, which
3192 mark these elements DESC_FLAG_ACCESSOR_DEFAULT so that an absent and a
3193 zero-length instance both arrive here unread. Note RFC 9559 derives the
3194 default from the frame size left by the PixelCrop elements when
3195 DisplayUnit is 0; nestegg reports the uncropped size. */
3196 value = params->width;
3197 ne_get_uint(entry->video.display_width, &value);
3198 params->display_width = value;
3199
3200 value = params->height;
3201 ne_get_uint(entry->video.display_height, &value);
3202 params->display_height = value;
3203
3204 if (ne_get_uint(entry->video.colour.matrix_coefficients, &value) == 0)
3205 params->matrix_coefficients = value;
3206
3207 if (ne_get_uint(entry->video.colour.range, &value) == 0)
3208 params->range = value;
3209
3210 if (ne_get_uint(entry->video.colour.transfer_characteristics, &value) == 0)
3211 params->transfer_characteristics = value;
3212
3213 if (ne_get_uint(entry->video.colour.primaries, &value) == 0)
3214 params->primaries = value;
3215
3216 value = 0;
3217 ne_get_uint(entry->video.colour.max_cll, &value);
3218 params->max_cll = value;
3219
3220 value = 0;
3221 ne_get_uint(entry->video.colour.max_fall, &value);
3222 params->max_fall = value;
3223
3224 if (ne_get_uint(entry->video.projection.type, &value) == 0)
3225 params->projection_type = value;
3226
3227 if (ne_get_float(entry->video.projection.pose_yaw, &fvalue) == 0)
3228 params->projection_pose_yaw = fvalue;
3229
3230 if (ne_get_float(entry->video.projection.pose_pitch, &fvalue) == 0)
3231 params->projection_pose_pitch = fvalue;
3232
3233 if (ne_get_float(entry->video.projection.pose_roll, &fvalue) == 0)
3234 params->projection_pose_roll = fvalue;
3235
3236 fvalue = strtod("NaN", NULL((void*)0));
3237 ne_get_float(entry->video.colour.mastering_metadata.primary_r_chromacity_x, &fvalue);
3238 params->primary_r_chromacity_x = fvalue;
3239
3240 fvalue = strtod("NaN", NULL((void*)0));
3241 ne_get_float(entry->video.colour.mastering_metadata.primary_r_chromacity_y, &fvalue);
3242 params->primary_r_chromacity_y = fvalue;
3243
3244 fvalue = strtod("NaN", NULL((void*)0));
3245 ne_get_float(entry->video.colour.mastering_metadata.primary_g_chromacity_x, &fvalue);
3246 params->primary_g_chromacity_x = fvalue;
3247
3248 fvalue = strtod("NaN", NULL((void*)0));
3249 ne_get_float(entry->video.colour.mastering_metadata.primary_g_chromacity_y, &fvalue);
3250 params->primary_g_chromacity_y = fvalue;
3251
3252 fvalue = strtod("NaN", NULL((void*)0));
3253 ne_get_float(entry->video.colour.mastering_metadata.primary_b_chromacity_x, &fvalue);
3254 params->primary_b_chromacity_x = fvalue;
3255
3256 fvalue = strtod("NaN", NULL((void*)0));
3257 ne_get_float(entry->video.colour.mastering_metadata.primary_b_chromacity_y, &fvalue);
3258 params->primary_b_chromacity_y = fvalue;
3259
3260 fvalue = strtod("NaN", NULL((void*)0));
3261 ne_get_float(entry->video.colour.mastering_metadata.white_point_chromaticity_x, &fvalue);
3262 params->white_point_chromaticity_x = fvalue;
3263
3264 fvalue = strtod("NaN", NULL((void*)0));
3265 ne_get_float(entry->video.colour.mastering_metadata.white_point_chromaticity_y, &fvalue);
3266 params->white_point_chromaticity_y = fvalue;
3267
3268 fvalue = strtod("NaN", NULL((void*)0));
3269 ne_get_float(entry->video.colour.mastering_metadata.luminance_max, &fvalue);
3270 params->luminance_max = fvalue;
3271
3272 fvalue = strtod("NaN", NULL((void*)0));
3273 ne_get_float(entry->video.colour.mastering_metadata.luminance_min, &fvalue);
3274 params->luminance_min = fvalue;
3275
3276 return 0;
3277}
3278
3279int
3280nestegg_track_audio_params(nestegg * ctx, unsigned int track,
3281 nestegg_audio_params * params)
3282{
3283 struct track_entry * entry;
3284 uint64_t value;
3285
3286 memset(params, 0, sizeof(*params));
3287
3288 entry = ne_find_track_entry(ctx, track);
3289 if (!entry)
3290 return -1;
3291
3292 if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_AUDIO1)
3293 return -1;
3294
3295 ne_get_float(entry->audio.sampling_frequency, &params->rate);
3296
3297 if (ne_get_uint(entry->audio.channels, &value) == 0)
3298 params->channels = value;
3299
3300 /* BitDepth has no declared default; 16 is nestegg API policy. The
3301 descriptor marks it DESC_FLAG_ACCESSOR_DEFAULT so that a zero-length
3302 BitDepth reads back as 16 too, rather than as an out-of-range 0. */
3303 value = 16;
3304 ne_get_uint(entry->audio.bit_depth, &value);
3305 params->depth = value;
3306
3307 if (ne_get_uint(entry->codec_delay, &value) == 0)
3308 params->codec_delay = value;
3309
3310 if (ne_get_uint(entry->seek_preroll, &value) == 0)
3311 params->seek_preroll = value;
3312
3313 return 0;
3314}
3315
3316int
3317nestegg_track_encoding(nestegg * ctx, unsigned int track)
3318{
3319 struct track_entry * entry;
3320 struct content_encoding * encoding;
3321 uint64_t encoding_value;
3322
3323 entry = ne_find_track_entry(ctx, track);
3324 if (!entry) {
3325 ctx->log(ctx, NESTEGG_LOG_ERROR1000, "No track entry found");
3326 return -1;
3327 }
3328
3329 if (!entry->content_encodings.content_encoding.head) {
3330 /* Default encoding is compression */
3331 return NESTEGG_ENCODING_COMPRESSION0;
3332 }
3333
3334 encoding = entry->content_encodings.content_encoding.head->data;
3335
3336 encoding_value = NESTEGG_ENCODING_COMPRESSION0;
3337 ne_get_uint(encoding->content_encoding_type, &encoding_value);
3338 if (encoding_value != NESTEGG_ENCODING_COMPRESSION0 && encoding_value != NESTEGG_ENCODING_ENCRYPTION1) {
3339 ctx->log(ctx, NESTEGG_LOG_ERROR1000, "Invalid ContentEncoding element found");
3340 return -1;
3341 }
3342
3343 return encoding_value;
3344}
3345
3346int
3347nestegg_track_content_enc_key_id(nestegg * ctx, unsigned int track, unsigned char const ** content_enc_key_id,
3348 size_t * content_enc_key_id_length)
3349{
3350 struct track_entry * entry;
3351 struct content_encoding * encoding;
3352 struct content_encryption * encryption;
3353 struct content_enc_aes_settings * aes_settings;
3354 struct nestegg_encryption_params;
3355 uint64_t value;
3356 struct ebml_binary enc_key_id;
3357
3358 entry = ne_find_track_entry(ctx, track);
3359 if (!entry) {
3360 ctx->log(ctx, NESTEGG_LOG_ERROR1000, "No track entry found");
3361 return -1;
3362 }
3363
3364 if (!entry->content_encodings.content_encoding.head) {
3365 ctx->log(ctx, NESTEGG_LOG_ERROR1000, "No ContentEncoding element found");
3366 return -1;
3367 }
3368
3369 encoding = entry->content_encodings.content_encoding.head->data;
3370
3371 value = 0;
3372 ne_get_uint(encoding->content_encoding_type, &value);
3373 if (value != NESTEGG_ENCODING_ENCRYPTION1) {
3374 ctx->log(ctx, NESTEGG_LOG_ERROR1000, "Disallowed ContentEncodingType found");
3375 return -1;
3376 }
3377
3378 if (!encoding->content_encryption.head) {
3379 ctx->log(ctx, NESTEGG_LOG_ERROR1000, "No ContentEncryption element found");
3380 return -1;
3381 }
3382
3383 encryption = encoding->content_encryption.head->data;
3384
3385 value = 0;
3386 ne_get_uint(encryption->content_enc_algo, &value);
3387
3388 if (value != CONTENT_ENC_ALGO_AES5) {
3389 ctx->log(ctx, NESTEGG_LOG_ERROR1000, "Disallowed ContentEncAlgo found");
3390 return -1;
3391 }
3392
3393 if (!encryption->content_enc_aes_settings.head) {
3394 ctx->log(ctx, NESTEGG_LOG_ERROR1000, "No ContentEncAesSettings element found");
3395 return -1;
3396 }
3397
3398 aes_settings = encryption->content_enc_aes_settings.head->data;
3399 value = AES_SETTINGS_CIPHER_CTR1;
3400 ne_get_uint(aes_settings->aes_settings_cipher_mode, &value);
3401
3402 if (value != AES_SETTINGS_CIPHER_CTR1) {
3403 ctx->log(ctx, NESTEGG_LOG_ERROR1000, "Disallowed AESSettingCipherMode used");
3404 return -1;
3405 }
3406
3407 if (ne_get_binary(encryption->content_enc_key_id, &enc_key_id) != 0) {
3408 ctx->log(ctx, NESTEGG_LOG_ERROR1000, "Could not retrieve track ContentEncKeyId");
3409 return -1;
3410 }
3411
3412 *content_enc_key_id = enc_key_id.data;
3413 *content_enc_key_id_length = enc_key_id.length;
3414
3415 return 0;
3416}
3417
3418int
3419nestegg_track_default_duration(nestegg * ctx, unsigned int track,
3420 uint64_t * duration)
3421{
3422 struct track_entry * entry;
3423 uint64_t value;
3424
3425 entry = ne_find_track_entry(ctx, track);
3426 if (!entry)
3427 return -1;
3428
3429 if (ne_get_uint(entry->default_duration, &value) != 0)
3430 return -1;
3431 *duration = value;
3432
3433 return 0;
3434}
3435
3436int
3437nestegg_read_reset(nestegg * ctx)
3438{
3439 assert(ctx->ancestor == NULL)((void) sizeof ((ctx->ancestor == ((void*)0)) ? 1 : 0), __extension__
({ if (ctx->ancestor == ((void*)0)) ; else __assert_fail (
"ctx->ancestor == NULL", "./../../../../media/libnestegg/src/nestegg.c"
, 3439, __extension__ __PRETTY_FUNCTION__); }))
;
3440 return ne_ctx_restore(ctx, &ctx->saved);
3441}
3442
3443int
3444nestegg_read_packet(nestegg * ctx, nestegg_packet ** pkt)
3445{
3446 int r, read_block = 0;
3447 uint64_t id, size;
3448
3449 *pkt = NULL((void*)0);
3450
3451 assert(ctx->ancestor == NULL)((void) sizeof ((ctx->ancestor == ((void*)0)) ? 1 : 0), __extension__
({ if (ctx->ancestor == ((void*)0)) ; else __assert_fail (
"ctx->ancestor == NULL", "./../../../../media/libnestegg/src/nestegg.c"
, 3451, __extension__ __PRETTY_FUNCTION__); }))
;
3452
3453 /* Prepare for read_reset to resume parsing from this point upon error. */
3454 r = ne_ctx_save(ctx, &ctx->saved);
3455 if (r != 0)
3456 return -1;
3457
3458 while (!read_block) {
3459 r = ne_read_element(ctx, &id, &size);
3460 if (r != 1)
3461 return r;
3462
3463 switch (id) {
3464 case ID_CLUSTER0x1f43b675: {
3465 for (;;) {
3466 r = ne_read_element(ctx, &id, &size);
3467 if (r != 1)
3468 return r;
3469
3470 if (id == ID_TIMECODE0xe7)
3471 break;
3472
3473 /* Block elements cannot precede the Timecode. */
3474 if (id == ID_SIMPLE_BLOCK0xa3 || id == ID_BLOCK_GROUP0xa0)
3475 return -1;
3476
3477 r = ne_io_read_skip(&ctx->io, size);
3478 if (r != 1)
3479 return r;
3480 }
3481
3482 r = ne_read_uint(&ctx->io, &ctx->cluster_timecode, size);
3483 if (r != 1)
3484 return r;
3485 ctx->read_cluster_timecode = 1;
3486 break;
3487 }
3488 case ID_SIMPLE_BLOCK0xa3:
3489 r = ne_read_block(ctx, id, size, pkt);
3490 if (r != 1)
3491 return r;
3492 (*pkt)->end_offset = ne_io_tell(&ctx->io);
3493 if ((*pkt)->end_offset < 0) {
3494 nestegg_free_packet(*pkt);
3495 *pkt = NULL((void*)0);
3496 return -1;
3497 }
3498
3499 read_block = 1;
3500 break;
3501 case ID_BLOCK_GROUP0xa0: {
3502 int64_t block_group_end;
3503 uint64_t block_duration = 0;
3504 int read_block_duration = 0;
3505 int64_t discard_padding = 0;
3506 int read_discard_padding = 0;
3507 int64_t reference_block = 0;
3508 int read_reference_block = 0;
3509 struct block_additional * block_additional = NULL((void*)0);
3510 uint64_t tc_scale;
3511
3512 block_group_end = ne_io_tell(&ctx->io);
3513 if (block_group_end < 0)
3514 return -1;
3515 block_group_end += size;
3516
3517 /* Read the entire BlockGroup manually. */
3518 while (1) {
3519 int64_t pos = ne_io_tell(&ctx->io);
3520 if (pos < 0) {
3521 ne_free_block_additions(block_additional);
3522 if (*pkt) {
3523 nestegg_free_packet(*pkt);
3524 *pkt = NULL((void*)0);
3525 }
3526 return -1;
3527 }
3528 if (pos >= block_group_end)
3529 break;
3530 r = ne_read_element(ctx, &id, &size);
3531 if (r != 1) {
3532 ne_free_block_additions(block_additional);
3533 if (*pkt) {
3534 nestegg_free_packet(*pkt);
3535 *pkt = NULL((void*)0);
3536 }
3537 return r;
3538 }
3539
3540 switch (id) {
3541 case ID_BLOCK0xa1: {
3542 if (*pkt) {
3543 ctx->log(ctx, NESTEGG_LOG_DEBUG1,
3544 "read_packet: multiple Blocks in BlockGroup, dropping previously read Block");
3545 nestegg_free_packet(*pkt);
3546 }
3547 r = ne_read_block(ctx, id, size, pkt);
3548 if (r != 1) {
3549 ne_free_block_additions(block_additional);
3550 if (*pkt) {
3551 nestegg_free_packet(*pkt);
3552 *pkt = NULL((void*)0);
3553 }
3554 return r;
3555 }
3556
3557 read_block = 1;
3558 break;
3559 }
3560 case ID_BLOCK_DURATION0x9b: {
3561 r = ne_read_uint(&ctx->io, &block_duration, size);
3562 if (r != 1) {
3563 ne_free_block_additions(block_additional);
3564 if (*pkt) {
3565 nestegg_free_packet(*pkt);
3566 *pkt = NULL((void*)0);
3567 }
3568 return r;
3569 }
3570 tc_scale = ne_get_timecode_scale(ctx);
3571 if (tc_scale == 0) {
3572 ne_free_block_additions(block_additional);
3573 if (*pkt) {
3574 nestegg_free_packet(*pkt);
3575 *pkt = NULL((void*)0);
3576 }
3577 return -1;
3578 }
3579 block_duration = ne_saturate_mul_uint64(block_duration, tc_scale);
3580 read_block_duration = 1;
3581 break;
3582 }
3583 case ID_DISCARD_PADDING0x75a2: {
3584 r = ne_read_int(&ctx->io, &discard_padding, size);
3585 if (r != 1) {
3586 ne_free_block_additions(block_additional);
3587 if (*pkt) {
3588 nestegg_free_packet(*pkt);
3589 *pkt = NULL((void*)0);
3590 }
3591 return r;
3592 }
3593 read_discard_padding = 1;
3594 break;
3595 }
3596 case ID_BLOCK_ADDITIONS0x75a1: {
3597 /* There should only be one BlockAdditions; treat multiple as an error. */
3598 if (block_additional) {
3599 ne_free_block_additions(block_additional);
3600 if (*pkt) {
3601 nestegg_free_packet(*pkt);
3602 *pkt = NULL((void*)0);
3603 }
3604 return -1;
3605 }
3606 r = ne_read_block_additions(ctx, size, &block_additional);
3607 if (r != 1) {
3608 ne_free_block_additions(block_additional);
3609 if (*pkt) {
3610 nestegg_free_packet(*pkt);
3611 *pkt = NULL((void*)0);
3612 }
3613 return r;
3614 }
3615 break;
3616 }
3617 case ID_REFERENCE_BLOCK0xfb: {
3618 r = ne_read_int(&ctx->io, &reference_block, size);
3619 if (r != 1) {
3620 ne_free_block_additions(block_additional);
3621 if (*pkt) {
3622 nestegg_free_packet(*pkt);
3623 *pkt = NULL((void*)0);
3624 }
3625 return r;
3626 }
3627 read_reference_block = 1;
3628 break;
3629 }
3630 default:
3631 /* We don't know what this element is, so skip over it */
3632 if (id != ID_VOID0xec && id != ID_CRC320xbf)
3633 ctx->log(ctx, NESTEGG_LOG_DEBUG1,
3634 "read_packet: unknown element %llx in BlockGroup", id);
3635 r = ne_io_read_skip(&ctx->io, size);
3636 if (r != 1) {
3637 ne_free_block_additions(block_additional);
3638 if (*pkt) {
3639 nestegg_free_packet(*pkt);
3640 *pkt = NULL((void*)0);
3641 }
3642 return r;
3643 }
3644 }
3645 }
3646
3647 assert(read_block == (*pkt != NULL))((void) sizeof ((read_block == (*pkt != ((void*)0))) ? 1 : 0)
, __extension__ ({ if (read_block == (*pkt != ((void*)0))) ; else
__assert_fail ("read_block == (*pkt != NULL)", "./../../../../media/libnestegg/src/nestegg.c"
, 3647, __extension__ __PRETTY_FUNCTION__); }))
;
3648 if (*pkt) {
3649 (*pkt)->end_offset = ne_io_tell(&ctx->io);
3650 if ((*pkt)->end_offset < 0) {
3651 ne_free_block_additions(block_additional);
3652 nestegg_free_packet(*pkt);
3653 *pkt = NULL((void*)0);
3654 return -1;
3655 }
3656 (*pkt)->duration = block_duration;
3657 (*pkt)->read_duration = read_block_duration;
3658 (*pkt)->discard_padding = discard_padding;
3659 (*pkt)->read_discard_padding = read_discard_padding;
3660 (*pkt)->reference_block = reference_block;
3661 (*pkt)->read_reference_block = read_reference_block;
3662 (*pkt)->block_additional = block_additional;
3663 if ((*pkt)->read_reference_block)
3664 /* If a packet has a reference block it contains
3665 predictive frames and no keyframes */
3666 (*pkt)->keyframe = NESTEGG_PACKET_HAS_KEYFRAME_FALSE0;
3667 } else {
3668 ne_free_block_additions(block_additional);
3669 }
3670 break;
3671 }
3672 default:
3673 ctx->log(ctx, NESTEGG_LOG_DEBUG1, "read_packet: unknown element %llx", id);
3674 r = ne_io_read_skip(&ctx->io, size);
3675 if (r != 1)
3676 return r;
3677 }
3678 }
3679
3680 return 1;
3681}
3682
3683int
3684nestegg_read_last_packet(nestegg * context, unsigned int track,
3685 nestegg_packet ** packet)
3686{
3687 struct saved_state saved;
3688 uint64_t max_end_ns = 0;
3689 nestegg_packet * last_packet = NULL((void*)0);
3690
3691 if (!context || !packet) {
3692 return -1;
3693 }
3694
3695 *packet = NULL((void*)0);
3696
3697 /* Save and restore the parser state later. */
3698 if (ne_ctx_save(context, &saved) != 0)
3699 return -1;
3700
3701 for (;;) {
3702 nestegg_packet * pkt = NULL((void*)0);
3703 unsigned int pkt_track = 0;
3704 int r = nestegg_read_packet(context, &pkt);
3705 if (r == 0) {
3706 /* EOS */
3707 break;
3708 }
3709 if (r < 0) {
3710 if (pkt) {
3711 nestegg_free_packet(pkt);
3712 }
3713 if (last_packet) {
3714 nestegg_free_packet(last_packet);
3715 last_packet = NULL((void*)0);
3716 }
3717 if (ne_ctx_restore(context, &saved) != 0)
3718 return -1;
3719 return -1;
3720 }
3721
3722 if (nestegg_packet_track(pkt, &pkt_track) == 0 && pkt_track == track) {
3723 /* Calculate the end timestamp of this packet */
3724 uint64_t ts = 0;
3725 uint64_t dur = 0;
3726 uint64_t end_ns = 0;
3727 nestegg_packet_tstamp(pkt, &ts);
3728 if (nestegg_packet_duration(pkt, &dur) != 0) {
3729 dur = 0;
3730 }
3731 end_ns = ts + dur;
3732 if (end_ns >= max_end_ns) {
3733 if (last_packet) {
3734 nestegg_free_packet(last_packet);
3735 }
3736 last_packet = pkt;
3737 max_end_ns = end_ns;
3738 pkt = NULL((void*)0);
3739 }
3740 }
3741
3742 if (pkt) {
3743 nestegg_free_packet(pkt);
3744 }
3745 }
3746
3747 if (ne_ctx_restore(context, &saved) != 0) {
3748 if (last_packet)
3749 nestegg_free_packet(last_packet);
3750 return -1;
3751 }
3752
3753 if (!last_packet) {
3754 return -1;
3755 }
3756 *packet = last_packet;
3757 return 0;
3758}
3759
3760void
3761nestegg_free_packet(nestegg_packet * pkt)
3762{
3763 unsigned int i;
3764
3765 for (i = 0; i < pkt->frame_count; ++i)
3766 ne_free_frame(pkt->frames[i]);
3767 free(pkt->frames);
3768
3769 ne_free_block_additions(pkt->block_additional);
3770
3771 free(pkt);
3772}
3773
3774int
3775nestegg_packet_has_keyframe(nestegg_packet * pkt)
3776{
3777 return pkt->keyframe;
3778}
3779
3780int
3781nestegg_packet_track(nestegg_packet * pkt, unsigned int * track)
3782{
3783 *track = pkt->track;
3784 return 0;
3785}
3786
3787int
3788nestegg_packet_tstamp(nestegg_packet * pkt, uint64_t * tstamp)
3789{
3790 *tstamp = pkt->timecode;
3791 return 0;
3792}
3793
3794int
3795nestegg_packet_duration(nestegg_packet * pkt, uint64_t * duration)
3796{
3797 if (!pkt->read_duration)
3798 return -1;
3799 *duration = pkt->duration;
3800 return 0;
3801}
3802
3803int
3804nestegg_packet_discard_padding(nestegg_packet * pkt, int64_t * discard_padding)
3805{
3806 if (!pkt->read_discard_padding)
3807 return -1;
3808 *discard_padding = pkt->discard_padding;
3809 return 0;
3810}
3811
3812int
3813nestegg_packet_reference_block(nestegg_packet * pkt, int64_t * reference_block)
3814{
3815 if (!pkt->read_reference_block)
3816 return -1;
3817 *reference_block = pkt->reference_block;
3818 return 0;
3819}
3820
3821int
3822nestegg_packet_end_offset(nestegg_packet * pkt, int64_t * end_offset)
3823{
3824 *end_offset = pkt->end_offset;
3825 return 0;
3826}
3827
3828int
3829nestegg_packet_count(nestegg_packet * pkt, unsigned int * count)
3830{
3831 *count = pkt->frame_count;
3832 return 0;
3833}
3834
3835int
3836nestegg_packet_data(nestegg_packet * pkt, unsigned int item,
3837 unsigned char ** data, size_t * length)
3838{
3839 struct frame * f;
3840
3841 *data = NULL((void*)0);
3842 *length = 0;
3843
3844 if (item >= pkt->frame_count)
3845 return -1;
3846
3847 f = pkt->frames[item];
3848 *data = f->data;
3849 *length = f->length;
3850 return 0;
3851}
3852
3853int
3854nestegg_packet_additional_data(nestegg_packet * pkt, unsigned int id,
3855 unsigned char ** data, size_t * length)
3856{
3857 struct block_additional * a = pkt->block_additional;
3858
3859 *data = NULL((void*)0);
3860 *length = 0;
3861
3862 while (a) {
3863 if (a->id == id) {
3864 *data = a->data;
3865 *length = a->length;
3866 return 0;
3867 }
3868 a = a->next;
3869 }
3870
3871 return -1;
3872}
3873
3874int
3875nestegg_packet_encryption(nestegg_packet * pkt)
3876{
3877 struct frame * f = pkt->frames[0];
3878 unsigned char encrypted_bit;
3879 unsigned char partitioned_bit;
3880
3881 if (!f->frame_encryption)
3882 return NESTEGG_PACKET_HAS_SIGNAL_BYTE_FALSE0;
3883
3884 /* Should never have parsed blocks with both encryption and lacing */
3885 assert(pkt->frame_count == 1)((void) sizeof ((pkt->frame_count == 1) ? 1 : 0), __extension__
({ if (pkt->frame_count == 1) ; else __assert_fail ("pkt->frame_count == 1"
, "./../../../../media/libnestegg/src/nestegg.c", 3885, __extension__
__PRETTY_FUNCTION__); }))
;
3886
3887 encrypted_bit = f->frame_encryption->signal_byte & ENCRYPTED_BIT_MASK(1 << 0);
3888 partitioned_bit = f->frame_encryption->signal_byte & PARTITIONED_BIT_MASK(1 << 1);
3889
3890 if (encrypted_bit != PACKET_ENCRYPTED1)
3891 return NESTEGG_PACKET_HAS_SIGNAL_BYTE_UNENCRYPTED1;
3892
3893 if (partitioned_bit == PACKET_PARTITIONED2)
3894 return NESTEGG_PACKET_HAS_SIGNAL_BYTE_PARTITIONED4;
3895
3896 return NESTEGG_PACKET_HAS_SIGNAL_BYTE_ENCRYPTED2;
3897}
3898
3899int
3900nestegg_packet_iv(nestegg_packet * pkt, unsigned char const ** iv, size_t * length)
3901{
3902 struct frame * f = pkt->frames[0];
3903 unsigned char encrypted_bit;
3904
3905 *iv = NULL((void*)0);
3906 *length = 0;
3907 if (!f->frame_encryption)
3908 return -1;
3909
3910 /* Should never have parsed blocks with both encryption and lacing */
3911 assert(pkt->frame_count == 1)((void) sizeof ((pkt->frame_count == 1) ? 1 : 0), __extension__
({ if (pkt->frame_count == 1) ; else __assert_fail ("pkt->frame_count == 1"
, "./../../../../media/libnestegg/src/nestegg.c", 3911, __extension__
__PRETTY_FUNCTION__); }))
;
3912
3913 encrypted_bit = f->frame_encryption->signal_byte & ENCRYPTED_BIT_MASK(1 << 0);
3914
3915 if (encrypted_bit != PACKET_ENCRYPTED1)
3916 return 0;
3917
3918 *iv = f->frame_encryption->iv;
3919 *length = f->frame_encryption->length;
3920 return 0;
3921}
3922
3923int
3924nestegg_packet_offsets(nestegg_packet * pkt,
3925 uint32_t const ** partition_offsets,
3926 uint8_t * num_partitions)
3927{
3928 struct frame * f = pkt->frames[0];
3929 unsigned char encrypted_bit;
3930 unsigned char partitioned_bit;
3931
3932 *partition_offsets = NULL((void*)0);
3933 *num_partitions = 0;
3934
3935 if (!f->frame_encryption)
3936 return -1;
3937
3938 /* Should never have parsed blocks with both encryption and lacing */
3939 assert(pkt->frame_count == 1)((void) sizeof ((pkt->frame_count == 1) ? 1 : 0), __extension__
({ if (pkt->frame_count == 1) ; else __assert_fail ("pkt->frame_count == 1"
, "./../../../../media/libnestegg/src/nestegg.c", 3939, __extension__
__PRETTY_FUNCTION__); }))
;
3940
3941 encrypted_bit = f->frame_encryption->signal_byte & ENCRYPTED_BIT_MASK(1 << 0);
3942 partitioned_bit = f->frame_encryption->signal_byte & PARTITIONED_BIT_MASK(1 << 1);
3943
3944 if (encrypted_bit != PACKET_ENCRYPTED1 || partitioned_bit != PACKET_PARTITIONED2)
3945 return -1;
3946
3947 *num_partitions = f->frame_encryption->num_partitions;
3948 *partition_offsets = f->frame_encryption->partition_offsets;
3949 return 0;
3950}
3951
3952int
3953nestegg_has_cues(nestegg * ctx)
3954{
3955 return ctx->segment.cues.cue_point.head ||
3956 ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES0x1c53bb6b);
3957}
3958
3959static int ne_sniff(unsigned char const* buffer, size_t length,
3960 const char* doc_type)
3961{
3962 nestegg_io io;
3963 struct io_buffer userdata;
3964
3965 userdata.buffer = buffer;
3966 userdata.length = length;
3967 userdata.offset = 0;
3968
3969 io.read = ne_buffer_read;
3970 io.seek = ne_buffer_seek;
3971 io.tell = ne_buffer_tell;
3972 io.userdata = &userdata;
3973 return ne_match_doc_type(io, length, doc_type);
3974}
3975
3976int nestegg_sniff_webm(unsigned char const* buffer, size_t length)
3977{
3978 return ne_sniff(buffer, length, DOCTYPE_WEBM"webm");
3979}
3980
3981int nestegg_sniff_mkv(unsigned char const* buffer, size_t length)
3982{
3983 return ne_sniff(buffer, length, DOCTYPE_MKV"matroska");
3984}
3985
3986/* Count frames in a Block/SimpleBlock from its lacing header, then skip the
3987 remaining payload. Sets frames_out on success; returns 1 on success, <0 on error. */
3988static int
3989ne_read_block_lacing(nestegg * ctx, uint64_t block_size, uint64_t* frames_out)
3990{
3991 int r;
3992 int64_t timecode;
3993 uint64_t track_number, length, flags, frames, header_bytes, remaining;
3994 unsigned int lacing;
3995
3996 if (block_size > LIMIT_BLOCK(1 << 30))
3997 return -1;
3998
3999 r = ne_read_vint(&ctx->io, &track_number, &length);
4000 if (r != 1)
4001 return r;
4002
4003 if (track_number == 0)
4004 return -1;
4005
4006 r = ne_read_int(&ctx->io, &timecode, 2);
4007 if (r != 1)
4008 return r;
4009
4010 r = ne_read_uint(&ctx->io, &flags, 1);
4011 if (r != 1)
4012 return r;
4013
4014 frames = 0;
4015 lacing = (flags & BLOCK_FLAGS_LACING6) >> 1;
4016
4017 switch (lacing) {
4018 case LACING_NONE0:
4019 frames = 1;
4020 break;
4021 case LACING_XIPH1:
4022 case LACING_FIXED2:
4023 case LACING_EBML3:
4024 r = ne_read_uint(&ctx->io, &frames, 1);
4025 if (r != 1)
4026 return r;
4027 frames += 1;
4028 break;
4029 default:
4030 assert(0)((void) sizeof ((0) ? 1 : 0), __extension__ ({ if (0) ; else __assert_fail
("0", "./../../../../media/libnestegg/src/nestegg.c", 4030, __extension__
__PRETTY_FUNCTION__); }))
;
4031 return -1;
4032 }
4033
4034 if (frames > 256)
4035 return -1;
4036
4037 /* Skip the remainder of the block payload. */
4038 header_bytes = length + 2 + 1 + (lacing == LACING_NONE0 ? 0 : 1);
4039 if (block_size < header_bytes)
4040 return -1;
4041 remaining = block_size - header_bytes;
4042 if (remaining) {
4043 r = ne_io_read_skip(&ctx->io, remaining);
4044 if (r != 1)
4045 return r;
4046 }
4047
4048 *frames_out = frames;
4049 return 1;
4050}
4051
4052/* Consume the payload of a SimpleBlock or BlockGroup:
4053 - If block-like, count frames via lacing and add to frames_out.
4054 - If not, skip the payload.
4055 Always advances I/O to the end of the element.
4056 Returns 1 on success, <0 on error. */
4057static int
4058ne_sum_block_or_group(nestegg * ctx, uint64_t id, uint64_t size, uint64_t * frames_out)
4059{
4060 int r;
4061
4062 if (id == ID_SIMPLE_BLOCK0xa3) {
4063 uint64_t frames;
4064 frames = 0;
4065 r = ne_read_block_lacing(ctx, size, &frames);
4066 if (r != 1)
4067 return r;
4068 *frames_out += frames;
4069 return 1;
4070 }
4071
4072 if (id == ID_BLOCK_GROUP0xa0) {
4073 int64_t group_end;
4074 group_end = ne_io_tell(&ctx->io);
4075 if (group_end < 0)
4076 return -1;
4077 group_end += (int64_t) size;
4078 while (1) {
4079 uint64_t gid, gsize;
4080 int64_t pos = ne_io_tell(&ctx->io);
4081 if (pos < 0)
4082 return -1;
4083 if (pos >= group_end)
4084 break;
4085 r = ne_read_element(ctx, &gid, &gsize);
4086 if (r != 1)
4087 return r;
4088
4089 if (gid == ID_BLOCK0xa1) {
4090 uint64_t frames;
4091 frames = 0;
4092 r = ne_read_block_lacing(ctx, gsize, &frames);
4093 if (r != 1)
4094 return r;
4095 *frames_out += frames;
4096 } else {
4097 r = ne_io_read_skip(&ctx->io, gsize);
4098 if (r != 1)
4099 return r;
4100 }
4101 }
4102 return 1;
4103 }
4104
4105 /* Not a block-like element: skip its payload. */
4106 r = ne_io_read_skip(&ctx->io, size);
4107 if (r != 1)
4108 return r;
4109
4110 return 1;
4111}
4112
4113/* Returns non-zero if 'size' equals the EBML unknown-size pattern for any VINT
4114 length. Patterns (data bits all 1): 0x7F, 0x3FFF, 0x1FFFFF, 0x0FFFFFFF,
4115 0x07FFFFFFFF, 0x03FFFFFFFFFF, 0x01FFFFFFFFFFFF, 0x00FFFFFFFFFFFFFF. */
4116static int
4117ne_size_is_unknown(uint64_t size)
4118{
4119 int len;
4120 for (len = 1; len <= 8; ++len) {
4121 uint64_t mask;
4122 if (len == 8)
4123 mask = 0x00FFFFFFFFFFFFFFULL; /* 56 data bits = all ones */
4124 else
4125 mask = (1ULL << (7 * len)) - 1ULL; /* 7 data bits per byte */
4126 if (size == mask)
4127 return 1;
4128 }
4129 return 0;
4130}
4131
4132/* Read ONE Cluster and return the sum of frames of ALL SimpleBlock/Block in it.
4133 Returns 1 on success (Cluster found), 0 on clean EOS before any Cluster,
4134 <0 on error. */
4135static int
4136ne_read_cluster_frames_count(nestegg * ctx, uint64_t * frames_out)
4137{
4138 int r;
4139 uint64_t id, size;
4140 int64_t cluster_end;
4141 uint64_t totalFrames;
4142
4143 assert(ctx->ancestor == NULL)((void) sizeof ((ctx->ancestor == ((void*)0)) ? 1 : 0), __extension__
({ if (ctx->ancestor == ((void*)0)) ; else __assert_fail (
"ctx->ancestor == NULL", "./../../../../media/libnestegg/src/nestegg.c"
, 4143, __extension__ __PRETTY_FUNCTION__); }))
;
4144
4145 /* Find the next Cluster at the top level. */
4146 for (;;) {
4147 r = ne_read_element(ctx, &id, &size);
4148 if (r == 0)
4149 return 0; /* EOS before any Cluster */
4150 if (r != 1)
4151 return r;
4152
4153 if (id != ID_CLUSTER0x1f43b675) {
4154 /* Not a Cluster: consume and keep scanning. */
4155 r = ne_io_read_skip(&ctx->io, size);
4156 if (r != 1)
4157 return r;
4158 continue;
4159 }
4160
4161 totalFrames = 0;
4162
4163 if (ne_size_is_unknown(size)) {
4164 for (;;) {
4165 uint64_t nid, nsize;
4166
4167 r = ne_peek_element(ctx, &nid, &nsize);
4168 if (r == 0)
4169 break; /* EOS ends the unknown-sized Cluster */
4170 if (r != 1)
4171 return r;
4172
4173 /* Stop at next top-level element without consuming it. */
4174 if (nid == ID_EBML0x1a45dfa3 ||
4175 nid == ID_SEGMENT0x18538067 ||
4176 nid == ID_SEEK_HEAD0x114d9b74 ||
4177 nid == ID_INFO0x1549a966 ||
4178 nid == ID_TRACKS0x1654ae6b ||
4179 nid == ID_CHAPTERS0x1043a770 ||
4180 nid == ID_CLUSTER0x1f43b675 ||
4181 nid == ID_CUES0x1c53bb6b ||
4182 nid == ID_ATTACHMENTS0x1941a469 ||
4183 nid == ID_TAGS0x1254c367) {
4184 break;
4185 }
4186
4187 r = ne_read_element(ctx, &nid, &nsize);
4188 if (r != 1)
4189 return r;
4190
4191 /* Sum frames for blocks; skip other children. */
4192 r = ne_sum_block_or_group(ctx, nid, nsize, &totalFrames);
4193 if (r != 1)
4194 return r;
4195 }
4196
4197 *frames_out = totalFrames;
4198 ctx->log(ctx, NESTEGG_LOG_DEBUG1,
4199 "ne_read_cluster_frames_count: totalFrames=%llu (unknown-sized Cluster)",
4200 totalFrames);
4201 return 1;
4202 }
4203
4204 /* Known-sized Cluster: read until cluster_end. */
4205 cluster_end = ne_io_tell(&ctx->io);
4206 if (cluster_end < 0)
4207 return -1;
4208 cluster_end += (int64_t) size;
4209
4210 while (1) {
4211 uint64_t cid, csize;
4212 int64_t pos = ne_io_tell(&ctx->io);
4213 if (pos < 0)
4214 return -1;
4215 if (pos >= cluster_end)
4216 break;
4217 r = ne_read_element(ctx, &cid, &csize);
4218 if (r != 1)
4219 return r;
4220
4221 /* Sum frames for blocks; skip other children. */
4222 r = ne_sum_block_or_group(ctx, cid, csize, &totalFrames);
4223 if (r != 1)
4224 return r;
4225 }
4226
4227 *frames_out = totalFrames;
4228 ctx->log(ctx, NESTEGG_LOG_DEBUG1,
4229 "ne_read_cluster_frames_count: totalFrames=%llu", totalFrames);
4230 return 1;
4231 }
4232}
4233
4234int
4235nestegg_read_total_frames_count(nestegg * context, uint64_t * frames_out)
4236{
4237 struct saved_state saved;
4238 uint64_t totalFrames;
4239 int r;
4240
4241 if (!context || !frames_out)
4242 return -1;
4243
4244 if (ne_ctx_save(context, &saved) != 0)
4245 return -1;
4246
4247 totalFrames = 0;
4248 for (;;) {
4249 uint64_t clusterFrames;
4250 clusterFrames = 0;
4251 r = ne_read_cluster_frames_count(context, &clusterFrames);
4252 if (r == 0) {
4253 /* EOS */
4254 break;
4255 }
4256 if (r < 0) {
4257 if (ne_ctx_restore(context, &saved) != 0)
4258 return -1;
4259 return -1;
4260 }
4261 totalFrames += clusterFrames;
4262 }
4263
4264 if (ne_ctx_restore(context, &saved) != 0)
4265 return -1;
4266
4267 *frames_out = totalFrames;
4268 return 0;
4269}