oggz_auto.c 32.8 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
  oggz_set_preroll (oggz, serialno, 3);

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

conrad's avatar
conrad committed
102 103 104 105
  return 1;
}

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

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

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

118
  oggz_set_granulerate (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);
conrad's avatar
conrad committed
119

120 121
  oggz_set_preroll (oggz, serialno, 2);

122 123
  oggz_stream_set_numheaders (oggz, serialno, 3);

conrad's avatar
conrad committed
124 125 126
  return 1;
}

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

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

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

149 150
  fps_numerator = INT32_BE_AT(&header[22]);
  fps_denominator = INT32_BE_AT(&header[26]);
conrad's avatar
conrad committed
151

152 153 154 155
  /* 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.
   */
156
  if (fps_numerator == 0) fps_numerator = 1;
157

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

#ifdef DEBUG
169
  printf ("Got theora fps %d/%d, keyframe_shift %d\n",
170
	  fps_numerator, fps_denominator, keyframe_shift);
conrad's avatar
conrad committed
171 172
#endif

173 174 175
  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
176

giles's avatar
giles committed
177

178 179
  oggz_stream_set_numheaders (oggz, serialno, 3);

conrad's avatar
conrad committed
180 181 182
  return 1;
}

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

  return 1;
}

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

198
  if (length < 28) return 0;
conrad's avatar
conrad committed
199 200 201 202 203 204 205 206

  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

207 208 209
  oggz_set_granulerate (oggz, serialno,
			granule_rate_numerator,
			OGGZ_AUTO_MULT * granule_rate_denominator);
conrad's avatar
conrad committed
210 211 212 213

  return 1;
}

214
static int
215
auto_flac0 (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
216
{
217
  unsigned char * header = data;
218 219
  ogg_int64_t granule_rate = 0;

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

226
  oggz_set_granulerate (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);
227

228 229
  oggz_stream_set_numheaders (oggz, serialno, 3);

230 231 232
  return 1;
}

233
static int
234
auto_flac (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
235
{
236
  unsigned char * header = data;
237
  ogg_int64_t granule_rate = 0;
238
  int numheaders;
239

240
  if (length < 51) return 0;
241

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

248
  oggz_set_granulerate (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);
249

250 251 252
  numheaders = INT16_BE_AT(&header[7]);
  oggz_stream_set_numheaders (oggz, serialno, numheaders);

253 254 255
  return 1;
}

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

266
  if (length < 28) return 0;
267 268 269 270 271 272 273 274

  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);

275 276
  oggz_stream_set_numheaders (oggz, serialno, 3);

277 278 279
  return 1;
}

