Coverage Report

Created: 2026-07-25 07:52

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
0
#define ENCODE_VENDOR_STRING "Xiph.Org libVorbis I 20200704 (Reducing Environment)"
34
35
/* helpers */
36
0
static void _v_writestring(oggpack_buffer *o,const char *s, int bytes){
37
38
0
  while(bytes--){
39
0
    oggpack_write(o,*s++,8);
40
0
  }
41
0
}
42
43
7.03k
static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
44
60.0k
  while(bytes--){
45
52.9k
    *buf++=oggpack_read(o,8);
46
52.9k
  }
47
7.03k
}
48
49
0
static int _v_toupper(int c) {
50
0
  return (c >= 'a' && c <= 'z') ? (c & ~('a' - 'A')) : c;
51
0
}
52
53
1.88k
void vorbis_comment_init(vorbis_comment *vc){
54
1.88k
  memset(vc,0,sizeof(*vc));
55
1.88k
}
56
57
0
void vorbis_comment_add(vorbis_comment *vc,const char *comment){
58
0
  vc->user_comments=_ogg_realloc(vc->user_comments,
59
0
                            (vc->comments+2)*sizeof(*vc->user_comments));
60
0
  vc->comment_lengths=_ogg_realloc(vc->comment_lengths,
61
0
                                  (vc->comments+2)*sizeof(*vc->comment_lengths));
62
0
  vc->comment_lengths[vc->comments]=strlen(comment);
63
0
  vc->user_comments[vc->comments]=_ogg_malloc(vc->comment_lengths[vc->comments]+1);
64
0
  strcpy(vc->user_comments[vc->comments], comment);
65
0
  vc->comments++;
66
0
  vc->user_comments[vc->comments]=NULL;
67
0
}
68
69
0
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
0
  char *comment=_ogg_malloc(strlen(tag)+strlen(contents)+2);
72
0
  strcpy(comment, tag);
73
0
  strcat(comment, "=");
74
0
  strcat(comment, contents);
75
0
  vorbis_comment_add(vc, comment);
76
0
  _ogg_free(comment);
77
0
}
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
2.12k
void vorbis_comment_clear(vorbis_comment *vc){
132
2.12k
  if(vc){
133
2.12k
    long i;
134
2.12k
    if(vc->user_comments){
135
2.35k
      for(i=0;i<vc->comments;i++)
136
826
        if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
137
1.53k
      _ogg_free(vc->user_comments);
138
1.53k
    }
139
2.12k
    if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
140
2.12k
    if(vc->vendor)_ogg_free(vc->vendor);
141
2.12k
    memset(vc,0,sizeof(*vc));
142
2.12k
  }
143
2.12k
}
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
1.88k
void vorbis_info_init(vorbis_info *vi){
154
1.88k
  memset(vi,0,sizeof(*vi));
155
1.88k
  vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info));
156
1.88k
}
157
158
2.45k
void vorbis_info_clear(vorbis_info *vi){
159
2.45k
  codec_setup_info     *ci=vi->codec_setup;
160
2.45k
  int i;
161
162
2.45k
  if(ci){
163
164
3.47k
    for(i=0;i<ci->modes;i++)
165
1.59k
      if(ci->mode_param[i])_ogg_free(ci->mode_param[i]);
166
167
3.86k
    for(i=0;i<ci->maps;i++) /* unpack does the range checking */
168
1.97k
      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
1.35k
        _mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
172
173
4.65k
    for(i=0;i<ci->floors;i++) /* unpack does the range checking */
174
2.77k
      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
1.13k
        _floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
178
179
4.82k
    for(i=0;i<ci->residues;i++) /* unpack does the range checking */
180
2.93k
      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
2.13k
        _residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
184
185
5.73k
    for(i=0;i<ci->books;i++){
186
3.84k
      if(ci->book_param[i]){
187
        /* knows if the book was not alloced */
188
0
        vorbis_staticbook_destroy(ci->book_param[i]);
189
0
      }
190
3.84k
      if(ci->fullbooks)
191
0
        vorbis_book_clear(ci->fullbooks+i);
192
3.84k
      if(ci->decbooks)
193
3.79k
        vorbis_decbook_clear(ci->decbooks+i);
194
3.84k
    }
195
1.88k
    if(ci->fullbooks)
196
0
        _ogg_free(ci->fullbooks);
197
1.88k
    if(ci->decbooks)
198
1.39k
      _ogg_free(ci->decbooks);
199
200
1.88k
    for(i=0;i<ci->psys;i++)
201
0
      _vi_psy_free(ci->psy_param[i]);
202
203
1.88k
    _ogg_free(ci);
204
1.88k
  }
205
206
2.45k
  memset(vi,0,sizeof(*vi));
207
2.45k
}
208
209
/* Header packing/unpacking ********************************************/
210
211
1.77k
static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
212
1.77k
  codec_setup_info     *ci=vi->codec_setup;
