media/libnestegg/src/nestegg.c

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

     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 <stdlib.h>
     9 #include <string.h>
    11 #include "halloc.h"
    12 #include "nestegg/nestegg.h"
    14 /* EBML Elements */
    15 #define ID_EBML                 0x1a45dfa3
    16 #define ID_EBML_VERSION         0x4286
    17 #define ID_EBML_READ_VERSION    0x42f7
    18 #define ID_EBML_MAX_ID_LENGTH   0x42f2
    19 #define ID_EBML_MAX_SIZE_LENGTH 0x42f3
    20 #define ID_DOCTYPE              0x4282
    21 #define ID_DOCTYPE_VERSION      0x4287
    22 #define ID_DOCTYPE_READ_VERSION 0x4285
    24 /* Global Elements */
    25 #define ID_VOID                 0xec
    26 #define ID_CRC32                0xbf
    28 /* WebM Elements */
    29 #define ID_SEGMENT              0x18538067
    31 /* Seek Head Elements */
    32 #define ID_SEEK_HEAD            0x114d9b74
    33 #define ID_SEEK                 0x4dbb
    34 #define ID_SEEK_ID              0x53ab
    35 #define ID_SEEK_POSITION        0x53ac
    37 /* Info Elements */
    38 #define ID_INFO                 0x1549a966
    39 #define ID_TIMECODE_SCALE       0x2ad7b1
    40 #define ID_DURATION             0x4489
    42 /* Cluster Elements */
    43 #define ID_CLUSTER              0x1f43b675
    44 #define ID_TIMECODE             0xe7
    45 #define ID_BLOCK_GROUP          0xa0
    46 #define ID_SIMPLE_BLOCK         0xa3
    48 /* BlockGroup Elements */
    49 #define ID_BLOCK                0xa1
    50 #define ID_BLOCK_DURATION       0x9b
    51 #define ID_REFERENCE_BLOCK      0xfb
    52 #define ID_DISCARD_PADDING      0x75a2
    54 /* Tracks Elements */
    55 #define ID_TRACKS               0x1654ae6b
    56 #define ID_TRACK_ENTRY          0xae
    57 #define ID_TRACK_NUMBER         0xd7
    58 #define ID_TRACK_UID            0x73c5
    59 #define ID_TRACK_TYPE           0x83
    60 #define ID_FLAG_ENABLED         0xb9
    61 #define ID_FLAG_DEFAULT         0x88
    62 #define ID_FLAG_LACING          0x9c
    63 #define ID_TRACK_TIMECODE_SCALE 0x23314f
    64 #define ID_LANGUAGE             0x22b59c
    65 #define ID_CODEC_ID             0x86
    66 #define ID_CODEC_PRIVATE        0x63a2
    67 #define ID_CODEC_DELAY          0x56aa
    68 #define ID_SEEK_PREROLL         0x56bb
    69 #define ID_DEFAULT_DURATION     0x23e383
    71 /* Video Elements */
    72 #define ID_VIDEO                0xe0
    73 #define ID_STEREO_MODE          0x53b8
    74 #define ID_PIXEL_WIDTH          0xb0
    75 #define ID_PIXEL_HEIGHT         0xba
    76 #define ID_PIXEL_CROP_BOTTOM    0x54aa
    77 #define ID_PIXEL_CROP_TOP       0x54bb
    78 #define ID_PIXEL_CROP_LEFT      0x54cc
    79 #define ID_PIXEL_CROP_RIGHT     0x54dd
    80 #define ID_DISPLAY_WIDTH        0x54b0
    81 #define ID_DISPLAY_HEIGHT       0x54ba
    83 /* Audio Elements */
    84 #define ID_AUDIO                0xe1
    85 #define ID_SAMPLING_FREQUENCY   0xb5
    86 #define ID_CHANNELS             0x9f
    87 #define ID_BIT_DEPTH            0x6264
    89 /* Cues Elements */
    90 #define ID_CUES                 0x1c53bb6b
    91 #define ID_CUE_POINT            0xbb
    92 #define ID_CUE_TIME             0xb3
    93 #define ID_CUE_TRACK_POSITIONS  0xb7
    94 #define ID_CUE_TRACK            0xf7
    95 #define ID_CUE_CLUSTER_POSITION 0xf1
    96 #define ID_CUE_BLOCK_NUMBER     0x5378
    98 /* EBML Types */
    99 enum ebml_type_enum {
   100   TYPE_UNKNOWN,
   101   TYPE_MASTER,
   102   TYPE_UINT,
   103   TYPE_FLOAT,
   104   TYPE_INT,
   105   TYPE_STRING,
   106   TYPE_BINARY
   107 };
   109 #define LIMIT_STRING            (1 << 20)
   110 #define LIMIT_BINARY            (1 << 24)
   111 #define LIMIT_BLOCK             (1 << 30)
   112 #define LIMIT_FRAME             (1 << 28)
   114 /* Field Flags */
   115 #define DESC_FLAG_NONE          0
   116 #define DESC_FLAG_MULTI         (1 << 0)
   117 #define DESC_FLAG_SUSPEND       (1 << 1)
   118 #define DESC_FLAG_OFFSET        (1 << 2)
   120 /* Block Header Flags */
   121 #define BLOCK_FLAGS_LACING      6
   123 /* Lacing Constants */
   124 #define LACING_NONE             0
   125 #define LACING_XIPH             1
   126 #define LACING_FIXED            2
   127 #define LACING_EBML             3
   129 /* Track Types */
   130 #define TRACK_TYPE_VIDEO        1
   131 #define TRACK_TYPE_AUDIO        2
   133 /* Track IDs */
   134 #define TRACK_ID_VP8            "V_VP8"
   135 #define TRACK_ID_VP9            "V_VP9"
   136 #define TRACK_ID_VORBIS         "A_VORBIS"
   137 #define TRACK_ID_OPUS           "A_OPUS"
   139 enum vint_mask {
   140   MASK_NONE,
   141   MASK_FIRST_BIT
   142 };
   144 struct ebml_binary {
   145   unsigned char * data;
   146   size_t length;
   147 };
   149 struct ebml_list_node {
   150   struct ebml_list_node * next;
   151   uint64_t id;
   152   void * data;
   153 };
   155 struct ebml_list {
   156   struct ebml_list_node * head;
   157   struct ebml_list_node * tail;
   158 };
   160 struct ebml_type {
   161   union ebml_value {
   162     uint64_t u;
   163     double f;
   164     int64_t i;
   165     char * s;
   166     struct ebml_binary b;
   167   } v;
   168   enum ebml_type_enum type;
   169   int read;
   170 };
   172 /* EBML Definitions */
   173 struct ebml {
   174   struct ebml_type ebml_version;
   175   struct ebml_type ebml_read_version;
   176   struct ebml_type ebml_max_id_length;
   177   struct ebml_type ebml_max_size_length;
   178   struct ebml_type doctype;
   179   struct ebml_type doctype_version;
   180   struct ebml_type doctype_read_version;
   181 };
   183 /* Matroksa Definitions */
   184 struct seek {
   185   struct ebml_type id;
   186   struct ebml_type position;
   187 };
   189 struct seek_head {
   190   struct ebml_list seek;
   191 };
   193 struct info {
   194   struct ebml_type timecode_scale;
   195   struct ebml_type duration;
   196 };
   198 struct block_group {
   199   struct ebml_type duration;
   200   struct ebml_type reference_block;
   201   struct ebml_type discard_padding;
   202 };
   204 struct cluster {
   205   struct ebml_type timecode;
   206   struct ebml_list block_group;
   207 };
   209 struct video {
   210   struct ebml_type stereo_mode;
   211   struct ebml_type pixel_width;
   212   struct ebml_type pixel_height;
   213   struct ebml_type pixel_crop_bottom;
   214   struct ebml_type pixel_crop_top;
   215   struct ebml_type pixel_crop_left;
   216   struct ebml_type pixel_crop_right;
   217   struct ebml_type display_width;
   218   struct ebml_type display_height;
   219 };
   221 struct audio {
   222   struct ebml_type sampling_frequency;
   223   struct ebml_type channels;
   224   struct ebml_type bit_depth;
   225 };
   227 struct track_entry {
   228   struct ebml_type number;
   229   struct ebml_type uid;
   230   struct ebml_type type;
   231   struct ebml_type flag_enabled;
   232   struct ebml_type flag_default;
   233   struct ebml_type flag_lacing;
   234   struct ebml_type track_timecode_scale;
   235   struct ebml_type language;
   236   struct ebml_type codec_id;
   237   struct ebml_type codec_private;
   238   struct ebml_type codec_delay;
   239   struct ebml_type seek_preroll;
   240   struct ebml_type default_duration;
   241   struct video video;
   242   struct audio audio;
   243 };
   245 struct tracks {
   246   struct ebml_list track_entry;
   247 };
   249 struct cue_track_positions {
   250   struct ebml_type track;
   251   struct ebml_type cluster_position;
   252   struct ebml_type block_number;
   253 };
   255 struct cue_point {
   256   struct ebml_type time;
   257   struct ebml_list cue_track_positions;
   258 };
   260 struct cues {
   261   struct ebml_list cue_point;
   262 };
   264 struct segment {
   265   struct ebml_list seek_head;
   266   struct info info;
   267   struct ebml_list cluster;
   268   struct tracks tracks;
   269   struct cues cues;
   270 };
   272 /* Misc. */
   273 struct pool_ctx {
   274   char dummy;
   275 };
   277 struct list_node {
   278   struct list_node * previous;
   279   struct ebml_element_desc * node;
   280   unsigned char * data;
   281 };
   283 struct saved_state {
   284   int64_t stream_offset;
   285   struct list_node * ancestor;
   286   uint64_t last_id;
   287   uint64_t last_size;
   288   int last_valid;
   289 };
   291 struct frame {
   292   unsigned char * data;
   293   size_t length;
   294   struct frame * next;
   295 };
   297 /* Public (opaque) Structures */
   298 struct nestegg {
   299   nestegg_io * io;
   300   nestegg_log log;
   301   struct pool_ctx * alloc_pool;
   302   uint64_t last_id;
   303   uint64_t last_size;
   304   int last_valid;
   305   struct list_node * ancestor;
   306   struct ebml ebml;
   307   struct segment segment;
   308   int64_t segment_offset;
   309   unsigned int track_count;
   310 };
   312 struct nestegg_packet {
   313   uint64_t track;
   314   uint64_t timecode;
   315   uint64_t duration;
   316   struct frame * frame;
   317   int64_t discard_padding;
   318 };
   320 /* Element Descriptor */
   321 struct ebml_element_desc {
   322   char const * name;
   323   uint64_t id;
   324   enum ebml_type_enum type;
   325   size_t offset;
   326   unsigned int flags;
   327   struct ebml_element_desc * children;
   328   size_t size;
   329   size_t data_offset;
   330 };
   332 #define E_FIELD(ID, TYPE, STRUCT, FIELD) \
   333   { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_NONE, NULL, 0, 0 }
   334 #define E_MASTER(ID, TYPE, STRUCT, FIELD) \
   335   { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_MULTI, ne_ ## FIELD ## _elements, \
   336       sizeof(struct FIELD), 0 }
   337 #define E_SINGLE_MASTER_O(ID, TYPE, STRUCT, FIELD) \
   338   { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_OFFSET, ne_ ## FIELD ## _elements, 0, \
   339       offsetof(STRUCT, FIELD ## _offset) }
   340 #define E_SINGLE_MASTER(ID, TYPE, STRUCT, FIELD) \
   341   { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_NONE, ne_ ## FIELD ## _elements, 0, 0 }
   342 #define E_SUSPEND(ID, TYPE) \
   343   { #ID, ID, TYPE, 0, DESC_FLAG_SUSPEND, NULL, 0, 0 }
   344 #define E_LAST \
   345   { NULL, 0, 0, 0, DESC_FLAG_NONE, NULL, 0, 0 }
   347 /* EBML Element Lists */
   348 static struct ebml_element_desc ne_ebml_elements[] = {
   349   E_FIELD(ID_EBML_VERSION, TYPE_UINT, struct ebml, ebml_version),
   350   E_FIELD(ID_EBML_READ_VERSION, TYPE_UINT, struct ebml, ebml_read_version),
   351   E_FIELD(ID_EBML_MAX_ID_LENGTH, TYPE_UINT, struct ebml, ebml_max_id_length),
   352   E_FIELD(ID_EBML_MAX_SIZE_LENGTH, TYPE_UINT, struct ebml, ebml_max_size_length),
   353   E_FIELD(ID_DOCTYPE, TYPE_STRING, struct ebml, doctype),
   354   E_FIELD(ID_DOCTYPE_VERSION, TYPE_UINT, struct ebml, doctype_version),
   355   E_FIELD(ID_DOCTYPE_READ_VERSION, TYPE_UINT, struct ebml, doctype_read_version),
   356   E_LAST
   357 };
   359 /* WebM Element Lists */
   360 static struct ebml_element_desc ne_seek_elements[] = {
   361   E_FIELD(ID_SEEK_ID, TYPE_BINARY, struct seek, id),
   362   E_FIELD(ID_SEEK_POSITION, TYPE_UINT, struct seek, position),
   363   E_LAST
   364 };
   366 static struct ebml_element_desc ne_seek_head_elements[] = {
   367   E_MASTER(ID_SEEK, TYPE_MASTER, struct seek_head, seek),
   368   E_LAST
   369 };
   371 static struct ebml_element_desc ne_info_elements[] = {
   372   E_FIELD(ID_TIMECODE_SCALE, TYPE_UINT, struct info, timecode_scale),
   373   E_FIELD(ID_DURATION, TYPE_FLOAT, struct info, duration),
   374   E_LAST
   375 };
   377 static struct ebml_element_desc ne_block_group_elements[] = {
   378   E_SUSPEND(ID_BLOCK, TYPE_BINARY),
   379   E_FIELD(ID_BLOCK_DURATION, TYPE_UINT, struct block_group, duration),
   380   E_FIELD(ID_REFERENCE_BLOCK, TYPE_INT, struct block_group, reference_block),
   381   E_FIELD(ID_DISCARD_PADDING, TYPE_INT, struct block_group, discard_padding),
   382   E_LAST
   383 };
   385 static struct ebml_element_desc ne_cluster_elements[] = {
   386   E_FIELD(ID_TIMECODE, TYPE_UINT, struct cluster, timecode),
   387   E_MASTER(ID_BLOCK_GROUP, TYPE_MASTER, struct cluster, block_group),
   388   E_SUSPEND(ID_SIMPLE_BLOCK, TYPE_BINARY),
   389   E_LAST
   390 };
   392 static struct ebml_element_desc ne_video_elements[] = {
   393   E_FIELD(ID_STEREO_MODE, TYPE_UINT, struct video, stereo_mode),
   394   E_FIELD(ID_PIXEL_WIDTH, TYPE_UINT, struct video, pixel_width),
   395   E_FIELD(ID_PIXEL_HEIGHT, TYPE_UINT, struct video, pixel_height),
   396   E_FIELD(ID_PIXEL_CROP_BOTTOM, TYPE_UINT, struct video, pixel_crop_bottom),
   397   E_FIELD(ID_PIXEL_CROP_TOP, TYPE_UINT, struct video, pixel_crop_top),
   398   E_FIELD(ID_PIXEL_CROP_LEFT, TYPE_UINT, struct video, pixel_crop_left),
   399   E_FIELD(ID_PIXEL_CROP_RIGHT, TYPE_UINT, struct video, pixel_crop_right),
   400   E_FIELD(ID_DISPLAY_WIDTH, TYPE_UINT, struct video, display_width),
   401   E_FIELD(ID_DISPLAY_HEIGHT, TYPE_UINT, struct video, display_height),
   402   E_LAST
   403 };
   405 static struct ebml_element_desc ne_audio_elements[] = {
   406   E_FIELD(ID_SAMPLING_FREQUENCY, TYPE_FLOAT, struct audio, sampling_frequency),
   407   E_FIELD(ID_CHANNELS, TYPE_UINT, struct audio, channels),
   408   E_FIELD(ID_BIT_DEPTH, TYPE_UINT, struct audio, bit_depth),
   409   E_LAST
   410 };
   412 static struct ebml_element_desc ne_track_entry_elements[] = {
   413   E_FIELD(ID_TRACK_NUMBER, TYPE_UINT, struct track_entry, number),
   414   E_FIELD(ID_TRACK_UID, TYPE_UINT, struct track_entry, uid),
   415   E_FIELD(ID_TRACK_TYPE, TYPE_UINT, struct track_entry, type),
   416   E_FIELD(ID_FLAG_ENABLED, TYPE_UINT, struct track_entry, flag_enabled),
   417   E_FIELD(ID_FLAG_DEFAULT, TYPE_UINT, struct track_entry, flag_default),
   418   E_FIELD(ID_FLAG_LACING, TYPE_UINT, struct track_entry, flag_lacing),
   419   E_FIELD(ID_TRACK_TIMECODE_SCALE, TYPE_FLOAT, struct track_entry, track_timecode_scale),
   420   E_FIELD(ID_LANGUAGE, TYPE_STRING, struct track_entry, language),
   421   E_FIELD(ID_CODEC_ID, TYPE_STRING, struct track_entry, codec_id),
   422   E_FIELD(ID_CODEC_PRIVATE, TYPE_BINARY, struct track_entry, codec_private),
   423   E_FIELD(ID_CODEC_DELAY, TYPE_UINT, struct track_entry, codec_delay),
   424   E_FIELD(ID_SEEK_PREROLL, TYPE_UINT, struct track_entry, seek_preroll),
   425   E_FIELD(ID_DEFAULT_DURATION, TYPE_UINT, struct track_entry, default_duration),
   426   E_SINGLE_MASTER(ID_VIDEO, TYPE_MASTER, struct track_entry, video),
   427   E_SINGLE_MASTER(ID_AUDIO, TYPE_MASTER, struct track_entry, audio),
   428   E_LAST
   429 };
   431 static struct ebml_element_desc ne_tracks_elements[] = {
   432   E_MASTER(ID_TRACK_ENTRY, TYPE_MASTER, struct tracks, track_entry),
   433   E_LAST
   434 };
   436 static struct ebml_element_desc ne_cue_track_positions_elements[] = {
   437   E_FIELD(ID_CUE_TRACK, TYPE_UINT, struct cue_track_positions, track),
   438   E_FIELD(ID_CUE_CLUSTER_POSITION, TYPE_UINT, struct cue_track_positions, cluster_position),
   439   E_FIELD(ID_CUE_BLOCK_NUMBER, TYPE_UINT, struct cue_track_positions, block_number),
   440   E_LAST
   441 };
   443 static struct ebml_element_desc ne_cue_point_elements[] = {
   444   E_FIELD(ID_CUE_TIME, TYPE_UINT, struct cue_point, time),
   445   E_MASTER(ID_CUE_TRACK_POSITIONS, TYPE_MASTER, struct cue_point, cue_track_positions),
   446   E_LAST
   447 };
   449 static struct ebml_element_desc ne_cues_elements[] = {
   450   E_MASTER(ID_CUE_POINT, TYPE_MASTER, struct cues, cue_point),
   451   E_LAST
   452 };
   454 static struct ebml_element_desc ne_segment_elements[] = {
   455   E_MASTER(ID_SEEK_HEAD, TYPE_MASTER, struct segment, seek_head),
   456   E_SINGLE_MASTER(ID_INFO, TYPE_MASTER, struct segment, info),
   457   E_MASTER(ID_CLUSTER, TYPE_MASTER, struct segment, cluster),
   458   E_SINGLE_MASTER(ID_TRACKS, TYPE_MASTER, struct segment, tracks),
   459   E_SINGLE_MASTER(ID_CUES, TYPE_MASTER, struct segment, cues),
   460   E_LAST
   461 };
   463 static struct ebml_element_desc ne_top_level_elements[] = {
   464   E_SINGLE_MASTER(ID_EBML, TYPE_MASTER, nestegg, ebml),
   465   E_SINGLE_MASTER_O(ID_SEGMENT, TYPE_MASTER, nestegg, segment),
   466   E_LAST
   467 };
   469 #undef E_FIELD
   470 #undef E_MASTER
   471 #undef E_SINGLE_MASTER_O
   472 #undef E_SINGLE_MASTER
   473 #undef E_SUSPEND
   474 #undef E_LAST
   476 static struct pool_ctx *
   477 ne_pool_init(void)
   478 {
   479   return h_malloc(sizeof(struct pool_ctx));
   480 }
   482 static void
   483 ne_pool_destroy(struct pool_ctx * pool)
   484 {
   485   h_free(pool);
   486 }
   488 static void *
   489 ne_pool_alloc(size_t size, struct pool_ctx * pool)
   490 {
   491   void * p;
   493   p = h_malloc(size);
   494   if (!p)
   495     return NULL;
   496   hattach(p, pool);
   497   memset(p, 0, size);
   498   return p;
   499 }
   501 static void *
   502 ne_alloc(size_t size)
   503 {
   504   return calloc(1, size);
   505 }
   507 static int
   508 ne_io_read(nestegg_io * io, void * buffer, size_t length)
   509 {
   510   return io->read(buffer, length, io->userdata);
   511 }
   513 static int
   514 ne_io_seek(nestegg_io * io, int64_t offset, int whence)
   515 {
   516   return io->seek(offset, whence, io->userdata);
   517 }
   519 static int
   520 ne_io_read_skip(nestegg_io * io, size_t length)
   521 {
   522   size_t get;
   523   unsigned char buf[8192];
   524   int r = 1;
   526   while (length > 0) {
   527     get = length < sizeof(buf) ? length : sizeof(buf);
   528     r = ne_io_read(io, buf, get);
   529     if (r != 1)
   530       break;
   531     length -= get;
   532   }
   534   return r;
   535 }
   537 static int64_t
   538 ne_io_tell(nestegg_io * io)
   539 {
   540   return io->tell(io->userdata);
   541 }
   543 static int
   544 ne_bare_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length, enum vint_mask maskflag)
   545 {
   546   int r;
   547   unsigned char b;
   548   size_t maxlen = 8;
   549   unsigned int count = 1, mask = 1 << 7;
   551   r = ne_io_read(io, &b, 1);
   552   if (r != 1)
   553     return r;
   555   while (count < maxlen) {
   556     if ((b & mask) != 0)
   557       break;
   558     mask >>= 1;
   559     count += 1;
   560   }
   562   if (length)
   563     *length = count;
   564   *value = b;
   566   if (maskflag == MASK_FIRST_BIT)
   567     *value = b & ~mask;
   569   while (--count) {
   570     r = ne_io_read(io, &b, 1);
   571     if (r != 1)
   572       return r;
   573     *value <<= 8;
   574     *value |= b;
   575   }
   577   return 1;
   578 }
   580 static int
   581 ne_read_id(nestegg_io * io, uint64_t * value, uint64_t * length)
   582 {
   583   return ne_bare_read_vint(io, value, length, MASK_NONE);
   584 }
   586 static int
   587 ne_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length)
   588 {
   589   return ne_bare_read_vint(io, value, length, MASK_FIRST_BIT);
   590 }
   592 static int
   593 ne_read_svint(nestegg_io * io, int64_t * value, uint64_t * length)
   594 {
   595   int r;
   596   uint64_t uvalue;
   597   uint64_t ulength;
   598   int64_t svint_subtr[] = {
   599     0x3f, 0x1fff,
   600     0xfffff, 0x7ffffff,
   601     0x3ffffffffLL, 0x1ffffffffffLL,
   602     0xffffffffffffLL, 0x7fffffffffffffLL
   603   };
   605   r = ne_bare_read_vint(io, &uvalue, &ulength, MASK_FIRST_BIT);
   606   if (r != 1)
   607     return r;
   608   *value = uvalue - svint_subtr[ulength - 1];
   609   if (length)
   610     *length = ulength;
   611   return r;
   612 }
   614 static int
   615 ne_read_uint(nestegg_io * io, uint64_t * val, uint64_t length)
   616 {
   617   unsigned char b;
   618   int r;
   620   if (length == 0 || length > 8)
   621     return -1;
   622   r = ne_io_read(io, &b, 1);
   623   if (r != 1)
   624     return r;
   625   *val = b;
   626   while (--length) {
   627     r = ne_io_read(io, &b, 1);
   628     if (r != 1)
   629       return r;
   630     *val <<= 8;
   631     *val |= b;
   632   }
   633   return 1;
   634 }
   636 static int
   637 ne_read_int(nestegg_io * io, int64_t * val, uint64_t length)
   638 {
   639   int r;
   640   uint64_t uval, base;
   642   r = ne_read_uint(io, &uval, length);
   643   if (r != 1)
   644     return r;
   646   if (length < sizeof(int64_t)) {
   647     base = 1;
   648     base <<= length * 8 - 1;
   649     if (uval >= base) {
   650         base = 1;
   651         base <<= length * 8;
   652     } else {
   653       base = 0;
   654     }
   655     *val = uval - base;
   656   } else {
   657     *val = (int64_t) uval;
   658   }
   660   return 1;
   661 }
   663 static int
   664 ne_read_float(nestegg_io * io, double * val, uint64_t length)
   665 {
   666   union {
   667     uint64_t u;
   668     float f;
   669     double d;
   670   } value;
   671   int r;
   673   /* Length == 10 not implemented. */
   674   if (length != 4 && length != 8)
   675     return -1;
   676   r = ne_read_uint(io, &value.u, length);
   677   if (r != 1)
   678     return r;
   679   if (length == 4)
   680     *val = value.f;
   681   else
   682     *val = value.d;
   683   return 1;
   684 }
   686 static int
   687 ne_read_string(nestegg * ctx, char ** val, uint64_t length)
   688 {
   689   char * str;
   690   int r;
   692   if (length == 0 || length > LIMIT_STRING)
   693     return -1;
   694   str = ne_pool_alloc(length + 1, ctx->alloc_pool);
   695   if (!str)
   696     return -1;
   697   r = ne_io_read(ctx->io, (unsigned char *) str, length);
   698   if (r != 1)
   699     return r;
   700   str[length] = '\0';
   701   *val = str;
   702   return 1;
   703 }
   705 static int
   706 ne_read_binary(nestegg * ctx, struct ebml_binary * val, uint64_t length)
   707 {
   708   if (length == 0 || length > LIMIT_BINARY)
   709     return -1;
   710   val->data = ne_pool_alloc(length, ctx->alloc_pool);
   711   if (!val->data)
   712     return -1;
   713   val->length = length;
   714   return ne_io_read(ctx->io, val->data, length);
   715 }
   717 static int
   718 ne_get_uint(struct ebml_type type, uint64_t * value)
   719 {
   720   if (!type.read)
   721     return -1;
   723   assert(type.type == TYPE_UINT);
   725   *value = type.v.u;
   727   return 0;
   728 }
   730 static int
   731 ne_get_float(struct ebml_type type, double * value)
   732 {
   733   if (!type.read)
   734     return -1;
   736   assert(type.type == TYPE_FLOAT);
   738   *value = type.v.f;
   740   return 0;
   741 }
   743 static int
   744 ne_get_string(struct ebml_type type, char ** value)
   745 {
   746   if (!type.read)
   747     return -1;
   749   assert(type.type == TYPE_STRING);
   751   *value = type.v.s;
   753   return 0;
   754 }
   756 static int
   757 ne_get_binary(struct ebml_type type, struct ebml_binary * value)
   758 {
   759   if (!type.read)
   760     return -1;
   762   assert(type.type == TYPE_BINARY);
   764   *value = type.v.b;
   766   return 0;
   767 }
   769 static int
   770 ne_is_ancestor_element(uint64_t id, struct list_node * ancestor)
   771 {
   772   struct ebml_element_desc * element;
   774   for (; ancestor; ancestor = ancestor->previous)
   775     for (element = ancestor->node; element->id; ++element)
   776       if (element->id == id)
   777         return 1;
   779   return 0;
   780 }
   782 static struct ebml_element_desc *
   783 ne_find_element(uint64_t id, struct ebml_element_desc * elements)
   784 {
   785   struct ebml_element_desc * element;
   787   for (element = elements; element->id; ++element)
   788     if (element->id == id)
   789       return element;
   791   return NULL;
   792 }
   794 static int
   795 ne_ctx_push(nestegg * ctx, struct ebml_element_desc * ancestor, void * data)
   796 {
   797   struct list_node * item;
   799   item = ne_alloc(sizeof(*item));
   800   if (!item)
   801     return -1;
   802   item->previous = ctx->ancestor;
   803   item->node = ancestor;
   804   item->data = data;
   805   ctx->ancestor = item;
   806   return 0;
   807 }
   809 static void
   810 ne_ctx_pop(nestegg * ctx)
   811 {
   812   struct list_node * item;
   814   item = ctx->ancestor;
   815   ctx->ancestor = item->previous;
   816   free(item);
   817 }
   819 static int
   820 ne_ctx_save(nestegg * ctx, struct saved_state * s)
   821 {
   822   s->stream_offset = ne_io_tell(ctx->io);
   823   if (s->stream_offset < 0)
   824     return -1;
   825   s->ancestor = ctx->ancestor;
   826   s->last_id = ctx->last_id;
   827   s->last_size = ctx->last_size;
   828   s->last_valid = ctx->last_valid;
   829   return 0;
   830 }
   832 static int
   833 ne_ctx_restore(nestegg * ctx, struct saved_state * s)
   834 {
   835   int r;
   837   r = ne_io_seek(ctx->io, s->stream_offset, NESTEGG_SEEK_SET);
   838   if (r != 0)
   839     return -1;
   840   ctx->ancestor = s->ancestor;
   841   ctx->last_id = s->last_id;
   842   ctx->last_size = s->last_size;
   843   ctx->last_valid = s->last_valid;
   844   return 0;
   845 }
   847 static int
   848 ne_peek_element(nestegg * ctx, uint64_t * id, uint64_t * size)
   849 {
   850   int r;
   852   if (ctx->last_valid) {
   853     if (id)
   854       *id = ctx->last_id;
   855     if (size)
   856       *size = ctx->last_size;
   857     return 1;
   858   }
   860   r = ne_read_id(ctx->io, &ctx->last_id, NULL);
   861   if (r != 1)
   862     return r;
   864   r = ne_read_vint(ctx->io, &ctx->last_size, NULL);
   865   if (r != 1)
   866     return r;
   868   if (id)
   869     *id = ctx->last_id;
   870   if (size)
   871     *size = ctx->last_size;
   873   ctx->last_valid = 1;
   875   return 1;
   876 }
   878 static int
   879 ne_read_element(nestegg * ctx, uint64_t * id, uint64_t * size)
   880 {
   881   int r;
   883   r = ne_peek_element(ctx, id, size);
   884   if (r != 1)
   885     return r;
   887   ctx->last_valid = 0;
   889   return 1;
   890 }
   892 static int
   893 ne_read_master(nestegg * ctx, struct ebml_element_desc * desc)
   894 {
   895   struct ebml_list * list;
   896   struct ebml_list_node * node, * oldtail;
   898   assert(desc->type == TYPE_MASTER && desc->flags & DESC_FLAG_MULTI);
   900   ctx->log(ctx, NESTEGG_LOG_DEBUG, "multi master element %llx (%s)",
   901            desc->id, desc->name);
   903   list = (struct ebml_list *) (ctx->ancestor->data + desc->offset);
   905   node = ne_pool_alloc(sizeof(*node), ctx->alloc_pool);
   906   if (!node)
   907     return -1;
   908   node->id = desc->id;
   909   node->data = ne_pool_alloc(desc->size, ctx->alloc_pool);
   910   if (!node->data)
   911     return -1;
   913   oldtail = list->tail;
   914   if (oldtail)
   915     oldtail->next = node;
   916   list->tail = node;
   917   if (!list->head)
   918     list->head = node;
   920   ctx->log(ctx, NESTEGG_LOG_DEBUG, " -> using data %p", node->data);
   922   if (ne_ctx_push(ctx, desc->children, node->data) < 0)
   923     return -1;
   925   return 0;
   926 }
   928 static int
   929 ne_read_single_master(nestegg * ctx, struct ebml_element_desc * desc)
   930 {
   931   assert(desc->type == TYPE_MASTER && !(desc->flags & DESC_FLAG_MULTI));
   933   ctx->log(ctx, NESTEGG_LOG_DEBUG, "single master element %llx (%s)",
   934            desc->id, desc->name);
   935   ctx->log(ctx, NESTEGG_LOG_DEBUG, " -> using data %p (%u)",
   936            ctx->ancestor->data + desc->offset, desc->offset);
   938   return ne_ctx_push(ctx, desc->children, ctx->ancestor->data + desc->offset);
   939 }
   941 static int
   942 ne_read_simple(nestegg * ctx, struct ebml_element_desc * desc, size_t length)
   943 {
   944   struct ebml_type * storage;
   945   int r;
   947   storage = (struct ebml_type *) (ctx->ancestor->data + desc->offset);
   949   if (storage->read) {
   950     ctx->log(ctx, NESTEGG_LOG_DEBUG, "element %llx (%s) already read, skipping",
   951              desc->id, desc->name);
   952     return 0;
   953   }
   955   storage->type = desc->type;
   957   ctx->log(ctx, NESTEGG_LOG_DEBUG, "element %llx (%s) -> %p (%u)",
   958            desc->id, desc->name, storage, desc->offset);
   960   switch (desc->type) {
   961   case TYPE_UINT:
   962     r = ne_read_uint(ctx->io, &storage->v.u, length);
   963     break;
   964   case TYPE_FLOAT:
   965     r = ne_read_float(ctx->io, &storage->v.f, length);
   966     break;
   967   case TYPE_INT:
   968     r = ne_read_int(ctx->io, &storage->v.i, length);
   969     break;
   970   case TYPE_STRING:
   971     r = ne_read_string(ctx, &storage->v.s, length);
   972     break;
   973   case TYPE_BINARY:
   974     r = ne_read_binary(ctx, &storage->v.b, length);
   975     break;
   976   case TYPE_MASTER:
   977   case TYPE_UNKNOWN:
   978     assert(0);
   979     r = 0;
   980     break;
   981   }
   983   if (r == 1)
   984     storage->read = 1;
   986   return r;
   987 }
   989 static int
   990 ne_parse(nestegg * ctx, struct ebml_element_desc * top_level, int64_t max_offset)
   991 {
   992   int r;
   993   int64_t * data_offset;
   994   uint64_t id, size, peeked_id;
   995   struct ebml_element_desc * element;
   997   if (!ctx->ancestor)
   998     return -1;
  1000   for (;;) {
  1001     if (max_offset > 0 && ne_io_tell(ctx->io) >= max_offset) {
  1002       /* Reached end of offset allowed for parsing - return gracefully */
  1003       r = 1;
  1004       break;
  1006     r = ne_peek_element(ctx, &id, &size);
  1007     if (r != 1)
  1008       break;
  1009     peeked_id = id;
  1011     element = ne_find_element(id, ctx->ancestor->node);
  1012     if (element) {
  1013       if (element->flags & DESC_FLAG_SUSPEND) {
  1014         assert(element->type == TYPE_BINARY);
  1015         ctx->log(ctx, NESTEGG_LOG_DEBUG, "suspend parse at %llx", id);
  1016         r = 1;
  1017         break;
  1020       r = ne_read_element(ctx, &id, &size);
  1021       if (r != 1)
  1022         break;
  1023       assert(id == peeked_id);
  1025       if (element->flags & DESC_FLAG_OFFSET) {
  1026         data_offset = (int64_t *) (ctx->ancestor->data + element->data_offset);
  1027         *data_offset = ne_io_tell(ctx->io);
  1028         if (*data_offset < 0) {
  1029           r = -1;
  1030           break;
  1034       if (element->type == TYPE_MASTER) {
  1035         if (element->flags & DESC_FLAG_MULTI) {
  1036           if (ne_read_master(ctx, element) < 0)
  1037             break;
  1038         } else {
  1039           if (ne_read_single_master(ctx, element) < 0)
  1040             break;
  1042         continue;
  1043       } else {
  1044         r = ne_read_simple(ctx, element, size);
  1045         if (r < 0)
  1046           break;
  1048     } else if (ne_is_ancestor_element(id, ctx->ancestor->previous)) {
  1049       ctx->log(ctx, NESTEGG_LOG_DEBUG, "parent element %llx", id);
  1050       if (top_level && ctx->ancestor->node == top_level) {
  1051         ctx->log(ctx, NESTEGG_LOG_DEBUG, "*** parse about to back up past top_level");
  1052         r = 1;
  1053         break;
  1055       ne_ctx_pop(ctx);
  1056     } else {
  1057       r = ne_read_element(ctx, &id, &size);
  1058       if (r != 1)
  1059         break;
  1061       if (id != ID_VOID && id != ID_CRC32)
  1062         ctx->log(ctx, NESTEGG_LOG_DEBUG, "unknown element %llx", id);
  1063       r = ne_io_read_skip(ctx->io, size);
  1064       if (r != 1)
  1065         break;
  1069   if (r != 1)
  1070     while (ctx->ancestor)
  1071       ne_ctx_pop(ctx);
  1073   return r;
  1076 static uint64_t
  1077 ne_xiph_lace_value(unsigned char ** np)
  1079   uint64_t lace;
  1080   uint64_t value;
  1081   unsigned char * p = *np;
  1083   lace = *p++;
  1084   value = lace;
  1085   while (lace == 255) {
  1086     lace = *p++;
  1087     value += lace;
  1090   *np = p;
  1092   return value;
  1095 static int
  1096 ne_read_xiph_lace_value(nestegg_io * io, uint64_t * value, size_t * consumed)
  1098   int r;
  1099   uint64_t lace;
  1101   r = ne_read_uint(io, &lace, 1);
  1102   if (r != 1)
  1103     return r;
  1104   *consumed += 1;
  1106   *value = lace;
  1107   while (lace == 255) {
  1108     r = ne_read_uint(io, &lace, 1);
  1109     if (r != 1)
  1110       return r;
  1111     *consumed += 1;
  1112     *value += lace;
  1115   return 1;
  1118 static int
  1119 ne_read_xiph_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
  1121   int r;
  1122   size_t i = 0;
  1123   uint64_t sum = 0;
  1125   while (--n) {
  1126     r = ne_read_xiph_lace_value(io, &sizes[i], read);
  1127     if (r != 1)
  1128       return r;
  1129     sum += sizes[i];
  1130     i += 1;
  1133   if (*read + sum > block)
  1134     return -1;
  1136   /* Last frame is the remainder of the block. */
  1137   sizes[i] = block - *read - sum;
  1138   return 1;
  1141 static int
  1142 ne_read_ebml_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
  1144   int r;
  1145   uint64_t lace, sum, length;
  1146   int64_t slace;
  1147   size_t i = 0;
  1149   r = ne_read_vint(io, &lace, &length);
  1150   if (r != 1)
  1151     return r;
  1152   *read += length;
  1154   sizes[i] = lace;
  1155   sum = sizes[i];
  1157   i += 1;
  1158   n -= 1;
  1160   while (--n) {
  1161     r = ne_read_svint(io, &slace, &length);
  1162     if (r != 1)
  1163       return r;
  1164     *read += length;
  1165     sizes[i] = sizes[i - 1] + slace;
  1166     sum += sizes[i];
  1167     i += 1;
  1170   if (*read + sum > block)
  1171     return -1;
  1173   /* Last frame is the remainder of the block. */
  1174   sizes[i] = block - *read - sum;
  1175   return 1;
  1178 static uint64_t
  1179 ne_get_timecode_scale(nestegg * ctx)
  1181   uint64_t scale;
  1183   if (ne_get_uint(ctx->segment.info.timecode_scale, &scale) != 0)
  1184     scale = 1000000;
  1186   return scale;
  1189 static int
  1190 ne_map_track_number_to_index(nestegg * ctx,
  1191                              unsigned int track_number,
  1192                              unsigned int * track_index)
  1194   struct ebml_list_node * node;
  1195   struct track_entry * t_entry;
  1196   uint64_t t_number = 0;
  1198   if (!track_index)
  1199     return -1;
  1200   *track_index = 0;
  1202   if (track_number == 0)
  1203     return -1;
  1205   node = ctx->segment.tracks.track_entry.head;
  1206   while (node) {
  1207     assert(node->id == ID_TRACK_ENTRY);
  1208     t_entry = node->data;
  1209     if (ne_get_uint(t_entry->number, &t_number) != 0)
  1210       return -1;
  1211     if (t_number == track_number)
  1212       return 0;
  1213     *track_index += 1;
  1214     node = node->next;
  1217   return -1;
  1220 static struct track_entry *
  1221 ne_find_track_entry(nestegg * ctx, unsigned int track)
  1223   struct ebml_list_node * node;
  1224   unsigned int tracks = 0;
  1226   node = ctx->segment.tracks.track_entry.head;
  1227   while (node) {
  1228     assert(node->id == ID_TRACK_ENTRY);
  1229     if (track == tracks)
  1230       return node->data;
  1231     tracks += 1;
  1232     node = node->next;
  1235   return NULL;
  1238 static int
  1239 ne_read_block(nestegg * ctx, uint64_t block_id, uint64_t block_size, nestegg_packet ** data)
  1241   int r;
  1242   int64_t timecode, abs_timecode;
  1243   nestegg_packet * pkt;
  1244   struct cluster * cluster;
  1245   struct frame * f, * last;
  1246   struct track_entry * entry;
  1247   double track_scale;
  1248   uint64_t track_number, length, frame_sizes[256], cluster_tc, flags, frames, tc_scale, total;
  1249   unsigned int i, lacing, track;
  1250   size_t consumed = 0;
  1252   *data = NULL;
  1254   if (block_size > LIMIT_BLOCK)
  1255     return -1;
  1257   r = ne_read_vint(ctx->io, &track_number, &length);
  1258   if (r != 1)
  1259     return r;
  1261   if (track_number == 0)
  1262     return -1;
  1264   consumed += length;
  1266   r = ne_read_int(ctx->io, &timecode, 2);
  1267   if (r != 1)
  1268     return r;
  1270   consumed += 2;
  1272   r = ne_read_uint(ctx->io, &flags, 1);
  1273   if (r != 1)
  1274     return r;
  1276   consumed += 1;
  1278   frames = 0;
  1280   /* Flags are different between Block and SimpleBlock, but lacing is
  1281      encoded the same way. */
  1282   lacing = (flags & BLOCK_FLAGS_LACING) >> 1;
  1284   switch (lacing) {
  1285   case LACING_NONE:
  1286     frames = 1;
  1287     break;
  1288   case LACING_XIPH:
  1289   case LACING_FIXED:
  1290   case LACING_EBML:
  1291     r = ne_read_uint(ctx->io, &frames, 1);
  1292     if (r != 1)
  1293       return r;
  1294     consumed += 1;
  1295     frames += 1;
  1298   if (frames > 256)
  1299     return -1;
  1301   switch (lacing) {
  1302   case LACING_NONE:
  1303     frame_sizes[0] = block_size - consumed;
  1304     break;
  1305   case LACING_XIPH:
  1306     if (frames == 1)
  1307       return -1;
  1308     r = ne_read_xiph_lacing(ctx->io, block_size, &consumed, frames, frame_sizes);
  1309     if (r != 1)
  1310       return r;
  1311     break;
  1312   case LACING_FIXED:
  1313     if ((block_size - consumed) % frames)
  1314       return -1;
  1315     for (i = 0; i < frames; ++i)
  1316       frame_sizes[i] = (block_size - consumed) / frames;
  1317     break;
  1318   case LACING_EBML:
  1319     if (frames == 1)
  1320       return -1;
  1321     r = ne_read_ebml_lacing(ctx->io, block_size, &consumed, frames, frame_sizes);
  1322     if (r != 1)
  1323       return r;
  1324     break;
  1327   /* Sanity check unlaced frame sizes against total block size. */
  1328   total = consumed;
  1329   for (i = 0; i < frames; ++i)
  1330     total += frame_sizes[i];
  1331   if (total > block_size)
  1332     return -1;
  1334   if (ne_map_track_number_to_index(ctx, track_number, &track) != 0)
  1335     return -1;
  1337   entry = ne_find_track_entry(ctx, track);
  1338   if (!entry)
  1339     return -1;
  1341   track_scale = 1.0;
  1343   tc_scale = ne_get_timecode_scale(ctx);
  1345   assert(ctx->segment.cluster.tail->id == ID_CLUSTER);
  1346   cluster = ctx->segment.cluster.tail->data;
  1347   if (ne_get_uint(cluster->timecode, &cluster_tc) != 0)
  1348     return -1;
  1350   abs_timecode = timecode + cluster_tc;
  1351   if (abs_timecode < 0)
  1352     return -1;
  1354   pkt = ne_alloc(sizeof(*pkt));
  1355   if (!pkt)
  1356     return -1;
  1357   pkt->track = track;
  1358   pkt->timecode = abs_timecode * tc_scale * track_scale;
  1360   ctx->log(ctx, NESTEGG_LOG_DEBUG, "%sblock t %lld pts %f f %llx frames: %llu",
  1361            block_id == ID_BLOCK ? "" : "simple", pkt->track, pkt->timecode / 1e9, flags, frames);
  1363   last = NULL;
  1364   for (i = 0; i < frames; ++i) {
  1365     if (frame_sizes[i] > LIMIT_FRAME) {
  1366       nestegg_free_packet(pkt);
  1367       return -1;
  1369     f = ne_alloc(sizeof(*f));
  1370     if (!f) {
  1371       nestegg_free_packet(pkt);
  1372       return -1;
  1374     f->data = ne_alloc(frame_sizes[i]);
  1375     if (!f->data) {
  1376       free(f);
  1377       nestegg_free_packet(pkt);
  1378       return -1;
  1380     f->length = frame_sizes[i];
  1381     r = ne_io_read(ctx->io, f->data, frame_sizes[i]);
  1382     if (r != 1) {
  1383       free(f->data);
  1384       free(f);
  1385       nestegg_free_packet(pkt);
  1386       return -1;
  1389     if (!last)
  1390       pkt->frame = f;
  1391     else
  1392       last->next = f;
  1393     last = f;
  1396   *data = pkt;
  1398   return 1;
  1401 static int
  1402 ne_read_block_duration(nestegg * ctx, nestegg_packet * pkt)
  1404   int r;
  1405   uint64_t id, size;
  1406   struct ebml_element_desc * element;
  1407   struct ebml_type * storage;
  1409   r = ne_peek_element(ctx, &id, &size);
  1410   if (r != 1)
  1411     return r;
  1413   if (id != ID_BLOCK_DURATION)
  1414     return 1;
  1416   element = ne_find_element(id, ctx->ancestor->node);
  1417   if (!element)
  1418     return 1;
  1420   r = ne_read_simple(ctx, element, size);
  1421   if (r != 1)
  1422     return r;
  1423   storage = (struct ebml_type *) (ctx->ancestor->data + element->offset);
  1424   pkt->duration = storage->v.i * ne_get_timecode_scale(ctx);
  1426   return 1;
  1429 static int
  1430 ne_read_discard_padding(nestegg * ctx, nestegg_packet * pkt)
  1432   int r;
  1433   uint64_t id, size;
  1434   struct ebml_element_desc * element;
  1435   struct ebml_type * storage;
  1437   r = ne_peek_element(ctx, &id, &size);
  1438   if (r != 1)
  1439     return r;
  1441   if (id != ID_DISCARD_PADDING)
  1442     return 1;
  1444   element = ne_find_element(id, ctx->ancestor->node);
  1445   if (!element)
  1446     return 1;
  1448   r = ne_read_simple(ctx, element, size);
  1449   if (r != 1)
  1450     return r;
  1451   storage = (struct ebml_type *) (ctx->ancestor->data + element->offset);
  1452   pkt->discard_padding = storage->v.i;
  1454   return 1;
  1458 static uint64_t
  1459 ne_buf_read_id(unsigned char const * p, size_t length)
  1461   uint64_t id = 0;
  1463   while (length--) {
  1464     id <<= 8;
  1465     id |= *p++;
  1468   return id;
  1471 static struct seek *
  1472 ne_find_seek_for_id(struct ebml_list_node * seek_head, uint64_t id)
  1474   struct ebml_list * head;
  1475   struct ebml_list_node * seek;
  1476   struct ebml_binary binary_id;
  1477   struct seek * s;
  1479   while (seek_head) {
  1480     assert(seek_head->id == ID_SEEK_HEAD);
  1481     head = seek_head->data;
  1482     seek = head->head;
  1484     while (seek) {
  1485       assert(seek->id == ID_SEEK);
  1486       s = seek->data;
  1488       if (ne_get_binary(s->id, &binary_id) == 0 &&
  1489           ne_buf_read_id(binary_id.data, binary_id.length) == id)
  1490         return s;
  1492       seek = seek->next;
  1495     seek_head = seek_head->next;
  1498   return NULL;
  1501 static struct cue_track_positions *
  1502 ne_find_cue_position_for_track(nestegg * ctx, struct ebml_list_node * node, unsigned int track)
  1504   struct cue_track_positions * pos = NULL;
  1505   uint64_t track_number;
  1506   unsigned int t;
  1508   while (node) {
  1509     assert(node->id == ID_CUE_TRACK_POSITIONS);
  1510     pos = node->data;
  1511     if (ne_get_uint(pos->track, &track_number) != 0)
  1512       return NULL;
  1514     if (ne_map_track_number_to_index(ctx, track_number, &t) != 0)
  1515       return NULL;
  1517     if (t == track)
  1518       return pos;
  1520     node = node->next;
  1523   return NULL;
  1526 static struct cue_point *
  1527 ne_find_cue_point_for_tstamp(nestegg * ctx, struct ebml_list_node * cue_point, unsigned int track, uint64_t scale, uint64_t tstamp)
  1529   uint64_t time;
  1530   struct cue_point * c, * prev = NULL;
  1532   while (cue_point) {
  1533     assert(cue_point->id == ID_CUE_POINT);
  1534     c = cue_point->data;
  1536     if (!prev)
  1537       prev = c;
  1539     if (ne_get_uint(c->time, &time) == 0 && time * scale > tstamp)
  1540       break;
  1542     if (ne_find_cue_position_for_track(ctx, c->cue_track_positions.head, track) != NULL)
  1543       prev = c;
  1545     cue_point = cue_point->next;
  1548   return prev;
  1551 static int
  1552 ne_is_suspend_element(uint64_t id)
  1554   if (id == ID_SIMPLE_BLOCK || id == ID_BLOCK)
  1555     return 1;
  1556   return 0;
  1559 static void
  1560 ne_null_log_callback(nestegg * ctx, unsigned int severity, char const * fmt, ...)
  1562   if (ctx && severity && fmt)
  1563     return;
  1566 static int
  1567 ne_init_cue_points(nestegg * ctx, int64_t max_offset)
  1569   int r;
  1570   struct ebml_list_node * node = ctx->segment.cues.cue_point.head;
  1571   struct seek * found;
  1572   uint64_t seek_pos, id;
  1573   struct saved_state state;
  1575   /* If there are no cues loaded, check for cues element in the seek head
  1576      and load it. */
  1577   if (!node) {
  1578     found = ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES);
  1579     if (!found)
  1580       return -1;
  1582     if (ne_get_uint(found->position, &seek_pos) != 0)
  1583       return -1;
  1585     /* Save old parser state. */
  1586     r = ne_ctx_save(ctx, &state);
  1587     if (r != 0)
  1588       return -1;
  1590     /* Seek and set up parser state for segment-level element (Cues). */
  1591     r = ne_io_seek(ctx->io, ctx->segment_offset + seek_pos, NESTEGG_SEEK_SET);
  1592     if (r != 0)
  1593       return -1;
  1594     ctx->last_valid = 0;
  1596     r = ne_read_element(ctx, &id, NULL);
  1597     if (r != 1)
  1598       return -1;
  1600     if (id != ID_CUES)
  1601       return -1;
  1603     ctx->ancestor = NULL;
  1604     if (ne_ctx_push(ctx, ne_top_level_elements, ctx) < 0)
  1605       return -1;
  1606     if (ne_ctx_push(ctx, ne_segment_elements, &ctx->segment) < 0)
  1607       return -1;
  1608     if (ne_ctx_push(ctx, ne_cues_elements, &ctx->segment.cues) < 0)
  1609       return -1;
  1610     /* parser will run until end of cues element. */
  1611     ctx->log(ctx, NESTEGG_LOG_DEBUG, "seek: parsing cue elements");
  1612     r = ne_parse(ctx, ne_cues_elements, max_offset);
  1613     while (ctx->ancestor)
  1614       ne_ctx_pop(ctx);
  1616     /* Reset parser state to original state and seek back to old position. */
  1617     if (ne_ctx_restore(ctx, &state) != 0)
  1618       return -1;
  1620     if (r < 0)
  1621       return -1;
  1623     node = ctx->segment.cues.cue_point.head;
  1624     if (!node)
  1625       return -1;
  1628   return 0;
  1631 /* Three functions that implement the nestegg_io interface, operating on a
  1632  * sniff_buffer. */
  1633 struct sniff_buffer {
  1634   unsigned char const * buffer;
  1635   size_t length;
  1636   int64_t offset;
  1637 };
  1639 static int
  1640 ne_buffer_read(void * buffer, size_t length, void * user_data)
  1642   struct sniff_buffer * sb = user_data;
  1644   int rv = 1;
  1645   size_t available = sb->length - sb->offset;
  1647   if (available < length)
  1648     return 0;
  1650   memcpy(buffer, sb->buffer + sb->offset, length);
  1651   sb->offset += length;
  1653   return rv;
  1656 static int
  1657 ne_buffer_seek(int64_t offset, int whence, void * user_data)
  1659   struct sniff_buffer * sb = user_data;
  1660   int64_t o = sb->offset;
  1662   switch(whence) {
  1663     case NESTEGG_SEEK_SET:
  1664       o = offset;
  1665       break;
  1666     case NESTEGG_SEEK_CUR:
  1667       o += offset;
  1668       break;
  1669     case NESTEGG_SEEK_END:
  1670       o = sb->length + offset;
  1671       break;
  1674   if (o < 0 || o > (int64_t) sb->length)
  1675     return -1;
  1677   sb->offset = o;
  1678   return 0;
  1681 static int64_t
  1682 ne_buffer_tell(void * user_data)
  1684   struct sniff_buffer * sb = user_data;
  1685   return sb->offset;
  1688 static int
  1689 ne_match_webm(nestegg_io io, int64_t max_offset)
  1691   int r;
  1692   uint64_t id;
  1693   char * doctype;
  1694   nestegg * ctx;
  1696   if (!(io.read && io.seek && io.tell))
  1697     return -1;
  1699   ctx = ne_alloc(sizeof(*ctx));
  1700   if (!ctx)
  1701     return -1;
  1703   ctx->io = ne_alloc(sizeof(*ctx->io));
  1704   if (!ctx->io) {
  1705     nestegg_destroy(ctx);
  1706     return -1;
  1708   *ctx->io = io;
  1709   ctx->alloc_pool = ne_pool_init();
  1710   if (!ctx->alloc_pool) {
  1711     nestegg_destroy(ctx);
  1712     return -1;
  1714   ctx->log = ne_null_log_callback;
  1716   r = ne_peek_element(ctx, &id, NULL);
  1717   if (r != 1) {
  1718     nestegg_destroy(ctx);
  1719     return 0;
  1722   if (id != ID_EBML) {
  1723     nestegg_destroy(ctx);
  1724     return 0;
  1727   ne_ctx_push(ctx, ne_top_level_elements, ctx);
  1729   /* we don't check the return value of ne_parse, that might fail because
  1730    * max_offset is not on a valid element end point. We only want to check
  1731    * the EBML ID and that the doctype is "webm". */
  1732   ne_parse(ctx, NULL, max_offset);
  1734   if (ne_get_string(ctx->ebml.doctype, &doctype) != 0 ||
  1735       strcmp(doctype, "webm") != 0) {
  1736     nestegg_destroy(ctx);
  1737     return 0;
  1740   nestegg_destroy(ctx);
  1742   return 1;
  1745 int
  1746 nestegg_init(nestegg ** context, nestegg_io io, nestegg_log callback, int64_t max_offset)
  1748   int r;
  1749   uint64_t id, version, docversion;
  1750   struct ebml_list_node * track;
  1751   char * doctype;
  1752   nestegg * ctx;
  1754   if (!(io.read && io.seek && io.tell))
  1755     return -1;
  1757   ctx = ne_alloc(sizeof(*ctx));
  1758   if (!ctx)
  1759     return -1;
  1761   ctx->io = ne_alloc(sizeof(*ctx->io));
  1762   if (!ctx->io) {
  1763     nestegg_destroy(ctx);
  1764     return -1;
  1766   *ctx->io = io;
  1767   ctx->log = callback;
  1768   ctx->alloc_pool = ne_pool_init();
  1769   if (!ctx->alloc_pool) {
  1770     nestegg_destroy(ctx);
  1771     return -1;
  1774   if (!ctx->log)
  1775     ctx->log = ne_null_log_callback;
  1777   r = ne_peek_element(ctx, &id, NULL);
  1778   if (r != 1) {
  1779     nestegg_destroy(ctx);
  1780     return -1;
  1783   if (id != ID_EBML) {
  1784     nestegg_destroy(ctx);
  1785     return -1;
  1788   ctx->log(ctx, NESTEGG_LOG_DEBUG, "ctx %p", ctx);
  1790   ne_ctx_push(ctx, ne_top_level_elements, ctx);
  1792   r = ne_parse(ctx, NULL, max_offset);
  1794   if (r != 1) {
  1795     nestegg_destroy(ctx);
  1796     return -1;
  1799   if (ne_get_uint(ctx->ebml.ebml_read_version, &version) != 0)
  1800     version = 1;
  1801   if (version != 1) {
  1802     nestegg_destroy(ctx);
  1803     return -1;
  1806   if (ne_get_string(ctx->ebml.doctype, &doctype) != 0)
  1807     doctype = "matroska";
  1808   if (strcmp(doctype, "webm") != 0) {
  1809     nestegg_destroy(ctx);
  1810     return -1;
  1813   if (ne_get_uint(ctx->ebml.doctype_read_version, &docversion) != 0)
  1814     docversion = 1;
  1815   if (docversion < 1 || docversion > 2) {
  1816     nestegg_destroy(ctx);
  1817     return -1;
  1820   if (!ctx->segment.tracks.track_entry.head) {
  1821     nestegg_destroy(ctx);
  1822     return -1;
  1825   track = ctx->segment.tracks.track_entry.head;
  1826   ctx->track_count = 0;
  1828   while (track) {
  1829     ctx->track_count += 1;
  1830     track = track->next;
  1833   *context = ctx;
  1835   return 0;
  1838 void
  1839 nestegg_destroy(nestegg * ctx)
  1841   while (ctx->ancestor)
  1842     ne_ctx_pop(ctx);
  1843   ne_pool_destroy(ctx->alloc_pool);
  1844   free(ctx->io);
  1845   free(ctx);
  1848 int
  1849 nestegg_duration(nestegg * ctx, uint64_t * duration)
  1851   uint64_t tc_scale;
  1852   double unscaled_duration;
  1854   if (ne_get_float(ctx->segment.info.duration, &unscaled_duration) != 0)
  1855     return -1;
  1857   tc_scale = ne_get_timecode_scale(ctx);
  1859   *duration = (uint64_t) (unscaled_duration * tc_scale);
  1860   return 0;
  1863 int
  1864 nestegg_tstamp_scale(nestegg * ctx, uint64_t * scale)
  1866   *scale = ne_get_timecode_scale(ctx);
  1867   return 0;
  1870 int
  1871 nestegg_track_count(nestegg * ctx, unsigned int * tracks)
  1873   *tracks = ctx->track_count;
  1874   return 0;
  1877 int
  1878 nestegg_get_cue_point(nestegg * ctx, unsigned int cluster_num, int64_t max_offset,
  1879                       int64_t * start_pos, int64_t * end_pos, uint64_t * tstamp)
  1881   int range_obtained = 0;
  1882   unsigned int cluster_count = 0;
  1883   struct cue_point * cue_point;
  1884   struct cue_track_positions * pos;
  1885   uint64_t seek_pos, track_number, tc_scale, time;
  1886   struct ebml_list_node * cues_node = ctx->segment.cues.cue_point.head;
  1887   struct ebml_list_node * cue_pos_node = NULL;
  1888   unsigned int track = 0, track_count = 0, track_index;
  1890   if (!start_pos || !end_pos || !tstamp)
  1891     return -1;
  1893   /* Initialise return values */
  1894   *start_pos = -1;
  1895   *end_pos = -1;
  1896   *tstamp = 0;
  1898   if (!cues_node) {
  1899     ne_init_cue_points(ctx, max_offset);
  1900     cues_node = ctx->segment.cues.cue_point.head;
  1901     /* Verify cues have been added to context. */
  1902     if (!cues_node)
  1903       return -1;
  1906   nestegg_track_count(ctx, &track_count);
  1908   tc_scale = ne_get_timecode_scale(ctx);
  1910   while (cues_node && !range_obtained) {
  1911     assert(cues_node->id == ID_CUE_POINT);
  1912     cue_point = cues_node->data;
  1913     cue_pos_node = cue_point->cue_track_positions.head;
  1914     while (cue_pos_node) {
  1915       assert(cue_pos_node->id == ID_CUE_TRACK_POSITIONS);
  1916       pos = cue_pos_node->data;
  1917       for (track = 0; track < track_count; track++) {
  1918         if (ne_get_uint(pos->track, &track_number) != 0)
  1919           return -1;
  1921         if (ne_map_track_number_to_index(ctx, track_number, &track_index) != 0)
  1922           return -1;
  1924         if (track_index == track) {
  1925           if (ne_get_uint(pos->cluster_position, &seek_pos) != 0)
  1926             return -1;
  1927           if (cluster_count == cluster_num) {
  1928             *start_pos = ctx->segment_offset+seek_pos;
  1929             if (ne_get_uint(cue_point->time, &time) != 0)
  1930               return -1;
  1931             *tstamp = time * tc_scale;
  1932           } else if (cluster_count == cluster_num+1) {
  1933             *end_pos = (ctx->segment_offset+seek_pos)-1;
  1934             range_obtained = 1;
  1935             break;
  1937           cluster_count++;
  1940       cue_pos_node = cue_pos_node->next;
  1942     cues_node = cues_node->next;
  1945   return 0;
  1948 int
  1949 nestegg_offset_seek(nestegg * ctx, uint64_t offset)
  1951   int r;
  1953   if (offset > INT64_MAX)
  1954     return -1;
  1956   /* Seek and set up parser state for segment-level element (Cluster). */
  1957   r = ne_io_seek(ctx->io, offset, NESTEGG_SEEK_SET);
  1958   if (r != 0)
  1959     return -1;
  1960   ctx->last_valid = 0;
  1962   while (ctx->ancestor)
  1963     ne_ctx_pop(ctx);
  1965   ne_ctx_push(ctx, ne_top_level_elements, ctx);
  1966   ne_ctx_push(ctx, ne_segment_elements, &ctx->segment);
  1968   ctx->log(ctx, NESTEGG_LOG_DEBUG, "seek: parsing cluster elements");
  1969   r = ne_parse(ctx, NULL, -1);
  1970   if (r != 1)
  1971     return -1;
  1973   return 0;
  1976 int
  1977 nestegg_track_seek(nestegg * ctx, unsigned int track, uint64_t tstamp)
  1979   int r;
  1980   struct cue_point * cue_point;
  1981   struct cue_track_positions * pos;
  1982   uint64_t seek_pos, tc_scale;
  1984   /* If there are no cues loaded, check for cues element in the seek head
  1985      and load it. */
  1986   if (!ctx->segment.cues.cue_point.head) {
  1987     r = ne_init_cue_points(ctx, -1);
  1988     if (r != 0)
  1989       return -1;
  1992   tc_scale = ne_get_timecode_scale(ctx);
  1994   cue_point = ne_find_cue_point_for_tstamp(ctx, ctx->segment.cues.cue_point.head,
  1995                                            track, tc_scale, tstamp);
  1996   if (!cue_point)
  1997     return -1;
  1999   pos = ne_find_cue_position_for_track(ctx, cue_point->cue_track_positions.head, track);
  2000   if (pos == NULL)
  2001     return -1;
  2003   if (ne_get_uint(pos->cluster_position, &seek_pos) != 0)
  2004     return -1;
  2006   /* Seek and set up parser state for segment-level element (Cluster). */
  2007   r = nestegg_offset_seek(ctx, ctx->segment_offset + seek_pos);
  2009   if (!ne_is_suspend_element(ctx->last_id))
  2010     return -1;
  2012   return 0;
  2015 int
  2016 nestegg_track_type(nestegg * ctx, unsigned int track)
  2018   struct track_entry * entry;
  2019   uint64_t type;
  2021   entry = ne_find_track_entry(ctx, track);
  2022   if (!entry)
  2023     return -1;
  2025   if (ne_get_uint(entry->type, &type) != 0)
  2026     return -1;
  2028   if (type & TRACK_TYPE_VIDEO)
  2029     return NESTEGG_TRACK_VIDEO;
  2031   if (type & TRACK_TYPE_AUDIO)
  2032     return NESTEGG_TRACK_AUDIO;
  2034   return -1;
  2037 int
  2038 nestegg_track_codec_id(nestegg * ctx, unsigned int track)
  2040   char * codec_id;
  2041   struct track_entry * entry;
  2043   entry = ne_find_track_entry(ctx, track);
  2044   if (!entry)
  2045     return -1;
  2047   if (ne_get_string(entry->codec_id, &codec_id) != 0)
  2048     return -1;
  2050   if (strcmp(codec_id, TRACK_ID_VP8) == 0)
  2051     return NESTEGG_CODEC_VP8;
  2053   if (strcmp(codec_id, TRACK_ID_VP9) == 0)
  2054     return NESTEGG_CODEC_VP9;
  2056   if (strcmp(codec_id, TRACK_ID_VORBIS) == 0)
  2057     return NESTEGG_CODEC_VORBIS;
  2059   if (strcmp(codec_id, TRACK_ID_OPUS) == 0)
  2060     return NESTEGG_CODEC_OPUS;
  2062   return -1;
  2065 int
  2066 nestegg_track_codec_data_count(nestegg * ctx, unsigned int track,
  2067                                unsigned int * count)
  2069   struct track_entry * entry;
  2070   struct ebml_binary codec_private;
  2071   unsigned char * p;
  2073   *count = 0;
  2075   entry = ne_find_track_entry(ctx, track);
  2076   if (!entry)
  2077     return -1;
  2079   if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS)
  2080     return -1;
  2082   if (ne_get_binary(entry->codec_private, &codec_private) != 0)
  2083     return -1;
  2085   if (codec_private.length < 1)
  2086     return -1;
  2088   p = codec_private.data;
  2089   *count = *p + 1;
  2091   if (*count > 3)
  2092     return -1;
  2094   return 0;
  2097 int
  2098 nestegg_track_codec_data(nestegg * ctx, unsigned int track, unsigned int item,
  2099                          unsigned char ** data, size_t * length)
  2101   struct track_entry * entry;
  2102   struct ebml_binary codec_private;
  2103   uint64_t sizes[3], total;
  2104   unsigned char * p;
  2105   unsigned int count, i;
  2107   *data = NULL;
  2108   *length = 0;
  2110   entry = ne_find_track_entry(ctx, track);
  2111   if (!entry)
  2112     return -1;
  2114   if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS
  2115     && nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_OPUS)
  2116     return -1;
  2118   if (ne_get_binary(entry->codec_private, &codec_private) != 0)
  2119     return -1;
  2121   if (nestegg_track_codec_id(ctx, track) == NESTEGG_CODEC_VORBIS) {
  2122       p = codec_private.data;
  2123       count = *p++ + 1;
  2125       if (count > 3)
  2126         return -1;
  2128       i = 0;
  2129       total = 0;
  2130       while (--count) {
  2131         sizes[i] = ne_xiph_lace_value(&p);
  2132         total += sizes[i];
  2133         i += 1;
  2135       sizes[i] = codec_private.length - total - (p - codec_private.data);
  2137       for (i = 0; i < item; ++i) {
  2138         if (sizes[i] > LIMIT_FRAME)
  2139           return -1;
  2140         p += sizes[i];
  2142       *data = p;
  2143       *length = sizes[item];
  2144   } else {
  2145     *data = codec_private.data;
  2146     *length = codec_private.length;
  2149   return 0;
  2152 int
  2153 nestegg_track_video_params(nestegg * ctx, unsigned int track,
  2154                            nestegg_video_params * params)
  2156   struct track_entry * entry;
  2157   uint64_t value;
  2159   memset(params, 0, sizeof(*params));
  2161   entry = ne_find_track_entry(ctx, track);
  2162   if (!entry)
  2163     return -1;
  2165   if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_VIDEO)
  2166     return -1;
  2168   value = 0;
  2169   ne_get_uint(entry->video.stereo_mode, &value);
  2170   if (value <= NESTEGG_VIDEO_STEREO_TOP_BOTTOM ||
  2171       value == NESTEGG_VIDEO_STEREO_RIGHT_LEFT)
  2172     params->stereo_mode = value;
  2174   if (ne_get_uint(entry->video.pixel_width, &value) != 0)
  2175     return -1;
  2176   params->width = value;
  2178   if (ne_get_uint(entry->video.pixel_height, &value) != 0)
  2179     return -1;
  2180   params->height = value;
  2182   value = 0;
  2183   ne_get_uint(entry->video.pixel_crop_bottom, &value);
  2184   params->crop_bottom = value;
  2186   value = 0;
  2187   ne_get_uint(entry->video.pixel_crop_top, &value);
  2188   params->crop_top = value;
  2190   value = 0;
  2191   ne_get_uint(entry->video.pixel_crop_left, &value);
  2192   params->crop_left = value;
  2194   value = 0;
  2195   ne_get_uint(entry->video.pixel_crop_right, &value);
  2196   params->crop_right = value;
  2198   value = params->width;
  2199   ne_get_uint(entry->video.display_width, &value);
  2200   params->display_width = value;
  2202   value = params->height;
  2203   ne_get_uint(entry->video.display_height, &value);
  2204   params->display_height = value;
  2206   return 0;
  2209 int
  2210 nestegg_track_audio_params(nestegg * ctx, unsigned int track,
  2211                            nestegg_audio_params * params)
  2213   struct track_entry * entry;
  2214   uint64_t value;
  2216   memset(params, 0, sizeof(*params));
  2218   entry = ne_find_track_entry(ctx, track);
  2219   if (!entry)
  2220     return -1;
  2222   if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_AUDIO)
  2223     return -1;
  2225   params->rate = 8000;
  2226   ne_get_float(entry->audio.sampling_frequency, &params->rate);
  2228   value = 1;
  2229   ne_get_uint(entry->audio.channels, &value);
  2230   params->channels = value;
  2232   value = 16;
  2233   ne_get_uint(entry->audio.bit_depth, &value);
  2234   params->depth = value;
  2236   value = 0;
  2237   ne_get_uint(entry->codec_delay, &value);
  2238   params->codec_delay = value;
  2240   value = 0;
  2241   ne_get_uint(entry->seek_preroll, &value);
  2242   params->seek_preroll = value;
  2244   return 0;
  2247 int
  2248 nestegg_track_default_duration(nestegg * ctx, unsigned int track,
  2249                                uint64_t * duration)
  2251   struct track_entry * entry;
  2252   uint64_t value;
  2254   entry = ne_find_track_entry(ctx, track);
  2255   if (!entry)
  2256     return -1;
  2258   if (ne_get_uint(entry->default_duration, &value) != 0)
  2259     return -1;
  2260   *duration = value;
  2262   return 0;
  2265 int
  2266 nestegg_read_packet(nestegg * ctx, nestegg_packet ** pkt)
  2268   int r;
  2269   uint64_t id, size;
  2271   *pkt = NULL;
  2273   for (;;) {
  2274     r = ne_peek_element(ctx, &id, &size);
  2275     if (r != 1)
  2276       return r;
  2278     /* Any DESC_FLAG_SUSPEND fields must be handled here. */
  2279     if (ne_is_suspend_element(id)) {
  2280       r = ne_read_element(ctx, &id, &size);
  2281       if (r != 1)
  2282         return r;
  2284       /* The only DESC_FLAG_SUSPEND fields are Blocks and SimpleBlocks, which we
  2285          handle directly. */
  2286       r = ne_read_block(ctx, id, size, pkt);
  2287       if (r != 1)
  2288         return r;
  2290       r = ne_read_block_duration(ctx, *pkt);
  2291       if (r != 1)
  2292         return r;
  2294       r = ne_read_discard_padding(ctx, *pkt);
  2295       if (r != 1)
  2296         return r;
  2298       return r;
  2301     r =  ne_parse(ctx, NULL, -1);
  2302     if (r != 1)
  2303       return r;
  2306   return 1;
  2309 void
  2310 nestegg_free_packet(nestegg_packet * pkt)
  2312   struct frame * frame;
  2314   while (pkt->frame) {
  2315     frame = pkt->frame;
  2316     pkt->frame = frame->next;
  2317     free(frame->data);
  2318     free(frame);
  2321  free(pkt);
  2324 int
  2325 nestegg_packet_track(nestegg_packet * pkt, unsigned int * track)
  2327   *track = pkt->track;
  2328   return 0;
  2331 int
  2332 nestegg_packet_tstamp(nestegg_packet * pkt, uint64_t * tstamp)
  2334   *tstamp = pkt->timecode;
  2335   return 0;
  2338 int
  2339 nestegg_packet_duration(nestegg_packet * pkt, uint64_t * duration)
  2341   *duration = pkt->duration;
  2342   return 0;
  2345 int
  2346 nestegg_packet_discard_padding(nestegg_packet * pkt, int64_t * discard_padding)
  2348   *discard_padding = pkt->discard_padding;
  2349   return 0;
  2352 int
  2353 nestegg_packet_count(nestegg_packet * pkt, unsigned int * count)
  2355   struct frame * f = pkt->frame;
  2357   *count = 0;
  2359   while (f) {
  2360     *count += 1;
  2361     f = f->next;
  2364   return 0;
  2367 int
  2368 nestegg_packet_data(nestegg_packet * pkt, unsigned int item,
  2369                     unsigned char ** data, size_t * length)
  2371   struct frame * f = pkt->frame;
  2372   unsigned int count = 0;
  2374   *data = NULL;
  2375   *length = 0;
  2377   while (f) {
  2378     if (count == item) {
  2379       *data = f->data;
  2380       *length = f->length;
  2381       return 0;
  2383     count += 1;
  2384     f = f->next;
  2387   return -1;
  2390 int
  2391 nestegg_has_cues(nestegg * ctx)
  2393   return ctx->segment.cues.cue_point.head ||
  2394          ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES);
  2397 int
  2398 nestegg_sniff(unsigned char const * buffer, size_t length)
  2400   nestegg_io io;
  2401   struct sniff_buffer user_data;
  2403   user_data.buffer = buffer;
  2404   user_data.length = length;
  2405   user_data.offset = 0;
  2407   io.read = ne_buffer_read;
  2408   io.seek = ne_buffer_seek;
  2409   io.tell = ne_buffer_tell;
  2410   io.userdata = &user_data;
  2411   return ne_match_webm(io, length);
  2414 void
  2415 nestegg_set_halloc_func(void * (* realloc_func)(void *, size_t))
  2417   halloc_allocator = realloc_func;

mercurial