[xiph-commits] r9600 - experimental/msmith

msmith at svn.xiph.org msmith at svn.xiph.org
Fri Jul 22 10:17:17 PDT 2005


Author: msmith
Date: 2005-07-22 10:17:13 -0700 (Fri, 22 Jul 2005)
New Revision: 9600

Added:
   experimental/msmith/README
   experimental/msmith/fix-eos.c
   experimental/msmith/fix-granulepos-on-empty-pages.c
   experimental/msmith/make-ogg.c
   experimental/msmith/ogg-pageinfo.c
   experimental/msmith/remove-negative-granulepos.c
Log:
Add some tools I wrote for diagnosing, testing, and fixing various ogg 
problems.


Added: experimental/msmith/README
===================================================================
--- experimental/msmith/README	2005-07-22 17:13:52 UTC (rev 9599)
+++ experimental/msmith/README	2005-07-22 17:17:13 UTC (rev 9600)
@@ -0,0 +1,5 @@
+These are some tools I wrote for diagnosing and fixing problems in ogg files.
+ogg-pageinfo is useful for figuring out what is actually on each ogg page.
+fix-* fix various problems, running them in the proper order is usually required
+play around if you want, there's no makefile, most of them require liboggz.
+

Added: experimental/msmith/fix-eos.c
===================================================================
--- experimental/msmith/fix-eos.c	2005-07-22 17:13:52 UTC (rev 9599)
+++ experimental/msmith/fix-eos.c	2005-07-22 17:17:13 UTC (rev 9600)
@@ -0,0 +1,198 @@
+/*
+   Copyright (C) 2003 Commonwealth Scientific and Industrial Research
+   Organisation (CSIRO) Australia
+   Also (C) 2005 Michael Smith <msmith at xiph.org>
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   - Neither the name of CSIRO Australia nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ORGANISATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <oggz/oggz.h>
+#include <ogg/ogg.h>
+
+struct eos_fix {
+  /* Output file */
+  FILE *out; 
+
+  /* Stream serial -> struct eos_fix_stream mapping */
+  OggzTable * tracks;
+};
+
+/* We have one of these for each logical stream */
+struct eos_fix_stream {
+  long lastvalidpage; /* The pageno of the final useful page */
+  int discarding; /* Once we've processed the final useful page, we throw
+                     out any further non-useful streams */
+};
+
+static void clear_table(OggzTable *table) {
+  int i, size = oggz_table_size(table);
+  for(i = 0; i < size; i++) {
+    free(oggz_table_nth(table, i, NULL));
+  }
+}
+
+static int
+read_page (OGGZ * oggz, const ogg_page * og, long serialno, void * user_data)
+{
+  struct eos_fix *fixer = (struct eos_fix *)user_data;
+  OggzTable * tracks = fixer->tracks;
+  long pageno = ogg_page_pageno((ogg_page *)og);
+
+  /* Insert this if it's a page that completes one or more packets; each time
+   * we call this it gets overwritten, the end result is that we mark the last
+   * page that contains the end of one or more packets.
+   */
+  if(ogg_page_packets((ogg_page *)og) != 0) {
+    struct eos_fix_stream *data = (struct eos_fix_stream *)oggz_table_lookup(tracks, serialno);
+    if(data == NULL) {
+      data = malloc(sizeof(struct eos_fix_stream));
+    }
+    data->lastvalidpage = pageno;
+    data->discarding = 0;
+    oggz_table_insert (tracks, serialno, data);
+  }
+
+  return 0;
+}
+
+static int
+write_page (OGGZ * oggz, const ogg_page * og, long serialno, void * user_data)
+{
+  struct eos_fix *fixer = (struct eos_fix *)user_data;
+  OggzTable * tracks = fixer->tracks;
+  long pageno = ogg_page_pageno((ogg_page *)og);
+  struct eos_fix_stream *data = (struct eos_fix_stream *)oggz_table_lookup(tracks, serialno);
+
+  if(data == NULL) {
+    fprintf(stderr, "Bailing out, internal consistency failure\n");
+    abort();
+  }
+
+  if(data->lastvalidpage == pageno) {
+    unsigned char header_type = og->header[5];
+    if(!(header_type & 0x4)) {
+      fprintf(stderr, "Setting EOS on final page of stream %ld\n",
+		      serialno);
+      header_type |= 0x4;
+      og->header[5] = header_type;
+
+      ogg_page_checksum_set((ogg_page *)og);
+    }
+
+    /* Now we want to discard any remaining partial packets at the end of this
+     * page. Unfortunately, neither libogg nor liboggz have helpful
+     * functions for this, so do it all in a manual way...
+     *
+     * We need to do this because libogg (correctly) doesn't tag the last
+     * complete packet on an EOS page with EOS if there's an incomplete
+     * packet following it (so you get complaints from oggz-validate).
+     */
+    {
+      int i, segments, discard = 0;
+      segments = og->header[26];
+      for(i=segments-1; i >= 0; i--) {
+        if(og->header[i+27] < 255)
+            break;
+        else
+            discard += 255;
+      }
+      if(i != segments-1) {
+        fprintf(stderr, "Discarding %d useless segments of %d, retaining %d\n", segments-1-i, segments, i+1);
+        og->header[26] = i+1;
+        ((ogg_page *)og)->header_len -= segments-1-i;
+        ((ogg_page *)og)->body_len -= discard;
+        ogg_page_checksum_set((ogg_page *)og);
+      }
+    }
+    
+    /* Write out this page, but no following ones */
+    fwrite (og->header, 1, og->header_len, fixer->out);
+    fwrite (og->body, 1, og->body_len, fixer->out);
+    data->discarding = 1;
+  }
+
+  if(!data->discarding) {
+    fwrite (og->header, 1, og->header_len, fixer->out);
+    fwrite (og->body, 1, og->body_len, fixer->out);
+  }
+
+  return 0;
+}
+
+int
+main (int argc, char ** argv)
+{
+  OGGZ * oggz;
+  struct eos_fix fixer;
+  long n;
+  char *progname = argv[0];
+
+  if (argc < 3) {
+    printf ("usage: %s in.ogg out.ogg\n", progname);
+  }
+
+  fixer.tracks = oggz_table_new ();
+  fixer.out = NULL;
+
+  if ((oggz = oggz_open ((char *)argv[1], OGGZ_READ | OGGZ_AUTO)) == NULL) {
+    printf ("%s: unable to open file %s\n", progname, argv[1]);
+    exit (1);
+  }
+
+  oggz_set_read_page (oggz, -1, read_page, &fixer);
+
+  while ((n = oggz_read (oggz, 1024)) > 0);
+
+  oggz_close (oggz);
+
+  fixer.out = fopen(argv[2], "wb");
+  if(!fixer.out) {
+    fprintf(stderr, "%s: Failed to open output file \"%s\"\n", progname, argv[2]);
+    exit(1);
+  }
+
+  if ((oggz = oggz_open ((char *)argv[1], OGGZ_READ | OGGZ_AUTO)) == NULL) {
+    printf ("%s: unable to open file %s\n", progname, argv[1]);
+    exit (1);
+  }
+
+  oggz_set_read_page (oggz, -1, write_page, &fixer);
+
+  while ((n = oggz_read (oggz, 1024)) > 0);
+
+  oggz_close (oggz);
+
+  clear_table(fixer.tracks);
+  oggz_table_delete (fixer.tracks);
+
+  fclose(fixer.out);
+
+  exit (0);
+}