213
1.77k
  int bs;
214
1.77k
  if(!ci)return(OV_EFAULT);
215
216
1.77k
  vi->version=oggpack_read(opb,32);
217
1.77k
  if(vi->version!=0)return(OV_EVERSION);
218
219
1.73k
  vi->channels=oggpack_read(opb,8);
220
1.73k
  vi->rate=oggpack_read(opb,32);
221
222
1.73k
  vi->bitrate_upper=(ogg_int32_t)oggpack_read(opb,32);
223
1.73k
  vi->bitrate_nominal=(ogg_int32_t)oggpack_read(opb,32);
224
1.73k
  vi->bitrate_lower=(ogg_int32_t)oggpack_read(opb,32);
225
226
1.73k
  bs = oggpack_read(opb,4);
227
1.73k
  if(bs<0)goto err_out;
228
1.72k
  ci->blocksizes[0]=1<<bs;
229
1.72k
  bs = oggpack_read(opb,4);
230
1.72k
  if(bs<0)goto err_out;
231
1.72k
  ci->blocksizes[1]=1<<bs;
232
233
1.72k
  if(vi->rate<1)goto err_out;
234
1.72k
  if(vi->channels<1)goto err_out;
235
1.72k
  if(ci->blocksizes[0]<64)goto err_out;
236
1.71k
  if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
237
1.70k
  if(ci->blocksizes[1]>8192)goto err_out;
238
239
1.70k
  if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
240
241
1.69k
  return(0);
242
32
 err_out:
243
32
  vorbis_info_clear(vi);
244
32
  return(OV_EBADHEADER);
245
1.70k
}
246
247
1.69k
static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
248
1.69k
  int i;
249
1.69k
  int vendorlen=oggpack_read(opb,32);
250
1.69k
  if(vendorlen<0)goto err_out;
251
1.66k
  if(vendorlen>opb->storage-8)goto err_out;
252
1.60k
  vc->vendor=_ogg_calloc(vendorlen+1,1);
253
1.60k
  _v_readstring(opb,vc->vendor,vendorlen);
254
1.60k
  i=oggpack_read(opb,32);
255
1.60k
  if(i<0)goto err_out;
256
1.57k
  if(i>((opb->storage-oggpack_bytes(opb))>>2))goto err_out;
257
1.53k
  vc->comments=i;
258
1.53k
  vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
259
1.53k
  vc->comment_lengths=_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
260
261
1.98k
  for(i=0;i<vc->comments;i++){
262
522
    int len=oggpack_read(opb,32);
263
522
    if(len<0)goto err_out;
264
505
    if(len>opb->storage-oggpack_bytes(opb))goto err_out;
265
453
    vc->comment_lengths[i]=len;
266
453
    vc->user_comments[i]=_ogg_calloc(len+1,1);
267
453
    _v_readstring(opb,vc->user_comments[i],len);
268
453
  }
269
1.46k
  if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
270
271
1.45k
  return(0);
272
235
 err_out:
273
235
  vorbis_comment_clear(vc);
274
235
  return(OV_EBADHEADER);
275
1.46k
}
276
277
/* all of the real encoding details are here.  The modes, books,
278
   everything */
279
1.44k
static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
280
1.44k
  codec_setup_info     *ci=vi->codec_setup;
281
1.44k
  int i;
282
283
  /* codebooks */
284
1.44k
  ci->books=oggpack_read(opb,8)+1;
285
1.44k
  if(ci->books<=0)goto err_out;
286
1.44k
  ci->decbooks=_ogg_calloc(ci->books,sizeof(*ci->decbooks));
287
1.44k
  if(ci->decbooks==NULL)goto err_out;
288
2.75k
  for(i=0;i<ci->books;i++){
289
1.48k
    if(vorbis_decbook_unpack(ci->decbooks+i,opb)<0)goto err_out;
290
1.48k
  }
291
292
  /* time backend settings; hooks are unused */
