Blame src/tools/oggz_tools.c

Packit a38265
/*
Packit a38265
  Copyright (C) 2005 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 <stdio.h>
Packit a38265
#include <stdlib.h>
Packit a38265
#include <string.h>
Packit a38265
#include <getopt.h>
Packit a38265
Packit a38265
#include "oggz/oggz.h"
Packit a38265
Packit a38265
#include "dirac.h"
Packit a38265
#include "oggz_tools_dirac.h"
Packit a38265
Packit a38265
#if defined (WIN32) || defined (__EMX__)
Packit a38265
#include <fcntl.h>
Packit a38265
#include <io.h>
Packit a38265
#define snprintf _snprintf
Packit a38265
#endif
Packit a38265
Packit a38265
#ifdef HAVE_INTTYPES_H
Packit a38265
#  include <inttypes.h>
Packit a38265
#else
Packit a38265
#  define PRId64 "I64d"
Packit a38265
#endif
Packit a38265
Packit a38265
Packit a38265
static  ogg_uint32_t
Packit a38265
_le_32 (ogg_uint32_t i)
Packit a38265
{
Packit a38265
   ogg_uint32_t ret=i;
Packit a38265
#ifdef WORDS_BIGENDIAN
Packit a38265
   ret =  (i>>24);
Packit a38265
   ret += (i>>8) & 0x0000ff00;
Packit a38265
   ret += (i<<8) & 0x00ff0000;
Packit a38265
   ret += (i<<24);
Packit a38265
#endif
Packit a38265
   return ret;
Packit a38265
}
Packit a38265
Packit a38265
static  ogg_uint16_t
Packit a38265
_be_16 (ogg_uint16_t s)
Packit a38265
{
Packit a38265
  unsigned short ret=s;
Packit a38265
#ifndef WORDS_BIGENDIAN
Packit a38265
  ret = (s>>8) & 0x00ffU;
Packit a38265
  ret += (s<<8) & 0xff00U;
Packit a38265
#endif
Packit a38265
  return ret;
Packit a38265
}
Packit a38265
Packit a38265
static  ogg_uint32_t
Packit a38265
_be_32 (ogg_uint32_t i)
Packit a38265
{
Packit a38265
   ogg_uint32_t ret=i;
Packit a38265
#ifndef WORDS_BIGENDIAN
Packit a38265
   ret =  (i>>24);
Packit a38265
   ret += (i>>8) & 0x0000ff00;
Packit a38265
   ret += (i<<8) & 0x00ff0000;
Packit a38265
   ret += (i<<24);
Packit a38265
#endif
Packit a38265
   return ret;
Packit a38265
}
Packit a38265
Packit a38265
static  ogg_int64_t
Packit a38265
_le_64 (ogg_int64_t l)
Packit a38265
{
Packit a38265
  ogg_int64_t ret=l;
Packit a38265
  unsigned char *ucptr = (unsigned char *)&ret;
Packit a38265
#ifdef WORDS_BIGENDIAN
Packit a38265
  unsigned char temp;
Packit a38265
Packit a38265
  temp = ucptr [0] ;
Packit a38265
  ucptr [0] = ucptr [7] ;
Packit a38265
  ucptr [7] = temp ;
Packit a38265
Packit a38265
  temp = ucptr [1] ;
Packit a38265
  ucptr [1] = ucptr [6] ;
Packit a38265
  ucptr [6] = temp ;
Packit a38265
Packit a38265
  temp = ucptr [2] ;
Packit a38265
  ucptr [2] = ucptr [5] ;
Packit a38265
  ucptr [5] = temp ;
Packit a38265
Packit a38265
  temp = ucptr [3] ;
Packit a38265
  ucptr [3] = ucptr [4] ;
Packit a38265
  ucptr [4] = temp ;
Packit a38265
Packit a38265
#endif
Packit a38265
  return (*(ogg_int64_t *)ucptr);
Packit a38265
}
Packit a38265
Packit a38265
#define INT32_LE_AT(x) _le_32((*(ogg_int32_t *)(x)))
Packit a38265
#define INT16_BE_AT(x) _be_16((*(ogg_uint16_t *)(x)))
Packit a38265
#define INT32_BE_AT(x) _be_32((*(ogg_int32_t *)(x)))
Packit a38265
#define INT64_LE_AT(x) _le_64((*(ogg_int64_t *)(x)))
Packit a38265
Packit a38265
typedef char * (* OTCodecInfoFunc) (unsigned char * data, long n);
Packit a38265
Packit a38265
static char *
Packit a38265
ot_theora_info (unsigned char * data, long len)
Packit a38265
{
Packit a38265
  char * buf;
Packit a38265
  int width, height;
Packit a38265
Packit a38265
  if (len < 41) return NULL;
Packit a38265
Packit a38265
  buf = malloc (128);
Packit a38265
Packit a38265
  width = INT16_BE_AT(&data[15]);
Packit a38265
  height = INT16_BE_AT(&data[18]);
Packit a38265
Packit a38265
  snprintf (buf, 128,
Packit a38265
            "\tTheora-Version: %d.%d.%d\n"
Packit a38265
	    "\tVideo-Framerate: %.3f fps\n"
Packit a38265
	    "\tVideo-Width: %d\n\tVideo-Height: %d\n",
Packit a38265
            data[7], data[8], data[9],
Packit a38265
	    (double)INT32_BE_AT(&data[22])/ (double)INT32_BE_AT(&data[26]),
Packit a38265
	    width, height);
Packit a38265
Packit a38265
  return buf;
Packit a38265
}
Packit a38265
Packit a38265
static char *
Packit a38265
ot_vorbis_info (unsigned char * data, long len)
Packit a38265
{
Packit a38265
  char * buf;
Packit a38265
Packit a38265
  if (len < 30) return NULL;
Packit a38265
Packit a38265
  buf = malloc (60);
Packit a38265
Packit a38265
  snprintf (buf, 60,
Packit a38265
	    "\tAudio-Samplerate: %d Hz\n\tAudio-Channels: %d\n",
Packit a38265
	    INT32_LE_AT(&data[12]), (int)(data[11]));
Packit a38265
Packit a38265
  return buf;
Packit a38265
}
Packit a38265
Packit a38265
static char *
Packit a38265
ot_speex_info (unsigned char * data, long len)
Packit a38265
{
Packit a38265
  char * buf;
Packit a38265
Packit a38265
  if (len < 68) return NULL;
Packit a38265
Packit a38265
  buf = malloc (60);
Packit a38265
Packit a38265
  snprintf (buf, 60,
Packit a38265
	    "\tAudio-Samplerate: %d Hz\n\tAudio-Channels: %d\n",
Packit a38265
	    INT32_LE_AT(&data[36]), INT32_LE_AT(&data[48]));
Packit a38265
Packit a38265
  return buf;
Packit a38265
}
Packit a38265
Packit a38265
static char *
Packit a38265
ot_celt_info (unsigned char * data, long len)
Packit a38265
{
Packit a38265
  char * buf;
Packit a38265
Packit a38265
  if (len < 56) return NULL;
Packit a38265
Packit a38265
  buf = malloc (60);
Packit a38265
Packit a38265
  snprintf (buf, 60,
Packit a38265
	    "\tAudio-Samplerate: %d Hz\n\tAudio-Channels: %d\n",
Packit a38265
	    INT32_LE_AT(&data[40]), INT32_LE_AT(&data[44]));
Packit a38265
Packit a38265
  return buf;
Packit a38265
}
Packit a38265
Packit a38265
static char *
Packit a38265
ot_flac_info (unsigned char * data, long len)
Packit a38265
{
Packit a38265
  char * buf;
Packit a38265
  int n;
Packit a38265
  int version_major, version_minor;
Packit a38265
  int samplerate;
Packit a38265
  int channels;
Packit a38265
Packit a38265
  if (len < 30) return NULL;
Packit a38265
Packit a38265
  buf = malloc (120);
Packit a38265
Packit a38265
  version_major = data[5];
Packit a38265
  version_minor = data[6];
Packit a38265
Packit a38265
  samplerate = (ogg_int64_t) (data[27] << 12) | (data[28] << 4) |
Packit a38265
               ((data[29] >> 4)&0xf);
Packit a38265
  channels = 1 + ((data[29] >> 1)&0x7);
Packit a38265
Packit a38265
  n = snprintf (buf, 120,
Packit a38265
	    "\tAudio-Samplerate: %d Hz\n\tAudio-Channels: %d\n",
Packit a38265
            samplerate, channels);
Packit a38265
Packit a38265
  snprintf (buf+n, 120-n,
Packit a38265
            "\tFLAC-Ogg-Mapping-Version: %d.%d\n",
Packit a38265
            version_major, version_minor);
Packit a38265
Packit a38265
  return buf;
Packit a38265
}
Packit a38265
Packit a38265
static char *
Packit a38265
ot_oggpcm2_info (unsigned char * data, long len)
Packit a38265
{
Packit a38265
  char * buf;
Packit a38265
Packit a38265
  if (len < 28) return NULL;
Packit a38265
Packit a38265
  buf = malloc (60);
Packit a38265
Packit a38265
  snprintf (buf, 60,
Packit a38265
	    "\tAudio-Samplerate: %d Hz\n\tAudio-Channels: %d\n",
Packit a38265
	    INT32_BE_AT(&data[16]), (int)data[21]);
Packit a38265
Packit a38265
  return buf;
Packit a38265
}
Packit a38265
Packit a38265
static char *
Packit a38265
ot_kate_info (unsigned char * data, long len)
Packit a38265
{
Packit a38265
  char * buf;
Packit a38265
Packit a38265
  static const size_t KATE_INFO_BUFFER_LEN =
Packit a38265
    1 /* tab */
