Bug 422538. Import liboggplay

This commit is contained in:
Xiph contributors, plus Chris Double 2008-07-29 23:46:06 -07:00
parent c38cc109bc
commit 813a91410f
35 changed files with 5973 additions and 0 deletions

View File

@ -0,0 +1,51 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Mozilla code.
#
# The Initial Developer of the Original Code is the Mozilla Corporation.
# Portions created by the Initial Developer are Copyright (C) 2007
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Chris Double <chris.double@double.co.nz>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = oggplay
DIRS = \
include \
src \
$(NULL)
include $(topsrcdir)/config/rules.mk

55
modules/liboggplay/README Normal file
View File

@ -0,0 +1,55 @@
OggPlay: a library for playing Ogg multimedia
Overview
--------
The current version of the plugin is still under development therefore
the setup requires manual installation of the plugin. For more information,
see also:
http://wiki.xiph.org/index.php/OggPlay
Dependencies
------------
For the core library (liboggplay), you need
* libogg, libvorbis, libspeex -- from http://www.xiph.org/
* liboggz and libfishsound -- from svn.annodex.net:
svn co http://svn.annodex.net/liboggz/trunk liboggz
svn co http://svn.annodex.net/libfishsound/trunk libfishsound
Optionally, for Kate stream support, you need
* libkate -- from http://libkate.googlecode.com/
See the README files associated with these libraries for installation
instructions.
To build src/tests/glut-player, you need:
* The core liboggplay dependencies (listed above)
* GLUT -- see http://www.opengl.org/resources/libraries/
To build src/tests/dump-all-streams, you need:
* The core liboggplay dependencies (listed above)
* libsndfile -- from http://www.mega-nerd.com/libsndfile/
To build src/tests/dump-first-frame, you need:
* The core liboggplay dependencies (listed above)
* Imlib2 -- from your distribution or from
http://sourceforge.net/project/showfiles.php?group_id=2&package_id=11130
On Debian, the required packages for all these additional libraries are:
g++ libogg-dev libvorbis-dev libspeex-dev libtheora-dev libsndfile1-dev
libimlib2-dev libglut-dev
Compile and Install liboggplay
------------------------------
./autogen.sh
./configure
make && make install

View File

@ -0,0 +1,9 @@
The source from this directory was copied from the liboggplay svn
source using the update.sh script. The only changes made were those
applied by update.sh and the addition/upate of Makefile.in files for
the Mozilla build system.
http://svn.annodex.net/liboggplay/trunk/
The svn revision number used was r3602. There is currently no official
source release of liboggplay, hence the reason an svn build was used.

View File

@ -0,0 +1,47 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Mozilla code.
#
# The Initial Developer of the Original Code is the Mozilla Corporation.
# Portions created by the Initial Developer are Copyright (C) 2007
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Chris Double <chris.double@double.co.nz>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = oggplay
DIRS = oggplay
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,57 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Mozilla code.
#
# The Initial Developer of the Original Code is the Mozilla Corporation.
# Portions created by the Initial Developer are Copyright (C) 2007
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Chris Double <chris.double@double.co.nz>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = oggplay
EXPORTS = \
config_win32.h \
oggplay.h \
oggplay_callback_info.h \
oggplay_enums.h \
oggplay_reader.h \
oggplay_tools.h \
oggplay_seek.h \
oggplay_query.h \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,75 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 0
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 0
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 0
/* Define if have liboggz */
#define HAVE_OGGZ
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 0
/* 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 0
/* 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 0
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 0
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 0
/* Name of package */
#define PACKAGE "liboggplay"
/* 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.0.1.svn"
/* Request Winsock 2.2 */
#define HAVE_WINSOCK2 1
/* Make sure inline is treated properly */
#define inline __inline
/* snprintf portability */
#define snprintf _snprintf
/* 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 */

View File

@ -0,0 +1,147 @@
/*
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.
*/
/*
* oggplay.h
*
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
*/
#ifndef __OGGPLAY_H__
#define __OGGPLAY_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <oggplay/oggplay_enums.h>
#include <oggplay/oggplay_reader.h>
typedef struct _OggPlay OggPlay;
typedef struct _OggPlayCallbackInfo OggPlayCallbackInfo;
typedef int (OggPlayDataCallback)(OggPlay *player, int num_records,
OggPlayCallbackInfo **records, void *user);
#include <oggplay/oggplay_query.h>
#include <oggplay/oggplay_callback_info.h>
#include <oggplay/oggplay_tools.h>
#include <oggplay/oggplay_seek.h>
/*
#include <oggplay/oggplay_retrieve.h>
#include <oggplay/oggplay_cmml.h>
*/
OggPlay *
oggplay_init(void);
OggPlayErrorCode
oggplay_set_reader(OggPlay *OS, OggPlayReader *OSR);
OggPlay *
oggplay_open_with_reader(OggPlayReader *reader);
OggPlay *
oggplay_new_with_reader(OggPlayReader *reader);
OggPlayErrorCode
oggplay_initialise(OggPlay *me, int block);
OggPlayErrorCode
oggplay_set_source(OggPlay *OS, char *source);
OggPlayErrorCode
oggplay_set_data_callback(OggPlay *me, OggPlayDataCallback callback,
void *user);
OggPlayErrorCode
oggplay_set_callback_num_frames(OggPlay *me, int stream, int frames);
OggPlayErrorCode
oggplay_set_offset(OggPlay *me, int track, ogg_int64_t offset);
OggPlayErrorCode
oggplay_get_video_y_size(OggPlay *me, int track, int *y_width, int *y_height);
OggPlayErrorCode
oggplay_get_video_uv_size(OggPlay *me, int track, int *uv_width, int *uv_height);
OggPlayErrorCode
oggplay_get_audio_channels(OggPlay *me, int track, int *channels);
OggPlayErrorCode
oggplay_get_audio_samplerate(OggPlay *me, int track, int *samplerate);
OggPlayErrorCode
oggplay_get_video_fps(OggPlay *me, int track, int* fps_denom, int* fps_num);
OggPlayErrorCode
oggplay_get_kate_category(OggPlay *me, int track, const char** category);
OggPlayErrorCode
oggplay_get_kate_language(OggPlay *me, int track, const char** language);
OggPlayErrorCode
oggplay_start_decoding(OggPlay *me);
OggPlayErrorCode
oggplay_step_decoding(OggPlay *me);
OggPlayErrorCode
oggplay_use_buffer(OggPlay *player, int size);
OggPlayCallbackInfo **
oggplay_buffer_retrieve_next(OggPlay *player);
OggPlayErrorCode
oggplay_buffer_release(OggPlay *player, OggPlayCallbackInfo **track_info);
void
oggplay_prepare_for_close(OggPlay *me);
OggPlayErrorCode
oggplay_close(OggPlay *player);
int
oggplay_get_available(OggPlay *player);
int
oggplay_get_duration(OggPlay * player);
int
oggplay_media_finished_retrieving(OggPlay * player);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,88 @@
/*
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.
*/
/*
* oggplay_callback_info.h
*
* Shane Stephens <shane.stephens@annodex.net>
*/
#ifndef __OGGPLAY_CALLBACK_INFO__
#define __OGGPLAY_CALLBACK_INFO__
typedef struct {
unsigned char * y;
unsigned char * u;
unsigned char * v;
} OggPlayVideoData;
typedef void * OggPlayAudioData;
typedef char OggPlayTextData;
struct _OggPlayDataHeader;
typedef struct _OggPlayDataHeader OggPlayDataHeader;
OggPlayDataType
oggplay_callback_info_get_type(OggPlayCallbackInfo *info);
int
oggplay_callback_info_get_available(OggPlayCallbackInfo *info);
int
oggplay_callback_info_get_required(OggPlayCallbackInfo *info);
OggPlayDataHeader **
oggplay_callback_info_get_headers(OggPlayCallbackInfo *info);
ogg_int64_t
oggplay_callback_info_get_record_size(OggPlayDataHeader *header);
OggPlayVideoData *
oggplay_callback_info_get_video_data(OggPlayDataHeader *header);
OggPlayAudioData *
oggplay_callback_info_get_audio_data(OggPlayDataHeader *header);
OggPlayTextData *
oggplay_callback_info_get_text_data(OggPlayDataHeader *header);
OggPlayStreamInfo
oggplay_callback_info_get_stream_info(OggPlayCallbackInfo *info);
void
oggplay_callback_info_lock_item(OggPlayDataHeader *header);
void
oggplay_callback_info_unlock_item(OggPlayDataHeader *header);
long
oggplay_callback_info_get_presentation_time(OggPlayDataHeader *header);
#endif

View File

@ -0,0 +1,86 @@
/*
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.
*/
/*
* oggplay_enums.h
*
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
*/
#ifndef __OGGPLAY_ENUMS_H__
#define __OGGPLAY_ENUMS_H__
typedef enum OggPlayErrorCode {
E_OGGPLAY_CONTINUE = 1,
E_OGGPLAY_OK = 0,
E_OGGPLAY_BAD_OGGPLAY = -1,
E_OGGPLAY_BAD_READER = -2,
E_OGGPLAY_BAD_INPUT = -3,
E_OGGPLAY_NO_SUCH_CHUNK = -4,
E_OGGPLAY_BAD_TRACK = -5,
E_OGGPLAY_TRACK_IS_SKELETON = -6,
E_OGGPLAY_OGGZ_UNHAPPY = -7,
E_OGGPLAY_END_OF_FILE = -8,
E_OGGPLAY_TRACK_IS_OVER = -9,
E_OGGPLAY_BAD_CALLBACK_INFO = -10,
E_OGGPLAY_WRONG_TRACK_TYPE = -11,
E_OGGPLAY_UNINITIALISED = -12,
E_OGGPLAY_CALLBACK_MODE = -13,
E_OGGPLAY_BUFFER_MODE = -14,
E_OGGPLAY_USER_INTERRUPT = -15,
E_OGGPLAY_SOCKET_ERROR = -16,
E_OGGPLAY_TIMEOUT = -17,
E_OGGPLAY_CANT_SEEK = -18,
E_OGGPLAY_NO_KATE_SUPPORT = -19,
E_OGGPLAY_NOTCHICKENPAYBACK = -777
} OggPlayErrorCode;
typedef enum OggPlayDataType {
OGGPLAY_INACTIVE = -1,
OGGPLAY_YUV_VIDEO = 0,
OGGPLAY_SHORTS_AUDIO = 1000,
OGGPLAY_FLOATS_AUDIO = 1001,
OGGPLAY_CMML = 2000,
OGGPLAY_KATE = 3000,
OGGPLAY_TYPE_UNKNOWN = 9000 /* higher to be able to add more types without changing value */
} OggPlayDataType;
typedef enum OggPlayStreamInfo {
OGGPLAY_STREAM_UNINITIALISED = 0,
OGGPLAY_STREAM_FIRST_DATA = 1,
OGGPLAY_STREAM_INITIALISED = 2,
OGGPLAY_STREAM_LAST_DATA = 3,
OGGPLAY_STREAM_JUST_SEEKED = 4
} OggPlayStreamInfo;
#endif

View File

@ -0,0 +1,59 @@
/*
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.
*/
/*
* oggplay_query.h
*
* Shane Stephens <shane.stephens@annodex.net>
*/
#ifndef __OGGPLAY_QUERY_H__
#define __OGGPLAY_QUERY_H__
#include <oggz/oggz.h>
int
oggplay_get_num_tracks (OggPlay * me);
OggzStreamContent
oggplay_get_track_type (OggPlay * me, int track_num);
const char *
oggplay_get_track_typename (OggPlay * me, int track_num);
OggPlayErrorCode
oggplay_set_track_active(OggPlay *me, int track_num);
OggPlayErrorCode
oggplay_set_track_inactive(OggPlay *me, int track_num);
#endif

View File

@ -0,0 +1,72 @@
/*
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.
*/
/*
* oggplay_reader.h
*
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
*/
#ifndef __OGGPLAY_READER_H__
#define __OGGPLAY_READER_H__
#include <stdlib.h>
#include <oggz/oggz.h>
#include <ogg/ogg.h>
struct _OggPlayReader;
typedef struct _OggPlayReader {
OggPlayErrorCode (*initialise)(struct _OggPlayReader * me, int block);
OggPlayErrorCode (*destroy)(struct _OggPlayReader * me);
OggPlayErrorCode (*seek)(struct _OggPlayReader *me, OGGZ *oggz,
ogg_int64_t milliseconds);
int (*available)(struct _OggPlayReader *me,
ogg_int64_t current_bytes,
ogg_int64_t current_time);
int (*duration)(struct _OggPlayReader *me);
int (*finished_retrieving)(struct _OggPlayReader *me);
/* low-level io functions for oggz */
size_t (*io_read)(void *user_handle, void *buf, size_t n);
int (*io_seek)(void *user_handle, long offset, int whence);
long (*io_tell)(void *user_handle);
} OggPlayReader;
OggPlayReader *
oggplay_file_reader_new(char *filename);
OggPlayReader *
oggplay_tcp_reader_new(char *uri, char *proxy, int proxy_port);
#endif

View File

@ -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.
*/
/*
* oggplay_enums.h
*
* Shane Stephens <shane.stephens@annodex.net>
*/
#ifndef __OGGPLAY_SEEK_H__
#define __OGGPLAY_SEEK_H__
OggPlayErrorCode
oggplay_seek(OggPlay *me, ogg_int64_t milliseconds);
#endif

View File

@ -0,0 +1,91 @@
/*
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.
*/
/*
* oggplay_tools.h
*
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
*/
#ifndef __OGGPLAY_TOOLS_H__
#define __OGGPLAY_TOOLS_H__
#include <ogg/ogg.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifdef WIN32
#include <time.h>
#else
#include <sys/time.h>
#include <time.h>
#endif
/* structure holds pointers to y, u, v channels */
typedef struct _OggPlayYUVChannels {
unsigned char * ptry;
unsigned char * ptru;
unsigned char * ptrv;
int y_width;
int y_height;
int uv_width;
int uv_height;
} OggPlayYUVChannels;
/* structure holds pointers to y, u, v channels */
typedef struct _OggPlayRGBChannels {
unsigned char * ptro;
int rgb_width;
int rgb_height;
} OggPlayRGBChannels;
void
oggplay_yuv2rgb(OggPlayYUVChannels* yuv, OggPlayRGBChannels * rgb);
void
oggplay_yuv2bgr(OggPlayYUVChannels* yuv, OggPlayRGBChannels * rgb);
ogg_int64_t
oggplay_sys_time_in_ms(void);
void
oggplay_millisleep(long ms);
#ifdef __cplusplus
}
#endif
#endif /*__OGGPLAY_TOOLS_H__*/

View File

@ -0,0 +1,47 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Mozilla code.
#
# The Initial Developer of the Original Code is the Mozilla Corporation.
# Portions created by the Initial Developer are Copyright (C) 2007
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Chris Double <chris.double@double.co.nz>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = oggplay
DIRS = liboggplay
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,69 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is Mozilla code.
#
# The Initial Developer of the Original Code is the Mozilla Corporation.
# Portions created by the Initial Developer are Copyright (C) 2007
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Chris Double <chris.double@double.co.nz>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = oggplay
LIBRARY_NAME = oggplay
FORCE_STATIC_LIB= 1
EXPORTS = \
oggplay_private.h \
oggplay_buffer.h \
oggplay_callback.h \
oggplay_data.h \
oggplay_private.h \
std_semaphore.h \
$(NULL)
CSRCS = \
oggplay.c \
oggplay_callback.c \
oggplay_query.c \
oggplay_data.c \
oggplay_callback_info.c \
oggplay_buffer.c \
oggplay_seek.c \
oggplay_yuv2rgb.c \
oggplay_tools.c \
$(NULL)
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,87 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define if have libfishsound */
#define HAVE_FISHSOUND
/* Define if we have GLUT. */
/* #undef HAVE_GLUT */
/* Define if have Imlib2 */
/* #undef HAVE_IMLIB2 */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define if have libkate */
/* #undef HAVE_KATE */
/* Define if have libsndfile */
/* #undef HAVE_LIBSNDFILE1 */
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define if have liboggz */
#define HAVE_OGGZ
/* 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 1 if your C compiler doesn't accept -c and -o together. */
/* #undef NO_MINUS_C_MINUS_O */
/* Name of package */
#define PACKAGE "liboggplay"
/* 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.0.1.svn"
/* 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 */
/* use MMX SSE2 compiler intrinsics */
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */

View File

