Coverage Report

Created: 2026-06-10 06:19

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/vorbis/lib/info.c
Line
Count
Source
1
/********************************************************************
2
 *                                                                  *
3
 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.   *
4
 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS     *
5
 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
6
 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
7
 *                                                                  *
8
 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015             *
9
 * by the Xiph.Org Foundation https://xiph.org/                     *
10
 *                                                                  *
11
 ********************************************************************
12
13
 function: maintain the info structure, info <-> header packets
14
15
 ********************************************************************/
16
17
/* general handling of the header and the vorbis_info structure (and
18
   substructures) */
19
20
#include <stdlib.h>
21
#include <string.h>
22
#include <ogg/ogg.h>
23
#include "vorbis/codec.h"
24
#include "codec_internal.h"
25
#include "codebook.h"
26
#include "registry.h"
27
#include "window.h"
28
#include "psy.h"
29
#include "misc.h"
30
#include "os.h"
31
32
0
#define GENERAL_VENDOR_STRING "Xiph.Org libVorbis 1.3.7"
33
4.42k
#define ENCODE_VENDOR_STRING "Xiph.Org libVorbis I 20200704 (Reducing Environment)"
34
35
/* helpers */
36
11.0k
static void _v_writestring(oggpack_buffer *o,const char *s, int bytes){
37
38
218k
  while(bytes--){
39
207k
    oggpack_write(o,*s++,8);
40
207k
  }
41
11.0k
}
42
43
57.0k
static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
44
450k
  while(bytes--){
45
393k
    *buf++=oggpack_read(o,8);
46
393k
  }
47
57.0k
}
48
49
0
static int _v_toupper(int c) {
50
0
  return (c >= 'a' && c <= 'z') ? (c & ~('a' - 'A')) : c;
51
0
}
52
53
13.9k
void vorbis_comment_init(vorbis_comment *vc){
54
13.9k
  memset(vc,0,sizeof(*vc));
55
13.9k
}
56
57
2.21k
void vorbis_comment_add(vorbis_comment *vc,const char *comment){
58
2.21k
  vc->user_comments=_ogg_realloc(vc->user_comments,
59
2.21k
                            (vc->comments+2)*sizeof(*vc->user_comments));
60
2.21k
  vc->comment_lengths=_ogg_realloc(vc->comment_lengths,
61
2.21k
                                  (vc->comments+2)*sizeof(*vc->comment_lengths));
62
2.21k
  vc->comment_lengths[vc->comments]=strlen(comment);
63
2.21k
  vc->user_comments[vc->comments]=_ogg_malloc(vc->comment_lengths[vc->comments]+1);
64
2.21k
  strcpy(vc->user_comments[vc->comments], comment);
65
2.21k
  vc->comments++;
66
2.21k
  vc->user_comments[vc->comments]=NULL;
67
2.21k
}
68
69
2.21k
void vorbis_comment_add_tag(vorbis_comment *vc, const char *tag, const char *contents){
70
  /* Length for key and value +2 for = and \0 */
71
2.21k
  char *comment=_ogg_malloc(strlen(tag)+strlen(contents)+2);
72
2.21k
  strcpy(comment, tag);
73
2.21k
  strcat(comment, "=");
74
2.21k
  strcat(comment, contents);
75
2.21k
  vorbis_comment_add(vc, comment);
76
2.21k
  _ogg_free(comment);
77
2.21k
}
78
79
/* This is more or less the same as strncasecmp - but that doesn't exist
80
 * everywhere, and this is a fairly trivial function, so we include it */
81
0
static int tagcompare(const char *s1, const char *s2, int n){
82
0
  int c=0;
83
0
  while(c < n){
84
0
    if(_v_toupper(s1[c]) != _v_toupper(s2[c]))
85
0
      return !0;
86
0
    c++;
87
0
  }
88
0
  return 0;
89
0
}
90
91
0
char *vorbis_comment_query(vorbis_comment *vc, const char *tag, int count){
92
0
  long i;
93
0
  int found = 0;
94
0
  int taglen = strlen(tag)+1; /* +1 for the = we append */
95
0
  char *fulltag = _ogg_malloc(taglen+1);
96
97
0
  strcpy(fulltag, tag);
98
0
  strcat(fulltag, "=");
99
100
0
  for(i=0;i<vc->comments;i++){
101
0
    if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
102
0
      if(count == found) {
103
        /* We return a pointer to the data, not a copy */
104
0
        _ogg_free(fulltag);
105
0
        return vc->user_comments[i] + taglen;
106
0
      } else {
107
0
        found++;
108
0
      }
109
0
    }
110
0
  }