Packit a38265
  +18 /* "Content-Language: " */
Packit a38265
  +15 /* 15 chars + NUL for language */
Packit a38265
   +1 /* \n */
Packit a38265
   +1 /* tab */
Packit a38265
  +18 /* "Content-Category: " */
Packit a38265
  +15 /* 15 chars + NUL for category */
Packit a38265
   +1 /* \n */
Packit a38265
   +1;/* terminating NUL */
Packit a38265
Packit a38265
  if (len < 64) return NULL;
Packit a38265
Packit a38265
  buf = malloc (KATE_INFO_BUFFER_LEN);
Packit a38265
Packit a38265
  /* Are these headers coming from some standard ? If so, need to find what should these be for Kate */
Packit a38265
  snprintf (buf, KATE_INFO_BUFFER_LEN,
Packit a38265
	    "\tContent-Language: %s\n"
Packit a38265
            "\tContent-Category: %s\n",
Packit a38265
	    &data[32], &data[48]);
Packit a38265
Packit a38265
#undef KATE_INFO_BUFFER_LEN
Packit a38265
Packit a38265
  return buf;
Packit a38265
}
Packit a38265
Packit a38265
static char *
Packit a38265
ot_dirac_info (unsigned char * data, long len)
Packit a38265
{
Packit a38265
  char * buf;
Packit a38265
  dirac_info *info;
Packit a38265
Packit a38265
  /* read in useful bits from sequence header */
Packit a38265
  if (len < 24) return NULL;
Packit a38265
Packit a38265
  buf = malloc (80);
Packit a38265
  info = malloc(sizeof(dirac_info));
Packit a38265
Packit a38265
  if (dirac_parse_info(info, data, len) == -1) {
Packit a38265
    free (info);
Packit a38265
    free (buf);
Packit a38265
    return NULL;
Packit a38265
  }
Packit a38265
Packit a38265
  snprintf (buf, 80,
Packit a38265
	    "\tVideo-Framerate: %.3f fps\n"
Packit a38265
	    "\tVideo-Width: %d\n\tVideo-Height: %d\n",
Packit a38265
	    (double)info->fps_numerator/ (double)info->fps_denominator,
Packit a38265
	    info->width, info->height);
Packit a38265
Packit a38265
  free(info);
Packit a38265
Packit a38265
  return buf;
Packit a38265
}
Packit a38265
Packit a38265
Packit a38265
static char *
Packit a38265
ot_skeleton_info (unsigned char * data, long len)
Packit a38265
{
Packit a38265
  char * buf;
Packit a38265
  double pres_n, pres_d, pres;
Packit a38265
  double base_n, base_d, base;
Packit a38265
Packit a38265
  if (len < 64L) return NULL;
Packit a38265
Packit a38265
  buf = malloc (60);
Packit a38265
Packit a38265
  pres_n = (double)INT64_LE_AT(&data[12]);
Packit a38265
  pres_d = (double)INT64_LE_AT(&data[20]);
Packit a38265
  if (pres_d != 0.0) {
Packit a38265
    pres = pres_n / pres_d;
Packit a38265
  } else {
Packit a38265
    pres = 0.0;
Packit a38265
  }
Packit a38265
Packit a38265
  base_n = (double)INT64_LE_AT(&data[28]);
Packit a38265
  base_d = (double)INT64_LE_AT(&data[36]);
Packit a38265
  if (base_d != 0.0) {
Packit a38265
    base = base_n / base_d;
Packit a38265
  } else {
Packit a38265
    base = 0.0;
Packit a38265
  }
Packit a38265
Packit a38265
  snprintf (buf, 60,
Packit a38265
	    "\tPresentation-Time: %.3f\n\tBasetime: %.3f\n", pres, base);
Packit a38265
Packit a38265
  return buf;
Packit a38265
}
Packit a38265
Packit a38265
static const OTCodecInfoFunc codec_ident[] = {
Packit a38265
  ot_theora_info,
Packit a38265
  ot_vorbis_info,
Packit a38265
  ot_speex_info,
Packit a38265
  ot_oggpcm2_info,
Packit a38265
  NULL,             /* CMML */
Packit a38265
  NULL,             /* ANNODEX */
Packit a38265
  ot_skeleton_info,
Packit a38265
  NULL,             /* FLAC0 */
Packit a38265
  ot_flac_info,     /* FLAC */
Packit a38265
  NULL,             /* ANXDATA */
Packit a38265
  ot_celt_info,     /* CELT */
Packit a38265
  ot_kate_info,     /* KATE */
Packit a38265
  ot_dirac_info,    /* BBCD */
Packit a38265
  NULL              /* UNKNOWN */
Packit a38265
};
Packit a38265
Packit a38265
const char *
Packit a38265
ot_page_identify (OGGZ *oggz, const ogg_page * og, char ** info)
Packit a38265
{
Packit a38265
  const char * ret = NULL;
Packit a38265
  int serial_no;
Packit a38265
  int content;
Packit a38265
Packit a38265
  /*
Packit a38265
   * identify stream content using oggz_stream_get_content, identify
Packit a38265
   * stream content name using oggz_stream_get_content_type
Packit a38265
   */
Packit a38265
Packit a38265
  serial_no = ogg_page_serialno((ogg_page *)og);
Packit a38265
Packit a38265
  content = oggz_stream_get_content(oggz, serial_no);
Packit a38265
  if (content == OGGZ_ERR_BAD_SERIALNO) return NULL;
Packit a38265
Packit a38265
  ret = oggz_stream_get_content_type(oggz, serial_no);
Packit a38265
Packit a38265
  if (info != NULL)
Packit a38265
  {
Packit a38265
    if (codec_ident[content] != NULL)
Packit a38265
    {
Packit a38265
      *info = codec_ident[content](og->body, og->body_len);
Packit a38265
    }
Packit a38265
  }
Packit a38265
Packit a38265
  return ret;
Packit a38265
}
Packit a38265
Packit a38265
/*
Packit a38265
 * Print a number of bytes to 3 significant figures
Packit a38265
 * using standard abbreviations (GB, MB, kB, byte[s])
Packit a38265
 */