@ -0,0 +1,661 @@
/*
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.
*/
/*
* oggplay.c
*
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
*/
#include "oggplay_private.h"
#include "oggplay_buffer.h"
#include <string.h>
#include <stdlib.h>
#define OGGZ_READ_CHUNK_SIZE 8192
OggPlay *
oggplay_new_with_reader(OggPlayReader *reader) {
OggPlay * me = (OggPlay *)malloc(sizeof(OggPlay));
me->reader = reader;
me->decode_data = NULL;
me->callback_info = NULL;
me->num_tracks = 0;
me->all_tracks_initialised = 0;
me->callback_period = 0;
me->callback = NULL;
me->target = 0L;
me->active_tracks = 0;
me->buffer = NULL;
me->shutdown = 0;
me->trash = NULL;
me->oggz = NULL;
me->pt_update_valid = 1;
return me;
}
OggPlayErrorCode
oggplay_initialise(OggPlay *me, int block) {
OggPlayErrorCode return_val;
int i;
return_val = me->reader->initialise(me->reader, block);
if (return_val != E_OGGPLAY_OK) {
return return_val;
}
/*
* this is the cut-off time value below which packets will be ignored. Initialise it to 0 here.
* We'll reinitialise it when/if we encounter a skeleton header
*/
me->presentation_time = 0;
/*
* start to retrieve data, until we get all of the track info. We need
* to do this now so that the user can query us for this info before entering
* the main loop
*/
me->oggz = oggz_new(OGGZ_READ | OGGZ_AUTO);
oggz_io_set_read(me->oggz, me->reader->io_read, me->reader);
oggz_io_set_seek(me->oggz, me->reader->io_seek, me->reader);
oggz_io_set_tell(me->oggz, me->reader->io_tell, me->reader);
oggz_set_read_callback(me->oggz, -1, oggplay_callback_predetected, me);
while (1) {
if (oggz_read(me->oggz, OGGZ_READ_CHUNK_SIZE) < 0) {
return E_OGGPLAY_BAD_INPUT;
}
if (me->all_tracks_initialised) {
break;
}
}
/*
* set all the tracks to inactive
*/
for (i = 0; i < me->num_tracks; i++) {
me->decode_data[i]->active = 0;
}
/*
* if the buffer was set up before initialisation, prepare it now
*/
if (me->buffer != NULL) {
oggplay_buffer_prepare(me);
}
return E_OGGPLAY_OK;
}
OggPlay *
oggplay_open_with_reader(OggPlayReader *reader) {
OggPlay *me = oggplay_new_with_reader(reader);
int r = E_OGGPLAY_TIMEOUT;
while (r == E_OGGPLAY_TIMEOUT) {
r = oggplay_initialise(me, 0);
}
if (r != E_OGGPLAY_OK) {
free(me);
return NULL;
}
return me;
}
/*
* API function to prevent bad input, and to prevent data callbacks being registered
* in buffer mode
*/
OggPlayErrorCode
oggplay_set_data_callback(OggPlay *me, OggPlayDataCallback callback,
void *user) {
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (me->buffer != NULL) {
return E_OGGPLAY_BUFFER_MODE;
}
oggplay_set_data_callback_force(me, callback, user);
return E_OGGPLAY_OK;
}
/*
* internal function that doesn't perform error checking. Used so the buffer
* can register a callback!
*/
void
oggplay_set_data_callback_force(OggPlay *me, OggPlayDataCallback callback,
void *user) {
me->callback = callback;
me->callback_user_ptr = user;
}
OggPlayErrorCode
oggplay_set_callback_num_frames(OggPlay *me, int track, int frames) {
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (track < 0 || track >= me->num_tracks) {
return E_OGGPLAY_BAD_TRACK;
}
me->callback_period = me->decode_data[track]->granuleperiod * frames;
me->target = me->presentation_time + me->callback_period - 1;
return E_OGGPLAY_OK;
}
OggPlayErrorCode
oggplay_set_offset(OggPlay *me, int track, ogg_int64_t offset) {
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (track <= 0 || track > me->num_tracks) {
return E_OGGPLAY_BAD_TRACK;
}
me->decode_data[track]->offset = (offset << 32);
return E_OGGPLAY_OK;
}
OggPlayErrorCode
oggplay_get_video_fps(OggPlay *me, int track, int* fps_denom, int* fps_num) {
OggPlayTheoraDecode *decode;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (track < 0 || track >= me->num_tracks) {
return E_OGGPLAY_BAD_TRACK;
}
if (me->decode_data[track]->decoded_type != OGGPLAY_YUV_VIDEO) {
return E_OGGPLAY_WRONG_TRACK_TYPE;
}
decode = (OggPlayTheoraDecode *)(me->decode_data[track]);
if ((decode->video_info.fps_denominator == 0)
|| (decode->video_info.fps_numerator == 0)) {
return E_OGGPLAY_UNINITIALISED;
}
(*fps_denom) = decode->video_info.fps_denominator;
(*fps_num) = decode->video_info.fps_numerator;
return E_OGGPLAY_OK;
}
OggPlayErrorCode
oggplay_get_video_y_size(OggPlay *me, int track, int *y_width, int *y_height) {
OggPlayTheoraDecode *decode;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (track < 0 || track >= me->num_tracks) {
return E_OGGPLAY_BAD_TRACK;
}
if (me->decode_data[track]->decoded_type != OGGPLAY_YUV_VIDEO) {
return E_OGGPLAY_WRONG_TRACK_TYPE;
}
decode = (OggPlayTheoraDecode *)(me->decode_data[track]);
if (decode->y_width == 0) {
return E_OGGPLAY_UNINITIALISED;
}
(*y_width) = decode->y_width;
(*y_height) = decode->y_height;
return E_OGGPLAY_OK;
}
OggPlayErrorCode
oggplay_get_video_uv_size(OggPlay *me, int track, int *uv_width, int *uv_height)
{
OggPlayTheoraDecode *decode;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (track < 0 || track >= me->num_tracks) {
return E_OGGPLAY_BAD_TRACK;
}
if (me->decode_data[track]->decoded_type != OGGPLAY_YUV_VIDEO) {
return E_OGGPLAY_WRONG_TRACK_TYPE;
}
decode = (OggPlayTheoraDecode *)(me->decode_data[track]);
if (decode->y_width == 0) {
return E_OGGPLAY_UNINITIALISED;
}
(*uv_width) = decode->uv_width;
(*uv_height) = decode->uv_height;
return E_OGGPLAY_OK;
}
int
oggplay_get_audio_channels(OggPlay *me, int track, int* channels) {
OggPlayAudioDecode *decode;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (track < 0 || track >= me->num_tracks) {
return E_OGGPLAY_BAD_TRACK;
}
if (me->decode_data[track]->decoded_type != OGGPLAY_FLOATS_AUDIO) {
return E_OGGPLAY_WRONG_TRACK_TYPE;
}
decode = (OggPlayAudioDecode *)(me->decode_data[track]);
if (decode->sound_info.channels == 0) {
return E_OGGPLAY_UNINITIALISED;
}
(*channels) = decode->sound_info.channels;
return E_OGGPLAY_OK;
}
int
oggplay_get_audio_samplerate(OggPlay *me, int track, int* rate) {
OggPlayAudioDecode * decode;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (track < 0 || track >= me->num_tracks) {
return E_OGGPLAY_BAD_TRACK;
}
if (me->decode_data[track]->decoded_type != OGGPLAY_FLOATS_AUDIO) {
return E_OGGPLAY_WRONG_TRACK_TYPE;
}
decode = (OggPlayAudioDecode *)(me->decode_data[track]);
if (decode->sound_info.channels == 0) {
return E_OGGPLAY_UNINITIALISED;
}
(*rate) = decode->sound_info.samplerate;
return E_OGGPLAY_OK;
}
int
oggplay_get_kate_category(OggPlay *me, int track, const char** category) {
#ifdef HAVE_KATE
OggPlayKateDecode * decode;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (track < 0 || track >= me->num_tracks) {
return E_OGGPLAY_BAD_TRACK;
}
if (me->decode_data[track]->decoded_type != OGGPLAY_KATE) {
return E_OGGPLAY_WRONG_TRACK_TYPE;
}
decode = (OggPlayKateDecode *)(me->decode_data[track]);
(*category) = decode->k.ki->category;
return E_OGGPLAY_OK;
#else
return E_OGGPLAY_NO_KATE_SUPPORT;
#endif
}
int
oggplay_get_kate_language(OggPlay *me, int track, const char** language) {
OggPlayKateDecode * decode;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (track < 0 || track >= me->num_tracks) {
return E_OGGPLAY_BAD_TRACK;
}
if (me->decode_data[track]->decoded_type != OGGPLAY_KATE) {
return E_OGGPLAY_WRONG_TRACK_TYPE;
}
decode = (OggPlayKateDecode *)(me->decode_data[track]);
#ifdef HAVE_KATE
(*language) = decode->k.ki->language;
return E_OGGPLAY_OK;
#else
return E_OGGPLAY_NO_KATE_SUPPORT;
#endif
}
#define MAX_CHUNK_COUNT 10
OggPlayErrorCode
oggplay_step_decoding(OggPlay *me) {
OggPlayCallbackInfo ** info;
int num_records;
int r;
int i;
int need_data = 0;
int chunk_count = 0;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
/*
* clean up any trash pointers. As soon as the current buffer has a
* frame taken out, we know the old buffer will no longer be used.
*/
if (me->trash != NULL && me->buffer->last_emptied > -1) {
oggplay_take_out_trash(me, me->trash);
me->trash = NULL;
}
read_more_data:
while (1) {
/*
* if there are no active tracks, we might need to return some data
* left over at the end of a once-active track that has had all of its
* data processed. Look through the tracks to find these overhangs
*/
int r;
if (me->active_tracks == 0) {
int remaining = 0;
for (i = 0; i < me->num_tracks; i++) {
if (me->decode_data[i]->current_loc +
me->decode_data[i]->granuleperiod >= me->target + me->decode_data[i]->offset) {
remaining++;
}
}
if (remaining == 0) {
return E_OGGPLAY_OK;
}
}
/*
* if any of the tracks have not yet met the target (modified by that
* track's offset), then retrieve more data
*/
need_data = 0;
for (i = 0; i < me->num_tracks; i++) {
if (me->decode_data[i]->active == 0)
continue;
if (me->decode_data[i]->content_type == OGGZ_CONTENT_CMML)
continue;
#ifdef HAVE_KATE
if (me->decode_data[i]->content_type == OGGZ_CONTENT_KATE)
continue;
#endif
if
(
me->decode_data[i]->current_loc
<
me->target + me->decode_data[i]->offset
)
{
need_data = 1;
break;
}
}
if (!need_data) {
break;
}
/*
* get a chunk of data. If we're at the end of the file, then we must
* have some final frames to render (?). E_OGGPLAY_END_OF_FILE is
* only returned if there is *no* more data.
*/
if (chunk_count > MAX_CHUNK_COUNT) {
return E_OGGPLAY_TIMEOUT;
}
chunk_count += 1;
r = oggz_read(me->oggz, OGGZ_READ_CHUNK_SIZE);
/* end-of-file */
if (r == 0) {
num_records = oggplay_callback_info_prepare(me, &info);
/*
* set all of the tracks to active
*/
for (i = 0; i < me->num_tracks; i++) {
me->decode_data[i]->active = 0;
me->active_tracks = 0;
}
if (info != NULL) {
me->callback (me, num_records, info, me->callback_user_ptr);
oggplay_callback_info_destroy(me, info);
}
/*
* ensure all tracks have their final data packet set to end_of_stream
*/
if (me->buffer != NULL) {
oggplay_buffer_set_last_data(me, me->buffer);
}
return E_OGGPLAY_OK;
}
}
/*
* prepare a callback
*/
num_records = oggplay_callback_info_prepare (me, &info);
if (info != NULL) {
r = me->callback (me, num_records, info, me->callback_user_ptr);
oggplay_callback_info_destroy (me, info);
} else {
r = 0;
}
/*
* clean the data lists
*/
for (i = 0; i < me->num_tracks; i++) {
oggplay_data_clean_list (me->decode_data[i]);
}
if (info == NULL) {
goto read_more_data;
}
me->target += me->callback_period;
if (me->shutdown) {
return E_OGGPLAY_OK;
}
if (r == -1) {
return E_OGGPLAY_USER_INTERRUPT;
}
return E_OGGPLAY_CONTINUE;
}
OggPlayErrorCode
oggplay_start_decoding(OggPlay *me) {
int r;
while (1) {
if ((r = oggplay_step_decoding(me)) != E_OGGPLAY_CONTINUE)
return (OggPlayErrorCode)r;
}
}
OggPlayErrorCode
oggplay_close(OggPlay *me) {
int i;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (me->reader != NULL) {
me->reader->destroy(me->reader);
}
for (i = 0; i < me->num_tracks; i++) {
oggplay_callback_shutdown(me->decode_data[i]);
}
oggz_close(me->oggz);
if (me->buffer != NULL) {
oggplay_buffer_shutdown(me, me->buffer);
}
free(me);
return E_OGGPLAY_OK;
}
/*
* this function is required to release the frame_sem in the buffer, if
* the buffer is being used.
*/
void
oggplay_prepare_for_close(OggPlay *me) {
me->shutdown = 1;
if (me->buffer != NULL) {
SEM_SIGNAL(((OggPlayBuffer *)(me->buffer))->frame_sem);
}
}
int
oggplay_get_available(OggPlay *me) {
ogg_int64_t current_time, current_byte;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
current_time = oggz_tell_units(me->oggz);
current_byte = (ogg_int64_t)oggz_tell(me->oggz);
return me->reader->available(me->reader, current_byte, current_time);
}
int
oggplay_get_duration(OggPlay *me) {
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
return me->reader->duration(me->reader);
}
int
oggplay_media_finished_retrieving(OggPlay *me) {
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (me->reader == NULL) {
return E_OGGPLAY_BAD_READER;
}
return me->reader->finished_retrieving(me->reader);
}

View File