111
0
  _ogg_free(fulltag);
112
0
  return NULL; /* didn't find anything */
113
0
}
114
115
0
int vorbis_comment_query_count(vorbis_comment *vc, const char *tag){
116
0
  int i,count=0;
117
0
  int taglen = strlen(tag)+1; /* +1 for the = we append */
118
0
  char *fulltag = _ogg_malloc(taglen+1);
119
0
  strcpy(fulltag,tag);
120
0
  strcat(fulltag, "=");
121
122
0
  for(i=0;i<vc->comments;i++){
123
0
    if(!tagcompare(vc->user_comments[i], fulltag, taglen))
124
0
      count++;
125
0
  }
126
127
0
  _ogg_free(fulltag);
128
0
  return count;
129
0
}
130
131
17.2k
void vorbis_comment_clear(vorbis_comment *vc){
132
17.2k
  if(vc){
133
17.2k
    long i;
134
17.2k
    if(vc->user_comments){
135
17.7k
      for(i=0;i<vc->comments;i++)
136
4.96k
        if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
137
12.7k
      _ogg_free(vc->user_comments);
138
12.7k
    }
139
17.2k
    if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
140
17.2k
    if(vc->vendor)_ogg_free(vc->vendor);
141
17.2k
    memset(vc,0,sizeof(*vc));
142
17.2k
  }
143
17.2k
}
144
145
/* blocksize 0 is guaranteed to be short, 1 is guaranteed to be long.
146
   They may be equal, but short will never ge greater than long */
147
0
int vorbis_info_blocksize(vorbis_info *vi,int zo){
148
0
  codec_setup_info *ci = vi->codec_setup;
149
0
  return ci ? ci->blocksizes[zo] : -1;
150
0
}
151
152
/* used by synthesis, which has a full, alloced vi */
153
13.9k
void vorbis_info_init(vorbis_info *vi){
154
13.9k
  memset(vi,0,sizeof(*vi));
155
13.9k
  vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info));
156
13.9k
}
157
158
18.5k
void vorbis_info_clear(vorbis_info *vi){
159
18.5k
  codec_setup_info     *ci=vi->codec_setup;
160
18.5k
  int i;
161
162
18.5k
  if(ci){
163
164
28.3k
    for(i=0;i<ci->modes;i++)
165
14.4k
      if(ci->mode_param[i])_ogg_free(ci->mode_param[i]);
166
167
29.0k
    for(i=0;i<ci->maps;i++) /* unpack does the range checking */
168
15.1k
      if(ci->map_param[i]) /* this may be cleaning up an aborted
169
                              unpack, in which case the below type
170
                              cannot be trusted */
171
13.7k
        _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
172
173
30.9k
    for(i=0;i<ci->floors;i++) /* unpack does the range checking */
174
16.9k
      if(ci->floor_param[i]) /* this may be cleaning up an aborted
175
                                unpack, in which case the below type
176
                                cannot be trusted */
177
14.5k
        _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
178
179
30.2k
    for(i=0;i<ci->residues;i++) /* unpack does the range checking */
180
16.2k
      if(ci->residue_param[i]) /* this may be cleaning up an aborted
181
                                  unpack, in which case the below type
182
                                  cannot be trusted */
183
15.0k
        _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
184
185
139k
    for(i=0;i<ci->books;i++){
186
125k
      if(ci->book_param[i]){
187
        /* knows if the book was not alloced */
188
78.8k
        vorbis_staticbook_destroy(ci->book_param[i]);
189
78.8k
      }
190
125k
      if(ci->fullbooks)
191
78.8k
        vorbis_book_clear(ci->fullbooks+i);
192
125k
      if(ci->decbooks)
193
46.0k
        vorbis_decbook_clear(ci->decbooks+i);
194
125k
    }
195
13.9k
    if(ci->fullbooks)
196
2.21k
        _ogg_free(ci->fullbooks);
197
13.9k
    if(ci->decbooks)
198
10.3k
      _ogg_free(ci->decbooks);
199
200
21.9k
    for(i=0;i<ci->psys;i++)
201
8.04k
      _vi_psy_free(ci->psy_param[i]);
202
203
13.9k
    _ogg_free(ci);
204
13.9k
  }
205
206
18.5k
  memset(vi,0,sizeof(*vi));
207
18.5k
}
208
209
/* Header packing/unpacking ********************************************/
210
211
11.2k
static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
212
11.2k
  codec_setup_info     *ci=vi->codec_setup;