293
1.27k
  {
294
1.27k
    int times=oggpack_read(opb,6)+1;
295
1.27k
    if(times<=0)goto err_out;
296
2.54k
    for(i=0;i<times;i++){
297
1.32k
      int test=oggpack_read(opb,16);
298
1.32k
      if(test<0 || test>=VI_TIMEB)goto err_out;
299
1.32k
    }
300
1.27k
  }
301
302
  /* floor backend settings */
303
1.21k
  ci->floors=oggpack_read(opb,6)+1;
304
1.21k
  if(ci->floors<=0)goto err_out;
305
2.34k
  for(i=0;i<ci->floors;i++){
306
1.27k
    ci->floor_type[i]=oggpack_read(opb,16);
307
1.27k
    if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
308
1.22k
    ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb);
309
1.22k
    if(!ci->floor_param[i])goto err_out;
310
1.22k
  }
311
312
  /* residue backend settings */
313
1.07k
  ci->residues=oggpack_read(opb,6)+1;
314
1.07k
  if(ci->residues<=0)goto err_out;
315
3.21k
  for(i=0;i<ci->residues;i++){
316
2.20k
    ci->residue_type[i]=oggpack_read(opb,16);
317
2.20k
    if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
318
2.18k
    ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
319
2.18k
    if(!ci->residue_param[i])goto err_out;
320
2.18k
  }
321
322
  /* map backend settings */
323
1.01k
  ci->maps=oggpack_read(opb,6)+1;
324
1.01k
  if(ci->maps<=0)goto err_out;
325
2.37k
  for(i=0;i<ci->maps;i++){
326
1.42k
    ci->map_type[i]=oggpack_read(opb,16);
327
1.42k
    if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
328
1.40k
    ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb);
329
1.40k
    if(!ci->map_param[i])goto err_out;
330
1.40k
  }
331
332
  /* mode settings */
333
951
  ci->modes=oggpack_read(opb,6)+1;
334
951
  if(ci->modes<=0)goto err_out;
335
1.96k
  for(i=0;i<ci->modes;i++){
336
1.05k
    ci->mode_param[i]=_ogg_calloc(1,sizeof(*ci->mode_param[i]));
337
1.05k
    ci->mode_param[i]->blockflag=oggpack_read(opb,1);
338
1.05k
    ci->mode_param[i]->windowtype=oggpack_read(opb,16);
339
1.05k
    ci->mode_param[i]->transformtype=oggpack_read(opb,16);
340
1.05k
    ci->mode_param[i]->mapping=oggpack_read(opb,8);
341
342
1.05k
    if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
343
1.03k
    if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
344
1.02k
    if(ci->mode_param[i]->mapping>=ci->maps)goto err_out;
345
1.01k
    if(ci->mode_param[i]->mapping<0)goto err_out;
346
1.01k
  }
347
348
915
  if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
349
350
913
  return(0);
351
535
 err_out:
352
535
  vorbis_info_clear(vi);
353
535
  return(OV_EBADHEADER);