@ -0,0 +1,347 @@
/*
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.
*/
/*
* oggplay_buffer.c
*
* Shane Stephens <shane.stephens@annodex.net>
*/
#include "oggplay_private.h"
#include <stdlib.h>
#include <string.h>
#define OGGPLAY_DEFAULT_BUFFER_SIZE 20
#define WRAP_INC(c, s) ((c + 1) % s)
/*
* Call this function to initialise the oggplay lock-free buffer. Do not use
* the buffer and the callback together!
*/
OggPlayBuffer *
oggplay_buffer_new_buffer(int size) {
OggPlayBuffer *buffer = 0;
if (size < 0) {
size = OGGPLAY_DEFAULT_BUFFER_SIZE;
}
buffer = (OggPlayBuffer*)malloc(sizeof (OggPlayBuffer));
buffer->buffer_list = malloc(sizeof (void *) * size);
memset(buffer->buffer_list, 0, sizeof (void *) * size);
buffer->buffer_mirror = malloc(sizeof (void *) * size);
memset(buffer->buffer_mirror, 0, sizeof (void *) * size);
buffer->buffer_size = size;
buffer->last_filled = -1;
buffer->last_emptied = -1;
SEM_CREATE(buffer->frame_sem, size);
return buffer;
}
void
oggplay_buffer_shutdown(OggPlay *me, volatile OggPlayBuffer *vbuffer) {
int i;
int j;
OggPlayBuffer *buffer = (OggPlayBuffer *)vbuffer;
for (i = 0; i < buffer->buffer_size; i++) {
if (buffer->buffer_mirror[i] != NULL) {
OggPlayCallbackInfo *ti = (OggPlayCallbackInfo *)buffer->buffer_mirror[i];
for (j = 0; j < me->num_tracks; j++) {
free((ti + j)->records);
}
free(ti);
}
}
free(buffer->buffer_list);
free(buffer->buffer_mirror);
SEM_CLOSE(buffer->frame_sem);
free(buffer);
}
int
oggplay_buffer_is_full(volatile OggPlayBuffer *buffer) {
return
(
(buffer == NULL) || (
buffer->buffer_list[WRAP_INC(buffer->last_filled, buffer->buffer_size)]
!=
NULL
)
);
}
void
oggplay_buffer_set_last_data(OggPlay *me, volatile OggPlayBuffer *buffer)
{
int i;
OggPlayCallbackInfo *p;
/*
* we're at last data before we've even started!
*/
if (buffer->last_filled == -1) {
return;
}
p = (OggPlayCallbackInfo *)buffer->buffer_list[buffer->last_filled];
for (i = 0; i < me->num_tracks; i++) {
p->stream_info = OGGPLAY_STREAM_LAST_DATA;
p++;
}
}
int
oggplay_buffer_callback(OggPlay *me, int tracks,
OggPlayCallbackInfo **track_info, void *user) {
int i;
int j;
int k;
OggPlayDataHeader ** headers;
OggPlayBuffer * buffer;
OggPlayCallbackInfo * ptr = track_info[0];
int required;
buffer = (OggPlayBuffer *)me->buffer;
if (buffer == NULL) {
return -1;
}
SEM_WAIT(buffer->frame_sem);
if (me->shutdown) {
return -1;
}
/*
* lock the item going into the buffer so that it doesn't get cleaned up
*/
for (i = 0; i < tracks; i++) {
headers = oggplay_callback_info_get_headers(track_info[i]);
required = oggplay_callback_info_get_required(track_info[i]);
for (j = 0; j < required; j++) {
oggplay_callback_info_lock_item(headers[j]);
}
}
/*
* check for and clean up empties
*/
for (k = 0; k < buffer->buffer_size; k++) {
if
(
(buffer->buffer_list[k] == NULL)
&&
(buffer->buffer_mirror[k] != NULL)
) {
OggPlayCallbackInfo *ti = (OggPlayCallbackInfo *)buffer->buffer_mirror[k];
for (i = 0; i < tracks; i++) {
headers = oggplay_callback_info_get_headers(ti + i);
required = oggplay_callback_info_get_required(ti + i);
for (j = 0; j < required; j++) {
oggplay_callback_info_unlock_item(headers[j]);
}
/* free these here, because we couldn't free them in
* oggplay_callback_info_destroy for buffer mode
*/
free((ti + i)->records);
}
free(ti);
buffer->buffer_mirror[k] = NULL;
}
}
/*
* replace the decode_data buffer for the next callback
*/
me->callback_info = (OggPlayCallbackInfo *)calloc(me->num_tracks, sizeof (OggPlayCallbackInfo));
/*
* fill both mirror and list, mirror first to avoid getting inconsistencies
*/
buffer->last_filled = WRAP_INC(buffer->last_filled, buffer->buffer_size);
/*
* set the buffer pointer in the first record
*/
ptr->buffer = buffer;
buffer->buffer_mirror[buffer->last_filled] = ptr;
buffer->buffer_list[buffer->last_filled] = ptr;
if (oggplay_buffer_is_full(buffer)) {
/*
* user interrupt when we fill the buffer rather than when we have a
* decoded frame and the buffer is already full
*/
return -1;
}
return 0;
}
OggPlayCallbackInfo **
oggplay_buffer_retrieve_next(OggPlay *me) {
OggPlayBuffer * buffer;
int next_loc;
OggPlayCallbackInfo * next_item;
OggPlayCallbackInfo ** return_val;
int i;
if (me == NULL) {
return NULL;
}
buffer = (OggPlayBuffer *)me->buffer;
if (buffer == NULL) {
return NULL;
}
next_loc = WRAP_INC(buffer->last_emptied, buffer->buffer_size);
if (buffer->buffer_list[next_loc] == NULL) {
return NULL;
}
next_item = (OggPlayCallbackInfo*)buffer->buffer_list[next_loc];
buffer->last_emptied = next_loc;
return_val = malloc(sizeof (OggPlayCallbackInfo *) * me->num_tracks);
for (i = 0; i < me->num_tracks; i++) {
return_val[i] = next_item + i;
}
return return_val;
}
OggPlayErrorCode
oggplay_buffer_release(OggPlay *me, OggPlayCallbackInfo **track_info) {
OggPlayBuffer *buffer;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (track_info == NULL) {
return E_OGGPLAY_OK;
}
buffer = (OggPlayBuffer *)track_info[0]->buffer;
if (buffer == NULL) {
return E_OGGPLAY_CALLBACK_MODE;
}
if (buffer->buffer_list[buffer->last_emptied] == NULL) {
return E_OGGPLAY_UNINITIALISED;
}
free(track_info);
buffer->buffer_list[buffer->last_emptied] = NULL;
SEM_SIGNAL(buffer->frame_sem);
return E_OGGPLAY_OK;
}
OggPlayErrorCode
oggplay_use_buffer(OggPlay *me, int size) {
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (me->callback != NULL) {
return E_OGGPLAY_CALLBACK_MODE;
}
if (me->buffer != NULL) {
/*
* we should check sizes, and maybe clear and reallocate the buffer?
*/
return E_OGGPLAY_OK;
}
me->buffer = oggplay_buffer_new_buffer(size);
/*
* if oggplay is already initialised, then prepare the buffer now
*/
if (me->all_tracks_initialised) {
oggplay_buffer_prepare(me);
}
return E_OGGPLAY_OK;
}
void
oggplay_buffer_prepare(OggPlay *me) {
int i;
oggplay_set_data_callback_force(me, &oggplay_buffer_callback, NULL);
for (i = 0; i < me->num_tracks; i++) {
if (oggplay_get_track_type(me, i) == OGGZ_CONTENT_THEORA) {
oggplay_set_callback_num_frames(me, i, 1);
break;
}
}
}

View File

@ -0,0 +1,57 @@
/*
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.
*/
/*
* oggplay_buffer.h
*
* Shane Stephens <shane.stephens@annodex.net>
*/
#ifndef __OGGPLAY_BUFFER_H__
#define __OGGPLAY_BUFFER_H__
OggPlayBuffer *
oggplay_buffer_new_buffer(int size);
int
oggplay_buffer_is_full(volatile OggPlayBuffer *buffer);
void
oggplay_buffer_shutdown(OggPlay *me, volatile OggPlayBuffer *buffer);
void
oggplay_buffer_prepare(OggPlay *me);
void
oggplay_buffer_set_last_data(OggPlay *me, volatile OggPlayBuffer *buffer);
#endif

View File

@ -0,0 +1,591 @@
/*
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.
*/
/*
* oggplay_callback.c
*
* Shane Stephens <shane.stephens@annodex.net>
*/
#include "oggplay_private.h"
#define TIME_THEORA_DECODE 0
#include <stdlib.h>
#if TIME_THEORA_DECODE
#include <sys/time.h>
#endif
#include <time.h>
#include <string.h>
void
oggplay_init_theora(void *user_data) {
OggPlayTheoraDecode * decoder = (OggPlayTheoraDecode *)user_data;
theora_info_init(&(decoder->video_info));
theora_comment_init(&(decoder->video_comment));
decoder->remaining_header_packets = 3;
decoder->granulepos_seen = 0;
decoder->frame_delta = 0;
decoder->y_width = 0;
decoder->decoder.decoded_type = OGGPLAY_YUV_VIDEO;
}
void
oggplay_shutdown_theora(void *user_data) {
OggPlayTheoraDecode * decoder = (OggPlayTheoraDecode *)user_data;
if (decoder->remaining_header_packets == 0) {
theora_clear(&(decoder->video_handle));
}
theora_info_clear(&(decoder->video_info));
theora_comment_clear(&(decoder->video_comment));
}
int
oggplay_callback_theora (OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data) {
OggPlayTheoraDecode * decoder = (OggPlayTheoraDecode *)user_data;
OggPlayDecode * common = &(decoder->decoder);
ogg_int64_t granulepos = oggz_tell_granulepos(oggz);
yuv_buffer buffer;
int granuleshift;
long frame;
#if TIME_THEORA_DECODE
struct timeval tv;
struct timeval tv2;
int musec;
#endif
/*
* always decode headers
*/
if (theora_packet_isheader(op)) {
theora_decode_header(&(decoder->video_info), &(decoder->video_comment), op);
/*
* initialise width/stride/height data (this is common to all frames).
* Use the buffer stride for the width to avoid passing negative stride
* issues on to the user.
*/
decoder->y_width = decoder->y_stride = decoder->video_info.frame_width;
decoder->y_height = decoder->video_info.frame_height;
decoder->uv_width = decoder->uv_stride = decoder->video_info.frame_width / 2;
decoder->uv_height = decoder->video_info.frame_height / 2;
if (--(decoder->remaining_header_packets) == 0) {
theora_decode_init(&(decoder->video_handle), &(decoder->video_info));
}
return 0;
}
if (!decoder->decoder.active) {
/*
* don't decode other packets
*/
return 0;
}
/*
* if we get to here then we've passed all the header packets
*/
if (common->current_loc == -1)
common->current_loc = 0;
/*
* Decode the frame
*/
#if TIME_THEORA_DECODE
gettimeofday(&tv, NULL);
#endif
theora_decode_packetin(&(decoder->video_handle), op);
theora_decode_YUVout(&(decoder->video_handle), &buffer);
#if TIME_THEORA_DECODE
gettimeofday(&tv2, NULL);
musec = tv2.tv_usec - tv.tv_usec;
if (tv2.tv_sec > tv.tv_sec)
musec += (tv2.tv_sec - tv.tv_sec) * 1000000;
printf("decode took %dus\n", musec);
#endif
if (granulepos != -1) {
granuleshift = oggz_get_granuleshift(oggz, serialno);
frame = (granulepos >> granuleshift);
frame += (granulepos & ((1 << granuleshift) - 1));
common->current_loc = frame * common->granuleperiod;
} else {
common->current_loc = -1;
}
if
(
(common->current_loc == -1)
||
(common->current_loc >= common->player->presentation_time)
)
{
/*
* store the frame,
* use the buffer stride for the width to avoid passing negative stride
* issues on to the user.
* */
oggplay_data_handle_theora_frame(decoder, &buffer);
}
if (op->e_o_s) {
common->active = 0;
common->player->active_tracks--;
}
return 0;
}
void
oggplay_init_cmml (void * user_data) {
OggPlayCmmlDecode * decoder = (OggPlayCmmlDecode *)user_data;
decoder->decoder.decoded_type = OGGPLAY_CMML;
decoder->granuleshift = 32; /* default */
}
int
oggplay_callback_cmml (OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data) {
OggPlayCmmlDecode * decoder = (OggPlayCmmlDecode *)user_data;
OggPlayDecode * common = &(decoder->decoder);
ogg_int64_t granulepos = oggz_tell_granulepos (oggz);
if (granulepos == 0) {
if (memcmp(op->packet, "CMML\0\0\0\0", 8) == 0) {
decoder->granuleshift = op->packet[28];
}
} else {
if (decoder->granuleshift > 0) {
granulepos >>= decoder->granuleshift;
}
common->current_loc = granulepos * common->granuleperiod;
oggplay_data_handle_cmml_data (&(decoder->decoder), op->packet, op->bytes);
}
return 0;
}
void
oggplay_init_skel (void * user_data) {
OggPlaySkeletonDecode * decoder = (OggPlaySkeletonDecode *)user_data;
decoder->presentation_time = 0;
decoder->base_time = 0;
}
static inline unsigned long extract_int32(unsigned char *data) {
return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24);
}
static inline ogg_int64_t extract_int64(unsigned char *data) {
return ((ogg_int64_t)(extract_int32(data))) |
(((ogg_int64_t)(extract_int32(data + 4))) << 32);
}
int
oggplay_callback_skel (OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data) {
OggPlaySkeletonDecode * decoder = (OggPlaySkeletonDecode *)user_data;
if (strncmp((char *)op->packet, "fishead", 7) == 0) {
ogg_int64_t pt_num, pt_den, bt_num, bt_den;
pt_num = extract_int64(op->packet + 12);
pt_den = extract_int64(op->packet + 20);
bt_num = extract_int64(op->packet + 28);
bt_den = extract_int64(op->packet + 36);
decoder->presentation_time = (pt_num << 32) * 1000 / pt_den;
decoder->base_time = (bt_num << 32) / bt_den;
/* initialise the presentation times in the player to the values recorded in the skeleton */
decoder->decoder.player->presentation_time = decoder->presentation_time;
} else {
int i;
long preroll = extract_int32(op->packet + 44);
long serialno = extract_int32(op->packet + 12);
//ogg_int64_t start_granule = extract_int64(op->packet + 36);
for (i = 1; i < decoder->decoder.player->num_tracks; i++) {
if (decoder->decoder.player->decode_data[i]->serialno == serialno) {
decoder->decoder.player->decode_data[i]->preroll = preroll;
break;
}
}
}
return 0;
}
int
oggplay_fish_sound_callback_floats(FishSound * fsound, float ** pcm,
long frames, void *user_data) {
OggPlayAudioDecode *decoder = (OggPlayAudioDecode *)user_data;
OggPlayDecode *common = &(decoder->decoder);
/*
* calculate the current location here so that it's only updated when
* audio data is actually available for processing
*/
if (common->last_granulepos > 0) {
common->current_loc = common->last_granulepos * common->granuleperiod;
} else {
common->current_loc = -1;
}
if
(
(common->current_loc == -1)
||
(common->current_loc >= common->player->presentation_time)
)
{
/*
* store the frame
*/
oggplay_data_handle_audio_data(&(decoder->decoder), (short *)pcm, frames,
sizeof(float));
}
return FISH_SOUND_CONTINUE;
}
void
oggplay_init_audio (void * user_data) {
OggPlayAudioDecode * decoder = (OggPlayAudioDecode *)user_data;
decoder->sound_handle = fish_sound_new(FISH_SOUND_DECODE,
&(decoder->sound_info));
decoder->sound_info.channels = 0;
fish_sound_set_interleave(decoder->sound_handle, 1);
fish_sound_set_decoded_float_ilv(decoder->sound_handle,
oggplay_fish_sound_callback_floats,
(void *)decoder);
decoder->decoder.decoded_type = OGGPLAY_FLOATS_AUDIO;
}
void
oggplay_shutdown_audio(void *user_data) {
OggPlayAudioDecode * decoder = (OggPlayAudioDecode *)user_data;
fish_sound_delete(decoder->sound_handle);
}
int
oggplay_callback_audio (OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data) {
OggPlayAudioDecode * decoder = (OggPlayAudioDecode *)user_data;
OggPlayDecode * common = &(decoder->decoder);
ogg_int64_t granulepos = oggz_tell_granulepos(oggz);
if (granulepos > 0 && (!decoder->decoder.active)) {
return 0;
}
common->last_granulepos = granulepos;
fish_sound_prepare_truncation (decoder->sound_handle, op->granulepos,
op->e_o_s);
fish_sound_decode (decoder->sound_handle, op->packet, op->bytes);
if (decoder->sound_info.channels == 0) {
fish_sound_command(decoder->sound_handle, FISH_SOUND_GET_INFO,
&(decoder->sound_info), sizeof(FishSoundInfo));
}
if (op->e_o_s) {
common->active = 0;
common->player->active_tracks--;
}
return 0;
}
void
oggplay_init_kate(void *user_data) {
#ifdef HAVE_KATE
OggPlayKateDecode * decoder = (OggPlayKateDecode *)user_data;
kate_high_decode_init(&(decoder->k));
decoder->decoder.decoded_type = OGGPLAY_KATE;
#endif
}
void
oggplay_shutdown_kate(void *user_data) {
#ifdef HAVE_KATE
OggPlayKateDecode * decoder = (OggPlayKateDecode *)user_data;
kate_high_decode_clear(&(decoder->k));
#endif
}
int
oggplay_callback_kate (OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data) {
#ifdef HAVE_KATE
OggPlayKateDecode * decoder = (OggPlayKateDecode *)user_data;
OggPlayDecode * common = &(decoder->decoder);
ogg_int64_t granulepos = oggz_tell_granulepos(oggz);
int granuleshift;
ogg_int64_t base, offset;
kate_packet kp;
const kate_event *ev = NULL;
int ret;
kate_packet_wrap(&kp, op->bytes, op->packet);
ret = kate_high_decode_packetin(&(decoder->k), &kp, &ev);
if (granulepos != -1) {
granuleshift = oggz_get_granuleshift(oggz, serialno);
base = (granulepos >> granuleshift);
offset = granulepos - (base << granuleshift);
common->current_loc = (base+offset) * common->granuleperiod;
} else {
common->current_loc = -1;
}
if
(
(common->current_loc == -1)
||
(common->current_loc >= common->player->presentation_time)
)
{
/*
* process the data from the packet
* */
if (ev) {
oggplay_data_handle_kate_data(decoder, ev);
}
}
if (op->e_o_s) {
common->active = 0;
}
#endif
return 0;
}
OggPlayCallbackFunctions callbacks[] = {
{oggplay_init_theora, oggplay_callback_theora, oggplay_shutdown_theora,
sizeof(OggPlayTheoraDecode)}, /* THEORA */
{oggplay_init_audio, oggplay_callback_audio, oggplay_shutdown_audio,
sizeof(OggPlayAudioDecode)}, /* VORBIS */
{oggplay_init_audio, oggplay_callback_audio, oggplay_shutdown_audio,
sizeof(OggPlayAudioDecode)}, /* SPEEX */
{NULL, NULL, NULL, sizeof(OggPlayDecode)}, /* PCM */
{oggplay_init_cmml, oggplay_callback_cmml, NULL, sizeof(OggPlayCmmlDecode)},
{NULL, NULL, NULL, sizeof(OggPlayDecode)}, /* ANX2 */
{oggplay_init_skel, oggplay_callback_skel, NULL,
sizeof(OggPlaySkeletonDecode)},
{NULL, NULL, NULL, sizeof(OggPlayDecode)}, /* FLAC0 */
{NULL, NULL, NULL, sizeof(OggPlayDecode)}, /* FLAC */
{NULL, NULL, NULL, sizeof(OggPlayDecode)}, /* ANXDATA */
{NULL, NULL, NULL, sizeof(OggPlayDecode)}, /* CELT */
{oggplay_init_kate, oggplay_callback_kate, oggplay_shutdown_kate,
sizeof(OggPlayKateDecode)}, /* KATE */
{NULL, NULL, NULL, sizeof(OggPlayDecode)} /* UNKNOWN */
};
OggPlayDecode *
oggplay_initialise_decoder(OggPlay *me, int content_type, int serialno) {
ogg_int64_t num;
ogg_int64_t denom;
OggPlayDecode * decoder = malloc (callbacks[content_type].size);
decoder->serialno = serialno;
decoder->content_type = content_type;
decoder->content_type_name =
oggz_stream_get_content_type (me->oggz, serialno);
decoder->active = 1;
decoder->final_granulepos = -1;
decoder->player = me;
decoder->decoded_type = OGGPLAY_TYPE_UNKNOWN;
/*
* set the StreamInfo to unitialised until we get some real data in
*/
decoder->stream_info = OGGPLAY_STREAM_UNINITIALISED;
/*
* set to -1 until headers decoded
*/
decoder->current_loc = -1;
decoder->last_granulepos = 0;
/*
* the offset is how far advanced or delayed this track is to the "standard"
* time position. An offset of 1000, for example, indicates that data for
* this track arrives 1 second in advance of data for other tracks
*/
decoder->offset = 0;
oggz_get_granulerate(me->oggz, serialno, &num, &denom);
/*
* convert num and denom to a 32.32 fixed point value
*/
decoder->granuleperiod = (denom << 32) / num;
if (callbacks[content_type].init != NULL) {
callbacks[content_type].init(decoder);
}
oggplay_data_initialise_list(decoder);
return decoder;
}
/*
* this function needs to be called on each track to clear up allocated memory
*/
void
oggplay_callback_shutdown(OggPlayDecode *decoder) {
if (callbacks[decoder->content_type].shutdown != NULL) {
callbacks[decoder->content_type].shutdown(decoder);
}
oggplay_data_shutdown_list(decoder);
free(decoder);
}
/*
* this is the callback that is used before all track types have been
* determined - i.e. at the beginning of an ogg bitstream or at the start
* of a new chain
*/
int
oggplay_callback_predetected (OGGZ *oggz, ogg_packet *op, long serialno,
void *user_data) {
OggPlay * me;
int i;
int content_type = 0;
me = (OggPlay *)user_data;
content_type = oggz_stream_get_content (me->oggz, serialno);
/*
* if we encounter a serialno for the second time, then we've reached the
* end of the b_o_s packets
*/
for (i = 0; i < me->num_tracks; i++) {
if (serialno == me->decode_data[i]->serialno) {
me->all_tracks_initialised = 1;
/*
* call appropriate callback
*/
if (callbacks[content_type].callback != NULL) {
callbacks[content_type].callback(oggz, op, serialno,
me->decode_data[i]);
}
/*
* set up all the other callbacks
*/
for (i = 0; i < me->num_tracks; i++) {
serialno = me->decode_data[i]->serialno;
content_type = oggz_stream_get_content (me->oggz, serialno);
oggz_set_read_callback(me->oggz, serialno,
callbacks[content_type].callback, me->decode_data[i]);
}
/*
* destroy this callback
*/
oggz_set_read_callback (me->oggz, -1, NULL, NULL);
return 0;
}
}
me->callback_info = realloc (me->callback_info,
sizeof (OggPlayCallbackInfo) * ++me->num_tracks);
me->decode_data = realloc (me->decode_data, sizeof (long) * me->num_tracks);
me->decode_data[me->num_tracks - 1] = oggplay_initialise_decoder(me,
content_type, serialno);
/*me->decode_data->callback_info = me->callback_info + (me->num_tracks - 1);*/
/*
* call appropriate callback
*/
if (callbacks[content_type].callback != NULL) {
callbacks[content_type].callback(oggz, op, serialno,
me->decode_data[me->num_tracks - 1]);
}
return 0;
}

