mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-05 05:30:29 +00:00
Bug 422538. Import liboggplay
This commit is contained in:
parent
c38cc109bc
commit
813a91410f
51
modules/liboggplay/Makefile.in
Normal file
51
modules/liboggplay/Makefile.in
Normal 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
55
modules/liboggplay/README
Normal 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
|
||||
|
||||
|
9
modules/liboggplay/README_MOZILLA
Normal file
9
modules/liboggplay/README_MOZILLA
Normal 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.
|
47
modules/liboggplay/include/Makefile.in
Normal file
47
modules/liboggplay/include/Makefile.in
Normal 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
|
57
modules/liboggplay/include/oggplay/Makefile.in
Normal file
57
modules/liboggplay/include/oggplay/Makefile.in
Normal 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
|
75
modules/liboggplay/include/oggplay/config_win32.h
Normal file
75
modules/liboggplay/include/oggplay/config_win32.h
Normal 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 */
|
147
modules/liboggplay/include/oggplay/oggplay.h
Normal file
147
modules/liboggplay/include/oggplay/oggplay.h
Normal 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
|
88
modules/liboggplay/include/oggplay/oggplay_callback_info.h
Normal file
88
modules/liboggplay/include/oggplay/oggplay_callback_info.h
Normal 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
|
86
modules/liboggplay/include/oggplay/oggplay_enums.h
Normal file
86
modules/liboggplay/include/oggplay/oggplay_enums.h
Normal 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
|
59
modules/liboggplay/include/oggplay/oggplay_query.h
Normal file
59
modules/liboggplay/include/oggplay/oggplay_query.h
Normal 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
|
72
modules/liboggplay/include/oggplay/oggplay_reader.h
Normal file
72
modules/liboggplay/include/oggplay/oggplay_reader.h
Normal 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
|
45
modules/liboggplay/include/oggplay/oggplay_seek.h
Normal file
45
modules/liboggplay/include/oggplay/oggplay_seek.h
Normal 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
|
91
modules/liboggplay/include/oggplay/oggplay_tools.h
Normal file
91
modules/liboggplay/include/oggplay/oggplay_tools.h
Normal 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__*/
|
||||
|
47
modules/liboggplay/src/Makefile.in
Normal file
47
modules/liboggplay/src/Makefile.in
Normal 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
|
69
modules/liboggplay/src/liboggplay/Makefile.in
Normal file
69
modules/liboggplay/src/liboggplay/Makefile.in
Normal 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
|
87
modules/liboggplay/src/liboggplay/config.h
Normal file
87
modules/liboggplay/src/liboggplay/config.h
Normal 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 */
|
661
modules/liboggplay/src/liboggplay/oggplay.c
Normal file
661
modules/liboggplay/src/liboggplay/oggplay.c
Normal 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);
|
||||
|
||||
}
|
347
modules/liboggplay/src/liboggplay/oggplay_buffer.c
Normal file
347
modules/liboggplay/src/liboggplay/oggplay_buffer.c
Normal 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;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
57
modules/liboggplay/src/liboggplay/oggplay_buffer.h
Normal file
57
modules/liboggplay/src/liboggplay/oggplay_buffer.h
Normal 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
|
591
modules/liboggplay/src/liboggplay/oggplay_callback.c
Normal file
591
modules/liboggplay/src/liboggplay/oggplay_callback.c
Normal 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;
|
||||
|
||||
}
|
59
modules/liboggplay/src/liboggplay/oggplay_callback.h
Normal file
59
modules/liboggplay/src/liboggplay/oggplay_callback.h
Normal 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
|
434
modules/liboggplay/src/liboggplay/oggplay_callback_info.c
Normal file
434
modules/liboggplay/src/liboggplay/oggplay_callback_info.c
Normal 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;
|
||||
|
||||
}
|
||||
|
396
modules/liboggplay/src/liboggplay/oggplay_data.c
Normal file
396
modules/liboggplay/src/liboggplay/oggplay_data.c
Normal 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
|
||||
|
70
modules/liboggplay/src/liboggplay/oggplay_data.h
Normal file
70
modules/liboggplay/src/liboggplay/oggplay_data.h
Normal 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
|
155
modules/liboggplay/src/liboggplay/oggplay_file_reader.c
Normal file
155
modules/liboggplay/src/liboggplay/oggplay_file_reader.c
Normal 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;
|
||||
|
||||
}
|
56
modules/liboggplay/src/liboggplay/oggplay_file_reader.h
Normal file
56
modules/liboggplay/src/liboggplay/oggplay_file_reader.h
Normal 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
|
283
modules/liboggplay/src/liboggplay/oggplay_private.h
Normal file
283
modules/liboggplay/src/liboggplay/oggplay_private.h
Normal 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
|
202
modules/liboggplay/src/liboggplay/oggplay_query.c
Normal file
202
modules/liboggplay/src/liboggplay/oggplay_query.c
Normal 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;
|
||||
}
|
155
modules/liboggplay/src/liboggplay/oggplay_seek.c
Normal file
155
modules/liboggplay/src/liboggplay/oggplay_seek.c
Normal 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);
|
||||
}
|
||||
}
|
688
modules/liboggplay/src/liboggplay/oggplay_tcp_reader.c
Normal file
688
modules/liboggplay/src/liboggplay/oggplay_tcp_reader.c
Normal 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;
|
||||
}
|
||||
|
||||
|
86
modules/liboggplay/src/liboggplay/oggplay_tcp_reader.h
Normal file
86
modules/liboggplay/src/liboggplay/oggplay_tcp_reader.h
Normal 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
|
67
modules/liboggplay/src/liboggplay/oggplay_tools.c
Normal file
67
modules/liboggplay/src/liboggplay/oggplay_tools.c
Normal 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
|
||||
}
|
||||
|
||||
|
450
modules/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
Normal file
450
modules/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
Normal 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
|
97
modules/liboggplay/src/liboggplay/std_semaphore.h
Normal file
97
modules/liboggplay/src/liboggplay/std_semaphore.h
Normal 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
|
||||
*/
|
||||
|
34
modules/liboggplay/update.sh
Normal file
34
modules/liboggplay/update.sh
Normal 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
|
Loading…
x
Reference in New Issue
Block a user