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