[xiph-commits] r6926 - experimental/giles
giles at dactyl.lonelymoon.com
giles
Tue Jun 29 13:24:55 PDT 2004
Author: giles
Date: Tue Jun 29 13:24:55 2004
New Revision: 6926
Added:
experimental/giles/oggfilter.c
Log:
Oggz-based packet filtering example that changes the aspect ratio on theora video files.
Added: experimental/giles/oggfilter.c
===================================================================
--- experimental/giles/oggfilter.c 2004-06-29 19:21:29 UTC (rev 6925)
+++ experimental/giles/oggfilter.c 2004-06-29 20:24:54 UTC (rev 6926)
@@ -0,0 +1,167 @@
+/*
+ Copyright (C) 2004 Xiph.org Foundation
+
+ 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.
+*/
+
+/* quick program to filter an ogg file
+ correcting (for example) header errors */
+
+/* compile with:
+ gcc -o oggfilter oggfilter.c `pkg-config --cflags oggz` \
+ `pkg-config --libs oggz`
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <oggz/oggz.h>
+
+#define BUFSIZE 4096
+
+/* write out a big-endian 32 bit integer */
+static void write_uint32(unsigned char *p, unsigned int v)
+{
+ p[0] = (v >> 24) & 0xFF;
+ p[1] = (v >> 16) & 0xFF;
+ p[2] = (v >> 8) & 0xFF;
+ p[3] = (v) & 0xFF;
+}
+
+/* write out a big-endian 32 bit integer */
+static void write_uint24(unsigned char *p, unsigned int v)
+{
+ p[0] = (v >> 16) & 0xFF;
+ p[1] = (v >> 8) & 0xFF;
+ p[2] = (v) & 0xFF;
+}
+
+/* write out a big-endian 16 bit integer */
+static void write_uint16(unsigned char *p, unsigned int v)
+{
+ p[0] = (v >> 8) & 0xFF;
+ p[1] = (v) & 0xFF;
+}
+
+/* copy an ogg packet from reader to writer */
+static int
+packet_copy (OGGZ *oggz, ogg_packet *op, long serialno, void *user_data)
+{
+ OGGZ *writer = (OGGZ *)user_data;
+ int flush;
+ int ret;
+
+ if (op->granulepos == -1) {
+ flush = 0;
+ } else {
+ flush = OGGZ_FLUSH_AFTER;
+ }
+
+ if ((ret = oggz_write_feed(writer, op, serialno, flush, NULL)) != 0) {
+ printf ("oggz_write_feed: %d\n", ret);
+ }
+
+ return 0;
+}
+
+/* do our special processing on a packet */
+static int
+packet_fix(OGGZ *oggz, ogg_packet *op, long serialno, void *user_data)
+{
+ int aspect_numerator = 1;
+ int aspect_denominator = 1;
+
+ /* fix the aspect ratio */
+ write_uint24(op->packet+30, aspect_numerator);
+ write_uint24(op->packet+33, aspect_denominator);
+
+ /* pass the packet on and replace ourselves so we're
+ only called for the first packet in the stream */
+ if (!packet_copy(oggz, op, serialno, user_data))
+ oggz_set_read_callback (oggz, -1, packet_copy, user_data);
+
+ return 0;
+}
+
+/* packet dispatch; called for new streams */
+static int
+packet_dispatch(OGGZ *oggz, ogg_packet *op, long serialno, void *user_data)
+{
+ OGGZ *writer = (OGGZ *)user_data;
+ const unsigned char theora_magic[] = "\x80theora";
+ const unsigned char vorbis_magic[] = "\x01vorbis";
+
+ if (!memcmp(op->packet, theora_magic, 7)) {
+ /* filter theora streams */
+ packet_fix(oggz, op, serialno, user_data);
+ } else {
+ /* just copy anything else */
+ if (!packet_copy(oggz, op, serialno, user_data))
+ oggz_set_read_callback(oggz, serialno, packet_copy, user_data);
+ }
+
+ return 0;
+}
+
+
+int
+main (int argc, char ** argv)
+{
+ OGGZ *reader, *writer;
+ int n;
+
+ if (argc < 3) {
+ printf("usage: %s <in.ogg> <out.ogg>\n", argv[0]);
+ printf(" filters in.ogg into out.ogg, doing\n");
+ printf(" whatever it was compiled to do.\n");
+ }
+
+ reader = oggz_open(argv[1], OGGZ_READ);
+ if (reader == NULL) {
+ printf ("unable to open file %s\n", argv[1]);
+ exit (1);
+ }
+
+ writer = oggz_open(argv[2], OGGZ_WRITE);
+ if (writer == NULL) {
+ printf ("unable to open file %s\n", argv[2]);
+ oggz_close(reader);
+ exit (1);
+ }
+
+ /* set the callback for stream dispatch */
+ oggz_set_read_callback(reader, -1, packet_dispatch, writer);
+
+ while ((n = oggz_read(reader, BUFSIZE)) > 0) {
+ while (oggz_write(writer, n) > 0);
+ }
+
+ oggz_close(writer);
+ oggz_close(reader);
+
+ return 0;
+}
More information about the commits
mailing list