oggz_auto.c 32.6 KB
Newer Older
conrad's avatar
conrad committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
/*
   Copyright (C) 2003 Commonwealth Scientific and Industrial Research
   Organisation (CSIRO) Australia

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions
   are met:

   - Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

   - Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

   - Neither the name of CSIRO Australia nor the names of its
   contributors may be used to endorse or promote products derived from
   this software without specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ORGANISATION OR
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/*
 * oggz_auto.c
 *
 * Conrad Parker <conrad@annodex.net>
 */

#include "config.h"

41
#include <stdlib.h>
conrad's avatar
conrad committed
42
43
#include <string.h>

44
#include "oggz_private.h"
conrad's avatar
conrad committed
45
#include "oggz_byteorder.h"
j's avatar
j committed
46
#include "dirac.h"
conrad's avatar
conrad committed
47

48
49
#include <oggz/oggz_stream.h>

conrad's avatar
conrad committed
50
51
/*#define DEBUG*/

52
53
54
55
56
/* Allow use of internal metrics; ie. the user_data for these gets free'd
 * when the metric is overwritten, or on close */
int oggz_set_metric_internal (OGGZ * oggz, long serialno, OggzMetric metric,
			      void * user_data, int internal);

57
58
59
60
int oggz_set_metric_linear (OGGZ * oggz, long serialno,
			    ogg_int64_t granule_rate_numerator,
			    ogg_int64_t granule_rate_denominator);

61
#define INT16_BE_AT(x) _be_16((*(ogg_int32_t *)(x)))
conrad's avatar
conrad committed
62
63
64
65
#define INT32_LE_AT(x) _le_32((*(ogg_int32_t *)(x)))
#define INT32_BE_AT(x) _be_32((*(ogg_int32_t *)(x)))
#define INT64_LE_AT(x) _le_64((*(ogg_int64_t *)(x)))

66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
static int
oggz_stream_set_numheaders (OGGZ * oggz, long serialno, int numheaders)
{
  oggz_stream_t * stream;

  if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;

  stream = oggz_get_stream (oggz, serialno);
  if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;

  stream->numheaders = numheaders;

  return 0;
}

