Blame src/tools/oggz-dump.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 <stdio.h>
Packit a38265
#include <stdlib.h>
Packit a38265
#include <string.h>
Packit a38265
#ifndef WIN32
Packit a38265
#include <strings.h>
Packit a38265
#endif
Packit a38265
#include <ctype.h>
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
#include <getopt.h>
Packit a38265
#include <errno.h>
Packit a38265
Packit a38265
#include "oggz/oggz.h"
Packit a38265
#include "oggz_tools.h"
Packit a38265
Packit a38265
/*#define DEBUG*/
Packit a38265
Packit a38265
#ifdef WIN32                                                                   
Packit a38265
#define strcasecmp _stricmp
Packit a38265
#endif  
Packit a38265
Packit a38265
#undef MIN
Packit a38265
#define MIN(a,b) (((a)<(b))?(a):(b))
Packit a38265
Packit a38265
typedef struct {
Packit a38265
  OggzTable * serialno_table;
Packit a38265
  OggzTable * content_types_table;
Packit a38265
  OggzReadPacket read_packet;
Packit a38265
  int dump_bits;
Packit a38265
  int dump_char;
Packit a38265
  int hide_offset;
Packit a38265
  int hide_serialno;
Packit a38265
  int hide_granulepos;
Packit a38265
  int hide_packetno;
Packit a38265
} ODData;
Packit a38265
Packit a38265
static char * progname;
Packit a38265
static FILE * outfile = NULL;
Packit a38265
static int truth = 1;
Packit a38265
Packit a38265
static void
Packit a38265
usage (char * progname)
Packit a38265
{
Packit a38265
  printf ("Usage: %s [options] filename\n", progname);
Packit a38265
  printf ("Hexdump packets of an Ogg file, or revert an Ogg file from such a hexdump\n");
Packit a38265
  printf ("\nDump format options\n");
Packit a38265
  printf ("  -b, --binary           Generate a binary dump of each packet\n");
Packit a38265
  printf ("  -x, --hexadecimal      Generate a hexadecimal dump of each packet\n");
Packit a38265
  printf ("\nFiltering options\n");
Packit a38265
  printf ("  -n, --new              Only dump the first packet of each logical bitstream\n");
Packit a38265
  printf ("  -c content-type, --content-type content-type\n");
Packit a38265
  printf ("                         Dump only the logical bitstreams for a specified\n");
Packit a38265
  printf ("                         content-type. Run oggz-known-codecs for a list of\n");
Packit a38265
  printf ("                         codec names which can be detected by this version of oggz.\n");
Packit a38265
  printf ("  -s serialno, --serialno serialno\n");
Packit a38265
  printf ("                         Dump only the logical bitstream with specified serialno\n");
Packit a38265
  printf ("  -O, --hide-offset      Hide the byte offset of each packet\n");
Packit a38265
  printf ("  -S, --hide-serialno    Hide the serialno field of each packet\n");
Packit a38265
  printf ("  -G, --hide-granulepos  Hide the granulepos field of each packet\n");
Packit a38265
  printf ("  -P, --hide-packetno    Hide the packetno field of each packet\n");
Packit a38265
  printf ("\nMode options\n");
Packit a38265
  printf ("  -r, --revert           Revert an oggz-dump. Generates an Ogg bitstream\n");
Packit a38265
  printf ("                         as prescribed in the input oggz-dump\n");
Packit a38265
  printf ("\nMiscellaneous options\n");
Packit a38265
  printf ("  -o filename, --output filename\n");
Packit a38265
  printf ("                         Specify output filename\n");
Packit a38265
  printf ("  -h, --help             Display this help and exit\n");
Packit a38265
  printf ("  -v, --version          Output version information and exit\n");
Packit a38265
  printf ("\n");
Packit a38265
  printf ("Please report bugs to <ogg-dev@xiph.org>\n");
Packit a38265
}
Packit a38265
Packit a38265
static void
Packit a38265
exit_out_of_memory (void)
Packit a38265
{
Packit a38265
  fprintf (stderr, "%s: Out of memory\n", progname);
Packit a38265
  exit (1);
Packit a38265
}
Packit a38265
Packit a38265
static ODData *
Packit a38265
oddata_new ()
Packit a38265
{
Packit a38265
  ODData * oddata = malloc (sizeof (ODData));
Packit a38265
Packit a38265
  if (oddata == NULL) return NULL;
Packit a38265
Packit a38265
  memset (oddata, 0, sizeof (ODData));
Packit a38265
Packit a38265
  oddata->serialno_table = oggz_table_new ();
Packit a38265
  if (oddata->serialno_table == NULL) {
Packit a38265
    free (oddata);
Packit a38265
    return NULL;
Packit a38265
  }
Packit a38265
Packit a38265
  oddata->content_types_table = oggz_table_new ();
Packit a38265
  if (oddata->content_types_table == NULL) {
Packit a38265
    free (oddata->serialno_table);
Packit a38265
    free (oddata);
Packit a38265
    return NULL;
Packit a38265
  }
Packit a38265
Packit a38265
  oddata->dump_bits = 0;
Packit a38265
  oddata->dump_char = 1;
Packit a38265
Packit a38265
  oddata->hide_offset = 0;
Packit a38265
  oddata->hide_serialno = 0;
Packit a38265
  oddata->hide_granulepos = 0;
Packit a38265
  oddata->hide_packetno = 0;
Packit a38265
Packit a38265
  return oddata;
Packit a38265
}
Packit a38265
Packit a38265
static void
Packit a38265
oddata_delete (ODData * oddata)
Packit a38265
{
Packit a38265
  oggz_table_delete (oddata->serialno_table);
Packit a38265
  oggz_table_delete (oddata->content_types_table);
Packit a38265
Packit a38265
  free (oddata);
Packit a38265
}
Packit a38265
Packit a38265
static void
Packit a38265
dump_char_line (unsigned char * buf, long n)
Packit a38265
{
Packit a38265
  int i;
Packit a38265
Packit a38265
  fprintf (outfile, "  ");
Packit a38265
Packit a38265
  for (i = 0; i < n; i++) {
Packit a38265
    if (isgraph(buf[i])) fprintf (outfile, "%c", buf[i]);
Packit a38265
    else if (isspace(buf[i])) fprintf (outfile, " ");
Packit a38265
    else fprintf (outfile, ".");
Packit a38265
  }
Packit a38265
}
Packit a38265
Packit a38265
static void
Packit a38265
hex_dump (unsigned char * buf, long n, int dump_char)
Packit a38265
{
Packit a38265
  int i;
Packit a38265
  long remaining = n, count = 0;
Packit a38265
  long rowlen;
Packit a38265
Packit a38265
  while (remaining > 0) {
Packit a38265
    rowlen = MIN (remaining, 16);
Packit a38265
Packit a38265
    if (n > 0xffffff)
Packit a38265
      fprintf (outfile, "%08lx:", count);
Packit a38265
    else if (n > 0xffff)
Packit a38265
      fprintf (outfile, "  %06lx:", count);
Packit a38265
    else
Packit a38265
      fprintf (outfile, "    %04lx:", count);
Packit a38265
Packit a38265
    for (i = 0; i < rowlen; i++) {
Packit a38265
      if (!(i%2)) fprintf (outfile, " ");
Packit a38265
      fprintf (outfile, "%02x", buf[i]);
Packit a38265
    }
Packit a38265
Packit a38265
    for (; i < 16; i++) {
Packit a38265
      if (!(i%2)) fprintf (outfile, " ");
Packit a38265
      fprintf (outfile, "  ");
Packit a38265
    }
Packit a38265
Packit a38265
    if (dump_char)
Packit a38265
      dump_char_line (buf, rowlen);
Packit a38265
Packit a38265
    fprintf(outfile, "\n");
Packit a38265
Packit a38265
    remaining -= rowlen;
Packit a38265
    buf += rowlen;
Packit a38265
    count += rowlen;
Packit a38265
  }
Packit a38265
}
Packit a38265
Packit a38265
static void
Packit a38265
bin_dump (unsigned char * buf, long n, int dump_char)
Packit a38265
{
Packit a38265
  int i, j;
Packit a38265
  long remaining = n, count = 0;
Packit a38265
  long rowlen;
Packit a38265
Packit a38265
  while (remaining > 0) {
Packit a38265
    rowlen = MIN (remaining, 6);
Packit a38265
Packit a38265
    if (n > 0xffffff)
Packit a38265
      fprintf (outfile, "%08lx:", count);
Packit a38265
    else if (n > 0xffff)
Packit a38265
      fprintf (outfile, "  %06lx:", count);
Packit a38265
    else
Packit a38265
      fprintf (outfile, "    %04lx:", count);
Packit a38265
Packit a38265
    for (i = 0; i < rowlen; i++) {
Packit a38265
      fprintf (outfile, " ");
Packit a38265
#ifdef WORDS_BIGENDIAN
Packit a38265
      for (j = 0; j < 8; j++)
Packit a38265
#else
Packit a38265
      for (j = 7; j >= 0; j--)
Packit a38265
#endif
Packit a38265
	fprintf (outfile, "%c", (buf[i]&(1<
Packit a38265
    }
Packit a38265
Packit a38265
    for (; i < 6; i++) {
Packit a38265
      if (!(i%2)) fprintf (outfile, " ");
Packit a38265
      fprintf (outfile, "         ");
Packit a38265
    }
Packit a38265
Packit a38265
    if (dump_char)
Packit a38265
      dump_char_line (buf, rowlen);
Packit a38265
Packit a38265
    printf("\n");
Packit a38265
Packit a38265
    remaining -= rowlen;
Packit a38265
    buf += rowlen;
Packit a38265
    count += rowlen;
Packit a38265
  }
Packit a38265
}
Packit a38265
Packit a38265
static int
Packit a38265
read_packet (OGGZ * oggz, oggz_packet * zp, long serialno, void * user_data)
Packit a38265
{
Packit a38265
  ODData * oddata = (ODData *) user_data;
Packit a38265
  ogg_packet * op = &zp->op;
Packit a38265
  ogg_int64_t units;
Packit a38265
  double time_offset;
Packit a38265
  ogg_int64_t calced_gp = oggz_tell_granulepos (oggz);
Packit a38265
Packit a38265
  if (oddata->hide_offset) {
Packit a38265
    fprintf (outfile, "oOo");
Packit a38265
  } else {
Packit a38265
    units = oggz_tell_units (oggz);
Packit a38265
    if (units == -1) {
Packit a38265
      fprintf (outfile, "%" PRId64 "x", oggz_tell (oggz));
Packit a38265
    } else {
Packit a38265
      time_offset = (double)units / 1000.0;
Packit a38265
      ot_fprint_time (outfile, time_offset);
Packit a38265
    }
Packit a38265
  }
Packit a38265
Packit a38265
  fprintf (outfile, ": serialno %010lu, ",
Packit a38265
	   oddata->hide_serialno ? -1 : serialno);
Packit a38265
Packit a38265
  if (oddata->hide_granulepos) {
Packit a38265
    fprintf (outfile, "granulepos gGg");
Packit a38265
  } else {
Packit a38265
    if (op->granulepos == -1) {
Packit a38265
      fprintf (outfile, "calc. gpos ");
Packit a38265
    } else {
Packit a38265
      fprintf (outfile, "granulepos ");
Packit a38265
    }
Packit a38265
    ot_fprint_granulepos (outfile, oggz, serialno, calced_gp);
Packit a38265
Packit a38265
    if (op->granulepos != -1 && op->granulepos != calced_gp) {
Packit a38265
      fprintf (outfile, " ERR: file gp ");
Packit a38265
      ot_fprint_granulepos (outfile, oggz, serialno, op->granulepos);
Packit a38265
    }
Packit a38265
  }
Packit a38265
Packit a38265
  fprintf (outfile, ", packetno %" PRId64,
Packit a38265
	   oddata->hide_packetno ? -1 : op->packetno);
Packit a38265
Packit a38265
  if (op->b_o_s) {
Packit a38265
    fprintf (outfile, " *** bos");
Packit a38265
  }
Packit a38265
Packit a38265
  if (op->e_o_s) {
Packit a38265
    fprintf (outfile, " *** eos");
Packit a38265
  }
Packit a38265
Packit a38265
  fprintf (outfile, ": ");
Packit a38265
  ot_fprint_bytes (outfile, op->bytes);
Packit a38265
  fputc ('\n', outfile);
Packit a38265
Packit a38265
  if (oddata->dump_bits) {
Packit a38265
    bin_dump (op->packet, op->bytes, oddata->dump_char);
Packit a38265
  } else {
Packit a38265
    hex_dump (op->packet, op->bytes, oddata->dump_char);
Packit a38265
  }
Packit a38265
Packit a38265
  fprintf (outfile, "\n");
Packit a38265
Packit a38265
  return 0;
Packit a38265
}
Packit a38265
Packit a38265
static int
Packit a38265
filter_page (OGGZ * oggz, const ogg_page * og, long serialno, void * user_data)
Packit a38265
{
Packit a38265
  ODData * oddata = (ODData *) user_data;
Packit a38265
  const char * ident;
Packit a38265
  int i, n;
Packit a38265
Packit a38265
  if (ogg_page_bos ((ogg_page *)og)) {
Packit a38265
    ident = ot_page_identify (oggz, og, NULL);
Packit a38265
    if (ident) {
Packit a38265
      n = oggz_table_size (oddata->content_types_table);
Packit a38265
      for (i = 0; i < n; i++) {
Packit a38265
	char * c = oggz_table_nth (oddata->content_types_table, i, NULL);
Packit a38265
	if (strcasecmp (c, ident) == 0) {
Packit a38265
	  oggz_set_read_callback (oggz, serialno, oddata->read_packet, oddata);
Packit a38265
	}
Packit a38265
      }
Packit a38265
    }
Packit a38265
  }
Packit a38265
Packit a38265
  return 0;
Packit a38265
}
Packit a38265
Packit a38265
static int
Packit a38265
read_new_packet (OGGZ * oggz, oggz_packet * zp, long serialno, void * user_data)
Packit a38265
{
Packit a38265
  ogg_packet * op = &zp->op;
Packit a38265
Packit a38265
  if (op->b_o_s) {
Packit a38265
    read_packet (oggz, zp, serialno, user_data);
Packit a38265
    return OGGZ_CONTINUE;
Packit a38265
  } else {
Packit a38265
    return OGGZ_STOP_OK;
Packit a38265
  }
Packit a38265
}
Packit a38265
Packit a38265
static void
Packit a38265
revert_packet (OGGZ * oggz, ogg_packet * op, long serialno, int flush)
Packit a38265
{
Packit a38265
  unsigned char buf[1024];
Packit a38265
  long n;
Packit a38265
  int ret;
Packit a38265
Packit a38265
#ifdef DEBUG
Packit a38265
  printf ("feeding packet (%010lu) %ld bytes %s, %s\n",
Packit a38265
          serialno, op->bytes,
Packit a38265
          op->b_o_s ? "bos" : "not bos",
Packit a38265
          op->e_o_s ? "eos" : "not eos");
Packit a38265
#endif
Packit a38265
  if ((ret = oggz_write_feed (oggz, op, serialno, flush, NULL)) != 0) {
Packit a38265
    fprintf (stderr, "%s: oggz_write_feed error %d\n", progname, ret);
Packit a38265
  }
Packit a38265
Packit a38265
  while ((n = oggz_write_output (oggz, buf, 1024)) > 0) {
Packit a38265
    if (fwrite (buf, 1, n, outfile) < (size_t)n)
Packit a38265
      break;
Packit a38265
  }
Packit a38265
}
Packit a38265
Packit a38265
static void
Packit a38265
revert_file (char * infilename)
Packit a38265
{
Packit a38265
  OGGZ * oggz;
Packit a38265
  FILE * infile;
Packit a38265
  char line[120];
Packit a38265
  int hh, mm, ss;
Packit a38265
  unsigned int offset;
Packit a38265
  long current_serialno = -1, serialno;
Packit a38265
  ogg_int64_t granulepos, iframe, pframe, packetno;
Packit a38265
  int is_packetinfo = 0;
Packit a38265
  int bos = 0, eos = 0;
Packit a38265
Packit a38265
  int line_offset = 0, consumed = 0;
Packit a38265
Packit a38265
  unsigned char * packet = NULL;
Packit a38265
  long max_bytes = 0;
Packit a38265
Packit a38265
  ogg_packet op;
Packit a38265
  int flush = 1;
Packit a38265
  char c;
Packit a38265
Packit a38265
  if (strcmp (infilename, "-") == 0) {
Packit a38265
    infile = stdin;
Packit a38265
  } else {
Packit a38265
    infile = fopen (infilename, "rb");
Packit a38265
  }
Packit a38265
Packit a38265
  oggz = oggz_new (OGGZ_WRITE|OGGZ_NONSTRICT|OGGZ_AUTO);
Packit a38265
  if (oggz == NULL)
Packit a38265
    exit_out_of_memory();
Packit a38265
Packit a38265
  while (fgets (line, 120, infile)) {
Packit a38265
    line_offset = 0;
Packit a38265
Packit a38265
    /* Skip time offsets, OR ensure line_offset is 0 */
Packit a38265
    if (sscanf (line, "%2d:%2d:%2d.%n", &hh, &mm, &ss, &line_offset) < 3)
Packit a38265
      line_offset = 0;
Packit a38265
Packit a38265
    is_packetinfo = 0;
Packit a38265
    if (sscanf (&line[line_offset], "%x: serialno %ld, granulepos %" PRId64 ", packetno %" PRId64 "%n",
Packit a38265
		&offset, &serialno, &granulepos, &packetno,
Packit a38265
		&line_offset) >= 4) {
Packit a38265
      is_packetinfo = 1;
Packit a38265
    } else {
Packit a38265
      if (sscanf (&line[line_offset], "%x: serialno %ld, granulepos %" PRId64 "%" PRId64 ", packetno %" PRId64 "%n",
Packit a38265
		  &offset, &serialno, &iframe, &pframe, &packetno,
Packit a38265
		  &line_offset) >= 5) {
Packit a38265
	int granuleshift = oggz_get_granuleshift (oggz, serialno);
Packit a38265
	is_packetinfo = 1;
Packit a38265
	granulepos = (iframe<
Packit a38265
      }
Packit a38265
    }
Packit a38265
Packit a38265
    if (is_packetinfo) {
Packit a38265
      /* flush any existing packets */
Packit a38265
      if (current_serialno != -1) {
Packit a38265
        revert_packet (oggz, &op, current_serialno, flush);
Packit a38265
      }
Packit a38265
Packit a38265
      /* Start new packet */
Packit a38265
      bos = 0; eos = 0;
Packit a38265
      while ((c=line[line_offset++]) && c != '*');
Packit a38265
      if (c == '*') {
Packit a38265
	if (!strncmp (&line[line_offset], "** bos", 6)) {
Packit a38265
	  bos = 1;
Packit a38265
	  line_offset += 6;
Packit a38265
	}
Packit a38265
	if (!strncmp (&line[line_offset], "** eos", 6)) {
Packit a38265
	  eos = 1;
Packit a38265
	  line_offset += 6;
Packit a38265
	}
Packit a38265
      }
Packit a38265
Packit a38265
      current_serialno = serialno;
Packit a38265
Packit a38265
      op.packet = packet;
Packit a38265
      op.bytes = 0;
Packit a38265
      op.b_o_s = bos;
Packit a38265
      op.e_o_s = eos;
Packit a38265
      op.granulepos = granulepos;
Packit a38265
      op.packetno = packetno;
Packit a38265
Packit a38265
    } else {
Packit a38265
      int nread = 0;
Packit a38265
      unsigned int val = 0;
Packit a38265
      unsigned int offset;
Packit a38265
Packit a38265
      if (current_serialno != -1 &&
Packit a38265
	  sscanf (line, "%x:%n", &offset, &line_offset) >= 1) {
Packit a38265
        /* NUL-terminate after hex data: don't scan char representation */
Packit a38265
        line[50] = '\0';
Packit a38265
	while (nread < 16 &&
Packit a38265
	       (sscanf (&line[line_offset], "%2x%n", &val, &consumed) > 0)) {
Packit a38265
	  op.bytes++;
Packit a38265
	  if (op.bytes > max_bytes) {
Packit a38265
	    unsigned char * new_packet;
Packit a38265
	    size_t new_size;
Packit a38265
Packit a38265
	    if (max_bytes == 0) {
Packit a38265
	      new_size = 128;
Packit a38265
	    } else {
Packit a38265
	      new_size = max_bytes * 2;
Packit a38265
	    }
Packit a38265
Packit a38265
	    new_packet = (unsigned char *) realloc((void *)packet, new_size);
Packit a38265
	    if (new_packet == NULL) {
Packit a38265
              exit_out_of_memory ();
Packit a38265
	    } else {
Packit a38265
	      max_bytes = (long)new_size;
Packit a38265
	      packet = new_packet;
Packit a38265
	      op.packet = packet;
Packit a38265
	    }
Packit a38265
	  }
Packit a38265
Packit a38265
	  packet[op.bytes-1] = (unsigned char) val;
Packit a38265
Packit a38265
	  line_offset += consumed;
Packit a38265
	  nread++;
Packit a38265
	}
Packit a38265
      }
Packit a38265
    }
Packit a38265
  }
Packit a38265
Packit a38265
  /* flush any existing packets */
Packit a38265
  if (current_serialno != -1) {
Packit a38265
    revert_packet (oggz, &op, current_serialno, flush);
Packit a38265
  }
Packit a38265
Packit a38265
  oggz_close(oggz);
Packit a38265
  fclose (infile);
Packit a38265
}
Packit a38265
Packit a38265
int
Packit a38265
main (int argc, char ** argv)
Packit a38265
{
Packit a38265
  int show_version = 0;
Packit a38265
  int show_help = 0;
Packit a38265
Packit a38265
  ODData * oddata;
Packit a38265
  OGGZ * oggz;
Packit a38265
  char * infilename = NULL, * outfilename = NULL;
Packit a38265
  int revert = 0;
Packit a38265
  long serialno;
Packit a38265
  int i, size;
Packit a38265
  long n;
Packit a38265
Packit a38265
  int filter_serialnos = 0;
Packit a38265
  int filter_content_types = 0;
Packit a38265
Packit a38265
  char * optstring = "hvbxnro:s:c:OSGP";
Packit a38265
Packit a38265
#ifdef HAVE_GETOPT_LONG
Packit a38265
  static struct option long_options[] = {
Packit a38265
    {"help", no_argument, 0, 'h'},
Packit a38265
    {"version", no_argument, 0, 'v'},
Packit a38265
    {"binary", no_argument, 0, 'b'},
Packit a38265
    {"hexadecimal", no_argument, 0, 'x'},
Packit a38265
    {"new", no_argument, 0, 'n'},
Packit a38265
    {"revert", no_argument, 0, 'r'},
Packit a38265
    {"output", required_argument, 0, 'o'},
Packit a38265
    {"serialno", required_argument, 0, 's'},
Packit a38265
    {"content-type", required_argument, 0, 'c'},
Packit a38265
    {"hide-offset", no_argument, 0, 'O'},
Packit a38265
    {"hide-serialno", no_argument, 0, 'S'},
Packit a38265
    {"hide-granulepos", no_argument, 0, 'G'},
Packit a38265
    {"hide-packetno", no_argument, 0, 'P'},
Packit a38265
    {0,0,0,0}
Packit a38265
  };
Packit a38265
#endif
Packit a38265
Packit a38265
  ot_init ();
Packit a38265
Packit a38265
  progname = argv[0];
Packit a38265
Packit a38265
  if (argc < 2) {
Packit a38265
    usage (progname);
Packit a38265
    return (1);
Packit a38265
  }
Packit a38265
Packit a38265
  if (!strncmp (argv[1], "-?", 2)) {
Packit a38265
#ifdef HAVE_GETOPT_LONG
Packit a38265
    ot_print_options (long_options, optstring);
Packit a38265
#else
Packit a38265
    ot_print_short_options (optstring);
Packit a38265
#endif
Packit a38265
    exit (0);
Packit a38265
  }
Packit a38265
Packit a38265
  oddata = oddata_new ();
Packit a38265
  if (oddata == NULL)
Packit a38265
    exit_out_of_memory();
Packit a38265
Packit a38265
  oddata->read_packet = read_packet;
Packit a38265
Packit a38265
  while (1) {
Packit a38265
#ifdef HAVE_GETOPT_LONG
Packit a38265
    i = getopt_long(argc, argv, optstring, long_options, NULL);
Packit a38265
#else
Packit a38265
    i = getopt (argc, argv, optstring);
Packit a38265
#endif
Packit a38265
    if (i == -1) break;
Packit a38265
    if (i == ':') {
Packit a38265
      usage (progname);
Packit a38265
      goto exit_err;
Packit a38265
    }
Packit a38265
Packit a38265
    switch (i) {
Packit a38265
    case 'h': /* help */
Packit a38265
      show_help = 1;
Packit a38265
      break;
Packit a38265
    case 'v': /* version */
Packit a38265
      show_version = 1;
Packit a38265
      break;
Packit a38265
    case 'b': /* binary */
Packit a38265
      oddata->dump_bits = 1;
Packit a38265
      break;
Packit a38265
    case 'n': /* new */
Packit a38265
      oddata->read_packet = read_new_packet;
Packit a38265
      break;
Packit a38265
    case 'o': /* output */
Packit a38265
      outfilename = optarg;
Packit a38265
      break;
Packit a38265
    case 'r': /* revert */
Packit a38265
      revert = 1;
Packit a38265
      break;
Packit a38265
    case 's': /* serialno */
Packit a38265
      filter_serialnos = 1;
Packit a38265
      serialno = atol (optarg);
Packit a38265
      oggz_table_insert (oddata->serialno_table, serialno, &truth);
Packit a38265
      break;
Packit a38265
    case 'c': /* content-type */
Packit a38265
      filter_content_types = 1;
Packit a38265
      n = (long)oggz_table_size (oddata->content_types_table);
Packit a38265
      oggz_table_insert (oddata->content_types_table, (long)n, optarg);
Packit a38265
      break;
Packit a38265
    case 'O': /* hide offset */
Packit a38265
      oddata->hide_offset = 1;
Packit a38265
      break;
Packit a38265
    case 'S': /* hide serialno */
Packit a38265
      oddata->hide_serialno = 1;
Packit a38265
      break;
Packit a38265
    case 'G': /* hide granulepos */
Packit a38265
      oddata->hide_granulepos = 1;
Packit a38265
      break;
Packit a38265
    case 'P': /* hide packetno */
Packit a38265
      oddata->hide_packetno = 1;
Packit a38265
      break;
Packit a38265
    default:
Packit a38265
      break;
Packit a38265
    }
Packit a38265
  }
Packit a38265
Packit a38265
  if (show_version) {
Packit a38265
    printf ("%s version " VERSION "\n", progname);
Packit a38265
  }
Packit a38265
Packit a38265
  if (show_help) {
Packit a38265
    usage (progname);
Packit a38265
  }
Packit a38265
Packit a38265
  if (show_version || show_help) {
Packit a38265
    goto exit_ok;
Packit a38265
  }
Packit a38265
Packit a38265
  if (optind >= argc) {
Packit a38265
    usage (progname);
Packit a38265
    goto exit_err;
Packit a38265
  }
Packit a38265
Packit a38265
  infilename = argv[optind++];
Packit a38265
Packit a38265
  if (outfilename == NULL) {
Packit a38265
    outfile = stdout;
Packit a38265
  } else {
Packit a38265
    outfile = fopen (outfilename, "wb");
Packit a38265
    if (outfile == NULL) {
Packit a38265
      fprintf (stderr, "%s: unable to open output file %s\n",
Packit a38265
	       progname, outfilename);
Packit a38265
      goto exit_err;
Packit a38265
    }
Packit a38265
  }
Packit a38265
Packit a38265
  if (revert) {
Packit a38265
    if (oddata->dump_bits) {
Packit a38265
      fprintf (stderr, "%s: Revert of binary dump not supported\n", progname);
Packit a38265
      goto exit_err;
Packit a38265
    }
Packit a38265
Packit a38265
    revert_file (infilename);
Packit a38265
  } else {
Packit a38265
    errno = 0;
Packit a38265
Packit a38265
    if (strcmp (infilename, "-") == 0) {
Packit a38265
      oggz = oggz_open_stdio (stdin, OGGZ_READ|OGGZ_AUTO);
Packit a38265
    } else {
Packit a38265
      oggz = oggz_open (infilename, OGGZ_READ|OGGZ_AUTO);
Packit a38265
    }
Packit a38265
Packit a38265
    if (oggz == NULL) {
Packit a38265
      if (errno == 0) {
Packit a38265
	fprintf (stderr, "%s: %s: OGGZ error opening input file\n",
Packit a38265
		 progname, infilename);
Packit a38265
      } else {
Packit a38265
	fprintf (stderr, "%s: %s: %s\n",
Packit a38265
		 progname, infilename, strerror (errno));
Packit a38265
      }
Packit a38265
      goto exit_err;
Packit a38265
    }
Packit a38265
Packit a38265
    if (!filter_serialnos && !filter_content_types) {
Packit a38265
      oggz_set_read_callback (oggz, -1, oddata->read_packet, oddata);
Packit a38265
    } else {
Packit a38265
      if (filter_serialnos) {
Packit a38265
	size = oggz_table_size (oddata->serialno_table);
Packit a38265
	for (i = 0; i < size; i++) {
Packit a38265
	  oggz_table_nth (oddata->serialno_table, i, &serialno);
Packit a38265
	  oggz_set_read_callback (oggz, serialno, oddata->read_packet, oddata);
Packit a38265
	}
Packit a38265
      }
Packit a38265
      
Packit a38265
      if (filter_content_types) {
Packit a38265
	oggz_set_read_page (oggz, -1, filter_page, oddata);
Packit a38265
      }
Packit a38265
    }
Packit a38265
Packit a38265
    oggz_run_set_blocksize (oggz, 1024*1024);
Packit a38265
    oggz_run (oggz);
Packit a38265
Packit a38265
    oggz_close (oggz);
Packit a38265
  }
Packit a38265
Packit a38265
 exit_ok:
Packit a38265
  oddata_delete (oddata);
Packit a38265
  exit (0);
Packit a38265
Packit a38265
 exit_err:
Packit a38265
  oddata_delete (oddata);
Packit a38265
  exit (1);
Packit a38265
}