Packit a38265
int
Packit a38265
ot_fprint_bytes (FILE * stream, long nr_bytes)
Packit a38265
{
Packit a38265
  if (nr_bytes > (1L<<30)) {
Packit a38265
    return fprintf (stream, "%0.3f GB",
Packit a38265
		   (double)nr_bytes / (1024.0 * 1024.0 * 1024.0));
Packit a38265
  } else if (nr_bytes > (1L<<20)) {
Packit a38265
    return fprintf (stream, "%0.3f MB",
Packit a38265
		   (double)nr_bytes / (1024.0 * 1024.0));
Packit a38265
  } else if (nr_bytes > (1L<<10)) {
Packit a38265
    return fprintf (stream, "%0.3f kB",
Packit a38265
		   (double)nr_bytes / (1024.0));
Packit a38265
  } else if (nr_bytes == 1) {
Packit a38265
    return fprintf (stream, "1 byte");
Packit a38265
  } else {
Packit a38265
    return fprintf (stream, "%ld bytes", nr_bytes);
Packit a38265
  }
Packit a38265
}
Packit a38265
Packit a38265
/*
Packit a38265
 * Print a bitrate to 3 significant figures
Packit a38265
 * using quasi-standard abbreviations (Gbps, Mbps, kbps, bps)
Packit a38265
 */
