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

173 174
  oggz_stream_set_numheaders (oggz, serialno, 3);

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

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

  return 1;
}

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

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

  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

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

  return 1;
}

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

215 216
  granule_rate = (ogg_int64_t) (header[14] << 12) | (header[15] << 4) | 
            ((header[16] >> 4)&0xf);
217 218 219 220
#ifdef DEBUG
    printf ("Got flac rate %d\n", (int)granule_rate);
#endif
    
221
  oggz_set_granulerate (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);
222

223 224
  oggz_stream_set_numheaders (oggz, serialno, 3);

225 226 227
  return 1;
}

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

235
  if (length < 51) return 0;
236

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

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

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

248 249 250
  return 1;
}

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

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

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

270 271
  oggz_stream_set_numheaders (oggz, serialno, 3);

272 273 274
  return 1;
}

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

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

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

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

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

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

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

323 324
  oggz_stream_set_numheaders (oggz, serialno, 3);

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

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

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

  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);
 
  oggz_stream_set_numheaders (oggz, serialno, numheaders);

  return 1;
}

j's avatar
j committed
358
static int
359
auto_dirac (OGGZ * oggz, long serialno, unsigned char * data, long length, void * user_data)
j's avatar
j committed
360 361 362 363 364 365 366
{
  char keyframe_granule_shift = 32;
  int keyframe_shift;
  dirac_info *info;

  info = malloc(sizeof(dirac_info));

367
  dirac_parse_info(info, data, length);
j's avatar
j committed
368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390

  /*
  FIXME: where is this in Ogg Dirac?
  keyframe_granule_shift = (char) ((header[40] & 0x03) << 3);
  keyframe_granule_shift |= (header[41] & 0xe0) >> 5; 
  */
  keyframe_shift = keyframe_granule_shift;

#ifdef DEBUG
  printf ("Got dirac fps %d/%d, keyframe_shift %d\n",
	  fps_numerator, fps_denominator, keyframe_shift);
#endif

  oggz_set_granulerate (oggz, serialno, (ogg_int64_t)info->fps_numerator,
                        OGGZ_AUTO_MULT * (ogg_int64_t)info->fps_denominator);
  oggz_set_granuleshift (oggz, serialno, keyframe_shift);

  oggz_stream_set_numheaders (oggz, serialno, 3);

  free(info);
  return 1;
}

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

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

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

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

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

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

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

  /* Increment the number of headers for this stream */
  numheaders = oggz_stream_get_numheaders (oggz, serialno);
  oggz_stream_set_numheaders (oggz, serialno, numheaders+1);
conrad's avatar
conrad committed
424
				
425 426 427
  return 1;
}

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

  /* For skeleton, numheaders will get incremented as each header is seen */
  oggz_stream_set_numheaders (oggz, serialno, 1);
435 436 437 438
  
  return 1;
}

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

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

