Blame ext/ogg/vorbis_parse.c

Packit 971217
/*
Packit 971217
   This file borrowed from liboggz
Packit 971217
 */
Packit 971217
/*
Packit 971217
   Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Packit 971217
   Organisation (CSIRO) Australia
Packit 971217
Packit 971217
   Redistribution and use in source and binary forms, with or without
Packit 971217
   modification, are permitted provided that the following conditions
Packit 971217
   are met:
Packit 971217
Packit 971217
   - Redistributions of source code must retain the above copyright
Packit 971217
   notice, this list of conditions and the following disclaimer.
Packit 971217
Packit 971217
   - Redistributions in binary form must reproduce the above copyright
Packit 971217
   notice, this list of conditions and the following disclaimer in the
Packit 971217
   documentation and/or other materials provided with the distribution.
Packit 971217
Packit 971217
   - Neither the name of CSIRO Australia nor the names of its
Packit 971217
   contributors may be used to endorse or promote products derived from
Packit 971217
   this software without specific prior written permission.
Packit 971217
Packit 971217
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 971217
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 971217
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
Packit 971217
   PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ORGANISATION OR
Packit 971217
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
Packit 971217
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
Packit 971217
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
Packit 971217
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
Packit 971217
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
Packit 971217
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Packit 971217
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 971217
*/
Packit 971217
Packit 971217
/*
Packit 971217
 * oggz_auto.c
Packit 971217
 *
Packit 971217
 * Conrad Parker <conrad@annodex.net>
Packit 971217
 */
Packit 971217
Packit 971217
#include "config.h"
Packit 971217
Packit 971217
#include <stdlib.h>
Packit 971217
#include <string.h>
Packit 971217
Packit 971217
#include "gstoggstream.h"
Packit 971217
#include "vorbis_parse.h"
Packit 971217
Packit 971217
/*
Packit 971217
 * Vorbis packets can be short or long, and each packet overlaps the previous
Packit 971217
 * and next packets.  The granulepos of a packet is always the last sample
Packit 971217
 * that is completely decoded at the end of decoding that packet - i.e. the
Packit 971217
 * last packet before the first overlapping packet.  If the sizes of packets
Packit 971217
 * are 's' and 'l', then the increment will depend on the previous and next
Packit 971217
 * packet types:
Packit 971217
 *  v                             prev<<1 | next
Packit 971217
 * lll:           l/2             3
Packit 971217
 * lls:           3l/4 - s/4      2
Packit 971217
 * lsl:           s/2
Packit 971217
 * lss:           s/2
Packit 971217
 * sll:           l/4 + s/4       1
Packit 971217
 * sls:           l/2             0
Packit 971217
 * ssl:           s/2
Packit 971217
 * sss:           s/2
Packit 971217
 *
Packit 971217
 * The previous and next packet types can be inferred from the current packet
Packit 971217
 * (additional information is not required)
Packit 971217
 *
Packit 971217
 * The two blocksizes can be determined from the first header packet, by reading
Packit 971217
 * byte 28.  1 << (packet[28] >> 4) == long_size.
Packit 971217
 * 1 << (packet[28] & 0xF) == short_size.
Packit 971217
 *
Packit 971217
 * (see http://xiph.org/vorbis/doc/Vorbis_I_spec.html for specification)
Packit 971217
 */
