Blame src/liboggz/metric_internal.c

Packit a38265
/*
Packit a38265
   Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Packit a38265
   Organisation (CSIRO) Australia
Packit a38265
Packit a38265
   Redistribution and use in source and binary forms, with or without
Packit a38265
   modification, are permitted provided that the following conditions
Packit a38265
   are met:
Packit a38265
Packit a38265
   - Redistributions of source code must retain the above copyright
Packit a38265
   notice, this list of conditions and the following disclaimer.
Packit a38265
Packit a38265
   - Redistributions in binary form must reproduce the above copyright
Packit a38265
   notice, this list of conditions and the following disclaimer in the
Packit a38265
   documentation and/or other materials provided with the distribution.
Packit a38265
Packit a38265
   - Neither the name of CSIRO Australia nor the names of its
Packit a38265
   contributors may be used to endorse or promote products derived from
Packit a38265
   this software without specific prior written permission.
Packit a38265
Packit a38265
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit a38265
   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit a38265
   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
Packit a38265
   PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ORGANISATION OR
Packit a38265
   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
Packit a38265
   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
Packit a38265
   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
Packit a38265
   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
Packit a38265
   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
Packit a38265
   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
Packit a38265
   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit a38265
*/
Packit a38265
Packit a38265
#include "config.h"
Packit a38265
Packit a38265
#include "oggz_private.h"
Packit a38265
Packit a38265
#include "oggz/oggz_stream.h"
Packit a38265
Packit a38265
static ogg_int64_t
Packit a38265
oggz_metric_dirac (OGGZ * oggz, long serialno,
Packit a38265
                   ogg_int64_t granulepos, void * user_data)
Packit a38265
{
Packit a38265
  oggz_stream_t * stream;
Packit a38265
  ogg_int64_t iframe, pframe;
Packit a38265
  ogg_uint32_t pt;
Packit a38265
  ogg_uint16_t dist;
Packit a38265
  ogg_uint16_t delay;
Packit a38265
  ogg_int64_t dt;
Packit a38265
  ogg_int64_t units;
Packit a38265
Packit a38265
  stream = oggz_get_stream (oggz, serialno);
Packit a38265
  if (stream == NULL) return -1;
Packit a38265
Packit a38265
  iframe = granulepos >> stream->granuleshift;
Packit a38265
  pframe = granulepos - (iframe << stream->granuleshift);
Packit a38265
  pt = (iframe + pframe) >> 9;
Packit a38265
  delay = pframe >> 9;
Packit a38265
  dt = (ogg_int64_t)pt - delay;
Packit a38265
Packit a38265
  units = dt * stream->granulerate_d / stream->granulerate_n;
Packit a38265
Packit a38265
#ifdef DEBUG
Packit a38265
  printf ("oggz_..._granuleshift: serialno %010lu Got frame or field %lld (%lld + %lld): %lld units\n",
Packit a38265
	  serialno, dt, iframe, pframe, units);
Packit a38265
#endif
Packit a38265
Packit a38265
  return units;
Packit a38265
}
Packit a38265
Packit a38265
static ogg_int64_t
Packit a38265
oggz_metric_default_granuleshift (OGGZ * oggz, long serialno,
Packit a38265
				  ogg_int64_t granulepos, void * user_data)
Packit a38265
{
Packit a38265
  oggz_stream_t * stream;
Packit a38265
  ogg_int64_t iframe, pframe;
Packit a38265
  ogg_int64_t units;
Packit a38265
Packit a38265
  stream = oggz_get_stream (oggz, serialno);
Packit a38265
  if (stream == NULL) return -1;
Packit a38265
Packit a38265
  iframe = granulepos >> stream->granuleshift;
Packit a38265
  pframe = granulepos - (iframe << stream->granuleshift);
Packit a38265
  granulepos = iframe + pframe;
Packit a38265
  if (granulepos > 0) granulepos -= stream->first_granule;
Packit a38265
Packit a38265
  units = granulepos * stream->granulerate_d / stream->granulerate_n;
Packit a38265
Packit a38265
#ifdef DEBUG
Packit a38265
  printf ("oggz_..._granuleshift: serialno %010lu Got frame %lld (%lld + %lld): %lld units\n",
Packit a38265
	  serialno, granulepos, iframe, pframe, units);
Packit a38265
#endif
Packit a38265
Packit a38265
  return units;
Packit a38265
}
Packit a38265
Packit a38265
static ogg_int64_t
Packit a38265
oggz_metric_default_linear (OGGZ * oggz, long serialno, ogg_int64_t granulepos,
Packit a38265
			    void * user_data)