213
11.2k
  int bs;
214
11.2k
  if(!ci)return(OV_EFAULT);
215
216
11.2k
  vi->version=oggpack_read(opb,32);
217
11.2k
  if(vi->version!=0)return(OV_EVERSION);
218
219
11.1k
  vi->channels=oggpack_read(opb,8);
220
11.1k
  vi->rate=oggpack_read(opb,32);
221
222
11.1k
  vi->bitrate_upper=(ogg_int32_t)oggpack_read(opb,32);
223
11.1k
  vi->bitrate_nominal=(ogg_int32_t)oggpack_read(opb,32);
224
11.1k
  vi->bitrate_lower=(ogg_int32_t)oggpack_read(opb,32);
225
226
11.1k
  bs = oggpack_read(opb,4);
227
11.1k
  if(bs<0)goto err_out;
228
11.1k
  ci->blocksizes[0]=1<<bs;
229
11.1k
  bs = oggpack_read(opb,4);
230
11.1k
  if(bs<0)goto err_out;
231
11.1k
  ci->blocksizes[1]=1<<bs;
232
233
11.1k
  if(vi->rate<1)goto err_out;
234
11.1k
  if(vi->channels<1)goto err_out;
235
11.1k
  if(ci->blocksizes[0]<64)goto err_out;
236
11.1k
  if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
237
11.1k
  if(ci->blocksizes[1]>8192)goto err_out;
238
239
11.1k
  if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
240
241
11.1k
  return(0);
242
72
 err_out:
243
72
  vorbis_info_clear(vi);
244
72
  return(OV_EBADHEADER);
245
11.1k
}
246
247
10.7k
static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
248
10.7k
  int i;
249
10.7k
  int vendorlen=oggpack_read(opb,32);
250
10.7k
  if(vendorlen<0)goto err_out;
251
10.7k
  if(vendorlen>opb->storage-8)goto err_out;
252
10.6k
  vc->vendor=_ogg_calloc(vendorlen+1,1);
253
10.6k
  _v_readstring(opb,vc->vendor,vendorlen);
254
10.6k
  i=oggpack_read(opb,32);
255
10.6k
  if(i<0)goto err_out;
256
10.6k
  if(i>((opb->storage-oggpack_bytes(opb))>>2))goto err_out;
257
10.5k
  vc->comments=i;
258
10.5k
  vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
259
10.5k
  vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
260
261
12.3k
  for(i=0;i<vc->comments;i++){
262
1.84k
    int len=oggpack_read(opb,32);
263
1.84k
    if(len<0)goto err_out;
264
1.80k
    if(len>opb->storage-oggpack_bytes(opb))goto err_out;
265
1.74k
    vc->comment_lengths[i]=len;
266
1.74k
    vc->user_comments[i]=_ogg_calloc(len+1,1);
267
1.74k
    _v_readstring(opb,vc->user_comments[i],len);
268
1.74k
  }
269
10.4k
  if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
270
271
10.4k
  return(0);
272
307
 err_out:
273
307
  vorbis_comment_clear(vc);
274
307
  return(OV_EBADHEADER);
275
10.4k
}
276
277
/* all of the real encoding details are here.  The modes, books,
278
   everything */
279
10.4k
static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
280
10.4k
  codec_setup_info     *ci=vi->codec_setup;
281
10.4k
  int i;
282
283
  /* codebooks */
284
10.4k
  ci->books=oggpack_read(opb,8)+1;
285
10.4k
  if(ci->books<=0)goto err_out;
286
10.4k
  ci->decbooks=_ogg_calloc(ci->books,sizeof(*ci->decbooks));
287
10.4k
  if(ci->decbooks==NULL)goto err_out;
288
30.0k
  for(i=0;i<ci->books;i++){
289
20.5k
    if(vorbis_decbook_unpack(ci->decbooks+i,opb)<0)goto err_out;
290
20.5k
  }
291
292
  /* time backend settings; hooks are unused */