280
static int
281
auto_celt (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
282
{
283
  unsigned char * header = data;
284 285 286
  ogg_int64_t granule_rate = 0;
  int numheaders;

287
  if (length < 56) return 0;
288 289 290 291 292 293 294 295 296 297 298 299 300 301

  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
302
static int
303
auto_cmml (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
conrad's avatar
conrad committed
304
{
305
  unsigned char * header = data;
conrad's avatar
conrad committed
306
  ogg_int64_t granule_rate_numerator = 0, granule_rate_denominator = 0;
307
  int granuleshift;
conrad's avatar
conrad committed
308

309
  if (length < 28) return 0;
conrad's avatar
conrad committed
310 311 312

  granule_rate_numerator = INT64_LE_AT(&header[12]);
  granule_rate_denominator = INT64_LE_AT(&header[20]);
313
  if (length > 28)
314 315 316 317
    granuleshift = (int)header[28];
  else
    granuleshift = 0;

conrad's avatar
conrad committed
318 319 320 321 322
#ifdef DEBUG
  printf ("Got CMML rate %lld/%lld\n", granule_rate_numerator,
	  granule_rate_denominator);
#endif

323 324 325
  oggz_set_granulerate (oggz, serialno,
			granule_rate_numerator,
			OGGZ_AUTO_MULT * granule_rate_denominator);
326
  oggz_set_granuleshift (oggz, serialno, granuleshift);
conrad's avatar
conrad committed
327

328 329
  oggz_stream_set_numheaders (oggz, serialno, 3);

conrad's avatar
conrad committed
330 331 332
  return 1;
}

333
static int
334
auto_kate (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
335
{
336
  unsigned char * header = data;
337 338 339 340
  ogg_int32_t gps_numerator, gps_denominator;
  unsigned char granule_shift = 0;
  int numheaders;

341
  if (length < 64) return 0;
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356

  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
357

358 359 360 361 362
  oggz_stream_set_numheaders (oggz, serialno, numheaders);

  return 1;
}

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

  info = malloc(sizeof(dirac_info));

371
  dirac_parse_info(info, data, length);
j's avatar
j committed
372 373

#ifdef DEBUG
374 375
  printf ("Got dirac fps %d/%d granule_shift %d\n",
    fps_numerator, fps_denominator, granule_shift);
j's avatar
j committed
376 377
#endif

378
  /* the granulerate is twice the frame rate (in order to handle interlace) */
379
  oggz_set_granulerate (oggz, serialno,
380
	2 * (ogg_int64_t)info->fps_numerator,
381
	OGGZ_AUTO_MULT * (ogg_int64_t)info->fps_denominator);
382
  oggz_set_granuleshift (oggz, serialno, granule_shift);
j's avatar
j committed
383

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

  free(info);
  return 1;
}

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

398
  if (length < 48) return 0;
399 400

  fisbone_serialno = (long) INT32_LE_AT(&header[12]);
401 402

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

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

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

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

  /* 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
423

424 425 426
  return 1;
}

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

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

435 436 437
  return 1;
}

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

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

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

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

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

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

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

  if (now > -1) {
477
    return now;
shans's avatar
shans committed
478
  }
479

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

shans's avatar
shans committed
485
    return -1;
486
  }
shans's avatar
shans committed
487 488 489

  return 0;

490
}
shans's avatar
 
shans committed
491

492 493 494 495 496 497 498 499 500 501
/*
 * 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
502
static ogg_int64_t
503
auto_calc_celt (ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {
giles's avatar
giles committed
504

505 506 507 508 509
  /*
   * on the first (b_o_s) packet, set calculate_data to be the number
   * of celt frames per packet
   */

giles's avatar
giles committed
510
  auto_calc_celt_info_t *info
511 512 513 514
          = (auto_calc_celt_info_t *)stream->calculate_data;

  if (stream->calculate_data == NULL) {
    stream->calculate_data = malloc(sizeof(auto_calc_celt_info_t));
515 516
    if (stream->calculate_data == NULL) return -1;

517 518 519 520 521 522 523 524 525 526 527 528
    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
529

530 531 532 533 534 535 536 537 538 539 540 541 542 543
  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
544

545 546 547 548 549 550
    return -1;
  }

  return 0;

}
shans's avatar
 
shans committed
551 552 553 554
/*
 * 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
555 556
 *
 * (see http://www.theora.org/doc/Theora_I_spec.pdf for the theora
shans's avatar
 
shans committed
557 558
 * specification)
 */
559 560 561 562 563 564

typedef struct {
  int encountered_first_data_packet;
} auto_calc_theora_info_t;


giles's avatar
giles committed
565
static ogg_int64_t
566 567 568 569 570
auto_calc_theora(ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {

  long keyframe_no;
  int keyframe_shift;
  unsigned char first_byte;
571
  auto_calc_theora_info_t *info;
572 573 574

  first_byte = op->packet[0];

575
  info = (auto_calc_theora_info_t *)stream->calculate_data;
576

577
  /* header packet */
578 579
  if (first_byte & 0x80)
  {
580 581
    if (info == NULL) {
      stream->calculate_data = malloc(sizeof(auto_calc_theora_info_t));
582
      if (stream->calculate_data == NULL) return -1;
583 584
      info = stream->calculate_data;
    }
585
    info->encountered_first_data_packet = 0;
586
    return (ogg_int64_t)0;
587
  }
giles's avatar
giles committed
588

589 590
  /* known granulepos */
  if (now > (ogg_int64_t)(-1)) {
591
    info->encountered_first_data_packet = 1;
592 593 594 595 596
    return now;
  }

  /* last granulepos unknown */
  if (stream->last_granulepos == -1) {
597 598 599 600 601 602 603 604 605
    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;
606
    return (ogg_int64_t)-1;
607 608
  }

609 610
  /* inter-coded packet */
  if (first_byte & 0x40)
611
  {
612
    return stream->last_granulepos + 1;
613 614
  }

giles's avatar
giles committed
615
  keyframe_shift = stream->granuleshift;
616 617 618 619 620 621 622 623 624
  /*
   * 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
625

626 627 628

}

629
static ogg_int64_t
giles's avatar
giles committed
630
auto_rcalc_theora(ogg_int64_t next_packet_gp, oggz_stream_t *stream,
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649
                  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
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670
/*
 * 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
671
 * byte 28.  1 << (packet[28] >> 4) == long_size.
shans's avatar
 
shans committed
672
 * 1 << (packet[28] & 0xF) == short_size.
giles's avatar
giles committed
673
 *
shans's avatar
 
shans committed
674 675 676 677 678 679 680 681 682 683 684 685 686 687
 * (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
688 689

static ogg_int64_t
shans's avatar
 
shans committed
690 691 692
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
693

shans's avatar
 
shans committed
694 695 696 697 698 699 700
  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
701

shans's avatar
 
shans committed
702 703 704 705
    long_size = 1 << (op->packet[28] >> 4);
    short_size = 1 << (op->packet[28] & 0xF);

    stream->calculate_data = malloc(sizeof(auto_calc_vorbis_info_t));
706 707
    if (stream->calculate_data == NULL) return -1;

shans's avatar
 
shans committed
708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728
    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
729
     * basically has only one actual set of values that everyone uses BUT YOU
shans's avatar
 
shans committed
730 731
     * 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
732
     * think people might want _just that_ and nothing else, you know, for
shans's avatar
 
shans committed
733 734 735 736 737 738 739 740 741 742 743 744 745 746
     * 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
747 748

      /*
shans's avatar
 
shans committed
749 750
       * This is the format of the mode data at the end of the packet for all
       * Vorbis Version 1 :
giles's avatar
giles committed
751
       *
shans's avatar
 
shans committed
752 753 754 755 756 757 758 759 760 761 762 763
       * [ 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
764
       * 0 0 1|0 0 0 0 0
shans's avatar
 
shans committed
765 766 767 768 769 770 771 772 773
       * 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
774 775 776 777 778
       * 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
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795
       * 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
796

shans's avatar
 
shans committed
797 798 799 800 801 802 803
        /*
         * 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
804 805

        if
shans's avatar
 
shans committed
806 807 808
        (
          ((current_pos[-5] & ~((1 << (offset + 1)) - 1)) != 0)
          ||
giles's avatar
giles committed
809 810 811 812
          current_pos[-4] != 0
          ||
          current_pos[-3] != 0
          ||
shans's avatar
 
shans committed
813 814 815 816 817 818 819
          current_pos[-2] != 0
          ||
          ((current_pos[-1] & ((1 << (offset + 1)) - 1)) != 0)
        )
        {
          break;
        }
giles's avatar
giles committed
820

shans's avatar
 
shans committed
821
        size += 1;
giles's avatar
giles committed
822

shans's avatar
 
shans committed
823
        current_pos -= 5;
giles's avatar
giles committed
824 825

      }
shans's avatar
 
shans committed
826 827 828 829 830 831 832 833 834

      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
835
        size_check |= (current_pos[-1] & ~((1 << (offset + 3)) - 1)) >>
shans's avatar
 
shans committed
836 837
                (offset + 3);
      }
giles's avatar
giles committed
838

shans's avatar
 
shans committed
839
      size_check += 1;
840
#ifdef DEBUG
shans's avatar
 
shans committed
841 842 843 844
      if (size_check != size)
      {
        printf("WARNING: size parsing failed for VORBIS mode packets\n");
      }
845
#endif
shans's avatar
 
shans committed
846 847 848 849

      /*
       * store mode size information in our info struct
       */
850
      info = realloc(stream->calculate_data,
shans's avatar
 
shans committed
851
              sizeof(auto_calc_vorbis_info_t) + (size - 1) * sizeof(int));
852 853 854
      if (info == NULL) return -1;

      stream->calculate_data = info;
giles's avatar
giles committed
855

shans's avatar
 
shans committed
856 857 858 859 860 861 862 863 864 865 866 867 868 869
      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
870

shans's avatar
 
shans committed
871
    }
giles's avatar
giles committed
872

shans's avatar
 
shans committed
873 874 875 876 877
    return 0;
  }

  info = (auto_calc_vorbis_info_t *)stream->calculate_data;

878 879
  return -1;

giles's avatar
giles committed
880
  {
shans's avatar
 
shans committed
881 882 883 884 885 886
    /*
     * 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;
887
    ogg_int64_t result;
shans's avatar
 
shans committed
888 889 890

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

shans's avatar
 
shans committed
892
    /*
893 894
     * 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
895
     */
896
    if (now > -1 && stream->last_granulepos == -1) {
shans's avatar
 
shans committed
897
      info->encountered_first_data_packet = 1;
898
      info->last_was_long = size;
899
      return now;
shans's avatar
 
shans committed
900
    }
901 902 903

    if (info->encountered_first_data_packet == 0) {
      info->encountered_first_data_packet = 1;
904
      info->last_was_long = size;
905
      return -1;
shans's avatar
 
shans committed
906
    }
907

shans's avatar
 
shans committed
908
    /*
909 910
     * otherwise, if we haven't yet had a working granulepos, we return
     * -1
shans's avatar
 
shans committed
911
     */
912
    if (stream->last_granulepos == -1) {
913
      info->last_was_long = size;
914 915
      return -1;
    }
shans's avatar
 
shans committed
916

giles's avatar
giles committed
917
    result = stream->last_granulepos +
shans's avatar
 
shans committed
918
      (
giles's avatar
giles committed
919 920
        (info->last_was_long ? info->long_size  : info->short_size)
        +
shans's avatar
 
shans committed
921 922 923
        (size ? info->long_size : info->short_size)
      ) / 4;
    info->last_was_long = size;
shans's avatar
shans committed
924

shans's avatar
 
shans committed
925
    return result;
giles's avatar
giles committed
926

shans's avatar
 
shans committed
927
  }
giles's avatar
giles committed
928

shans's avatar
 
shans committed
929
}
930