Added: experimental/msmith/fix-granulepos-on-empty-pages.c
===================================================================
--- experimental/msmith/fix-granulepos-on-empty-pages.c	2005-07-22 17:13:52 UTC (rev 9599)
+++ experimental/msmith/fix-granulepos-on-empty-pages.c	2005-07-22 17:17:13 UTC (rev 9600)
@@ -0,0 +1,98 @@
+/*
+   Copyright (C) 2003 Commonwealth Scientific and Industrial Research
+   Organisation (CSIRO) Australia
+   Also (C) 2005 Michael Smith <msmith at xiph.org>
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   - Neither the name of CSIRO Australia nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ORGANISATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <oggz/oggz.h>
+#include <ogg/ogg.h>
+
+static FILE *out;
+
+static char * progname;
+
+static int
+process_page (OGGZ * oggz, const ogg_page * og, long serialno, void * user_data)
+{
+  ogg_int64_t gpos = ogg_page_granulepos((ogg_page *)og);
+
+  if(gpos != -1 && ogg_page_packets((ogg_page *)og) == 0) {
+    int i;
+
+    fprintf(stderr, "Fixing granulepos on page with no completed packets\n");
+    for(i=6;i<14;i++){
+      gpos = -1;
+      og->header[i]=(unsigned char)(gpos&0xff);
+      gpos>>=8;
+    }
+    ogg_page_checksum_set((ogg_page *)og);
+  }
+
+  fwrite (og->header, 1, og->header_len, out);
+  fwrite (og->body, 1, og->body_len, out);
+
+  return 0;
+}
+
+int
+main (int argc, char ** argv)
+{
+  OGGZ * oggz;
+  long n;
+
+  progname = argv[0];
+
+  if (argc < 3) {
+    printf ("usage: %s in.ogg out.ogg\n", progname);
+  }
+
+  if ((oggz = oggz_open ((char *)argv[1], OGGZ_READ | OGGZ_AUTO)) == NULL) {
+    printf ("%s: unable to open file %s\n", progname, argv[1]);
+    exit (1);
+  }
+
+  out = fopen(argv[2], "wb");
+  if(!out) {
+    fprintf(stderr, "%s: Failed to open output file \"%s\"\n", progname, argv[2]);
+    exit(1);
+  }
+
+  oggz_set_read_page (oggz, -1, process_page, NULL);
+
+  while ((n = oggz_read (oggz, 1024)) > 0);
+
+  oggz_close (oggz);
+
+  fclose(out);
+
+  exit (0);
+}

Added: experimental/msmith/make-ogg.c
===================================================================
--- experimental/msmith/make-ogg.c	2005-07-22 17:13:52 UTC (rev 9599)
+++ experimental/msmith/make-ogg.c	2005-07-22 17:17:13 UTC (rev 9600)
@@ -0,0 +1,68 @@
+#include <ogg/ogg.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void write_ogg(FILE *out) 
+{
+    ogg_packet packet;
+    ogg_page page;
+    int sizes[] = {10, 100, 1000, 10000, -1};
+    int i = 0;
+    ogg_int64_t current_granulepos = 0;
+    ogg_stream_state stream;
+    int serial = 123456;
+
+    ogg_stream_init(&stream, serial);
+
+    while(sizes[i] >= 0) {
+        int size = sizes[i];
+        fprintf(stderr, "Doing size %d\n", size);
+
+        packet.b_o_s = (i == 0);
+        packet.e_o_s = sizes[i+1] < 0;
+        packet.packet = calloc(1, size);
+        packet.bytes = size;
+        packet.packetno = i;
+        packet.granulepos = current_granulepos;
+        
+        current_granulepos += 1;
+
+        fprintf(stderr, "Submitting packet with GP %lld\n", packet.granulepos);
+        ogg_stream_packetin(&stream, &packet);
+
+        while(ogg_stream_pageout(&stream, &page)) 
+        {
+            fprintf(stderr, "Writing page %ld\n", ogg_page_pageno(&page));
+            fwrite(page.header, 1, page.header_len, out);
+            fwrite(page.body, 1, page.body_len, out);
+        }
+
+        i++;
+    }
+
+    ogg_stream_clear(&stream);
+}
+
+int main(int argc, char **argv)
+{
+    FILE *out;
+
+    if(argc < 2) {
+        fprintf(stderr, "Usage: make-ogg out.ogg\n");
+        exit(1);
+    }
+
+    out = fopen(argv[1], "wb");
+
+    if(!out) {
+        fprintf(stderr, "Couldn't write to %s\n", argv[1]);
+        exit(1);
+    }
+
+    write_ogg(out);
+    fclose(out);
+
+    return 0;
+}
+
+    

Added: experimental/msmith/ogg-pageinfo.c
===================================================================
--- experimental/msmith/ogg-pageinfo.c	2005-07-22 17:13:52 UTC (rev 9599)
+++ experimental/msmith/ogg-pageinfo.c	2005-07-22 17:17:13 UTC (rev 9600)
@@ -0,0 +1,120 @@
+/*
+   Copyright (C) 2003 Commonwealth Scientific and Industrial Research
+   Organisation (CSIRO) Australia
+   Also (C) 2005 Michael Smith <msmith at xiph.org>
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   - Neither the name of CSIRO Australia nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ORGANISATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <oggz/oggz.h>
+#include <ogg/ogg.h>
+
+static int
+process_page (OGGZ * oggz, const ogg_page * og, long serialno, void * user_data)
+{
+  ogg_int64_t gpos = ogg_page_granulepos((ogg_page *)og);
+  int granuleshift = oggz_get_granuleshift(oggz, serialno);
+
+  fprintf (stdout, "|%010ld| ", serialno);
+	fprintf(stdout, "page %ld, ", ogg_page_pageno((ogg_page *)og));
+  if(granuleshift < 1) {
+    fprintf(stdout, "GP %lld, ", gpos);
+	}
+	else {
+	  ogg_int64_t iframe, pframe;
+    iframe = gpos >> granuleshift;
+    pframe = gpos - (iframe << granuleshift);
+
+    fprintf (stdout, "granulepos %lld|%lld, ", iframe, pframe);
+	}
+
+	fprintf(stdout, "Flags: ");
+	if(ogg_page_continued((ogg_page *)og))
+		fprintf(stdout, "C");
+	if(ogg_page_bos((ogg_page *)og))
+		fprintf(stdout, "B");
+	if(ogg_page_eos((ogg_page *)og))
+		fprintf(stdout, "E");
+
+	fprintf(stdout, " (%d)", ogg_page_packets((ogg_page *)og));
+	
+	fprintf(stdout, "\n");
+	
+
+  return 0;
+}
+
+int process_packet(OGGZ *oggz, ogg_packet *op, long serialno, void *user_data)
+{
+  int granuleshift = oggz_get_granuleshift (oggz, serialno);
+  fprintf (stdout, "|%010ld|   ", serialno);
+  if(granuleshift < 1) {
+    fprintf(stdout, "GP %lld, ", op->granulepos);
+	}
+	else {
+	  ogg_int64_t iframe, pframe;
+    iframe = op->granulepos >> granuleshift;
+    pframe = op->granulepos - (iframe << granuleshift);
+
+    fprintf (stdout, "GP %lld|%lld, ", iframe, pframe);
+	}
+  fprintf (stdout, " packetno %lld", op->packetno);
+
+  fprintf(stdout, ": %ld bytes\n", op->bytes);
+
+	return 0;
+}
+
+int
+main (int argc, char ** argv)
+{
+  OGGZ * oggz;
+  long n;
+
+  char *progname = argv[0];
+
+  if (argc < 2) {
+    printf ("usage: %s file.ogg\n", progname);
+  }
+
+  if ((oggz = oggz_open ((char *)argv[1], OGGZ_READ | OGGZ_AUTO)) == NULL) {
+    printf ("%s: unable to open file %s\n", progname, argv[1]);
+    exit (1);
+  }
+
+  oggz_set_read_page (oggz, -1, process_page, NULL);
+	oggz_set_read_callback(oggz, -1, process_packet, NULL);
+
+  while ((n = oggz_read (oggz, 1024)) > 0);
+
+  oggz_close (oggz);
+
+  exit (0);
+}

Added: experimental/msmith/remove-negative-granulepos.c
===================================================================
--- experimental/msmith/remove-negative-granulepos.c	2005-07-22 17:13:52 UTC (rev 9599)
+++ experimental/msmith/remove-negative-granulepos.c	2005-07-22 17:17:13 UTC (rev 9600)
@@ -0,0 +1,106 @@
+/*
+   Copyright (C) 2003 Commonwealth Scientific and Industrial Research
+   Organisation (CSIRO) Australia
+   Also (C) 2005 Michael Smith <msmith at xiph.org>
+
+   Redistribution and use in source and binary forms, with or without
+   modification, are permitted provided that the following conditions
+   are met:
+
+   - Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+
+   - Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+
+   - Neither the name of CSIRO Australia nor the names of its
+   contributors may be used to endorse or promote products derived from
+   this software without specific prior written permission.
+
+   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+   ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+   PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE ORGANISATION OR
+   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+   EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+   PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+   LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+   SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <oggz/oggz.h>
+#include <ogg/ogg.h>
+
+static FILE *out;
+
+static char * progname;
+
+long pages_written = 0;
+
+static void set_ogg_pageno(ogg_page *og, long pageno) {
+  int i;
+  for(i=18;i<22;i++){
+    og->header[i]=(unsigned char)(pageno&0xff);
+    pageno>>=8;
+  }
+  ogg_page_checksum_set(og);
+}
+
+static int
+process_page (OGGZ * oggz, const ogg_page * og, long serialno, void * user_data)
+{
+  ogg_int64_t gpos = ogg_page_granulepos((ogg_page *)og);
+
+  if(gpos < -1) {
+    fprintf(stderr, "Skipping page with granulepos %lld\n", gpos);
+  }
+  else {
+    if(ogg_page_pageno((ogg_page *)og) != pages_written)
+      set_ogg_pageno((ogg_page *)og, pages_written);
+
+    fwrite (og->header, 1, og->header_len, out);
+    fwrite (og->body, 1, og->body_len, out);
+    pages_written++;
+  }
+
+  return 0;
+}
+
+int
+main (int argc, char ** argv)
+{
+  OGGZ * oggz;
+  long n;
+
+  progname = argv[0];
+
+  if (argc < 3) {
+    printf ("usage: %s in.ogg out.ogg\n", progname);
+  }
+
+  if ((oggz = oggz_open ((char *)argv[1], OGGZ_READ | OGGZ_AUTO)) == NULL) {
+    printf ("%s: unable to open file %s\n", progname, argv[1]);
+    exit (1);
+  }
+
+  out = fopen(argv[2], "wb");
+  if(!out) {
+    fprintf(stderr, "%s: Failed to open output file \"%s\"\n", progname, argv[2]);
+    exit(1);
+  }
+
+  oggz_set_read_page (oggz, -1, process_page, NULL);
+
+  while ((n = oggz_read (oggz, 1024)) > 0);
+
+  oggz_close (oggz);
+
+  fclose(out);
+
+  exit (0);
+}



More information about the commits mailing list