Packit 971217
Packit 971217
Packit 971217
void
Packit 971217
gst_parse_vorbis_header_packet (GstOggStream * pad, ogg_packet * packet)
Packit 971217
{
Packit 971217
  /*
Packit 971217
   * on the first (b_o_s) packet, determine the long and short sizes,
Packit 971217
   * and then calculate l/2, l/4 - s/4, 3 * l/4 - s/4, l/2 - s/2 and s/2
Packit 971217
   */
Packit 971217
  int short_size;
Packit 971217
  int long_size;
Packit 971217
Packit 971217
  long_size = 1 << (packet->packet[28] >> 4);
Packit 971217
  short_size = 1 << (packet->packet[28] & 0xF);
Packit 971217
Packit 971217
  pad->nln_increments[3] = long_size >> 1;
Packit 971217
  pad->nln_increments[2] = 3 * (long_size >> 2) - (short_size >> 2);
Packit 971217
  pad->nln_increments[1] = (long_size >> 2) + (short_size >> 2);
Packit 971217
  pad->nln_increments[0] = pad->nln_increments[3];
Packit 971217
  pad->short_size = short_size;
Packit 971217
  pad->long_size = long_size;
Packit 971217
  pad->nsn_increment = short_size >> 1;
Packit 971217
}
Packit 971217
Packit 971217
void
Packit 971217
gst_parse_vorbis_setup_packet (GstOggStream * pad, ogg_packet * op)
Packit 971217
{
Packit 971217
  /*
Packit 971217
   * the code pages, a whole bunch of other fairly useless stuff, AND,
Packit 971217
   * RIGHT AT THE END (of a bunch of variable-length compressed rubbish that
Packit 971217
   * basically has only one actual set of values that everyone uses BUT YOU
Packit 971217
   * CAN'T BE SURE OF THAT, OH NO YOU CAN'T) is the only piece of data that's
Packit 971217
   * actually useful to us - the packet modes (because it's inconceivable to
Packit 971217
   * think people might want _just that_ and nothing else, you know, for
Packit 971217
   * seeking and stuff).
Packit 971217
   *
Packit 971217
   * Fortunately, because of the mandate that non-used bits must be zero
Packit 971217
   * at the end of the packet, we might be able to sneakily work backwards
Packit 971217
   * and find out the information we need (namely a mapping of modes to
Packit 971217
   * packet sizes)
Packit 971217
   */
Packit 971217
  unsigned char *current_pos = &op->packet[op->bytes - 1];
Packit 971217
  int offset;
Packit 971217
  int size;
Packit 971217
  int size_check;
Packit 971217
  int *mode_size_ptr;
Packit 971217
  int i;
Packit 971217
  int ii;
Packit 971217
Packit 971217
  /*
Packit 971217
   * This is the format of the mode data at the end of the packet for all
Packit 971217
   * Vorbis Version 1 :
Packit 971217
   *
Packit 971217
   * [ 6:number_of_modes ]
Packit 971217
   * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ]
Packit 971217
   * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ]
Packit 971217
   * [ 1:size | 16:window_type(0) | 16:transform_type(0) | 8:mapping ]
Packit 971217
   * [ 1:framing(1) ]
Packit 971217
   *
Packit 971217
   * e.g.:
Packit 971217
   *
Packit 971217
   *              <-
Packit 971217
   * 0 0 0 0 0 1 0 0
Packit 971217
   * 0 0 1 0 0 0 0 0
Packit 971217
   * 0 0 1 0 0 0 0 0
Packit 971217
   * 0 0 1|0 0 0 0 0
Packit 971217
   * 0 0 0 0|0|0 0 0
Packit 971217
   * 0 0 0 0 0 0 0 0
Packit 971217
   * 0 0 0 0|0 0 0 0
Packit 971217
   * 0 0 0 0 0 0 0 0
Packit 971217
   * 0 0 0 0|0 0 0 0
Packit 971217
   * 0 0 0|1|0 0 0 0 |
Packit 971217
   * 0 0 0 0 0 0 0 0 V
Packit 971217
   * 0 0 0|0 0 0 0 0
Packit 971217
   * 0 0 0 0 0 0 0 0
Packit 971217
   * 0 0 1|0 0 0 0 0
Packit 971217
   * 0 0|1|0 0 0 0 0
Packit 971217
   *
Packit 971217
   *
Packit 971217
   * i.e. each entry is an important bit, 32 bits of 0, 8 bits of blah, a
Packit 971217
   * bit of 1.
Packit 971217
   * Let's find our last 1 bit first.
Packit 971217
   *
Packit 971217
   */
Packit 971217
Packit 971217
  size = 0;
Packit 971217
Packit 971217
  offset = 8;
Packit 971217
  while (!((1 << --offset) & *current_pos)) {
Packit 971217
    if (offset == 0) {
Packit 971217
      offset = 8;
Packit 971217
      current_pos -= 1;
Packit 971217
    }
Packit 971217
  }
Packit 971217
Packit 971217
  while (1) {
Packit 971217
Packit 971217
    /*
Packit 971217
     * from current_pos-5:(offset+1) to current_pos-1:(offset+1) should
Packit 971217
     * be zero
Packit 971217
     */
Packit 971217
    offset = (offset + 7) % 8;
Packit 971217
    if (offset == 7)
Packit 971217
      current_pos -= 1;
Packit 971217
Packit 971217
    if (((current_pos[-5] & ~((1 << (offset + 1)) - 1)) != 0)
Packit 971217
        ||
Packit 971217
        current_pos[-4] != 0
Packit 971217
        ||
Packit 971217
        current_pos[-3] != 0
Packit 971217
        ||
Packit 971217
        current_pos[-2] != 0
Packit 971217
        || ((current_pos[-1] & ((1 << (offset + 1)) - 1)) != 0)
Packit 971217
        ) {
Packit 971217
      break;
Packit 971217
    }
Packit 971217
Packit 971217
    size += 1;
Packit 971217
Packit 971217
    current_pos -= 5;
Packit 971217
Packit 971217
  }
Packit 971217
Packit 971217
  /* Give ourselves a chance to recover if we went back too far by using
Packit 971217
   * the size check. */
Packit 971217
  for (ii = 0; ii < 2; ii++) {
Packit 971217
    if (offset > 4) {
Packit 971217
      size_check = (current_pos[0] >> (offset - 5)) & 0x3F;
Packit 971217
    } else {
Packit 971217
      /* mask part of byte from current_pos */
Packit 971217
      size_check = (current_pos[0] & ((1 << (offset + 1)) - 1));
Packit 971217
      /* shift to appropriate position */
Packit 971217
      size_check <<= (5 - offset);
Packit 971217
      /* or in part of byte from current_pos - 1 */
Packit 971217
      size_check |= (current_pos[-1] & ~((1 << (offset + 3)) - 1)) >>
Packit 971217
          (offset + 3);
Packit 971217
    }
Packit 971217
Packit 971217
    size_check += 1;
Packit 971217
    if (size_check == size) {
Packit 971217
      break;
Packit 971217
    }
Packit 971217
    offset = (offset + 1) % 8;
Packit 971217
    if (offset == 0)
Packit 971217
      current_pos += 1;
Packit 971217
    current_pos += 5;
Packit 971217
    size -= 1;
Packit 971217
  }
Packit 971217
Packit 971217
  /* Store mode size information in our info struct */
Packit 971217
  i = -1;
Packit 971217
  while ((1 << (++i)) < size);
Packit 971217
  pad->vorbis_log2_num_modes = i;
Packit 971217
Packit 971217
  mode_size_ptr = pad->vorbis_mode_sizes;
Packit 971217
Packit 971217
  for (i = 0; i < size; i++) {
Packit 971217
    offset = (offset + 1) % 8;
Packit 971217
    if (offset == 0)
Packit 971217
      current_pos += 1;
Packit 971217
    *mode_size_ptr++ = (current_pos[0] >> offset) & 0x1;
Packit 971217
    current_pos += 5;
Packit 971217
  }
Packit 971217
Packit 971217
}