View File

@ -0,0 +1,59 @@
/*
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.
*/
/*
* oggplay_callback.h
*
* Shane Stephens <shane.stephens@annodex.net>
*/
#ifndef __OGGPLAY_CALLBACK_H__
#define __OGGPLAY_CALLBACK_H__
int
oggplay_callback_predetected (OGGZ *oggz, ogg_packet *op, long serialno,
void *user_data);
void
oggplay_process_leftover_packet(OggPlay *me);
OggPlayDecode *
oggplay_initialise_decoder(OggPlay *me, int content_type, int serialno);
int
oggplay_callback_info_prepare(OggPlay *me, OggPlayCallbackInfo ***info);
void
oggplay_callback_info_destroy(OggPlay *me, OggPlayCallbackInfo **info);
void
oggplay_callback_shutdown(OggPlayDecode *decoder);
#endif

View File

@ -0,0 +1,434 @@
/*
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.
*/
/*
* oggplay_callback_info.c
*
* Shane Stephens <shane.stephens@annodex.net>
*/
#include "oggplay_private.h"
#include <stdlib.h>
#define M(x) ((x) >> 32)
void _print_list(char *name, OggPlayDataHeader *p);
int
oggplay_callback_info_prepare(OggPlay *me, OggPlayCallbackInfo ***info) {
int i;
int tcount = 0;
int added_required_record = 1;
ogg_int64_t diff;
ogg_int64_t latest_first_record = 0x0LL;
//ogg_int64_t lpt = 0;
/*
* allocate the structure for return to the user
*/
(*info) = malloc (me->num_tracks * sizeof (OggPlayCallbackInfo *));
/*
* fill in each active track. Leave gaps for inactive tracks.
*/
for (i = 0; i < me->num_tracks; i++) {
OggPlayDecode * track = me->decode_data[i];
OggPlayCallbackInfo * track_info = me->callback_info + i;
int count = 0;
OggPlayDataHeader * p;
OggPlayDataHeader * q = NULL;
(*info)[i] = track_info;
/*
* this track is inactive and has no data - create an empty record
* for it
*/
if (track->active == 0 && track->data_list == NULL) {
track_info->data_type = OGGPLAY_INACTIVE;
track_info->available_records = track_info->required_records = 0;
track_info->records = NULL;
track_info->stream_info = OGGPLAY_STREAM_UNINITIALISED;
continue;
}
/*
* find the first not presented packet of data, count the total number that
* have not been presented
*/
for (p = track->data_list; p != NULL; p = p->next) {
if (!p->has_been_presented) {
if (q == NULL) {
q = p;
}
count++;
}
}
/*
* tcount is set if any of the tracks have unpresented data
*/
if (count > 0) {
tcount = 1;
/*
* set this track's StreamState. If the track isn't active and there's
* only one timestamp's worth of data in the data list, then this is
* the last data!
*/
if
(
track->active == 0
&&
(
track->end_of_data_list->presentation_time
<=
me->target + track->offset
)
)
{
track_info->stream_info = OGGPLAY_STREAM_LAST_DATA;
} else {
track_info->stream_info = track->stream_info;
}
} else {
track_info->stream_info = OGGPLAY_STREAM_UNINITIALISED;
}
/* null-terminate the record list for the python interface */
track_info->records = malloc ((count + 1) * sizeof (OggPlayDataHeader *));
track_info->records[count] = NULL;
track_info->available_records = count;
track_info->required_records = 0;
track_info->data_type = track->decoded_type;
count = 0;
for (p = q; p != NULL; p = p->next) {
track_info->records[count++] = p;
if (p->presentation_time <= me->target + track->offset) {
track_info->required_records++;
p->has_been_presented = 1;
//lpt = p->presentation_time;
}
}
if (track_info->required_records > 0) {
/*
* if the StreamState is FIRST_DATA then update it to INITIALISED,
* as we've marked the first data instance
*/
if
(
track->stream_info == OGGPLAY_STREAM_FIRST_DATA
||
track->stream_info == OGGPLAY_STREAM_JUST_SEEKED
)
{
track->stream_info = OGGPLAY_STREAM_INITIALISED;
}
}
/*
printf("%d: %d/%d\t", i,
track_info->required_records, count);
if (q != NULL) {
printf("fst: %lld lst: %lld sz: %lld pt: %lld\n",
q->presentation_time >> 32, lpt >> 32,
(lpt - q->presentation_time) >> 32,
me->presentation_time >> 32);
}
*/
/*
* this statement detects if this track needs records but has none.
* We need to be careful - there are 2 cases where this could happen. The
* first is where the presentation time is less than it should be, and
* there is no data available between now and the target. In this case
* we want to set added_required_record to 0 and trigger the presentation
* time update code below.
* <-------data----------...
* ^ ^ ^
* pt target current_loc
*
* The second case occurs when the packet from the last timestamp contained
* so much data that there *is* none in this timestamp. In this case we
* don't want to set added_required_record to 0.
*
* <----------data---------------|--------...
* <-timeslice1-><-timeslice2-><-timeslice3->
* ^ ^ ^
* pt target current_loc
*
* How do we discriminate between these two cases? We assume the pt update
* needs to be explicitly required (e.g. by seeking or start of movie), and
* create a new member in the player struct called pt_update_valid
*/
if
(
track->decoded_type != OGGPLAY_CMML
&&
track->decoded_type != OGGPLAY_KATE // TODO: check this is the right thing to do
&&
track_info->required_records == 0
&&
track->active == 1
&&
me->pt_update_valid
) {
added_required_record = 0;
me->pt_update_valid = 0;
}
}
//printf("\n");
/*
* there are no required records! This means that we need to advance the
* target to the period before the first actual record - the bitstream has
* lied about the presence of data here.
*
* This happens for example with some Annodex streams (a bug in libannodex
* causes incorrect timestamping)
*
* What we actually need is the first timestamp *just before* a timestamp
* with valid data on all active tracks that are not CMML tracks.
*/
latest_first_record = 0x0LL;
if (tcount > 0 && added_required_record == 0) {
for (i = 0; i < me->num_tracks; i++) {
OggPlayCallbackInfo * track_info = me->callback_info + i;
if (track_info->data_type == OGGPLAY_CMML || track_info->data_type == OGGPLAY_KATE) {
continue;
}
if (track_info->available_records > 0) {
if (track_info->records[0]->presentation_time > latest_first_record) {
latest_first_record = track_info->records[0]->presentation_time;
}
}
}
/*
* update target to the time-period before the first record. This is
* independent of the offset (after all, we want to maintain synchronisation
* between the streams).
*/
diff = latest_first_record - me->target;
diff = (diff / me->callback_period) * me->callback_period;
me->target += diff + me->callback_period;
/*
* update the presentation_time to the latest_first_record. This ensures
* that we don't play material for timestamps that only exist in one track.
*/
me->presentation_time = me->target - me->callback_period;
/*
* indicate that we need to go through another round of fragment collection
* and callback creation
*/
for (i = 0; i < me->num_tracks; i++) {
if ((*info)[i]->records != NULL) free((*info)[i]->records);
}
free(*info);
(*info) = NULL;
}
if (tcount == 0) {
for (i = 0; i < me->num_tracks; i++) {
if ((*info)[i]->records != NULL) free((*info)[i]->records);
}
free(*info);
(*info) = NULL;
}
return me->num_tracks;
}
void
oggplay_callback_info_destroy(OggPlay *me, OggPlayCallbackInfo **info) {
int i;
OggPlayCallbackInfo * p;
for (i = 0; i < me->num_tracks; i++) {
p = info[i];
if (me->buffer == NULL && p->records != NULL)
free(p->records);
}
free(info);
}
OggPlayDataType
oggplay_callback_info_get_type(OggPlayCallbackInfo *info) {
if (info == NULL) {
return (OggPlayDataType)E_OGGPLAY_BAD_CALLBACK_INFO;
}
return info->data_type;
}
int
oggplay_callback_info_get_available(OggPlayCallbackInfo *info) {
if (info == NULL) {
return E_OGGPLAY_BAD_CALLBACK_INFO;
}
return info->available_records;
}
int
oggplay_callback_info_get_required(OggPlayCallbackInfo *info) {
if (info == NULL) {
return E_OGGPLAY_BAD_CALLBACK_INFO;
}
return info->required_records;
}
OggPlayStreamInfo
oggplay_callback_info_get_stream_info(OggPlayCallbackInfo *info) {
if (info == NULL) {
return E_OGGPLAY_BAD_CALLBACK_INFO;
}
return info->stream_info;
}
OggPlayDataHeader **
oggplay_callback_info_get_headers(OggPlayCallbackInfo *info) {
if (info == NULL) {
return NULL;
}
return info->records;
}
/**
* Returns number of samples in the record
* Note: the resulting data include samples for all audio channels */
ogg_int64_t
oggplay_callback_info_get_record_size(OggPlayDataHeader *header) {
if (header == NULL) {
return 0;
}
return header->samples_in_record;
}
void
oggplay_callback_info_lock_item(OggPlayDataHeader *header) {
if (header == NULL) {
return;
}
header->lock += 1;
}
void
oggplay_callback_info_unlock_item(OggPlayDataHeader *header) {
if (header == NULL) {
return;
}
header->lock -= 1;
}
long
oggplay_callback_info_get_presentation_time(OggPlayDataHeader *header) {
if (header == NULL) {
return -1;
}
/* SGS: is this correct? */
return (header->presentation_time >> 32) & 0xFFFFFFFF;
}
OggPlayVideoData *
oggplay_callback_info_get_video_data(OggPlayDataHeader *header) {
if (header == NULL) {
return NULL;
}
return &((OggPlayVideoRecord *)header)->data;
}
OggPlayAudioData *
oggplay_callback_info_get_audio_data(OggPlayDataHeader *header) {
if (header == NULL) {
return NULL;
}
return (OggPlayAudioData *)((OggPlayAudioRecord *)header)->data;
}
OggPlayTextData *
oggplay_callback_info_get_text_data(OggPlayDataHeader *header) {
if (header == NULL) {
return NULL;
}
return ((OggPlayTextRecord *)header)->data;
}

View File