293
9.52k
  {
294
9.52k
    int times=oggpack_read(opb,6)+1;
295
9.52k
    if(times<=0)goto err_out;
296
19.5k
    for(i=0;i<times;i++){
297
10.1k
      int test=oggpack_read(opb,16);
298
10.1k
      if(test<0 || test>=VI_TIMEB)goto err_out;
299
10.1k
    }
300
9.49k
  }
301
302
  /* floor backend settings */
303
9.39k
  ci->floors=oggpack_read(opb,6)+1;
304
9.39k
  if(ci->floors<=0)goto err_out;
305
19.8k
  for(i=0;i<ci->floors;i++){
306
10.6k
    ci->floor_type[i]=oggpack_read(opb,16);
307
10.6k
    if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
308
10.5k
    ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb);
309
10.5k
    if(!ci->floor_param[i])goto err_out;
310
10.5k
  }
311
312
  /* residue backend settings */
313
9.21k
  ci->residues=oggpack_read(opb,6)+1;
314
9.21k
  if(ci->residues<=0)goto err_out;
315
20.2k
  for(i=0;i<ci->residues;i++){
316
11.1k
    ci->residue_type[i]=oggpack_read(opb,16);
317
11.1k
    if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
318
11.1k
    ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
319
11.1k
    if(!ci->residue_param[i])goto err_out;
320
11.1k
  }
321
322
  /* map backend settings */
323
9.08k
  ci->maps=oggpack_read(opb,6)+1;
324
9.08k
  if(ci->maps<=0)goto err_out;
325
18.7k
  for(i=0;i<ci->maps;i++){
326
9.80k
    ci->map_type[i]=oggpack_read(opb,16);
327
9.80k
    if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
328
9.78k
    ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb);
329
9.78k
    if(!ci->map_param[i])goto err_out;
330
9.78k
  }
331
332
  /* mode settings */
333
8.96k
  ci->modes=oggpack_read(opb,6)+1;
334
8.96k
  if(ci->modes<=0)goto err_out;
335
19.0k
  for(i=0;i<ci->modes;i++){
336
10.1k
    ci->mode_param[i]=_ogg_calloc(1,sizeof(*ci->mode_param[i]));
337
10.1k
    ci->mode_param[i]->blockflag=oggpack_read(opb,1);
338
10.1k
    ci->mode_param[i]->windowtype=oggpack_read(opb,16);
339
10.1k
    ci->mode_param[i]->transformtype=oggpack_read(opb,16);
340
10.1k
    ci->mode_param[i]->mapping=oggpack_read(opb,8);
341
342
10.1k
    if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
343
10.1k
    if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
344
10.1k
    if(ci->mode_param[i]->mapping>=ci->maps)goto err_out;
345
10.1k
    if(ci->mode_param[i]->mapping<0)goto err_out;
346
10.1k
  }
347
348
8.92k
  if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
349
350
8.92k
  return(0);
351
1.53k
 err_out:
352
1.53k
  vorbis_info_clear(vi);
353
1.53k
  return(OV_EBADHEADER);
354
8.92k
}
355
356
/* Is this packet a vorbis ID header? */
357
14.3k
int vorbis_synthesis_idheader(ogg_packet *op){
358
14.3k
  oggpack_buffer opb;
359
14.3k
  char buffer[6];
360
361
14.3k
  if(op){
362
14.3k
    oggpack_readinit(&opb,op->packet,op->bytes);
363
364
14.3k
    if(!op->b_o_s)
365
999
      return(0); /* Not the initial packet */
366
367
13.3k
    if(oggpack_read(&opb,8) != 1)
368
1.27k
      return 0; /* not an ID header */
369
370
12.0k
    memset(buffer,0,6);
371
12.0k
    _v_readstring(&opb,buffer,6);
372
12.0k
    if(memcmp(buffer,"vorbis",6))
373
843
      return 0; /* not vorbis */
374
375
11.2k
    return 1;
376
12.0k
  }
377
378
0
  return 0;
379
14.3k
}
380
381
/* The Vorbis header is in three packets; the initial small packet in
382
   the first page that identifies basic parameters, a second packet
383
   with bitstream comments and a third packet that holds the
384
   codebook. */