Packit a38265
int
Packit a38265
ot_print_bitrate (long bps)
Packit a38265
{
Packit a38265
  if (bps > (1000000000L)) {
Packit a38265
    return printf ("%0.3f Gbps",
Packit a38265
		   (double)bps / (1000.0 * 1000.0 * 1000.0));
Packit a38265
  } else if (bps > (1000000L)) {
Packit a38265
    return printf ("%0.3f Mbps",
Packit a38265
		   (double)bps / (1000.0 * 1000.0));
Packit a38265
  } else if (bps > (1000L)) {
Packit a38265
    return printf ("%0.3f kbps",
Packit a38265
		   (double)bps / (1000.0));
Packit a38265
  } else {
Packit a38265
    return printf ("%ld bps", bps);
Packit a38265
  }
Packit a38265
}
Packit a38265
Packit a38265
int
Packit a38265
ot_fprint_time (FILE * stream, double seconds)
Packit a38265
{
Packit a38265
  int hrs, min;
Packit a38265
  double sec;
Packit a38265
  char * sign;
Packit a38265
Packit a38265
  sign = (seconds < 0.0) ? "-" : "";
Packit a38265
Packit a38265
  if (seconds < 0.0) seconds = -seconds;
Packit a38265
Packit a38265
  hrs = (int) (seconds/3600.0);
Packit a38265
  min = (int) ((seconds - ((double)hrs * 3600.0)) / 60.0);
Packit a38265
  sec = seconds - ((double)hrs * 3600.0)- ((double)min * 60.0);
Packit a38265
Packit a38265
  return fprintf (stream, "%s%02d:%02d:%06.3f", sign, hrs, min, sec);
Packit a38265
}
Packit a38265
Packit a38265
void
Packit a38265
ot_dirac_gpos_parse (ogg_int64_t iframe, ogg_int64_t pframe,
Packit a38265
                     struct ot_dirac_gpos * dg)