@ -0,0 +1,396 @@
/*
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.
*/
/*
* oggplay_data.c
*
* Shane Stephens <shane.stephens@annodex.net>
*/
#include "oggplay_private.h"
#include <stdlib.h>
#include <string.h>
#if HAVE_INTTYPES_H
#include <inttypes.h>
#else
#if LONG_MAX==2147483647L
#define PRId64 "lld"
#else
#define PRId64 "ld"
#endif
#endif
/*
* the normal lifecycle for a frame is:
*
* (1) frame gets decoded and added to list with a locking value of 1
* (2) frame gets delivered to user
* (3) frame becomes out-of-date (its presentation time expires) and its
* lock is decremented
* (4) frame is removed from list and freed
*
* This can be modified by:
* (a) early consumption by user (user calls oggplay_mark_record_consumed)
* (b) frame locking by user (user calls oggplay_mark_record_locked) and
* subsequent unlocking (user calls oggplay_mark_record_consumed)
*/
void
oggplay_data_initialise_list (OggPlayDecode *decode) {
decode->data_list = decode->end_of_data_list = NULL;
decode->untimed_data_list = NULL;
}
/*
* helper function to append data packets to end of data_list
*/
void
oggplay_data_add_to_list_end(OggPlayDecode *decode, OggPlayDataHeader *data) {
data->next = NULL;
if (decode->data_list == NULL) {
decode->data_list = data;
decode->end_of_data_list = data;
} else {
decode->end_of_data_list->next = data;
decode->end_of_data_list = data;
}
}
#define M(x) ((x) >> 32)
/*
* helper function to append data packets to front of data_list
*/
void
oggplay_data_add_to_list_front(OggPlayDecode *decode, OggPlayDataHeader *data) {
if (decode->data_list == NULL) {
decode->data_list = decode->end_of_data_list = data;
data->next = NULL;
} else {
data->next = decode->data_list;
decode->data_list = data;
}
}
void
_print_list(char *name, OggPlayDataHeader *p) {
printf("%s: ", name);
for (; p != NULL; p = p->next) {
printf("%"PRId64"[%d]", p->presentation_time >> 32, p->lock);
if (p->next != NULL) printf("->");
}
printf("\n");
}
void
oggplay_data_add_to_list (OggPlayDecode *decode, OggPlayDataHeader *data) {
/*
* if this is a packet with an unknown display time, prepend it to
* the untimed_data_list for later timestamping.
*/
ogg_int64_t samples_in_next_in_list;
//_print_list("before", decode->data_list);
//_print_list("untimed before", decode->untimed_data_list);
if (data->presentation_time == -1) {
data->next = decode->untimed_data_list;
decode->untimed_data_list = data;
} else {
/*
* process the untimestamped data into the timestamped data list.
*
* First store any old data.
*/
ogg_int64_t presentation_time = data->presentation_time;
samples_in_next_in_list = data->samples_in_record;
while (decode->untimed_data_list != NULL) {
OggPlayDataHeader *untimed = decode->untimed_data_list;
presentation_time -=
samples_in_next_in_list * decode->granuleperiod;
untimed->presentation_time = presentation_time;
decode->untimed_data_list = untimed->next;
samples_in_next_in_list = untimed->samples_in_record;
if (untimed->presentation_time >= decode->player->presentation_time) {
oggplay_data_add_to_list_front(decode, untimed);
} else {
free(untimed);
}
}
oggplay_data_add_to_list_end(decode, data);
/*
* if the StreamInfo is still at uninitialised, then this is the first
* meaningful data packet! StreamInfo will be updated to
* OGGPLAY_STREAM_INITIALISED in oggplay_callback_info.c as part of the
* callback process.
*/
if (decode->stream_info == OGGPLAY_STREAM_UNINITIALISED) {
decode->stream_info = OGGPLAY_STREAM_FIRST_DATA;
}
}
//_print_list("after", decode->data_list);
//_print_list("untimed after", decode->untimed_data_list);
}
void
oggplay_data_free_list(OggPlayDataHeader *list) {
OggPlayDataHeader *p;
while (list != NULL) {
p = list;
list = list->next;
free(p);
}
}
void
oggplay_data_shutdown_list (OggPlayDecode *decode) {
oggplay_data_free_list(decode->data_list);
oggplay_data_free_list(decode->untimed_data_list);
}
/*
* this function removes any displayed, unlocked frames from the list.
*
* this function also removes any undisplayed frames that are before the
* global presentation time.
*/
void
oggplay_data_clean_list (OggPlayDecode *decode) {
ogg_int64_t target = decode->player->target;
OggPlayDataHeader * header = decode->data_list;
OggPlayDataHeader * p = NULL;
while (header != NULL) {
if
(
header->lock == 0
&&
(
(
(header->presentation_time < (target + decode->offset))
&&
header->has_been_presented
)
||
(
(header->presentation_time < decode->player->presentation_time)
)
)
)
{
if (p == NULL) {
decode->data_list = decode->data_list->next;
if (decode->data_list == NULL)
decode->end_of_data_list = NULL;
free (header);
header = decode->data_list;
} else {
if (header->next == NULL)
decode->end_of_data_list = p;
p->next = header->next;
free (header);
header = p->next;
}
} else {
p = header;
header = header->next;
}
}
}
void
oggplay_data_initialise_header (OggPlayDecode *decode,
OggPlayDataHeader *header) {
/*
* the frame is not cleaned until its presentation time has passed. We'll
* check presentation times in oggplay_data_clean_list.
*/
header->lock = 0;
header->next = NULL;
header->presentation_time = decode->current_loc;
header->has_been_presented = 0;
}
void
oggplay_data_handle_audio_data (OggPlayDecode *decode, void *data,
int samples, int samplesize) {
int num_channels;
OggPlayAudioRecord * record;
num_channels = ((OggPlayAudioDecode *)decode)->sound_info.channels;
record = (OggPlayAudioRecord*)calloc(sizeof(OggPlayAudioRecord) +
samples * samplesize * num_channels, 1);
oggplay_data_initialise_header(decode, &(record->header));
record->header.samples_in_record = samples;
record->data = (void *)(record + 1);
memcpy(record->data, data, samples * samplesize * num_channels);
/*
printf("[%f%f%f]\n", ((float *)record->data)[0], ((float *)record->data)[1],
((float *)record->data)[2]);
*/
oggplay_data_add_to_list(decode, &(record->header));
}
void
oggplay_data_handle_cmml_data(OggPlayDecode *decode, unsigned char *data,
int size) {
OggPlayTextRecord * record;
record =
(OggPlayTextRecord*)calloc (sizeof(OggPlayTextRecord) + size + 1, 1);
oggplay_data_initialise_header(decode, &(record->header));
record->header.samples_in_record = 1;
record->data = (char *)(record + 1);
memcpy(record->data, data, size);
record->data[size] = '\0';
oggplay_data_add_to_list(decode, &(record->header));
}
void
oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
yuv_buffer *buffer) {
int size = sizeof (OggPlayVideoRecord);
int i;
unsigned char * p;
unsigned char * q;
unsigned char * p2;
unsigned char * q2;
OggPlayVideoRecord * record;
OggPlayVideoData * data;
if (buffer->y_stride < 0) {
size -= buffer->y_stride * buffer->y_height;
size -= buffer->uv_stride * buffer->uv_height * 2;
} else {
size += buffer->y_stride * buffer->y_height;
size += buffer->uv_stride * buffer->uv_height * 2;
}
/*
* we need to set the output strides to the input widths because we are
* trying not to pass negative output stride issues on to the poor user.
*/
record = (OggPlayVideoRecord*)malloc (size);
record->header.samples_in_record = 1;
data = &(record->data);
oggplay_data_initialise_header((OggPlayDecode *)decode, &(record->header));
data->y = (unsigned char *)(record + 1);
data->u = data->y + (decode->y_stride * decode->y_height);
data->v = data->u + (decode->uv_stride * decode->uv_height);
/*
* *grumble* theora plays silly buggers with pointers so we need to do
* a row-by-row copy (stride may be negative)
*/
p = data->y;
q = buffer->y;
for (i = 0; i < decode->y_height; i++) {
memcpy(p, q, decode->y_width);
p += decode->y_width;
q += buffer->y_stride;
}
p = data->u;
q = buffer->u;
p2 = data->v;
q2 = buffer->v;
for (i = 0; i < decode->uv_height; i++) {
memcpy(p, q, decode->uv_width);
memcpy(p2, q2, decode->uv_width);
p += decode->uv_width;
p2 += decode->uv_width;
q += buffer->uv_stride;
q2 += buffer->uv_stride;
}
oggplay_data_add_to_list((OggPlayDecode *)decode, &(record->header));
}
#ifdef HAVE_KATE
void
oggplay_data_handle_kate_data(OggPlayKateDecode *decode, const kate_event *ev) {
// TODO: should be able to send the data rendered as YUV data, but just text for now
OggPlayTextRecord * record;
record = (OggPlayTextRecord*)calloc (sizeof(OggPlayTextRecord) + ev->len0, 1);
oggplay_data_initialise_header(&decode->decoder, &(record->header));
//record->header.presentation_time = (ogg_int64_t)(ev->start_time*1000);
record->header.samples_in_record = (ev->end_time-ev->start_time)*1000;
record->data = (char *)(record + 1);
memcpy(record->data, ev->text, ev->len0);
oggplay_data_add_to_list(&decode->decoder, &(record->header));
}
#endif

View File

@ -0,0 +1,70 @@
/*
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.
*/
/*
* oggplay_data.h
*
* Shane Stephens <shane.stephens@annodex.net>
*/
#ifndef __OGGPLAY_DATA_H__
#define __OGGPLAY_DATA_H__
void
oggplay_data_initialise_list (OggPlayDecode *decode);
void
oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
yuv_buffer *buffer);
void
oggplay_data_handle_audio_data (OggPlayDecode *decode, void *data,
int samples, int samplesize);
void
oggplay_data_handle_cmml_data(OggPlayDecode *decode, unsigned char *data,
int size);
#ifdef HAVE_KATE
void
oggplay_data_handle_kate_data(OggPlayKateDecode *decode,
const kate_event *ev);
#endif
void
oggplay_data_clean_list (OggPlayDecode *decode);
void
oggplay_data_free_list(OggPlayDataHeader *list);
void
oggplay_data_shutdown_list (OggPlayDecode *decode);
#endif

View File

@ -0,0 +1,155 @@
/*
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.
*/
/*
* oggplay_file_reader.c
*
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
*/
#include "oggplay_private.h"
#include "oggplay_file_reader.h"
#include <stdlib.h>
#include <string.h>
OggPlayErrorCode
oggplay_file_reader_initialise(OggPlayReader * opr, int block) {
OggPlayFileReader * me = (OggPlayFileReader *)opr;
(void)block; /* unused for file readers */
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
}
me->file = fopen(me->file_name, "rb");
if (me->file == NULL) {
return E_OGGPLAY_BAD_INPUT;
}
fseek(me->file, SEEK_END, 0);
me->size = ftell(me->file);
fseek(me->file, SEEK_SET, 0);
me->current_position = 0;
return E_OGGPLAY_OK;
}
OggPlayErrorCode
oggplay_file_reader_destroy(OggPlayReader * opr) {
OggPlayFileReader * me;
me = (OggPlayFileReader *)opr;
fclose(me->file);
free(me);
return E_OGGPLAY_OK;
}
int
oggplay_file_reader_available(OggPlayReader * opr, ogg_int64_t current_bytes,
ogg_int64_t current_time) {
OggPlayFileReader *me = (OggPlayFileReader *)opr;
return me->size;
}
int
oggplay_file_reader_finished_retrieving(OggPlayReader *opr) {
return 1;
}
static size_t
oggplay_file_reader_io_read(void * user_handle, void * buf, size_t n) {
OggPlayFileReader *me = (OggPlayFileReader *)user_handle;
int r;
r = fread(buf, 1, n, me->file);
if (r > 0) {
me->current_position += r;
}
return r;
}
static int
oggplay_file_reader_io_seek(void * user_handle, long offset, int whence) {
OggPlayFileReader * me = (OggPlayFileReader *)user_handle;
int r;
r = fseek(me->file, offset, whence);
me->current_position = ftell(me->file);
return r;
}
static long
oggplay_file_reader_io_tell(void * user_handle) {
OggPlayFileReader * me = (OggPlayFileReader *)user_handle;
return ftell(me->file);
}
OggPlayReader *
oggplay_file_reader_new(char *file_name) {
OggPlayFileReader * me = malloc (sizeof (OggPlayFileReader));
me->current_position = 0;
me->file_name = file_name;
me->file = NULL;
me->functions.initialise = &oggplay_file_reader_initialise;
me->functions.destroy = &oggplay_file_reader_destroy;
me->functions.available = &oggplay_file_reader_available;
me->functions.finished_retrieving = &oggplay_file_reader_finished_retrieving;
me->functions.seek = NULL;
me->functions.io_read = &oggplay_file_reader_io_read;
me->functions.io_seek = &oggplay_file_reader_io_seek;
me->functions.io_tell = &oggplay_file_reader_io_tell;
return (OggPlayReader *)me;
}

View File

@ -0,0 +1,56 @@
/*
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.
*/
/*
* oggplay_file_reader.h
*
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
*/
#ifndef __OGGPLAY_FILE_READER_H__
#define __OGGPLAY_FILE_READER_H__
#include <stdio.h>
#define FILE_READER_CHUNK_SIZE 8192
#define FILE_READER_INITIAL_NUM_BUFFERS 8
typedef struct {
OggPlayReader functions;
char * file_name;
FILE * file;
int current_position;
int size;
} OggPlayFileReader;
#endif

View File

@ -0,0 +1,283 @@
/*
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.
*/
/*
* oggplay_private.h
*
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
*/
#ifndef __OGGPLAY_PRIVATE_H__
#define __OGGPLAY_PRIVATE_H__
#ifdef WIN32
#include "config_win32.h"
#else
#include <config.h>
#endif
#include <oggplay/oggplay.h>
#include <oggz/oggz.h>
#include <theora/theora.h>
#include <fishsound/fishsound.h>
#ifdef HAVE_KATE
#include <kate/kate.h>
#endif
#ifdef WIN32
#ifdef HAVE_WINSOCK2
#include <winsock2.h>
#else
#include <winsock.h>
#endif
#endif
// for Win32 <windows.h> has to be included last
#include "std_semaphore.h"
/**
*
* has_been_presented: 0 until the data has been added as a "required" element,
* then 1.
*/
struct _OggPlayDataHeader {
int lock;
struct _OggPlayDataHeader * next;
ogg_int64_t presentation_time;
ogg_int64_t samples_in_record;
int has_been_presented;
};
typedef struct {
OggPlayDataHeader header;
OggPlayVideoData data;
} OggPlayVideoRecord;
typedef struct {
OggPlayDataHeader header;
void * data;
} OggPlayAudioRecord;
typedef struct {
OggPlayDataHeader header;
char * data;
} OggPlayTextRecord;
struct _OggPlay;
typedef struct {
void ** buffer_list;
void ** buffer_mirror;
int buffer_size;
int last_filled;
int last_emptied;
semaphore frame_sem;
} OggPlayBuffer;
struct _OggPlayCallbackInfo {
OggPlayDataType data_type;
int available_records;
int required_records;
OggPlayStreamInfo stream_info;
OggPlayDataHeader ** records;
OggPlayBuffer * buffer;
};
/**
* OggPlayDecode
*
* A structure that contains information about a single track within the Ogg
* file.
*
* data_list, end_of_data_list: Contain decoded data packets for this track.
* These packets are time-ordered, and have a
* known presentation time
*
* untimed_data_list: Contains decoded data packets for this track.
* These packets are reverse time-ordered, and
* have not got a known presentation time. This
* list gets constructed when a new Ogg file is
* first being read, and gets torn down as soon as
* the first packet with a granulepos is processed
*
* granuleperiod The period between adjacent samples in this
* track
*/
typedef struct {
long serialno;
int content_type;
const char * content_type_name;
OggPlayDataType decoded_type;
ogg_int64_t granuleperiod;
ogg_int64_t last_granulepos;
ogg_int64_t offset;
ogg_int64_t current_loc;
int active;
ogg_int64_t final_granulepos;
struct _OggPlay * player;
OggPlayDataHeader * data_list;
OggPlayDataHeader * end_of_data_list;
OggPlayDataHeader * untimed_data_list;
OggPlayStreamInfo stream_info;
int preroll;
} OggPlayDecode;
typedef struct {
OggPlayDecode decoder;
theora_state video_handle;
theora_info video_info;
theora_comment video_comment;
int remaining_header_packets;
int granulepos_seen;
int frame_delta;
int y_width;
int y_height;
int y_stride;
int uv_width;
int uv_height;
int uv_stride;
int cached_keyframe;
} OggPlayTheoraDecode;
typedef struct {
OggPlayDecode decoder;
FishSound * sound_handle;
FishSoundInfo sound_info;
} OggPlayAudioDecode;
typedef struct {
OggPlayDecode decoder;
int granuleshift;
} OggPlayCmmlDecode;
typedef struct {
OggPlayDecode decoder;
ogg_int64_t presentation_time;
ogg_int64_t base_time;
} OggPlaySkeletonDecode;
typedef struct {
OggPlayDecode decoder;
#ifdef HAVE_KATE
int granuleshift;
kate_state k;
#endif
} OggPlayKateDecode;
struct OggPlaySeekTrash;
typedef struct OggPlaySeekTrash {
OggPlayDataHeader * old_data;
OggPlayBuffer * old_buffer;
struct OggPlaySeekTrash * next;
} OggPlaySeekTrash;
struct _OggPlay {
OggPlayReader * reader;
OGGZ * oggz;
OggPlayDecode ** decode_data;
OggPlayCallbackInfo * callback_info;
int num_tracks;
int all_tracks_initialised;
ogg_int64_t callback_period;
OggPlayDataCallback * callback;
void * callback_user_ptr;
ogg_int64_t target;
int active_tracks;
volatile OggPlayBuffer * buffer;
ogg_int64_t presentation_time;
OggPlaySeekTrash * trash;
int shutdown;
int pt_update_valid;
};
void
oggplay_set_data_callback_force(OggPlay *me, OggPlayDataCallback callback,
void *user);
void
oggplay_take_out_trash(OggPlay *me, OggPlaySeekTrash *trash);
typedef struct {
void (*init)(void *user_data);
int (*callback)(OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data);
void (*shutdown)(void *user_data);
int size;
} OggPlayCallbackFunctions;
#include "oggplay_callback.h"
#include "oggplay_data.h"
#include "oggplay_buffer.h"
#if 0
static inline void _free(void *x) {
printf("%p\n", x);
free(x);
}
static inline void *_malloc(int s) {
void *x;
printf("%d ", s);
x = malloc(s);
printf("%p\n", x);
return x;
}
static inline void *_realloc(void *x, int s) {
void *y;
printf("%p %d ", x, s);
y = realloc(x, s);
printf("%p\n", y);
return y;
}
static inline void *_calloc(int n, int s) {
void *x;
printf("%d %d ", n, s);
x = calloc(n, s);
printf("%p\n", x);
return x;
}
#define free(x) {printf("FREE %s %d ", __FILE__, __LINE__); _free(x);}
#define malloc(s) (printf("MALLOC %s %d ", __FILE__, __LINE__), \
_malloc(s))
#define realloc(x, s) (printf("REALLOC %s %d ", __FILE__, __LINE__), \
_realloc(x, s))
#define calloc(n, s) (printf("CALLOC %s %d ", __FILE__, __LINE__), \
_calloc(n, s))
#endif
#endif