Packit a38265
{
Packit a38265
  oggz_stream_t * stream;
Packit a38265
Packit a38265
  stream = oggz_get_stream (oggz, serialno);
Packit a38265
  if (stream == NULL) return -1;
Packit a38265
Packit a38265
  return (stream->granulerate_d * granulepos / stream->granulerate_n);
Packit a38265
}
Packit a38265
Packit a38265
static int
Packit a38265
oggz_metric_update (OGGZ * oggz, long serialno)
Packit a38265
{
Packit a38265
  oggz_stream_t * stream;
Packit a38265
Packit a38265
  if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
Packit a38265
Packit a38265
  stream = oggz_get_stream (oggz, serialno);
Packit a38265
  if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
Packit a38265
Packit a38265
  /* we divide by the granulerate, ie. mult by gr_d/gr_n, so ensure
Packit a38265
   * numerator is non-zero */
Packit a38265
  if (stream->granulerate_n == 0) {
Packit a38265
    stream->granulerate_n= 1;
Packit a38265
    stream->granulerate_d = 0;
Packit a38265
  }
Packit a38265
Packit a38265
  if (stream->granuleshift == 0) {
Packit a38265
    return oggz_set_metric_internal (oggz, serialno,
Packit a38265
				     oggz_metric_default_linear,
Packit a38265
				     NULL, 1);
Packit a38265
  } else if (oggz_stream_get_content (oggz, serialno) == OGGZ_CONTENT_DIRAC) {
Packit a38265
    return oggz_set_metric_internal (oggz, serialno,
Packit a38265
				     oggz_metric_dirac,
Packit a38265
				     NULL, 1);
Packit a38265
  } else {
Packit a38265
    return oggz_set_metric_internal (oggz, serialno,
Packit a38265
				     oggz_metric_default_granuleshift,
Packit a38265
				     NULL, 1);
Packit a38265
  }
Packit a38265
}
Packit a38265
Packit a38265
int
Packit a38265
oggz_set_granuleshift (OGGZ * oggz, long serialno, int granuleshift)
Packit a38265
{
Packit a38265
  oggz_stream_t * stream;
Packit a38265
Packit a38265
  if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
Packit a38265
Packit a38265
  stream = oggz_get_stream (oggz, serialno);
Packit a38265
  if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
Packit a38265
Packit a38265
  stream->granuleshift = granuleshift;
Packit a38265
Packit a38265
  return oggz_metric_update (oggz, serialno);
Packit a38265
}
Packit a38265
Packit a38265
int
Packit a38265
oggz_get_granuleshift (OGGZ * oggz, long serialno)
Packit a38265
{
Packit a38265
  oggz_stream_t * stream;
Packit a38265
Packit a38265
  if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
Packit a38265
Packit a38265
  stream = oggz_get_stream (oggz, serialno);
Packit a38265
  if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
Packit a38265
Packit a38265
  return stream->granuleshift;
Packit a38265
}
Packit a38265
Packit a38265
int
Packit a38265
oggz_set_granulerate (OGGZ * oggz, long serialno,
Packit a38265
		      ogg_int64_t granule_rate_numerator,
Packit a38265
		      ogg_int64_t granule_rate_denominator)
Packit a38265
{
Packit a38265
  oggz_stream_t * stream;
Packit a38265
Packit a38265
  if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
Packit a38265
Packit a38265
  stream = oggz_get_stream (oggz, serialno);
Packit a38265
  if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
Packit a38265
Packit a38265
  stream->granulerate_n = granule_rate_numerator;
Packit a38265
  stream->granulerate_d = granule_rate_denominator;
Packit a38265
Packit a38265
  return oggz_metric_update (oggz, serialno);
Packit a38265
}
Packit a38265
Packit a38265
int
Packit a38265
oggz_get_granulerate (OGGZ * oggz, long serialno,
Packit a38265
		      ogg_int64_t * granulerate_n,
Packit a38265
		      ogg_int64_t * granulerate_d)
Packit a38265
{
Packit a38265
  oggz_stream_t * stream;
Packit a38265
Packit a38265
  if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
Packit a38265
Packit a38265
  stream = oggz_get_stream (oggz, serialno);
Packit a38265
  if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
Packit a38265
Packit a38265
  *granulerate_n = stream->granulerate_n;
Packit a38265
  *granulerate_d = stream->granulerate_d / OGGZ_AUTO_MULT;
Packit a38265
Packit a38265
  return 0;
Packit a38265
}
Packit a38265
Packit a38265
int
Packit a38265
oggz_set_first_granule (OGGZ * oggz, long serialno,
Packit a38265
		        ogg_int64_t first_granule)
Packit a38265
{
Packit a38265
  oggz_stream_t * stream;
Packit a38265
Packit a38265
  if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
Packit a38265
Packit a38265
  stream = oggz_get_stream (oggz, serialno);
Packit a38265
  if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
Packit a38265
Packit a38265
  stream->first_granule = first_granule;
Packit a38265
Packit a38265
  return oggz_metric_update (oggz, serialno);
Packit a38265
}
Packit a38265
Packit a38265
/** DEPRECATED **/
Packit a38265
int
Packit a38265
oggz_set_metric_linear (OGGZ * oggz, long serialno,
Packit a38265
			ogg_int64_t granule_rate_numerator,
Packit a38265
			ogg_int64_t granule_rate_denominator)
Packit a38265
{
Packit a38265
  oggz_stream_t * stream;
Packit a38265
Packit a38265
  if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
Packit a38265
Packit a38265
  stream = oggz_get_stream (oggz, serialno);
Packit a38265
  if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
Packit a38265
Packit a38265
  stream->granulerate_n = granule_rate_numerator;
Packit a38265
  stream->granulerate_d = granule_rate_denominator;
Packit a38265
  stream->granuleshift = 0;
Packit a38265
Packit a38265
  return oggz_metric_update (oggz, serialno);
Packit a38265
}
Packit a38265