385
386
32.5k
int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){
387
32.5k
  oggpack_buffer opb;
388
389
32.5k
  if(op){
390
32.5k
    oggpack_readinit(&opb,op->packet,op->bytes);
391
392
    /* Which of the three types of header is this? */
393
    /* Also verify header-ness, vorbis */
394
32.5k
    {
395
32.5k
      char buffer[6];
396
32.5k
      int packtype=oggpack_read(&opb,8);
397
32.5k
      memset(buffer,0,6);
398
32.5k
      _v_readstring(&opb,buffer,6);
399
32.5k
      if(memcmp(buffer,"vorbis",6)){
400
        /* not a vorbis header */
401
32
        return(OV_ENOTVORBIS);
402
32
      }
403
32.5k
      switch(packtype){
404
11.2k
      case 0x01: /* least significant *bit* is read first */
405
11.2k
        if(!op->b_o_s){
406
          /* Not the initial packet */
407
1
          return(OV_EBADHEADER);
408
1
        }
409
11.2k
        if(vi->rate!=0){
410
          /* previously initialized info header */
411
29
          return(OV_EBADHEADER);
412
29
        }
413
414
11.2k
        return(_vorbis_unpack_info(vi,&opb));
415
416
10.7k
      case 0x03: /* least significant *bit* is read first */
417
10.7k
        if(vi->rate==0){
418
          /* um... we didn't get the initial header */
419
0
          return(OV_EBADHEADER);
420
0
        }
421
10.7k
        if(vc->vendor!=NULL){
422
          /* previously initialized comment header */
423
1
          return(OV_EBADHEADER);
424
1
        }
425
426
10.7k
        return(_vorbis_unpack_comment(vc,&opb));
427
428
10.4k
      case 0x05: /* least significant *bit* is read first */
429
10.4k
        if(vi->rate==0 || vc->vendor==NULL){
430
          /* um... we didn;t get the initial header or comments yet */
431
15
          return(OV_EBADHEADER);
432
15
        }
433
10.4k
        if(vi->codec_setup==NULL){
434
          /* improperly initialized vorbis_info */
435
0
          return(OV_EFAULT);
436
0
        }
437
10.4k
        if(((codec_setup_info *)vi->codec_setup)->books>0){
438
          /* previously initialized setup header */
439
0
          return(OV_EBADHEADER);
440
0
        }
441
442
10.4k
        return(_vorbis_unpack_books(vi,&opb));
443
444
2
      default:
445
        /* Not a valid vorbis header type */
446
2
        return(OV_EBADHEADER);
447
0
        break;
448
32.5k
      }
449
32.5k
    }
450
32.5k
  }
451
0
  return(OV_EBADHEADER);
452
32.5k
}
453
454
/* pack side **********************************************************/
455
456
2.21k
static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){
457
2.21k
  codec_setup_info     *ci=vi->codec_setup;
458
2.21k
  if(!ci||
459
2.21k
     ci->blocksizes[0]<64||
460
2.21k
     ci->blocksizes[1]<ci->blocksizes[0]){
461
0
    return(OV_EFAULT);
462
0
  }
463
464
  /* preamble */
465
2.21k
  oggpack_write(opb,0x01,8);
466
2.21k
  _v_writestring(opb,"vorbis", 6);
467
468
  /* basic information about the stream */
469
2.21k
  oggpack_write(opb,0x00,32);
470
2.21k
  oggpack_write(opb,vi->channels,8);
471
2.21k
  oggpack_write(opb,vi->rate,32);
472
473
2.21k
  oggpack_write(opb,vi->bitrate_upper,32);
474
2.21k
  oggpack_write(opb,vi->bitrate_nominal,32);
475
2.21k
  oggpack_write(opb,vi->bitrate_lower,32);
476
477
2.21k
  oggpack_write(opb,ov_ilog(ci->blocksizes[0]-1),4);
478
2.21k
  oggpack_write(opb,ov_ilog(ci->blocksizes[1]-1),4);
479
2.21k
  oggpack_write(opb,1,1);
480
481
2.21k
  return(0);
482
2.21k
}
483
484
2.21k
static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){
485
2.21k
  int bytes = strlen(ENCODE_VENDOR_STRING);
486
487
  /* preamble */
488
2.21k
  oggpack_write(opb,0x03,8);
489
2.21k
  _v_writestring(opb,"vorbis", 6);
490
491
  /* vendor */
492
2.21k
  oggpack_write(opb,bytes,32);
493
2.21k
  _v_writestring(opb,ENCODE_VENDOR_STRING, bytes);
494
495
  /* comments */
496
497
2.21k
  oggpack_write(opb,vc->comments,32);
498
2.21k
  if(vc->comments){
499
2.21k
    int i;
500
4.42k
    for(i=0;i<vc->comments;i++){
501
2.21k
      if(vc->user_comments[i]){
502
2.21k
        oggpack_write(opb,vc->comment_lengths[i],32);
503
2.21k
        _v_writestring(opb,vc->user_comments[i], vc->comment_lengths[i]);
504
2.21k
      }else{
505
0
        oggpack_write(opb,0,32);
506
0
      }
507
2.21k
    }
508
2.21k
  }
509
2.21k
  oggpack_write(opb,1,1);
510
511
2.21k
  return(0);
512
2.21k
}
513
514
2.21k
static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){
515
2.21k
  codec_setup_info     *ci=vi->codec_setup;
516
2.21k
  int i;
517
2.21k
  if(!ci)return(OV_EFAULT);
518
519
2.21k
  oggpack_write(opb,0x05,8);
520
2.21k
  _v_writestring(opb,"vorbis", 6);
521
522
  /* books */
523
2.21k
  oggpack_write(opb,ci->books-1,8);
524
81.1k
  for(i=0;i<ci->books;i++)
525
78.8k
    if(vorbis_staticbook_pack(ci->book_param[i],opb))goto err_out;
526
527
  /* times; hook placeholders */
528
2.21k
  oggpack_write(opb,0,6);
529
2.21k
  oggpack_write(opb,0,16);
530
531
  /* floors */
532
2.21k
  oggpack_write(opb,ci->floors-1,6);
533
6.33k
  for(i=0;i<ci->floors;i++){
534
4.12k
    oggpack_write(opb,ci->floor_type[i],16);
535
4.12k
    if(_floor_P[ci->floor_type[i]]->pack)
536
4.12k
      _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb);
537
0
    else
538
0
      goto err_out;
539
4.12k
  }