View File

@ -0,0 +1,202 @@
/*
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.
*/
/*
* oggplay_query.c
*
* Shane Stephens <shane.stephens@annodex.net>
*/
#include "oggplay_private.h"
int
oggplay_get_num_tracks (OggPlay * me) {
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (me->reader == NULL) {
return E_OGGPLAY_BAD_READER;
}
if (me->all_tracks_initialised == 0) {
return E_OGGPLAY_UNINITIALISED;
}
return me->num_tracks;
}
OggzStreamContent
oggplay_get_track_type (OggPlay * me, int track_num) {
if (me == NULL) {
return (OggzStreamContent)E_OGGPLAY_BAD_OGGPLAY;
}
if (me->reader == NULL) {
return (OggzStreamContent)E_OGGPLAY_BAD_READER;
}
if (me->all_tracks_initialised == 0) {
return E_OGGPLAY_UNINITIALISED;
}
if (track_num < 0 || track_num >= me->num_tracks) {
return (OggzStreamContent)E_OGGPLAY_BAD_TRACK;
}
return (OggzStreamContent)me->decode_data[track_num]->content_type;
}
const char *
oggplay_get_track_typename (OggPlay * me, int track_num) {
if (me == NULL) {
return NULL;
}
if (me->reader == NULL) {
return NULL;
}
if (me->all_tracks_initialised == 0) {
return NULL;
}
if (track_num < 0 || track_num >= me->num_tracks) {
return NULL;
}
return me->decode_data[track_num]->content_type_name;
}
OggPlayErrorCode
oggplay_set_track_active(OggPlay *me, int track_num) {
ogg_int64_t p;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (me->reader == NULL) {
return E_OGGPLAY_BAD_READER;
}
if (me->all_tracks_initialised == 0) {
return E_OGGPLAY_UNINITIALISED;
}
if (track_num < 0 || track_num >= me->num_tracks) {
return E_OGGPLAY_BAD_TRACK;
}
/*
* Skeleton tracks should not be set active - data in them should be queried
* using alternative mechanisms (there is no concept of time-synced data
* in a skeleton track)
*/
if (me->decode_data[track_num]->content_type == OGGZ_CONTENT_SKELETON) {
return E_OGGPLAY_TRACK_IS_SKELETON;
}
if ((p = me->decode_data[track_num]->final_granulepos) != -1) {
if (p * me->decode_data[track_num]->granuleperiod > me->target) {
return E_OGGPLAY_TRACK_IS_OVER;
}
}
if (me->decode_data[track_num]->active == 0) {
me->decode_data[track_num]->active = 1;
/*
* CMML tracks aren't counted when deciding whether we've read enough data
* from the stream. This is because CMML data is not continuous, and
* determining that we've read enough data from each other stream is enough
* to determing that we've read any CMML data that is available.
* This also applies to Kate streams.
*/
if (me->decode_data[track_num]->content_type != OGGZ_CONTENT_CMML
#ifdef HAVE_KATE
&& me->decode_data[track_num]->content_type != OGGZ_CONTENT_KATE
#endif
) {
me->active_tracks ++;
}
}
return E_OGGPLAY_OK;
}
OggPlayErrorCode
oggplay_set_track_inactive(OggPlay *me, int track_num) {
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (me->reader == NULL) {
return E_OGGPLAY_BAD_READER;
}
if (me->all_tracks_initialised == 0) {
return E_OGGPLAY_UNINITIALISED;
}
if (track_num < 0 || track_num >= me->num_tracks) {
return E_OGGPLAY_BAD_TRACK;
}
if (me->decode_data[track_num]->content_type == OGGZ_CONTENT_SKELETON) {
return E_OGGPLAY_TRACK_IS_SKELETON;
}
if (me->decode_data[track_num]->active == 1) {
me->decode_data[track_num]->active = 0;
/*
* see above comment in oggplay_set_track_active
*/
if (me->decode_data[track_num]->content_type != OGGZ_CONTENT_CMML
#ifdef HAVE_KATE
&& me->decode_data[track_num]->content_type != OGGZ_CONTENT_KATE
#endif
) {
me->active_tracks --;
}
}
return E_OGGPLAY_OK;
}

View File

@ -0,0 +1,155 @@
/*
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.
*/
/*
* oggplay_enums.h
*
* Shane Stephens <shane.stephens@annodex.net>
*/
#include "oggplay_private.h"
OggPlayErrorCode
oggplay_seek(OggPlay *me, ogg_int64_t milliseconds) {
OggPlaySeekTrash * trash;
OggPlaySeekTrash ** p;
OggPlayDataHeader ** end_of_list_p;
int i;
int eof;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (milliseconds < 0) {
return E_OGGPLAY_CANT_SEEK;
}
eof = me->reader->duration(me->reader);
if (eof > -1 && milliseconds > eof) {
return E_OGGPLAY_CANT_SEEK;
}
if (me->reader->seek != NULL) {
if
(
me->reader->seek(me->reader, me->oggz, milliseconds)
==
E_OGGPLAY_CANT_SEEK
)
{
return E_OGGPLAY_CANT_SEEK;
}
} else {
if (oggz_seek_units(me->oggz, milliseconds, SEEK_SET) == -1) {
return E_OGGPLAY_CANT_SEEK;
}
}
/*
* first, create a trash object to store the context that we want to
* delete but can't until the presentation thread is no longer using it -
* this will occur as soon as the thread calls oggplay_buffer_release_next
*/
trash = malloc(sizeof(OggPlaySeekTrash));
/*
* store the old buffer in it next.
*/
trash->old_buffer = (OggPlayBuffer *)me->buffer;
/*
* replace the buffer with a new one. From here on, the presentation thread
* will start using this buffer instead.
*/
me->buffer = oggplay_buffer_new_buffer(me->buffer->buffer_size);
/*
* strip all of the data packets out of the streams and put them into the
* trash. We can free the untimed packets immediately - they are USELESS
* SCUM OF THE EARTH (and also unreferenced by the buffer).
*/
end_of_list_p = &trash->old_data;
for (i = 0; i < me->num_tracks; i++) {
OggPlayDecode *track = me->decode_data[i];
if (track->data_list != NULL) {
*(end_of_list_p) = track->data_list;
end_of_list_p = &(track->end_of_data_list->next);
oggplay_data_free_list(track->untimed_data_list);
}
track->data_list = track->end_of_data_list = NULL;
track->untimed_data_list = NULL;
track->current_loc = -1;
track->stream_info = OGGPLAY_STREAM_JUST_SEEKED;
}
/*
* set the presentation time
*/
me->presentation_time = milliseconds;
me->target = me->callback_period - 1;
me->pt_update_valid = 1;
trash->next = NULL;
p = &(me->trash);
while (*p != NULL) {
p = &((*p)->next);
}
*p = trash;
return E_OGGPLAY_OK;
}
void
oggplay_take_out_trash(OggPlay *me, OggPlaySeekTrash *trash) {
OggPlaySeekTrash *p = NULL;
for (; trash != NULL; trash = trash->next) {
oggplay_buffer_shutdown(me, trash->old_buffer);
oggplay_data_free_list(trash->old_data);
if (p != NULL) {
free(p);
}
p = trash;
}
if (p != NULL) {
free(p);
}
}

View File

