liboggz-0.8.3

git-svn-id: file:///srv/svn/repos/haiku/trunk/current@7948 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
shatty
2004-06-13 00:18:40 +00:00
parent 7b8b434fbf
commit c11def3bf2
22 changed files with 6061 additions and 0 deletions
@@ -0,0 +1,11 @@
Conrad Parker <[email protected]>
- Design, general implementation
Silvia Pfeiffer <[email protected]>
- Design, MS Windows porting
Andre Pang <[email protected]>
- Design, Mac OS X porting
Zentaro Kavanagh <[email protected]>
- MS Windows Porting and packaging. Windows specific bugfixes.
@@ -0,0 +1,29 @@
Copyright (C) 2003 CSIRO Australia
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 the CSIRO 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.
@@ -0,0 +1,17 @@
Fri May 21 16:48:34 EST 2004 Conrad Parker <[email protected]>
* Version 0.8.3
* fixes for win32 build procedure
* improved API documentation for seeking, OGGZ_AUTO and OggzIO
Thu Mar 11 11:00:00 EST 2004 Silvia Pfeiffer <[email protected]>
* Version 0.8.2
* fixed up the Makefiles to not include the CVS subdirectories
Sun Mar 07 16:00:00 EST 2004 Silvia Pfeiffer <[email protected]>
* Version 0.8.1
* includes Windows port with Makefile & VC6 workspace & .NET solution
Thu Oct 16 21:55:07 EST 2003 Conrad Parker <[email protected]>
* split liboggz out from libannodex sources, started ChangeLog
@@ -0,0 +1,14 @@
SubDir OBOS_TOP src add-ons media plugins ogg liboggz ;
SubDirHdrs [ FDirName $(SUBDIR) .. libogg ] ;
SubDirCcFlags -Wno-missing-prototypes ;
StaticLibrary oggz :
oggz.c
oggz_auto.c
oggz_io.c
oggz_read.c
oggz_table.c
oggz_vector.c
oggz_write.c
;
@@ -0,0 +1,97 @@
/* config.h. Generated by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <dlfcn.h> header file. */
/* #undef HAVE_DLFCN_H */
/* Define to 1 if you have the <fcntl.h> header file. */
#define HAVE_FCNTL_H 1
/* Define to 1 if you have the 'getopt_long' function */
#define HAVE_GETOPT_LONG
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `memmove' function. */
#define HAVE_MEMMOVE 1
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the `random' function. */
#define HAVE_RANDOM 1
/* Define to 1 if your system has a GNU libc compatible `realloc' function,
and to 0 otherwise. */
#define HAVE_REALLOC 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to build experimental code */
/* #undef OGGZ_CONFIG_EXPERIMENTAL */
/* Do not build reading support */
#define OGGZ_CONFIG_READ 1
/* Do not build writing support */
#define OGGZ_CONFIG_WRITE 1
/* Name of package */
#define PACKAGE "liboggz"
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT ""
/* Define to the full name of this package. */
#define PACKAGE_NAME ""
/* Define to the full name and version of this package. */
#define PACKAGE_STRING ""
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME ""
/* Define to the version of this package. */
#define PACKAGE_VERSION ""
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Version number of package */
#define VERSION "0.8.3"
/* Define to 1 if your processor stores words with the most significant byte
first (like Motorola and SPARC, unlike Intel and VAX). */
/* #undef WORDS_BIGENDIAN */
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `long' if <sys/types.h> does not define. */
/* #undef off_t */
/* Define to rpl_realloc if the replacement function should be used. */
/* #undef realloc */
/* Define to `unsigned' if <sys/types.h> does not define. */
/* #undef size_t */
@@ -0,0 +1,502 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
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 "config.h"
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <ogg/ogg.h>
#include "oggz_compat.h"
#include "oggz_private.h"
#include "oggz_vector.h"
/*#define DEBUG*/
static int
oggz_flags_disabled (int flags)
{
if (flags & OGGZ_WRITE) {
if (!OGGZ_CONFIG_WRITE) return OGGZ_ERR_DISABLED;
} else {
if (!OGGZ_CONFIG_READ) return OGGZ_ERR_DISABLED;
}
return 0;
}
OGGZ *
oggz_new (int flags)
{
OGGZ * oggz;
if (oggz_flags_disabled (flags)) return NULL;
oggz = (OGGZ *) oggz_malloc (sizeof (OGGZ));
if (oggz == NULL) return NULL;
oggz->flags = flags;
oggz->file = NULL;
oggz->io = NULL;
oggz->offset = 0;
oggz->offset_data_begin = 0;
oggz->streams = oggz_vector_new ();
oggz->all_at_eos = 0;
oggz->metric = NULL;
oggz->metric_user_data = NULL;
oggz->metric_internal = 0;
oggz->order = NULL;
oggz->order_user_data = NULL;
if (OGGZ_CONFIG_WRITE && (oggz->flags & OGGZ_WRITE)) {
oggz_write_init (oggz);
} else if (OGGZ_CONFIG_READ) {
oggz_read_init (oggz);
}
return oggz;
}
OGGZ *
oggz_open (char * filename, int flags)
{
OGGZ * oggz = NULL;
FILE * file = NULL;
if (oggz_flags_disabled (flags)) return NULL;
if (flags & OGGZ_WRITE) {
file = fopen (filename, "wb");
} else {
file = fopen (filename, "rb");
}
if (file == NULL) return NULL;
oggz = oggz_new (flags);
oggz->file = file;
return oggz;
}
OGGZ *
oggz_open_stdio (FILE * file, int flags)
{
OGGZ * oggz = NULL;
if (oggz_flags_disabled (flags)) return NULL;
oggz = oggz_new (flags);
oggz->file = file;
return oggz;
}
int
oggz_flush (OGGZ * oggz)
{
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
return oggz_io_flush (oggz);
}
static int
oggz_stream_clear (void * data)
{
oggz_stream_t * stream = (oggz_stream_t *) data;
if (stream->ogg_stream.serialno != -1)
ogg_stream_clear (&stream->ogg_stream);
if (stream->metric_internal)
oggz_free (stream->metric_user_data);
return 0;
}
int
oggz_close (OGGZ * oggz)
{
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
oggz_vector_foreach (oggz->streams, oggz_stream_clear);
oggz_vector_delete (oggz->streams);
if (OGGZ_CONFIG_WRITE && (oggz->flags & OGGZ_WRITE)) {
oggz_write_close (oggz);
} else if (OGGZ_CONFIG_READ) {
oggz_read_close (oggz);
}
if (oggz->file != NULL) {
if (fclose (oggz->file) == EOF) {
return OGGZ_ERR_SYSTEM;
}
}
oggz_free (oggz);
return 0;
}
off_t
oggz_tell (OGGZ * oggz)
{
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
return oggz->offset;
}
ogg_int64_t
oggz_tell_units (OGGZ * oggz)
{
OggzReader * reader;
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (oggz->flags & OGGZ_WRITE) {
return OGGZ_ERR_INVALID;
}
reader = &oggz->x.reader;
if (OGGZ_CONFIG_READ) {
return reader->current_unit;
} else {
return OGGZ_ERR_DISABLED;
}
}
/******** oggz_stream management ********/
static int
oggz_find_stream (void * data, long serialno)
{
oggz_stream_t * stream = (oggz_stream_t *) data;
return (stream->ogg_stream.serialno == serialno);
}
oggz_stream_t *
oggz_get_stream (OGGZ * oggz, long serialno)
{
if (serialno < 0) return NULL;
return oggz_vector_find (oggz->streams, oggz_find_stream, serialno);
}
oggz_stream_t *
oggz_add_stream (OGGZ * oggz, long serialno)
{
oggz_stream_t * stream;
stream = oggz_malloc (sizeof (oggz_stream_t));
if (stream == NULL) return NULL;
ogg_stream_init (&stream->ogg_stream, (int)serialno);
stream->delivered_non_b_o_s = 0;
stream->b_o_s = 1;
stream->e_o_s = 0;
stream->granulepos = 0;
stream->packetno = -1; /* will be incremented on first write */
stream->metric = NULL;
stream->metric_user_data = NULL;
stream->metric_internal = 0;
stream->order = NULL;
stream->order_user_data = NULL;
stream->read_packet = NULL;
stream->read_user_data = NULL;
oggz_vector_insert_p (oggz->streams, stream);
return stream;
}
int
oggz_get_bos (OGGZ * oggz, long serialno)
{
oggz_stream_t * stream;
int i, size;
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (serialno == -1) {
size = oggz_vector_size (oggz->streams);
for (i = 0; i < size; i++) {
stream = (oggz_stream_t *)oggz_vector_nth_p (oggz->streams, i);
#if 1
/* If this stream has delivered a non bos packet, return FALSE */
if (stream->delivered_non_b_o_s) return 0;
#else
/* If this stream has delivered its bos packet, return FALSE */
if (!stream->b_o_s) return 0;
#endif
}
return 1;
} else {
stream = oggz_get_stream (oggz, serialno);
if (stream == NULL)
return OGGZ_ERR_BAD_SERIALNO;
return stream->b_o_s;
}
}
int
oggz_get_eos (OGGZ * oggz, long serialno)
{
oggz_stream_t * stream;
int i, size;
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (serialno == -1) {
size = oggz_vector_size (oggz->streams);
for (i = 0; i < size; i++) {
stream = (oggz_stream_t *)oggz_vector_nth_p (oggz->streams, i);
if (!stream->e_o_s) return 0;
}
return 1;
} else {
stream = oggz_get_stream (oggz, serialno);
if (stream == NULL)
return OGGZ_ERR_BAD_SERIALNO;
return stream->e_o_s;
}
}
int
oggz_set_eos (OGGZ * oggz, long serialno)
{
oggz_stream_t * stream;
int i, size;
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (serialno == -1) {
size = oggz_vector_size (oggz->streams);
for (i = 0; i < size; i++) {
stream = (oggz_stream_t *) oggz_vector_nth_p (oggz->streams, i);
stream->e_o_s = 1;
}
oggz->all_at_eos = 1;
} else {
stream = oggz_get_stream (oggz, serialno);
if (stream == NULL)
return OGGZ_ERR_BAD_SERIALNO;
stream->e_o_s = 1;
if (oggz_get_eos (oggz, -1))
oggz->all_at_eos = 1;
}
return 0;
}
long
oggz_serialno_new (OGGZ * oggz)
{
long serialno;
do {
serialno = oggz_random();
} while (oggz_get_stream (oggz, serialno) != NULL);
return serialno;
}
/******** OggzMetric management ********/
typedef struct {
ogg_int64_t gr_n;
ogg_int64_t gr_d;
} oggz_metric_linear_t;
static ogg_int64_t
oggz_metric_default_linear (OGGZ * oggz, long serialno, ogg_int64_t granulepos,
void * user_data)
{
oggz_metric_linear_t * ldata = (oggz_metric_linear_t *)user_data;
return (ldata->gr_d * granulepos / ldata->gr_n);
}
int
oggz_set_metric_internal (OGGZ * oggz, long serialno,
OggzMetric metric, void * user_data, int internal)
{
oggz_stream_t * stream;
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (serialno == -1) {
if (oggz->metric_internal)
oggz_free (oggz->metric_user_data);
oggz->metric = metric;
oggz->metric_user_data = user_data;
oggz->metric_internal = internal;
} else {
stream = oggz_get_stream (oggz, serialno);
if (stream == NULL) return OGGZ_ERR_BAD_SERIALNO;
if (stream->metric_internal)
oggz_free (stream->metric_user_data);
stream->metric = metric;
stream->metric_user_data = user_data;
stream->metric_internal = internal;
}
return 0;
}
int
oggz_set_metric (OGGZ * oggz, long serialno,
OggzMetric metric, void * user_data)
{
return oggz_set_metric_internal (oggz, serialno, metric, user_data, 0);
}
int
oggz_set_metric_linear (OGGZ * oggz, long serialno,
ogg_int64_t granule_rate_numerator,
ogg_int64_t granule_rate_denominator)
{
oggz_metric_linear_t * linear_data;
/* we divide by the granulerate, ie. mult by gr_d/gr_n, so ensure
* numerator is non-zero */
if (granule_rate_numerator == 0) {
granule_rate_numerator = 1;
granule_rate_denominator = 0;
}
linear_data = oggz_malloc (sizeof (oggz_metric_linear_t));
linear_data->gr_n = granule_rate_numerator;
linear_data->gr_d = granule_rate_denominator;
return oggz_set_metric_internal (oggz, serialno, oggz_metric_default_linear,
linear_data, 1);
}
/*
* Check if an oggz has metrics for all streams
*/
int
oggz_has_metrics (OGGZ * oggz)
{
int i, size;
oggz_stream_t * stream;
if (oggz->metric != NULL) return 1;
size = oggz_vector_size (oggz->streams);
for (i = 0; i < size; i++) {
stream = (oggz_stream_t *)oggz_vector_nth_p (oggz->streams, i);
if (stream->metric == NULL) return 0;
}
return 1;
}
ogg_int64_t
oggz_get_unit (OGGZ * oggz, long serialno, ogg_int64_t granulepos)
{
oggz_stream_t * stream;
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (granulepos == -1) return -1;
if (serialno == -1) {
if (oggz->metric)
return oggz->metric (oggz, serialno, granulepos,
oggz->metric_user_data);
} else {
stream = oggz_get_stream (oggz, serialno);
if (!stream) return -1;
if (stream->metric) {
return stream->metric (oggz, serialno, granulepos,
stream->metric_user_data);
} else if (oggz->metric) {
return oggz->metric (oggz, serialno, granulepos,
oggz->metric_user_data);
}
}
return -1;
}
int
oggz_set_order (OGGZ * oggz, long serialno,
OggzOrder order, void * user_data)
{
oggz_stream_t * stream;
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (oggz->flags & OGGZ_WRITE) {
return OGGZ_ERR_INVALID;
}
if (serialno == -1) {
oggz->order = order;
oggz->order_user_data = user_data;
} else {
stream = oggz_get_stream (oggz, serialno);
stream->order = order;
stream->order_user_data = user_data;
}
return 0;
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,161 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
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.
*/
#ifndef __OGGZ_CONSTANTS_H__
#define __OGGZ_CONSTANTS_H__
/** \file
* General constants used by liboggz.
*/
/**
* Flags to oggz_new(), oggz_open(), and oggz_openfd().
* Can be or'ed together in the following combinations:
* - OGGZ_READ | OGGZ_AUTO
* - OGGZ_WRITE | OGGZ_NONSTRICT
*/
enum OggzFlags {
/** Read only */
OGGZ_READ = 0x00,
/** Write only */
OGGZ_WRITE = 0x01,
/** Disable strict adherence to mapping constraints, eg for
* handling an incomplete stream */
OGGZ_NONSTRICT = 0x10,
/**
* Scan for known headers while reading, and automatically set
* metrics appropriately. Opening a file for reading with
* \a flags = OGGZ_READ | OGGZ_AUTO will allow seeking on Speex,
* Vorbis, Theora and all Annodex streams in units of milliseconds,
* once all bos pages have been delivered. */
OGGZ_AUTO = 0x20
};
enum OggzStatus {
OGGZ_STATUS_INITIALIZED = 0,
OGGZ_STATUS_INTERNAL_ERROR = 1,
OGGZ_STATUS_READ_ACTIVE = 10,
OGGZ_STATUS_READ_STOP_OK = 11,
OGGZ_STATUS_READ_STOP_ERR = 12,
OGGZ_STATUS_READ_EOF = 13
};
enum OggzStopCtl {
/** Continue calling read callbacks */
OGGZ_CONTINUE = 0,
/** Stop calling callbacks, but retain buffered packet data */
OGGZ_STOP_OK = 1,
/** Stop calling callbacks, and purge buffered packet data */
OGGZ_STOP_ERR = -1
};
/**
* Flush options for oggz_write_feed; can be or'ed together
*/
enum OggzFlushOpts {
/** Flush all streams before beginning this packet */
OGGZ_FLUSH_BEFORE = 0x01,
/** Flush after this packet */
OGGZ_FLUSH_AFTER = 0x02
};
/**
* Definitions of error return values
*/
enum OggzError {
/** No error */
OGGZ_ERR_OK = 0,
/** generic error */
OGGZ_ERR_GENERIC = -1,
/** oggz is not a valid OGGZ */
OGGZ_ERR_BAD_OGGZ = -2,
/** The requested operation is not suitable for this OGGZ */
OGGZ_ERR_INVALID = -3,
/** oggz contains no logical bitstreams */
OGGZ_ERR_NO_STREAMS = -4,
/** Operation is inappropriate for oggz in current bos state */
OGGZ_ERR_BOS = -5,
/** Operation is inappropriate for oggz in current eos state */
OGGZ_ERR_EOS = -6,
/** Operation requires a valid metric, but none has been set */
OGGZ_ERR_BAD_METRIC = -7,
/** System specific error; check errno for details */
OGGZ_ERR_SYSTEM = -10,
/** Functionality disabled at build time */
OGGZ_ERR_DISABLED = -11,
/** Seeking operation is not possible for this OGGZ */
OGGZ_ERR_NOSEEK = -13,
/** The requested serialno does not exist in this OGGZ */
OGGZ_ERR_BAD_SERIALNO = -20,
/** Packet disallowed due to invalid byte length */
OGGZ_ERR_BAD_BYTES = -21,
/** Packet disallowed due to invalid b_o_s (beginning of stream) flag */
OGGZ_ERR_BAD_B_O_S = -22,
/** Packet disallowed due to invalid e_o_s (end of stream) flag */
OGGZ_ERR_BAD_E_O_S = -23,
/** Packet disallowed due to invalid granulepos */
OGGZ_ERR_BAD_GRANULEPOS = -24,
/** Packet disallowed due to invalid packetno */
OGGZ_ERR_BAD_PACKETNO = -25,
/** Guard provided by user has non-zero value */
OGGZ_ERR_BAD_GUARD = -210,
/** Attempt to call oggz_write() or oggz_write_output() from within
* a hungry() callback */
OGGZ_ERR_RECURSIVE_WRITE = -266
};
#endif /* __OGGZ_CONSTANTS_H__ */
@@ -0,0 +1,231 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
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.
*/
#ifndef __OGGZ_IO_H__
#define __OGGZ_IO_H__
/** \file
* Overriding the functions used for input and output of raw data.
*
* OggzIO provides a way of overriding the functions Oggz uses to access
* its raw input or output data. This is required in many situations where
* the raw stream cannot be accessed via stdio, but can be accessed by
* other means. This is typically useful within media frameworks, where
* accessing and moving around in the data is possible only using methods
* provided by the framework.
*
* The functions you provide for overriding IO will be used by Oggz
* whenever you call oggz_read() or oggz_write(). They will also be
* used repeatedly by Oggz when you call oggz_seek().
*
* \note Opening a file with oggz_open() or oggz_open_stdio() is equivalent
* to calling oggz_new() and setting stdio based functions for data IO.
*/
/**
* This is the signature of a function which you provide for Oggz
* to call when it needs to acquire raw input data.
*
* \param user_handle A generic pointer you have provided earlier
* \param n The length in bytes that Oggz wants to read
* \param buf The buffer that you read data into
* \retval "> 0" The number of bytes successfully read into the buffer
* \retval 0 to indicate that there is no more data to read (End of file)
* \retval "< 0" An error condition
*/
typedef size_t (*OggzIORead) (void * user_handle, void * buf, size_t n);
/**
* This is the signature of a function which you provide for Oggz
* to call when it needs to output raw data.
*
* \param user_handle A generic pointer you have provided earlier
* \param n The length in bytes of the data
* \param buf A buffer containing data to write
* \retval ">= 0" The number of bytes successfully written (may be less than
* \a n if a write error has occurred)
* \retval "< 0" An error condition
*/
typedef size_t (*OggzIOWrite) (void * user_handle, void * buf, size_t n);
/**
* This is the signature of a function which you provide for Oggz
* to call when it needs to seek on the raw input or output data.
*
* \param user_handle A generic pointer you have provided earlier
* \param offset The offset in bytes to seek to
* \param whence SEEK_SET, SEEK_CUR or SEEK_END (as for stdio.h)
* \retval ">= 0" The offset seeked to
* \retval "< 0" An error condition
*
* \note If you provide an OggzIOSeek function, you MUST also provide
* an OggzIOTell function, or else all your seeks will fail.
*/
typedef int (*OggzIOSeek) (void * user_handle, long offset, int whence);
/**
* This is the signature of a function which you provide for Oggz
* to call when it needs to determine the current offset of the raw
* input or output data.
*
* \param user_handle A generic pointer you have provided earlier
* \retval ">= 0" The offset
* \retval "< 0" An error condition
*/
typedef long (*OggzIOTell) (void * user_handle);
/**
* This is the signature of a function which you provide for Oggz
* to call when it needs to flush the output data. The behaviour
* of this function is similar to that of fflush() in stdio.
*
* \param user_handle A generic pointer you have provided earlier
* \retval 0 Success
* \retval "< 0" An error condition
*/
typedef int (*OggzIOFlush) (void * user_handle);
/**
* Set a function for Oggz to call when it needs to read input data.
*
* \param oggz An OGGZ handle
* \param read Your reading function
* \param user_handle Any arbitrary data you wish to pass to the function
* \retval 0 Success
* \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
* \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ; \a oggz not
* open for reading.
*/
int oggz_io_set_read (OGGZ * oggz, OggzIORead read, void * user_handle);
/**
* Retrieve the user_handle associated with the function you have provided
* for reading input data.
*
* \param oggz An OGGZ handle
* \returns the associated user_handle
*/
void * oggz_io_get_read_user_handle (OGGZ * oggz);
/**
* Set a function for Oggz to call when it needs to write output data.
*
* \param oggz An OGGZ handle
* \param write Your writing function
* \param user_handle Any arbitrary data you wish to pass to the function
* \retval 0 Success
* \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
* \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ; \a oggz not
* open for writing.
*/
int oggz_io_set_write (OGGZ * oggz, OggzIOWrite write, void * user_handle);
/**
* Retrieve the user_handle associated with the function you have provided
* for writing output data.
*
* \param oggz An OGGZ handle
* \returns the associated user_handle
*/
void * oggz_io_get_write_user_handle (OGGZ * oggz);
/**
* Set a function for Oggz to call when it needs to seek on its raw data.
*
* \param oggz An OGGZ handle
* \param seek Your seeking function
* \param user_handle Any arbitrary data you wish to pass to the function
* \retval 0 Success
* \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
* \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
*
* \note If you provide an OggzIOSeek function, you MUST also provide
* an OggzIOTell function, or else all your seeks will fail.
*/
int oggz_io_set_seek (OGGZ * oggz, OggzIOSeek seek, void * user_handle);
/**
* Retrieve the user_handle associated with the function you have provided
* for seeking on input or output data.
*
* \param oggz An OGGZ handle
* \returns the associated user_handle
*/
void * oggz_io_get_seek_user_handle (OGGZ * oggz);
/**
* Set a function for Oggz to call when it needs to determine the offset
* within its input data (if OGGZ_READ) or output data (if OGGZ_WRITE).
*
* \param oggz An OGGZ handle
* \param tell Your tell function
* \param user_handle Any arbitrary data you wish to pass to the function
* \retval 0 Success
* \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
* \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ
*/
int oggz_io_set_tell (OGGZ * oggz, OggzIOTell tell, void * user_handle);
/**
* Retrieve the user_handle associated with the function you have provided
* for determining the current offset in input or output data.
*
* \param oggz An OGGZ handle
* \returns the associated user_handle
*/
void * oggz_io_get_tell_user_handle (OGGZ * oggz);
/**
* Set a function for Oggz to call when it needs to flush its output. The
* meaning of this is similar to that of fflush() in stdio.
*
* \param oggz An OGGZ handle
* \param flush Your flushing function
* \param user_handle Any arbitrary data you wish to pass to the function
* \retval 0 Success
* \retval OGGZ_ERR_BAD_OGGZ \a oggz does not refer to an existing OGGZ
* \retval OGGZ_ERR_INVALID Operation not suitable for this OGGZ; \a oggz not
* open for writing.
*/
int oggz_io_set_flush (OGGZ * oggz, OggzIOFlush flush, void * user_handle);
/**
* Retrieve the user_handle associated with the function you have provided
* for flushing output.
*
* \param oggz An OGGZ handle
* \returns the associated user_handle
*/
void * oggz_io_get_flush_user_handle (OGGZ * oggz);
#endif /* __OGGZ_IO_H__ */
@@ -0,0 +1,103 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
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.
*/
#ifndef __OGGZ_TABLE_H__
#define __OGGZ_TABLE_H__
/** \file
* A lookup table.
*
* OggzTable is provided for convenience to allow the storage of
* serialno-specific data.
*/
/**
* A table of key-value pairs.
*/
typedef void OggzTable;
/**
* Instantiate a new OggzTable
* \returns A new OggzTable
*/
OggzTable *
oggz_table_new (void);
/**
* Delete an OggzTable
* \param table An OggzTable
*/
void
oggz_table_delete (OggzTable * table);
/**
* Insert an element into a table.
* \param table An OggzTable
* \param key Key to access this data element
* \param data The new element to add
* \retval data If the element was successfully added
* \retval NULL If adding the element failed due to a realloc() error
*/
void *
oggz_table_insert (OggzTable * table, long key, void * data);
/**
* Retrieve the element of an OggzTable indexed by a given key
* \param table An OggzTable
* \param key a key
* \returns The element indexed by \a key
* \retval NULL \a table is undefined, or no element is indexed by \a key
*/
void *
oggz_table_lookup (OggzTable * table, long key);
/**
* Query the number of elements in an OggzTable
* \param table An OggzTable
* \returns the number of elements in \a table
*/
int
oggz_table_size (OggzTable * table);
/**
* Retrieve the nth element of an OggzTable
* \param table An OggzTable
* \param n An index into the \a table
* \param key Return value for key corresponding to nth data element
* of \a table
* \returns The nth data element of \a table
* \retval NULL \a table is undefined, or \a n is out of range
*/
void *
oggz_table_nth (OggzTable * table, int n, long * key);
#endif /* __OGGZ_TABLE_H__ */
@@ -0,0 +1,238 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
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.
*/
/*
* oggz_auto.c
*
* Conrad Parker <[email protected]>
*/
#include "config.h"
#if OGGZ_CONFIG_READ
#include <stdlib.h>
#include <string.h>
#include <oggz/oggz.h>
#include "oggz_auto.h"
#include "oggz_byteorder.h"
#include "oggz_macros.h"
#define INT32_LE_AT(x) _le_32((*(ogg_int32_t *)(x)))
#define INT32_BE_AT(x) _be_32((*(ogg_int32_t *)(x)))
#define INT64_LE_AT(x) _le_64((*(ogg_int64_t *)(x)))
/*#define DEBUG*/
#define OGGZ_AUTO_MULT 1000
static int
auto_speex (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
{
unsigned char * header = op->packet;
ogg_int64_t granule_rate = 0;
if (op->bytes < 68) return 0;
if (strncmp ((char *)header, "Speex ", 8)) return 0;
if (!op->b_o_s) return 0;
granule_rate = (ogg_int64_t) INT32_LE_AT(&header[36]);
#ifdef DEBUG
printf ("Got speex rate %d\n", (int)granule_rate);
#endif
oggz_set_metric_linear (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);
return 1;
}
static int
auto_vorbis (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
{
unsigned char * header = op->packet;
ogg_int64_t granule_rate = 0;
if (op->bytes < 30) return 0;
if (header[0] != 0x01) return 0;
if (strncmp ((char *)&header[1], "vorbis", 6)) return 0;
if (!op->b_o_s) return 0;
granule_rate = (ogg_int64_t) INT32_LE_AT(&header[12]);
#ifdef DEBUG
printf ("Got vorbis rate %d\n", (int)granule_rate);
#endif
oggz_set_metric_linear (oggz, serialno, granule_rate, OGGZ_AUTO_MULT);
return 1;
}
typedef struct {
ogg_int32_t fps_numerator;
ogg_int32_t fps_denominator;
int keyframe_shift;
} oggz_theora_metric_t;
static int intlog(int num) {
int ret=0;
while(num>0){
num=num/2;
ret=ret+1;
}
return(ret);
}
static ogg_int64_t
auto_theora_metric (OGGZ * oggz, long serialno, ogg_int64_t granulepos,
void * user_data)
{
oggz_theora_metric_t * tdata = (oggz_theora_metric_t *)user_data;
ogg_int64_t iframe, pframe;
ogg_int64_t units;
iframe = granulepos >> tdata->keyframe_shift;
pframe = granulepos - (iframe << tdata->keyframe_shift);
granulepos = (iframe + pframe);
units = OGGZ_AUTO_MULT * granulepos * tdata->fps_denominator /
tdata->fps_numerator;
return units;
}
static int
auto_theora (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
{
unsigned char * header = op->packet;
char keyframe_granule_shift = 0;
oggz_theora_metric_t * tdata;
if (op->bytes < 41) return 0;
if (header[0] != 0x80) return 0;
if (strncmp ((char *)&header[1], "theora", 6)) return 0;
if (!op->b_o_s) return 0;
tdata = oggz_malloc (sizeof (oggz_theora_metric_t));
tdata->fps_numerator = INT32_BE_AT(&header[22]);
tdata->fps_denominator = INT32_BE_AT(&header[26]);
#if USE_THEORA_PRE_ALPHA_3_FORMAT
/* old header format, used by Theora alpha2 and earlier */
keyframe_granule_shift = (header[36] & 0xf8) >> 3;
#else
keyframe_granule_shift = (header[40] & 0x03) << 3;
keyframe_granule_shift |= (header[41] & 0xe0) >> 5;
#endif
tdata->keyframe_shift = intlog (keyframe_granule_shift - 1);
#ifdef DEBUG
printf ("Got theora fps %d/%d, keyframe_granule_shift %d\n",
tdata->fps_numerator, tdata->fps_denominator,
keyframe_granule_shift);
#endif
/*oggz_set_metric_internal (oggz, serialno, auto_theora_metric, tdata, 1);*/
oggz_set_metric (oggz, serialno, auto_theora_metric, tdata);
return 1;
}
static int
auto_annodex (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
{
unsigned char * header = op->packet;
if (op->bytes < 8) return 0;
if (strncmp ((char *)header, "Annodex", 8)) return 0;
if (!op->b_o_s) return 0;
/* Yeah ... set it up with a "linear" metric with numerator 0 :) */
oggz_set_metric_linear (oggz, serialno, 0, 1);
return 1;
}
static int
auto_anxdata (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
{
unsigned char * header = op->packet;
ogg_int64_t granule_rate_numerator = 0, granule_rate_denominator = 0;
if (op->bytes < 28) return 0;
if (strncmp ((char *)header, "AnxData", 8)) return 0;
if (!op->b_o_s) return 0;
granule_rate_numerator = INT64_LE_AT(&header[8]);
granule_rate_denominator = INT64_LE_AT(&header[16]);
#ifdef DEBUG
printf ("Got AnxData rate %lld/%lld\n", granule_rate_numerator,
granule_rate_denominator);
#endif
oggz_set_metric_linear (oggz, serialno,
granule_rate_numerator,
OGGZ_AUTO_MULT * granule_rate_denominator);
return 1;
}
static OggzReadPacket auto_readers[] = {
auto_speex,
auto_vorbis,
auto_theora,
auto_annodex,
auto_anxdata,
NULL
};
int
oggz_auto (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data)
{
OggzReadPacket read_packet;
int i = 0;
for (read_packet = auto_readers[0]; read_packet;
read_packet = auto_readers[++i]) {
if (read_packet (oggz, op, serialno, user_data)) return 0;
}
return 0;
}
#endif /* OGGZ_CONFIG_READ */
@@ -0,0 +1,255 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
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.
*/
/*
* oggz_auto.h
*
* Conrad Parker <[email protected]>
*/
#ifndef __OGGZ_AUTO_H__
#define __OGGZ_AUTO_H__
#include <ogg/os_types.h>
/**
* Speex
*
* Default field type: LITTLE ENDIAN unsigned integer
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1| Byte
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| speex_string: Identifier char[8]: 'Speex ' | 0-3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | 4-7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| speex_version: char[20] | 8-11
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | 12-15
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | 16-19
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | 20-23
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | 24-27
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| speex_version_id | 28-31
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| header_size | 32-35
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| rate | 36-39
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| mode | 40-43
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| mode_bitstream_version | 44-47
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| nb_channels | 48-51
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| bitrate | 52-55
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| frame_size | 56-59
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| vbr | 60-63
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| frames_per_packet | 64-67
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| extra_headers | 68-71
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| reserved1 | 72-75
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| reserved2 | 76-79
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Vorbis
*
* Default field type: LITTLE ENDIAN unsigned integer
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1| Byte
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| packtype | Identifier char[6]: 'vorbis' | 0-3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | version | 4-7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | channels | 8-11
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| rate | 12-15
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| bitrate_upper | 16-19
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| bitrate_nominal | 20-23
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| bitrate_lower | 24-27
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| l2bs0 | l2bs1 |e| 28-31
+-+-+-+-+-+-+-+-+-+
*/
/**
* Theora
*
* Default field type: BIG ENDIAN unsigned integer
*
Field names in full caps refer to fields described in the Theora I
specification. Lowercase refers to theora_info struct members from
libtheora.
This is the Theora header for theora-alpha3:
(VMAJ=3, VMIN=2, VREV=0)
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1| Byte
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| packtype | Identifier char[6]: 'theora' | 0-3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | VMAJ | 4-7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| VMIN | VREV | FMBW: width >> 4 | 8-11
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| FMBH: height >> 4 | PICW: frame_width | 12-15
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | PICH: frame_height | 16-19
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| PICX: offset_x| PICY: offset_y| FRN: fps_numerator | 20-23
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | FRD: fps_denominator | 24-27
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | PARN: aspect_numerator | 28-31
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | PARD: aspect_denominator | 32-35
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| CS: colorspace| NOMBR: target_bitrate | 36-39
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| QUAL | KFGSHIFT| PF| resv| 40-43
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
This was the Theora header for theora-alpha2:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1| Byte
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| packtype | Identifier char[6]: 'theora' | 0-3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | Version major | 4-7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Version minor | Version sub | width >> 4 | 8-11
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| height >> 4 | frame_width | 12-15
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | frame_height | 16-19
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| offset_x | offset_y | fps_numerator | 20-23
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | fps_denominator | 24-27
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | aspect_numerator | 28-31
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | aspect_denominator | 32-35
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| kgshift | colorspace | target_bitrate | 36-39
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | quality | 40-43
+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* Annodex
*
* Default field type: LITTLE ENDIAN unsigned integer
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1| Byte
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identifier char[8]: 'Annodex\0' | 0-3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | 4-7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Version major | Version minor | 8-11
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Timebase numerator | 12-15
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | 16-19
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Timebase denominator | 20-23
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | 24-27
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| UTC | 28-31
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | 32-35
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | 36-39
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | 40-43
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | 44-47
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
/**
* AnxData
*
* Default field type: LITTLE ENDIAN unsigned integer
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1| Byte
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Identifier char[8]: 'AnxData\0' | 0-3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | 4-7
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Granule rate numerator | 8-11
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | 12-15
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Granule rate denominator | 16-19
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| | 20-23
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Number of secondary header pages | 24-27
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Headers ... | 28-
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
#endif /* __OGGZ_AUTO_H__ */
@@ -0,0 +1,103 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
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.
*/
#ifndef __OGGZ_BYTEORDER_H__
#define __OGGZ_BYTEORDER_H__
#ifdef _UNUSED_
static unsigned short
_le_16 (unsigned short s)
{
unsigned short ret=s;
#ifdef WORDS_BIGENDIAN
ret = (s>>8) & 0x00ffU;
ret += (s<<8) & 0xff00U;
#endif
return ret;
}
#endif
static ogg_uint32_t
_le_32 (ogg_uint32_t i)
{
ogg_uint32_t ret=i;
#ifdef WORDS_BIGENDIAN
ret = (i>>24);
ret += (i>>8) & 0x0000ff00;
ret += (i<<8) & 0x00ff0000;
ret += (i<<24);
#endif
return ret;
}
static ogg_uint32_t
_be_32 (ogg_uint32_t i)
{
ogg_uint32_t ret=i;
#ifndef WORDS_BIGENDIAN
ret = (i>>24);
ret += (i>>8) & 0x0000ff00;
ret += (i<<8) & 0x00ff0000;
ret += (i<<24);
#endif
return ret;
}
static ogg_int64_t
_le_64 (ogg_int64_t l)
{
ogg_int64_t ret=l;
unsigned char *ucptr = (unsigned char *)&ret;
#ifdef WORDS_BIGENDIAN
unsigned char temp;
temp = ucptr [0] ;
ucptr [0] = ucptr [7] ;
ucptr [7] = temp ;
temp = ucptr [1] ;
ucptr [1] = ucptr [6] ;
ucptr [6] = temp ;
temp = ucptr [2] ;
ucptr [2] = ucptr [5] ;
ucptr [5] = temp ;
temp = ucptr [3] ;
ucptr [3] = ucptr [4] ;
ucptr [4] = temp ;
#endif
return (*(ogg_int64_t *)ucptr);
}
#endif /* __OGGZ_BYTEORDER_H__ */
@@ -0,0 +1,45 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
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 "config.h"
#ifdef HAVE_RANDOM
# define oggz_random random
#else
# define oggz_random rand
#endif
#ifndef WIN32
# define oggz_stat_regular(mode) (S_ISREG((mode)) || S_ISLNK((mode)))
#else
# define oggz_stat_regular(mode) ((mode) & S_IFREG)
#endif
@@ -0,0 +1,307 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
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.
*/
/*
* oggz_io.c
*
* Conrad Parker <[email protected]>
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include "oggz_compat.h"
#include "oggz_private.h"
/*#define DEBUG*/
size_t
oggz_io_read (OGGZ * oggz, void * buf, size_t n)
{
OggzIO * io;
size_t bytes;
if (oggz->file != NULL) {
if ((bytes = fread (buf, 1, n, oggz->file)) == 0) {
if (ferror (oggz->file)) {
return OGGZ_ERR_SYSTEM;
}
}
}
else if ((io = oggz->io) != NULL) {
if (io->read == NULL) return -1;
bytes = io->read (io->read_user_handle, buf, n);
}
else return OGGZ_ERR_INVALID;
return bytes;
}
size_t
oggz_io_write (OGGZ * oggz, void * buf, size_t n)
{
OggzIO * io;
size_t bytes;
if (oggz->file != NULL) {
bytes = fwrite (buf, 1, n, oggz->file);
}
else if ((io = oggz->io) != NULL) {
if (io->write == NULL) return -1;
bytes = io->write (io->write_user_handle, buf, n);
}
else return OGGZ_ERR_INVALID;
return bytes;
}
int
oggz_io_seek (OGGZ * oggz, long offset, int whence)
{
OggzIO * io;
if (oggz->file != NULL) {
if (fseek (oggz->file, offset, whence) == -1) {
if (errno == ESPIPE) {
/*oggz_set_error (oggz, OGGZ_ERR_NOSEEK);*/
} else {
/*oggz_set_error (oggz, OGGZ_ERR_SYSTEM);*/
}
return OGGZ_ERR_SYSTEM;
}
}
else if ((io = oggz->io) != NULL) {
if (io->seek == NULL) return -1;
if (io->seek (io->seek_user_handle, offset, whence) == -1)
return -1;
}
else return OGGZ_ERR_INVALID;
return 0;
}
long
oggz_io_tell (OGGZ * oggz)
{
OggzIO * io;
long offset;
if (oggz->file != NULL) {
if ((offset = ftell (oggz->file)) == -1) {
if (errno == ESPIPE) {
/*oggz_set_error (oggz, OGGZ_ERR_NOSEEK);*/
} else {
/*oggz_set_error (oggz, OGGZ_ERR_SYSTEM);*/
}
return -1;
}
}
else if ((io = oggz->io) != NULL) {
if (io->tell == NULL) return -1;
if ((offset = io->tell (io->tell_user_handle)) == -1)
return -1;
}
else return OGGZ_ERR_INVALID;
return offset;
}
int
oggz_io_flush (OGGZ * oggz)
{
OggzIO * io;
if (oggz->file != NULL) {
if (fflush (oggz->file) == EOF) {
/* check errno for write-related errors */
return OGGZ_ERR_SYSTEM;
}
}
else if ((io = oggz->io) != NULL) {
if (io->flush == NULL) return OGGZ_ERR_INVALID;
if (io->flush (io->flush_user_handle) == -1) {
return -1;
}
}
else return OGGZ_ERR_INVALID;
return 0;
}
/* get/set functions */
static void
oggz_io_init (OGGZ * oggz)
{
oggz->io = (OggzIO *) oggz_malloc (sizeof (OggzIO));
memset (oggz->io, 0, sizeof (OggzIO));
}
int
oggz_io_set_read (OGGZ * oggz, OggzIORead read, void * user_handle)
{
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (oggz->file != NULL) return OGGZ_ERR_INVALID;
if (oggz->io == NULL) oggz_io_init (oggz);
oggz->io->read = read;
oggz->io->read_user_handle = user_handle;
return 0;
}
void *
oggz_io_get_read_user_handle (OGGZ * oggz)
{
if (oggz == NULL) return NULL;
if (oggz->file != NULL) return NULL;
if (oggz->io == NULL) return NULL;
return oggz->io->read_user_handle;
}
int
oggz_io_set_write (OGGZ * oggz, OggzIOWrite write, void * user_handle)
{
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (oggz->file != NULL) return OGGZ_ERR_INVALID;
if (oggz->io == NULL) oggz_io_init (oggz);
oggz->io->write = write;
oggz->io->write_user_handle = user_handle;
return 0;
}
void *
oggz_io_get_write_user_handle (OGGZ * oggz)
{
if (oggz == NULL) return NULL;
if (oggz->file != NULL) return NULL;
if (oggz->io == NULL) return NULL;
return oggz->io->write_user_handle;
}
int
oggz_io_set_seek (OGGZ * oggz, OggzIOSeek seek, void * user_handle)
{
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (oggz->file != NULL) return OGGZ_ERR_INVALID;
if (oggz->io == NULL) oggz_io_init (oggz);
oggz->io->seek = seek;
oggz->io->seek_user_handle = user_handle;
return 0;
}
void *
oggz_io_get_seek_user_handle (OGGZ * oggz)
{
if (oggz == NULL) return NULL;
if (oggz->file != NULL) return NULL;
if (oggz->io == NULL) return NULL;
return oggz->io->seek_user_handle;
}
int
oggz_io_set_tell (OGGZ * oggz, OggzIOTell tell, void * user_handle)
{
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (oggz->file != NULL) return OGGZ_ERR_INVALID;
if (oggz->io == NULL) oggz_io_init (oggz);
oggz->io->tell = tell;
oggz->io->tell_user_handle = user_handle;
return 0;
}
void *
oggz_io_get_tell_user_handle (OGGZ * oggz)
{
if (oggz == NULL) return NULL;
if (oggz->file != NULL) return NULL;
if (oggz->io == NULL) return NULL;
return oggz->io->tell_user_handle;
}
int
oggz_io_set_flush (OGGZ * oggz, OggzIOFlush flush, void * user_handle)
{
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (oggz->file != NULL) return OGGZ_ERR_INVALID;
if (oggz->io == NULL) oggz_io_init (oggz);
oggz->io->flush = flush;
oggz->io->flush_user_handle = user_handle;
return 0;
}
void *
oggz_io_get_flush_user_handle (OGGZ * oggz)
{
if (oggz == NULL) return NULL;
if (oggz->file != NULL) return NULL;
if (oggz->io == NULL) return NULL;
return oggz->io->flush_user_handle;
}
@@ -0,0 +1,48 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
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.
*/
#ifndef __OGGZ_MACROS_H__
#define __OGGZ_MACROS_H__
#include <ogg/ogg.h>
/* Use the malloc and free used by ogg; defaults are those from stdlib */
#define oggz_malloc _ogg_malloc
#define oggz_free _ogg_free
#undef MIN
#define MIN(a,b) ((a)<(b)?(a):(b))
#undef MAX
#define MAX(a,b) ((a)>(b)?(a):(b))
#endif /* __OGGZ_MACROS_H__ */
@@ -0,0 +1,222 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
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.
*/
#ifndef __OGGZ_PRIVATE_H__
#define __OGGZ_PRIVATE_H__
#include <stdio.h>
#include <sys/types.h>
#include <ogg/ogg.h>
#include <oggz/oggz_constants.h>
#include "oggz_macros.h"
#include "oggz_vector.h"
typedef struct _OGGZ OGGZ;
typedef struct _OggzIO OggzIO;
typedef struct _OggzReader OggzReader;
typedef struct _OggzWriter OggzWriter;
typedef int (*OggzReadPacket) (OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data);
typedef ogg_int64_t (*OggzMetric) (OGGZ * oggz, long serialno,
ogg_int64_t granulepos,
void * user_data);
typedef int (*OggzOrder) (OGGZ * oggz, ogg_packet * op, void * target,
void * user_data);
typedef int (*OggzWriteHungry) (OGGZ * oggz, int empty, void * user_data);
/* oggz_io */
typedef size_t (*OggzIORead) (void * user_handle, void * buf, size_t n);
typedef size_t (*OggzIOWrite) (void * user_handle, void * buf, size_t n);
typedef int (*OggzIOSeek) (void * user_handle, long offset, int whence);
typedef long (*OggzIOTell) (void * user_handle);
typedef int (*OggzIOFlush) (void * user_handle);
typedef struct {
ogg_stream_state ogg_stream;
/* non b_o_s packet has been written (not just queued) */
int delivered_non_b_o_s;
int b_o_s; /* beginning of stream */
int e_o_s; /* end of stream */
ogg_int64_t granulepos;
ogg_int64_t packetno;
OggzMetric metric;
void * metric_user_data;
int metric_internal;
OggzOrder order;
void * order_user_data;
OggzReadPacket read_packet;
void * read_user_data;
} oggz_stream_t;
struct _OggzReader {
ogg_sync_state ogg_sync;
/* XXX: these two can prolly be removed again :) */
ogg_stream_state ogg_stream;
long current_serialno;
OggzReadPacket read_packet;
void * read_user_data;
ogg_int64_t current_unit;
#if 0
off_t offset_page_end; /* offset of end of current page */
#endif
};
/**
* Bundle a packet with the stream it is being queued for; used in
* the packet_queue vector
*/
typedef struct {
ogg_packet op;
oggz_stream_t * stream;
int flush;
int * guard;
} oggz_writer_packet_t;
enum oggz_writer_state {
OGGZ_MAKING_PACKETS = 0,
OGGZ_WRITING_PAGES = 1
};
struct _OggzWriter {
oggz_writer_packet_t * next_zpacket; /* stashed in case of FLUSH_BEFORE */
OggzVector * packet_queue;
OggzWriteHungry hungry;
void * hungry_user_data;
int hungry_only_when_empty;
int writing; /* already mid-write; check for recursive writes */
int state; /* OGGZ_MAKING_PACKETS or OGGZ_WRITING_PAGES */
int flushing; /* whether current packet is being flushed or just paged out */
int eog; /* end of page */
#if 0
int eop; /* end of packet */
#endif
int eos; /* end of stream */
oggz_writer_packet_t * current_zpacket;
int packet_offset; /* n bytes already copied out of current packet */
int page_offset; /* n bytes already copied out of current page */
ogg_stream_state * current_stream;
};
struct _OggzIO {
OggzIORead read;
void * read_user_handle;
OggzIOWrite write;
void * write_user_handle;
OggzIOSeek seek;
void * seek_user_handle;
OggzIOTell tell;
void * tell_user_handle;
OggzIOFlush flush;
void * flush_user_handle;
};
struct _OGGZ {
int flags;
FILE * file;
OggzIO * io;
ogg_packet current_packet;
ogg_page current_page;
off_t offset; /* offset of current page start */
off_t offset_data_begin; /* offset of unit 0 page start */
OggzVector * streams;
int all_at_eos; /* all streams are at eos */
OggzMetric metric;
void * metric_user_data;
int metric_internal;
OggzOrder order;
void * order_user_data;
union {
OggzReader reader;
OggzWriter writer;
} x;
};
OGGZ * oggz_read_init (OGGZ * oggz);
OGGZ * oggz_read_close (OGGZ * oggz);
OGGZ * oggz_write_init (OGGZ * oggz);
OGGZ * oggz_write_close (OGGZ * oggz);
oggz_stream_t * oggz_get_stream (OGGZ * oggz, long serialno);
oggz_stream_t * oggz_add_stream (OGGZ * oggz, long serialno);
int oggz_get_bos (OGGZ * oggz, long serialno);
ogg_int64_t oggz_get_unit (OGGZ * oggz, long serialno, ogg_int64_t granulepos);
int oggz_set_metric_internal (OGGZ * oggz, long serialno, OggzMetric metric,
void * user_data, int internal);
int oggz_has_metrics (OGGZ * oggz);
int oggz_purge (OGGZ * oggz);
int oggz_auto (OGGZ * oggz, ogg_packet * op, long serialno, void * user_data);
/* oggz_io */
size_t oggz_io_read (OGGZ * oggz, void * buf, size_t n);
size_t oggz_io_write (OGGZ * oggz, void * buf, size_t n);
int oggz_io_seek (OGGZ * oggz, long offset, int whence);
long oggz_io_tell (OGGZ * oggz);
int oggz_io_flush (OGGZ * oggz);
#endif /* __OGGZ_PRIVATE_H__ */
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,122 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
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 <stdlib.h>
#include "oggz_macros.h"
#include "oggz_vector.h"
typedef struct _OggzTable OggzTable;
struct _OggzTable {
OggzVector * keys;
OggzVector * data;
};
OggzTable *
oggz_table_new (void)
{
OggzTable * table;
table = oggz_malloc (sizeof (OggzTable));
table->keys = oggz_vector_new ();
table->data = oggz_vector_new ();
return table;
}
void
oggz_table_delete (OggzTable * table)
{
if (table == NULL) return;
oggz_vector_delete (table->keys);
oggz_vector_delete (table->data);
oggz_free (table);
}
void *
oggz_table_lookup (OggzTable * table, long key)
{
int i, size;
size = oggz_vector_size (table->keys);
for (i = 0; i < size; i++) {
if (oggz_vector_nth_l (table->keys, i) == key) {
return oggz_vector_nth_p (table->data, i);
}
}
return NULL;
}
void *
oggz_table_insert (OggzTable * table, long key, void * data)
{
void * old_data;
if ((old_data = oggz_table_lookup (table, key)) != NULL) {
if (oggz_vector_remove_l (table->keys, key) == NULL)
return NULL;
if (oggz_vector_remove_p (table->data, old_data) == NULL) {
/* XXX: This error condition can only happen if the previous
* removal succeeded, and this removal failed, ie. there was
* an error reallocing table->data->data downwards. */
return NULL;
}
}
if (oggz_vector_insert_l (table->keys, key) == -1)
return NULL;
if (oggz_vector_insert_p (table->data, data) == NULL) {
oggz_vector_remove_l (table->keys, key);
return NULL;
}
return data;
}
int
oggz_table_size (OggzTable * table)
{
if (table == NULL) return 0;
return oggz_vector_size (table->data);
}
void *
oggz_table_nth (OggzTable * table, int n, long * key)
{
if (table == NULL) return NULL;
if (key) *key = oggz_vector_nth_l (table->keys, n);
return oggz_vector_nth_p (table->data, n);
}
@@ -0,0 +1,399 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
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 <string.h>
#include "oggz_macros.h"
typedef int (*OggzFunc) (void * data);
typedef int (*OggzFindFunc) (void * data, long serialno);
typedef int (*OggzCmpFunc) (void * a, void * b, void * user_data);
typedef struct _OggzVector OggzVector;
typedef union {
void * p;
long l;
} oggz_data_t;
struct _OggzVector {
int max_elements;
int nr_elements;
oggz_data_t * data;
OggzCmpFunc compare;
void * compare_user_data;
};
/*
* A vector of void * or long; iff it's a vector of void * objects, it
* can be optionally sorted. (The sorting is used to implement the
* packet queue; the vector of longs is used to implement OggzTable)
*
* if you set a comparison function (oggz_vector_set_cmp()), the vector
* will be sorted and new elements will be inserted in sorted order.
*
* if you don't set a comparison function, new elements will be appended
* at the tail
*
* to unset the comparison function, call oggz_vector_set_cmp (NULL,NULL)
*/
OggzVector *
oggz_vector_new (void)
{
OggzVector * vector;
vector = oggz_malloc (sizeof (OggzVector));
vector->max_elements = 0;
vector->nr_elements = 0;
vector->data = NULL;
vector->compare = NULL;
vector->compare_user_data = NULL;
return vector;
}
static void
oggz_vector_clear (OggzVector * vector)
{
oggz_free (vector->data);
vector->data = NULL;
vector->nr_elements = 0;
vector->max_elements = 0;
}
void
oggz_vector_delete (OggzVector * vector)
{
oggz_vector_clear (vector);
oggz_free (vector);
}
int
oggz_vector_size (OggzVector * vector)
{
if (vector == NULL) return 0;
return vector->nr_elements;
}
void *
oggz_vector_nth_p (OggzVector * vector, int n)
{
if (vector == NULL) return NULL;
if (n >= vector->nr_elements) return NULL;
return vector->data[n].p;
}
long
oggz_vector_nth_l (OggzVector * vector, int n)
{
if (vector == NULL) return -1L;
if (n >= vector->nr_elements) return -1L;
return vector->data[n].l;
}
void *
oggz_vector_find (OggzVector * vector, OggzFindFunc func, long serialno)
{
void * data;
int i;
for (i = 0; i < vector->nr_elements; i++) {
data = vector->data[i].p;
if (func (data, serialno))
return data;
}
return NULL;
}
int
oggz_vector_foreach (OggzVector * vector, OggzFunc func)
{
int i;
for (i = 0; i < vector->nr_elements; i++) {
func (vector->data[i].p);
}
return 0;
}
static void
_array_swap (oggz_data_t v[], int i, int j)
{
void * t;
t = v[i].p;
v[i].p = v[j].p;
v[j].p = t;
}
/**
* Helper function for oggz_vector_insert (). Sorts the vector by
* insertion sort, assuming the tail element has just been added and the
* rest of the vector is sorted.
* \param vector An OggzVector
* \pre The vector has just had a new element added to its tail
* \pre All elements other than the tail element are already sorted.
*/
static void
oggz_vector_tail_insertion_sort (OggzVector * vector)
{
int i;
if (vector->compare == NULL) return;
for (i = vector->nr_elements-1; i > 0; i--) {
if (vector->compare (vector->data[i-1].p, vector->data[i].p,
vector->compare_user_data) > 0) {
_array_swap (vector->data, i, i-1);
} else {
break;
}
}
return;
}
static OggzVector *
oggz_vector_grow (OggzVector * vector)
{
void * new_elements;
int new_max_elements;
vector->nr_elements++;
if (vector->nr_elements > vector->max_elements) {
if (vector->max_elements == 0) {
new_max_elements = 1;
} else {
new_max_elements = vector->max_elements * 2;
}
new_elements =
realloc (vector->data, (size_t)new_max_elements * sizeof (oggz_data_t));
if (new_elements == NULL) {
vector->nr_elements--;
return NULL;
}
vector->max_elements = new_max_elements;
vector->data = new_elements;
}
return vector;
}
void *
oggz_vector_insert_p (OggzVector * vector, void * data)
{
if (oggz_vector_grow (vector) == NULL)
return NULL;
vector->data[vector->nr_elements-1].p = data;
oggz_vector_tail_insertion_sort (vector);
return data;
}
long
oggz_vector_insert_l (OggzVector * vector, long ldata)
{
if (oggz_vector_grow (vector) == NULL)
return -1;
vector->data[vector->nr_elements-1].l = ldata;
return ldata;
}
static void
oggz_vector_qsort (OggzVector * vector, int left, int right)
{
int i, last;
oggz_data_t * v = vector->data;
if (left >= right) return;
_array_swap (v, left, (left + right)/2);
last = left;
for (i = left+1; i <= right; i++) {
if (vector->compare (v[i].p, v[left].p, vector->compare_user_data) < 0)
_array_swap (v, ++last, i);
}
_array_swap (v, left, last);
oggz_vector_qsort (vector, left, last-1);
oggz_vector_qsort (vector, last+1, right);
}
int
oggz_vector_set_cmp (OggzVector * vector, OggzCmpFunc compare,
void * user_data)
{
vector->compare = compare;
vector->compare_user_data = user_data;
if (compare) {
oggz_vector_qsort (vector, 0, vector->nr_elements-1);
}
return 0;
}
static void *
oggz_vector_remove_nth (OggzVector * vector, int n)
{
int i;
oggz_data_t * new_elements;
int new_max_elements;
vector->nr_elements--;
if (vector->nr_elements == 0) {
oggz_vector_clear (vector);
} else {
for (i = n; i < vector->nr_elements; i++) {
vector->data[i] = vector->data[i+1];
}
if (vector->nr_elements < vector->max_elements/2) {
new_max_elements = vector->max_elements/2;
new_elements =
realloc (vector->data,
(size_t)new_max_elements * sizeof (oggz_data_t));
if (new_elements == NULL)
return NULL;
vector->max_elements = new_max_elements;
vector->data = new_elements;
}
}
return vector;
}
OggzVector *
oggz_vector_remove_p (OggzVector * vector, void * data)
{
int i;
for (i = 0; i < vector->nr_elements; i++) {
if (vector->data[i].p == data) {
return oggz_vector_remove_nth (vector, i);
}
}
return vector;
}
OggzVector *
oggz_vector_remove_l (OggzVector * vector, long ldata)
{
int i;
for (i = 0; i < vector->nr_elements; i++) {
if (vector->data[i].l == ldata) {
return oggz_vector_remove_nth (vector, i);
}
}
return vector;
}
void *
oggz_vector_pop (OggzVector * vector)
{
void * data;
#if 0
void * new_elements;
int new_max_elements;
#endif
if (!vector || vector->data == NULL) return NULL;
data = vector->data[0].p;
#if 0
vector->nr_elements--;
if (vector->nr_elements == 0) {
oggz_vector_clear (vector);
} else {
#if 0
memmove (vector->data, &vector->data[1],
vector->nr_elements * sizeof (void *));
#else
{
int i;
for (i = 0; i < vector->nr_elements; i++) {
vector->data[i].p = vector->data[i+1].p;
}
}
#endif
if (vector->nr_elements < vector->max_elements/2) {
new_max_elements = vector->max_elements/2;
new_elements =
realloc (vector->data,
(size_t)new_max_elements * sizeof (oggz_data_t));
if (new_elements != NULL) {
vector->max_elements = new_max_elements;
vector->data = new_elements;
}
}
}
#else
oggz_vector_remove_nth (vector, 0);
#endif
return data;
}
@@ -0,0 +1,101 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
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.
*/
#ifndef __OGGZ_VECTOR_H__
#define __OGGZ_VECTOR_H__
typedef void OggzVector;
typedef int (*OggzFunc) (void * data);
typedef int (*OggzFindFunc) (void * data, long serialno);
typedef int (*OggzCmpFunc) (void * a, void * b, void * user_data);
OggzVector *
oggz_vector_new (void);
void
oggz_vector_delete (OggzVector * vector);
void *
oggz_vector_find (OggzVector * vector, OggzFindFunc func, long serialno);
void *
oggz_vector_nth_p (OggzVector * vector, int n);
long
oggz_vector_nth_l (OggzVector * vector, int n);
int
oggz_vector_foreach (OggzVector * vector, OggzFunc func);
int
oggz_vector_size (OggzVector * vector);
/**
* Add an element to a vector. If the vector has a comparison function,
* the new element is inserted in sorted order, otherwise it is appended
* to the tail.
* \param vector An OggzVector
* \param data The new element to add
* \retval data If the element was successfully added
* \retval NULL If adding the element failed due to a realloc() error
*/
void *
oggz_vector_insert_p (OggzVector * vector, void * data);
long
oggz_vector_insert_l (OggzVector * vector, long ldata);
/**
* Remove a (void *) element of a vector
* \retval \a vector on success
* \retval NULL on failure (realloc error)
*/
OggzVector *
oggz_vector_remove_p (OggzVector * vector, void * data);
/**
* Remove a (long) element of a vector
* \retval \a vector on success
* \retval NULL on failure (realloc error)
*/
OggzVector *
oggz_vector_remove_l (OggzVector * vector, long ldata);
int
oggz_vector_set_cmp (OggzVector * vector, OggzCmpFunc compare,
void * user_data);
void *
oggz_vector_pop (OggzVector * vector);
#endif /* __OGGZ_VECTOR_H__ */
@@ -0,0 +1,749 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
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 "config.h"
#if OGGZ_CONFIG_WRITE
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <ogg/ogg.h>
#include "oggz_private.h"
#include "oggz_vector.h"
/* #define DEBUG */
/* #define ALWAYS_FLUSH */
/* #define ZPACKET_CMP */
#ifdef ZPACKET_CMP
static int
oggz_zpacket_cmp (oggz_writer_packet_t * a, oggz_writer_packet_t * b,
void * user_data)
{
OGGZ * oggz = (OGGZ *)user_data;
long serialno_a, serialno_b;
ogg_int64_t unit_a, unit_b;
serialno_a = a->stream->ogg_stream.serialno;
serialno_b = b->stream->ogg_stream.serialno;
unit_a = oggz_get_unit (oggz, serialno_a, a->op.granulepos);
unit_b = oggz_get_unit (oggz, serialno_b, b->op.granulepos);
if (unit_a < unit_b) return -1;
else return (unit_a > unit_b);
}
#endif
OGGZ *
oggz_write_init (OGGZ * oggz)
{
OggzWriter * writer = &oggz->x.writer;
writer->next_zpacket = NULL;
writer->packet_queue = oggz_vector_new ();
#ifdef ZPACKET_CMP
/* XXX: comparison function should only kick in when a metric is set */
oggz_vector_set_cmp (writer->packet_queue,
(OggzCmpFunc)oggz_zpacket_cmp, oggz);
#endif
writer->hungry = NULL;
writer->hungry_user_data = NULL;
writer->hungry_only_when_empty = 0;
writer->writing = 0;
writer->state = OGGZ_MAKING_PACKETS;
writer->flushing = 0;
#if 0
writer->eog = 1;
writer->eop = 1; /* init ready to start next packet */
#endif
writer->eos = 0;
writer->current_zpacket = NULL;
writer->packet_offset = 0;
writer->page_offset = 0;
return oggz;
}
static int
oggz_writer_packet_free (oggz_writer_packet_t * zpacket)
{
if (!zpacket) return 0;
if (zpacket->guard) {
/* managed by user; flag guard */
*zpacket->guard = 1;
} else {
/* managed by oggz; free copied data */
oggz_free (zpacket->op.packet);
}
oggz_free (zpacket);
return 0;
}
OGGZ *
oggz_write_close (OGGZ * oggz)
{
OggzWriter * writer = &oggz->x.writer;
oggz_vector_foreach (writer->packet_queue,
(OggzFunc)oggz_writer_packet_free);
oggz_vector_delete (writer->packet_queue);
return oggz;
}
/******** Packet queueing ********/
int
oggz_write_set_hungry_callback (OGGZ * oggz, OggzWriteHungry hungry,
int only_when_empty, void * user_data)
{
OggzWriter * writer;
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (!(oggz->flags & OGGZ_WRITE)) {
return OGGZ_ERR_INVALID;
}
writer = &oggz->x.writer;
writer->hungry = hungry;
writer->hungry_user_data = user_data;
writer->hungry_only_when_empty = only_when_empty;
return 0;
}
int
oggz_write_feed (OGGZ * oggz, ogg_packet * op, long serialno, int flush,
int * guard)
{
OggzWriter * writer;
oggz_stream_t * stream;
oggz_writer_packet_t * packet;
ogg_packet * new_op;
unsigned char * new_buf;
int b_o_s, e_o_s, bos_auto;
int strict;
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (!(oggz->flags & OGGZ_WRITE)) {
return OGGZ_ERR_INVALID;
}
writer = &oggz->x.writer;
if (guard && *guard != 0) return OGGZ_ERR_BAD_GUARD;
#ifdef DEBUG
printf ("oggz_write_feed: (%010ld) FLUSH: %d\n", serialno, flush);
#endif
/* Cache strict */
strict = !(oggz->flags & OGGZ_NONSTRICT);
/* Set bos, eos to canonical values */
bos_auto = (op->b_o_s == -1) ? 1 : 0;
b_o_s = op->b_o_s ? 1 : 0;
e_o_s = op->e_o_s ? 1 : 0;
stream = oggz_get_stream (oggz, serialno);
if (stream == NULL) {
if (bos_auto) b_o_s = 1;
if (strict && b_o_s && !oggz_get_bos (oggz, -1)) {
return OGGZ_ERR_BOS;
}
if (b_o_s || !strict) {
stream = oggz_add_stream (oggz, serialno);
} else {
return OGGZ_ERR_BAD_SERIALNO;
}
} else {
if (bos_auto) b_o_s = 0;
if (strict && stream->e_o_s)
return OGGZ_ERR_EOS;
}
/* Check packet against mapping restrictions */
if (strict) {
if (op->bytes < 0) return OGGZ_ERR_BAD_BYTES;
if (b_o_s != stream->b_o_s) return OGGZ_ERR_BAD_B_O_S;
if (op->granulepos != -1 && op->granulepos < stream->granulepos)
return OGGZ_ERR_BAD_GRANULEPOS;
/* Allow packetno == -1 to indicate oggz should fill it in; otherwise:
* if op is the first packet in the stream, initialize the stream's
* packetno to the given one, otherwise check it for strictness */
if (op->packetno != -1) {
if (b_o_s) {
stream->packetno = op->packetno;
} else if (op->packetno <= stream->packetno) {
return OGGZ_ERR_BAD_PACKETNO;
}
}
}
/* OK -- Update stream's memory of packet details */
stream->b_o_s = 0; /* The stream is henceforth no longer at bos */
stream->e_o_s = e_o_s; /* We believe the eos value */
stream->granulepos = op->granulepos; /* and the granulepos */
/* If the user specified a packetno of -1, fill it in automatically;
* otherwise, use the user-specified value */
stream->packetno = (op->packetno != -1) ? op->packetno : stream->packetno+1;
/* Now set up the packet and add it to the queue */
if (guard == NULL) {
new_buf = oggz_malloc ((size_t)op->bytes);
memcpy (new_buf, op->packet, (size_t)op->bytes);
} else {
new_buf = op->packet;
}
packet = oggz_malloc (sizeof (oggz_writer_packet_t));
new_op = &packet->op;
new_op->packet = new_buf;
new_op->bytes = op->bytes;
new_op->b_o_s = op->b_o_s;
new_op->e_o_s = op->e_o_s;
new_op->granulepos = op->granulepos;
new_op->packetno = stream->packetno;
packet->stream = stream;
packet->flush = flush;
packet->guard = guard;
#ifdef DEBUG
printf ("oggz_write_feed: made packet bos %ld eos %ld (%ld bytes) FLUSH: %d\n",
new_op->b_o_s, new_op->e_o_s, new_op->bytes, packet->flush);
#endif
if (oggz_vector_insert_p (writer->packet_queue, packet) == NULL) {
oggz_free (packet);
if (!guard) oggz_free (new_buf);
return -1;
}
return 0;
}
/******** Page creation ********/
/*
*
____ __________________\___ ____
/ \ / Page ready / \ / \
| \ /=========\ /=========\ / |
Page | || Make || || Write || | Page
!ready V || packet || || page || V ready
| / \=========/ \=========/ \ |
\____/ \___/__________________/ \____/
\ Page !ready
*
*/
/*
* oggz_page_init (oggz)
*
* Initialises the next page of the current packet.
*
* If this returns 0, the page is not ready for writing.
*/
static long
oggz_page_init (OGGZ * oggz)
{
OggzWriter * writer = &oggz->x.writer;
ogg_stream_state * os;
ogg_page * og;
int ret;
if (oggz == NULL) return -1;
os = writer->current_stream;
og = &oggz->current_page;
#ifdef ALWAYS_FLUSH
ret = ogg_stream_flush (os, og);
#else
if (writer->flushing) {
#ifdef DEBUG
printf ("*** ATTEMPT FLUSH: ");
#endif
ret = ogg_stream_flush (os, og);
} else {
#ifdef DEBUG
printf ("*** ATTEMPT pageout: ");
#endif
ret = ogg_stream_pageout (os, og);
}
#endif
if (ret) {
writer->page_offset = 0;
}
#ifdef DEBUG
printf ("%s\n", ret ? "OK" : "NO");
#endif
return ret;
}
/*
* oggz_packet_init (oggz, buf, n)
*
* Initialises the next packet with data from buf, length n
*/
static long
oggz_packet_init (OGGZ * oggz, oggz_writer_packet_t * next_zpacket)
{
OggzWriter * writer = &oggz->x.writer;
oggz_stream_t * stream;
ogg_stream_state * os;
ogg_packet * op;
if (oggz == NULL) return -1L;
writer->current_zpacket = next_zpacket;
op = &next_zpacket->op;
#ifdef DEBUG
printf ("oggz_packet_init: %ld bytes\n", (long)op->bytes);
#endif
stream = next_zpacket->stream;
/* Mark this stream as having delivered a non b_o_s packet if so */
if (!op->b_o_s) stream->delivered_non_b_o_s = 1;
os = &stream->ogg_stream;
ogg_stream_packetin (os, op);
writer->flushing = (next_zpacket->flush & OGGZ_FLUSH_AFTER);
#ifdef DEBUG
printf ("oggz_packet_init: set flush to %d\n", writer->flushing);
#endif
writer->current_stream = os;
writer->packet_offset = 0;
return 0;
}
static long
oggz_page_copyout (OGGZ * oggz, unsigned char * buf, long n)
{
OggzWriter * writer = &oggz->x.writer;
long h, b;
ogg_page * og;
if (oggz == NULL) return -1L;
og = &oggz->current_page;
h = MIN (n, og->header_len - writer->page_offset);
if (h > 0) {
memcpy (buf, og->header + writer->page_offset, h);
writer->page_offset += h;
n -= h;
buf += h;
} else {
h = 0;
}
b = MIN (n, og->header_len + og->body_len - writer->page_offset);
if (b > 0) {
#ifdef DEBUG
{
unsigned char * c = &og->body[writer->page_offset - og->header_len];
printf ("oggz_page_copyout [%d] (@%ld): %c%c%c%c ...\n",
ogg_page_serialno (og), (long) ogg_page_granulepos (og),
c[0], c[1], c[2], c[3]);
}
#endif
memcpy (buf, og->body + (writer->page_offset - og->header_len), b);
writer->page_offset += b;
n -= b;
buf += b;
} else {
b = 0;
}
return h + b;
}
static long
oggz_page_writeout (OGGZ * oggz, long n)
{
OggzWriter * writer = &oggz->x.writer;
long h, b, nwritten;
ogg_page * og;
#ifdef OGGZ_WRITE_DIRECT
int fd;
#endif
if (oggz == NULL) return -1L;
og = &oggz->current_page;
#ifdef OGGZ_WRITE_DIRECT
fd = fileno (oggz->file);
#endif
h = MIN (n, og->header_len - writer->page_offset);
if (h > 0) {
#ifdef OGGZ_WRITE_DIRECT
nwritten = write (fd, og->header + writer->page_offset, h);
#else
nwritten = (long)oggz_io_write (oggz, og->header + writer->page_offset, h);
#endif
#ifdef DEBUG
if (nwritten < h) {
printf ("oggz_page_writeout: %ld < %ld\n", nwritten, h);
}
#endif
writer->page_offset += h;
n -= h;
} else {
h = 0;
}
b = MIN (n, og->header_len + og->body_len - writer->page_offset);
if (b > 0) {
#ifdef OGGZ_WRITE_DIRECT
nwritten = write (fd,
og->body + (writer->page_offset - og->header_len), b);
#else
nwritten = (long)oggz_io_write (oggz, og->body + (writer->page_offset - og->header_len), b);
#endif
#ifdef DEBUG
if (nwritten < b) {
printf ("oggz_page_writeout: %ld < %ld\n", nwritten, b);
}
#endif
writer->page_offset += b;
n -= b;
} else {
b = 0;
}
return h + b;
}
static oggz_writer_packet_t *
oggz_dequeue_packet (OGGZ * oggz)
{
OggzWriter * writer = &oggz->x.writer;
oggz_writer_packet_t * next_zpacket;
if (writer->next_zpacket != NULL) {
next_zpacket = writer->next_zpacket;
writer->next_zpacket = NULL;
} else {
next_zpacket = oggz_vector_pop (writer->packet_queue);
if (next_zpacket == NULL) {
if (writer->hungry) {
writer->hungry (oggz, 1, writer->hungry_user_data);
next_zpacket = oggz_vector_pop (writer->packet_queue);
}
}
}
return next_zpacket;
}
static long
oggz_writer_make_packet (OGGZ * oggz)
{
OggzWriter * writer = &oggz->x.writer;
oggz_writer_packet_t * zpacket, * next_zpacket;
int cb_ret = 0, ret = 0;
#ifdef DEBUG
printf ("make packet ...\n");
#endif
/* finished with current packet; unguard */
zpacket = writer->current_zpacket;
oggz_writer_packet_free (zpacket);
writer->current_zpacket = NULL;
/* if the user wants the hungry callback after every packet, give
* it to them, marking emptiness appropriately
*/
if (writer->hungry && !writer->hungry_only_when_empty) {
int empty = (oggz_vector_size (writer->packet_queue) == 0);
cb_ret = writer->hungry (oggz, empty, writer->hungry_user_data);
}
if (cb_ret == 0) {
/* dequeue and init the next packet */
if ((next_zpacket = oggz_dequeue_packet (oggz)) == NULL) {
/*writer->eos = 1;*/
ret = 0;
} else {
if ((writer->current_stream != NULL) &&
(next_zpacket->flush & OGGZ_FLUSH_BEFORE)) {
writer->flushing = 1;
#ifdef DEBUG
printf ("oggz_writer_make_packet: set flush to %d\n",
writer->flushing);
#endif
next_zpacket->flush &= OGGZ_FLUSH_AFTER;
writer->next_zpacket = next_zpacket;
} else {
oggz_packet_init (oggz, next_zpacket);
}
ret = 1;
}
} else {
ret = 0;
}
return ret;
}
long
oggz_write_output (OGGZ * oggz, unsigned char * buf, long n)
{
OggzWriter * writer = &oggz->x.writer;
long bytes, bytes_written = 1, remaining = n, nwritten = 0;
int active = 1;
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (!(oggz->flags & OGGZ_WRITE)) {
return OGGZ_ERR_INVALID;
}
if (writer->writing) return OGGZ_ERR_RECURSIVE_WRITE;
writer->writing = 1;
while (active && remaining > 0) {
bytes = MIN (remaining, 1024);
while (writer->state == OGGZ_MAKING_PACKETS) {
if (!oggz_writer_make_packet (oggz)) {
active = 0;
break;
}
if (oggz_page_init (oggz)) {
writer->state = OGGZ_WRITING_PAGES;
}
}
if (writer->state == OGGZ_WRITING_PAGES) {
bytes_written = oggz_page_copyout (oggz, buf, bytes);
if (bytes_written == -1) {
active = 0;
return OGGZ_ERR_SYSTEM; /* XXX: catch next */
} else if (bytes_written == 0) {
if (!oggz_page_init (oggz)) {
writer->state = OGGZ_MAKING_PACKETS;
}
}
buf += bytes_written;
remaining -= bytes_written;
nwritten += bytes_written;
}
}
writer->writing = 0;
return nwritten;
}
long
oggz_write (OGGZ * oggz, long n)
{
OggzWriter * writer = &oggz->x.writer;
long bytes, bytes_written = 1, remaining = n, nwritten = 0;
int active = 1;
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (!(oggz->flags & OGGZ_WRITE)) {
return OGGZ_ERR_INVALID;
}
if (writer->writing) return OGGZ_ERR_RECURSIVE_WRITE;
writer->writing = 1;
#ifdef DEBUG
printf ("oggz_write: IN\n");
#endif
while (active && remaining > 0) {
bytes = MIN (remaining, 1024);
#ifdef DEBUG
printf ("oggz_write: write loop (%ld , %ld remain) ...\n", bytes,
remaining);
#endif
while (writer->state == OGGZ_MAKING_PACKETS) {
if (!oggz_writer_make_packet (oggz)) {
active = 0;
#ifdef DEBUG
printf ("oggz_write: no packets\n");
#endif
break;
}
if (oggz_page_init (oggz)) {
writer->state = OGGZ_WRITING_PAGES;
}
}
if (writer->state == OGGZ_WRITING_PAGES) {
bytes_written = oggz_page_writeout (oggz, bytes);
if (bytes_written == -1) {
active = 0;
return OGGZ_ERR_SYSTEM; /* XXX: catch next */
} else if (bytes_written == 0) {
if (!oggz_page_init (oggz)) {
#ifdef DEBUG
printf ("oggz_write: bytes_written == 0, DONE\n");
#endif
writer->state = OGGZ_MAKING_PACKETS;
}
}
remaining -= bytes_written;
nwritten += bytes_written;
}
}
#ifdef DEBUG
printf ("oggz_write: OUT %ld\n", nwritten);
#endif
writer->writing = 0;
return nwritten;
}
long
oggz_write_get_next_page_size (OGGZ * oggz)
{
OggzWriter * writer = &oggz->x.writer;
ogg_page * og;
if (oggz == NULL) return OGGZ_ERR_BAD_OGGZ;
if (!(oggz->flags & OGGZ_WRITE)) {
return OGGZ_ERR_INVALID;
}
og = &oggz->current_page;
return (og->header_len + og->body_len - (long)writer->page_offset);
}
#else /* OGGZ_CONFIG_WRITE */
#include <ogg/ogg.h>
#include "oggz_private.h"
int
oggz_write_set_hungry_callback (OGGZ * oggz, OggzWriteHungry hungry,
int only_when_empty, void * user_data)
{
return OGGZ_ERR_DISABLED;
}
int
oggz_write_feed (OGGZ * oggz, ogg_packet * op, long serialno, int flush,
int * guard)
{
return OGGZ_ERR_DISABLED;
}
long
oggz_write_output (OGGZ * oggz, unsigned char * buf, long n)
{
return OGGZ_ERR_DISABLED;
}
long
oggz_write (OGGZ * oggz, long n)
{
return OGGZ_ERR_DISABLED;
}
long
oggz_write_get_next_page_size (OGGZ * oggz)
{
return OGGZ_ERR_DISABLED;
}
#endif