540
541
  /* residues */
542
2.21k
  oggpack_write(opb,ci->residues-1,6);
543
6.23k
  for(i=0;i<ci->residues;i++){
544
4.02k
    oggpack_write(opb,ci->residue_type[i],16);
545
4.02k
    _residue_P[ci->residue_type[i]]->pack(ci->residue_param[i],opb);
546
4.02k
  }
547
548
  /* maps */
549
2.21k
  oggpack_write(opb,ci->maps-1,6);
550
6.23k
  for(i=0;i<ci->maps;i++){
551
4.02k
    oggpack_write(opb,ci->map_type[i],16);
552
4.02k
    _mapping_P[ci->map_type[i]]->pack(vi,ci->map_param[i],opb);
553
4.02k
  }
554
555
  /* modes */
556
2.21k
  oggpack_write(opb,ci->modes-1,6);
557
6.23k
  for(i=0;i<ci->modes;i++){
558
4.02k
    oggpack_write(opb,ci->mode_param[i]->blockflag,1);
559
4.02k
    oggpack_write(opb,ci->mode_param[i]->windowtype,16);
560
4.02k
    oggpack_write(opb,ci->mode_param[i]->transformtype,16);
561
4.02k
    oggpack_write(opb,ci->mode_param[i]->mapping,8);
562
4.02k
  }
563
2.21k
  oggpack_write(opb,1,1);
564
565
2.21k
  return(0);
566
0
err_out:
567
0
  return(-1);
568
2.21k
}
569
570
int vorbis_commentheader_out(vorbis_comment *vc,
571
0
                                          ogg_packet *op){
572
573
0
  oggpack_buffer opb;
574
575
0
  oggpack_writeinit(&opb);
576
0
  if(_vorbis_pack_comment(&opb,vc)){
577
0
    oggpack_writeclear(&opb);
578
0
    return OV_EIMPL;
579
0
  }
580
581
0
  op->packet = _ogg_malloc(oggpack_bytes(&opb));
582
0
  memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));
583
584
0
  op->bytes=oggpack_bytes(&opb);
585
0
  op->b_o_s=0;
586
0
  op->e_o_s=0;
587
0
  op->granulepos=0;
588
0
  op->packetno=1;
589
590
0
  oggpack_writeclear(&opb);
591
0
  return 0;