@ -0,0 +1,688 @@
/*
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.
*/
/*
* oggplay_tcp_reader.c
*
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
*/
#include "oggplay_private.h"
#include "oggplay_tcp_reader.h"
#include <stdlib.h>
#include <string.h>
#ifdef WIN32
#include <process.h>
#include <io.h>
#else
#include <sys/types.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/fcntl.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <time.h>
#include <netdb.h>
#include <unistd.h>
#endif
#include <assert.h>
#define PRINT_BUFFER(s,m) \
printf("%s: in_mem: %d size: %d pos: %d stored: %d\n", \
s, m->amount_in_memory, m->buffer_size, \
m->current_position, m->stored_offset);
#ifndef WIN32
typedef int SOCKET;
#define INVALID_SOCKET -1
#endif
#define START_TIMEOUT(ref) \
(ref) = oggplay_sys_time_in_ms()
#ifdef WIN32
#define CHECK_ERROR(error) \
(WSAGetLastError() == WSA##error)
#else
#define CHECK_ERROR(error) \
(errno == error)
#endif
#define RETURN_ON_TIMEOUT_OR_CONTINUE(ref) \
if (oggplay_sys_time_in_ms() - (ref) > 500) { \
return E_OGGPLAY_TIMEOUT; \
} else { \
oggplay_millisleep(10); \
continue; \
}
#ifdef WIN32
int
oggplay_set_socket_blocking_state(SOCKET socket, int is_blocking) {
u_long io_mode = !is_blocking;
if (ioctlsocket(socket, FIONBIO, &io_mode) == SOCKET_ERROR) {
return 0;
}
return 1;
}
#else
int
oggplay_set_socket_blocking_state(SOCKET socket, int is_blocking) {
if (fcntl(socket, F_SETFL, is_blocking ? 0 : O_NONBLOCK) == -1) {
return 0;
}
return 1;
}
#endif
SOCKET
oggplay_create_socket() {
SOCKET sock;
#ifdef WIN32
WORD wVersionRequested;
WSADATA wsaData;
#ifdef HAVE_WINSOCK2
wVersionRequested = MAKEWORD(2,2);
#else
wVersionRequested = MAKEWORD(1,1);
#endif
if (WSAStartup(wVersionRequested, &wsaData) == -1) {
printf("Socket open error\n");
return INVALID_SOCKET;
}
if (wsaData.wVersion != wVersionRequested) {
printf("Incorrect winsock version [%d]\n", wVersionRequested);
WSACleanup();
return INVALID_SOCKET;
}
#endif
sock = socket(PF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
printf("Could not create socket\n");
#ifdef WIN32
WSACleanup();
#endif
return INVALID_SOCKET;
}
return sock;
}
/*
* this function guarantees it will return malloced versions of host and
* path
*/
void
oggplay_hostname_and_path(char *location, char *proxy, int proxy_port,
char **host, int *port, char **path) {
char * colon;
char * slash;
char * end_of_host;
/* if we have a proxy installed this is all dead simple */
if (proxy != NULL) {
*host = strdup(proxy);
*port = proxy_port;
*path = strdup(location);
return;
}
/* find start_pos */
if (strncmp(location, "http://", 7) == 0) {
location += 7;
}
colon = strchr(location, ':');
slash = strchr(location, '/');
/*
* if both are null, then just set the simple defaults and return
*/
if (colon == NULL && slash == NULL) {
*host = strdup(location);
*port = 80;
*path = strdup("/");
return;
}
/*
* if there's a slash and it's before colon, there's no port. Hence, after
* this code, the only time that there's a port is when colon is non-NULL
*/
if (slash != NULL && colon > slash) {
colon = NULL;
}
/*
* we might as well extract the port now. We can also work out where
* the end of the hostname is, as it's either the colon (if there's a port)
* or the slash (if there's no port)
*/
if (colon != NULL) {
*port = (int)strtol(colon+1, NULL, 10);
end_of_host = colon;
} else {
*port = 80;
end_of_host = slash;
}
*host = strdup(location);
(*host)[end_of_host - location] = '\0';
if (slash == NULL) {
*path = strdup("/");
return;
}
*path = strdup(slash);
}
OggPlayErrorCode
oggplay_connect_to_host(SOCKET socket, struct sockaddr *addr) {
ogg_int64_t time_ref;
START_TIMEOUT(time_ref);
while (connect(socket, addr, sizeof(struct sockaddr_in)) < 0) {
if (
CHECK_ERROR(EINPROGRESS) || CHECK_ERROR(EALREADY)
#ifdef WIN32
/* see http://msdn2.microsoft.com/en-us/library/ms737625.aspx */
|| CHECK_ERROR(EWOULDBLOCK) || CHECK_ERROR(EINVAL)
#endif
) {
RETURN_ON_TIMEOUT_OR_CONTINUE(time_ref);
}
else if CHECK_ERROR(EISCONN)
{
break;
}
printf("Could not connect to host; error code is %d\n", errno);
return CHECK_ERROR(ETIMEDOUT) ? E_OGGPLAY_TIMEOUT :
E_OGGPLAY_SOCKET_ERROR;
}
return E_OGGPLAY_OK;
}
OggPlayErrorCode
oggplay_tcp_reader_initialise(OggPlayReader * opr, int block) {
OggPlayTCPReader * me = (OggPlayTCPReader *)opr;
struct hostent * he;
struct sockaddr_in addr;
char * host;
char * path;
int port;
int nbytes;
int remaining;
char http_request_header[1024];
ogg_int64_t time_ref;
int r;
char * pos;
int len;
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
}
if (me->state == OTRS_INIT_COMPLETE) {
return E_OGGPLAY_OK;
}
/*
* Create the socket.
*/
if (me->state == OTRS_UNINITIALISED) {
assert(me->socket == INVALID_SOCKET);
me->socket = oggplay_create_socket();
if (me->socket == INVALID_SOCKET) {
return E_OGGPLAY_SOCKET_ERROR;
}
me->state = OTRS_SOCKET_CREATED;
}
/*
* If required, set the socket to non-blocking mode so we can
* timeout and return control to the caller.
*/
if (!block) {
if (!oggplay_set_socket_blocking_state(me->socket, 0)) {
return E_OGGPLAY_SOCKET_ERROR;
}
}
/*
* Extract the host name and the path from the location.
*/
oggplay_hostname_and_path(me->location, me->proxy, me->proxy_port,
&host, &port, &path);
/*
* Prepare the HTTP request header now, so we can free all our
* allocated memory before returning on any errors.
*/
snprintf(http_request_header, 1024,
"GET %s HTTP/1.0\n"
"Host: %s\n"
"User-Agent: AnnodexFirefoxPlugin/0.1\n"
"Accept: */*\n"
"Connection: Keep-Alive\n\n", path, host);
he = gethostbyname(host);
free(host);
free(path);
if (he == NULL) {
printf("Host not found\n");
return E_OGGPLAY_BAD_INPUT;
}
memcpy(&addr.sin_addr.s_addr, he->h_addr, he->h_length);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
/*
* Connect to the host.
*/
if (me->state == OTRS_SOCKET_CREATED) {
r = oggplay_connect_to_host(me->socket, (struct sockaddr *)&addr);
if (r != E_OGGPLAY_OK) {
return r;
}
me->state = OTRS_CONNECTED;
}
/*
* Send the HTTP request header.
*
* If this times out after sending some, but not all, of the request header,
* we'll end up sending the entire header string again. This is probably not
* the best idea, so we may want to rework it at some time...
*/
if (me->state == OTRS_CONNECTED) {
oggplay_set_socket_blocking_state(me->socket, 1);
pos = http_request_header;
len = strlen(http_request_header);
#ifdef WIN32
nbytes = send(me->socket, pos, len, 0);
#else
nbytes = write(me->socket, pos, len);
#endif
assert(nbytes == len);
if (nbytes < 0) {
return E_OGGPLAY_SOCKET_ERROR;
}
me->state = OTRS_SENT_HEADER;
}
/*
* Strip out the HTTP response by finding the first Ogg packet.
*/
if (me->state == OTRS_SENT_HEADER) {
int offset;
int found_http_response = 0;
if (me->buffer == NULL) {
me->buffer = (unsigned char*)malloc(TCP_READER_MAX_IN_MEMORY);
me->buffer_size = TCP_READER_MAX_IN_MEMORY;
me->amount_in_memory = 0;
}
while (1) {
char *dpos;
remaining = TCP_READER_MAX_IN_MEMORY - me->amount_in_memory - 1;
#ifdef WIN32
nbytes = recv(me->socket, (char*)(me->buffer + me->amount_in_memory),
remaining, 0);
#else
nbytes = read(me->socket, (char*)(me->buffer + me->amount_in_memory),
remaining);
#endif
if (nbytes < 0) {
return E_OGGPLAY_SOCKET_ERROR;
} else if (nbytes == 0) {
/*
* End-of-file is an error here, because we should at least be able
* to read a complete HTTP response header.
*/
return E_OGGPLAY_END_OF_FILE;
}
me->amount_in_memory += nbytes;
me->buffer[me->amount_in_memory] = '\0';
if (me->amount_in_memory < 15) {
continue;
}
if
(
(!found_http_response)
&&
strncmp((char *)me->buffer, "HTTP/1.1 200 OK", 15) != 0
&&
strncmp((char *)me->buffer, "HTTP/1.0 200 OK", 15) != 0
)
{
return E_OGGPLAY_BAD_INPUT;
} else {
found_http_response = 1;
}
dpos = strstr((char *)me->buffer, "X-Content-Duration:");
if (dpos != NULL) {
me->duration = (int)(strtod(dpos + 20, NULL) * 1000);
}
pos = strstr((char *)(me->buffer), "OggS");
if (pos != NULL) {
break;
}
}
offset = pos - (char *)(me->buffer);
memmove(me->buffer, pos, me->amount_in_memory - offset);
me->amount_in_memory -= offset;
me->backing_store = tmpfile();
fwrite(me->buffer, 1, me->amount_in_memory, me->backing_store);
me->current_position = 0;
me->stored_offset = me->amount_in_memory;
me->amount_in_memory = 0;
me->state = OTRS_HTTP_RESPONDED;
}
/*
* Read in enough data to fill the buffer.
*/
if (!block) {
oggplay_set_socket_blocking_state(me->socket, 0);
}
if (me->state == OTRS_HTTP_RESPONDED) {
remaining = TCP_READER_MAX_IN_MEMORY - me->amount_in_memory;
START_TIMEOUT(time_ref);
while (remaining > 0) {
#ifdef WIN32
nbytes = recv(me->socket, (char*)(me->buffer + me->amount_in_memory),
remaining, 0);
#else
nbytes = read(me->socket, me->buffer + me->amount_in_memory, remaining);
#endif
if (nbytes < 0) {
#ifdef WIN32
if CHECK_ERROR(EWOULDBLOCK) {
#else
if CHECK_ERROR(EAGAIN) {
#endif
RETURN_ON_TIMEOUT_OR_CONTINUE(time_ref);
}
return E_OGGPLAY_SOCKET_ERROR;
} else if (nbytes == 0) {
/*
* End-of-file is *not* an error here, it's just a really small file.
*/
break;
}
me->amount_in_memory += nbytes;
remaining -= nbytes;
}
fwrite(me->buffer, 1, me->amount_in_memory, me->backing_store);
me->stored_offset += me->amount_in_memory;
me->amount_in_memory = 0;
me->state = OTRS_INIT_COMPLETE;
}
/*
* Set the socket back to blocking mode.
*/
if (!oggplay_set_socket_blocking_state(me->socket, 1)) {
return E_OGGPLAY_SOCKET_ERROR;
}
return E_OGGPLAY_OK;
}
OggPlayErrorCode
oggplay_tcp_reader_destroy(OggPlayReader * opr) {
OggPlayTCPReader * me = (OggPlayTCPReader *)opr;
if (me->socket != INVALID_SOCKET) {
#ifdef WIN32
#ifdef HAVE_WINSOCK2
shutdown(me->socket, SD_BOTH);
#endif
closesocket(me->socket);
WSACleanup();
#else
close(me->socket);
#endif
}
free(me->buffer);
free(me->location);
if (me->backing_store != NULL) {
fclose(me->backing_store);
}
free(me);
return E_OGGPLAY_OK;
}
OggPlayErrorCode
grab_some_data(OggPlayTCPReader *me, int block) {
int remaining;
int r;
if (me->socket == INVALID_SOCKET) return E_OGGPLAY_OK;
/*
* see if we can grab some more data
* if we're not blocking, make sure there's some available data
*/
if (!block) {
struct timeval tv;
fd_set reads;
fd_set empty;
tv.tv_sec = 0;
tv.tv_usec = 0;
FD_ZERO(&reads);
FD_ZERO(&empty);
FD_SET(me->socket, &reads);
if (select(me->socket + 1, &reads, &empty, &empty, &tv) == 0) {
return E_OGGPLAY_OK;
}
}
remaining = me->buffer_size;
#ifdef WIN32
r = recv(me->socket, (char*)(me->buffer + me->amount_in_memory),
remaining, 0);
#else
r = read(me->socket, me->buffer + me->amount_in_memory, remaining);
#endif
if (!block && r <= 0) {
#ifdef WIN32
#ifdef HAVE_WINSOCK2
shutdown(me->socket, SD_BOTH);
#endif
closesocket(me->socket);
WSACleanup();
#else
close(me->socket);
#endif
me->socket = INVALID_SOCKET;
}
fwrite(me->buffer, 1, r, me->backing_store);
me->stored_offset += r;
return E_OGGPLAY_OK;
}
#define MIN(a,b) ((a)<(b)?(a):(b))
int
oggplay_tcp_reader_available(OggPlayReader * opr, ogg_int64_t current_bytes,
ogg_int64_t current_time) {
OggPlayTCPReader * me;
ogg_int64_t tpb = (current_time << 16) / current_bytes;
me = (OggPlayTCPReader *)opr;
if (me->socket == INVALID_SOCKET) {
return me->duration;
}
grab_some_data(me, 0);
if (me->duration > -1 && ((tpb * me->stored_offset) >> 16) > me->duration)
{
return me->duration;
}
return (int)((tpb * me->stored_offset) >> 16);
}
int
oggplay_tcp_reader_duration(OggPlayReader * opr) {
OggPlayTCPReader *me = (OggPlayTCPReader *)opr;
return me->duration;
}
static size_t
oggplay_tcp_reader_io_read(void * user_handle, void * buf, size_t n) {
OggPlayTCPReader * me = (OggPlayTCPReader *)user_handle;
int len;
grab_some_data(me, 0);
fseek(me->backing_store, me->current_position, SEEK_SET);
len = fread(buf, 1, n, me->backing_store);
if (len == 0) {
fseek(me->backing_store, 0, SEEK_END);
grab_some_data(me, 1);
fseek(me->backing_store, me->current_position, SEEK_SET);
len = fread(buf, 1, n, me->backing_store);
}
me->current_position += len;
fseek(me->backing_store, 0, SEEK_END);
return len;
}
int
oggplay_tcp_reader_finished_retrieving(OggPlayReader *opr) {
OggPlayTCPReader *me = (OggPlayTCPReader *)opr;
return (me->socket == INVALID_SOCKET);
}
static int
oggplay_tcp_reader_io_seek(void * user_handle, long offset, int whence) {
OggPlayTCPReader * me = (OggPlayTCPReader *)user_handle;
int r;
fseek(me->backing_store, me->current_position, SEEK_SET);
r = fseek(me->backing_store, offset, whence);
me->current_position = ftell(me->backing_store);
fseek(me->backing_store, 0, SEEK_END);
return r;
}
static long
oggplay_tcp_reader_io_tell(void * user_handle) {
OggPlayTCPReader * me = (OggPlayTCPReader *)user_handle;
return me->current_position;
}
OggPlayReader *
oggplay_tcp_reader_new(char *location, char *proxy, int proxy_port) {
OggPlayTCPReader * me = (OggPlayTCPReader *)malloc (sizeof (OggPlayTCPReader));
me->state = OTRS_UNINITIALISED;
me->socket = INVALID_SOCKET;
me->buffer = NULL;
me->buffer_size = 0;
me->current_position = 0;
me->location = strdup(location);
me->amount_in_memory = 0;
me->backing_store = NULL;
me->stored_offset = 0;
me->proxy = proxy;
me->proxy_port = proxy_port;
me->functions.initialise = &oggplay_tcp_reader_initialise;
me->functions.destroy = &oggplay_tcp_reader_destroy;
me->functions.seek = NULL;
me->functions.available = &oggplay_tcp_reader_available;
me->functions.duration = &oggplay_tcp_reader_duration;
me->functions.finished_retrieving = &oggplay_tcp_reader_finished_retrieving;
me->functions.io_read = &oggplay_tcp_reader_io_read;
me->functions.io_seek = &oggplay_tcp_reader_io_seek;
me->functions.io_tell = &oggplay_tcp_reader_io_tell;
return (OggPlayReader *)me;
}

View File

@ -0,0 +1,86 @@
/*
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.
*/
/*
* oggplay_tcp_reader.h
*
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
*/
#ifndef __OGGPLAY_FILE_READER_H__
#define __OGGPLAY_FILE_READER_H__
#include <stdio.h>
/* we'll fill to the MAX_IN_MEMORY line, then write out to the
* WRITE_THRESHOLD line
*/
#define TCP_READER_MAX_IN_MEMORY 128*1024
#define TCP_READER_WRITE_THRESHOLD 64*1024
typedef enum {
TCP_READER_FROM_MEMORY,
TCP_READER_FROM_FILE
} dataLocation;
typedef enum {
OTRS_UNINITIALISED,
OTRS_SOCKET_CREATED,
OTRS_CONNECTED,
OTRS_SENT_HEADER,
OTRS_HTTP_RESPONDED,
OTRS_INIT_COMPLETE
} OPTCPReaderState;
typedef struct {
OggPlayReader functions;
OPTCPReaderState state;
#ifdef _WIN32
SOCKET socket;
#else
int socket;
#endif
unsigned char * buffer;
int buffer_size;
int current_position;
char * location;
char * proxy;
int proxy_port;
int amount_in_memory;
FILE * backing_store;
int stored_offset;
dataLocation mode;
int duration;
} OggPlayTCPReader;
#endif

View File

@ -0,0 +1,67 @@
/*
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.
*/
/*
* oggplay_tools.c
*
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
*/
#include "oggplay_private.h"
#include <string.h>
ogg_int64_t
oggplay_sys_time_in_ms(void) {
#ifdef WIN32
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
return ((ogg_int64_t)ft.dwHighDateTime << 32 | ft.dwLowDateTime) / 10000;
#else
struct timeval tv;
gettimeofday(&tv, NULL);
return (ogg_int64_t)tv.tv_sec * 1000 + (ogg_int64_t)tv.tv_usec / 1000;
#endif
}
void
oggplay_millisleep(long ms) {
#ifdef WIN32
Sleep(ms);
#else
struct timespec ts = {0, (ogg_int64_t)ms * 1000000LL};
nanosleep(&ts, NULL);
#endif
}

View File

@ -0,0 +1,450 @@
/*
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.
*/
/*
* yuv2rgb.c
*
* YUV->RGB function, using platform-specific optimisations where possible.
*
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
* Marcin Lubonski
*/
#include "oggplay_private.h"
/*
* YUV -> RGB conversion
* R = Y + 1.140V
* G = Y - 0.395U - 0.581V
* B = Y + 2.032U
*
* RGB -> YUV conversion
* Y = 0.299 R + 0.587 G + 0.114 B
* U = 0.147 R - 0.289 G + 0.436 B
* V = 0.615 R - 0.515 G - 0.100 B
*/
#if defined(__MMX__) || defined(__SSE__) || defined(__SSE2__) || defined(__SSE3__)
#if defined(WIN32)
#define restrict
#include <emmintrin.h>
#else
#include <xmmintrin.h>
#ifndef restrict
#define restrict __restrict__
#endif
#endif
/* YUV -> RGB Intel MMX implementation */
void oggplay_yuv2rgb(OggPlayYUVChannels * yuv, OggPlayRGBChannels * rgb) {
int i;
unsigned char * restrict ptry;
unsigned char * restrict ptru;
unsigned char * restrict ptrv;
register __m64 *y, *o;
register __m64 zero, ut, vt, imm, imm2;
register __m64 r, g, b;
register __m64 tmp, tmp2;
zero = _mm_setzero_si64();
ptry = yuv->ptry;
ptru = yuv->ptru;
ptrv = yuv->ptrv;
for (i = 0; i < yuv->y_height; i++) {
int j;
o = (__m64*)rgb->ptro;
rgb->ptro += rgb->rgb_width * 4;
for (j = 0; j < yuv->y_width; j += 8) {
y = (__m64*)&ptry[j];
ut = _m_from_int(*(int *)(ptru + j/2));
vt = _m_from_int(*(int *)(ptrv + j/2));
//ut = _m_from_int(0);
//vt = _m_from_int(0);
ut = _m_punpcklbw(ut, zero);
vt = _m_punpcklbw(vt, zero);
/* subtract 128 from u and v */
imm = _mm_set1_pi16(128);
ut = _m_psubw(ut, imm);
vt = _m_psubw(vt, imm);
/* transfer and multiply into r, g, b registers */
imm = _mm_set1_pi16(-51);
g = _m_pmullw(ut, imm);
imm = _mm_set1_pi16(130);
b = _m_pmullw(ut, imm);
imm = _mm_set1_pi16(146);
r = _m_pmullw(vt, imm);
imm = _mm_set1_pi16(-74);
imm = _m_pmullw(vt, imm);
g = _m_paddsw(g, imm);
/* add 64 to r, g and b registers */
imm = _mm_set1_pi16(64);
r = _m_paddsw(r, imm);
g = _m_paddsw(g, imm);
imm = _mm_set1_pi16(32);
b = _m_paddsw(b, imm);
/* shift r, g and b registers to the right */
r = _m_psrawi(r, 7);
g = _m_psrawi(g, 7);
b = _m_psrawi(b, 6);
/* subtract 16 from r, g and b registers */
imm = _mm_set1_pi16(16);
r = _m_psubsw(r, imm);
g = _m_psubsw(g, imm);
b = _m_psubsw(b, imm);
y = (__m64*)&ptry[j];
/* duplicate u and v channels and add y
* each of r,g, b in the form [s1(16), s2(16), s3(16), s4(16)]
* first interleave, so tmp is [s1(16), s1(16), s2(16), s2(16)]
* then add y, then interleave again
* then pack with saturation, to get the desired output of
* [s1(8), s1(8), s2(8), s2(8), s3(8), s3(8), s4(8), s4(8)]
*/
tmp = _m_punpckhwd(r, r);
imm = _m_punpckhbw(*y, zero);
//printf("tmp: %llx imm: %llx\n", tmp, imm);
tmp = _m_paddsw(tmp, imm);
tmp2 = _m_punpcklwd(r, r);
imm2 = _m_punpcklbw(*y, zero);
tmp2 = _m_paddsw(tmp2, imm2);
r = _m_packuswb(tmp2, tmp);
tmp = _m_punpckhwd(g, g);
tmp2 = _m_punpcklwd(g, g);
tmp = _m_paddsw(tmp, imm);
tmp2 = _m_paddsw(tmp2, imm2);
g = _m_packuswb(tmp2, tmp);
tmp = _m_punpckhwd(b, b);
tmp2 = _m_punpcklwd(b, b);
tmp = _m_paddsw(tmp, imm);
tmp2 = _m_paddsw(tmp2, imm2);
b = _m_packuswb(tmp2, tmp);
//printf("duplicated r g and b: %llx %llx %llx\n", r, g, b);
/* now we have 8 8-bit r, g and b samples. we want these to be packed
* into 32-bit values.
*/
//r = _m_from_int(0);
//b = _m_from_int(0);
imm = _mm_set1_pi32(0xFFFFFFFF);
tmp = _m_punpcklbw(r, b);
tmp2 = _m_punpcklbw(g, imm);
*o++ = _m_punpcklbw(tmp, tmp2);
*o++ = _m_punpckhbw(tmp, tmp2);
//printf("tmp, tmp2, write1, write2: %llx %llx %llx %llx\n", tmp, tmp2,
// _m_punpcklbw(tmp, tmp2), _m_punpckhbw(tmp, tmp2));
tmp = _m_punpckhbw(r, b);
tmp2 = _m_punpckhbw(g, imm);
*o++ = _m_punpcklbw(tmp, tmp2);
*o++ = _m_punpckhbw(tmp, tmp2);
//exit(1);
}
if (i & 0x1) {
ptru += yuv->uv_width;
ptrv += yuv->uv_width;
}
ptry += yuv->y_width;
}
_m_empty();
}
/* YUV -> BGR Intel MMX implementation */
void oggplay_yuv2bgr(OggPlayYUVChannels * yuv, OggPlayRGBChannels * rgb) {
int i;
unsigned char * restrict ptry;
unsigned char * restrict ptru;
unsigned char * restrict ptrv;
register __m64 *y, *o;
register __m64 zero, ut, vt, imm, imm2;
register __m64 r, g, b;
register __m64 tmp, tmp2;
zero = _mm_setzero_si64();
ptry = yuv->ptry;
ptru = yuv->ptru;
ptrv = yuv->ptrv;
for (i = 0; i < yuv->y_height; i++) {
int j;
o = (__m64*)rgb->ptro;
rgb->ptro += rgb->rgb_width * 4;
for (j = 0; j < yuv->y_width; j += 8) {
y = (__m64*)&ptry[j];
ut = _m_from_int(*(int *)(ptru + j/2));
vt = _m_from_int(*(int *)(ptrv + j/2));
//ut = _m_from_int(0);
//vt = _m_from_int(0);
ut = _m_punpcklbw(ut, zero);
vt = _m_punpcklbw(vt, zero);
/* subtract 128 from u and v */
imm = _mm_set1_pi16(128);
ut = _m_psubw(ut, imm);
vt = _m_psubw(vt, imm);
/* transfer and multiply into r, g, b registers */
imm = _mm_set1_pi16(-51);
g = _m_pmullw(ut, imm);
imm = _mm_set1_pi16(130);
b = _m_pmullw(ut, imm);
imm = _mm_set1_pi16(146);
r = _m_pmullw(vt, imm);
imm = _mm_set1_pi16(-74);
imm = _m_pmullw(vt, imm);
g = _m_paddsw(g, imm);
/* add 64 to r, g and b registers */
imm = _mm_set1_pi16(64);
r = _m_paddsw(r, imm);
g = _m_paddsw(g, imm);
imm = _mm_set1_pi16(32);
b = _m_paddsw(b, imm);
/* shift r, g and b registers to the right */
r = _m_psrawi(r, 7);
g = _m_psrawi(g, 7);
b = _m_psrawi(b, 6);
/* subtract 16 from r, g and b registers */
imm = _mm_set1_pi16(16);
r = _m_psubsw(r, imm);
g = _m_psubsw(g, imm);
b = _m_psubsw(b, imm);
y = (__m64*)&ptry[j];
/* duplicate u and v channels and add y
* each of r,g, b in the form [s1(16), s2(16), s3(16), s4(16)]
* first interleave, so tmp is [s1(16), s1(16), s2(16), s2(16)]
* then add y, then interleave again
* then pack with saturation, to get the desired output of
* [s1(8), s1(8), s2(8), s2(8), s3(8), s3(8), s4(8), s4(8)]
*/
tmp = _m_punpckhwd(r, r);
imm = _m_punpckhbw(*y, zero);
//printf("tmp: %llx imm: %llx\n", tmp, imm);
tmp = _m_paddsw(tmp, imm);
tmp2 = _m_punpcklwd(r, r);
imm2 = _m_punpcklbw(*y, zero);
tmp2 = _m_paddsw(tmp2, imm2);
r = _m_packuswb(tmp2, tmp);
tmp = _m_punpckhwd(g, g);
tmp2 = _m_punpcklwd(g, g);
tmp = _m_paddsw(tmp, imm);
tmp2 = _m_paddsw(tmp2, imm2);
g = _m_packuswb(tmp2, tmp);
tmp = _m_punpckhwd(b, b);
tmp2 = _m_punpcklwd(b, b);
tmp = _m_paddsw(tmp, imm);
tmp2 = _m_paddsw(tmp2, imm2);
b = _m_packuswb(tmp2, tmp);
//printf("duplicated r g and b: %llx %llx %llx\n", r, g, b);
/* now we have 8 8-bit r, g and b samples. we want these to be packed
* into 32-bit values.
*/
//r = _m_from_int(0);
//b = _m_from_int(0);
imm = _mm_set1_pi32(0xFFFFFFFF);
tmp = _m_punpcklbw(b, r);
tmp2 = _m_punpcklbw(g, imm);
*o++ = _m_punpcklbw(tmp, tmp2);
*o++ = _m_punpckhbw(tmp, tmp2);
//printf("tmp, tmp2, write1, write2: %llx %llx %llx %llx\n", tmp, tmp2,
// _m_punpcklbw(tmp, tmp2), _m_punpckhbw(tmp, tmp2));
tmp = _m_punpckhbw(b, r);
tmp2 = _m_punpckhbw(g, imm);
*o++ = _m_punpcklbw(tmp, tmp2);
*o++ = _m_punpckhbw(tmp, tmp2);
//exit(1);
}
if (i & 0x1) {
ptru += yuv->uv_width;
ptrv += yuv->uv_width;
}
ptry += yuv->y_width;
}
_m_empty();
}
#elif defined(__xxAPPLExx__)
/*
* TODO: implement the SIMD method above using Apple's AltiVec code;
* for now, we'll use the vanilla implementation for Macs.
*
* Also, there's probably a better preprocessor macro for detecting
* the presence of AltiVec than __APPLE__.
*/
/* Macintosh AltiVec implementation */
void oggplay_yuv2rgb(OggPlayYUVChannels * yuv, OggPlayRGBChannels * rgb) {
}
#else
#define CLAMP(v) ((v) > 255 ? 255 : (v) < 0 ? 0 : (v))
/* Vanilla implementation if YUV->RGB conversion */
void oggplay_yuv2rgb(OggPlayYUVChannels * yuv, OggPlayRGBChannels * rgb) {
unsigned char * ptry = yuv->ptry;
unsigned char * ptru = yuv->ptru;
unsigned char * ptrv = yuv->ptrv;
unsigned char * ptro = rgb->ptro;
unsigned char * ptro2;
int i, j;
for (i = 0; i < yuv->y_height; i++) {
ptro2 = ptro;
for (j = 0; j < yuv->y_width; j += 2) {
short pr, pg, pb;
short r, g, b;
//pr = ((128 + (ptrv[j/2] - 128) * 292) >> 8) - 16; /* 1.14 * 256 */
pr = (-41344 + ptrv[j/2] * 292) >> 8;
//pg = ((128 - (ptru[j/2] - 128) * 101 - (ptrv[j/2] - 128) * 149) >> 8)-16;
// /* 0.395 & 0.581 */
pg = (28032 - ptru[j/2] * 101 - ptrv[j/2] * 149) >> 8;
//pb = ((128 + (ptru[j/2] - 128) * 520) >> 8) - 16; /* 2.032 */
pb = (-70528 + ptru[j/2] * 520) >> 8;
r = ptry[j] + pr;
g = ptry[j] + pg;
b = ptry[j] + pb;
*ptro2++ = CLAMP(r);
*ptro2++ = CLAMP(g);
*ptro2++ = CLAMP(b);
*ptro2++ = 255;
r = ptry[j + 1] + pr;
g = ptry[j + 1] + pg;
b = ptry[j + 1] + pb;
*ptro2++ = CLAMP(r);
*ptro2++ = CLAMP(g);
*ptro2++ = CLAMP(b);
*ptro2++ = 255;
}
ptry += yuv->y_width;
if (i & 1) {
ptru += yuv->uv_width;
ptrv += yuv->uv_width;
}
ptro += rgb->rgb_width * 4;
}
}
/* Vanilla implementation of YUV->BGR conversion*/
void oggplay_yuv2bgr(OggPlayYUVChannels * yuv, OggPlayRGBChannels * rgb) {
unsigned char * ptry = yuv->ptry;
unsigned char * ptru = yuv->ptru;
unsigned char * ptrv = yuv->ptrv;
unsigned char * ptro = rgb->ptro;
unsigned char * ptro2;
int i, j;
for (i = 0; i < yuv->y_height; i++) {
ptro2 = ptro;
for (j = 0; j < yuv->y_width; j += 2) {
short pr, pg, pb;
short r, g, b;
//pr = ((128 + (ptrv[j/2] - 128) * 292) >> 8) - 16; /* 1.14 * 256 */
pr = (-41344 + ptrv[j/2] * 292) >> 8;
//pg = ((128 - (ptru[j/2] - 128) * 101 - (ptrv[j/2] - 128) * 149) >> 8)-16;
// /* 0.395 & 0.581 */
pg = (28032 - ptru[j/2] * 101 - ptrv[j/2] * 149) >> 8;
//pb = ((128 + (ptru[j/2] - 128) * 520) >> 8) - 16; /* 2.032 */
pb = (-70528 + ptru[j/2] * 520) >> 8;
r = ptry[j] + pr;
g = ptry[j] + pg;
b = ptry[j] + pb;
*ptro2++ = CLAMP(b);
*ptro2++ = CLAMP(g);
*ptro2++ = CLAMP(r);
*ptro2++ = 255;
r = ptry[j + 1] + pr;
g = ptry[j + 1] + pg;
b = ptry[j + 1] + pb;
*ptro2++ = CLAMP(b);
*ptro2++ = CLAMP(g);
*ptro2++ = CLAMP(r);
*ptro2++ = 255;
}
ptry += yuv->y_width;
if (i & 1) {
ptru += yuv->uv_width;
ptrv += yuv->uv_width;
}
ptro += rgb->rgb_width * 4;
}
}
#endif

View File

@ -0,0 +1,97 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Initial Developer of the Original Code is
* CSIRO
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s): Shane Stephens, Michael Martin
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef _STD_SEMAPHORE_H
#define _STD_SEMAPHORE_H
#if defined(linux)
#include <semaphore.h>
#define SEM_CREATE(p,s) sem_init(&(p), 1, s)
#define SEM_SIGNAL(p) sem_post(&(p))
#define SEM_WAIT(p) sem_wait(&(p))
#define SEM_CLOSE(p) sem_destroy(&(p))
typedef sem_t semaphore;
#elif defined(WIN32)
#include <windows.h>
#define SEM_CREATE(p,s) p = CreateSemaphore(NULL, (long)(s), (long)(s), NULL)
#define SEM_SIGNAL(p) ReleaseSemaphore(p, 1, NULL)
#define SEM_WAIT(p) WaitForSingleObject(p, INFINITE)
#define SEM_TEST(p,s) p = WaitForSingleObject(s, 0)
#define SEM_CLOSE(p) CloseHandle(p)
typedef HANDLE semaphore;
#elif defined(__APPLE__)
#include <Multiprocessing.h>
#define SEM_CREATE(p,s) MPCreateSemaphore(s, s, &(p))
#define SEM_SIGNAL(p) MPSignalSemaphore(p)
#define SEM_WAIT(p) MPWaitOnSemaphore(p, kDurationForever)
#define SEM_CLOSE(p) MPDeleteSemaphore(p)
typedef MPSemaphoreID semaphore;
#endif
#endif
/*
#if defined(XP_UX)
sem_init(&(pointers->sem), 1, LIBOGGPLAY_BUFFER_SIZE);
#elif defined(XP_WIN)
pointers->sem = CreateSemaphore(NULL, (long)LIBOGGPLAY_BUFFER_SIZE,
(long)LIBOGGPLAY_BUFFER_SIZE, NULL);
#elif defined(XP_MACOSX)
MPCreateSemaphore(LIBOGGPLAY_BUFFER_SIZE, LIBOGGPLAY_BUFFER_SIZE,
&(pointers->sem));
#endif
#if defined(XP_UX)
sem_post(&(ptrs->sem));
#elif defined(XP_WIN)
ReleaseSemaphore(ptrs->sem, 1, NULL);
#elif defined(XP_MACOSX)
MPSignalSemaphore(ptrs->sem);
#endif
#if defined(XP_UX)
sem_wait(&(pointers->sem));
#elif defined(XP_WIN)
WaitForSingleObject(pointers->sem, INFINITE);
#elif defined(XP_MACOSX)
MPWaitOnSemaphore(pointers->sem, kDurationForever);
#endif
#if defined(XP_UX)
sem_destroy(&(pointers->sem));
#elif defined(XP_WIN)
CloseHandle(pointers->sem);
#elif defined(XP_MACOSX)
MPDeleteSemaphore(pointers->sem);
#endif
*/