449 450 451 452 453 454 455
static ogg_int64_t 
auto_calc_speex(ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {
  
  /*
   * on the first (b_o_s) packet, set calculate_data to be the number
   * of speex frames per packet
   */
shans's avatar
shans committed
456 457 458 459

  auto_calc_speex_info_t *info 
          = (auto_calc_speex_info_t *)stream->calculate_data;

460
  if (stream->calculate_data == NULL) {
shans's avatar
shans committed
461 462 463 464 465 466 467
    stream->calculate_data = malloc(sizeof(auto_calc_speex_info_t));
    info = stream->calculate_data;
    info->encountered_first_data_packet = 0;
    info->packet_size = 
            (*(int *)(op->packet + 64)) * (*(int *)(op->packet + 56));
    info->headers_encountered = 1;
    return 0;
468 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 484 485
  if (info->encountered_first_data_packet) {
    if (stream->last_granulepos > 0) {
      return stream->last_granulepos + info->packet_size;
    }
    
    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 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548
/*
 * 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;

static ogg_int64_t 
auto_calc_celt (ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {
  
  /*
   * on the first (b_o_s) packet, set calculate_data to be the number
   * of celt frames per packet
   */

  auto_calc_celt_info_t *info 
          = (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;
  }
  
  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;
    }
    
    return -1;
  }

  return 0;

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

typedef struct {
  int encountered_first_data_packet;
} auto_calc_theora_info_t;


563 564 565 566 567 568
static ogg_int64_t 
auto_calc_theora(ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {

  long keyframe_no;
  int keyframe_shift;
  unsigned char first_byte;
569
  auto_calc_theora_info_t *info;
570 571 572

  first_byte = op->packet[0];

573
  info = (auto_calc_theora_info_t *)stream->calculate_data;
574

575
  /* header packet */
576 577
  if (first_byte & 0x80)
  {
578 579 580 581
    if (info == NULL) {
      stream->calculate_data = malloc(sizeof(auto_calc_theora_info_t));
      info = stream->calculate_data;
    }
582
    info->encountered_first_data_packet = 0;
583
    return (ogg_int64_t)0;
584 585
  }
  
586 587
  /* known granulepos */
  if (now > (ogg_int64_t)(-1)) {
588
    info->encountered_first_data_packet = 1;
589 590 591 592 593
    return now;
  }

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

606 607
  /* inter-coded packet */
  if (first_byte & 0x40)
608
  {
609
    return stream->last_granulepos + 1;
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
  }

  keyframe_shift = stream->granuleshift; 
  /*
   * 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;
  

}

626
static ogg_int64_t
627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646
auto_rcalc_theora(ogg_int64_t next_packet_gp, oggz_stream_t *stream, 
                  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
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 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 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868
/*
 * 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
 * byte 28.  1 << (packet[28] >> 4) == long_size.  
 * 1 << (packet[28] & 0xF) == short_size.
 * 
 * (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;
        

static ogg_int64_t 
auto_calc_vorbis(ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op) {

  auto_calc_vorbis_info_t *info;
  
  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;
  
    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
     * basically has only one actual set of values that everyone uses BUT YOU 
     * 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
     * think people might want _just that_ and nothing else, you know, for 
     * 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;
      
      /* 
       * This is the format of the mode data at the end of the packet for all
       * Vorbis Version 1 :
       * 
       * [ 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
       * 0 0 1|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 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
       * 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 
       * 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)
      {
        
        /*
         * 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;
        
        if 
        (
          ((current_pos[-5] & ~((1 << (offset + 1)) - 1)) != 0)
          ||
          current_pos[-4] != 0 
          || 
          current_pos[-3] != 0 
          || 
          current_pos[-2] != 0
          ||
          ((current_pos[-1] & ((1 << (offset + 1)) - 1)) != 0)
        )
        {
          break;
        }
        
        size += 1;
        
        current_pos -= 5;
        
      } 

      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 */
        size_check |= (current_pos[-1] & ~((1 << (offset + 3)) - 1)) >> 
                (offset + 3);
      }
      
      size_check += 1;
      if (size_check != size)
      {
        printf("WARNING: size parsing failed for VORBIS mode packets\n");
      }

      /*
       * 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);
      
      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;
      }
      
    }
    
    return 0;
  }

  info = (auto_calc_vorbis_info_t *)stream->calculate_data;

869 870
  return -1;

shans's avatar
 
shans committed
871 872 873 874 875 876 877
  { 
    /*
     * 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;
878
    ogg_int64_t result;
shans's avatar
 
shans committed
879 880 881 882 883

    mode = (op->packet[0] >> 1) & ((1 << info->log2_num_modes) - 1);
    size = info->mode_sizes[mode];
  
    /*
884 885
     * 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
886
     */
887
    if (now > -1 && stream->last_granulepos == -1) {
shans's avatar
 
shans committed
888
      info->encountered_first_data_packet = 1;
889
      info->last_was_long = size;
890
      return now;
shans's avatar
 
shans committed
891
    }
892 893 894

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

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

    result = stream->last_granulepos + 
      (
        (info->last_was_long ? info->long_size  : info->short_size) 
        + 
        (size ? info->long_size : info->short_size)
      ) / 4;
    info->last_was_long = size;
shans's avatar
shans committed
915

shans's avatar
 
shans committed
916 917 918 919 920
    return result;
    
  }
  
}
921

922 923 924 925 926 927 928 929 930 931 932
ogg_int64_t
auto_rcalc_vorbis(ogg_int64_t next_packet_gp, oggz_stream_t *stream,
                  ogg_packet *this_packet, ogg_packet *next_packet) {

  auto_calc_vorbis_info_t *info = 
                  (auto_calc_vorbis_info_t *)stream->calculate_data;

  int mode = 
      (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;
933
  ogg_int64_t r;
934 935 936 937

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

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

}

944 945
/**
 * FLAC
946 947 948 949 950 951 952 953 954 955 956 957 958
 * 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
 */

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

964 965 966
static ogg_int64_t 
auto_calc_flac (ogg_int64_t now, oggz_stream_t *stream, ogg_packet *op)
{
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 1057
  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;
1058 1059
}

1060
const oggz_auto_contenttype_t oggz_auto_codec_ident[] = {
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
  {"\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},
  {"\177FLAC", 4, "Flac", auto_flac, auto_calc_flac, NULL},
  {"AnxData", 7, "AnxData", auto_anxdata, NULL, NULL},
1071
  {"CELT    ", 8, "CELT", auto_celt, auto_calc_celt, NULL},
1072
  {"\200kate\0\0\0", 8, "Kate", auto_kate, NULL, NULL},
j's avatar
j committed
1073
  {"BBCD\0", 5, "Dirac", auto_dirac, NULL, NULL},
1074
  {"", 0, "Unknown", NULL, NULL, NULL}
1075 1076
}; 

1077 1078
static int
oggz_auto_identify (OGGZ * oggz, long serialno, unsigned char * data, long len)
1079
{
1080 1081 1082 1083 1084 1085
  int i;
  
  for (i = 0; i < OGGZ_CONTENT_UNKNOWN; i++)
  {
    const oggz_auto_contenttype_t *codec = oggz_auto_codec_ident + i;
    
1086 1087
    if (len >= codec->bos_str_len &&
        memcmp (data, codec->bos_str, codec->bos_str_len) == 0) {
1088 1089 1090 1091 1092 1093 1094 1095 1096 1097
      
      oggz_stream_set_content (oggz, serialno, i);
      
      return 1;
    }
  }
                      
  oggz_stream_set_content (oggz, serialno, OGGZ_CONTENT_UNKNOWN);
  return 0;
}
conrad's avatar
conrad committed
1098

1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110
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
1111
int
1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129
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
oggz_auto_read_bos_packet (OGGZ * oggz, ogg_packet * op, long serialno, 
                           void * user_data)
1130
{
1131
  int content = 0;
conrad's avatar
conrad committed
1132

1133 1134 1135
  content = oggz_stream_get_content(oggz, serialno);
  if (content < 0 || content >= OGGZ_CONTENT_UNKNOWN) {
    return 0;
1136 1137 1138 1139
  } 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
1140 1141 1142
  }
}

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

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

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

  return 0;

1165 1166
}

1167 1168 1169 1170 1171
int
oggz_auto_read_comments (OGGZ * oggz, oggz_stream_t * stream, long serialno,
                         ogg_packet * op)
{
  int offset = -1;
conrad's avatar
conrad committed
1172
  long len = -1;
1173 1174 1175

  switch (stream->content) {
    case OGGZ_CONTENT_VORBIS:
1176 1177
      if (op->bytes > 7 && memcmp (op->packet, "\003vorbis", 7) == 0)
        offset = 7;
1178 1179 1180 1181
      break;
    case OGGZ_CONTENT_SPEEX:
      offset = 0; break;
    case OGGZ_CONTENT_THEORA:
1182 1183
      if (op->bytes > 7 && memcmp (op->packet, "\201theora", 7) == 0)
        offset = 7;
1184
      break;
1185
    case OGGZ_CONTENT_KATE:
1186 1187
      if (op->bytes > 9 && memcmp (op->packet, "\201kate\0\0\0", 8) == 0) {
        /* we skip the reserved 0 byte after the signature */
1188 1189 1190
        offset = 9;
      }
      break;
conrad's avatar
conrad committed
1191 1192 1193 1194 1195
    case OGGZ_CONTENT_FLAC:
      if (op->bytes > 4 && (op->packet[0] & 0x7) == 4) {
        len = (op->packet[1]<<16) + (op->packet[2]<<8) + op->packet[3];
        offset = 4;
      }
1196
      break;
1197 1198 1199 1200
    default:
      break;
  }

conrad's avatar
conrad committed
1201 1202 1203 1204 1205
  /* The length of the comments to decode is the rest of the packet,
   * unless otherwise determined (ie. for FLAC) */
  if (len == -1)
    len = op->bytes - offset;

1206
  if (offset >= 0) {
conrad's avatar
conrad committed
1207
    oggz_comments_decode (oggz, serialno, op->packet+offset, len);
1208 1209 1210 1211 1212
  }

  return 0;
}