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:
@@ -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
|
||||
Reference in New Issue
Block a user