LCOV - code coverage report
Current view: directory - media/libnestegg/src - nestegg.c (source / functions) Found Hit Coverage
Test: app.info Lines: 810 0 0.0 %
Date: 2012-06-02 Functions: 63 0 0.0 %

       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>
      10                 : 
      11                 : #include "halloc.h"
      12                 : #include "nestegg/nestegg.h"
      13                 : 
      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
      23                 : 
      24                 : /* Global Elements */
      25                 : #define ID_VOID                 0xec
      26                 : #define ID_CRC32                0xbf
      27                 : 
      28                 : /* WebMedia Elements */
      29                 : #define ID_SEGMENT              0x18538067
      30                 : 
      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
      36                 : 
      37                 : /* Info Elements */
      38                 : #define ID_INFO                 0x1549a966
      39                 : #define ID_TIMECODE_SCALE       0x2ad7b1
      40                 : #define ID_DURATION             0x4489
      41                 : 
      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
      47                 : 
      48                 : /* BlockGroup Elements */
      49                 : #define ID_BLOCK                0xa1
      50                 : #define ID_BLOCK_DURATION       0x9b
      51                 : #define ID_REFERENCE_BLOCK      0xfb
      52                 : 
      53                 : /* Tracks Elements */
      54                 : #define ID_TRACKS               0x1654ae6b
      55                 : #define ID_TRACK_ENTRY          0xae
      56                 : #define ID_TRACK_NUMBER         0xd7
      57                 : #define ID_TRACK_UID            0x73c5
      58                 : #define ID_TRACK_TYPE           0x83
      59                 : #define ID_FLAG_ENABLED         0xb9
      60                 : #define ID_FLAG_DEFAULT         0x88
      61                 : #define ID_FLAG_LACING          0x9c
      62                 : #define ID_TRACK_TIMECODE_SCALE 0x23314f
      63                 : #define ID_LANGUAGE             0x22b59c
      64                 : #define ID_CODEC_ID             0x86
      65                 : #define ID_CODEC_PRIVATE        0x63a2
      66                 : 
      67                 : /* Video Elements */
      68                 : #define ID_VIDEO                0xe0
      69                 : #define ID_STEREO_MODE          0x53b8
      70                 : #define ID_PIXEL_WIDTH          0xb0
      71                 : #define ID_PIXEL_HEIGHT         0xba
      72                 : #define ID_PIXEL_CROP_BOTTOM    0x54aa
      73                 : #define ID_PIXEL_CROP_TOP       0x54bb
      74                 : #define ID_PIXEL_CROP_LEFT      0x54cc
      75                 : #define ID_PIXEL_CROP_RIGHT     0x54dd
      76                 : #define ID_DISPLAY_WIDTH        0x54b0
      77                 : #define ID_DISPLAY_HEIGHT       0x54ba
      78                 : 
      79                 : /* Audio Elements */
      80                 : #define ID_AUDIO                0xe1
      81                 : #define ID_SAMPLING_FREQUENCY   0xb5
      82                 : #define ID_CHANNELS             0x9f
      83                 : #define ID_BIT_DEPTH            0x6264
      84                 : 
      85                 : /* Cues Elements */
      86                 : #define ID_CUES                 0x1c53bb6b
      87                 : #define ID_CUE_POINT            0xbb
      88                 : #define ID_CUE_TIME             0xb3
      89                 : #define ID_CUE_TRACK_POSITIONS  0xb7
      90                 : #define ID_CUE_TRACK            0xf7
      91                 : #define ID_CUE_CLUSTER_POSITION 0xf1
      92                 : #define ID_CUE_BLOCK_NUMBER     0x5378
      93                 : 
      94                 : /* EBML Types */
      95                 : enum ebml_type_enum {
      96                 :   TYPE_UNKNOWN,
      97                 :   TYPE_MASTER,
      98                 :   TYPE_UINT,
      99                 :   TYPE_FLOAT,
     100                 :   TYPE_INT,
     101                 :   TYPE_STRING,
     102                 :   TYPE_BINARY
     103                 : };
     104                 : 
     105                 : #define LIMIT_STRING            (1 << 20)
     106                 : #define LIMIT_BINARY            (1 << 24)
     107                 : #define LIMIT_BLOCK             (1 << 30)
     108                 : #define LIMIT_FRAME             (1 << 28)
     109                 : 
     110                 : /* Field Flags */
     111                 : #define DESC_FLAG_NONE          0
     112                 : #define DESC_FLAG_MULTI         (1 << 0)
     113                 : #define DESC_FLAG_SUSPEND       (1 << 1)
     114                 : #define DESC_FLAG_OFFSET        (1 << 2)
     115                 : 
     116                 : /* Block Header Flags */
     117                 : #define BLOCK_FLAGS_LACING      6
     118                 : 
     119                 : /* Lacing Constants */
     120                 : #define LACING_NONE             0
     121                 : #define LACING_XIPH             1
     122                 : #define LACING_FIXED            2
     123                 : #define LACING_EBML             3
     124                 : 
     125                 : /* Track Types */
     126                 : #define TRACK_TYPE_VIDEO        1
     127                 : #define TRACK_TYPE_AUDIO        2
     128                 : 
     129                 : /* Track IDs */
     130                 : #define TRACK_ID_VP8            "V_VP8"
     131                 : #define TRACK_ID_VORBIS         "A_VORBIS"
     132                 : 
     133                 : enum vint_mask {
     134                 :   MASK_NONE,
     135                 :   MASK_FIRST_BIT
     136                 : };
     137                 : 
     138                 : struct ebml_binary {
     139                 :   unsigned char * data;
     140                 :   size_t length;
     141                 : };
     142                 : 
     143                 : struct ebml_list_node {
     144                 :   struct ebml_list_node * next;
     145                 :   uint64_t id;
     146                 :   void * data;
     147                 : };
     148                 : 
     149                 : struct ebml_list {
     150                 :   struct ebml_list_node * head;
     151                 :   struct ebml_list_node * tail;
     152                 : };
     153                 : 
     154                 : struct ebml_type {
     155                 :   union ebml_value {
     156                 :     uint64_t u;
     157                 :     double f;
     158                 :     int64_t i;
     159                 :     char * s;
     160                 :     struct ebml_binary b;
     161                 :   } v;
     162                 :   enum ebml_type_enum type;
     163                 :   int read;
     164                 : };
     165                 : 
     166                 : /* EBML Definitions */
     167                 : struct ebml {
     168                 :   struct ebml_type ebml_version;
     169                 :   struct ebml_type ebml_read_version;
     170                 :   struct ebml_type ebml_max_id_length;
     171                 :   struct ebml_type ebml_max_size_length;
     172                 :   struct ebml_type doctype;
     173                 :   struct ebml_type doctype_version;
     174                 :   struct ebml_type doctype_read_version;
     175                 : };
     176                 : 
     177                 : /* Matroksa Definitions */
     178                 : struct seek {
     179                 :   struct ebml_type id;
     180                 :   struct ebml_type position;
     181                 : };
     182                 : 
     183                 : struct seek_head {
     184                 :   struct ebml_list seek;
     185                 : };
     186                 : 
     187                 : struct info {
     188                 :   struct ebml_type timecode_scale;
     189                 :   struct ebml_type duration;
     190                 : };
     191                 : 
     192                 : struct block_group {
     193                 :   struct ebml_type duration;
     194                 :   struct ebml_type reference_block;
     195                 : };
     196                 : 
     197                 : struct cluster {
     198                 :   struct ebml_type timecode;
     199                 :   struct ebml_list block_group;
     200                 : };
     201                 : 
     202                 : struct video {
     203                 :   struct ebml_type stereo_mode;
     204                 :   struct ebml_type pixel_width;
     205                 :   struct ebml_type pixel_height;
     206                 :   struct ebml_type pixel_crop_bottom;
     207                 :   struct ebml_type pixel_crop_top;
     208                 :   struct ebml_type pixel_crop_left;
     209                 :   struct ebml_type pixel_crop_right;
     210                 :   struct ebml_type display_width;
     211                 :   struct ebml_type display_height;
     212                 : };
     213                 : 
     214                 : struct audio {
     215                 :   struct ebml_type sampling_frequency;
     216                 :   struct ebml_type channels;
     217                 :   struct ebml_type bit_depth;
     218                 : };
     219                 : 
     220                 : struct track_entry {
     221                 :   struct ebml_type number;
     222                 :   struct ebml_type uid;
     223                 :   struct ebml_type type;
     224                 :   struct ebml_type flag_enabled;
     225                 :   struct ebml_type flag_default;
     226                 :   struct ebml_type flag_lacing;
     227                 :   struct ebml_type track_timecode_scale;
     228                 :   struct ebml_type language;
     229                 :   struct ebml_type codec_id;
     230                 :   struct ebml_type codec_private;
     231                 :   struct video video;
     232                 :   struct audio audio;
     233                 : };
     234                 : 
     235                 : struct tracks {
     236                 :   struct ebml_list track_entry;
     237                 : };
     238                 : 
     239                 : struct cue_track_positions {
     240                 :   struct ebml_type track;
     241                 :   struct ebml_type cluster_position;
     242                 :   struct ebml_type block_number;
     243                 : };
     244                 : 
     245                 : struct cue_point {
     246                 :   struct ebml_type time;
     247                 :   struct ebml_list cue_track_positions;
     248                 : };
     249                 : 
     250                 : struct cues {
     251                 :   struct ebml_list cue_point;
     252                 : };
     253                 : 
     254                 : struct segment {
     255                 :   struct ebml_list seek_head;
     256                 :   struct info info;
     257                 :   struct ebml_list cluster;
     258                 :   struct tracks tracks;
     259                 :   struct cues cues;
     260                 : };
     261                 : 
     262                 : /* Misc. */
     263                 : struct pool_ctx {
     264                 :   char dummy;
     265                 : };
     266                 : 
     267                 : struct list_node {
     268                 :   struct list_node * previous;
     269                 :   struct ebml_element_desc * node;
     270                 :   unsigned char * data;
     271                 : };
     272                 : 
     273                 : struct saved_state {
     274                 :   int64_t stream_offset;
     275                 :   struct list_node * ancestor;
     276                 :   uint64_t last_id;
     277                 :   uint64_t last_size;
     278                 : };
     279                 : 
     280                 : struct frame {
     281                 :   unsigned char * data;
     282                 :   size_t length;
     283                 :   struct frame * next;
     284                 : };
     285                 : 
     286                 : /* Public (opaque) Structures */
     287                 : struct nestegg {
     288                 :   nestegg_io * io;
     289                 :   nestegg_log log;
     290                 :   struct pool_ctx * alloc_pool;
     291                 :   uint64_t last_id;
     292                 :   uint64_t last_size;
     293                 :   struct list_node * ancestor;
     294                 :   struct ebml ebml;
     295                 :   struct segment segment;
     296                 :   int64_t segment_offset;
     297                 :   unsigned int track_count;
     298                 : };
     299                 : 
     300                 : struct nestegg_packet {
     301                 :   uint64_t track;
     302                 :   uint64_t timecode;
     303                 :   struct frame * frame;
     304                 : };
     305                 : 
     306                 : /* Element Descriptor */
     307                 : struct ebml_element_desc {
     308                 :   char const * name;
     309                 :   uint64_t id;
     310                 :   enum ebml_type_enum type;
     311                 :   size_t offset;
     312                 :   unsigned int flags;
     313                 :   struct ebml_element_desc * children;
     314                 :   size_t size;
     315                 :   size_t data_offset;
     316                 : };
     317                 : 
     318                 : #define E_FIELD(ID, TYPE, STRUCT, FIELD) \
     319                 :   { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_NONE, NULL, 0, 0 }
     320                 : #define E_MASTER(ID, TYPE, STRUCT, FIELD) \
     321                 :   { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_MULTI, ne_ ## FIELD ## _elements, \
     322                 :       sizeof(struct FIELD), 0 }
     323                 : #define E_SINGLE_MASTER_O(ID, TYPE, STRUCT, FIELD) \
     324                 :   { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_OFFSET, ne_ ## FIELD ## _elements, 0, \
     325                 :       offsetof(STRUCT, FIELD ## _offset) }
     326                 : #define E_SINGLE_MASTER(ID, TYPE, STRUCT, FIELD) \
     327                 :   { #ID, ID, TYPE, offsetof(STRUCT, FIELD), DESC_FLAG_NONE, ne_ ## FIELD ## _elements, 0, 0 }
     328                 : #define E_SUSPEND(ID, TYPE) \
     329                 :   { #ID, ID, TYPE, 0, DESC_FLAG_SUSPEND, NULL, 0, 0 }
     330                 : #define E_LAST \
     331                 :   { NULL, 0, 0, 0, DESC_FLAG_NONE, NULL, 0, 0 }
     332                 : 
     333                 : /* EBML Element Lists */
     334                 : static struct ebml_element_desc ne_ebml_elements[] = {
     335                 :   E_FIELD(ID_EBML_VERSION, TYPE_UINT, struct ebml, ebml_version),
     336                 :   E_FIELD(ID_EBML_READ_VERSION, TYPE_UINT, struct ebml, ebml_read_version),
     337                 :   E_FIELD(ID_EBML_MAX_ID_LENGTH, TYPE_UINT, struct ebml, ebml_max_id_length),
     338                 :   E_FIELD(ID_EBML_MAX_SIZE_LENGTH, TYPE_UINT, struct ebml, ebml_max_size_length),
     339                 :   E_FIELD(ID_DOCTYPE, TYPE_STRING, struct ebml, doctype),
     340                 :   E_FIELD(ID_DOCTYPE_VERSION, TYPE_UINT, struct ebml, doctype_version),
     341                 :   E_FIELD(ID_DOCTYPE_READ_VERSION, TYPE_UINT, struct ebml, doctype_read_version),
     342                 :   E_LAST
     343                 : };
     344                 : 
     345                 : /* WebMedia Element Lists */
     346                 : static struct ebml_element_desc ne_seek_elements[] = {
     347                 :   E_FIELD(ID_SEEK_ID, TYPE_BINARY, struct seek, id),
     348                 :   E_FIELD(ID_SEEK_POSITION, TYPE_UINT, struct seek, position),
     349                 :   E_LAST
     350                 : };
     351                 : 
     352                 : static struct ebml_element_desc ne_seek_head_elements[] = {
     353                 :   E_MASTER(ID_SEEK, TYPE_MASTER, struct seek_head, seek),
     354                 :   E_LAST
     355                 : };
     356                 : 
     357                 : static struct ebml_element_desc ne_info_elements[] = {
     358                 :   E_FIELD(ID_TIMECODE_SCALE, TYPE_UINT, struct info, timecode_scale),
     359                 :   E_FIELD(ID_DURATION, TYPE_FLOAT, struct info, duration),
     360                 :   E_LAST
     361                 : };
     362                 : 
     363                 : static struct ebml_element_desc ne_block_group_elements[] = {
     364                 :   E_SUSPEND(ID_BLOCK, TYPE_BINARY),
     365                 :   E_FIELD(ID_BLOCK_DURATION, TYPE_UINT, struct block_group, duration),
     366                 :   E_FIELD(ID_REFERENCE_BLOCK, TYPE_INT, struct block_group, reference_block),
     367                 :   E_LAST
     368                 : };
     369                 : 
     370                 : static struct ebml_element_desc ne_cluster_elements[] = {
     371                 :   E_FIELD(ID_TIMECODE, TYPE_UINT, struct cluster, timecode),
     372                 :   E_MASTER(ID_BLOCK_GROUP, TYPE_MASTER, struct cluster, block_group),
     373                 :   E_SUSPEND(ID_SIMPLE_BLOCK, TYPE_BINARY),
     374                 :   E_LAST
     375                 : };
     376                 : 
     377                 : static struct ebml_element_desc ne_video_elements[] = {
     378                 :   E_FIELD(ID_STEREO_MODE, TYPE_UINT, struct video, stereo_mode),
     379                 :   E_FIELD(ID_PIXEL_WIDTH, TYPE_UINT, struct video, pixel_width),
     380                 :   E_FIELD(ID_PIXEL_HEIGHT, TYPE_UINT, struct video, pixel_height),
     381                 :   E_FIELD(ID_PIXEL_CROP_BOTTOM, TYPE_UINT, struct video, pixel_crop_bottom),
     382                 :   E_FIELD(ID_PIXEL_CROP_TOP, TYPE_UINT, struct video, pixel_crop_top),
     383                 :   E_FIELD(ID_PIXEL_CROP_LEFT, TYPE_UINT, struct video, pixel_crop_left),
     384                 :   E_FIELD(ID_PIXEL_CROP_RIGHT, TYPE_UINT, struct video, pixel_crop_right),
     385                 :   E_FIELD(ID_DISPLAY_WIDTH, TYPE_UINT, struct video, display_width),
     386                 :   E_FIELD(ID_DISPLAY_HEIGHT, TYPE_UINT, struct video, display_height),
     387                 :   E_LAST
     388                 : };
     389                 : 
     390                 : static struct ebml_element_desc ne_audio_elements[] = {
     391                 :   E_FIELD(ID_SAMPLING_FREQUENCY, TYPE_FLOAT, struct audio, sampling_frequency),
     392                 :   E_FIELD(ID_CHANNELS, TYPE_UINT, struct audio, channels),
     393                 :   E_FIELD(ID_BIT_DEPTH, TYPE_UINT, struct audio, bit_depth),
     394                 :   E_LAST
     395                 : };
     396                 : 
     397                 : static struct ebml_element_desc ne_track_entry_elements[] = {
     398                 :   E_FIELD(ID_TRACK_NUMBER, TYPE_UINT, struct track_entry, number),
     399                 :   E_FIELD(ID_TRACK_UID, TYPE_UINT, struct track_entry, uid),
     400                 :   E_FIELD(ID_TRACK_TYPE, TYPE_UINT, struct track_entry, type),
     401                 :   E_FIELD(ID_FLAG_ENABLED, TYPE_UINT, struct track_entry, flag_enabled),
     402                 :   E_FIELD(ID_FLAG_DEFAULT, TYPE_UINT, struct track_entry, flag_default),
     403                 :   E_FIELD(ID_FLAG_LACING, TYPE_UINT, struct track_entry, flag_lacing),
     404                 :   E_FIELD(ID_TRACK_TIMECODE_SCALE, TYPE_FLOAT, struct track_entry, track_timecode_scale),
     405                 :   E_FIELD(ID_LANGUAGE, TYPE_STRING, struct track_entry, language),
     406                 :   E_FIELD(ID_CODEC_ID, TYPE_STRING, struct track_entry, codec_id),
     407                 :   E_FIELD(ID_CODEC_PRIVATE, TYPE_BINARY, struct track_entry, codec_private),
     408                 :   E_SINGLE_MASTER(ID_VIDEO, TYPE_MASTER, struct track_entry, video),
     409                 :   E_SINGLE_MASTER(ID_AUDIO, TYPE_MASTER, struct track_entry, audio),
     410                 :   E_LAST
     411                 : };
     412                 : 
     413                 : static struct ebml_element_desc ne_tracks_elements[] = {
     414                 :   E_MASTER(ID_TRACK_ENTRY, TYPE_MASTER, struct tracks, track_entry),
     415                 :   E_LAST
     416                 : };
     417                 : 
     418                 : static struct ebml_element_desc ne_cue_track_positions_elements[] = {
     419                 :   E_FIELD(ID_CUE_TRACK, TYPE_UINT, struct cue_track_positions, track),
     420                 :   E_FIELD(ID_CUE_CLUSTER_POSITION, TYPE_UINT, struct cue_track_positions, cluster_position),
     421                 :   E_FIELD(ID_CUE_BLOCK_NUMBER, TYPE_UINT, struct cue_track_positions, block_number),
     422                 :   E_LAST
     423                 : };
     424                 : 
     425                 : static struct ebml_element_desc ne_cue_point_elements[] = {
     426                 :   E_FIELD(ID_CUE_TIME, TYPE_UINT, struct cue_point, time),
     427                 :   E_MASTER(ID_CUE_TRACK_POSITIONS, TYPE_MASTER, struct cue_point, cue_track_positions),
     428                 :   E_LAST
     429                 : };
     430                 : 
     431                 : static struct ebml_element_desc ne_cues_elements[] = {
     432                 :   E_MASTER(ID_CUE_POINT, TYPE_MASTER, struct cues, cue_point),
     433                 :   E_LAST
     434                 : };
     435                 : 
     436                 : static struct ebml_element_desc ne_segment_elements[] = {
     437                 :   E_MASTER(ID_SEEK_HEAD, TYPE_MASTER, struct segment, seek_head),
     438                 :   E_SINGLE_MASTER(ID_INFO, TYPE_MASTER, struct segment, info),
     439                 :   E_MASTER(ID_CLUSTER, TYPE_MASTER, struct segment, cluster),
     440                 :   E_SINGLE_MASTER(ID_TRACKS, TYPE_MASTER, struct segment, tracks),
     441                 :   E_SINGLE_MASTER(ID_CUES, TYPE_MASTER, struct segment, cues),
     442                 :   E_LAST
     443                 : };
     444                 : 
     445                 : static struct ebml_element_desc ne_top_level_elements[] = {
     446                 :   E_SINGLE_MASTER(ID_EBML, TYPE_MASTER, nestegg, ebml),
     447                 :   E_SINGLE_MASTER_O(ID_SEGMENT, TYPE_MASTER, nestegg, segment),
     448                 :   E_LAST
     449                 : };
     450                 : 
     451                 : #undef E_FIELD
     452                 : #undef E_MASTER
     453                 : #undef E_SINGLE_MASTER_O
     454                 : #undef E_SINGLE_MASTER
     455                 : #undef E_SUSPEND
     456                 : #undef E_LAST
     457                 : 
     458                 : static struct pool_ctx *
     459               0 : ne_pool_init(void)
     460                 : {
     461                 :   struct pool_ctx * pool;
     462                 : 
     463               0 :   pool = h_malloc(sizeof(*pool));
     464               0 :   if (!pool)
     465               0 :     abort();
     466               0 :   return pool;
     467                 : }
     468                 : 
     469                 : static void
     470               0 : ne_pool_destroy(struct pool_ctx * pool)
     471                 : {
     472               0 :   h_free(pool);
     473               0 : }
     474                 : 
     475                 : static void *
     476               0 : ne_pool_alloc(size_t size, struct pool_ctx * pool)
     477                 : {
     478                 :   void * p;
     479                 : 
     480               0 :   p = h_malloc(size);
     481               0 :   if (!p)
     482               0 :     abort();
     483               0 :   hattach(p, pool);
     484               0 :   memset(p, 0, size);
     485               0 :   return p;
     486                 : }
     487                 : 
     488                 : static void *
     489               0 : ne_alloc(size_t size)
     490                 : {
     491                 :   void * p;
     492                 : 
     493               0 :   p = calloc(1, size);
     494               0 :   if (!p)
     495               0 :     abort();
     496               0 :   return p;
     497                 : }
     498                 : 
     499                 : static int
     500               0 : ne_io_read(nestegg_io * io, void * buffer, size_t length)
     501                 : {
     502               0 :   return io->read(buffer, length, io->userdata);
     503                 : }
     504                 : 
     505                 : static int
     506               0 : ne_io_seek(nestegg_io * io, int64_t offset, int whence)
     507                 : {
     508               0 :   return io->seek(offset, whence, io->userdata);
     509                 : }
     510                 : 
     511                 : static int
     512               0 : ne_io_read_skip(nestegg_io * io, size_t length)
     513                 : {
     514                 :   size_t get;
     515                 :   unsigned char buf[8192];
     516               0 :   int r = 1;
     517                 : 
     518               0 :   while (length > 0) {
     519               0 :     get = length < sizeof(buf) ? length : sizeof(buf);
     520               0 :     r = ne_io_read(io, buf, get);
     521               0 :     if (r != 1)
     522               0 :       break;
     523               0 :     length -= get;
     524                 :   }
     525                 : 
     526               0 :   return r;
     527                 : }
     528                 : 
     529                 : static int64_t
     530               0 : ne_io_tell(nestegg_io * io)
     531                 : {
     532               0 :   return io->tell(io->userdata);
     533                 : }
     534                 : 
     535                 : static int
     536               0 : ne_bare_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length, enum vint_mask maskflag)
     537                 : {
     538                 :   int r;
     539                 :   unsigned char b;
     540               0 :   size_t maxlen = 8;
     541               0 :   unsigned int count = 1, mask = 1 << 7;
     542                 : 
     543               0 :   r = ne_io_read(io, &b, 1);
     544               0 :   if (r != 1)
     545               0 :     return r;
     546                 : 
     547               0 :   while (count < maxlen) {
     548               0 :     if ((b & mask) != 0)
     549               0 :       break;
     550               0 :     mask >>= 1;
     551               0 :     count += 1;
     552                 :   }
     553                 : 
     554               0 :   if (length)
     555               0 :     *length = count;
     556               0 :   *value = b;
     557                 : 
     558               0 :   if (maskflag == MASK_FIRST_BIT)
     559               0 :     *value = b & ~mask;
     560                 : 
     561               0 :   while (--count) {
     562               0 :     r = ne_io_read(io, &b, 1);
     563               0 :     if (r != 1)
     564               0 :       return r;
     565               0 :     *value <<= 8;
     566               0 :     *value |= b;
     567                 :   }
     568                 : 
     569               0 :   return 1;
     570                 : }
     571                 : 
     572                 : static int
     573               0 : ne_read_id(nestegg_io * io, uint64_t * value, uint64_t * length)
     574                 : {
     575               0 :   return ne_bare_read_vint(io, value, length, MASK_NONE);
     576                 : }
     577                 : 
     578                 : static int
     579               0 : ne_read_vint(nestegg_io * io, uint64_t * value, uint64_t * length)
     580                 : {
     581               0 :   return ne_bare_read_vint(io, value, length, MASK_FIRST_BIT);
     582                 : }
     583                 : 
     584                 : static int
     585               0 : ne_read_svint(nestegg_io * io, int64_t * value, uint64_t * length)
     586                 : {
     587                 :   int r;
     588                 :   uint64_t uvalue;
     589                 :   uint64_t ulength;
     590               0 :   int64_t svint_subtr[] = {
     591                 :     0x3f, 0x1fff,
     592                 :     0xfffff, 0x7ffffff,
     593                 :     0x3ffffffffLL, 0x1ffffffffffLL,
     594                 :     0xffffffffffffLL, 0x7fffffffffffffLL
     595                 :   };
     596                 : 
     597               0 :   r = ne_bare_read_vint(io, &uvalue, &ulength, MASK_FIRST_BIT);
     598               0 :   if (r != 1)
     599               0 :     return r;
     600               0 :   *value = uvalue - svint_subtr[ulength - 1];
     601               0 :   if (length)
     602               0 :     *length = ulength;
     603               0 :   return r;
     604                 : }
     605                 : 
     606                 : static int
     607               0 : ne_read_uint(nestegg_io * io, uint64_t * val, uint64_t length)
     608                 : {
     609                 :   unsigned char b;
     610                 :   int r;
     611                 : 
     612               0 :   if (length == 0 || length > 8)
     613               0 :     return -1;
     614               0 :   r = ne_io_read(io, &b, 1);
     615               0 :   if (r != 1)
     616               0 :     return r;
     617               0 :   *val = b;
     618               0 :   while (--length) {
     619               0 :     r = ne_io_read(io, &b, 1);
     620               0 :     if (r != 1)
     621               0 :       return r;
     622               0 :     *val <<= 8;
     623               0 :     *val |= b;
     624                 :   }
     625               0 :   return 1;
     626                 : }
     627                 : 
     628                 : static int
     629               0 : ne_read_int(nestegg_io * io, int64_t * val, uint64_t length)
     630                 : {
     631                 :   int r;
     632                 :   uint64_t uval, base;
     633                 : 
     634               0 :   r = ne_read_uint(io, &uval, length);
     635               0 :   if (r != 1)
     636               0 :     return r;
     637                 : 
     638               0 :   if (length < sizeof(int64_t)) {
     639               0 :     base = 1;
     640               0 :     base <<= length * 8 - 1;
     641               0 :     if (uval >= base) {
     642               0 :         base = 1;
     643               0 :         base <<= length * 8;
     644                 :     } else {
     645               0 :       base = 0;
     646                 :     }
     647               0 :     *val = uval - base;
     648                 :   } else {
     649               0 :     *val = (int64_t) uval;
     650                 :   }
     651                 : 
     652               0 :   return 1;
     653                 : }
     654                 : 
     655                 : static int
     656               0 : ne_read_float(nestegg_io * io, double * val, uint64_t length)
     657                 : {
     658                 :   union {
     659                 :     uint64_t u;
     660                 :     float f;
     661                 :     double d;
     662                 :   } value;
     663                 :   int r;
     664                 : 
     665                 :   /* length == 10 not implemented */
     666               0 :   if (length != 4 && length != 8)
     667               0 :     return -1;
     668               0 :   r = ne_read_uint(io, &value.u, length);
     669               0 :   if (r != 1)
     670               0 :     return r;
     671               0 :   if (length == 4)
     672               0 :     *val = value.f;
     673                 :   else
     674               0 :     *val = value.d;
     675               0 :   return 1;
     676                 : }
     677                 : 
     678                 : static int
     679               0 : ne_read_string(nestegg * ctx, char ** val, uint64_t length)
     680                 : {
     681                 :   char * str;
     682                 :   int r;
     683                 : 
     684               0 :   if (length == 0 || length > LIMIT_STRING)
     685               0 :     return -1;
     686               0 :   str = ne_pool_alloc(length + 1, ctx->alloc_pool);
     687               0 :   r = ne_io_read(ctx->io, (unsigned char *) str, length);
     688               0 :   if (r != 1)
     689               0 :     return r;
     690               0 :   str[length] = '\0';
     691               0 :   *val = str;
     692               0 :   return 1;
     693                 : }
     694                 : 
     695                 : static int
     696               0 : ne_read_binary(nestegg * ctx, struct ebml_binary * val, uint64_t length)
     697                 : {
     698               0 :   if (length == 0 || length > LIMIT_BINARY)
     699               0 :     return -1;
     700               0 :   val->data = ne_pool_alloc(length, ctx->alloc_pool);
     701               0 :   val->length = length;
     702               0 :   return ne_io_read(ctx->io, val->data, length);
     703                 : }
     704                 : 
     705                 : static int
     706               0 : ne_get_uint(struct ebml_type type, uint64_t * value)
     707                 : {
     708               0 :   if (!type.read)
     709               0 :     return -1;
     710                 : 
     711               0 :   assert(type.type == TYPE_UINT);
     712                 : 
     713               0 :   *value = type.v.u;
     714                 : 
     715               0 :   return 0;
     716                 : }
     717                 : 
     718                 : static int
     719               0 : ne_get_float(struct ebml_type type, double * value)
     720                 : {
     721               0 :   if (!type.read)
     722               0 :     return -1;
     723                 : 
     724               0 :   assert(type.type == TYPE_FLOAT);
     725                 : 
     726               0 :   *value = type.v.f;
     727                 : 
     728               0 :   return 0;
     729                 : }
     730                 : 
     731                 : static int
     732               0 : ne_get_string(struct ebml_type type, char ** value)
     733                 : {
     734               0 :   if (!type.read)
     735               0 :     return -1;
     736                 : 
     737               0 :   assert(type.type == TYPE_STRING);
     738                 : 
     739               0 :   *value = type.v.s;
     740                 : 
     741               0 :   return 0;
     742                 : }
     743                 : 
     744                 : static int
     745               0 : ne_get_binary(struct ebml_type type, struct ebml_binary * value)
     746                 : {
     747               0 :   if (!type.read)
     748               0 :     return -1;
     749                 : 
     750               0 :   assert(type.type == TYPE_BINARY);
     751                 : 
     752               0 :   *value = type.v.b;
     753                 : 
     754               0 :   return 0;
     755                 : }
     756                 : 
     757                 : static int
     758               0 : ne_is_ancestor_element(uint64_t id, struct list_node * ancestor)
     759                 : {
     760                 :   struct ebml_element_desc * element;
     761                 : 
     762               0 :   for (; ancestor; ancestor = ancestor->previous)
     763               0 :     for (element = ancestor->node; element->id; ++element)
     764               0 :       if (element->id == id)
     765               0 :         return 1;
     766                 : 
     767               0 :   return 0;
     768                 : }
     769                 : 
     770                 : static struct ebml_element_desc *
     771               0 : ne_find_element(uint64_t id, struct ebml_element_desc * elements)
     772                 : {
     773                 :   struct ebml_element_desc * element;
     774                 : 
     775               0 :   for (element = elements; element->id; ++element)
     776               0 :     if (element->id == id)
     777               0 :       return element;
     778                 : 
     779               0 :   return NULL;
     780                 : }
     781                 : 
     782                 : static void
     783               0 : ne_ctx_push(nestegg * ctx, struct ebml_element_desc * ancestor, void * data)
     784                 : {
     785                 :   struct list_node * item;
     786                 : 
     787               0 :   item = ne_alloc(sizeof(*item));
     788               0 :   item->previous = ctx->ancestor;
     789               0 :   item->node = ancestor;
     790               0 :   item->data = data;
     791               0 :   ctx->ancestor = item;
     792               0 : }
     793                 : 
     794                 : static void
     795               0 : ne_ctx_pop(nestegg * ctx)
     796                 : {
     797                 :   struct list_node * item;
     798                 : 
     799               0 :   item = ctx->ancestor;
     800               0 :   ctx->ancestor = item->previous;
     801               0 :   free(item);
     802               0 : }
     803                 : 
     804                 : static int
     805               0 : ne_ctx_save(nestegg * ctx, struct saved_state * s)
     806                 : {
     807               0 :   s->stream_offset = ne_io_tell(ctx->io);
     808               0 :   if (s->stream_offset < 0)
     809               0 :     return -1;
     810               0 :   s->ancestor = ctx->ancestor;
     811               0 :   s->last_id = ctx->last_id;
     812               0 :   s->last_size = ctx->last_size;
     813               0 :   return 0;
     814                 : }
     815                 : 
     816                 : static int
     817               0 : ne_ctx_restore(nestegg * ctx, struct saved_state * s)
     818                 : {
     819                 :   int r;
     820                 : 
     821               0 :   r = ne_io_seek(ctx->io, s->stream_offset, NESTEGG_SEEK_SET);
     822               0 :   if (r != 0)
     823               0 :     return -1;
     824               0 :   ctx->ancestor = s->ancestor;
     825               0 :   ctx->last_id = s->last_id;
     826               0 :   ctx->last_size = s->last_size;
     827               0 :   return 0;
     828                 : }
     829                 : 
     830                 : static int
     831               0 : ne_peek_element(nestegg * ctx, uint64_t * id, uint64_t * size)
     832                 : {
     833                 :   int r;
     834                 : 
     835               0 :   if (ctx->last_id && ctx->last_size) {
     836               0 :     if (id)
     837               0 :       *id = ctx->last_id;
     838               0 :     if (size)
     839               0 :       *size = ctx->last_size;
     840               0 :     return 1;
     841                 :   }
     842                 : 
     843               0 :   r = ne_read_id(ctx->io, &ctx->last_id, NULL);
     844               0 :   if (r != 1)
     845               0 :     return r;
     846                 : 
     847               0 :   r = ne_read_vint(ctx->io, &ctx->last_size, NULL);
     848               0 :   if (r != 1)
     849               0 :     return r;
     850                 : 
     851               0 :   if (id)
     852               0 :     *id = ctx->last_id;
     853               0 :   if (size)
     854               0 :     *size = ctx->last_size;
     855                 : 
     856               0 :   return 1;
     857                 : }
     858                 : 
     859                 : static int
     860               0 : ne_read_element(nestegg * ctx, uint64_t * id, uint64_t * size)
     861                 : {
     862                 :   int r;
     863                 : 
     864               0 :   r = ne_peek_element(ctx, id, size);
     865               0 :   if (r != 1)
     866               0 :     return r;
     867                 : 
     868               0 :   ctx->last_id = 0;
     869               0 :   ctx->last_size = 0;
     870                 : 
     871               0 :   return 1;
     872                 : }
     873                 : 
     874                 : static void
     875               0 : ne_read_master(nestegg * ctx, struct ebml_element_desc * desc)
     876                 : {
     877                 :   struct ebml_list * list;
     878                 :   struct ebml_list_node * node, * oldtail;
     879                 : 
     880               0 :   assert(desc->type == TYPE_MASTER && desc->flags & DESC_FLAG_MULTI);
     881                 : 
     882               0 :   ctx->log(ctx, NESTEGG_LOG_DEBUG, "multi master element %llx (%s)",
     883                 :            desc->id, desc->name);
     884                 : 
     885               0 :   list = (struct ebml_list *) (ctx->ancestor->data + desc->offset);
     886                 : 
     887               0 :   node = ne_pool_alloc(sizeof(*node), ctx->alloc_pool);
     888               0 :   node->id = desc->id;
     889               0 :   node->data = ne_pool_alloc(desc->size, ctx->alloc_pool);
     890                 : 
     891               0 :   oldtail = list->tail;
     892               0 :   if (oldtail)
     893               0 :     oldtail->next = node;
     894               0 :   list->tail = node;
     895               0 :   if (!list->head)
     896               0 :     list->head = node;
     897                 : 
     898               0 :   ctx->log(ctx, NESTEGG_LOG_DEBUG, " -> using data %p", node->data);
     899                 : 
     900               0 :   ne_ctx_push(ctx, desc->children, node->data);
     901               0 : }
     902                 : 
     903                 : static void
     904               0 : ne_read_single_master(nestegg * ctx, struct ebml_element_desc * desc)
     905                 : {
     906               0 :   assert(desc->type == TYPE_MASTER && !(desc->flags & DESC_FLAG_MULTI));
     907                 : 
     908               0 :   ctx->log(ctx, NESTEGG_LOG_DEBUG, "single master element %llx (%s)",
     909                 :            desc->id, desc->name);
     910               0 :   ctx->log(ctx, NESTEGG_LOG_DEBUG, " -> using data %p (%u)",
     911               0 :            ctx->ancestor->data + desc->offset, desc->offset);
     912                 : 
     913               0 :   ne_ctx_push(ctx, desc->children, ctx->ancestor->data + desc->offset);
     914               0 : }
     915                 : 
     916                 : static int
     917               0 : ne_read_simple(nestegg * ctx, struct ebml_element_desc * desc, size_t length)
     918                 : {
     919                 :   struct ebml_type * storage;
     920                 :   int r;
     921                 : 
     922               0 :   storage = (struct ebml_type *) (ctx->ancestor->data + desc->offset);
     923                 : 
     924               0 :   if (storage->read) {
     925               0 :     ctx->log(ctx, NESTEGG_LOG_DEBUG, "element %llx (%s) already read, skipping",
     926                 :              desc->id, desc->name);
     927               0 :     return 0;
     928                 :   }
     929                 : 
     930               0 :   storage->type = desc->type;
     931                 : 
     932               0 :   ctx->log(ctx, NESTEGG_LOG_DEBUG, "element %llx (%s) -> %p (%u)",
     933                 :            desc->id, desc->name, storage, desc->offset);
     934                 : 
     935               0 :   r = -1;
     936                 : 
     937               0 :   switch (desc->type) {
     938                 :   case TYPE_UINT:
     939               0 :     r = ne_read_uint(ctx->io, &storage->v.u, length);
     940               0 :     break;
     941                 :   case TYPE_FLOAT:
     942               0 :     r = ne_read_float(ctx->io, &storage->v.f, length);
     943               0 :     break;
     944                 :   case TYPE_INT:
     945               0 :     r = ne_read_int(ctx->io, &storage->v.i, length);
     946               0 :     break;
     947                 :   case TYPE_STRING:
     948               0 :     r = ne_read_string(ctx, &storage->v.s, length);
     949               0 :     break;
     950                 :   case TYPE_BINARY:
     951               0 :     r = ne_read_binary(ctx, &storage->v.b, length);
     952               0 :     break;
     953                 :   case TYPE_MASTER:
     954                 :   case TYPE_UNKNOWN:
     955               0 :     assert(0);
     956                 :     break;
     957                 :   }
     958                 : 
     959               0 :   if (r == 1)
     960               0 :     storage->read = 1;
     961                 : 
     962               0 :   return r;
     963                 : }
     964                 : 
     965                 : static int
     966               0 : ne_parse(nestegg * ctx, struct ebml_element_desc * top_level)
     967                 : {
     968                 :   int r;
     969                 :   int64_t * data_offset;
     970                 :   uint64_t id, size;
     971                 :   struct ebml_element_desc * element;
     972                 : 
     973                 :   /* loop until we need to return:
     974                 :      - hit suspend point
     975                 :      - parse complete
     976                 :      - error occurred */
     977                 : 
     978                 :   /* loop over elements at current level reading them if sublevel found,
     979                 :      push ctx onto stack and continue if sublevel ended, pop ctx off stack
     980                 :      and continue */
     981                 : 
     982               0 :   if (!ctx->ancestor)
     983               0 :     return -1;
     984                 : 
     985                 :   for (;;) {
     986               0 :     r = ne_peek_element(ctx, &id, &size);
     987               0 :     if (r != 1)
     988               0 :       break;
     989                 : 
     990               0 :     element = ne_find_element(id, ctx->ancestor->node);
     991               0 :     if (element) {
     992               0 :       if (element->flags & DESC_FLAG_SUSPEND) {
     993               0 :         assert(element->type == TYPE_BINARY);
     994               0 :         ctx->log(ctx, NESTEGG_LOG_DEBUG, "suspend parse at %llx", id);
     995               0 :         r = 1;
     996               0 :         break;
     997                 :       }
     998                 : 
     999               0 :       r = ne_read_element(ctx, &id, &size);
    1000               0 :       if (r != 1)
    1001               0 :         break;
    1002                 : 
    1003               0 :       if (element->flags & DESC_FLAG_OFFSET) {
    1004               0 :         data_offset = (int64_t *) (ctx->ancestor->data + element->data_offset);
    1005               0 :         *data_offset = ne_io_tell(ctx->io);
    1006               0 :         if (*data_offset < 0) {
    1007               0 :           r = -1;
    1008               0 :           break;
    1009                 :         }
    1010                 :       }
    1011                 : 
    1012               0 :       if (element->type == TYPE_MASTER) {
    1013               0 :         if (element->flags & DESC_FLAG_MULTI)
    1014               0 :           ne_read_master(ctx, element);
    1015                 :         else
    1016               0 :           ne_read_single_master(ctx, element);
    1017               0 :         continue;
    1018                 :       } else {
    1019               0 :         r = ne_read_simple(ctx, element, size);
    1020               0 :         if (r < 0)
    1021               0 :           break;
    1022                 :       }
    1023               0 :     } else if (ne_is_ancestor_element(id, ctx->ancestor->previous)) {
    1024               0 :       ctx->log(ctx, NESTEGG_LOG_DEBUG, "parent element %llx", id);
    1025               0 :       if (top_level && ctx->ancestor->node == top_level) {
    1026               0 :         ctx->log(ctx, NESTEGG_LOG_DEBUG, "*** parse about to back up past top_level");
    1027               0 :         r = 1;
    1028               0 :         break;
    1029                 :       }
    1030               0 :       ne_ctx_pop(ctx);
    1031                 :     } else {
    1032               0 :       r = ne_read_element(ctx, &id, &size);
    1033               0 :       if (r != 1)
    1034               0 :         break;
    1035                 : 
    1036               0 :       if (id != ID_VOID && id != ID_CRC32)
    1037               0 :         ctx->log(ctx, NESTEGG_LOG_DEBUG, "unknown element %llx", id);
    1038               0 :       r = ne_io_read_skip(ctx->io, size);
    1039               0 :       if (r != 1)
    1040               0 :         break;
    1041                 :     }
    1042               0 :   }
    1043                 : 
    1044               0 :   if (r != 1)
    1045               0 :     while (ctx->ancestor)
    1046               0 :       ne_ctx_pop(ctx);
    1047                 : 
    1048               0 :   return r;
    1049                 : }
    1050                 : 
    1051                 : static uint64_t
    1052               0 : ne_xiph_lace_value(unsigned char ** np)
    1053                 : {
    1054                 :   uint64_t lace;
    1055                 :   uint64_t value;
    1056               0 :   unsigned char * p = *np;
    1057                 : 
    1058               0 :   lace = *p++;
    1059               0 :   value = lace;
    1060               0 :   while (lace == 255) {
    1061               0 :     lace = *p++;
    1062               0 :     value += lace;
    1063                 :   }
    1064                 : 
    1065               0 :   *np = p;
    1066                 : 
    1067               0 :   return value;
    1068                 : }
    1069                 : 
    1070                 : static int
    1071               0 : ne_read_xiph_lace_value(nestegg_io * io, uint64_t * value, size_t * consumed)
    1072                 : {
    1073                 :   int r;
    1074                 :   uint64_t lace;
    1075                 : 
    1076               0 :   r = ne_read_uint(io, &lace, 1);
    1077               0 :   if (r != 1)
    1078               0 :     return r;
    1079               0 :   *consumed += 1;
    1080                 : 
    1081               0 :   *value = lace;
    1082               0 :   while (lace == 255) {
    1083               0 :     r = ne_read_uint(io, &lace, 1);
    1084               0 :     if (r != 1)
    1085               0 :       return r;
    1086               0 :     *consumed += 1;
    1087               0 :     *value += lace;
    1088                 :   }
    1089                 : 
    1090               0 :   return 1;
    1091                 : }
    1092                 : 
    1093                 : static int
    1094               0 : ne_read_xiph_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
    1095                 : {
    1096                 :   int r;
    1097               0 :   size_t i = 0;
    1098               0 :   uint64_t sum = 0;
    1099                 : 
    1100               0 :   while (--n) {
    1101               0 :     r = ne_read_xiph_lace_value(io, &sizes[i], read);
    1102               0 :     if (r != 1)
    1103               0 :       return r;
    1104               0 :     sum += sizes[i];
    1105               0 :     i += 1;
    1106                 :   }
    1107                 : 
    1108               0 :   if (*read + sum > block)
    1109               0 :     return -1;
    1110                 : 
    1111                 :   /* last frame is the remainder of the block */
    1112               0 :   sizes[i] = block - *read - sum;
    1113               0 :   return 1;
    1114                 : }
    1115                 : 
    1116                 : static int
    1117               0 : ne_read_ebml_lacing(nestegg_io * io, size_t block, size_t * read, uint64_t n, uint64_t * sizes)
    1118                 : {
    1119                 :   int r;
    1120                 :   uint64_t lace, sum, length;
    1121                 :   int64_t slace;
    1122               0 :   size_t i = 0;
    1123                 : 
    1124               0 :   r = ne_read_vint(io, &lace, &length);
    1125               0 :   if (r != 1)
    1126               0 :     return r;
    1127               0 :   *read += length;
    1128                 : 
    1129               0 :   sizes[i] = lace;
    1130               0 :   sum = sizes[i];
    1131                 : 
    1132               0 :   i += 1;
    1133               0 :   n -= 1;
    1134                 : 
    1135               0 :   while (--n) {
    1136               0 :     r = ne_read_svint(io, &slace, &length);
    1137               0 :     if (r != 1)
    1138               0 :       return r;
    1139               0 :     *read += length;
    1140               0 :     sizes[i] = sizes[i - 1] + slace;
    1141               0 :     sum += sizes[i];
    1142               0 :     i += 1;
    1143                 :   }
    1144                 : 
    1145               0 :   if (*read + sum > block)
    1146               0 :     return -1;
    1147                 : 
    1148                 :   /* last frame is the remainder of the block */
    1149               0 :   sizes[i] = block - *read - sum;
    1150               0 :   return 1;
    1151                 : }
    1152                 : 
    1153                 : static uint64_t
    1154               0 : ne_get_timecode_scale(nestegg * ctx)
    1155                 : {
    1156                 :   uint64_t scale;
    1157                 : 
    1158               0 :   if (ne_get_uint(ctx->segment.info.timecode_scale, &scale) != 0)
    1159               0 :     scale = 1000000;
    1160                 : 
    1161               0 :   return scale;
    1162                 : }
    1163                 : 
    1164                 : static struct track_entry *
    1165               0 : ne_find_track_entry(nestegg * ctx, unsigned int track)
    1166                 : {
    1167                 :   struct ebml_list_node * node;
    1168               0 :   unsigned int tracks = 0;
    1169                 : 
    1170               0 :   node = ctx->segment.tracks.track_entry.head;
    1171               0 :   while (node) {
    1172               0 :     assert(node->id == ID_TRACK_ENTRY);
    1173               0 :     if (track == tracks)
    1174               0 :       return node->data;
    1175               0 :     tracks += 1;
    1176               0 :     node = node->next;
    1177                 :   }
    1178                 : 
    1179               0 :   return NULL;
    1180                 : }
    1181                 : 
    1182                 : static int
    1183               0 : ne_read_block(nestegg * ctx, uint64_t block_id, uint64_t block_size, nestegg_packet ** data)
    1184                 : {
    1185                 :   int r;
    1186                 :   int64_t timecode, abs_timecode;
    1187                 :   nestegg_packet * pkt;
    1188                 :   struct cluster * cluster;
    1189                 :   struct frame * f, * last;
    1190                 :   struct track_entry * entry;
    1191                 :   double track_scale;
    1192                 :   uint64_t track, length, frame_sizes[256], cluster_tc, flags, frames, tc_scale, total;
    1193                 :   unsigned int i, lacing;
    1194               0 :   size_t consumed = 0;
    1195                 : 
    1196               0 :   *data = NULL;
    1197                 : 
    1198               0 :   if (block_size > LIMIT_BLOCK)
    1199               0 :     return -1;
    1200                 : 
    1201               0 :   r = ne_read_vint(ctx->io, &track, &length);
    1202               0 :   if (r != 1)
    1203               0 :     return r;
    1204                 : 
    1205               0 :   if (track == 0 || track > ctx->track_count)
    1206               0 :     return -1;
    1207                 : 
    1208               0 :   consumed += length;
    1209                 : 
    1210               0 :   r = ne_read_int(ctx->io, &timecode, 2);
    1211               0 :   if (r != 1)
    1212               0 :     return r;
    1213                 : 
    1214               0 :   consumed += 2;
    1215                 : 
    1216               0 :   r = ne_read_uint(ctx->io, &flags, 1);
    1217               0 :   if (r != 1)
    1218               0 :     return r;
    1219                 : 
    1220               0 :   consumed += 1;
    1221                 : 
    1222               0 :   frames = 0;
    1223                 : 
    1224                 :   /* flags are different between block and simpleblock, but lacing is
    1225                 :      encoded the same way */
    1226               0 :   lacing = (flags & BLOCK_FLAGS_LACING) >> 1;
    1227                 : 
    1228               0 :   switch (lacing) {
    1229                 :   case LACING_NONE:
    1230               0 :     frames = 1;
    1231               0 :     break;
    1232                 :   case LACING_XIPH:
    1233                 :   case LACING_FIXED:
    1234                 :   case LACING_EBML:
    1235               0 :     r = ne_read_uint(ctx->io, &frames, 1);
    1236               0 :     if (r != 1)
    1237               0 :       return r;
    1238               0 :     consumed += 1;
    1239               0 :     frames += 1;
    1240                 :   }
    1241                 : 
    1242               0 :   if (frames > 256)
    1243               0 :     return -1;
    1244                 : 
    1245               0 :   switch (lacing) {
    1246                 :   case LACING_NONE:
    1247               0 :     frame_sizes[0] = block_size - consumed;
    1248               0 :     break;
    1249                 :   case LACING_XIPH:
    1250               0 :     if (frames == 1)
    1251               0 :       return -1;
    1252               0 :     r = ne_read_xiph_lacing(ctx->io, block_size, &consumed, frames, frame_sizes);
    1253               0 :     if (r != 1)
    1254               0 :       return r;
    1255               0 :     break;
    1256                 :   case LACING_FIXED:
    1257               0 :     if ((block_size - consumed) % frames)
    1258               0 :       return -1;
    1259               0 :     for (i = 0; i < frames; ++i)
    1260               0 :       frame_sizes[i] = (block_size - consumed) / frames;
    1261               0 :     break;
    1262                 :   case LACING_EBML:
    1263               0 :     if (frames == 1)
    1264               0 :       return -1;
    1265               0 :     r = ne_read_ebml_lacing(ctx->io, block_size, &consumed, frames, frame_sizes);
    1266               0 :     if (r != 1)
    1267               0 :       return r;
    1268               0 :     break;
    1269                 :   }
    1270                 : 
    1271                 :   /* sanity check unlaced frame sizes against total block size. */
    1272               0 :   total = consumed;
    1273               0 :   for (i = 0; i < frames; ++i)
    1274               0 :     total += frame_sizes[i];
    1275               0 :   if (total > block_size)
    1276               0 :     return -1;
    1277                 : 
    1278               0 :   entry = ne_find_track_entry(ctx, track - 1);
    1279               0 :   if (!entry)
    1280               0 :     return -1;
    1281                 : 
    1282               0 :   track_scale = 1.0;
    1283                 : 
    1284               0 :   tc_scale = ne_get_timecode_scale(ctx);
    1285                 : 
    1286               0 :   assert(ctx->segment.cluster.tail->id == ID_CLUSTER);
    1287               0 :   cluster = ctx->segment.cluster.tail->data;
    1288               0 :   if (ne_get_uint(cluster->timecode, &cluster_tc) != 0)
    1289               0 :     return -1;
    1290                 : 
    1291               0 :   abs_timecode = timecode + cluster_tc;
    1292               0 :   if (abs_timecode < 0)
    1293               0 :     return -1;
    1294                 : 
    1295               0 :   pkt = ne_alloc(sizeof(*pkt));
    1296               0 :   pkt->track = track - 1;
    1297               0 :   pkt->timecode = abs_timecode * tc_scale * track_scale;
    1298                 : 
    1299               0 :   ctx->log(ctx, NESTEGG_LOG_DEBUG, "%sblock t %lld pts %f f %llx frames: %llu",
    1300               0 :            block_id == ID_BLOCK ? "" : "simple", pkt->track, pkt->timecode / 1e9, flags, frames);
    1301                 : 
    1302               0 :   last = NULL;
    1303               0 :   for (i = 0; i < frames; ++i) {
    1304               0 :     if (frame_sizes[i] > LIMIT_FRAME) {
    1305               0 :       nestegg_free_packet(pkt);
    1306               0 :       return -1;
    1307                 :     }
    1308               0 :     f = ne_alloc(sizeof(*f));
    1309               0 :     f->data = ne_alloc(frame_sizes[i]);
    1310               0 :     f->length = frame_sizes[i];
    1311               0 :     r = ne_io_read(ctx->io, f->data, frame_sizes[i]);
    1312               0 :     if (r != 1) {
    1313               0 :       free(f->data);
    1314               0 :       free(f);
    1315               0 :       nestegg_free_packet(pkt);
    1316               0 :       return -1;
    1317                 :     }
    1318                 : 
    1319               0 :     if (!last)
    1320               0 :       pkt->frame = f;
    1321                 :     else
    1322               0 :       last->next = f;
    1323               0 :     last = f;
    1324                 :   }
    1325                 : 
    1326               0 :   *data = pkt;
    1327                 : 
    1328               0 :   return 1;
    1329                 : }
    1330                 : 
    1331                 : static uint64_t
    1332               0 : ne_buf_read_id(unsigned char const * p, size_t length)
    1333                 : {
    1334               0 :   uint64_t id = 0;
    1335                 : 
    1336               0 :   while (length--) {
    1337               0 :     id <<= 8;
    1338               0 :     id |= *p++;
    1339                 :   }
    1340                 : 
    1341               0 :   return id;
    1342                 : }
    1343                 : 
    1344                 : static struct seek *
    1345               0 : ne_find_seek_for_id(struct ebml_list_node * seek_head, uint64_t id)
    1346                 : {
    1347                 :   struct ebml_list * head;
    1348                 :   struct ebml_list_node * seek;
    1349                 :   struct ebml_binary binary_id;
    1350                 :   struct seek * s;
    1351                 : 
    1352               0 :   while (seek_head) {
    1353               0 :     assert(seek_head->id == ID_SEEK_HEAD);
    1354               0 :     head = seek_head->data;
    1355               0 :     seek = head->head;
    1356                 : 
    1357               0 :     while (seek) {
    1358               0 :       assert(seek->id == ID_SEEK);
    1359               0 :       s = seek->data;
    1360                 : 
    1361               0 :       if (ne_get_binary(s->id, &binary_id) == 0 &&
    1362               0 :           ne_buf_read_id(binary_id.data, binary_id.length) == id)
    1363               0 :         return s;
    1364                 : 
    1365               0 :       seek = seek->next;
    1366                 :     }
    1367                 : 
    1368               0 :     seek_head = seek_head->next;
    1369                 :   }
    1370                 : 
    1371               0 :   return NULL;
    1372                 : }
    1373                 : 
    1374                 : static struct cue_point *
    1375               0 : ne_find_cue_point_for_tstamp(struct ebml_list_node * cue_point, uint64_t scale, uint64_t tstamp)
    1376                 : {
    1377                 :   uint64_t time;
    1378               0 :   struct cue_point * c, * prev = NULL;
    1379                 : 
    1380               0 :   while (cue_point) {
    1381               0 :     assert(cue_point->id == ID_CUE_POINT);
    1382               0 :     c = cue_point->data;
    1383                 : 
    1384               0 :     if (!prev)
    1385               0 :       prev = c;
    1386                 : 
    1387               0 :     if (ne_get_uint(c->time, &time) == 0 && time * scale > tstamp)
    1388               0 :       break;
    1389                 : 
    1390               0 :     prev = cue_point->data;
    1391               0 :     cue_point = cue_point->next;
    1392                 :   }
    1393                 : 
    1394               0 :   return prev;
    1395                 : }
    1396                 : 
    1397                 : static int
    1398               0 : ne_is_suspend_element(uint64_t id)
    1399                 : {
    1400                 :   /* this could search the tree of elements for DESC_FLAG_SUSPEND */
    1401               0 :   if (id == ID_SIMPLE_BLOCK || id == ID_BLOCK)
    1402               0 :     return 1;
    1403               0 :   return 0;
    1404                 : }
    1405                 : 
    1406                 : static void
    1407               0 : ne_null_log_callback(nestegg * ctx, unsigned int severity, char const * fmt, ...)
    1408                 : {
    1409               0 :   if (ctx && severity && fmt)
    1410               0 :     return;
    1411                 : }
    1412                 : 
    1413                 : int
    1414               0 : nestegg_init(nestegg ** context, nestegg_io io, nestegg_log callback)
    1415                 : {
    1416                 :   int r;
    1417                 :   uint64_t id, version, docversion;
    1418                 :   struct ebml_list_node * track;
    1419                 :   char * doctype;
    1420                 :   nestegg * ctx;
    1421                 : 
    1422               0 :   if (!(io.read && io.seek && io.tell))
    1423               0 :     return -1;
    1424                 : 
    1425               0 :   ctx = ne_alloc(sizeof(*ctx));
    1426                 : 
    1427               0 :   ctx->io = ne_alloc(sizeof(*ctx->io));
    1428               0 :   *ctx->io = io;
    1429               0 :   ctx->log = callback;
    1430               0 :   ctx->alloc_pool = ne_pool_init();
    1431                 : 
    1432               0 :   if (!ctx->log)
    1433               0 :     ctx->log = ne_null_log_callback;
    1434                 : 
    1435               0 :   r = ne_peek_element(ctx, &id, NULL);
    1436               0 :   if (r != 1) {
    1437               0 :     nestegg_destroy(ctx);
    1438               0 :     return -1;
    1439                 :   }
    1440                 : 
    1441               0 :   if (id != ID_EBML) {
    1442               0 :     nestegg_destroy(ctx);
    1443               0 :     return -1;
    1444                 :   }
    1445                 : 
    1446               0 :   ctx->log(ctx, NESTEGG_LOG_DEBUG, "ctx %p", ctx);
    1447                 : 
    1448               0 :   ne_ctx_push(ctx, ne_top_level_elements, ctx);
    1449                 : 
    1450               0 :   r = ne_parse(ctx, NULL);
    1451                 : 
    1452               0 :   if (r != 1) {
    1453               0 :     nestegg_destroy(ctx);
    1454               0 :     return -1;
    1455                 :   }
    1456                 : 
    1457               0 :   if (ne_get_uint(ctx->ebml.ebml_read_version, &version) != 0)
    1458               0 :     version = 1;
    1459               0 :   if (version != 1) {
    1460               0 :     nestegg_destroy(ctx);
    1461               0 :     return -1;
    1462                 :   }
    1463                 : 
    1464               0 :   if (ne_get_string(ctx->ebml.doctype, &doctype) != 0)
    1465               0 :     doctype = "matroska";
    1466               0 :   if (strcmp(doctype, "webm") != 0) {
    1467               0 :     nestegg_destroy(ctx);
    1468               0 :     return -1;
    1469                 :   }
    1470                 : 
    1471               0 :   if (ne_get_uint(ctx->ebml.doctype_read_version, &docversion) != 0)
    1472               0 :     docversion = 1;
    1473               0 :   if (docversion < 1 || docversion > 2) {
    1474               0 :     nestegg_destroy(ctx);
    1475               0 :     return -1;
    1476                 :   }
    1477                 : 
    1478               0 :   if (!ctx->segment.tracks.track_entry.head) {
    1479               0 :     nestegg_destroy(ctx);
    1480               0 :     return -1;
    1481                 :   }
    1482                 : 
    1483               0 :   track = ctx->segment.tracks.track_entry.head;
    1484               0 :   ctx->track_count = 0;
    1485                 : 
    1486               0 :   while (track) {
    1487               0 :     ctx->track_count += 1;
    1488               0 :     track = track->next;
    1489                 :   }
    1490                 : 
    1491               0 :   *context = ctx;
    1492                 : 
    1493               0 :   return 0;
    1494                 : }
    1495                 : 
    1496                 : void
    1497               0 : nestegg_destroy(nestegg * ctx)
    1498                 : {
    1499               0 :   while (ctx->ancestor)
    1500               0 :     ne_ctx_pop(ctx);
    1501               0 :   ne_pool_destroy(ctx->alloc_pool);
    1502               0 :   free(ctx->io);
    1503               0 :   free(ctx);
    1504               0 : }
    1505                 : 
    1506                 : int
    1507               0 : nestegg_duration(nestegg * ctx, uint64_t * duration)
    1508                 : {
    1509                 :   uint64_t tc_scale;
    1510                 :   double unscaled_duration;
    1511                 : 
    1512               0 :   if (ne_get_float(ctx->segment.info.duration, &unscaled_duration) != 0)
    1513               0 :     return -1;
    1514                 : 
    1515               0 :   tc_scale = ne_get_timecode_scale(ctx);
    1516                 : 
    1517               0 :   *duration = (uint64_t) (unscaled_duration * tc_scale);
    1518               0 :   return 0;
    1519                 : }
    1520                 : 
    1521                 : int
    1522               0 : nestegg_tstamp_scale(nestegg * ctx, uint64_t * scale)
    1523                 : {
    1524               0 :   *scale = ne_get_timecode_scale(ctx);
    1525               0 :   return 0;
    1526                 : }
    1527                 : 
    1528                 : int
    1529               0 : nestegg_track_count(nestegg * ctx, unsigned int * tracks)
    1530                 : {
    1531               0 :   *tracks = ctx->track_count;
    1532               0 :   return 0;
    1533                 : }
    1534                 : 
    1535                 : int
    1536               0 : nestegg_track_seek(nestegg * ctx, unsigned int track, uint64_t tstamp)
    1537                 : {
    1538                 :   int r;
    1539                 :   struct cue_point * cue_point;
    1540                 :   struct cue_track_positions * pos;
    1541                 :   struct saved_state state;
    1542                 :   struct seek * found;
    1543                 :   uint64_t seek_pos, tc_scale, t, id;
    1544               0 :   struct ebml_list_node * node = ctx->segment.cues.cue_point.head;
    1545                 : 
    1546                 :   /* If there are no cues loaded, check for cues element in the seek head
    1547                 :      and load it. */
    1548               0 :   if (!node) {
    1549               0 :     found = ne_find_seek_for_id(ctx->segment.seek_head.head, ID_CUES);
    1550               0 :     if (!found)
    1551               0 :       return -1;
    1552                 : 
    1553               0 :     if (ne_get_uint(found->position, &seek_pos) != 0)
    1554               0 :       return -1;
    1555                 : 
    1556                 :     /* Save old parser state. */
    1557               0 :     r = ne_ctx_save(ctx, &state);
    1558               0 :     if (r != 0)
    1559               0 :       return -1;
    1560                 : 
    1561                 :     /* Seek and set up parser state for segment-level element (Cues). */
    1562               0 :     r = ne_io_seek(ctx->io, ctx->segment_offset + seek_pos, NESTEGG_SEEK_SET);
    1563               0 :     if (r != 0)
    1564               0 :       return -1;
    1565               0 :     ctx->last_id = 0;
    1566               0 :     ctx->last_size = 0;
    1567                 : 
    1568               0 :     r = ne_read_element(ctx, &id, NULL);
    1569               0 :     if (r != 1)
    1570               0 :       return -1;
    1571                 : 
    1572               0 :     if (id != ID_CUES)
    1573               0 :       return -1;
    1574                 : 
    1575               0 :     ctx->ancestor = NULL;
    1576               0 :     ne_ctx_push(ctx, ne_top_level_elements, ctx);
    1577               0 :     ne_ctx_push(ctx, ne_segment_elements, &ctx->segment);
    1578               0 :     ne_ctx_push(ctx, ne_cues_elements, &ctx->segment.cues);
    1579                 :     /* parser will run until end of cues element. */
    1580               0 :     ctx->log(ctx, NESTEGG_LOG_DEBUG, "seek: parsing cue elements");
    1581               0 :     r = ne_parse(ctx, ne_cues_elements);
    1582               0 :     while (ctx->ancestor)
    1583               0 :       ne_ctx_pop(ctx);
    1584                 : 
    1585                 :     /* Reset parser state to original state and seek back to old position. */
    1586               0 :     if (ne_ctx_restore(ctx, &state) != 0)
    1587               0 :       return -1;
    1588                 : 
    1589               0 :     if (r < 0)
    1590               0 :       return -1;
    1591                 :   }
    1592                 : 
    1593               0 :   tc_scale = ne_get_timecode_scale(ctx);
    1594                 : 
    1595               0 :   cue_point = ne_find_cue_point_for_tstamp(ctx->segment.cues.cue_point.head, tc_scale, tstamp);
    1596               0 :   if (!cue_point)
    1597               0 :     return -1;
    1598                 : 
    1599               0 :   node = cue_point->cue_track_positions.head;
    1600                 : 
    1601               0 :   seek_pos = 0;
    1602                 : 
    1603               0 :   while (node) {
    1604               0 :     assert(node->id == ID_CUE_TRACK_POSITIONS);
    1605               0 :     pos = node->data;
    1606               0 :     if (ne_get_uint(pos->track, &t) == 0 && t - 1 == track) {
    1607               0 :       if (ne_get_uint(pos->cluster_position, &seek_pos) != 0)
    1608               0 :         return -1;
    1609               0 :       break;
    1610                 :     }
    1611               0 :     node = node->next;
    1612                 :   }
    1613                 : 
    1614                 :   /* Seek and set up parser state for segment-level element (Cluster). */
    1615               0 :   r = ne_io_seek(ctx->io, ctx->segment_offset + seek_pos, NESTEGG_SEEK_SET);
    1616               0 :   if (r != 0)
    1617               0 :     return -1;
    1618               0 :   ctx->last_id = 0;
    1619               0 :   ctx->last_size = 0;
    1620                 : 
    1621               0 :   while (ctx->ancestor)
    1622               0 :     ne_ctx_pop(ctx);
    1623                 : 
    1624               0 :   ne_ctx_push(ctx, ne_top_level_elements, ctx);
    1625               0 :   ne_ctx_push(ctx, ne_segment_elements, &ctx->segment);
    1626               0 :   ctx->log(ctx, NESTEGG_LOG_DEBUG, "seek: parsing cluster elements");
    1627               0 :   r = ne_parse(ctx, NULL);
    1628               0 :   if (r != 1)
    1629               0 :     return -1;
    1630                 : 
    1631               0 :   if (!ne_is_suspend_element(ctx->last_id))
    1632               0 :     return -1;
    1633                 : 
    1634               0 :   return 0;
    1635                 : }
    1636                 : 
    1637                 : int
    1638               0 : nestegg_track_type(nestegg * ctx, unsigned int track)
    1639                 : {
    1640                 :   struct track_entry * entry;
    1641                 :   uint64_t type;
    1642                 : 
    1643               0 :   entry = ne_find_track_entry(ctx, track);
    1644               0 :   if (!entry)
    1645               0 :     return -1;
    1646                 : 
    1647               0 :   if (ne_get_uint(entry->type, &type) != 0)
    1648               0 :     return -1;
    1649                 : 
    1650               0 :   if (type & TRACK_TYPE_VIDEO)
    1651               0 :     return NESTEGG_TRACK_VIDEO;
    1652                 : 
    1653               0 :   if (type & TRACK_TYPE_AUDIO)
    1654               0 :     return NESTEGG_TRACK_AUDIO;
    1655                 : 
    1656               0 :   return -1;
    1657                 : }
    1658                 : 
    1659                 : int
    1660               0 : nestegg_track_codec_id(nestegg * ctx, unsigned int track)
    1661                 : {
    1662                 :   char * codec_id;
    1663                 :   struct track_entry * entry;
    1664                 : 
    1665               0 :   entry = ne_find_track_entry(ctx, track);
    1666               0 :   if (!entry)
    1667               0 :     return -1;
    1668                 : 
    1669               0 :   if (ne_get_string(entry->codec_id, &codec_id) != 0)
    1670               0 :     return -1;
    1671                 : 
    1672               0 :   if (strcmp(codec_id, TRACK_ID_VP8) == 0)
    1673               0 :     return NESTEGG_CODEC_VP8;
    1674                 : 
    1675               0 :   if (strcmp(codec_id, TRACK_ID_VORBIS) == 0)
    1676               0 :     return NESTEGG_CODEC_VORBIS;
    1677                 : 
    1678               0 :   return -1;
    1679                 : }
    1680                 : 
    1681                 : int
    1682               0 : nestegg_track_codec_data_count(nestegg * ctx, unsigned int track,
    1683                 :                                unsigned int * count)
    1684                 : {
    1685                 :   struct track_entry * entry;
    1686                 :   struct ebml_binary codec_private;
    1687                 :   unsigned char * p;
    1688                 : 
    1689               0 :   *count = 0;
    1690                 : 
    1691               0 :   entry = ne_find_track_entry(ctx, track);
    1692               0 :   if (!entry)
    1693               0 :     return -1;
    1694                 : 
    1695               0 :   if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS)
    1696               0 :     return -1;
    1697                 : 
    1698               0 :   if (ne_get_binary(entry->codec_private, &codec_private) != 0)
    1699               0 :     return -1;
    1700                 : 
    1701               0 :   if (codec_private.length < 1)
    1702               0 :     return -1;
    1703                 : 
    1704               0 :   p = codec_private.data;
    1705               0 :   *count = *p + 1;
    1706                 : 
    1707               0 :   if (*count > 3)
    1708               0 :     return -1;
    1709                 : 
    1710               0 :   return 0;
    1711                 : }
    1712                 : 
    1713                 : int
    1714               0 : nestegg_track_codec_data(nestegg * ctx, unsigned int track, unsigned int item,
    1715                 :                          unsigned char ** data, size_t * length)
    1716                 : {
    1717                 :   struct track_entry * entry;
    1718                 :   struct ebml_binary codec_private;
    1719                 :   uint64_t sizes[3], total;
    1720                 :   unsigned char * p;
    1721                 :   unsigned int count, i;
    1722                 : 
    1723               0 :   *data = NULL;
    1724               0 :   *length = 0;
    1725                 : 
    1726               0 :   entry = ne_find_track_entry(ctx, track);
    1727               0 :   if (!entry)
    1728               0 :     return -1;
    1729                 : 
    1730               0 :   if (nestegg_track_codec_id(ctx, track) != NESTEGG_CODEC_VORBIS)
    1731               0 :     return -1;
    1732                 : 
    1733               0 :   if (ne_get_binary(entry->codec_private, &codec_private) != 0)
    1734               0 :     return -1;
    1735                 : 
    1736               0 :   p = codec_private.data;
    1737               0 :   count = *p++ + 1;
    1738                 : 
    1739               0 :   if (count > 3)
    1740               0 :     return -1;
    1741                 : 
    1742               0 :   i = 0;
    1743               0 :   total = 0;
    1744               0 :   while (--count) {
    1745               0 :     sizes[i] = ne_xiph_lace_value(&p);
    1746               0 :     total += sizes[i];
    1747               0 :     i += 1;
    1748                 :   }
    1749               0 :   sizes[i] = codec_private.length - total - (p - codec_private.data);
    1750                 : 
    1751               0 :   for (i = 0; i < item; ++i) {
    1752               0 :     if (sizes[i] > LIMIT_FRAME)
    1753               0 :       return -1;
    1754               0 :     p += sizes[i];
    1755                 :   }
    1756               0 :   *data = p;
    1757               0 :   *length = sizes[item];
    1758                 : 
    1759               0 :   return 0;
    1760                 : }
    1761                 : 
    1762                 : int
    1763               0 : nestegg_track_video_params(nestegg * ctx, unsigned int track,
    1764                 :                            nestegg_video_params * params)
    1765                 : {
    1766                 :   struct track_entry * entry;
    1767                 :   uint64_t value;
    1768                 : 
    1769               0 :   memset(params, 0, sizeof(*params));
    1770                 : 
    1771               0 :   entry = ne_find_track_entry(ctx, track);
    1772               0 :   if (!entry)
    1773               0 :     return -1;
    1774                 : 
    1775               0 :   if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_VIDEO)
    1776               0 :     return -1;
    1777                 : 
    1778               0 :   value = 0;
    1779               0 :   ne_get_uint(entry->video.stereo_mode, &value);
    1780               0 :   if (value <= NESTEGG_VIDEO_STEREO_TOP_BOTTOM ||
    1781               0 :       value == NESTEGG_VIDEO_STEREO_RIGHT_LEFT)
    1782               0 :     params->stereo_mode = value;
    1783                 : 
    1784               0 :   if (ne_get_uint(entry->video.pixel_width, &value) != 0)
    1785               0 :     return -1;
    1786               0 :   params->width = value;
    1787                 : 
    1788               0 :   if (ne_get_uint(entry->video.pixel_height, &value) != 0)
    1789               0 :     return -1;
    1790               0 :   params->height = value;
    1791                 : 
    1792               0 :   value = 0;
    1793               0 :   ne_get_uint(entry->video.pixel_crop_bottom, &value);
    1794               0 :   params->crop_bottom = value;
    1795                 : 
    1796               0 :   value = 0;
    1797               0 :   ne_get_uint(entry->video.pixel_crop_top, &value);
    1798               0 :   params->crop_top = value;
    1799                 : 
    1800               0 :   value = 0;
    1801               0 :   ne_get_uint(entry->video.pixel_crop_left, &value);
    1802               0 :   params->crop_left = value;
    1803                 : 
    1804               0 :   value = 0;
    1805               0 :   ne_get_uint(entry->video.pixel_crop_right, &value);
    1806               0 :   params->crop_right = value;
    1807                 : 
    1808               0 :   value = params->width;
    1809               0 :   ne_get_uint(entry->video.display_width, &value);
    1810               0 :   params->display_width = value;
    1811                 : 
    1812               0 :   value = params->height;
    1813               0 :   ne_get_uint(entry->video.display_height, &value);
    1814               0 :   params->display_height = value;
    1815                 : 
    1816               0 :   return 0;
    1817                 : }
    1818                 : 
    1819                 : int
    1820               0 : nestegg_track_audio_params(nestegg * ctx, unsigned int track,
    1821                 :                            nestegg_audio_params * params)
    1822                 : {
    1823                 :   struct track_entry * entry;
    1824                 :   uint64_t value;
    1825                 : 
    1826               0 :   memset(params, 0, sizeof(*params));
    1827                 : 
    1828               0 :   entry = ne_find_track_entry(ctx, track);
    1829               0 :   if (!entry)
    1830               0 :     return -1;
    1831                 : 
    1832               0 :   if (nestegg_track_type(ctx, track) != NESTEGG_TRACK_AUDIO)
    1833               0 :     return -1;
    1834                 : 
    1835               0 :   params->rate = 8000;
    1836               0 :   ne_get_float(entry->audio.sampling_frequency, &params->rate);
    1837                 : 
    1838               0 :   value = 1;
    1839               0 :   ne_get_uint(entry->audio.channels, &value);
    1840               0 :   params->channels = value;
    1841                 : 
    1842               0 :   value = 16;
    1843               0 :   ne_get_uint(entry->audio.bit_depth, &value);
    1844               0 :   params->depth = value;
    1845                 : 
    1846               0 :   return 0;
    1847                 : }
    1848                 : 
    1849                 : int
    1850               0 : nestegg_read_packet(nestegg * ctx, nestegg_packet ** pkt)
    1851                 : {
    1852                 :   int r;
    1853                 :   uint64_t id, size;
    1854                 : 
    1855               0 :   *pkt = NULL;
    1856                 : 
    1857                 :   for (;;) {
    1858               0 :     r = ne_peek_element(ctx, &id, &size);
    1859               0 :     if (r != 1)
    1860               0 :       return r;
    1861                 : 
    1862                 :     /* any suspend fields must be handled here */
    1863               0 :     if (ne_is_suspend_element(id)) {
    1864               0 :       r = ne_read_element(ctx, &id, &size);
    1865               0 :       if (r != 1)
    1866               0 :         return r;
    1867                 : 
    1868                 :       /* the only suspend fields are blocks and simple blocks, which we
    1869                 :          handle directly. */
    1870               0 :       r = ne_read_block(ctx, id, size, pkt);
    1871               0 :       return r;
    1872                 :     }
    1873                 : 
    1874               0 :     r =  ne_parse(ctx, NULL);
    1875               0 :     if (r != 1)
    1876               0 :       return r;
    1877               0 :   }
    1878                 : 
    1879                 :   return 1;
    1880                 : }
    1881                 : 
    1882                 : void
    1883               0 : nestegg_free_packet(nestegg_packet * pkt)
    1884                 : {
    1885                 :   struct frame * frame;
    1886                 : 
    1887               0 :   while (pkt->frame) {
    1888               0 :     frame = pkt->frame;
    1889               0 :     pkt->frame = frame->next;
    1890               0 :     free(frame->data);
    1891               0 :     free(frame);
    1892                 :   }
    1893                 : 
    1894               0 :  free(pkt);
    1895               0 : }
    1896                 : 
    1897                 : int
    1898               0 : nestegg_packet_track(nestegg_packet * pkt, unsigned int * track)
    1899                 : {
    1900               0 :   *track = pkt->track;
    1901               0 :   return 0;
    1902                 : }
    1903                 : 
    1904                 : int
    1905               0 : nestegg_packet_tstamp(nestegg_packet * pkt, uint64_t * tstamp)
    1906                 : {
    1907               0 :   *tstamp = pkt->timecode;
    1908               0 :   return 0;
    1909                 : }
    1910                 : 
    1911                 : int
    1912               0 : nestegg_packet_count(nestegg_packet * pkt, unsigned int * count)
    1913                 : {
    1914               0 :   struct frame * f = pkt->frame;
    1915                 : 
    1916               0 :   *count = 0;
    1917                 : 
    1918               0 :   while (f) {
    1919               0 :     *count += 1;
    1920               0 :     f = f->next;
    1921                 :   }
    1922                 : 
    1923               0 :   return 0;
    1924                 : }
    1925                 : 
    1926                 : int
    1927               0 : nestegg_packet_data(nestegg_packet * pkt, unsigned int item,
    1928                 :                     unsigned char ** data, size_t * length)
    1929                 : {
    1930               0 :   struct frame * f = pkt->frame;
    1931               0 :   unsigned int count = 0;
    1932                 : 
    1933               0 :   *data = NULL;
    1934               0 :   *length = 0;
    1935                 : 
    1936               0 :   while (f) {
    1937               0 :     if (count == item) {
    1938               0 :       *data = f->data;
    1939               0 :       *length = f->length;
    1940               0 :       return 0;
    1941                 :     }
    1942               0 :     count += 1;
    1943               0 :     f = f->next;
    1944                 :   }
    1945                 : 
    1946               0 :   return -1;
    1947                 : }

Generated by: LCOV version 1.7