592
0
}
593
594
int vorbis_analysis_headerout(vorbis_dsp_state *v,
595
                              vorbis_comment *vc,
596
                              ogg_packet *op,
597
                              ogg_packet *op_comm,
598
2.21k
                              ogg_packet *op_code){
599
2.21k
  int ret=OV_EIMPL;
600
2.21k
  vorbis_info *vi=v->vi;
601
2.21k
  oggpack_buffer opb;
602
2.21k
  private_state *b=v->backend_state;
603
604
2.21k
  if(!b||vi->channels<=0||vi->channels>256){
605
0
    b = NULL;
606
0
    ret=OV_EFAULT;
607
0
    goto err_out;
608
0
  }
609
610
  /* first header packet **********************************************/
611
612
2.21k
  oggpack_writeinit(&opb);
613
2.21k
  if(_vorbis_pack_info(&opb,vi))goto err_out;
614
615
  /* build the packet */
616
2.21k
  if(b->header)_ogg_free(b->header);
617
2.21k
  b->header=_ogg_malloc(oggpack_bytes(&opb));
618
2.21k
  memcpy(b->header,opb.buffer,oggpack_bytes(&opb));
619
2.21k
  op->packet=b->header;
620
2.21k
  op->bytes=oggpack_bytes(&opb);
621
2.21k
  op->b_o_s=1;
622
2.21k
  op->e_o_s=0;
623
2.21k
  op->granulepos=0;
624
2.21k
  op->packetno=0;
625
626
  /* second header packet (comments) **********************************/
627
628
2.21k
  oggpack_reset(&opb);
629
2.21k
  if(_vorbis_pack_comment(&opb,vc))goto err_out;
630
631
2.21k
  if(b->header1)_ogg_free(b->header1);
632
2.21k
  b->header1=_ogg_malloc(oggpack_bytes(&opb));
633
2.21k
  memcpy(b->header1,opb.buffer,oggpack_bytes(&opb));
634
2.21k
  op_comm->packet=b->header1;
635
2.21k
  op_comm->bytes=oggpack_bytes(&opb);
636
2.21k
  op_comm->b_o_s=0;
637
2.21k
  op_comm->e_o_s=0;
638
2.21k
  op_comm->granulepos=0;
639
2.21k
  op_comm->packetno=1;
640
641
  /* third header packet (modes/codebooks) ****************************/
642
643
2.21k
  oggpack_reset(&opb);
644
2.21k
  if(_vorbis_pack_books(&opb,vi))goto err_out;
645
646
2.21k
  if(b->header2)_ogg_free(b->header2);
647
2.21k
  b->header2=_ogg_malloc(oggpack_bytes(&opb));
648
2.21k
  memcpy(b->header2,opb.buffer,oggpack_bytes(&opb));
649
2.21k
  op_code->packet=b->header2;
650
2.21k
  op_code->bytes=oggpack_bytes(&opb);
651
2.21k
  op_code->b_o_s=0;
652
2.21k
  op_code->e_o_s=0;
653
2.21k
  op_code->granulepos=0;
654
2.21k
  op_code->packetno=2;
655
656
2.21k
  oggpack_writeclear(&opb);
657
2.21k
  return(0);
658
0
 err_out:
659
0
  memset(op,0,sizeof(*op));
660
0
  memset(op_comm,0,sizeof(*op_comm));
661
0
  memset(op_code,0,sizeof(*op_code));
662
663
0
  if(b){
664
0
    if(vi->channels>0)oggpack_writeclear(&opb);
665
0
    if(b->header)_ogg_free(b->header);
666
0
    if(b->header1)_ogg_free(b->header1);
667
0
    if(b->header2)_ogg_free(b->header2);
668
0
    b->header=NULL;
669
0
    b->header1=NULL;
670
0
    b->header2=NULL;
671
0
  }
672
0
  return(ret);
673
2.21k
}
674
675
0
double vorbis_granule_time(vorbis_dsp_state *v,ogg_int64_t granulepos){
676
0
  if(granulepos == -1) return -1;
677
678
  /* We're not guaranteed a 64 bit unsigned type everywhere, so we
679
     have to put the unsigned granpo in a signed type. */
680
0
  if(granulepos>=0){
681
0
    return((double)granulepos/v->vi->rate);
682
0
  }else{
683
0
    ogg_int64_t granuleoff=0xffffffff;
684
0
    granuleoff<<=31;
685
0
    granuleoff|=0x7ffffffff;
686
0
    return(((double)granulepos+2+granuleoff+granuleoff)/v->vi->rate);
687
0
  }
688
0
}
689
690
0
const char *vorbis_version_string(void){
691
0
  return GENERAL_VENDOR_STRING;
692
0
}