conrad's avatar
conrad committed
81
static int
82
auto_speex (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
conrad's avatar
conrad committed
83
{
84
  unsigned char * header = data;
conrad's avatar
conrad committed
85
  ogg_int64_t granule_rate = 0;
86
  int numheaders;
conrad's avatar
conrad committed
87

88
  if (length < 68) return 0;
conrad's avatar
conrad committed
89
90
91
92
93
94

  granule_rate = (ogg_int64_t) INT32_LE_AT(&header[36]);
#ifdef DEBUG
  printf ("Got speex rate %d\n", (int)granule_rate);
#endif

95
  oggz_set_granulerate (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);
conrad's avatar
conrad committed
96

97
98
99
  numheaders = (ogg_int64_t) INT32_LE_AT(&header[68]) + 2;
  oggz_stream_set_numheaders (oggz, serialno, numheaders);

conrad's avatar
conrad committed
100
101
102
103
  return 1;
}

static int
104
auto_vorbis (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
conrad's avatar
conrad committed
105
{
106
  unsigned char * header = data;
conrad's avatar
conrad committed
107
108
  ogg_int64_t granule_rate = 0;

109
  if (length < 30) return 0;
conrad's avatar
conrad committed
110
111
112
113
114
115

  granule_rate = (ogg_int64_t) INT32_LE_AT(&header[12]);
#ifdef DEBUG
  printf ("Got vorbis rate %d\n", (int)granule_rate);
#endif

116
  oggz_set_granulerate (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);
conrad's avatar
conrad committed
117

118
119
  oggz_stream_set_numheaders (oggz, serialno, 3);

conrad's avatar
conrad committed
120
121
122
  return 1;
}

123
#if USE_THEORA_PRE_ALPHA_3_FORMAT
conrad's avatar
conrad committed
124
125
126
127
128
129
130
131
static int intlog(int num) {
  int ret=0;
  while(num>0){
    num=num/2;
    ret=ret+1;
  }
  return(ret);
}
132
#endif
conrad's avatar
conrad committed
133
134

static int
135
auto_theora (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
conrad's avatar
conrad committed
136
{
137
  unsigned char * header = data;
138
  ogg_int32_t fps_numerator, fps_denominator;
conrad's avatar
conrad committed
139
  char keyframe_granule_shift = 0;
140
  int keyframe_shift;
conrad's avatar
conrad committed
141

142
  /* TODO: this should check against 42 for the relevant version numbers */
143
  if (length < 41) return 0;
conrad's avatar
conrad committed
144

145
146
  fps_numerator = INT32_BE_AT(&header[22]);
  fps_denominator = INT32_BE_AT(&header[26]);
conrad's avatar
conrad committed
147

148
149
150
151
  /* Very old theora versions used a value of 0 to mean 1.
   * Unfortunately theora hasn't incremented its version field,
   * hence we hardcode this workaround for old or broken streams.
   */
152
  if (fps_numerator == 0) fps_numerator = 1;
153

conrad's avatar
conrad committed
154
155
#if USE_THEORA_PRE_ALPHA_3_FORMAT
  /* old header format, used by Theora alpha2 and earlier */
conrad's avatar
conrad committed
156
  keyframe_granule_shift = (header[36] & 0xf8) >> 3;
157
  keyframe_shift = intlog (keyframe_granule_shift - 1);
conrad's avatar
conrad committed
158
#else
colinw's avatar
colinw committed
159
  keyframe_granule_shift = (char) ((header[40] & 0x03) << 3);
160
  keyframe_granule_shift |= (header[41] & 0xe0) >> 5; /* see TODO above */
161
  keyframe_shift = keyframe_granule_shift;
conrad's avatar
conrad committed
162
#endif
conrad's avatar
conrad committed
163
164

#ifdef DEBUG
165
  printf ("Got theora fps %d/%d, keyframe_shift %d\n",
166
	  fps_numerator, fps_denominator, keyframe_shift);
conrad's avatar
conrad committed
167
168
#endif

169
170
171
  oggz_set_granulerate (oggz, serialno, (ogg_int64_t)fps_numerator,
			OGGZ_AUTO_MULT * (ogg_int64_t)fps_denominator);
  oggz_set_granuleshift (oggz, serialno, keyframe_shift);
conrad's avatar
conrad committed
172

giles's avatar
giles committed
173

174
175
  oggz_stream_set_numheaders (oggz, serialno, 3);

conrad's avatar
conrad committed
176
177
178
  return 1;
}

179
static int
180
auto_annodex (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
181
{
182
  /* Apply a zero metric */
183
  oggz_set_granulerate (oggz, serialno, 0, 1);
184
185
186
187

  return 1;
}

conrad's avatar
conrad committed
188
static int
189
auto_anxdata (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
conrad's avatar
conrad committed
190
{
191
  unsigned char * header = data;
conrad's avatar
conrad committed
192
193
  ogg_int64_t granule_rate_numerator = 0, granule_rate_denominator = 0;

194
  if (length < 28) return 0;
conrad's avatar
conrad committed
195
196
197
198
199
200
201
202

  granule_rate_numerator = INT64_LE_AT(&header[8]);
  granule_rate_denominator = INT64_LE_AT(&header[16]);
#ifdef DEBUG
  printf ("Got AnxData rate %lld/%lld\n", granule_rate_numerator,
	  granule_rate_denominator);
#endif

203
204
205
  oggz_set_granulerate (oggz, serialno,
			granule_rate_numerator,
			OGGZ_AUTO_MULT * granule_rate_denominator);
conrad's avatar
conrad committed
206
207
208
209

  return 1;
}

210
static int
211
auto_flac0 (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
212
{
213
  unsigned char * header = data;
214
215
  ogg_int64_t granule_rate = 0;

giles's avatar
giles committed
216
  granule_rate = (ogg_int64_t) (header[14] << 12) | (header[15] << 4) |
217
            ((header[16] >> 4)&0xf);
218
219
220
#ifdef DEBUG
    printf ("Got flac rate %d\n", (int)granule_rate);
#endif
giles's avatar
giles committed
221

222
  oggz_set_granulerate (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);
223

224
225
  oggz_stream_set_numheaders (oggz, serialno, 3);

226
227
228
  return 1;
}

229
static int
230
auto_flac (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
231
{
232
  unsigned char * header = data;
233
  ogg_int64_t granule_rate = 0;
234
  int numheaders;
235

236
  if (length < 51) return 0;
237

giles's avatar
giles committed
238
  granule_rate = (ogg_int64_t) (header[27] << 12) | (header[28] << 4) |
239
            ((header[29] >> 4)&0xf);
240
241
242
243
#ifdef DEBUG
  printf ("Got flac rate %d\n", (int)granule_rate);
#endif

244
  oggz_set_granulerate (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);
245

246
247
248
  numheaders = INT16_BE_AT(&header[7]);
  oggz_stream_set_numheaders (oggz, serialno, numheaders);

249
250
251
  return 1;
}

252
253
254
255
256
/**
 * Recognizer for OggPCM2:
 * http://wiki.xiph.org/index.php/OggPCM2
 */
static int
257
auto_oggpcm2 (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
258
{
259
  unsigned char * header = data;
260
261
  ogg_int64_t granule_rate;

262
  if (length < 28) return 0;
263
264
265
266
267
268
269
270

  granule_rate = (ogg_int64_t) INT32_BE_AT(&header[16]);
#ifdef DEBUG
  printf ("Got OggPCM2 rate %d\n", (int)granule_rate);
#endif

  oggz_set_granulerate (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);

271
272
  oggz_stream_set_numheaders (oggz, serialno, 3);

273
274
275
  return 1;
}

276
static int
277
auto_celt (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
278
{
279
  unsigned char * header = data;
280
281
282
  ogg_int64_t granule_rate = 0;
  int numheaders;

283
  if (length < 56) return 0;
284
285
286
287
288
289
290
291
292
293
294
295
296
297

  granule_rate = (ogg_int64_t) INT32_LE_AT(&header[40]);
#ifdef DEBUG
  printf ("Got celt sample rate %d\n", (int)granule_rate);
#endif

  oggz_set_granulerate (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);

  numheaders = (ogg_int64_t) INT32_LE_AT(&header[52]) + 2;
  oggz_stream_set_numheaders (oggz, serialno, numheaders);

  return 1;
}

conrad's avatar
conrad committed
298
static int
299
auto_cmml (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
conrad's avatar
conrad committed
300
{
301
  unsigned char * header = data;
conrad's avatar
conrad committed
302
  ogg_int64_t granule_rate_numerator = 0, granule_rate_denominator = 0;
303
  int granuleshift;
conrad's avatar
conrad committed
304

305
  if (length < 28) return 0;
conrad's avatar
conrad committed
306
307
308

  granule_rate_numerator = INT64_LE_AT(&header[12]);
  granule_rate_denominator = INT64_LE_AT(&header[20]);
309
  if (length > 28)
310
311
312
313
    granuleshift = (int)header[28];
  else
    granuleshift = 0;

conrad's avatar
conrad committed
314
315
316
317
318
#ifdef DEBUG
  printf ("Got CMML rate %lld/%lld\n", granule_rate_numerator,
	  granule_rate_denominator);
#endif

319
320
321
  oggz_set_granulerate (oggz, serialno,
			granule_rate_numerator,
			OGGZ_AUTO_MULT * granule_rate_denominator);
322
  oggz_set_granuleshift (oggz, serialno, granuleshift);
conrad's avatar
conrad committed
323

324
325
  oggz_stream_set_numheaders (oggz, serialno, 3);

conrad's avatar
conrad committed
326
327
328
  return 1;
}

329
static int
330
auto_kate (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
331
{
332
  unsigned char * header = data;
333
334
335
336
  ogg_int32_t gps_numerator, gps_denominator;
  unsigned char granule_shift = 0;
  int numheaders;

337
  if (length < 64) return 0;
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352

  gps_numerator = INT32_LE_AT(&header[24]);
  gps_denominator = INT32_LE_AT(&header[28]);

  granule_shift = (header[15]);
  numheaders = (header[11]);

#ifdef DEBUG
  printf ("Got kate gps %d/%d, granule shift %d\n",
	  gps_numerator, gps_denominator, granule_shift);
#endif

  oggz_set_granulerate (oggz, serialno, gps_numerator,
			OGGZ_AUTO_MULT * gps_denominator);
  oggz_set_granuleshift (oggz, serialno, granule_shift);
giles's avatar
giles committed
353

354
355
356
357
358
  oggz_stream_set_numheaders (oggz, serialno, numheaders);

  return 1;
}

j's avatar
j committed
359
static int
360
auto_dirac (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
j's avatar
j committed
361
{
362
  int granule_shift = 22; /* not a typo */
j's avatar
j committed
363
364
365
366
  dirac_info *info;

  info = malloc(sizeof(dirac_info));

367
  dirac_parse_info(info, data, length);
j's avatar
j committed
368
369

#ifdef DEBUG
370
371
  printf ("Got dirac fps %d/%d granule_shift %d\n",
    fps_numerator, fps_denominator, granule_shift);
j's avatar
j committed
372
373
#endif

374
375
376
377
  /* the granulerate is twice the frame rate (in order to handle interlace)
   * it is also multiplied by (1<<9) since the decode time is stored in
   * the top 32bits of granulepos, but the granule_shift is 22. */
  oggz_set_granulerate (oggz, serialno,
378
379
	2*(1<<9)*(ogg_int64_t)info->fps_numerator,
	OGGZ_AUTO_MULT * (ogg_int64_t)info->fps_denominator);
380
  oggz_set_granuleshift (oggz, serialno, granule_shift);
j's avatar
j committed
381

382
  oggz_stream_set_numheaders (oggz, serialno, 0);
j's avatar
j committed
383
384
385
386
387

  free(info);
  return 1;
}

388
static int
389
auto_fisbone (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
390
{
391
  unsigned char * header = data;
392
  long fisbone_serialno; /* The serialno referred to in this fisbone */
393
  ogg_int64_t granule_rate_numerator = 0, granule_rate_denominator = 0;
394
  int granuleshift, numheaders;
395

396
  if (length < 48) return 0;
397
398

  fisbone_serialno = (long) INT32_LE_AT(&header[12]);
399
400

  /* Don't override an already assigned metric */
401
  if (oggz_stream_has_metric (oggz, fisbone_serialno)) return 1;
402
403
404

  granule_rate_numerator = INT64_LE_AT(&header[20]);
  granule_rate_denominator = INT64_LE_AT(&header[28]);
conrad's avatar
conrad committed
405
406
  granuleshift = (int)header[48];

407
#ifdef DEBUG
conrad's avatar
conrad committed
408
409
  printf ("Got fisbone granulerate %lld/%lld, granuleshift %d for serialno %010ld\n",
	  granule_rate_numerator, granule_rate_denominator, granuleshift,
410
411
412
	  fisbone_serialno);
#endif

413
414
415
416
  oggz_set_granulerate (oggz, fisbone_serialno,
			granule_rate_numerator,
			OGGZ_AUTO_MULT * granule_rate_denominator);
  oggz_set_granuleshift (oggz, fisbone_serialno, granuleshift);
417
418
419
420

  /* Increment the number of headers for this stream */
  numheaders = oggz_stream_get_numheaders (oggz, serialno);
  oggz_stream_set_numheaders (oggz, serialno, numheaders+1);
giles's avatar
giles committed
421

422
423
424
  return 1;
}

425
static int
426
auto_fishead (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
427
428
{
  oggz_set_granulerate (oggz, serialno, 0, 1);
429
430
431

  /* For skeleton, numheaders will get incremented as each header is seen */
  oggz_stream_set_numheaders (oggz, serialno, 1);
giles's avatar
giles committed
432

433
434
435
  return 1;
}

shans's avatar
   
shans committed
436
437
438
/*
 * The first two speex packets are header and comment packets (granulepos = 0)
 */
shans's avatar
shans committed
439
440
441
442
443
444
445

typedef struct {
  int headers_encountered;
  int packet_size;
  int encountered_first_data_packet;
} auto_calc_speex_info_t;

giles's avatar
giles committed
446
static ogg_int64_t
447
auto_calc_speex(ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {
giles's avatar
giles committed
448

449
450
451
452
  /*
   * on the first (b_o_s) packet, set calculate_data to be the number
   * of speex frames per packet
   */
shans's avatar
shans committed
453

giles's avatar
giles committed
454
  auto_calc_speex_info_t *info
shans's avatar
shans committed
455
456
          = (auto_calc_speex_info_t *)stream->calculate_data;

457
  if (stream->calculate_data == NULL) {
shans's avatar
shans committed
458
459
460
    stream->calculate_data = malloc(sizeof(auto_calc_speex_info_t));
    info = stream->calculate_data;
    info->encountered_first_data_packet = 0;
giles's avatar
giles committed
461
    info->packet_size =
shans's avatar
shans committed
462
463
464
            (*(int *)(op->packet + 64)) * (*(int *)(op->packet + 56));
    info->headers_encountered = 1;
    return 0;
465
  }
giles's avatar
giles committed
466

shans's avatar
shans committed
467
468
469
470
471
472
473
  if (info->headers_encountered < 2) {
    info->headers_encountered += 1;
  } else {
    info->encountered_first_data_packet = 1;
  }

  if (now > -1) {
474
    return now;
shans's avatar
shans committed
475
  }
476

shans's avatar
shans committed
477
478
479
480
  if (info->encountered_first_data_packet) {
    if (stream->last_granulepos > 0) {
      return stream->last_granulepos + info->packet_size;
    }
giles's avatar
giles committed
481

shans's avatar
shans committed
482
    return -1;
483
  }
shans's avatar
shans committed
484
485
486

  return 0;

487
}
shans's avatar
   
shans committed
488

489
490
491
492
493
494
495
496
497
498
/*
 * The first two CELT packets are header and comment packets (granulepos = 0)
 */

typedef struct {
  int headers_encountered;
  int packet_size;
  int encountered_first_data_packet;
} auto_calc_celt_info_t;

giles's avatar
giles committed
499
static ogg_int64_t
500
auto_calc_celt (ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {
giles's avatar
giles committed
501

502
503
504
505
506
  /*
   * on the first (b_o_s) packet, set calculate_data to be the number
   * of celt frames per packet
   */

giles's avatar
giles committed
507
  auto_calc_celt_info_t *info
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
          = (auto_calc_celt_info_t *)stream->calculate_data;

  if (stream->calculate_data == NULL) {
    stream->calculate_data = malloc(sizeof(auto_calc_celt_info_t));
    info = stream->calculate_data;
    info->encountered_first_data_packet = 0;

    /* In general, the number of frames per packet depends on the mode.
     * Currently (20080213) both available modes, mono and stereo, have 256
     * frames per packet.
     */
    info->packet_size = 256;

    info->headers_encountered = 1;
    return 0;
  }
giles's avatar
giles committed
524

525
526
527
528
529
530
531
532
533
534
535
536
537
538
  if (info->headers_encountered < 2) {
    info->headers_encountered += 1;
  } else {
    info->encountered_first_data_packet = 1;
  }

  if (now > -1) {
    return now;
  }

  if (info->encountered_first_data_packet) {
    if (stream->last_granulepos > 0) {
      return stream->last_granulepos + info->packet_size;
    }
giles's avatar
giles committed
539

540
541
542
543
544
545
    return -1;
  }

  return 0;

}
shans's avatar
   
shans committed
546
547
548
549
/*
 * Header packets are marked by a set MSB in the first byte.  Inter packets
 * are marked by a set 2MSB in the first byte.  Intra packets (keyframes)
 * are any that are left over ;-)
giles's avatar
giles committed
550
551
 *
 * (see http://www.theora.org/doc/Theora_I_spec.pdf for the theora
shans's avatar
   
shans committed
552
553
 * specification)
 */
554
555
556
557
558
559

typedef struct {
  int encountered_first_data_packet;
} auto_calc_theora_info_t;


giles's avatar
giles committed
560
static ogg_int64_t
561
562
563
564
565
auto_calc_theora(ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {

  long keyframe_no;
  int keyframe_shift;
  unsigned char first_byte;
566
  auto_calc_theora_info_t *info;
567
568
569

  first_byte = op->packet[0];

570
  info = (auto_calc_theora_info_t *)stream->calculate_data;
571

572
  /* header packet */
573
574
  if (first_byte & 0x80)
  {
575
576
577
578
    if (info == NULL) {
      stream->calculate_data = malloc(sizeof(auto_calc_theora_info_t));
      info = stream->calculate_data;
    }
579
    info->encountered_first_data_packet = 0;
580
    return (ogg_int64_t)0;
581
  }
giles's avatar
giles committed
582

583
584
  /* known granulepos */
  if (now > (ogg_int64_t)(-1)) {
585
    info->encountered_first_data_packet = 1;
586
587
588
589
590
    return now;
  }

  /* last granulepos unknown */
  if (stream->last_granulepos == -1) {
591
592
593
594
595
596
597
598
599
    info->encountered_first_data_packet = 1;
    return (ogg_int64_t)-1;
  }

  /*
   * first data packet is -1 if gp not set
   */
  if (!info->encountered_first_data_packet) {
    info->encountered_first_data_packet = 1;
600
    return (ogg_int64_t)-1;
601
602
  }

603
604
  /* inter-coded packet */
  if (first_byte & 0x40)
605
  {
606
    return stream->last_granulepos + 1;
607
608
  }

giles's avatar
giles committed
609
  keyframe_shift = stream->granuleshift;
610
611
612
613
614
615
616
617
618
  /*
   * retrieve last keyframe number
   */
  keyframe_no = (int)(stream->last_granulepos >> keyframe_shift);
  /*
   * add frames since last keyframe number
   */
  keyframe_no += (stream->last_granulepos & ((1 << keyframe_shift) - 1)) + 1;
  return ((ogg_int64_t)keyframe_no) << keyframe_shift;
giles's avatar
giles committed
619

620
621
622

}

623
static ogg_int64_t
giles's avatar
giles committed
624
auto_rcalc_theora(ogg_int64_t next_packet_gp, oggz_stream_t *stream,
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
                  ogg_packet *this_packet, ogg_packet *next_packet) {

  int keyframe = (int)(next_packet_gp >> stream->granuleshift);
  int offset = (int)(next_packet_gp - (keyframe << stream->granuleshift));

  /* assume kf is 60 frames ago. NOTE: This is going to cause problems,
   * but I can't think of what else to do.  The position of the last kf
   * is fundamentally unknowable.
   */
  if (offset == 0) {
    return ((keyframe - 60L) << stream->granuleshift) + 59;
  }
  else {
    return (((ogg_int64_t)keyframe) << stream->granuleshift) + (offset - 1);
  }

}


shans's avatar
   
shans committed
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
/*
 * Vorbis packets can be short or long, and each packet overlaps the previous
 * and next packets.  The granulepos of a packet is always the last sample
 * that is completely decoded at the end of decoding that packet - i.e. the
 * last packet before the first overlapping packet.  If the sizes of packets
 * are 's' and 'l', then the increment will depend on the previous and next
 * packet types:
 *  v                             prev<<1 | next
 * lll:           l/2             3
 * lls:           3l/4 - s/4      2
 * lsl:           s/2
 * lss:           s/2
 * sll:           l/4 + s/4       1
 * sls:           l/2             0
 * ssl:           s/2
 * sss:           s/2
 *
 * The previous and next packet types can be inferred from the current packet
 * (additional information is not required)
 *
 * The two blocksizes can be determined from the first header packet, by reading
giles's avatar
giles committed
665
 * byte 28.  1 << (packet[28] >> 4) == long_size.
shans's avatar
   
shans committed
666
 * 1 << (packet[28] & 0xF) == short_size.
giles's avatar
giles committed
667
 *
shans's avatar
   
shans committed
668
669
670
671
672
673
674
675
676
677
678
679
680
681
 * (see http://xiph.org/vorbis/doc/Vorbis_I_spec.html for specification)
 */

typedef struct {
  int nln_increments[4];
  int nsn_increment;
  int short_size;
  int long_size;
  int encountered_first_data_packet;
  int last_was_long;
  int log2_num_modes;
  int mode_sizes[1];
} auto_calc_vorbis_info_t;

giles's avatar
giles committed
682
683

static ogg_int64_t
shans's avatar
   
shans committed
684
685
686
auto_calc_vorbis(ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {

  auto_calc_vorbis_info_t *info;
giles's avatar
giles committed
687

shans's avatar
   
shans committed
688
689
690
691
692
693
694
  if (stream->calculate_data == NULL) {
    /*
     * on the first (b_o_s) packet, determine the long and short sizes,
     * and then calculate l/2, l/4 - s/4, 3 * l/4 - s/4, l/2 - s/2 and s/2
     */
    int short_size;
    int long_size;
giles's avatar
giles committed
695

shans's avatar
   
shans committed
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
    long_size = 1 << (op->packet[28] >> 4);
    short_size = 1 << (op->packet[28] & 0xF);

    stream->calculate_data = malloc(sizeof(auto_calc_vorbis_info_t));
    info = (auto_calc_vorbis_info_t *)stream->calculate_data;
    info->nln_increments[3] = long_size >> 1;
    info->nln_increments[2] = 3 * (long_size >> 2) - (short_size >> 2);
    info->nln_increments[1] = (long_size >> 2) + (short_size >> 2);
    info->nln_increments[0] = info->nln_increments[3];
    info->short_size = short_size;
    info->long_size = long_size;
    info->nsn_increment = short_size >> 1;
    info->encountered_first_data_packet = 0;

    /* this is a header packet */
    return 0;
  }

  /*
   * marker for header packets
   */
  if (op->packet[0] & 0x1) {
    /*
     * the code pages, a whole bunch of other fairly useless stuff, AND,
     * RIGHT AT THE END (of a bunch of variable-length compressed rubbish that
giles's avatar
giles committed
721
     * basically has only one actual set of values that everyone uses BUT YOU
shans's avatar
   
shans committed
722
723
     * CAN'T BE SURE OF THAT, OH NO YOU CAN'T) is the only piece of data that's
     * actually useful to us - the packet modes (because it's inconceivable to
giles's avatar
giles committed
724
     * think people might want _just that_ and nothing else, you know, for
shans's avatar
   
shans committed
725
726
727
728
729
730
731
732
733
734
735
736
737
738
     * seeking and stuff).
     *
     * Fortunately, because of the mandate that non-used bits must be zero
     * at the end of the packet, we might be able to sneakily work backwards
     * and find out the information we need (namely a mapping of modes to
     * packet sizes)
     */
    if (op->packet[0] == 5) {
      unsigned char *current_pos = &op->packet[op->bytes - 1];
      int offset;
      int size;
      int size_check;
      int *mode_size_ptr;
      int i;
giles's avatar
giles committed
739
740

      /*
shans's avatar
   
shans committed
741
742
       * This is the format of the mode data at the end of the packet for all
       * Vorbis Version 1 :
giles's avatar
giles committed
743
       *
shans's avatar
   
shans committed
744
745
746
747
748
749
750
751
752
753
754
755
       * [ 6:number_of_modes ]
       * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ]
       * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ]
       * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ]
       * [ 1:framing(1) ]
       *
       * e.g.:
       *
       *              <-
       * 0 0 0 0 0 1 0 0
       * 0 0 1 0 0 0 0 0
       * 0 0 1 0 0 0 0 0
giles's avatar
giles committed
756
       * 0 0 1|0 0 0 0 0
shans's avatar
   
shans committed
757
758
759
760
761
762
763
764
765
       * 0 0 0 0|0|0 0 0
       * 0 0 0 0 0 0 0 0
       * 0 0 0 0|0 0 0 0
       * 0 0 0 0 0 0 0 0
       * 0 0 0 0|0 0 0 0
       * 0 0 0|1|0 0 0 0 |
       * 0 0 0 0 0 0 0 0 V
       * 0 0 0|0 0 0 0 0
       * 0 0 0 0 0 0 0 0
giles's avatar
giles committed
766
767
768
769
770
       * 0 0 1|0 0 0 0 0
       * 0 0|1|0 0 0 0 0
       *
       *
       * i.e. each entry is an important bit, 32 bits of 0, 8 bits of blah, a
shans's avatar
   
shans committed
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
       * bit of 1.
       * Let's find our last 1 bit first.
       *
       */

      size = 0;

      offset = 8;
      while (!((1 << --offset) & *current_pos)) {
        if (offset == 0) {
          offset = 8;
          current_pos -= 1;
        }
      }

      while (1)
      {
giles's avatar
giles committed
788

shans's avatar
   
shans committed
789
790
791
792
793
794
795
        /*
         * from current_pos-5:(offset+1) to current_pos-1:(offset+1) should
         * be zero
         */
        offset = (offset + 7) % 8;
        if (offset == 7)
          current_pos -= 1;
giles's avatar
giles committed
796
797

        if
shans's avatar
   
shans committed
798
799
800
        (
          ((current_pos[-5] & ~((1 << (offset + 1)) - 1)) != 0)
          ||
giles's avatar
giles committed
801
802
803
804
          current_pos[-4] != 0
          ||
          current_pos[-3] != 0
          ||
shans's avatar
   
shans committed
805
806
807
808
809
810
811
          current_pos[-2] != 0
          ||
          ((current_pos[-1] & ((1 << (offset + 1)) - 1)) != 0)
        )
        {
          break;
        }
giles's avatar
giles committed
812

shans's avatar
   
shans committed
813
        size += 1;
giles's avatar
giles committed
814

shans's avatar
   
shans committed
815
        current_pos -= 5;
giles's avatar
giles committed
816
817

      }
shans's avatar
   
shans committed
818
819
820
821
822
823
824
825
826

      if (offset > 4) {
        size_check = (current_pos[0] >> (offset - 5)) & 0x3F;
      } else {
        /* mask part of byte from current_pos */
        size_check = (current_pos[0] & ((1 << (offset + 1)) - 1));
        /* shift to appropriate position */
        size_check <<= (5 - offset);
        /* or in part of byte from current_pos - 1 */
giles's avatar
giles committed
827
        size_check |= (current_pos[-1] & ~((1 << (offset + 3)) - 1)) >>
shans's avatar
   
shans committed
828
829
                (offset + 3);
      }
giles's avatar
giles committed
830

shans's avatar
   
shans committed
831
      size_check += 1;
832
#ifdef DEBUG
shans's avatar
   
shans committed
833
834
835
836
      if (size_check != size)
      {
        printf("WARNING: size parsing failed for VORBIS mode packets\n");
      }
837
#endif
shans's avatar
   
shans committed
838
839
840
841
842
843
844

      /*
       * store mode size information in our info struct
       */
      stream->calculate_data = realloc(stream->calculate_data,
              sizeof(auto_calc_vorbis_info_t) + (size - 1) * sizeof(int));
      info = (auto_calc_vorbis_info_t *)(stream->calculate_data);
giles's avatar
giles committed
845

shans's avatar
   
shans committed
846
847
848
849
850
851
852
853
854
855
856
857
858
859
      i = -1;
      while ((1 << (++i)) < size);
      info->log2_num_modes = i;

      mode_size_ptr = info->mode_sizes;

      for(i = 0; i < size; i++)
      {
        offset = (offset + 1) % 8;
        if (offset == 0)
          current_pos += 1;
        *mode_size_ptr++ = (current_pos[0] >> offset) & 0x1;
        current_pos += 5;
      }
giles's avatar
giles committed
860

shans's avatar
   
shans committed
861
    }
giles's avatar
giles committed
862

shans's avatar
   
shans committed
863
864
865
866
867
    return 0;
  }

  info = (auto_calc_vorbis_info_t *)stream->calculate_data;

868
869
  return -1;

giles's avatar
giles committed
870
  {
shans's avatar
   
shans committed
871
872
873
874
875
876
    /*
     * we're in a data packet!  First we need to get the mode of the packet,
     * and from the mode, the size
     */
    int mode;
    int size;
877
    ogg_int64_t result;
shans's avatar
   
shans committed
878
879
880

    mode = (op->packet[0] >> 1) & ((1 << info->log2_num_modes) - 1);
    size = info->mode_sizes[mode];
giles's avatar
giles committed
881

shans's avatar
   
shans committed
882
    /*
883
884
     * if we have a working granulepos, we use it, but only if we can't
     * calculate a valid gp value.
shans's avatar
   
shans committed
885
     */
886
    if (now > -1 && stream->last_granulepos == -1) {
shans's avatar
   
shans committed
887
      info->encountered_first_data_packet = 1;
888
      info->last_was_long = size;
889
      return now;
shans's avatar
   
shans committed
890
    }
891
892
893

    if (info->encountered_first_data_packet == 0) {
      info->encountered_first_data_packet = 1;
894
      info->last_was_long = size;
895
      return -1;
shans's avatar
   
shans committed
896
    }
897

shans's avatar
   
shans committed
898
    /*
899
900
     * otherwise, if we haven't yet had a working granulepos, we return
     * -1
shans's avatar
   
shans committed
901
     */
902
    if (stream->last_granulepos == -1) {
903
      info->last_was_long = size;
904
905
      return -1;
    }
shans's avatar
   
shans committed
906

giles's avatar
giles committed
907
    result = stream->last_granulepos +
shans's avatar
   
shans committed
908
      (
giles's avatar
giles committed
909
910
        (info->last_was_long ? info->long_size  : info->short_size)
        +
shans's avatar
   
shans committed
911
912
913
        (size ? info->long_size : info->short_size)
      ) / 4;
    info->last_was_long = size;
shans's avatar
shans committed
914

shans's avatar
   
shans committed
915
    return result;
giles's avatar
giles committed
916

shans's avatar
   
shans committed
917
  }
giles's avatar
giles committed
918

shans's avatar
   
shans committed
919
}
920

921
922
923
924
ogg_int64_t
auto_rcalc_vorbis(ogg_int64_t next_packet_gp, oggz_stream_t *stream,
                  ogg_packet *this_packet, ogg_packet *next_packet) {

giles's avatar
giles committed
925
  auto_calc_vorbis_info_t *info =
926
927
                  (auto_calc_vorbis_info_t *)stream->calculate_data;

giles's avatar
giles committed
928
  int mode =
929
930
931
      (this_packet->packet[0] >> 1) & ((1 << info->log2_num_modes) - 1);
  int this_size = info->mode_sizes[mode] ? info->long_size : info->short_size;
  int next_size;
932
  ogg_int64_t r;
933
934
935
936

  mode = (next_packet->packet[0] >> 1) & ((1 << info->log2_num_modes) - 1);
  next_size = info->mode_sizes[mode] ? info->long_size : info->short_size;

937
938
939
  r = next_packet_gp - ((this_size + next_size) / 4);
  if (r < 0) return 0L;
  return r;
940
941
942

}

943
944
/**
 * FLAC
945
946
947
948
949
950
951
952
953
954
955
956
957
 * Defined at: http://flac.sourceforge.net/ogg_mapping.html
 *   - Native FLAC audio frames appear as subsequent packets in the stream.
 *     Each packet corresponds to one FLAC audio frame.
 *   - FLAC packets may span page boundaries.
 *
 * The frame header defines block size
 * http://flac.sourceforge.net/format.html#frame_header
 *
 * Note that most FLAC packets will have a granulepos, but rare cases exist
 * where they don't. See for example
 * http://rafb.net/paste/results/Pkib5w72.html
 */

958
959
960
961
962
typedef struct {
  ogg_int64_t previous_gp;
  int encountered_first_data_packet;
} auto_calc_flac_info_t;

giles's avatar
giles committed
963
static ogg_int64_t
964
965
auto_calc_flac (ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op)
{
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
  auto_calc_flac_info_t *info;

  if (stream->calculate_data == NULL) {
    stream->calculate_data = malloc(sizeof(auto_calc_flac_info_t));
    info = (auto_calc_flac_info_t *)stream->calculate_data;
    info->previous_gp = 0;
    info->encountered_first_data_packet = 0;

    /* this is a header packet */
    goto out;
  }

  info = (auto_calc_flac_info_t *)stream->calculate_data;

  /* FLAC audio frames begin with marker 0xFF */
  if (op->packet[0] == 0xff)
      info->encountered_first_data_packet = 1;

  if (now == -1 && op->packet[0] == 0xff && op->bytes > 2) {
    unsigned char bs;
    int block_size;

    bs = (op->packet[2] & 0xf0) >> 4;

    switch (bs) {
      case 0x0: /*   0000 : get from STREAMINFO metadata block */
        block_size = -1;
        break;
      case 0x1: /* 0001 : 192 samples */
        block_size = 192;
        break;
      /* 0010-0101 : 576 * (2^(n-2)) samples, i.e. 576/1152/2304/4608 */
      case 0x2:
        block_size = 576;
        break;
      case 0x3:
        block_size = 1152;
        break;
      case 0x4:
        block_size = 2304;
        break;
      case 0x5:
        block_size = 4608;
        break;
      case 0x6: /* 0110 : get 8 bit (blocksize-1) from end of header */
        block_size = -1;
        break;
      case 0x7: /* 0111 : get 16 bit (blocksize-1) from end of header */
        block_size = -1;
        break;
      /* 1000-1111 : 256 * (2^(n-8)) samples, i.e. 256/512/1024/2048/4096/8192/16384/32768 */
      case 0x8:
        block_size = 256;
        break;
      case 0x9:
        block_size = 512;
        break;
      case 0xa:
        block_size = 1024;
        break;
      case 0xb:
        block_size = 2048;
        break;
      case 0xc:
        block_size = 4096;
        break;
      case 0xd:
        block_size = 8192;
        break;
      case 0xe:
        block_size = 16384;
        break;
      case 0xf:
        block_size = 32768;
        break;
      default:
        block_size = -1;
        break;
    }

    if (block_size != -1) {
      now = info->previous_gp + block_size;
    }
  } else if (now == -1 && info->encountered_first_data_packet == 0) {
    /* this is a header packet */
    now = 0;
  }

out:
  info->previous_gp = now;
  return now;
1057
1058
}

1059
const oggz_auto_contenttype_t oggz_auto_codec_ident[] = {
1060
1061
1062
1063
1064
1065
1066
1067
  {"\200theora", 7, "Theora", auto_theora, auto_calc_theora, auto_rcalc_theora},
  {"\001vorbis", 7, "Vorbis", auto_vorbis, auto_calc_vorbis, auto_rcalc_vorbis},
  {"Speex", 5, "Speex", auto_speex, auto_calc_speex, NULL},
  {"PCM     ", 8, "PCM", auto_oggpcm2, NULL, NULL},
  {"CMML\0\0\0\0", 8, "CMML", auto_cmml, NULL, NULL},
  {"Annodex", 8, "Annodex", auto_annodex, NULL, NULL},
  {"fishead", 7, "Skeleton", auto_fishead, NULL, NULL},
  {"fLaC", 4, "Flac0", auto_flac0, auto_calc_flac, NULL},
1068
  {"\177FLAC", 5, "Flac", auto_flac, auto_calc_flac, NULL},
1069
  {"AnxData", 7, "AnxData", auto_anxdata, NULL, NULL},
1070
  {"CELT    ", 8, "CELT", auto_celt, auto_calc_celt, NULL},
1071
  {"\200kate\0\0\0", 8, "Kate", auto_kate, NULL, NULL},
j's avatar
j committed
1072
  {"BBCD\0", 5, "Dirac", auto_dirac, NULL, NULL},
1073
  {"", 0, "Unknown", NULL, NULL, NULL}
giles's avatar
giles committed
1074
};
1075

1076
1077
static int
oggz_auto_identify (OGGZ * oggz, long serialno, unsigned char * data, long len)
1078
{
1079
  int i;
giles's avatar
giles committed
1080

1081
1082
1083
  for (i = 0; i < OGGZ_CONTENT_UNKNOWN; i++)
  {
    const oggz_auto_contenttype_t *codec = oggz_auto_codec_ident + i;
giles's avatar
giles committed
1084

1085
1086
    if (len >= codec->bos_str_len &&
        memcmp (data, codec->bos_str, codec->bos_str_len) == 0) {
giles's avatar
giles committed
1087

1088
      oggz_stream_set_content (oggz, serialno, i);
giles's avatar
giles committed
1089

1090
1091
1092
      return 1;
    }
  }
giles's avatar
giles committed
1093

1094
1095
1096
  oggz_stream_set_content (oggz, serialno, OGGZ_CONTENT_UNKNOWN);
  return 0;
}
conrad's avatar
conrad committed
1097

1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
int
oggz_auto_identify_page (OGGZ * oggz, ogg_page *og, long serialno)
{
  return oggz_auto_identify (oggz, serialno, og->body, og->body_len);
}

int
oggz_auto_identify_packet (OGGZ * oggz, ogg_packet * op, long serialno)
{
  return oggz_auto_identify (oggz, serialno, op->packet, op->bytes);
}

conrad's avatar
conrad committed
1110
int
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
oggz_auto_read_bos_page (OGGZ * oggz, ogg_page * og, long serialno,
                         void * user_data)
{
  int content = 0;

  content = oggz_stream_get_content(oggz, serialno);
  if (content < 0 || content >= OGGZ_CONTENT_UNKNOWN) {
    return 0;
  } else if (content == OGGZ_CONTENT_SKELETON && !ogg_page_bos(og)) {
    return auto_fisbone(oggz, serialno, og->body, og->body_len, user_data);
  } else {
    return oggz_auto_codec_ident[content].reader(oggz, serialno, og->body, og->body_len, user_data);
  }
}

int
giles's avatar
giles committed
1127
oggz_auto_read_bos_packet (OGGZ * oggz, ogg_packet * op, long serialno,
1128
                           void * user_data)
1129
{
1130
  int content = 0;
conrad's avatar
conrad committed
1131

1132
1133
1134
  content = oggz_stream_get_content(oggz, serialno);
  if (content < 0 || content >= OGGZ_CONTENT_UNKNOWN) {
    return 0;
1135
1136
1137
1138
  } else if (content == OGGZ_CONTENT_SKELETON && !op->b_o_s) {
    return auto_fisbone(oggz, serialno, op->packet, op->bytes, user_data);
  } else {
    return oggz_auto_codec_ident[content].reader(oggz, serialno, op->packet, op->bytes, user_data);
conrad's avatar
conrad committed
1139
1140
1141
  }
}

giles's avatar
giles committed
1142
1143
ogg_int64_t
oggz_auto_calculate_granulepos(int content, ogg_int64_t now,
1144
1145
                oggz_stream_t *stream, ogg_packet *op) {
  if (oggz_auto_codec_ident[content].calculator != NULL) {
shans's avatar
shans committed
1146
1147
    ogg_int64_t r = oggz_auto_codec_ident[content].calculator(now, stream, op);
    return r;
giles's avatar
giles committed
1148
  }
shans's avatar
shans committed
1149
1150

  return now;
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
}

ogg_int64_t
oggz_auto_calculate_gp_backwards(int content, ogg_int64_t next_packet_gp,
      oggz_stream_t *stream, ogg_packet *this_packet, ogg_packet *next_packet) {

  if (oggz_auto_codec_ident[content].r_calculator != NULL) {
    return oggz_auto_codec_ident[content].r_calculator(next_packet_gp,
            stream, this_packet, next_packet);