Packit a38265
{
Packit a38265
  dg->pt = (iframe + pframe) >> 9;
Packit a38265
  dg->dist = ((iframe & 0xff) << 8) | (pframe & 0xff);
Packit a38265
  dg->delay = pframe >> 9;
Packit a38265
  dg->dt = (ogg_int64_t)dg->pt - dg->delay;
Packit a38265
}
Packit a38265
Packit a38265
int
Packit a38265
ot_fprint_granulepos (FILE * stream, OGGZ * oggz, long serialno,
Packit a38265
                      ogg_int64_t granulepos)
Packit a38265
{
Packit a38265
  int ret, granuleshift = oggz_get_granuleshift (oggz, serialno);
Packit a38265
Packit a38265
  if (granuleshift < 1) {
Packit a38265
    ret = fprintf (stream, "%" PRId64, granulepos);
Packit a38265
  } else {
Packit a38265
    ogg_int64_t iframe, pframe;
Packit a38265
    iframe = granulepos >> granuleshift;
Packit a38265
    pframe = granulepos - (iframe << granuleshift);
Packit a38265
Packit a38265
    if (oggz_stream_get_content (oggz, serialno) != OGGZ_CONTENT_DIRAC) {
Packit a38265
      ret = fprintf (stream, "%" PRId64 "|%" PRId64, iframe, pframe);
Packit a38265
    } else {
Packit a38265
      struct ot_dirac_gpos dg;
Packit a38265
      ot_dirac_gpos_parse (iframe, pframe, &dg;;
Packit a38265
      ret = fprintf (stream,
Packit a38265
		     "(pt:%u,dt:%" PRId64 ",dist:%hu,delay:%hu)",
Packit a38265
		     dg.pt, dg.dt, dg.dist, dg.delay);
Packit a38265
    }
Packit a38265
Packit a38265
}
Packit a38265
Packit a38265
  return ret;
Packit a38265
}
Packit a38265
Packit a38265
void
Packit a38265
ot_init (void)
Packit a38265
{
Packit a38265
#ifdef _WIN32
Packit a38265
  /* We need to set stdin/stdout to binary mode on Win32 */
Packit a38265
Packit a38265
  _setmode( _fileno( stdin ), _O_BINARY );
Packit a38265
  _setmode( _fileno( stdout ), _O_BINARY );
Packit a38265
#endif
Packit a38265
#ifdef __EMX__
Packit a38265
  /* We need to set stdin/stdout to binary mode on OS/2*/
Packit a38265
Packit a38265
  setmode( fileno( stdin ), O_BINARY );
Packit a38265
  setmode( fileno( stdout ), O_BINARY );
Packit a38265
#endif
Packit a38265
}
Packit a38265
Packit a38265
void
Packit a38265
ot_print_short_options (char * optstring)
Packit a38265
{
Packit a38265
  char *c;
Packit a38265
Packit a38265
  for (c=optstring; *c; c++) {
Packit a38265
    if (*c != ':') printf ("-%c ", *c);
Packit a38265
  }
Packit a38265
Packit a38265
  printf ("\n");
Packit a38265
}
Packit a38265
Packit a38265
#ifdef HAVE_GETOPT_LONG
Packit a38265
void
Packit a38265
ot_print_options (struct option long_options[], char * optstring)
Packit a38265
{
Packit a38265
  int i;
Packit a38265
  for (i=0; long_options[i].name != NULL; i++)  {
Packit a38265
    printf ("--%s ", long_options[i].name);
Packit a38265
  }
Packit a38265
Packit a38265
  ot_print_short_options (optstring);
Packit a38265
}
Packit a38265
#endif