View File

@ -0,0 +1,34 @@
# Usage: ./update.sh <oggplay_src_directory>
#
# Copies the needed files from a directory containing the original
# liboggplay source that we need for the Mozilla HTML5 media support.
sed s/\#define\ __SSE2__\ 1//g $1/config.h >./src/liboggplay/config.h
cp $1/include/oggplay/oggplay_callback_info.h ./include/oggplay/oggplay_callback_info.h
cp $1/include/oggplay/oggplay_query.h ./include/oggplay/oggplay_query.h
cp $1/include/oggplay/oggplay_seek.h ./include/oggplay/oggplay_seek.h
cp $1/include/oggplay/oggplay_enums.h ./include/oggplay/oggplay_enums.h
cp $1/include/oggplay/oggplay_tools.h ./include/oggplay/oggplay_tools.h
cp $1/win32/config_win32.h ./include/oggplay/config_win32.h
cp $1/include/oggplay/oggplay.h ./include/oggplay/oggplay.h
cp $1/include/oggplay/oggplay_reader.h ./include/oggplay/oggplay_reader.h
cp $1/README ./README
cp $1/src/liboggplay/oggplay_buffer.c ./src/liboggplay/oggplay_buffer.c
cp $1/src/liboggplay/oggplay_tcp_reader.h ./src/liboggplay/oggplay_tcp_reader.h
cp $1/src/liboggplay/oggplay_callback_info.c ./src/liboggplay/oggplay_callback_info.c
cp $1/src/liboggplay/oggplay_tools.c ./src/liboggplay/oggplay_tools.c
cp $1/src/liboggplay/oggplay_yuv2rgb.c ./src/liboggplay/oggplay_yuv2rgb.c
cp $1/src/liboggplay/oggplay_seek.c ./src/liboggplay/oggplay_seek.c
cp $1/src/liboggplay/oggplay_buffer.h ./src/liboggplay/oggplay_buffer.h
cp $1/src/liboggplay/oggplay_file_reader.c ./src/liboggplay/oggplay_file_reader.c
cp $1/src/liboggplay/oggplay_data.h ./src/liboggplay/oggplay_data.h
cp $1/src/liboggplay/oggplay_callback.c ./src/liboggplay/oggplay_callback.c
cp $1/src/liboggplay/oggplay_file_reader.h ./src/liboggplay/oggplay_file_reader.h
cp $1/src/liboggplay/std_semaphore.h ./src/liboggplay/std_semaphore.h
cp $1/src/liboggplay/oggplay.c ./src/liboggplay/oggplay.c
cp $1/src/liboggplay/oggplay_callback.h ./src/liboggplay/oggplay_callback.h
cp $1/src/liboggplay/oggplay_tcp_reader.c ./src/liboggplay/oggplay_tcp_reader.c
cp $1/src/liboggplay/oggplay_query.c ./src/liboggplay/oggplay_query.c
sed s/\#include\ \"config_win32.h\"//g $1/src/liboggplay/oggplay_private.h >./src/liboggplay/oggplay_private.h1
sed s/\#include\ \<config.h\>/\#ifdef\ WIN32\\n\#include\ \"config_win32.h\"\\n\#else\\n\#include\ \<config.h\>\\n\#endif/g ./src/liboggplay/oggplay_private.h1 >./src/liboggplay/oggplay_private.h
rm ./src/liboggplay/oggplay_private.h1
sed s/\#ifdef\ HAVE_INTTYPES_H/\#if\ HAVE_INTTYPES_H/g $1/src/liboggplay/oggplay_data.c >./src/liboggplay/oggplay_data.c