354
915
}
355
356
/* Is this packet a vorbis ID header? */
357
0
int vorbis_synthesis_idheader(ogg_packet *op){
358
0
  oggpack_buffer opb;
359
0
  char buffer[6];
360
361
0
  if(op){
362
0
    oggpack_readinit(&opb,op->packet,op->bytes);
363
364
0
    if(!op->b_o_s)
365
0
      return(0); /* Not the initial packet */
366
367
0
    if(oggpack_read(&opb,8) != 1)
368
0
      return 0; /* not an ID header */
369
370
0
    memset(buffer,0,6);
371
0
    _v_readstring(&opb,buffer,6);
372
0
    if(memcmp(buffer,"vorbis",6))
373
0
      return 0; /* not vorbis */
374
375
0
    return 1;
376
0
  }
377
378
0
  return 0;
379
0
}
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
4.97k
int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){
387
4.97k
  oggpack_buffer opb;
388
389
4.97k
  if(op){
390
4.97k
    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
4.97k
    {
395
4.97k
      char buffer[6];
396
4.97k
      int packtype=oggpack_read(&opb,8);
397
4.97k
      memset(buffer,0,6);
398
4.97k
      _v_readstring(&opb,buffer,6);
399
4.97k
      if(memcmp(buffer,"vorbis",6)){
400
        /* not a vorbis header */
401
56
        return(OV_ENOTVORBIS);
402
56
      }
403
4.91k
      switch(packtype){
404
1.77k
      case 0x01: /* least significant *bit* is read first */
405
1.77k
        if(!op->b_o_s){
406
          /* Not the initial packet */
407
1
          return(OV_EBADHEADER);
408
1
        }
409
1.77k
        if(vi->rate!=0){
410
          /* previously initialized info header */
411
0
          return(OV_EBADHEADER);
412
0
        }
413
414
1.77k
        return(_vorbis_unpack_info(vi,&opb));
415
416
1.69k
      case 0x03: /* least significant *bit* is read first */
417
1.69k
        if(vi->rate==0){
418
          /* um... we didn't get the initial header */
419
1
          return(OV_EBADHEADER);
420
1
        }
421
1.69k
        if(vc->vendor!=NULL){
422
          /* previously initialized comment header */
423
1
          return(OV_EBADHEADER);
424
1
        }
425
426
1.69k
        return(_vorbis_unpack_comment(vc,&opb));
427
428
1.45k
      case 0x05: /* least significant *bit* is read first */
429
1.45k
        if(vi->rate==0 || vc->vendor==NULL){
430
          /* um... we didn;t get the initial header or comments yet */
431
4
          return(OV_EBADHEADER);
432
4
        }
433
1.44k
        if(vi->codec_setup==NULL){
434
          /* improperly initialized vorbis_info */
435
0
          return(OV_EFAULT);
436
0
        }
437
1.44k
        if(((codec_setup_info *)vi->codec_setup)->books>0){
438
          /* previously initialized setup header */
439
0
          return(OV_EBADHEADER);
440
0
        }
441
442
1.44k
        return(_vorbis_unpack_books(vi,&opb));
443
444
1
      default:
445
        /* Not a valid vorbis header type */
446
1
        return(OV_EBADHEADER);
447
0
        break;
448
4.91k
      }
449
4.91k
    }
450
4.91k
  }
451
0
  return(OV_EBADHEADER);
452
4.97k
}
453
454
/* pack side **********************************************************/
455
456
0
static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){
457
0
  codec_setup_info     *ci=vi->codec_setup;
458
0
  if(!ci||
459
0
     ci->blocksizes[0]<64||
460
0
     ci->blocksizes[1]<ci->blocksizes[0]){
461
0
    return(OV_EFAULT);
462
0
  }
463
464
  /* preamble */
465
0
  oggpack_write(opb,0x01,8);
466
0
  _v_writestring(opb,"vorbis", 6);
467
468
  /* basic information about the stream */
469
0
  oggpack_write(opb,0x00,32);
470
0
  oggpack_write(opb,vi->channels,8);
471
0
  oggpack_write(opb,vi->rate,32);
472
473
0
  oggpack_write(opb,vi->bitrate_upper,32);
474
0
  oggpack_write(opb,vi->bitrate_nominal,32);
475
0
  oggpack_write(opb,vi->bitrate_lower,32);
476
477
0
  oggpack_write(opb,ov_ilog(ci->blocksizes[0]-1),4);
478
0
  oggpack_write(opb,ov_ilog(ci->blocksizes[1]-1),4);
479
0
  oggpack_write(opb,1,1);
480
481
0
  return(0);
482
0
}
483
484
0
static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){
485
0
  int bytes = strlen(ENCODE_VENDOR_STRING);
486
487
  /* preamble */
488
0
  oggpack_write(opb,0x03,8);
489
0
  _v_writestring(opb,"vorbis", 6);
490
491
  /* vendor */
492
0
  oggpack_write(opb,bytes,32);
493
0
  _v_writestring(opb,ENCODE_VENDOR_STRING, bytes);
494
495
  /* comments */
496
497
0
  oggpack_write(opb,vc->comments,32);
498
0
  if(vc->comments){
499
0
    int i;
500
0
    for(i=0;i<vc->comments;i++){
501
0
      if(vc->user_comments[i]){
502
0
        oggpack_write(opb,vc->comment_lengths[i],32);
503
0
        _v_writestring(opb,vc->user_comments[i], vc->comment_lengths[i]);
504
0
      }else{
505
0
        oggpack_write(opb,0,32);
506
0
      }
507
0
    }
508
0
  }
509
0
  oggpack_write(opb,1,1);
510
511
0
  return(0);
512
0
}
513
514
0
static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){
515
0
  codec_setup_info     *ci=vi->codec_setup;
516
0
  int i;
517
0
  if(!ci)return(OV_EFAULT);
518
519
0
  oggpack_write(opb,0x05,8);
520
0
  _v_writestring(opb,"vorbis", 6);
521
522
  /* books */
523
0
  oggpack_write(opb,ci->books-1,8);
524
0
  for(i=0;i<ci->books;i++)
525
0
    if(vorbis_staticbook_pack(ci->book_param[i],opb))goto err_out;
526
527
  /* times; hook placeholders */
528
0
  oggpack_write(opb,0,6);
529
0
  oggpack_write(opb,0,16);
530
531
  /* floors */
532
0
  oggpack_write(opb,ci->floors-1,6);
533
0
  for(i=0;i<ci->floors;i++){
534
0
    oggpack_write(opb,ci->floor_type[i],16);
535
0
    if(_floor_P[ci->floor_type[i]]->pack)
536
0
      _floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb);
537
0
    else
538
0
      goto err_out;
539
0
  }
540
541
  /* residues */
542
0
  oggpack_write(opb,ci->residues-1,6);
543
0
  for(i=0;i<ci->residues;i++){
544
0
    oggpack_write(opb,ci->residue_type[i],16);
545
0
    _residue_P[ci->residue_type[i]]->pack(ci->residue_param[i],opb);
546
0
  }
547
548
  /* maps */
549
0
  oggpack_write(opb,ci->maps-1,6);
550
0
  for(i=0;i<ci->maps;i++){
551
0
    oggpack_write(opb,ci->map_type[i],16);
552
0
    _mapping_P[ci->map_type[i]]->pack(vi,ci->map_param[i],opb);
553
0
  }
554
555
  /* modes */
556
0
  oggpack_write(opb,ci->modes-1,6);
557
0
  for(i=0;i<ci->modes;i++){
558
0
    oggpack_write(opb,ci->mode_param[i]->blockflag,1);
559
0
    oggpack_write(opb,ci->mode_param[i]->windowtype,16);
560
0
    oggpack_write(opb,ci->mode_param[i]->transformtype,16);
561
0
    oggpack_write(opb,ci->mode_param[i]->mapping,8);
562
0
  }
563
0
  oggpack_write(opb,1,1);
564
565
0
  return(0);
566
0
err_out:
567
0
  return(-1);
568
0
}
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
0
                              ogg_packet *op_code){
599
0
  int ret=OV_EIMPL;
600
0
  vorbis_info *vi=v->vi;
601
0
  oggpack_buffer opb;
602
0
  private_state *b=v->backend_state;
603
604
0
  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
0
  oggpack_writeinit(&opb);
613
0
  if(_vorbis_pack_info(&opb,vi))goto err_out;
614
615
  /* build the packet */
616
0
  if(b->header)_ogg_free(b->header);
617
0
  b->header=_ogg_malloc(oggpack_bytes(&opb));
618
0
  memcpy(b->header,opb.buffer,oggpack_bytes(&opb));
619
0
  op->packet=b->header;
620
0
  op->bytes=oggpack_bytes(&opb);
621
0
  op->b_o_s=1;
622
0
  op->e_o_s=0;
623
0
  op->granulepos=0;
624
0
  op->packetno=0;
625
626
  /* second header packet (comments) **********************************/
627
628
0
  oggpack_reset(&opb);
629
0
  if(_vorbis_pack_comment(&opb,vc))goto err_out;
630
631
0
  if(b->header1)_ogg_free(b->header1);
632
0
  b->header1=_ogg_malloc(oggpack_bytes(&opb));
633
0
  memcpy(b->header1,opb.buffer,oggpack_bytes(&opb));
634
0
  op_comm->packet=b->header1;
635
0
  op_comm->bytes=oggpack_bytes(&opb);
636
0
  op_comm->b_o_s=0;
637
0
  op_comm->e_o_s=0;
638
0
  op_comm->granulepos=0;
639
0
  op_comm->packetno=1;
640
641
  /* third header packet (modes/codebooks) ****************************/
642
643
0
  oggpack_reset(&opb);
644
0
  if(_vorbis_pack_books(&opb,vi))goto err_out;
645
646
0
  if(b->header2)_ogg_free(b->header2);
647
0
  b->header2=_ogg_malloc(oggpack_bytes(&opb));
648
0
  memcpy(b->header2,opb.buffer,oggpack_bytes(&opb));
649
0
  op_code->packet=b->header2;
650
0
  op_code->bytes=oggpack_bytes(&opb);
651
0
  op_code->b_o_s=0;
652
0
  op_code->e_o_s=0;
653
0
  op_code->granulepos=0;
654
0
  op_code->packetno=2;
655
656
0
  oggpack_writeclear(&opb);
657
0
  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
0
}
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
}