Bug 556455 - Remove liboggz, liboggplay, libfishsound from video decoder. r=doublec

This commit is contained in:
Chris Pearce 2010-04-27 20:53:48 +12:00
Родитель 0f8dbb7df1
Коммит 59037fa6fb
177 изменённых файлов: 4 добавлений и 32620 удалений

Просмотреть файл

@ -47,13 +47,11 @@ LIBXUL_LIBRARY = 1
EXPORTS += \
nsChannelReader.h \
nsOggDecoder.h \
nsOggCodecState.h \
$(NULL)
CPPSRCS = \
nsChannelReader.cpp \
nsOggDecoder.cpp \
nsOggCodecState.cpp \
nsOggReader.cpp \

Просмотреть файл

@ -1,156 +0,0 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** 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 ***** */
#include "nsAString.h"
#include "nsThreadUtils.h"
#include "nsNetUtil.h"
#include "prlog.h"
#include "nsOggDecoder.h"
#include "nsChannelReader.h"
#include "nsIScriptSecurityManager.h"
OggPlayErrorCode nsChannelReader::initialise(int aBlock)
{
return E_OGGPLAY_OK;
}
OggPlayErrorCode nsChannelReader::destroy()
{
// We don't have to do anything here, the decoder will clean stuff up
return E_OGGPLAY_OK;
}
void nsChannelReader::SetLastFrameTime(PRInt64 aTime)
{
mLastFrameTime = aTime;
}
size_t nsChannelReader::io_read(char* aBuffer, size_t aCount)
{
PRUint32 bytes = 0;
nsresult rv = mStream->Read(aBuffer, aCount, &bytes);
if (!NS_SUCCEEDED(rv)) {
return static_cast<size_t>(OGGZ_ERR_SYSTEM);
}
nsOggDecoder* decoder =
static_cast<nsOggDecoder*>(mStream->Decoder());
decoder->NotifyBytesConsumed(bytes);
return bytes;
}
int nsChannelReader::io_seek(long aOffset, int aWhence)
{
nsresult rv = mStream->Seek(aWhence, aOffset);
if (NS_SUCCEEDED(rv))
return aOffset;
return OGGZ_STOP_ERR;
}
long nsChannelReader::io_tell()
{
return mStream->Tell();
}
ogg_int64_t nsChannelReader::duration()
{
return mLastFrameTime;
}
static OggPlayErrorCode oggplay_channel_reader_initialise(OggPlayReader* aReader, int aBlock)
{
nsChannelReader * me = static_cast<nsChannelReader*>(aReader);
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
}
return me->initialise(aBlock);
}
static OggPlayErrorCode oggplay_channel_reader_destroy(OggPlayReader* aReader)
{
nsChannelReader* me = static_cast<nsChannelReader*>(aReader);
return me->destroy();
}
static size_t oggplay_channel_reader_io_read(void* aReader, void* aBuffer, size_t aCount)
{
nsChannelReader* me = static_cast<nsChannelReader*>(aReader);
return me->io_read(static_cast<char*>(aBuffer), aCount);
}
static int oggplay_channel_reader_io_seek(void* aReader, long aOffset, int aWhence)
{
nsChannelReader* me = static_cast<nsChannelReader*>(aReader);
return me->io_seek(aOffset, aWhence);
}
static long oggplay_channel_reader_io_tell(void* aReader)
{
nsChannelReader* me = static_cast<nsChannelReader*>(aReader);
return me->io_tell();
}
static ogg_int64_t oggplay_channel_reader_duration(struct _OggPlayReader *aReader)
{
nsChannelReader* me = static_cast<nsChannelReader*>(aReader);
return me->duration();
}
void nsChannelReader::Init(nsMediaStream* aStream)
{
mStream = aStream;
}
nsChannelReader::~nsChannelReader()
{
MOZ_COUNT_DTOR(nsChannelReader);
}
nsChannelReader::nsChannelReader() :
mLastFrameTime(-1)
{
MOZ_COUNT_CTOR(nsChannelReader);
OggPlayReader* reader = this;
reader->initialise = &oggplay_channel_reader_initialise;
reader->destroy = &oggplay_channel_reader_destroy;
reader->seek = 0;
reader->io_read = &oggplay_channel_reader_io_read;
reader->io_seek = &oggplay_channel_reader_io_seek;
reader->io_tell = &oggplay_channel_reader_io_tell;
reader->duration = &oggplay_channel_reader_duration;
}

Просмотреть файл

@ -1,87 +0,0 @@
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* ***** 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 ***** */
#if !defined(nsChannelReader_h_)
#define nsChannelReader_h_
#include "nsAutoPtr.h"
#include "nsMediaStream.h"
#include "oggplay/oggplay.h"
class nsIURI;
class nsIChannel;
class nsIStreamListener;
class nsMediaDecoder;
class nsChannelReader : public OggPlayReader
{
public:
nsChannelReader();
~nsChannelReader();
/**
* Initialize the reader with the media stream.
* This takes ownership of aStream.
*/
void Init(nsMediaStream* aStream);
nsMediaStream* Stream() { return mStream; }
// Set the time of the last frame. This is returned in duration() to
// liboggplay. Call with decoder lock obtained so that liboggplay cannot
// call duration() on the decoder thread while it is changing.
void SetLastFrameTime(PRInt64 aTime);
nsIPrincipal* GetCurrentPrincipal();
// Implementation of OggPlay Reader API.
OggPlayErrorCode initialise(int aBlock);
OggPlayErrorCode destroy();
size_t io_read(char* aBuffer, size_t aCount);
int io_seek(long aOffset, int aWhence);
long io_tell();
ogg_int64_t duration();
public:
nsAutoPtr<nsMediaStream> mStream;
// Timestamp of the end of the last frame in the media resource.
// -1 if not known.
PRInt64 mLastFrameTime;
};
#endif

Просмотреть файл

@ -43,7 +43,6 @@
#include "nsBuiltinDecoder.h"
#include "nsOggReader.h"
#include "nsOggPlayStateMachine.h"
#include "oggplay/oggplay.h"
#include "mozilla/mozalloc.h"
#include "VideoUtils.h"

Просмотреть файл

@ -246,10 +246,8 @@ public:
/**
* This makes a copy of the data buffers.
* XXX Eventually we will change this to not make a copy of the data,
* but we can't do that until we have tighter control of nsOggDecoder's
* buffer management (i.e. not going through liboggplay). Right now
* it doesn't matter because the BasicLayer implementation does YCbCr
* conversion here anyway.
* Right now it doesn't matter because the BasicLayer implementation
* does YCbCr conversion here anyway.
*/
virtual void SetData(const Data& aData) = 0;

Просмотреть файл

@ -118,10 +118,7 @@ endif
ifdef MOZ_OGG
SHARED_LIBRARY_LIBS += \
$(DEPTH)/media/libfishsound/src/libfishsound/$(LIB_PREFIX)fishsound.$(LIB_SUFFIX) \
$(DEPTH)/media/libogg/src/$(LIB_PREFIX)ogg.$(LIB_SUFFIX) \
$(DEPTH)/media/liboggplay/src/liboggplay/$(LIB_PREFIX)oggplay.$(LIB_SUFFIX) \
$(DEPTH)/media/liboggz/src/liboggz/$(LIB_PREFIX)oggz.$(LIB_SUFFIX) \
$(DEPTH)/media/libtheora/lib/$(LIB_PREFIX)theora.$(LIB_SUFFIX) \
$(DEPTH)/media/libvorbis/lib/$(LIB_PREFIX)vorbis.$(LIB_SUFFIX) \
$(DEPTH)/content/media/ogg/$(LIB_PREFIX)gkconogg_s.$(LIB_SUFFIX) \

Просмотреть файл

@ -1,25 +0,0 @@
Conrad Parker <conrad@metadecks.org>
- Design, implementation.
- Vorbis, Speex support
Tobias Gehrig
- FLAC support
Michel Salim
- libFLAC 1.1.3 support
Silvia Pfeiffer <silvia@annodex.net>
- MS Windows porting, general packaging.
Zentaro Kavanagh <ogg@illiminable.com>
- Windows porting and packaging.
based on code from:
libvorbis, by Monty <monty@xiph.org>, Xiph.org Foundation.
libspeex, by Jean-Marc Valin <jean-marc.valin@hermes.usherb.ca>,
Xiph.Org Foundation
libFLAC, by Josh Coalson, Xiph.Org Foundation.

Просмотреть файл

@ -1,29 +0,0 @@
Copyright (C) 2003 CSIRO Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of the CSIRO nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Просмотреть файл

@ -1,83 +0,0 @@
2007-01-12 Thomas Vander Stichele <thomas at apestaart dot org>
* Makefile.am:
dist m4 macro
* include/fishsound/Makefile.am:
fix include directory when overriding includedir
2005-06-13 Thomas Vander Stichele <thomas at apestaart dot org>
* autogen.sh:
* m4/as-ac-expand.m4:
add m4 dir and use it
add an expand macro
* configure.ac:
uniformize configure's output across the annodex stack
Thu Jan 13 17:58:45 EST 2005 Conrad Parker <conrad@metadecks.org>
* added liboil support from David Schleef <ds@schleef.org>
Thu Jun 24 18:48:46 EST 2004 Conrad Parker <conrad@metadecks.org>
* Version 0.6.3
Bug fixes:
* non-interleaved Speex encoding re-written and tested
* memory leak in comments API closed
Tests and examples:
* new examples fishsound-encdec and fishsound-decenc to trial
encode<->decode pipelines
* improved testing of Speex non-interleaved encoding
Fri May 21 14:32:41 EST 2004 Conrad Parker <conrad@metadecks.org>
* Version 0.6.2
Improved handling of first and last blocks of data (bos and eos
packets in Ogg):
* new fish_sound_prepare_truncation() API call
* improved encdec-audio test to keep track of frames in and out,
and warn if unequal. (Currently not set to FAIL on this condition
as it appears to be common for Speex)
Updates to Win32 nmake build files
Wed May 5 21:44:26 EST 2004 Conrad Parker <conrad@metadecks.org>
* Version 0.6.1
Added support for comment packets, tests, and various bugfixes.
* Added fish_sound_comment_() API, <fishsound/comments.h>
* Fixed segv bug in decoding stereo Speex to non-interleaved
* Added test for encode/decode pipeline with a variety of
combinations of format, interleave, samplerate, channels and
buffer size.
* Added tests for comments data structure and encode/decode pipeline
* Added fish_sound_{get,set}_frameno() API calls
Wed Mar 24 17:53:55 EST 2004 Conrad Parker <conrad@metadecks.org>
* Version 0.6.0
* moved encode and decode to examples, added documentation for each
* added fish_sound_{get,set}_interleave() api calls
* various bugfixes from zen and silvia
* updated win32 dev files from silvia
Sun Mar 07 17:30:00 EST 2004 Silvia Pfeiffer <Silvia.Pfeiffer@csiro.au>
* Version 0.5.41
* fixed up windows port and release preparation with
REAME files etc.
Some time in the year 2003...
* A new fish was born...
* ... by Conrad Parker <Conrad.Parker@csiro.au>
* ... and it had a long unlogged journey...
* before arriving at 0.5.40 . :)

Просмотреть файл

@ -1,51 +0,0 @@
# ***** 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 = fishsound
DIRS = \
include \
src \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -1,46 +0,0 @@
FishSound, the sound of fish!
-----------------------------
Full documentation is available in doc/fishsound/html/index.html,
or online at http://www.annodex.net/software/libfishsound/html/
Updates are available online at the FishSound homepage:
http://www.annodex.net/software/libfishsound/
libfishsound provides a simple programming interface for decoding and
encoding audio data using Xiph.Org codecs (FLAC, Speex and Vorbis).
libfishsound by itself is designed to handle raw codec streams from a
lower level layer such as UDP datagrams. When these codecs are used in
files, they are commonly encapsulated in Ogg to produce Ogg FLAC, Speex
and Ogg Vorbis files.
libfishsound is a wrapper around the existing codec libraries and provides
a consistent, higher-level programming interface. It has been designed for
use in a wide variety of applications; it has no direct dependencies on
Ogg encapsulation, though it is most commonly used in conjunction with
liboggz to decode or encode FLAC, Speex or Vorbis audio tracks in Ogg files,
including Ogg Theora and Annodex.
This source tarball
-------------------
FishSound has been developed and tested on GNU/Linux, Darwin/MacOSX and
Win32. It probably also works on other Unix-like systems via GNU autoconf.
For Win32: nmake Makefiles, Visual Studio .NET 2003 solution files and
Visual C++ 6.0 workspace files are all provided in the source distribution.
Details for building with GNU autotools are in the file INSTALL. Read the
file README.win32 for installing under MS Windows.
src/libfishsound/ the library source code.
src/examples/ example tools for programming with libfishsound.
include/ the libfishound include files that will be installed
into the system include directory.
doc/ documentation for libfishsound. The subdirectory
doc/libfishsound is autocreated by doxygen from
comments contained in <fishsound/fishsound.h>
win32/ files necessary to compile under MS Windows.

Просмотреть файл

@ -1,18 +0,0 @@
The source from this directory was copied from the libfishsound git
distribution 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.
Some files are renamed during the copy to prevent clashes with object
file names with other Mozilla libraries.
The git commit id used was 20b5cdf6fe38f61a9847e46e82da60d7ac4b7877
from git://git.xiph.org/libfishsound.git
endian.patch is applied to fix Bug 452698.
bug487519.patch: Fixes for bug487519
trac497.patch: Annodex trac ticket 497 fix and mozilla bug 462141.
fishsound_reset.patch: Fixes bug 516323.
bug520500.patch: Don't reject files with vorbis comments with name or
values of length 0.

Просмотреть файл

@ -1,20 +0,0 @@
diff --git a/media/libfishsound/src/libfishsound/fishsound_vorbis.c b/media/libfishsound/src/libfishsound/fishsound_vorbis.c
index 68bdb3a..236dda4 100644
--- a/media/libfishsound/src/libfishsound/fishsound_vorbis.c
+++ b/media/libfishsound/src/libfishsound/fishsound_vorbis.c
@@ -154,9 +154,13 @@ fs_vorbis_decode (FishSound * fsound, unsigned char * buf, long bytes)
} else {
FishSoundDecoded_FloatIlv df;
FishSoundDecoded_Float dfi;
-
- if (vorbis_synthesis (&fsv->vb, &op) == 0)
+ int r;
+ if ((r = vorbis_synthesis (&fsv->vb, &op)) == 0)
vorbis_synthesis_blockin (&fsv->vd, &fsv->vb);
+
+ if (r == OV_EBADPACKET) {
+ return FISH_SOUND_ERR_GENERIC;
+ }
while ((samples = vorbis_synthesis_pcmout (&fsv->vd, &fsv->pcm)) > 0) {
vorbis_synthesis_read (&fsv->vd, samples);

Просмотреть файл

@ -1,54 +0,0 @@
diff --git a/media/libfishsound/src/libfishsound/fishsound_comments.c b/media/libfishsound/src/libfishsound/fishsound_comments.c
--- a/media/libfishsound/src/libfishsound/fishsound_comments.c
+++ b/media/libfishsound/src/libfishsound/fishsound_comments.c
@@ -480,44 +480,47 @@ fish_sound_comments_decode (FishSound *
len=readint(c, 0);
debug_printf (1, "[%d] len %d\n", i, len);
c+=4;
if (len > (unsigned long) (end-c)) return -1;
name = c;
value = fs_index_len (c, '=', len);
+ n = 0;
if (value) {
*value = '\0';
value++;
-
n = c+len - value;
+
+ }
+ if (n) {
if ((nvalue = fs_strdup_len (value, n)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
debug_printf (1, "%s -> %s (length %d)", name, nvalue, n);
if ((comment = fs_comment_new (name, nvalue)) == NULL) {
fs_free (nvalue);
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
if (_fs_comment_add (fsound, comment) == NULL) {
fs_free (nvalue);
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
fs_free (nvalue);
- } else {
+ } else if (len > 0) {
debug_printf (1, "[%d] %s (no value)", i, name, len);
if ((nvalue = fs_strdup_len (name, len)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
- if ((comment = fs_comment_new (nvalue, NULL)) == NULL) {
+ if ((comment = fs_comment_new (nvalue, "")) == NULL) {
fs_free (nvalue);
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
if (_fs_comment_add (fsound, comment) == NULL) {
fs_free (nvalue);
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}

Просмотреть файл

@ -1,26 +0,0 @@
diff --git a/media/libfishsound/include/fishsound/config.h b/media/libfishsound/include/fishsound/config.h
index 573822f..b7cae62 100644
--- a/media/libfishsound/include/fishsound/config.h
+++ b/media/libfishsound/include/fishsound/config.h
@@ -104,3 +104,8 @@
#undef HAVE_VORBISENC
#define HAVE_VORBISENC 0
#undef DEBUG
+
+#include "prcpucfg.h"
+#ifdef IS_BIG_ENDIAN
+#define WORDS_BIGENDIAN
+#endif
diff --git a/media/libfishsound/src/libfishsound/config.h b/media/libfishsound/src/libfishsound/config.h
index 573822f..b7cae62 100644
--- a/media/libfishsound/src/libfishsound/config.h
+++ b/media/libfishsound/src/libfishsound/config.h
@@ -104,3 +104,8 @@
#undef HAVE_VORBISENC
#define HAVE_VORBISENC 0
#undef DEBUG
+
+#include "prcpucfg.h"
+#ifdef IS_BIG_ENDIAN
+#define WORDS_BIGENDIAN
+#endif

Просмотреть файл

@ -1,12 +0,0 @@
diff --git a/media/libfishsound/src/libfishsound/fishsound_vorbis.c b/media/libfishsound/src/libfishsound/fishsound_vorbis.c
--- a/media/libfishsound/src/libfishsound/fishsound_vorbis.c
+++ b/media/libfishsound/src/libfishsound/fishsound_vorbis.c
@@ -412,7 +412,7 @@
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
vorbis_block_init (&fsv->vd, &fsv->vb);
-
+ fsv->packetno = 0;
return 0;
}

Просмотреть файл

@ -1,47 +0,0 @@
# ***** 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 = fishsound
DIRS = fishsound
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -1,55 +0,0 @@
# ***** 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
EXPORTS_NAMESPACES = fishsound
EXPORTS_fishsound = \
comments.h \
constants.h \
decode.h \
deprecated.h \
encode.h \
fishsound.h \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -1,211 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FISH_SOUND_COMMENT_H__
#define __FISH_SOUND_COMMENT_H__
/** \file
* Encoding and decoding of comments.
*
* Vorbis and Speex bitstreams
* use a comment format called "Vorbiscomment", defined
* <a href="http://www.xiph.org/ogg/vorbis/doc/v-comment.html">here</a>.
* Many standard comment names (such as TITLE, COPYRIGHT and GENRE) are
* defined in that document.
*
* The following general features of Vorbiscomment are relevant to this API:
* - Each stream has one comment packet, which occurs before any encoded
* audio data in the stream.
* - When encoding, FishSound will generate the comment block and pass it
* to the encoded() callback in sequence, just like any other packet.
* Hence, all comments must be set before any call to fish_sound_encode_*().
* - When decoding, FishSound will decode the comment block before calling
* the first decoded() callback. Hence, retrieving comment data is possible
* from as soon as the decoded() callback is first called.
*
* Each comment block contains one Vendor string, which can be retrieved
* with fish_sound_comment_get_vendor(). When encoding, this string is
* effectively fixed by the codec libraries; it cannot be set by the
* application.
*
* The rest of a comment block consists of \a name = \a value pairs, with
* the following restrictions:
* - Both the \a name and \a value must be non-empty
* - The \a name is case-insensitive and must consist of ASCII within the
* range 0x20 to 0x7D inclusive, 0x3D ('=') excluded.
* - The \a name is not unique; multiple entries may exist with equivalent
* \a name within a Vorbiscomment block.
* - The \a value may be any UTF-8 string.
*
* \section comments_get Retrieving comments
*
* FishSound contains API methods to iterate through all comments associated
* with a FishSound* handle (fish_sound_comment_first() and
* fish_sound_comment_next(), and to iterate through comments matching a
* particular name (fish_sound_comment_first_byname() and
* fish_sound_comment_next_byname()). Given that multiple comments may exist
* with the same \a name, you should not use
* fish_sound_comment_first_byname() as a simple "get" function.
*
* \section comments_set Encoding comments
*
* For encoding, FishSound contains API methods for adding comments
* (fish_sound_comment_add() and fish_sound_comment_add_byname()
* and for removing comments
* (fish_sound_comment_remove() and fish_sound_comment_remove_byname()).
*/
#include <fishsound/fishsound.h>
/**
* A comment.
*/
typedef struct {
/** The name of the comment, eg. "AUTHOR" */
char * name;
/** The value of the comment, as UTF-8 */
char * value;
} FishSoundComment;
#ifdef __cplusplus
extern "C" {
#endif
/**
* Retrieve the vendor string.
* \param fsound A FishSound* handle
* \returns A read-only copy of the vendor string
* \retval NULL No vendor string is associated with \a fsound,
* or \a fsound is NULL.
*/
const char *
fish_sound_comment_get_vendor (FishSound * fsound);
/**
* Retrieve the first comment.
* \param fsound A FishSound* handle
* \returns A read-only copy of the first comment, or NULL if no comments
* exist for this FishSound* object.
*/
const FishSoundComment *
fish_sound_comment_first (FishSound * fsound);
/**
* Retrieve the next comment.
* \param fsound A FishSound* handle
* \param comment The previous comment.
* \returns A read-only copy of the comment immediately following the given
* comment.
*/
const FishSoundComment *
fish_sound_comment_next (FishSound * fsound, const FishSoundComment * comment);
/**
* Retrieve the first comment with a given name.
* \param fsound A FishSound* handle
* \param name the name of the comment to retrieve.
* \returns A read-only copy of the first comment matching the given \a name.
* \retval NULL no match was found.
* \note If \a name is NULL, the behaviour is the same as for
* fish_sound_comment_first()
*/
const FishSoundComment *
fish_sound_comment_first_byname (FishSound * fsound, char * name);
/**
* Retrieve the next comment following and with the same name as a given
* comment.
* \param fsound A FishSound* handle
* \param comment A comment
* \returns A read-only copy of the next comment with the same name as
* \a comment.
* \retval NULL no further comments with the same name exist for
* this FishSound* object.
*/
const FishSoundComment *
fish_sound_comment_next_byname (FishSound * fsound,
const FishSoundComment * comment);
/**
* Add a comment
* \param fsound A FishSound* handle (created with mode FISH_SOUND_ENCODE)
* \param comment The comment to add
* \retval 0 Success
* \retval FISH_SOUND_ERR_BAD \a fsound is not a valid FishSound* handle
* \retval FISH_SOUND_ERR_INVALID Operation not suitable for this FishSound
*/
int
fish_sound_comment_add (FishSound * fsound, FishSoundComment * comment);
/**
* Add a comment by name and value.
* \param fsound A FishSound* handle (created with mode FISH_SOUND_ENCODE)
* \param name The name of the comment to add
* \param value The contents of the comment to add
* \retval 0 Success
* \retval FISH_SOUND_ERR_BAD \a fsound is not a valid FishSound* handle
* \retval FISH_SOUND_ERR_INVALID Operation not suitable for this FishSound
*/
int
fish_sound_comment_add_byname (FishSound * fsound, const char * name,
const char * value);
/**
* Remove a comment
* \param fsound A FishSound* handle (created with FISH_SOUND_ENCODE)
* \param comment The comment to remove.
* \retval 1 Success: comment removed
* \retval 0 No-op: comment not found, nothing to remove
* \retval FISH_SOUND_ERR_BAD \a fsound is not a valid FishSound* handle
* \retval FISH_SOUND_ERR_INVALID Operation not suitable for this FishSound
*/
int
fish_sound_comment_remove (FishSound * fsound, FishSoundComment * comment);
/**
* Remove all comments with a given name.
* \param fsound A FishSound* handle (created with FISH_SOUND_ENCODE)
* \param name The name of the comments to remove
* \retval ">= 0" The number of comments removed
* \retval FISH_SOUND_ERR_BAD \a fsound is not a valid FishSound* handle
* \retval FISH_SOUND_ERR_INVALID Operation not suitable for this FishSound
*/
int
fish_sound_comment_remove_byname (FishSound * fsound, char * name);
#ifdef __cplusplus
}
#endif
#endif /* __FISH_SOUND_COMMENTS_H__ */

Просмотреть файл

@ -1,138 +0,0 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Do not build decoding support */
#define FS_DECODE 1
/* Do not build encoding support */
#define FS_ENCODE 0
/* Define to build experimental code */
/* #undef FS_EXPERIMENTAL */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have libFLAC */
#define HAVE_FLAC 0
/* Define to 1 if you have libFLAC 1.1.2 */
/* #undef HAVE_FLAC_1_1_2 */
/* Define to 1 if you have libFLAC 1.1.3 */
/* #undef HAVE_FLAC_1_1_3 */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* 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 */
/* #undef HAVE_OGGZ */
/* Define to 1 if you have libspeex */
#define HAVE_SPEEX 0
/* Define to 1 if you have libspeex 1.1.x */
/* #undef HAVE_SPEEX_1_1 */
/* Define to 1 if speex_lib_get_mode() exists in libspeex */
/* #undef HAVE_SPEEX_LIB_GET_MODE */
/* 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 the system has the type `uintptr_t'. */
/* #define HAVE_UINTPTR_T 1 */
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have libvorbis */
#define HAVE_VORBIS 1
/* Define to 1 if you have libvorbisenc */
#define HAVE_VORBISENC 0
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Name of package */
#define PACKAGE "libfishsound"
/* 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.9.2"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
#undef FS_ENCODE
#define FS_ENCODE 0
#undef HAVE_FLAC
#define HAVE_FLAC 0
#undef HAVE_OGGZ
#define HAVE_OGGZ 1
#undef HAVE_SPEEX
#define HAVE_SPEEX 0
#undef HAVE_VORBIS
#define HAVE_VORBIS 1
#undef HAVE_VORBISENC
#define HAVE_VORBISENC 0
#undef DEBUG
#include "prcpucfg.h"
#ifdef IS_BIG_ENDIAN
#define WORDS_BIGENDIAN
#endif

Просмотреть файл

@ -1,122 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FISH_SOUND_CONSTANTS_H__
#define __FISH_SOUND_CONSTANTS_H__
/** \file
* Constants used by libfishsound
*/
/** Mode of operation (encode or decode) */
typedef enum _FishSoundMode {
/** Decode */
FISH_SOUND_DECODE = 0x10,
/** Encode */
FISH_SOUND_ENCODE = 0x20
} FishSoundMode;
/** Identifiers for supported codecs */
typedef enum _FishSoundCodecID {
/** Unknown */
FISH_SOUND_UNKNOWN = 0x00,
/** Vorbis */
FISH_SOUND_VORBIS = 0x01,
/** Speex */
FISH_SOUND_SPEEX = 0x02,
/** Flac */
FISH_SOUND_FLAC = 0x03
} FishSoundCodecID;
/** Decode callback return values */
typedef enum _FishSoundStopCtl {
/** Continue calling decode callbacks */
FISH_SOUND_CONTINUE = 0,
/** Stop calling callbacks, but retain buffered data */
FISH_SOUND_STOP_OK = 1,
/** Stop calling callbacks, and purge buffered data */
FISH_SOUND_STOP_ERR = -1
} FishSoundStopCtl;
/** Command codes */
typedef enum _FishSoundCommand {
/** No operation */
FISH_SOUND_COMMAND_NOP = 0x0000,
/** Retrieve the FishSoundInfo */
FISH_SOUND_GET_INFO = 0x1000,
/** Query if multichannel audio should be interpreted as interleaved */
FISH_SOUND_GET_INTERLEAVE = 0x2000,
/** Set to 1 to interleave, 0 to non-interleave */
FISH_SOUND_SET_INTERLEAVE = 0x2001,
FISH_SOUND_SET_ENCODE_VBR = 0x4000,
FISH_SOUND_COMMAND_MAX
} FishSoundCommand;
/** Error values */
typedef enum _FishSoundError {
/** No error */
FISH_SOUND_OK = 0,
/** generic error */
FISH_SOUND_ERR_GENERIC = -1,
/** Not a valid FishSound* handle */
FISH_SOUND_ERR_BAD = -2,
/** The requested operation is not suitable for this FishSound* handle */
FISH_SOUND_ERR_INVALID = -3,
/** Out of memory */
FISH_SOUND_ERR_OUT_OF_MEMORY = -4,
/** Functionality disabled at build time */
FISH_SOUND_ERR_DISABLED = -10,
/** Too few bytes passed to fish_sound_identify() */
FISH_SOUND_ERR_SHORT_IDENTIFY = -20,
/** Comment violates VorbisComment restrictions */
FISH_SOUND_ERR_COMMENT_INVALID = -21
} FishSoundError;
#endif /* __FISH_SOUND_CONSTANTS_H__ */

Просмотреть файл

@ -1,129 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FISH_SOUND_DECODE_H__
#define __FISH_SOUND_DECODE_H__
#ifdef __cplusplus
extern "C" {
#endif
/** \file
* Decode functions and callback prototypes
*/
/**
* Signature of a callback for libfishsound to call when it has decoded
* PCM audio data, and you want this provided as non-interleaved floats.
* \param fsound The FishSound* handle
* \param pcm The decoded audio
* \param frames The count of frames decoded
* \param user_data Arbitrary user data
* \retval FISH_SOUND_CONTINUE Continue decoding
* \retval FISH_SOUND_STOP_OK Stop decoding immediately and
* return control to the fish_sound_decode() caller
* \retval FISH_SOUND_STOP_ERR Stop decoding immediately, purge buffered
* data, and return control to the fish_sound_decode() caller
*/
typedef int (*FishSoundDecoded_Float) (FishSound * fsound, float * pcm[],
long frames, void * user_data);
/**
* Signature of a callback for libfishsound to call when it has decoded
* PCM audio data, and you want this provided as interleaved floats.
* \param fsound The FishSound* handle
* \param pcm The decoded audio
* \param frames The count of frames decoded
* \param user_data Arbitrary user data
* \retval FISH_SOUND_CONTINUE Continue decoding
* \retval FISH_SOUND_STOP_OK Stop decoding immediately and
* return control to the fish_sound_decode() caller
* \retval FISH_SOUND_STOP_ERR Stop decoding immediately, purge buffered
* data, and return control to the fish_sound_decode() caller
*/
typedef int (*FishSoundDecoded_FloatIlv) (FishSound * fsound, float ** pcm,
long frames, void * user_data);
/**
* Set the callback for libfishsound to call when it has a block of decoded
* PCM audio ready, and you want this provided as non-interleaved floats.
* \param fsound A FishSound* handle (created with mode FISH_SOUND_DECODE)
* \param decoded The callback to call
* \param user_data Arbitrary user data to pass to the callback
* \retval 0 Success
* \retval FISH_SOUND_ERR_BAD Not a valid FishSound* handle
* \retval FISH_SOUND_ERR_OUT_OF_MEMORY Out of memory
*/
int fish_sound_set_decoded_float (FishSound * fsound,
FishSoundDecoded_Float decoded,
void * user_data);
/**
* Set the callback for libfishsound to call when it has a block of decoded
* PCM audio ready, and you want this provided as interleaved floats.
* \param fsound A FishSound* handle (created with mode FISH_SOUND_DECODE)
* \param decoded The callback to call
* \param user_data Arbitrary user data to pass to the callback
* \retval 0 Success
* \retval FISH_SOUND_ERR_BAD Not a valid FishSound* handle
* \retval FISH_SOUND_ERR_OUT_OF_MEMORY Out of memory
*/
int fish_sound_set_decoded_float_ilv (FishSound * fsound,
FishSoundDecoded_FloatIlv decoded,
void * user_data);
/**
* Decode a block of compressed data.
* No internal buffering is done, so a complete compressed audio packet
* must be passed each time.
* \param fsound A FishSound* handle (created with mode FISH_SOUND_DECODE)
* \param buf A buffer containing a compressed audio packet
* \param bytes A count of bytes to decode (i.e. the length of buf)
* \returns The number of bytes consumed
* \retval FISH_SOUND_ERR_STOP_OK Decoding was stopped by a FishSoundDecode*
* callback returning FISH_SOUND_STOP_OK before any input bytes were consumed.
* This will occur when PCM is decoded from previously buffered input, and
* stopping is immediately requested.
* \retval FISH_SOUND_ERR_STOP_ERR Decoding was stopped by a FishSoundDecode*
* callback returning FISH_SOUND_STOP_ERR before any input bytes were consumed.
* This will occur when PCM is decoded from previously buffered input, and
* stopping is immediately requested.
* \retval FISH_SOUND_ERR_BAD Not a valid FishSound* handle
* \retval FISH_SOUND_ERR_OUT_OF_MEMORY Out of memory
*/
long fish_sound_decode (FishSound * fsound, unsigned char * buf, long bytes);
#ifdef __cplusplus
}
#endif
#endif /* __FISH_SOUND_DECODE_H__ */

Просмотреть файл

@ -1,107 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FISH_SOUND_DEPRECATED_H__
#define __FISH_SOUND_DEPRECATED_H__
/** \file
* Deprecated interfaces
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* DEPRECATED TYPE.
* Signature of a callback for libfishsound to call when it has decoded
* PCM audio data, and you want this provided as floats using the current
* interleave method as set by fish_sound_set_interleave().
*/
typedef FishSoundDecoded_Float FishSoundDecoded;
/**
* DEPRECATED FUNCTION.
* Set the callback for libfishsound to call when it has a block of decoded
* PCM audio ready, and you want this provided as floats using the current
* interleave method as set by fish_sound_set_interleave().
* This function, and fish_sound_set_interleave(), have been superceded by
* the typesafe fish_sound_set_decoded_TYPE() callbacks, such as
* fish_sound_set_decoded_float() or fish_sound_set_decoded_float_ilv().
*
* \param fsound A FishSound* handle (created with mode FISH_SOUND_DECODE)
* \param decoded The callback to call
* \param user_data Arbitrary user data to pass to the callback
* \returns 0 on success, -1 on failure
*/
int fish_sound_set_decoded_callback (FishSound * fsound,
FishSoundDecoded decoded,
void * user_data);
/**
* DEPRECATED FUNCTION.
* Set the PCM format used by a FishSound object. The default value is
* non-interleaved.
* Prior to libfishsound 0.7.0, you would (optionally) specify whether you
* wanted to receive interleaved or per-channel PCM data using
* fish_sound_set_interleave(), the default being per-channel
* (non-interleaved) PCM.
* Whether or not your decoded callback expects interleaved or
* non-interleaved data is now implied by the particular
* fish_sound_set_decoded_TYPE() method you use to set it, such as
* fish_sound_set_decoded_float() or fish_sound_set_decoded_float_ilv().
*
* \param fsound A FishSound* handle
* \param interleave Whether to use interleaved PCM or not. Valid values are
* 0 for non-interleaved, and 1 for interleaved.
* \retval 0 Success
* \retval -1 Invalid \a fsound
*/
int fish_sound_set_interleave (FishSound * fsound, int interleave);
/**
* DEPRECATED FUNCTION.
* Encode a block of audio
* \param fsound A FishSound* handle (created with mode FISH_SOUND_ENCODE)
* \param pcm The audio data to encode
* \param frames A count of frames to encode
* \returns The number of frames encoded
* \note For multichannel audio, the audio data is interpreted according
* to the current PCM style
*/
long fish_sound_encode (FishSound * fsound, float ** pcm, long frames);
#ifdef __cplusplus
}
#endif
#endif /* __FISH_SOUND_DEPRECATED_H__ */

Просмотреть файл

@ -1,97 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FISH_SOUND_ENCODE_H__
#define __FISH_SOUND_ENCODE_H__
#ifdef __cplusplus
extern "C" {
#endif
/** \file
* Encode functions and callback prototypes
*/
/**
* Signature of a callback for libfishsound to call when it has encoded
* data.
* \param fsound The FishSound* handle
* \param buf The encoded data
* \param bytes The count of bytes encoded
* \param user_data Arbitrary user data
* \retval 0 to continue
* \retval non-zero to stop encoding immediately and
* return control to the fish_sound_encode() caller
*/
typedef int (*FishSoundEncoded) (FishSound * fsound, unsigned char * buf,
long bytes, void * user_data);
/**
* Set the callback for libfishsound to call when it has a block of
* encoded data ready
* \param fsound A FishSound* handle (created with mode FISH_SOUND_ENCODE)
* \param encoded The callback to call
* \param user_data Arbitrary user data to pass to the callback
* \returns 0 on success, -1 on failure
*/
int fish_sound_set_encoded_callback (FishSound * fsound,
FishSoundEncoded encoded,
void * user_data);
/**
* Encode a block of PCM audio given as non-interleaved floats.
* \param fsound A FishSound* handle (created with mode FISH_SOUND_ENCODE)
* \param pcm The audio data to encode
* \param frames A count of frames to encode
* \returns The number of frames encoded
* \note For multichannel audio, the audio data is interpreted according
* to the current PCM style
*/
long fish_sound_encode_float (FishSound * fsound, float * pcm[], long frames);
/**
* Encode a block of audio given as interleaved floats.
* \param fsound A FishSound* handle (created with mode FISH_SOUND_ENCODE)
* \param pcm The audio data to encode
* \param frames A count of frames to encode
* \returns The number of frames encoded
* \note For multichannel audio, the audio data is interpreted according
* to the current PCM style
*/
long fish_sound_encode_float_ilv (FishSound * fsound, float ** pcm,
long frames);
#ifdef __cplusplus
}
#endif
#endif /* __FISH_SOUND_ENCODE_H__ */

Просмотреть файл

@ -1,589 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FISH_SOUND_H__
#define __FISH_SOUND_H__
#include <fishsound/constants.h>
/** \mainpage
*
* \section intro FishSound, the sound of fish!
*
* This is the documentation for the FishSound C API. FishSound provides
* a simple programming interface for decoding and encoding audio data
* using Xiph.Org codecs (FLAC, Speex and Vorbis).
*
* libfishsound by itself is designed to handle raw codec streams from
* a lower level layer such as UDP datagrams.
* When these codecs are used in files, they are commonly encapsulated in
* <a href="http://www.xiph.org/ogg/">Ogg</a> to produce
* <em>Ogg FLAC</em>, <em>Speex</em> and <em>Ogg Vorbis</em> files.
* Example C programs using
* <a href="http://www.annodex.net/software/liboggz/">liboggz</a> to
* read and write these files are provided in the libfishsound sources.
*
* For more information on the design and history of libfishsound, see the
* \link about About \endlink section of this documentation, and the
* <a href="http://www.annodex.net/software/libfishsound/">libfishsound</a>
* homepage.
*
* \subsection contents Contents
*
* - \link fishsound.h fishsound.h \endlink:
* Documentation of the FishSound API.
*
* - \link comments.h Handling comments \endlink:
* How to add and retrieve \a name = \a value metadata in Vorbis and Speex
* streams.
*
* - \link decode Decoding audio data \endlink:
* How to decode audio data with FishSound, including source for a fully
* working Ogg FLAC, Speex and Ogg Vorbis decoder.
*
* - \link encode Encoding audio data \endlink:
* How to encode audio data with FishSound, including source for a fully
* working Ogg FLAC, Speex and Ogg Vorbis encoder.
*
* - \link configuration Configuration \endlink:
* Customizing libfishsound to only decode or encode,
* or to disable support for a particular codec.
*
* - \link building Building \endlink:
* Information related to building software that uses libfishsound.
*
* - \link about About \endlink:
* Design, motivation, history and acknowledgements.
*
* \section Licensing
*
* libfishsound is provided under the following BSD-style open source license:
*
* \include COPYING
*
*/
/** \defgroup about About
*
* \section design Design
* libfishsound provides a simple programming interface for decoding and
* encoding audio data using codecs from
* <a href="http://www.xiph.org/">Xiph.Org</a>.
*
* libfishsound by itself is designed to handle raw codec streams from
* a lower level layer such as UDP datagrams.
* When these codecs are used in files, they are commonly encapsulated in
* <a href="http://www.xiph.org/ogg/">Ogg</a> to produce
* <em>Ogg FLAC</em>, <em>Speex</em> and <em>Ogg Vorbis</em> files.
* Example C programs using
* <a href="http://www.annodex.net/software/liboggz/">liboggz</a> to
* read and write these files are provided in the libfishsound sources.
*
* libfishsound is implemented as a wrapper around the existing codec
* libraries and provides a consistent, higher-level programming
* interface. The motivation for this is twofold: to simplify the task
* of developing application software that supports these codecs,
* and to ensure that valid codec streams are generated.
*
* \section history History
* libfishsound was designed and developed by Conrad Parker on the
* weekend of October 18-19 2003. Previously the author had implemented
* Vorbis and Speex support in the following software:
* - <a href="http://www.metadecks.org/software/sweep/">Sweep</a>, a
* digital audio editor with decoding and GUI control of all encoding
* options of Vorbis and Speex
* - Speex support in the <a href="http://www.xinehq.org/">xine</a>
* multimedia player
* - Vorbis and Speex importers for
* <a href="http://www.annodex.net/software/libannodex/">libannodex</a>,
the basic library for reading and writing
* <a href="http://www.annodex.net/">Annodex.net</a> media files.
*
* The implementation of libfishsound draws heavily on these sources, and
* in turn the original example sources of libvorbis and libvorbisenc by
* Monty, and libspeex by Jean-Marc Valin.
*
* The naming of libfishsound reflects both the Xiph.Org logo and
* the author's reputation as a dirty, smelly old fish.
*
* \section limitations Limitations
*
* libfishsound has been designed to accomodate the various decoding and
* encoding styles required by a wide variety of software. However, as it
* is an abstraction of the underlying libvorbis, libvorbisenc and libspeex
* libraries, it may not be possible to implement some low-level techniques
* that these libraries enable, such as parallelization of Vorbis sub-block
* decoding. Nevertheless it is expected that libfishsound is a useful
* API for most software requiring Vorbis or Speex support, including most
* applications the author has encountered.
*
* \section acknowledgements Acknowledgements
* Much of the API design follows the style of
* <a href="http://www.zip.com.au/~erikd/libsndfile/">libsndfile</a>.
* The author would like to thank Erik de Castro Lopo for feedback on the
* design of libfishsound.
*/
/** \defgroup configuration Configuration
*
* \section platforms Platform-specific configuration
*
* FishSound can be configured on most platforms using the GNU autoconf
* ./configure system described below.
*
* For Win32, see the \link win32 README.win32 \endlink section. You will
* need to edit <tt>win32/config.h</tt> by hand to achieve the customizations
* described below.
*
* \section ./configure ./configure
*
* It is possible to customize the functionality of libfishsound
* by using various ./configure flags when
* building it from source; for example you can build a smaller
* version of libfishsound to only decode or encode, or and you can
* choose to disable support for a particular codec.
* By default, both decoding and encoding support is built for all
* codecs found on the system.
*
* For general information about using ./configure, see the file
* \link install INSTALL \endlink
*
* \subsection no_encode Removing encoding support
*
* Configuring with \a --disable-encode will remove all support for encoding:
* - All internal encoding related functions will not be built
* - Any attempt to call fish_sound_new() with \a mode == FISH_SOUND_ENCODE
* will fail, returning NULL
* - Any attempt to call fish_sound_encode_*() will return
* FISH_SOUND_ERR_DISABLED
* - The resulting library will not be linked against libvorbisenc
*
* \subsection no_decode Removing decoding support
*
* Configuring with \a --disable-decode will remove all support for decoding:
* - All internal decoding related functions will not be built
* - Any attempt to call fish_sound_new() with \a mode == FISH_SOUND_DECODE
* will fail, returning NULL
* - Any attempt to call fish_sound_decode() will return
* FISH_SOUND_ERR_DISABLED
*
* \subsection no_flac Removing FLAC support
*
* Configuring with \a --disable-flac will remove all support for FLAC:
* - All internal FLAC related functions will not be built
* - Any attempt to call fish_sound_new() with \a mode == FISH_SOUND_ENCODE
* and \a fsinfo->format == FISH_SOUND_FLAC will fail, returning NULL
* - The resulting library will not be linked against libFLAC
*
* \subsection no_speex Removing Speex support
*
* Configuring with \a --disable-speex will remove all support for Speex:
* - All internal Speex related functions will not be built
* - Any attempt to call fish_sound_new() with \a mode == FISH_SOUND_ENCODE
* and \a fsinfo->format == FISH_SOUND_SPEEX will fail, returning NULL
* - The resulting library will not be linked against libspeex
*
* \subsection no_vorbis Removing Vorbis support
*
* Configuring with \a --disable-vorbis will remove all support for Vorbis:
* - All internal Vorbis related functions will not be built
* - Any attempt to call fish_sound_new() with \a mode == FISH_SOUND_ENCODE
* and \a fsinfo->format == FISH_SOUND_VORBIS will fail, returning NULL
* - The resulting library will not be linked against libvorbis or libvorbisenc
*
* \subsection summary Configuration summary
*
* Upon successful configuration, you should see something like this:
<pre>
------------------------------------------------------------------------
libfishsound 0.9.0: Automatic configuration OK.
General configuration:
Experimental code: ........... no
Decoding support: ............ yes
Encoding support: ............ yes
Library configuration (./src/libfishsound):
FLAC support: ................ yes
Speex support: ............... yes (1.1.x)
Vorbis support: .............. yes
Example programs (./src/examples):
fishsound-identify fishsound-decode fishsound-encode
Installation paths:
libfishsound: ................ /usr/local/lib
C header files: .............. /usr/local/include/fishsound
Documentation: ............... /usr/local/share/doc/libfishsound
Building:
Type 'make' to compile libfishsound.
Type 'make install' to install libfishsound.
Type 'make check' to run test suite (Valgrind testing not enabled)
Example programs will be built but not installed.
------------------------------------------------------------------------
</pre>
*/
/** \defgroup install Installation
* \section install INSTALL
*
* \include INSTALL
*/
/** \defgroup win32 Building on Win32
* \section win32 README.Win32
*
* \include README.win32
*/
/** \defgroup building Building against libfishsound
*
*
* \section autoconf Using GNU autoconf
*
* If you are using GNU autoconf, you do not need to call pkg-config
* directly. Use the following macro to determine if libfishsound is
* available:
*
<pre>
PKG_CHECK_MODULES(FISHSOUND, fishsound >= 0.6.0,
HAVE_FISHSOUND="yes", HAVE_FISHSOUND="no")
if test "x$HAVE_FISHSOUND" = "xyes" ; then
AC_SUBST(FISHSOUND_CFLAGS)
AC_SUBST(FISHSOUND_LIBS)
fi
</pre>
* (Note that if your application requires FLAC support, you should check
* for a version of fishsound >= 0.9.0).
*
* If libfishsound is found, HAVE_FISHSOUND will be set to "yes", and
* the autoconf variables FISHSOUND_CFLAGS and FISHSOUND_LIBS will
* be set appropriately.
*
* \section pkg-config Determining compiler options with pkg-config
*
* If you are not using GNU autoconf in your project, you can use the
* pkg-config tool directly to determine the correct compiler options.
*
<pre>
FISHSOUND_CFLAGS=`pkg-config --cflags fishsound`
FISHSOUND_LIBS=`pkg-config --libs fishsound`
</pre>
*
*/
/** \file
* The libfishsound C API.
*
* \section general General usage
*
* All access is managed via a FishSound* handle. This is instantiated
* using fish_sound_new() and should be deleted with fish_sound_delete()
* when no longer required. If there is a discontinuity in the input
* data (eg. after seeking in an input file), call fish_sound_reset() to
* reset the internal codec state.
*
* \section decoding Decoding
*
* libfishsound provides callback based decoding: you feed it encoded audio
* data, and it will call your callback with decoded PCM. A more detailed
* explanation and a full example of decoding Ogg FLAC, Speex and Ogg Vorbis
* files is provided in the \link decode Decoding audio data \endlink section.
*
* \section encoding Encoding
*
* libfishsound provides callback based encoding: you feed it PCM audio,
* and it will call your callback with encoded audio data. A more detailed
* explanation and a full example of encoding Ogg FLAC, Speex and Ogg Vorbis
* files is provided in the \link encode Encoding audio data \endlink section.
*/
/** \defgroup decode Decoding audio data
*
* To decode audio data using libfishsound:
*
* - create a FishSound* object with mode FISH_SOUND_DECODE. fish_sound_new()
* will return a new FishSound* object, initialised for decoding, and the
* FishSoundInfo structure will be cleared.
* - provide a FishSoundDecoded_* callback for libfishsound to call when it has
* decoded audio.
* - (optionally) specify whether you want to receive interleaved or
* per-channel PCM data, using a fish_sound_set_interleave().
* The default is for per-channel (non-interleaved) PCM.
* - feed encoded audio data to libfishsound via fish_sound_decode().
* libfishsound will decode the audio for you, calling the FishSoundDecoded_*
* callback you provided earlier each time it has a block of audio ready.
* - when finished, call fish_sound_delete().
*
* This procedure is illustrated in src/examples/fishsound-decode.c.
* Note that this example additionally:
* - uses <a href="http://www.annodex.net/software/liboggz/">liboggz</a> to
* demultiplex audio data from an Ogg encapsulated FLAC, Speex or Vorbis
* stream. The step of feeding encoded data to libfishsound is done within
* the OggzReadPacket callback.
* - uses <a href="http://www.mega-nerd.com/libsndfile/">libsndfile</a> to
* write the decoded audio to a WAV file.
*
* Hence this example code demonstrates all that is needed to decode
* Ogg FLAC, Speex or Ogg Vorbis files:
*
* \include fishsound-decode.c
*/
/** \defgroup encode Encoding audio data
*
* To encode audio data using libfishsound:
*
* - create a FishSound* object with mode FISH_SOUND_ENCODE, and with a
* FishSoundInfo structure filled in with the required encoding parameters.
* fish_sound_new() will return a new FishSound* object initialised for
* encoding.
* - provide a FishSoundEncoded callback for libfishsound to call when it
* has a block of encoded audio
* - feed raw PCM audio data to libfishsound via fish_sound_encode_*().
* libfishsound will encode the audio for you, calling the FishSoundEncoded
* callback you provided earlier each time it has a block of encoded audio
* ready.
* - when finished, call fish_sound_delete().
*
* This procedure is illustrated in src/examples/fishsound-encode.c.
* Note that this example additionally:
* - uses <a href="http://www.mega-nerd.com/libsndfile/">libsndfile</a> to
* read input from a PCM audio file (WAV, AIFF, etc.)
* - uses <a href="http://www.annodex.net/software/liboggz/">liboggz</a> to
* encapsulate the encoded FLAC, Speex or Vorbis data in an Ogg stream.
*
* Hence this example code demonstrates all that is needed to encode
* Ogg FLAC, Speex and Ogg Vorbis files:
*
* \include fishsound-encode.c
*/
/**
* Info about a particular encoder/decoder instance
*/
typedef struct {
/** Sample rate of audio data in Hz */
int samplerate;
/** Count of channels */
int channels;
/** FISH_SOUND_VORBIS, FISH_SOUND_SPEEX, FISH_SOUND_FLAC etc. */
int format;
} FishSoundInfo;
/**
* Info about a particular sound format
*/
typedef struct {
/** FISH_SOUND_VORBIS, FISH_SOUND_SPEEX, FISH_SOUND_FLAC etc. */
int format;
/** Printable name */
const char * name;
/** Commonly used file extension */
const char * extension;
} FishSoundFormat;
/**
* An opaque handle to a FishSound. This is returned by fishsound_new()
* and is passed to all other fish_sound_*() functions.
*/
typedef void * FishSound;
#ifdef __cplusplus
extern "C" {
#endif
/**
* Identify a codec based on the first few bytes of data.
* \param buf A pointer to the first few bytes of the data
* \param bytes The count of bytes available at buf
* \retval FISH_SOUND_xxxxxx FISH_SOUND_VORBIS, FISH_SOUND_SPEEX or
* FISH_SOUND_FLAC if \a buf was identified as the initial bytes of a
* supported codec
* \retval FISH_SOUND_UNKNOWN if the codec could not be identified
* \retval FISH_SOUND_ERR_SHORT_IDENTIFY if \a bytes is less than 8
* \note If \a bytes is exactly 8, then only a weak check is performed,
* which is fast but may return a false positive.
* \note If \a bytes is greater than 8, then a stronger check is performed
* in which an attempt is made to decode \a buf as the initial header of
* each supported codec. This is unlikely to return a false positive but
* is only useful if \a buf is the entire payload of a packet derived from
* a lower layer such as Ogg framing or UDP datagrams.
*/
int
fish_sound_identify (unsigned char * buf, long bytes);
/**
* Instantiate a new FishSound* handle
* \param mode FISH_SOUND_DECODE or FISH_SOUND_ENCODE
* \param fsinfo Encoder configuration, may be NULL for FISH_SOUND_DECODE
* \returns A new FishSound* handle, or NULL on error
*/
FishSound * fish_sound_new (int mode, FishSoundInfo * fsinfo);
/**
* Flush any internally buffered data, forcing encode
* \param fsound A FishSound* handle
* \returns 0 on success, -1 on failure
*/
long fish_sound_flush (FishSound * fsound);
/**
* Reset the codec state of a FishSound object.
*
* When decoding from a seekable file, fish_sound_reset() should be called
* after any seek operations. See also fish_sound_set_frameno().
*
* \param fsound A FishSound* handle
* \returns 0 on success, -1 on failure
*/
int fish_sound_reset (FishSound * fsound);
/**
* Delete a FishSound object
* \param fsound A FishSound* handle
* \returns 0 on success, -1 on failure
*/
int fish_sound_delete (FishSound * fsound);
/**
* Command interface
* \param fsound A FishSound* handle
* \param command The command action
* \param data Command data
* \param datasize Size of the data in bytes
* \returns 0 on success, -1 on failure
*/
int fish_sound_command (FishSound * fsound, int command, void * data,
int datasize);
/**
* Query whether a FishSound object is using interleaved PCM
* \param fsound A FishSound* handle
* \retval 0 \a fsound uses non-interleaved PCM
* \retval 1 \a fsound uses interleaved PCM
* \retval -1 Invalid \a fsound, or out of memory.
*/
int fish_sound_get_interleave (FishSound * fsound);
/**
* Query the current frame number of a FishSound object.
*
* For decoding, this is the greatest frame index that has been decoded and
* made available to a FishSoundDecoded callback. This function is safe to
* call from within a FishSoundDecoded callback, and corresponds to the frame
* number of the last frame in the current decoded block.
*
* For encoding, this is the greatest frame index that has been encoded. This
* function is safe to call from within a FishSoundEncoded callback, and
* corresponds to the frame number of the last frame encoded in the current
* block.
*
* \param fsound A FishSound* handle
* \returns The current frame number
* \retval -1 Invalid \a fsound
*/
long fish_sound_get_frameno (FishSound * fsound);
/**
* Set the current frame number of a FishSound object.
*
* When decoding from a seekable file, fish_sound_set_frameno() should be
* called after any seek operations, otherwise the value returned by
* fish_sound_get_frameno() will simply continue to increment. See also
* fish_sound_reset().
*
* \param fsound A FishSound* handle
* \param frameno The current frame number.
* \retval 0 Success
* \retval -1 Invalid \a fsound
*/
int fish_sound_set_frameno (FishSound * fsound, long frameno);
/**
* Prepare truncation details for the next block of data.
* The semantics of these parameters derives directly from Ogg encapsulation
* of Vorbis, described
* <a href="http://www.xiph.org/ogg/vorbis/doc/Vorbis_I_spec.html#vorbis-over-ogg">here</a>.
*
* When decoding from Ogg, you should call this function with the \a granulepos
* and \a eos of the \a ogg_packet structure. This call should be made before
* passing the packet's data to fish_sound_decode(). Failure to do so may
* result in minor decode errors on the first and/or last packet of the stream.
*
* When encoding into Ogg, you should call this function with the \a granulepos
* and \a eos that will be used for the \a ogg_packet structure. This call
* should be made before passing the block of audio data to
* fish_sound_encode_*(). Failure to do so may result in minor encoding errors
* on the first and/or last packet of the stream.
*
* \param fsound A FishSound* handle
* \param next_granulepos The "granulepos" for the next block to decode.
* If unknown, set \a next_granulepos to -1. Otherwise,
* \a next_granulepos specifies the frameno of the final frame in the
* block. This is authoritative, hence can be used to indicate
* various forms of truncation at the beginning or end of a stream.
* Mid-stream, a later-than-expected "granulepos" indicates that some
* data was missing.
* \param next_eos A boolean indicating whether the next data block will be
* the last in the stream.
* \retval 0 Success
* \retval -1 Invalid \a fsound
*/
int fish_sound_prepare_truncation (FishSound * fsound, long next_granulepos,
int next_eos);
#ifdef __cplusplus
}
#endif
#include <fishsound/decode.h>
#include <fishsound/encode.h>
#include <fishsound/comments.h>
#include <fishsound/deprecated.h>
#endif /* __FISH_SOUND_H__ */

Просмотреть файл

@ -1,47 +0,0 @@
# ***** 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 = fishsound
DIRS = libfishsound
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -1,58 +0,0 @@
# ***** 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 = fishsound
LIBRARY_NAME = fishsound
FORCE_STATIC_LIB= 1
CSRCS = \
fishsound_comments.c \
fishsound_decode.c \
fishsound.c \
fs_vector.c \
fishsound_speex.c \
fishsound_vorbis.c \
fishsound_flac.c \
$(NULL)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -1,138 +0,0 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Do not build decoding support */
#define FS_DECODE 1
/* Do not build encoding support */
#define FS_ENCODE 0
/* Define to build experimental code */
/* #undef FS_EXPERIMENTAL */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 1
/* Define to 1 if you have libFLAC */
#define HAVE_FLAC 0
/* Define to 1 if you have libFLAC 1.1.2 */
/* #undef HAVE_FLAC_1_1_2 */
/* Define to 1 if you have libFLAC 1.1.3 */
/* #undef HAVE_FLAC_1_1_3 */
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* 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 */
/* #undef HAVE_OGGZ */
/* Define to 1 if you have libspeex */
#define HAVE_SPEEX 0
/* Define to 1 if you have libspeex 1.1.x */
/* #undef HAVE_SPEEX_1_1 */
/* Define to 1 if speex_lib_get_mode() exists in libspeex */
/* #undef HAVE_SPEEX_LIB_GET_MODE */
/* 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 the system has the type `uintptr_t'. */
/* #define HAVE_UINTPTR_T 1 */
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to 1 if you have libvorbis */
#define HAVE_VORBIS 1
/* Define to 1 if you have libvorbisenc */
#define HAVE_VORBISENC 0
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* Name of package */
#define PACKAGE "libfishsound"
/* 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.9.2"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
#undef FS_ENCODE
#define FS_ENCODE 0
#undef HAVE_FLAC
#define HAVE_FLAC 0
#undef HAVE_OGGZ
#define HAVE_OGGZ 1
#undef HAVE_SPEEX
#define HAVE_SPEEX 0
#undef HAVE_VORBIS
#define HAVE_VORBIS 1
#undef HAVE_VORBISENC
#define HAVE_VORBISENC 0
#undef DEBUG
#include "prcpucfg.h"
#ifdef IS_BIG_ENDIAN
#define WORDS_BIGENDIAN
#endif

Просмотреть файл

@ -1,68 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FISH_SOUND_CONVERT_H__
#define __FISH_SOUND_CONVERT_H__
/* inline functions */
static inline void
_fs_deinterleave (float ** src, float * dest[],
long frames, int channels, float mult_factor)
{
int i, j;
float * d, * s = (float *)src;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
d = dest[j];
d[i] = s[i*channels + j] * mult_factor;
}
}
}
static inline void
_fs_interleave (float * src[], float ** dest,
long frames, int channels, float mult_factor)
{
int i, j;
float * s, * d = (float *)dest;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
s = src[j];
d[i*channels + j] = s[i] * mult_factor;
}
}
}
#endif /* __FISH_SOUND_CONVERT_H__ */

Просмотреть файл

@ -1,415 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FISH_SOUND_CONVERT_C_H__
#define __FISH_SOUND_CONVERT_C_H__
#include <string.h>
#include <ogg/ogg.h>
/* inline functions */
static inline void
_fs_deinterleave_s_s (short ** src, short * dest[],
long frames, int channels)
{
int i, j;
short * d, * s = (short *)src;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
d = dest[j];
d[i] = s[i*channels + j];
}
}
}
static inline void
_fs_deinterleave_s_i (short ** src, int * dest[], long frames, int channels)
{
int i, j;
short * s = (short *)src;
int * d;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
d = dest[j];
d[i] = (int) s[i*channels + j];
}
}
}
static inline void
_fs_deinterleave_s_f (short ** src, float * dest[], long frames, int channels,
float mult)
{
int i, j;
short * s = (short *)src;
float * d;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
d = dest[j];
d[i] = ((float) s[i*channels + j]) * mult;
}
}
}
static inline void
_fs_deinterleave_s_d (short ** src, double * dest[], long frames, int channels,
double mult)
{
int i, j;
short * s = (short *)src;
double * d;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
d = dest[j];
d[i] = ((double) s[i*channels + j]) * mult;
}
}
}
static inline void
_fs_deinterleave_f_s (float ** src, short * dest[],
long frames, int channels, float mult)
{
int i, j;
float * s = (float *)src;
short * d;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
d = dest[j];
d[i] = (short) (s[i*channels + j] * mult);
}
}
}
static inline void
_fs_deinterleave_f_i (float ** src, int * dest[],
long frames, int channels, float mult)
{
int i, j;
float * s = (float *)src;
int * d;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
d = dest[j];
d[i] = (int) (s[i*channels + j] * mult);
}
}
}
static inline void
_fs_deinterleave_f_f (float ** src, float * dest[],
long frames, int channels, float mult)
{
int i, j;
float * s = (float *)src, * d;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
d = dest[j];
d[i] = s[i*channels + j] * mult;
}
}
}
static inline void
_fs_deinterleave_f_d (float ** src, double * dest[],
long frames, int channels, double mult)
{
int i, j;
float * s = (float *)src;
double * d;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
d = dest[j];
d[i] = (double) s[i*channels + j] * mult;
}
}
}
static inline void
_fs_interleave_f_s (float * src[], short ** dest,
long frames, int channels, float mult)
{
int i, j;
float * s;
short * d = (short *)dest;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
s = src[j];
d[i*channels + j] = (short) (s[i] * mult);
}
}
}
static inline void
_fs_interleave_s_s (short * src[], short ** dest,
long frames, int channels)
{
int i, j;
short * s, * d = (short *)dest;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
s = src[j];
d[i*channels + j] = s[i];
}
}
}
static inline void
_fs_interleave_s_f (short * src[], float ** dest,
long frames, int channels, float mult)
{
int i, j;
short * s;
float * d = (float *)dest;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
s = src[j];
d[i*channels + j] = (float) (s[i] * mult);
}
}
}
static inline ogg_int32_t CLIP_TO_15(ogg_int32_t x) {
int ret=x;
ret-= ((x<=32767)-1)&(x-32767);
ret-= ((x>=-32768)-1)&(x+32768);
return(ret);
}
static inline void
_fs_interleave_i_s (ogg_int32_t * src[], short ** dest,
long frames, int channels, int shift)
{
int i, j;
ogg_int32_t * s;
short * d = (short *)dest;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
s = src[j];
d[i*channels + j] = (short) CLIP_TO_15(s[i]>>9);
}
}
}
static inline void
_fs_interleave_i_f (int * src[], float ** dest,
long frames, int channels, float mult)
{
int i, j;
int * s;
float * d = (float *)dest;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
s = src[j];
d[i*channels + j] = (float) (s[i] * mult);
}
}
}
static inline void
_fs_interleave_f_f (float * src[], float ** dest,
long frames, int channels, float mult)
{
int i, j;
float * s, * d = (float *)dest;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
s = src[j];
d[i*channels + j] = s[i] * mult;
}
}
}
static inline void
_fs_interleave_d_s (double * src[], short ** dest,
long frames, int channels, double mult)
{
int i, j;
double * s;
short * d = (short *)dest;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
s = src[j];
d[i*channels + j] = (short) (s[i] * mult);
}
}
}
static inline void
_fs_interleave_d_f (double * src[], float ** dest,
long frames, int channels, float mult)
{
int i, j;
double * s;
float * d = (float *)dest;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
s = src[j];
d[i*channels + j] = (float) s[i] * mult;
}
}
}
static inline void
_fs_convert_s_s (short * src, short * dest, long samples)
{
memcpy (dest, src, samples * sizeof (short));
}
static inline void
_fs_convert_s_i (short * src, int * dest, long samples)
{
int i;
for (i = 0; i < samples; i++) {
dest[i] = (int) src[i];
}
}
static inline void
_fs_convert_s_f (short * src, float * dest, long samples, float mult)
{
int i;
for (i = 0; i < samples; i++) {
dest[i] = (float) src[i] * mult;
}
}
static inline void
_fs_convert_s_d (short * src, double * dest, long samples, double mult)
{
int i;
for (i = 0; i < samples; i++) {
dest[i] = ((double)src[i]) * mult;
}
}
static inline void
_fs_convert_i_s (int * src, short * dest, long samples)
{
int i;
for (i = 0; i < samples; i++) {
dest[i] = (short) src[i];
}
}
static inline void
_fs_convert_i_f (int * src, float * dest, long samples, float mult)
{
int i;
for (i = 0; i < samples; i++) {
dest[i] = (float) src[i] * mult;
}
}
static inline void
_fs_convert_f_s (float * src, short * dest, long samples, float mult)
{
int i;
for (i = 0; i < samples; i++) {
dest[i] = (short) (src[i] * mult);
}
}
static inline void
_fs_convert_f_i (float * src, int * dest, long samples, float mult)
{
int i;
for (i = 0; i < samples; i++) {
dest[i] = (int) (src[i] * mult);
}
}
static inline void
_fs_convert_f_f (float * src, float * dest, long samples, float mult)
{
int i;
for (i = 0; i < samples; i++) {
dest[i] = src[i] * mult;
}
}
static inline void
_fs_convert_f_d (float * src, double * dest, long samples, double mult)
{
int i;
for (i = 0; i < samples; i++) {
dest[i] = (double)src[i] * mult;
}
}
static inline void
_fs_convert_d_s (double * src, short * dest, long samples, double mult)
{
int i;
for (i = 0; i < samples; i++) {
dest[i] = (short) (src[i] * mult);
}
}
static inline void
_fs_convert_d_f (double * src, float * dest, long samples, float mult)
{
int i;
for (i = 0; i < samples; i++) {
dest[i] = (float)src[i] * mult;
}
}
#endif /* __FISH_SOUND_CONVERT_C_H__ */

Просмотреть файл

@ -1,393 +0,0 @@
/*
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.
*/
/*
* David Schleef, ds@schleef.org
* January, 2005
*/
#ifndef __FISH_SOUND_CONVERT_OIL_H__
#define __FISH_SOUND_CONVERT_OIL_H__
#include <string.h>
#include <ogg/ogg.h>
#include <liboil/liboil.h>
/* inline functions */
static inline void
_fs_deinterleave_s_s (short ** src, short * dest[],
long frames, int channels)
{
int j;
short * s = (short *)src;
#define oil_restride_s16(a,b,c,d,e) oil_conv_u16_s16((uint16_t *)a,b,c,d,e)
for (j = 0; j < channels; j++) {
oil_restride_s16 (dest[j], sizeof(short), s + j,
channels * sizeof(short), frames);
}
}
static inline void
_fs_deinterleave_s_i (short ** src, int * dest[], long frames, int channels)
{
int j;
short * s = (short *)src;
for (j = 0; j < channels; j++) {
oil_conv_s32_s16 (dest[j], sizeof(int), s + j,
channels * sizeof(short), frames);
}
}
static inline void
_fs_deinterleave_s_f (short ** src, float * dest[], long frames, int channels,
float mult)
{
int j;
short * s = (short *)src;
for (j = 0; j < channels; j++) {
oil_conv_f32_s16 (dest[j], sizeof(float), s + j,
channels * sizeof(short), frames);
oil_scalarmult_f32 (dest[j], sizeof (float), dest[j], sizeof(float),
&mult, frames);
}
}
static inline void
_fs_deinterleave_s_d (short ** src, double * dest[], long frames, int channels,
double mult)
{
int j;
short * s = (short *)src;
for (j = 0; j < channels; j++) {
oil_conv_f64_s16 (dest[j], sizeof(double), s + j,
channels * sizeof(short), frames);
oil_scalarmult_f64 (dest[j], sizeof (double), dest[j], sizeof (double),
&mult, frames);
}
}
static inline void
_fs_deinterleave_f_s (float ** src, short * dest[],
long frames, int channels, float mult)
{
int i, j;
float * s = (float *)src;
short * d;
/* FIXME: this needs a temporary buffer for liboil */
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
d = dest[j];
d[i] = (short) (s[i*channels + j] * mult);
}
}
}
static inline void
_fs_deinterleave_f_i (float ** src, int * dest[],
long frames, int channels, float mult)
{
int i, j;
float * s = (float *)src;
int * d;
/* FIXME: this needs a temporary buffer for liboil */
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
d = dest[j];
d[i] = (int) (s[i*channels + j] * mult);
}
}
}
static inline void
_fs_deinterleave_f_f (float ** src, float * dest[],
long frames, int channels, float mult)
{
int j;
float * s = (float *)src;
for (j = 0; j < channels; j++) {
oil_scalarmult_f32 (dest[j], sizeof(float), s + j,
channels * sizeof(float), &mult, frames);
}
}
static inline void
_fs_deinterleave_f_d (float ** src, double * dest[],
long frames, int channels, double mult)
{
int j;
float * s = (float *)src;
for (j = 0; j < channels; j++) {
oil_conv_f64_f32 (dest[j], sizeof(double), s + j,
channels * sizeof(float), frames);
oil_scalarmult_f64 (dest[j], sizeof(double), dest[j],
sizeof(double), &mult, frames);
}
}
static inline void
_fs_interleave_f_s (float * src[], short ** dest,
long frames, int channels, float mult)
{
int i, j;
float * s;
short * d = (short *)dest;
/* FIXME: this needs a temporary buffer for liboil */
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
s = src[j];
d[i*channels + j] = (short) (s[i] * mult);
}
}
}
static inline void
_fs_interleave_s_s (short * src[], short ** dest,
long frames, int channels)
{
int j;
short * d = (short *)dest;
for (j = 0; j < channels; j++) {
oil_restride_s16 (d + j, sizeof (short) * channels, src[j],
sizeof (short), frames);
}
}
static inline void
_fs_interleave_s_f (short * src[], float ** dest,
long frames, int channels, float mult)
{
int j;
float * d = (float *)dest;
for (j = 0; j < channels; j++) {
oil_conv_f32_s16 (d + j, sizeof (float) * channels, src[j],
sizeof (short), frames);
}
oil_scalarmult_f32 (d, sizeof(float), d, sizeof(float), &mult,
channels * frames);
}
static inline ogg_int32_t CLIP_TO_15(ogg_int32_t x) {
int ret=x;
ret-= ((x<=32767)-1)&(x-32767);
ret-= ((x>=-32768)-1)&(x+32768);
return(ret);
}
static inline void
_fs_interleave_i_s (ogg_int32_t * src[], short ** dest,
long frames, int channels, int shift)
{
int i, j;
ogg_int32_t * s;
short * d = (short *)dest;
/* FIXME: shouldn't this use shift? */
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
s = src[j];
d[i*channels + j] = (short) CLIP_TO_15(s[i]>>9);
}
}
}
static inline void
_fs_interleave_i_f (int * src[], float ** dest,
long frames, int channels, float mult)
{
int j;
float * d = (float *)dest;
for (j = 0; j < channels; j++) {
oil_conv_f32_s32 (d + j, sizeof (float) * channels, src[j],
sizeof (int), frames);
}
oil_scalarmult_f32 (d, sizeof(float), d, sizeof(float), &mult,
channels * frames);
}
static inline void
_fs_interleave_f_f (float * src[], float ** dest,
long frames, int channels, float mult)
{
int j;
float * d = (float *)dest;
for (j = 0; j < channels; j++) {
oil_scalarmult_f32 (d + j, sizeof (float) * channels, src[j],
sizeof (float), &mult, frames);
}
}
static inline void
_fs_interleave_d_s (double * src[], short ** dest,
long frames, int channels, double mult)
{
int i, j;
double * s;
short * d = (short *)dest;
/* FIXME: needs temporary buffer */
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
s = src[j];
d[i*channels + j] = (short) (s[i] * mult);
}
}
}
static inline void
_fs_interleave_d_f (double * src[], float ** dest,
long frames, int channels, float mult)
{
int j;
float * d = (float *)dest;
for (j = 0; j < channels; j++) {
oil_conv_f32_f64 (d + j, sizeof (float) * channels, src[j],
sizeof (double), frames);
}
oil_scalarmult_f32 (d, sizeof(float), d, sizeof(float), &mult,
channels * frames);
}
static inline void
_fs_convert_s_s (short * src, short * dest, long samples)
{
memcpy (dest, src, samples * sizeof (short));
}
static inline void
_fs_convert_s_i (short * src, int * dest, long samples)
{
oil_conv_s32_s16 (dest, sizeof(int), src, sizeof(short), samples);
}
static inline void
_fs_convert_s_f (short * src, float * dest, long samples, float mult)
{
oil_conv_f32_s16 (dest, sizeof(float), src, sizeof(short), samples);
oil_scalarmult_f32 (dest, sizeof(float), dest, sizeof(float), &mult, samples);
}
static inline void
_fs_convert_s_d (short * src, double * dest, long samples, double mult)
{
oil_conv_f64_s16 (dest, sizeof(double), src, sizeof(short), samples);
oil_scalarmult_f64 (dest, sizeof(double), dest, sizeof(double), &mult,
samples);
}
static inline void
_fs_convert_i_s (int * src, short * dest, long samples)
{
/* FIXME: should this clip? */
oil_conv_s16_s32 (dest, sizeof(dest), src, sizeof(int), samples);
/* oil_clipconv_s16_s32 (dest, sizeof(dest), src, sizeof(int), samples); */
}
static inline void
_fs_convert_i_f (int * src, float * dest, long samples, float mult)
{
oil_conv_f32_s32 (dest, sizeof(float), src, sizeof(int), samples);
oil_scalarmult_f32 (dest, sizeof(float), dest, sizeof(float), &mult, samples);
}
static inline void
_fs_convert_f_s (float * src, short * dest, long samples, float mult)
{
int i;
/* FIXME: needs temp buffer */
for (i = 0; i < samples; i++) {
dest[i] = (short) (src[i] * mult);
}
}
static inline void
_fs_convert_f_i (float * src, int * dest, long samples, float mult)
{
int i;
/* FIXME: needs temp buffer */
for (i = 0; i < samples; i++) {
dest[i] = (int) (src[i] * mult);
}
}
static inline void
_fs_convert_f_f (float * src, float * dest, long samples, float mult)
{
oil_scalarmult_f32 (dest, sizeof(float), src, sizeof(float), &mult, samples);
}
static inline void
_fs_convert_f_d (float * src, double * dest, long samples, double mult)
{
oil_conv_f64_f32 (dest, sizeof(double), src, sizeof(float), samples);
oil_scalarmult_f64 (dest, sizeof(double), dest, sizeof(double), &mult, samples);
}
static inline void
_fs_convert_d_s (double * src, short * dest, long samples, double mult)
{
int i;
/* FIXME: needs temp buffer */
for (i = 0; i < samples; i++) {
dest[i] = (short) (src[i] * mult);
}
}
static inline void
_fs_convert_d_f (double * src, float * dest, long samples, float mult)
{
int i;
/* FIXME: needs temp buffer */
for (i = 0; i < samples; i++) {
dest[i] = (float)src[i] * mult;
}
}
#endif /* __FISH_SOUND_CONVERT_OIL_H__ */

Просмотреть файл

@ -1,92 +0,0 @@
/*
* A generic debugging printer.
*
* Conrad Parker <conrad@metadecks.org>, May 2009
*
* Usage:
*
* #define DEBUG_LEVEL 3
* #include "debug.h"
*
* ...
* debug_printf (2, "Something went wrong");
* ...
*
* The macro print_debug(level, fmt) prints a formatted debugging message
* of level 'level' to stderr. You should set the maximum tolerable debug
* level before including debug.h. If it is 0, or if neither DEBUG_LEVEL
* nor DEBUG are defined, then the debug_printf() macro is ignored, and
* none of this file is included.
*/
#ifndef __DEBUG_H__
#define __DEBUG_H__
/* MSVC can't handle C99 */
#if (defined (_MSCVER) || defined (_MSC_VER))
#define debug_printf //
#else
#ifdef DEBUG
#ifndef DEBUG_LEVEL
#define DEBUG_LEVEL 1
#endif
#endif
#if (DEBUG_LEVEL > 0)
#define DEBUG_MAXLINE 4096
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
/*
* debug_print_err (func, line, fmt)
*
* Print a formatted error message to stderr.
*/
static void
debug_print_err (const char * func, int line, const char * fmt, ...)
{
va_list ap;
int errno_save;
char buf[DEBUG_MAXLINE];
int n=0;
errno_save = errno;
va_start (ap, fmt);
if (func) {
snprintf (buf+n, DEBUG_MAXLINE-n, "%s():%d: ", func, line);
n = strlen (buf);
}
vsnprintf (buf+n, DEBUG_MAXLINE-n, fmt, ap);
n = strlen (buf);
fflush (stdout); /* in case stdout and stderr are the same */
fputs (buf, stderr);
fputc ('\n', stderr);
fflush (NULL);
va_end (ap);
}
/*
* debug_printf (level, fmt)
*
* Print a formatted debugging message of level 'level' to stderr
*/
#define debug_printf(x,y...) {if (x <= DEBUG_LEVEL) debug_print_err (__func__, __LINE__, y);}
#undef MAXLINE
#else
#define debug_printf(x,y...)
#endif
#endif /* non-C99 */
#endif /* __DEBUG_H__ */

Просмотреть файл

@ -1,254 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include "private.h"
int
fish_sound_identify (unsigned char * buf, long bytes)
{
if (bytes < 8) return FISH_SOUND_ERR_SHORT_IDENTIFY;
if (HAVE_VORBIS &&
fish_sound_vorbis_identify (buf, bytes) != FISH_SOUND_UNKNOWN)
return FISH_SOUND_VORBIS;
if (HAVE_SPEEX &&
fish_sound_speex_identify (buf, bytes) != FISH_SOUND_UNKNOWN)
return FISH_SOUND_SPEEX;
if (fish_sound_flac_identify (buf, bytes) != FISH_SOUND_UNKNOWN)
return FISH_SOUND_FLAC;
return FISH_SOUND_UNKNOWN;
}
int
fish_sound_set_format (FishSound * fsound, int format)
{
if (format == FISH_SOUND_VORBIS) {
fsound->codec = fish_sound_vorbis_codec ();
} else if (format == FISH_SOUND_SPEEX) {
fsound->codec = fish_sound_speex_codec ();
} else if (format == FISH_SOUND_FLAC) {
fsound->codec = fish_sound_flac_codec ();
} else {
return -1;
}
if (fsound->codec && fsound->codec->init)
if (fsound->codec->init (fsound) == NULL) return -1;
fsound->info.format = format;
return format;
}
FishSound *
fish_sound_new (int mode, FishSoundInfo * fsinfo)
{
FishSound * fsound;
if (!FS_DECODE && mode == FISH_SOUND_DECODE) return NULL;
if (!FS_ENCODE && mode == FISH_SOUND_ENCODE) return NULL;
if (mode == FISH_SOUND_ENCODE) {
if (fsinfo == NULL) {
return NULL;
} else {
if (!(HAVE_VORBIS && HAVE_VORBISENC)) {
if (fsinfo->format == FISH_SOUND_VORBIS) return NULL;
}
if (!HAVE_SPEEX) {
if (fsinfo->format == FISH_SOUND_SPEEX) return NULL;
}
if (!HAVE_FLAC) {
if (fsinfo->format == FISH_SOUND_FLAC) return NULL;
}
}
} else if (mode != FISH_SOUND_DECODE) {
return NULL;
}
fsound = fs_malloc (sizeof (FishSound));
if (fsound == NULL) return NULL;
fsound->mode = mode;
fsound->interleave = 0;
fsound->frameno = 0;
fsound->next_granulepos = -1;
fsound->next_eos = 0;
fsound->codec = NULL;
fsound->codec_data = NULL;
fsound->callback.encoded = NULL;
fsound->user_data = NULL;
fish_sound_comments_init (fsound);
if (mode == FISH_SOUND_DECODE) {
fsound->info.samplerate = 0;
fsound->info.channels = 0;
fsound->info.format = FISH_SOUND_UNKNOWN;
} else if (mode == FISH_SOUND_ENCODE) {
fsound->info.samplerate = fsinfo->samplerate;
fsound->info.channels = fsinfo->channels;
fsound->info.format = fsinfo->format;
if (fish_sound_set_format (fsound, fsinfo->format) == -1) {
fs_free (fsound);
return NULL;
}
}
return fsound;
}
long
fish_sound_flush (FishSound * fsound)
{
if (fsound == NULL) return -1;
if (fsound->codec && fsound->codec->flush)
return fsound->codec->flush (fsound);
return 0;
}
int
fish_sound_reset (FishSound * fsound)
{
if (fsound == NULL) return -1;
if (fsound->codec && fsound->codec->reset)
return fsound->codec->reset (fsound);
return 0;
}
FishSound *
fish_sound_delete (FishSound * fsound)
{
if (fsound == NULL) return NULL;
if (fsound->codec && fsound->codec->del)
fsound->codec->del (fsound);
fs_free (fsound->codec);
fish_sound_comments_free (fsound);
fs_free (fsound);
return NULL;
}
int
fish_sound_command (FishSound * fsound, int command, void * data, int datasize)
{
FishSoundInfo * fsinfo = (FishSoundInfo *)data;
int * pi = (int *)data;
if (fsound == NULL) return -1;
switch (command) {
case FISH_SOUND_GET_INFO:
memcpy (fsinfo, &fsound->info, sizeof (FishSoundInfo));
break;
case FISH_SOUND_GET_INTERLEAVE:
*pi = fsound->interleave;
break;
case FISH_SOUND_SET_INTERLEAVE:
fsound->interleave = (*pi ? 1 : 0);
break;
default:
if (fsound->codec && fsound->codec->command)
return fsound->codec->command (fsound, command, data, datasize);
break;
}
return 0;
}
int
fish_sound_get_interleave (FishSound * fsound)
{
if (fsound == NULL) return -1;
return fsound->interleave;
}
#ifndef FS_DISABLE_DEPRECATED
int
fish_sound_set_interleave (FishSound * fsound, int interleave)
{
if (fsound == NULL) return -1;
fsound->interleave = (interleave ? 1 : 0);
return 0;
}
#endif
long
fish_sound_get_frameno (FishSound * fsound)
{
if (fsound == NULL) return -1L;
return fsound->frameno;
}
int
fish_sound_set_frameno (FishSound * fsound, long frameno)
{
if (fsound == NULL) return -1;
fsound->frameno = frameno;
return 0;
}
int
fish_sound_prepare_truncation (FishSound * fsound, long next_granulepos,
int next_eos)
{
if (fsound == NULL) return -1;
fsound->next_granulepos = next_granulepos;
fsound->next_eos = next_eos;
return 0;
}

Просмотреть файл

@ -1,654 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h> /* ULONG_MAX */
#ifndef WIN32
#include <strings.h>
#endif
#include "private.h"
/*#define DEBUG*/
#include "debug.h"
/* Ensure comment vector length can be expressed in 32 bits
* including space for the trailing NUL */
#define MAX_COMMENT_LENGTH 0xFFFFFFFE
#define fs_comment_clamp(c) MIN((c),MAX_COMMENT_LENGTH)
static size_t
fs_comment_len (const char * s)
{
size_t len;
if (s == NULL) return 0;
len = strlen (s);
return fs_comment_clamp(len);
}
static char *
fs_strdup (const char * s)
{
char * ret;
if (s == NULL) return NULL;
ret = fs_malloc (fs_comment_len(s) + 1);
if (ret == NULL) return NULL;
return strcpy (ret, s);
}
static char *
fs_strdup_len (const char * s, size_t len)
{
char * ret;
if (s == NULL) return NULL;
if (len == 0) return NULL;
len = fs_comment_clamp(len);
ret = fs_malloc (len + 1);
if (ret == NULL) return NULL;
if (strncpy (ret, s, len) == NULL) {
fs_free (ret);
return NULL;
}
ret[len] = '\0';
return ret;
}
static char *
fs_index_len (const char * s, char c, int len)
{
int i;
for (i = 0; *s && i < len; i++, s++) {
if (*s == c) return (char *)s;
}
if (i < len) return (char *)s;
return NULL;
}
/*
Comments will be stored in the Vorbis style.
It is describled in the "Structure" section of
http://www.xiph.org/ogg/vorbis/doc/v-comment.html
The comment header is decoded as follows:
1) [vendor_length] = read an unsigned integer of 32 bits
2) [vendor_string] = read a UTF-8 vector as [vendor_length] octets
3) [user_comment_list_length] = read an unsigned integer of 32 bits
4) iterate [user_comment_list_length] times {
5) [length] = read an unsigned integer of 32 bits
6) this iteration's user comment = read a UTF-8 vector as [length] octets
}
7) [framing_bit] = read a single bit as boolean
8) if ( [framing_bit] unset or end of packet ) then ERROR
9) done.
If you have troubles, please write to ymnk@jcraft.com.
*/
#define readint(buf, base) (((buf[base+3]<<24)&0xff000000)| \
((buf[base+2]<<16)&0xff0000)| \
((buf[base+1]<<8)&0xff00)| \
(buf[base]&0xff))
#define writeint(buf, base, val) do{ buf[base+3]=((val)>>24)&0xff; \
buf[base+2]=((val)>>16)&0xff; \
buf[base+1]=((val)>>8)&0xff; \
buf[base]=(val)&0xff; \
}while(0)
static int
fs_comment_validate_byname (const char * name, const char * value)
{
const char * c;
if (!name || !value) return 0;
for (c = name; *c; c++) {
if (*c < 0x20 || *c > 0x7D || *c == 0x3D) {
debug_printf (1, "XXX char %c in %s invalid", *c, name);
return 0;
}
}
/* XXX: we really should validate value as UTF-8 here, but ... */
return 1;
}
static FishSoundComment *
fs_comment_new (const char * name, const char * value)
{
FishSoundComment * comment;
if (!fs_comment_validate_byname (name, value)) return NULL;
/* Ensures that name != NULL, value != NULL, and validates strings */
comment = fs_malloc (sizeof (FishSoundComment));
if (comment == NULL) return NULL;
comment->name = fs_strdup (name);
if (comment->name == NULL) {
fs_free (comment);
return NULL;
}
comment->value = fs_strdup (value);
if (comment->value == NULL) {
fs_free (comment->name);
fs_free (comment);
return NULL;
}
return comment;
}
static void
fs_comment_free (FishSoundComment * comment)
{
if (!comment) return;
if (comment->name) fs_free (comment->name);
if (comment->value) fs_free (comment->value);
fs_free (comment);
}
static int
fs_comment_cmp (const FishSoundComment * comment1, const FishSoundComment * comment2)
{
if (comment1 == comment2) return 1;
if (!comment1 || !comment2) return 0;
if (strcasecmp (comment1->name, comment2->name)) return 0;
if (strcmp (comment1->value, comment2->value)) return 0;
return 1;
}
int
fish_sound_comment_set_vendor (FishSound * fsound, const char * vendor_string)
{
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
if (fsound->vendor) fs_free (fsound->vendor);
if ((fsound->vendor = fs_strdup (vendor_string)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
return 0;
}
/* Public API */
const char *
fish_sound_comment_get_vendor (FishSound * fsound)
{
if (fsound == NULL) return NULL;
return fsound->vendor;
}
const FishSoundComment *
fish_sound_comment_first (FishSound * fsound)
{
if (fsound == NULL) return NULL;
return fs_vector_nth (fsound->comments, 0);
}
const FishSoundComment *
fish_sound_comment_first_byname (FishSound * fsound, char * name)
{
FishSoundComment * comment;
int i;
if (fsound == NULL) return NULL;
if (name == NULL) return fs_vector_nth (fsound->comments, 0);
if (!fs_comment_validate_byname (name, ""))
return NULL;
for (i = 0; i < fs_vector_size (fsound->comments); i++) {
comment = (FishSoundComment *) fs_vector_nth (fsound->comments, i);
if (comment->name && !strcasecmp (name, comment->name))
return comment;
}
return NULL;
}
const FishSoundComment *
fish_sound_comment_next (FishSound * fsound, const FishSoundComment * comment)
{
int i;
if (fsound == NULL || comment == NULL) return NULL;
i = fs_vector_find_index (fsound->comments, comment);
return fs_vector_nth (fsound->comments, i+1);
}
const FishSoundComment *
fish_sound_comment_next_byname (FishSound * fsound,
const FishSoundComment * comment)
{
FishSoundComment * v_comment;
int i;
if (fsound == NULL || comment == NULL) return NULL;
i = fs_vector_find_index (fsound->comments, comment);
for (i++; i < fs_vector_size (fsound->comments); i++) {
v_comment = (FishSoundComment *) fs_vector_nth (fsound->comments, i);
if (v_comment->name && !strcasecmp (comment->name, v_comment->name))
return v_comment;
}
return NULL;
}
#define _fs_comment_add(f,c) fs_vector_insert ((f)->comments, (c))
int
fish_sound_comment_add (FishSound * fsound, FishSoundComment * comment)
{
#if FS_ENCODE
FishSoundComment * new_comment;
#endif
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
if (fsound->mode != FISH_SOUND_ENCODE)
return FISH_SOUND_ERR_INVALID;
#if FS_ENCODE
if (!fs_comment_validate_byname (comment->name, comment->value))
return FISH_SOUND_ERR_COMMENT_INVALID;
if ((new_comment = fs_comment_new (comment->name, comment->value)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
if (_fs_comment_add (fsound, new_comment) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
return FISH_SOUND_OK;
#else
return FISH_SOUND_ERR_DISABLED;
#endif
}
int
fish_sound_comment_add_byname (FishSound * fsound, const char * name,
const char * value)
{
#if FS_ENCODE
FishSoundComment * comment;
#endif
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
if (fsound->mode != FISH_SOUND_ENCODE)
return FISH_SOUND_ERR_INVALID;
#if FS_ENCODE
if (!fs_comment_validate_byname (name, value))
return FISH_SOUND_ERR_COMMENT_INVALID;
if ((comment = fs_comment_new (name, value)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
if (_fs_comment_add (fsound, comment) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
return FISH_SOUND_OK;
return 0;
#else
return FISH_SOUND_ERR_DISABLED;
#endif
}
int
fish_sound_comment_remove (FishSound * fsound, FishSoundComment * comment)
{
#if FS_ENCODE
FishSoundComment * v_comment;
#endif
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
if (fsound->mode != FISH_SOUND_ENCODE)
return FISH_SOUND_ERR_INVALID;
#if FS_ENCODE
v_comment = fs_vector_find (fsound->comments, comment);
if (v_comment == NULL) return 0;
fs_vector_remove (fsound->comments, v_comment);
fs_comment_free (v_comment);
return 1;
#else
return FISH_SOUND_ERR_DISABLED;
#endif
}
int
fish_sound_comment_remove_byname (FishSound * fsound, char * name)
{
#if FS_ENCODE
FishSoundComment * comment;
int i;
#endif
int ret = 0;
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
if (fsound->mode != FISH_SOUND_ENCODE)
return FISH_SOUND_ERR_INVALID;
#if FS_ENCODE
for (i = 0; i < fs_vector_size (fsound->comments); i++) {
comment = (FishSoundComment *) fs_vector_nth (fsound->comments, i);
if (!strcasecmp (name, comment->name)) {
fish_sound_comment_remove (fsound, comment);
i--;
ret++;
}
}
return ret;
#else
return FISH_SOUND_ERR_DISABLED;
#endif
}
/* Internal API */
int
fish_sound_comments_init (FishSound * fsound)
{
fsound->vendor = NULL;
fsound->comments = fs_vector_new ((FishSoundCmpFunc) fs_comment_cmp);
return 0;
}
int
fish_sound_comments_free (FishSound * fsound)
{
fs_vector_foreach (fsound->comments, (FishSoundFunc)fs_comment_free);
fs_vector_delete (fsound->comments);
fsound->comments = NULL;
if (fsound->vendor) fs_free (fsound->vendor);
fsound->vendor = NULL;
return 0;
}
int
fish_sound_comments_decode (FishSound * fsound, unsigned char * comments,
long length)
{
char *c= (char *)comments;
int i, nb_fields, n;
size_t len;
char *end;
char * name, * value, * nvalue = NULL;
FishSoundComment * comment;
if (length<8)
return -1;
end = c+length;
len=readint(c, 0);
c+=4;
if (len > (unsigned long) length - 4) return -1;
/* Vendor */
if (len > 0) {
if ((nvalue = fs_strdup_len (c, len)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
if (fish_sound_comment_set_vendor (fsound, nvalue) == FISH_SOUND_ERR_OUT_OF_MEMORY) {
fs_free (nvalue);
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
fs_free (nvalue);
}
#ifdef DEBUG
fwrite(c, 1, len, stderr); fputc ('\n', stderr);
#endif
c+=len;
if (c+4>end) return -1;
/* This value gets checked effectively by the 'for' condition
and the checks within the loop for c running off the end. */
nb_fields=readint(c, 0);
debug_printf (1, "%d comments", nb_fields);
c+=4;
for (i=0;i<nb_fields;i++)
{
if (c+4>end) return -1;
len=readint(c, 0);
debug_printf (1, "[%d] len %d\n", i, len);
c+=4;
if (len > (unsigned long) (end-c)) return -1;
name = c;
value = fs_index_len (c, '=', len);
n = 0;
if (value) {
*value = '\0';
value++;
n = c+len - value;
}
if (n) {
if ((nvalue = fs_strdup_len (value, n)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
debug_printf (1, "%s -> %s (length %d)", name, nvalue, n);
if ((comment = fs_comment_new (name, nvalue)) == NULL) {
fs_free (nvalue);
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
if (_fs_comment_add (fsound, comment) == NULL) {
fs_free (nvalue);
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
fs_free (nvalue);
} else if (len > 0) {
debug_printf (1, "[%d] %s (no value)", i, name, len);
if ((nvalue = fs_strdup_len (name, len)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
if ((comment = fs_comment_new (nvalue, "")) == NULL) {
fs_free (nvalue);
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
if (_fs_comment_add (fsound, comment) == NULL) {
fs_free (nvalue);
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
fs_free (nvalue);
}
c+=len;
}
debug_printf (1, "OUT");
return FISH_SOUND_OK;
}
/*
* Pre-condition: at least one of accum, delta are non-zero,
* ie. don't call accum_length (0, 0);
* \retval 0 Failure: integer overflow
*/
static unsigned long
accum_length (unsigned long * accum, unsigned long delta)
{
/* Pre-condition: don't call accum_length (0, 0) */
if (*accum == 0 && delta == 0)
return 0;
/* Check for integer overflow */
if (delta > ULONG_MAX - (*accum))
return 0;
*accum += delta;
return *accum;
}
long
fish_sound_comments_encode (FishSound * fsound, unsigned char * buf,
long length)
{
char * c = (char *)buf;
const FishSoundComment * comment;
int nb_fields = 0, vendor_length = 0;
unsigned long actual_length = 0, remaining = length, field_length;
/* Vendor string */
if (fsound->vendor)
vendor_length = fs_comment_len (fsound->vendor);
if (accum_length (&actual_length, 4 + vendor_length) == 0)
return 0;
/* user comment list length */
if (accum_length (&actual_length, 4) == 0)
return 0;
for (comment = fish_sound_comment_first (fsound); comment;
comment = fish_sound_comment_next (fsound, comment)) {
/* [size]"name" */
if (accum_length (&actual_length, 4 + fs_comment_len (comment->name)) == 0)
return 0;
if (comment->value) {
/* "=value" */
if (accum_length (&actual_length, 1 + fs_comment_len (comment->value)) == 0)
return 0;
}
debug_printf (1, "%s = %s", comment->name, comment->value);
nb_fields++;
}
/* framing bit */
if (accum_length (&actual_length, 1) == 0)
return 0;
/* NB. actual_length is not modified from here onwards */
if (buf == NULL) return actual_length;
remaining -= 4;
if (remaining <= 0) return actual_length;
writeint (c, 0, vendor_length);
c += 4;
if (fsound->vendor) {
field_length = fs_comment_len (fsound->vendor);
memcpy (c, fsound->vendor, MIN (field_length, remaining));
c += field_length; remaining -= field_length;
if (remaining <= 0) return actual_length;
}
remaining -= 4;
if (remaining <= 0) return actual_length;
writeint (c, 0, nb_fields);
c += 4;
for (comment = fish_sound_comment_first (fsound); comment;
comment = fish_sound_comment_next (fsound, comment)) {
field_length = fs_comment_len (comment->name); /* [size]"name" */
if (comment->value)
field_length += 1 + fs_comment_len (comment->value); /* "=value" */
remaining -= 4;
if (remaining <= 0) return actual_length;
writeint (c, 0, field_length);
c += 4;
field_length = fs_comment_len (comment->name);
memcpy (c, comment->name, MIN (field_length, remaining));
c += field_length; remaining -= field_length;
if (remaining <= 0) return actual_length;
if (comment->value) {
remaining --;
if (remaining <= 0) return actual_length;
*c = '=';
c++;
field_length = fs_comment_len (comment->value);
memcpy (c, comment->value, MIN (field_length, remaining));
c += field_length; remaining -= field_length;
if (remaining <= 0) return actual_length;
}
}
if (remaining <= 0) return actual_length;
*c = 0x01;
return actual_length;
}

Просмотреть файл

@ -1,136 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include "private.h"
static int
fs_decode_update (FishSound * fsound, int interleave)
{
int ret = 0;
if (fsound->codec && fsound->codec->update)
ret = fsound->codec->update (fsound, interleave);
if (ret >= 0) {
fsound->interleave = interleave;
}
return ret;
}
int fish_sound_set_decoded_float (FishSound * fsound,
FishSoundDecoded_Float decoded,
void * user_data)
{
int ret = 0;
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
#if FS_DECODE
ret = fs_decode_update (fsound, 0);
if (ret >= 0) {
fsound->callback.decoded_float = decoded;
fsound->user_data = user_data;
}
#else
return FISH_SOUND_ERR_DISABLED;
#endif
return ret;
}
int fish_sound_set_decoded_float_ilv (FishSound * fsound,
FishSoundDecoded_FloatIlv decoded,
void * user_data)
{
int ret = 0;
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
#if FS_DECODE
ret = fs_decode_update (fsound, 1);
if (ret >= 0) {
fsound->callback.decoded_float_ilv = decoded;
fsound->user_data = user_data;
}
#else
return FISH_SOUND_ERR_DISABLED;
#endif
return ret;
}
long
fish_sound_decode (FishSound * fsound, unsigned char * buf, long bytes)
{
int format;
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
#if FS_DECODE
if (fsound->info.format == FISH_SOUND_UNKNOWN) {
format = fish_sound_identify (buf, bytes);
if (format == FISH_SOUND_UNKNOWN) return -1;
fish_sound_set_format (fsound, format);
}
/*printf ("format: %s\n", fsound->codec->format->name);*/
if (fsound->codec && fsound->codec->decode)
return fsound->codec->decode (fsound, buf, bytes);
#else
return FISH_SOUND_ERR_DISABLED;
#endif
return 0;
}
/* DEPRECATED */
int fish_sound_set_decoded_callback (FishSound * fsound,
FishSoundDecoded_Float decoded,
void * user_data)
{
if (fsound == NULL) return -1;
return fsound->interleave ?
fish_sound_set_decoded_float_ilv (fsound, decoded, user_data) :
fish_sound_set_decoded_float (fsound, decoded, user_data);
}

Просмотреть файл

@ -1,106 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <stdio.h>
#include <string.h>
#include "private.h"
int
fish_sound_set_encoded_callback (FishSound * fsound,
FishSoundEncoded encoded,
void * user_data)
{
if (fsound == NULL) return -1;
#if FS_ENCODE
fsound->callback.encoded = (void *)encoded;
fsound->user_data = user_data;
#else
return FISH_SOUND_ERR_DISABLED;
#endif
return 0;
}
long fish_sound_encode_float (FishSound * fsound, float * pcm[], long frames)
{
if (fsound == NULL) return -1;
#if FS_ENCODE
if (fsound->codec && fsound->codec->encode_f)
return fsound->codec->encode_f (fsound, pcm, frames);
#else
return FISH_SOUND_ERR_DISABLED;
#endif
return 0;
}
long fish_sound_encode_float_ilv (FishSound * fsound, float ** pcm,
long frames)
{
if (fsound == NULL) return -1;
#if FS_ENCODE
if (fsound->codec && fsound->codec->encode_f_ilv)
return fsound->codec->encode_f_ilv (fsound, pcm, frames);
#else
return FISH_SOUND_ERR_DISABLED;
#endif
return 0;
}
#ifndef FS_DISABLE_DEPRECATED
long
fish_sound_encode (FishSound * fsound, float ** pcm, long frames)
{
if (fsound == NULL) return -1;
#if FS_ENCODE
if (fsound->interleave) {
if (fsound->codec && fsound->codec->encode_f_ilv)
return fsound->codec->encode_f_ilv (fsound, pcm, frames);
} else {
if (fsound->codec && fsound->codec->encode_f)
return fsound->codec->encode_f (fsound, pcm, frames);
}
#else
return FISH_SOUND_ERR_DISABLED;
#endif
return 0;
}
#endif /* DEPRECATED */

Просмотреть файл

@ -1,851 +0,0 @@
/*
Copyright (C) 2007 Annodex Association
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of the Annodex Association 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 ASSOCIATION 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.
*/
/* Original patches by Tobias Gehrig, 2005
* http://www.annodex.net/software/libfishsound/libfishsound-flac/
*
* The Ogg FLAC mapping is documented in:
* http://flac.sourceforge.net/ogg_mapping.html
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "private.h"
#include "convert.h"
#define DEBUG_VERBOSE 2
/* #define DEBUG */
/* #define DEBUG_LEVEL DEBUG_VERBOSE */
#include "debug.h"
#if HAVE_FLAC
#include "FLAC/all.h"
#define BITS_PER_SAMPLE 24
typedef struct _FishSoundFlacInfo {
FLAC__StreamDecoder *fsd;
FLAC__StreamEncoder *fse;
unsigned char * buffer;
char header;
long bufferlength;
unsigned long packetno;
struct {
unsigned char major, minor;
} version;
unsigned short header_packets;
void * ipcm;
#if FS_DECODE
float * pcm_out[8]; /* non-interleaved pcm, output (decode only);
* FLAC does max 8 channels */
#endif
#if FS_ENCODE
FLAC__StreamMetadata * enc_vc_metadata; /* FLAC metadata structure for
* vorbiscomments (encode only) */
#endif
} FishSoundFlacInfo;
int
fish_sound_flac_identify (unsigned char * buf, long bytes)
{
if (bytes < 8) return FISH_SOUND_UNKNOWN;
if (buf[0] != 0x7f) return FISH_SOUND_UNKNOWN;
if (!strncmp ((char *)buf+1, "FLAC", 4)) {
debug_printf(1, "flac found");
/* if only a short buffer was passed, do a weak identify */
if (bytes == 8) return FISH_SOUND_FLAC;
/* otherwise, look for the fLaC header preceding STREAMINFO */
if (!strncmp ((char *)buf+9, "fLaC", 4)) {
return FISH_SOUND_FLAC;
}
}
return FISH_SOUND_UNKNOWN;
}
static int
fs_flac_command (FishSound * fsound, int command, void * data, int datasize)
{
return 0;
}
#if FS_DECODE
static FLAC__StreamDecoderReadStatus
fs_flac_read_callback(const FLAC__StreamDecoder *decoder,
FLAC__byte buffer[], unsigned *bytes,
void *client_data)
{
FishSound* fsound = (FishSound*)client_data;
FishSoundFlacInfo* fi = (FishSoundFlacInfo *)fsound->codec_data;
debug_printf(DEBUG_VERBOSE, "fs_flac_read_callback: IN");
if (fi->bufferlength > *bytes) {
debug_printf(1, "too much data");
return FLAC__STREAM_DECODER_READ_STATUS_ABORT;
} else if (fi->bufferlength < 1) {
debug_printf(1, "no data, %ld",fi->bufferlength);
return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
}
memcpy(buffer, fi->buffer, fi->bufferlength);
*bytes = fi->bufferlength;
fi->bufferlength = 0;
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
}
static FLAC__StreamDecoderWriteStatus
fs_flac_write_callback(const FLAC__StreamDecoder *decoder,
const FLAC__Frame *frame,
const FLAC__int32 * const buffer[],
void *client_data)
{
FishSound* fsound = (FishSound*)client_data;
FishSoundFlacInfo* fi = (FishSoundFlacInfo *)fsound->codec_data;
int i, j, channels, blocksize, offset;
float * ipcm;
channels = frame->header.channels;
blocksize = frame->header.blocksize;
debug_printf(DEBUG_VERBOSE, "IN, blocksize %d", blocksize);
fsound->frameno += blocksize;
if (fsound->callback.decoded_float) {
float norm = 1.0 / ((1 << (frame->header.bits_per_sample - 1)));
if (fsound->interleave) {
FishSoundDecoded_FloatIlv dfi;
float* retpcm;
if ((ipcm = realloc(fi->ipcm, sizeof(float) * channels * blocksize)) == NULL)
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
fi->ipcm = ipcm;
retpcm = (float*) fi->ipcm;
for (i = 0; i < blocksize; i++) {
offset = i * channels;
for (j = 0; j < channels; j++)
retpcm[offset + j] = buffer[j][i] * norm;
}
dfi = (FishSoundDecoded_FloatIlv)fsound->callback.decoded_float_ilv;
dfi (fsound, (float **)retpcm, blocksize, fsound->user_data);
} else {
FishSoundDecoded_Float df;
FLAC__int32 * s = (FLAC__int32 *)buffer; /* de-interleave source */
float *d; /* de-interleave dest */
for (j = 0; j < channels; j++) {
if ((ipcm = realloc(fi->pcm_out[j], sizeof(float) * blocksize)) == NULL)
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
fi->pcm_out[j] = ipcm;
}
for (i = 0; i < blocksize; i++)
for (j = 0; j < channels; j++) {
d = fi->pcm_out[j];
d[i] = s[i*channels + j] * norm;
}
df = (FishSoundDecoded_Float)fsound->callback.decoded_float;
df (fsound, fi->pcm_out, blocksize, fsound->user_data);
}
}
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
}
static void
fs_flac_meta_callback(const FLAC__StreamDecoder *decoder,
const FLAC__StreamMetadata *metadata,
void *client_data)
{
FishSound* fsound = (FishSound*)client_data;
/* FishSoundFlacInfo* fi = (FishSoundFlacInfo *)fsound->codec_data; */
debug_printf(1, "IN");
switch (metadata->type) {
case FLAC__METADATA_TYPE_STREAMINFO:
debug_printf(1, "channels %d, samplerate %d",
metadata->data.stream_info.channels,
metadata->data.stream_info.sample_rate);
fsound->info.channels = metadata->data.stream_info.channels;
fsound->info.samplerate = metadata->data.stream_info.sample_rate;
break;
default:
debug_printf(1, "not yet implemented type");
break;
}
}
static void
fs_flac_error_callback(const FLAC__StreamDecoder *decoder,
FLAC__StreamDecoderErrorStatus status,
void *client_data)
{
debug_printf(1, "IN");
fprintf(stderr, "FLAC ERROR: %s\n", FLAC__StreamDecoderErrorStatusString[status]);
}
#endif
#if FS_DECODE
static void*
fs_flac_decode_header (FishSound * fsound, unsigned char *buf, long bytes)
{
FishSoundFlacInfo *fi = fsound->codec_data;
if (bytes < 9) return NULL;
if (buf[0] != 0x7f) return NULL;
if (strncmp((char *)buf+1, "FLAC", 4) != 0) return NULL;
fi->version.major = buf[5];
fi->version.minor = buf[6];
debug_printf(1, "Flac Ogg Mapping Version: %d.%d",
fi->version.major, fi->version.minor);
fi->header_packets = buf[7] << 8 | buf[8];
debug_printf(1, "Number of Header packets: %d", fi->header_packets);
if ((fi->fsd = FLAC__stream_decoder_new()) == NULL) {
debug_printf (1, "unable to create new stream_decoder");
return NULL;
}
#if defined (HAVE_FLAC_1_1_2)
FLAC__stream_decoder_set_read_callback(fi->fsd, fs_flac_read_callback);
FLAC__stream_decoder_set_write_callback(fi->fsd, fs_flac_write_callback);
FLAC__stream_decoder_set_metadata_callback(fi->fsd, fs_flac_meta_callback);
FLAC__stream_decoder_set_error_callback(fi->fsd, fs_flac_error_callback);
FLAC__stream_decoder_set_client_data(fi->fsd, fsound);
if (FLAC__stream_decoder_init(fi->fsd) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
return NULL;
#elif defined (HAVE_FLAC_1_1_3)
if (FLAC__stream_decoder_init_stream
(fi->fsd,
fs_flac_read_callback,
NULL, /* seek callback */
NULL, /* tell callback */
NULL, /* length callback */
NULL, /* EOF callback */
fs_flac_write_callback,
fs_flac_meta_callback,
fs_flac_error_callback,
fsound
) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
return NULL;
#endif
return fi->fsd;
}
static long
fs_flac_decode (FishSound * fsound, unsigned char * buf, long bytes)
{
FishSoundFlacInfo *fi = fsound->codec_data;
debug_printf(DEBUG_VERBOSE, "IN, fi->packetno = %ld", fi->packetno);
if (fi->packetno == 0) {
if (fs_flac_decode_header (fsound, buf, bytes) == NULL) {
debug_printf(1, "Error reading header");
return -1;
}
if ((fi->buffer = fs_malloc(sizeof(unsigned char)*bytes)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
memcpy(fi->buffer, buf+9, bytes-9);
fi->bufferlength = bytes-9;
}
else if (fi->packetno <= fi->header_packets){
unsigned char* tmp;
debug_printf(1, "handling header (fi->header_packets = %d)",
fi->header_packets);
#if 0
if (fi->packetno == 1) fish_sound_comments_decode (fsound, buf, bytes);
#endif
if ((buf[0] & 0x7) == 4) {
int len = (buf[1]<<16) + (buf[2]<<8) + buf[3];
debug_printf (1, "got vorbiscomments len %d", len);
if (fish_sound_comments_decode (fsound, buf+4, len) == FISH_SOUND_ERR_OUT_OF_MEMORY) {
fi->packetno++;
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
}
if ((tmp = fs_malloc(sizeof(unsigned char)*(fi->bufferlength+bytes))) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
memcpy(tmp, fi->buffer, fi->bufferlength);
memcpy(tmp+fi->bufferlength, buf, bytes);
fi->bufferlength += bytes;
fs_free(fi->buffer);
fi->buffer = tmp;
if (fi->packetno == fi->header_packets) {
if (FLAC__stream_decoder_process_until_end_of_metadata(fi->fsd) == false) {
goto dec_err;
}
fs_free(fi->buffer);
}
} else {
fi->buffer = buf;
fi->bufferlength = bytes;
if (FLAC__stream_decoder_process_single(fi->fsd) == false) {
goto dec_err;
}
}
fi->packetno++;
return 0;
dec_err:
switch (FLAC__stream_decoder_get_state(fi->fsd)) {
case FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR:
return FISH_SOUND_ERR_OUT_OF_MEMORY;
default:
return FISH_SOUND_ERR_GENERIC;
}
}
#else /* !FS_DECODE */
#define fs_flac_decode NULL
#endif
#if FS_ENCODE
static FLAC__StreamEncoderWriteStatus
fs_flac_enc_write_callback(const FLAC__StreamEncoder *encoder,
const FLAC__byte buffer[], unsigned bytes,
unsigned samples, unsigned current_frame,
void *client_data)
{
FishSound* fsound = (FishSound*)client_data;
FishSoundFlacInfo *fi = fsound->codec_data;
debug_printf(1, "IN");
debug_printf(1, "bytes: %d, samples: %d", bytes, samples);
if (fsound->callback.encoded) {
FishSoundEncoded encoded = (FishSoundEncoded) fsound->callback.encoded;
if (fi->packetno == 0 && fi->header <= 1) {
if (fi->header == 0) {
/* libFLAC has called us with data containing the normal fLaC header
* and a STREAMINFO block. Prepend the FLAC Ogg mapping header,
* as described in http://flac.sourceforge.net/ogg_mapping.html.
*/
debug_printf(1, "generating FLAC header packet: %c%c%c%c",
buffer[0], buffer[1], buffer[2], buffer[3]);
if ((fi->buffer = (unsigned char*)fs_malloc(sizeof(unsigned char)*(bytes+9))) == NULL)
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
fi->buffer[0] = 0x7f;
fi->buffer[1] = 0x46; /* 'F' */
fi->buffer[2] = 0x4c; /* 'L' */
fi->buffer[3] = 0x41; /* 'A' */
fi->buffer[4] = 0x43; /* 'C' */
fi->buffer[5] = 1; /* Version major generated by this file */
fi->buffer[6] = 0; /* Version minor generated by this file */
fi->buffer[7] = 0; /* MSB(be): Nr. other non-audio header packets */
fi->buffer[8] = 1; /* LSB(be): Nr. other non-audio header packets */
memcpy (fi->buffer+9, buffer, bytes); /* fLaC header ++ STREAMINFO */
fi->bufferlength = bytes+9;
fi->header++;
} else {
/* Make a temporary copy of the metadata header to pass to the user
* callback.
*/
unsigned char* tmp;
if ((tmp = (unsigned char*)fs_malloc(sizeof(unsigned char)*(bytes+fi->bufferlength))) == NULL)
return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
memcpy (tmp, fi->buffer, fi->bufferlength);
memcpy (tmp+fi->bufferlength, buffer, bytes);
fs_free(fi->buffer);
fi->buffer = tmp;
fi->bufferlength += bytes;
fi->header++;
encoded (fsound, (unsigned char *)fi->buffer, (long)fi->bufferlength,
fsound->user_data);
}
} else {
fsound->frameno += samples;
encoded (fsound, (unsigned char *)buffer, (long)bytes,
fsound->user_data);
}
}
return FLAC__STREAM_ENCODER_WRITE_STATUS_OK;
}
static void
fs_flac_enc_meta_callback(const FLAC__StreamEncoder *encoder,
const FLAC__StreamMetadata *metadata,
void *client_data)
{
/* FishSound* fsound = (FishSound*)client_data; */
/* FishSoundFlacInfo* fi = (FishSoundFlacInfo *)fsound->codec_data; */
debug_printf(1, "IN");
switch (metadata->type) {
case FLAC__METADATA_TYPE_STREAMINFO:
debug_printf(1, "channels %d, samplerate %d",
metadata->data.stream_info.channels,
metadata->data.stream_info.sample_rate);
/*
fsound->info.channels = metadata->data.stream_info.channels;
fsound->info.samplerate = metadata->data.stream_info.sample_rate;
*/
break;
default:
debug_printf(1, "metadata type not yet implemented");
break;
}
return;
}
/* Create a local alias for an unwieldy type name */
typedef FLAC__StreamMetadata_VorbisComment_Entry FLAC__VCEntry;
static void
fs_flac_metadata_free (FLAC__StreamMetadata * metadata)
{
unsigned int i, length;
FLAC__VCEntry * comments;
if (metadata == NULL) return;
length = metadata->data.vorbis_comment.num_comments;
comments = metadata->data.vorbis_comment.comments;
for (i = 0; i < length; i++) {
fs_free (comments[i].entry);
}
fs_free (comments);
fs_free (metadata);
return;
}
static FLAC__byte *
fs_flac_encode_vcentry (const FishSoundComment * comment)
{
FLAC__byte * entry;
FLAC__uint32 length;
size_t name_len=0, value_len=0;
name_len = strlen(comment->name);
length = name_len + 1;
if (comment->value) {
value_len = strlen (comment->value);
length += value_len + 1;
}
if ((entry = fs_malloc (length)) == NULL)
return NULL;
/* We assume that comment->name, value are NUL terminated, as they were
* produced by our own comments.c */
strcpy ((char *)entry, comment->name);
if (comment->value) {
entry[name_len] = '=';
strcpy ((char *)&entry[name_len+1], comment->value);
}
entry[length-1] = '\0';
return entry;
}
static FLAC__StreamMetadata *
fs_flac_encode_vorbiscomments (FishSound * fsound)
{
FishSoundFlacInfo * fi = fsound->codec_data;
FLAC__StreamMetadata * metadata = NULL;
const FishSoundComment * comment;
unsigned int i=0, length=0, total_length;
FLAC__VCEntry * comments;
/* libFLAC seems to require us to know the total length of the generated
* vorbiscomment packet, even though it will silently generate the
* vendor string. Hence, this value was determined by inspection for
* the version "reference libFLAC 1.1.2"
*/
total_length = 40;
/* Count the number of comments */
for (comment = fish_sound_comment_first (fsound); comment;
comment = fish_sound_comment_next (fsound, comment)) {
length++;
}
if (length == 0) return NULL;
if ((comments = (FLAC__VCEntry *)fs_malloc (sizeof(FLAC__VCEntry) * length)) == NULL)
goto encode_vc_oom;
for (comment = fish_sound_comment_first (fsound); comment;
comment = fish_sound_comment_next (fsound, comment)) {
if ((comments[i].entry = fs_flac_encode_vcentry (comment)) == NULL) {
}
comments[i].length = strlen((char *)comments[i].entry);
/* In the generated vorbiscomment data, each entry is preceded by a
* 32bit length specifier. */
total_length += 4 + comments[i].length;
i++;
}
if ((metadata = (FLAC__StreamMetadata *) fs_malloc (sizeof (*metadata))) == NULL)
goto encode_vc_oom;
metadata->type = FLAC__METADATA_TYPE_VORBIS_COMMENT;
metadata->is_last = true;
metadata->length = total_length;
/* Don't bother setting the vendor_string, as libFLAC ignores it */
metadata->data.vorbis_comment.num_comments = length;
metadata->data.vorbis_comment.comments = comments;
/* Remember the allocated metadata */
fi->enc_vc_metadata = metadata;
return metadata;
encode_vc_oom:
if (metadata != NULL)
fs_free (metadata);
/* Unwind allocated comment entries */
for (i--; i >= 0; i--) {
if (comments[i].entry != NULL)
fs_free (comments[i].entry);
}
if (comments != NULL)
fs_free (comments);
return NULL;
}
static FishSound *
fs_flac_enc_headers (FishSound * fsound)
{
FishSoundFlacInfo * fi = fsound->codec_data;
FLAC__StreamMetadata * metadata;
fi->fse = FLAC__stream_encoder_new();
FLAC__stream_encoder_set_channels(fi->fse, fsound->info.channels);
FLAC__stream_encoder_set_sample_rate(fi->fse, fsound->info.samplerate);
FLAC__stream_encoder_set_bits_per_sample(fi->fse, BITS_PER_SAMPLE);
#if defined (HAVE_FLAC_1_1_2)
FLAC__stream_encoder_set_write_callback(fi->fse, fs_flac_enc_write_callback);
FLAC__stream_encoder_set_metadata_callback(fi->fse, fs_flac_enc_meta_callback);
FLAC__stream_encoder_set_client_data(fi->fse, fsound);
#endif
metadata = fs_flac_encode_vorbiscomments (fsound);
if (metadata != NULL)
FLAC__stream_encoder_set_metadata (fi->fse, &metadata, 1);
/* FLAC__stream_encoder_set_total_samples_estimate(fi->fse, ...);*/
#if defined (HAVE_FLAC_1_1_2)
if (FLAC__stream_encoder_init(fi->fse) != FLAC__STREAM_ENCODER_OK)
return NULL;
#elif defined (HAVE_FLAC_1_1_3)
if (FLAC__stream_encoder_init_stream
(fi->fse,
fs_flac_enc_write_callback,
NULL, /* seek callback */
NULL, /* tell callback */
fs_flac_enc_meta_callback,
fsound
) != FLAC__STREAM_ENCODER_OK)
return NULL;
#endif
return fsound;
}
static long
fs_flac_encode_fatal (FishSoundFlacInfo *fi, long err)
{
FLAC__stream_encoder_delete (fi->fse);
fi->fse = NULL;
return err;
}
static long
fs_flac_encode_f (FishSound * fsound, float * pcm[], long frames)
{
FishSoundFlacInfo *fi = fsound->codec_data;
FLAC__int32 *buffer, *ipcm;
float * p, norm = (1 << (BITS_PER_SAMPLE - 1));
long i;
int j, channels = fsound->info.channels;
debug_printf("IN, frames = %ld", frames);
if ((ipcm = realloc(fi->ipcm, sizeof(FLAC__int32) * channels * frames)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
fi->ipcm = ipcm;
buffer = (FLAC__int32*) fi->ipcm;
for (i = 0; i < frames; i++) {
for (j = 0; j < channels; j++) {
p = pcm[j];
buffer[i*channels + j] = (FLAC__int32) (p[i] * norm);
}
}
if (fi->packetno == 0)
fs_flac_enc_headers (fsound);
/* We could have used FLAC__stream_encoder_process() and a more direct
* conversion loop above, rather than converting and interleaving. */
if (FLAC__stream_encoder_process_interleaved(fi->fse, buffer, frames) == false) {
switch (FLAC__stream_encoder_get_state (fi->fse)) {
case FLAC__STREAM_ENCODER_OK:
case FLAC__STREAM_ENCODER_UNINITIALIZED:
break;
case FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR:
return fs_flac_encode_fatal (fi, FISH_SOUND_ERR_OUT_OF_MEMORY);
default:
return fs_flac_encode_fatal (fi, FISH_SOUND_ERR_GENERIC);
}
}
fi->packetno++;
return frames;
}
static long
fs_flac_encode_f_ilv (FishSound * fsound, float ** pcm, long frames)
{
FishSoundFlacInfo *fi = fsound->codec_data;
FLAC__int32 *buffer, *ipcm;
float * p = (float*)pcm, norm = (1 << (BITS_PER_SAMPLE - 1));
long i, length = frames * fsound->info.channels;
debug_printf(1, "IN, frames = %ld", frames);
if ((ipcm = realloc(fi->ipcm, sizeof(FLAC__int32)*fsound->info.channels*frames)) == NULL)
return FISH_SOUND_ERR_OUT_OF_MEMORY;
fi->ipcm = ipcm;
buffer = (FLAC__int32*) fi->ipcm;
for (i=0; i<length; i++)
buffer[i] = p[i] * norm;
if (fi->packetno == 0)
fs_flac_enc_headers (fsound);
if (FLAC__stream_encoder_process_interleaved(fi->fse, buffer, frames) == false) {
switch (FLAC__stream_encoder_get_state (fi->fse)) {
case FLAC__STREAM_ENCODER_OK:
case FLAC__STREAM_ENCODER_UNINITIALIZED:
break;
case FLAC__STREAM_ENCODER_MEMORY_ALLOCATION_ERROR:
return fs_flac_encode_fatal (fi, FISH_SOUND_ERR_OUT_OF_MEMORY);
default:
return fs_flac_encode_fatal (fi, FISH_SOUND_ERR_GENERIC);
}
}
fi->packetno++;
return frames;
}
#else /* ! FS_ENCODE */
#define fs_flac_encode_f NULL
#define fs_flac_encode_f_ilv NULL
#endif /* ! FS_ENCODE */
static FishSound *
fs_flac_delete (FishSound * fsound)
{
FishSoundFlacInfo * fi = (FishSoundFlacInfo *)fsound->codec_data;
int i;
debug_printf("IN");
if (fsound->mode == FISH_SOUND_DECODE) {
if (fi->fsd) {
FLAC__stream_decoder_finish(fi->fsd);
FLAC__stream_decoder_delete(fi->fsd);
}
} else if (fsound->mode == FISH_SOUND_ENCODE) {
if (fi->fse) {
FLAC__stream_encoder_finish(fi->fse);
FLAC__stream_encoder_delete(fi->fse);
}
if (fi->buffer) {
fs_free(fi->buffer);
fi->buffer = NULL;
}
}
if (fi->ipcm) fs_free(fi->ipcm);
for (i = 0; i < 8; i++) {
if (fi->pcm_out[i]) fs_free (fi->pcm_out[i]);
}
#if FS_ENCODE
if (fi->enc_vc_metadata) {
fs_flac_metadata_free (fi->enc_vc_metadata);
}
#endif
fs_free (fi);
fsound->codec_data = NULL;
return fsound;
}
static int
fs_flac_update (FishSound * fsound, int interleave)
{
return 0;
}
static int
fs_flac_reset (FishSound * fsound)
{
/*FishSoundFlacInfo * fi = (FishSoundFlacInfo *)fsound->codec_data;*/
#if 0
if (fsound->mode == FISH_SOUND_DECODE) {
FLAC__stream_decoder_reset(fi->fsd);
} else if (fsound->mode == FISH_SOUND_ENCODE) {
}
#endif
return 0;
}
static long
fs_flac_flush (FishSound * fsound)
{
FishSoundFlacInfo * fi = (FishSoundFlacInfo *)fsound->codec_data;
debug_printf("IN (%s)", fsound->mode == FISH_SOUND_DECODE ? "decode" : "encode");
if (fsound->mode == FISH_SOUND_DECODE) {
FLAC__stream_decoder_finish(fi->fsd);
} else if (fsound->mode == FISH_SOUND_ENCODE) {
FLAC__stream_encoder_finish(fi->fse);
}
return 0;
}
static FishSound *
fs_flac_init (FishSound * fsound)
{
FishSoundFlacInfo *fi;
int i;
fi = fs_malloc (sizeof (FishSoundFlacInfo));
if (fi == NULL) return NULL;
fi->fsd = NULL;
fi->fse = NULL;
fi->buffer = NULL;
fi->packetno = 0;
fi->header = 0;
fi->header_packets = 0;
fi->ipcm = NULL;
for (i = 0; i < 8; i++) {
fi->pcm_out[i] = NULL;
}
#if FS_ENCODE
fi->enc_vc_metadata = NULL;
#endif
fsound->codec_data = fi;
return fsound;
}
FishSoundCodec *
fish_sound_flac_codec (void)
{
FishSoundCodec * codec;
codec = (FishSoundCodec *) fs_malloc (sizeof (FishSoundCodec));
if (codec == NULL) return NULL;
codec->format.format = FISH_SOUND_FLAC;
codec->format.name = "Flac (Xiph.Org)";
codec->format.extension = "ogg";
codec->init = fs_flac_init;
codec->del = fs_flac_delete;
codec->reset = fs_flac_reset;
codec->update = fs_flac_update;
codec->command = fs_flac_command;
codec->decode = fs_flac_decode;
codec->encode_f = fs_flac_encode_f;
codec->encode_f_ilv = fs_flac_encode_f_ilv;
codec->flush = fs_flac_flush;
return codec;
}
#else /* !HAVE_FLAC */
int
fish_sound_flac_identify (unsigned char * buf, long bytes)
{
return FISH_SOUND_UNKNOWN;
}
FishSoundCodec *
fish_sound_flac_codec (void)
{
return NULL;
}
#endif

Просмотреть файл

@ -1,802 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if HAVE_STDINT_H
#include <stdint.h>
#endif
#include <ctype.h>
#include "private.h"
#include "convert.h"
/*#define DEBUG*/
#include "debug.h"
#if HAVE_SPEEX
#if HAVE_SPEEX_1_1
#include <speex/speex.h>
#include <speex/speex_header.h>
#include <speex/speex_stereo.h>
#include <speex/speex_callbacks.h>
#else /* Speex 1.0 */
#include <speex.h>
#include <speex_header.h>
#include <speex_stereo.h>
#include <speex_callbacks.h>
#endif
/* Format for the vendor string: "Encoded with Speex VERSION", where VERSION
* is the libspeex version as read from a newly-generated Speex header.
*/
#define VENDOR_FORMAT "Encoded with Speex %s"
#define DEFAULT_ENH_ENABLED 1
#define MAX_FRAME_BYTES 2000
typedef struct _FishSoundSpeexEnc {
int frame_offset; /* number of speex frames done in this packet */
int pcm_offset;
char cbits[MAX_FRAME_BYTES];
int id;
} FishSoundSpeexEnc;
typedef struct _FishSoundSpeexInfo {
int packetno;
void * st;
SpeexBits bits;
int frame_size;
int nframes;
int extra_headers;
SpeexStereoState stereo;
int pcm_len; /* nr frames in pcm */
float * ipcm; /* interleaved pcm */
float * pcm[2]; /* Speex does max 2 channels */
FishSoundSpeexEnc * enc;
} FishSoundSpeexInfo;
int
fish_sound_speex_identify (unsigned char * buf, long bytes)
{
SpeexHeader * header;
if (bytes < 8) return FISH_SOUND_UNKNOWN;
if (!strncmp ((char *)buf, "Speex ", 8)) {
/* if only a short buffer was passed, do a weak identify */
if (bytes == 8) return FISH_SOUND_SPEEX;
/* otherwise, assume the buffer is an entire initial header and
* feed it to speex_packet_to_header() */
if ((header = speex_packet_to_header ((char *)buf, (int)bytes)) != NULL) {
fs_free(header);
return FISH_SOUND_SPEEX;
}
}
return FISH_SOUND_UNKNOWN;
}
static int
fs_speex_command (FishSound * fsound, int command, void * data, int datasize)
{
return 0;
}
#if FS_DECODE
static void *
process_header(unsigned char * buf, long bytes, int enh_enabled,
int * frame_size, int * rate,
int * nframes, int forceMode, int * channels,
SpeexStereoState * stereo, int * extra_headers)
{
void *st;
SpeexMode *mode;
SpeexHeader *header;
int modeID;
SpeexCallback callback;
header = speex_packet_to_header((char*)buf, (int)bytes);
if (!header) {
/* cannot read header */
return NULL;
}
if (header->mode >= SPEEX_NB_MODES || header->mode < 0) {
/* Mode number does not (any longer) exist in this version */
return NULL;
}
modeID = header->mode;
if (forceMode!=-1)
modeID = forceMode;
#if HAVE_SPEEX_LIB_GET_MODE
mode = (SpeexMode *) speex_lib_get_mode (modeID);
#else
/* speex_mode_list[] is declared const in speex 1.1.x, hence the cast */
mode = (SpeexMode *)speex_mode_list[modeID];
#endif
if (header->speex_version_id > 1) {
/* Unknown bitstream version */
return NULL;
}
if (mode->bitstream_version < header->mode_bitstream_version) {
/* The file was encoded with a newer version of Speex,
* need to upgrade in order to play it */
return NULL;
}
if (mode->bitstream_version > header->mode_bitstream_version) {
/* The file was encoded with an older version of Speex.
* You would need to downgrade the version in order to play it */
return NULL;
}
st = speex_decoder_init(mode);
if (!st) {
/* Decoder initialization failed */
return NULL;
}
speex_decoder_ctl(st, SPEEX_SET_ENH, &enh_enabled);
speex_decoder_ctl(st, SPEEX_GET_FRAME_SIZE, frame_size);
if (!(*channels==1))
{
callback.callback_id = SPEEX_INBAND_STEREO;
callback.func = speex_std_stereo_request_handler;
callback.data = stereo;
speex_decoder_ctl(st, SPEEX_SET_HANDLER, &callback);
}
if (!*rate)
*rate = header->rate;
/* Adjust rate if --force-* options are used */
if (forceMode!=-1)
{
if (header->mode < forceMode)
*rate <<= (forceMode - header->mode);
if (header->mode > forceMode)
*rate >>= (header->mode - forceMode);
}
speex_decoder_ctl(st, SPEEX_SET_SAMPLING_RATE, rate);
*nframes = header->frames_per_packet;
if (*channels == -1)
*channels = header->nb_channels;
debug_printf (1, "Decoding %d Hz audio using %s mode",
*rate, mode->modeName);
#ifdef DEBUG
if (*channels==1)
fprintf (stderr, " (mono");
else
fprintf (stderr, " (stereo");
if (header->vbr)
fprintf (stderr, " (VBR)\n");
else
fprintf(stderr, "\n");
#endif
*extra_headers = header->extra_headers;
fs_free(header);
return st;
}
static int
fs_speex_free_buffers (FishSound * fsound)
{
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
if (fsound->mode == FISH_SOUND_DECODE) {
if (fss->ipcm && fss->ipcm != fss->pcm[0]) fs_free (fss->ipcm);
if (fss->pcm[0]) fs_free (fss->pcm[0]);
if (fss->pcm[1]) fs_free (fss->pcm[1]);
} else {
if (fss->ipcm) fs_free (fss->ipcm);
}
return 0;
}
static inline int
fs_speex_float_dispatch (FishSound * fsound)
{
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
FishSoundDecoded_FloatIlv df;
FishSoundDecoded_Float dfi;
int retval;
if (fsound->interleave) {
dfi = (FishSoundDecoded_FloatIlv)fsound->callback.decoded_float_ilv;
retval = dfi (fsound, (float **)fss->ipcm, fss->frame_size,
fsound->user_data);
} else {
df = (FishSoundDecoded_Float)fsound->callback.decoded_float;
retval = df (fsound, fss->pcm, fss->frame_size, fsound->user_data);
}
return retval;
}
static long
fs_speex_decode (FishSound * fsound, unsigned char * buf, long bytes)
{
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
int enh_enabled = DEFAULT_ENH_ENABLED;
int rate = 0;
int channels = -1;
int forceMode = -1;
int i, j;
if (fss->packetno == 0) {
fss->st = process_header (buf, bytes, enh_enabled,
&fss->frame_size, &rate,
&fss->nframes, forceMode, &channels,
&fss->stereo,
&fss->extra_headers);
if (fss->st == NULL) {
/* TODO: Return more specific error identifiers for invalid header fields */
return FISH_SOUND_ERR_GENERIC;
}
debug_printf (1, "speex: got %d channels, %d Hz", channels, rate);
fsound->info.samplerate = rate;
fsound->info.channels = channels;
/* Sanity check the channels value, as we will use it to determine buffer
sizes below.
*/
if (channels < 1 || channels > 2)
return FISH_SOUND_ERR_GENERIC;
#if HAVE_UINTPTR_T
/* Sanity check: frame_size is not so large that the buffer size calculations
* would wrap. In reality, frame_size is set by libspeex according to the
* mode index specified in the file header, and is usually equal to 320.
*/
if (fss->frame_size > UINTPTR_MAX / (sizeof(float) * channels))
return FISH_SOUND_ERR_GENERIC;
#endif
fss->ipcm = fs_malloc (sizeof (float) * fss->frame_size * channels);
if (fss->ipcm == NULL) {
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
if (channels == 1) {
fss->pcm[0] = fss->ipcm;
} else if (channels == 2) {
fss->pcm[0] = fs_malloc (sizeof (float) * fss->frame_size);
if (fss->pcm[0] == NULL) {
fs_free (fss->ipcm);
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
fss->pcm[1] = fs_malloc (sizeof (float) * fss->frame_size);
if (fss->pcm[1] == NULL) {
fs_free (fss->pcm[0]);
fs_free (fss->ipcm);
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
}
if (fss->nframes == 0) fss->nframes = 1;
} else if (fss->packetno == 1) {
/* Comments */
if (fish_sound_comments_decode (fsound, buf, bytes) == FISH_SOUND_ERR_OUT_OF_MEMORY) {
fss->packetno++;
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
} else if (fss->packetno <= 1+fss->extra_headers) {
/* Unknown extra headers */
} else {
speex_bits_read_from (&fss->bits, (char *)buf, (int)bytes);
for (i = 0; i < fss->nframes; i++) {
/* Decode frame */
speex_decode (fss->st, &fss->bits, fss->ipcm);
if (fsound->info.channels == 2) {
speex_decode_stereo (fss->ipcm, fss->frame_size, &fss->stereo);
if (fsound->interleave) {
for (j = 0; j < fss->frame_size * fsound->info.channels; j++) {
fss->ipcm[j] /= 32767.0;
}
} else {
_fs_deinterleave ((float **)fss->ipcm, fss->pcm,
fss->frame_size, 2, (float)(1/32767.0));
}
} else {
for (j = 0; j < fss->frame_size; j++) {
fss->ipcm[j] /= 32767.0;
}
}
fsound->frameno += fss->frame_size;
fs_speex_float_dispatch (fsound);
}
}
fss->packetno++;
return 0;
}
#else /* !FS_DECODE */
#define fs_speex_decode NULL
#endif
#if FS_ENCODE
static FishSound *
fs_speex_enc_headers (FishSound * fsound)
{
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
int modeID;
SpeexMode * mode = NULL;
SpeexHeader header;
unsigned char * header_buf = NULL, * comments_buf = NULL;
int header_bytes, comments_bytes;
size_t buflen;
modeID = 1;
#if HAVE_SPEEX_LIB_GET_MODE
mode = (SpeexMode *) speex_lib_get_mode (modeID);
#else
/* speex_mode_list[] is declared const in speex 1.1.x, hence the cast */
mode = (SpeexMode *)speex_mode_list[modeID];
#endif
speex_init_header (&header, fsound->info.samplerate, 1, mode);
header.frames_per_packet = fss->nframes; /* XXX: frames per packet */
header.vbr = 1; /* XXX: VBR */
header.nb_channels = fsound->info.channels;
fss->st = speex_encoder_init (mode);
if (fsound->callback.encoded) {
char vendor_string[128];
/* Allocate and create header */
header_buf = (unsigned char *) speex_header_to_packet (&header, &header_bytes);
if (header_buf == NULL) {
return NULL;
}
/* Allocate and create comments */
snprintf (vendor_string, 128, VENDOR_FORMAT, header.speex_version);
if (fish_sound_comment_set_vendor (fsound, vendor_string) == FISH_SOUND_ERR_OUT_OF_MEMORY) {
fs_free (header_buf);
return NULL;
}
comments_bytes = fish_sound_comments_encode (fsound, NULL, 0);
comments_buf = fs_malloc (comments_bytes);
if (comments_buf == NULL) {
fs_free (header_buf);
return NULL;
}
}
speex_encoder_ctl (fss->st, SPEEX_SET_SAMPLING_RATE,
&fsound->info.samplerate);
speex_encoder_ctl (fss->st, SPEEX_GET_FRAME_SIZE, &fss->frame_size);
debug_printf (1, "got frame size %d", fss->frame_size);
/* XXX: set VBR etc. */
buflen = fss->frame_size * fsound->info.channels * sizeof (float);
fss->ipcm = fs_malloc (buflen);
if (fss->ipcm == NULL) {
if (comments_buf) fs_free (comments_buf);
if (header_buf) fs_free (header_buf);
return NULL;
}
memset (fss->ipcm, 0, buflen);
/* Allocations succeeded, actually call encoded callback for headers */
if (fsound->callback.encoded) {
FishSoundEncoded encoded = (FishSoundEncoded)fsound->callback.encoded;
/* header */
encoded (fsound, header_buf, (long)header_bytes, fsound->user_data);
fss->packetno++;
fs_free (header_buf);
/* comments */
comments_bytes = fish_sound_comments_encode (fsound, comments_buf, comments_bytes);
encoded (fsound, comments_buf, (long)comments_bytes, fsound->user_data);
fss->packetno++;
fs_free (comments_buf);
}
return fsound;
}
static long
fs_speex_encode_write (FishSound * fsound)
{
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
FishSoundSpeexEnc * fse = (FishSoundSpeexEnc *)fss->enc;
int bytes;
speex_bits_insert_terminator (&fss->bits);
bytes = speex_bits_write (&fss->bits, fse->cbits, MAX_FRAME_BYTES);
speex_bits_reset (&fss->bits);
if (fsound->callback.encoded) {
FishSoundEncoded encoded = (FishSoundEncoded)fsound->callback.encoded;
encoded (fsound, (unsigned char *)fse->cbits, (long)bytes,
fsound->user_data);
}
return bytes;
}
static long
fs_speex_encode_block (FishSound * fsound)
{
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
FishSoundSpeexEnc * fse = (FishSoundSpeexEnc *)fss->enc;
long nencoded = fse->pcm_offset;
if (fsound->info.channels == 2)
speex_encode_stereo (fss->ipcm, fse->pcm_offset, &fss->bits);
speex_encode (fss->st, fss->ipcm, &fss->bits);
fsound->frameno += fse->pcm_offset;
fse->frame_offset++;
if (fse->frame_offset == fss->nframes) {
fs_speex_encode_write (fsound);
fse->frame_offset = 0;
}
fse->pcm_offset = 0;
return nencoded;
}
static long
fs_speex_encode_f_ilv (FishSound * fsound, float ** pcm, long frames)
{
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
FishSoundSpeexEnc * fse = (FishSoundSpeexEnc *)fss->enc;
long remaining = frames, len, nencoded = 0;
int j, start, end;
int channels = fsound->info.channels;
float * p = (float *)pcm;
if (fss->packetno == 0)
fs_speex_enc_headers (fsound);
while (remaining > 0) {
len = MIN (remaining, fss->frame_size - fse->pcm_offset);
start = fse->pcm_offset * channels;
end = (len + fse->pcm_offset) * channels;
for (j = start; j < end; j++) {
fss->ipcm[j] = *p++ * (float)32767.0;
}
fse->pcm_offset += len;
if (fse->pcm_offset == fss->frame_size) {
nencoded += fs_speex_encode_block (fsound);
}
remaining -= len;
}
return frames - remaining;
}
static long
fs_speex_encode_f (FishSound * fsound, float * pcm[], long frames)
{
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
FishSoundSpeexEnc * fse = (FishSoundSpeexEnc *)fss->enc;
long remaining = frames, len, n = 0, nencoded = 0;
int j, start;
if (fss->packetno == 0)
fs_speex_enc_headers (fsound);
while (remaining > 0) {
len = MIN (remaining, fss->frame_size - fse->pcm_offset);
start = fse->pcm_offset;
fss->pcm[0] = &pcm[0][n];
if (fsound->info.channels == 2) {
fss->pcm[1] = &pcm[1][n];
_fs_interleave (fss->pcm, (float **)&fss->ipcm[start*2],
len, 2, 32767.0);
} else {
for (j = 0; j < len; j++) {
fss->ipcm[start + j] = fss->pcm[0][j] * (float)32767.0;
}
}
fse->pcm_offset += len;
if (fse->pcm_offset == fss->frame_size) {
nencoded += fs_speex_encode_block (fsound);
}
remaining -= len;
n += len;
}
return frames - remaining;
}
static long
fs_speex_flush (FishSound * fsound)
{
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
FishSoundSpeexEnc * fse = (FishSoundSpeexEnc *)fss->enc;
long nencoded = 0;
if (fsound->mode != FISH_SOUND_ENCODE)
return 0;
if (fse->pcm_offset > 0) {
nencoded += fs_speex_encode_block (fsound);
}
/* If, at this point, fse->frame_offset == 0, then either:
- all remaining encoded data has just been flushed out via
fs_speex_encode_block(), OR
- there was no data remaining to flush at the beginning of this
function (fse->pcm_offset == 0 && fse->frame_offset == 0)
*/
if (fse->frame_offset == 0) return 0;
while (fse->frame_offset < fss->nframes) {
speex_bits_pack (&fss->bits, 15, 5);
fse->frame_offset++;
}
nencoded += fs_speex_encode_write (fsound);
fse->frame_offset = 0;
return nencoded;
}
#else /* !FS_ENCODE */
#define fs_speex_encode_f NULL
#define fs_speex_encode_f_ilv NULL
#define fs_speex_flush NULL
#endif
static int
fs_speex_reset (FishSound * fsound)
{
/*FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;*/
return 0;
}
static int
fs_speex_update (FishSound * fsound, int interleave)
{
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
size_t pcm_size = sizeof (float);
float *ipcm_new, *pcm0, *pcm1;
ipcm_new = (float *)fs_realloc (fss->ipcm,
pcm_size * fss->frame_size * fsound->info.channels);
if (ipcm_new == NULL) return FISH_SOUND_ERR_OUT_OF_MEMORY;
fss->ipcm = ipcm_new;
if (interleave) {
/* if transitioning from non-interleave to interleave,
free non-ilv buffers */
if (!fsound->interleave && fsound->info.channels == 2) {
if (fss->pcm[0]) fs_free (fss->pcm[0]);
if (fss->pcm[1]) fs_free (fss->pcm[1]);
fss->pcm[0] = NULL;
fss->pcm[1] = NULL;
}
} else {
if (fsound->info.channels == 1) {
fss->pcm[0] = (float *) fss->ipcm;
} else if (fsound->info.channels == 2) {
#if HAVE_UINTPTR_T
/* Sanity check: frame_size is not so large that the buffer size calculations
* would wrap. In reality, frame_size is set by libspeex according to the
* mode index specified in the file header, and is usually equal to 320.
*/
if (fss->frame_size > UINTPTR_MAX / pcm_size)
return FISH_SOUND_ERR_GENERIC;
#endif
pcm0 = fs_realloc (fss->pcm[0], pcm_size * fss->frame_size);
if (pcm0 == NULL) {
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
pcm1 = fs_realloc (fss->pcm[1], pcm_size * fss->frame_size);
if (pcm1 == NULL) {
fs_free (pcm0);
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
fss->pcm[0] = pcm0;
fss->pcm[1] = pcm1;
}
}
return 0;
}
static FishSound *
fs_speex_enc_init (FishSound * fsound)
{
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
FishSoundSpeexEnc * fse;
fse = fs_malloc (sizeof (FishSoundSpeexEnc));
if (fse == NULL) return NULL;
fse->frame_offset = 0;
fse->pcm_offset = 0;
fse->id = 0;
fss->enc = fse;
return fsound;
}
static FishSound *
fs_speex_init (FishSound * fsound)
{
FishSoundSpeexInfo * fss;
SpeexStereoState stereo_init = SPEEX_STEREO_STATE_INIT;
fss = fs_malloc (sizeof (FishSoundSpeexInfo));
if (fss == NULL) return NULL;
fss->packetno = 0;
fss->st = NULL;
fss->frame_size = 0;
fss->nframes = 1;
fss->pcm_len = 0;
fss->ipcm = NULL;
fss->pcm[0] = NULL;
fss->pcm[1] = NULL;
memcpy (&fss->stereo, &stereo_init, sizeof (SpeexStereoState));
speex_bits_init (&fss->bits);
fsound->codec_data = fss;
if (fsound->mode == FISH_SOUND_ENCODE)
fs_speex_enc_init (fsound);
return fsound;
}
static FishSound *
fs_speex_delete (FishSound * fsound)
{
FishSoundSpeexInfo * fss = (FishSoundSpeexInfo *)fsound->codec_data;
fs_speex_free_buffers (fsound);
if (fsound->mode == FISH_SOUND_DECODE) {
if (fss->st) speex_decoder_destroy (fss->st);
} else if (fsound->mode == FISH_SOUND_ENCODE) {
if (fss->st) speex_encoder_destroy (fss->st);
if (fss->enc) fs_free (fss->enc);
}
speex_bits_destroy (&fss->bits);
fs_free (fss);
fsound->codec_data = NULL;
return fsound;
}
FishSoundCodec *
fish_sound_speex_codec (void)
{
FishSoundCodec * codec;
codec = (FishSoundCodec *) fs_malloc (sizeof (FishSoundCodec));
if (codec == NULL) return NULL;
codec->format.format = FISH_SOUND_SPEEX;
codec->format.name = "Speex (Xiph.Org)";
codec->format.extension = "spx";
codec->init = fs_speex_init;
codec->del = fs_speex_delete;
codec->reset = fs_speex_reset;
codec->update = fs_speex_update;
codec->command = fs_speex_command;
codec->decode = fs_speex_decode;
codec->encode_f = fs_speex_encode_f;
codec->encode_f_ilv = fs_speex_encode_f_ilv;
codec->flush = fs_speex_flush;
return codec;
}
#else /* !HAVE_SPEEX */
int
fish_sound_speex_identify (unsigned char * buf, long bytes)
{
return FISH_SOUND_UNKNOWN;
}
FishSoundCodec *
fish_sound_speex_codec (void)
{
return NULL;
}
#endif

Просмотреть файл

@ -1,511 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "private.h"
#include "convert.h"
/*#define DEBUG*/
#include "debug.h"
#if HAVE_VORBIS
#include <vorbis/codec.h>
#if HAVE_VORBISENC
#include <vorbis/vorbisenc.h>
#endif
typedef struct _FishSoundVorbisInfo {
int packetno;
int finished;
vorbis_info vi;
vorbis_comment vc;
vorbis_dsp_state vd; /** central working state for the PCM->packet encoder */
vorbis_block vb; /** local working space for PCM->packet encode */
float ** pcm; /** ongoing pcm working space for decoder (stateful) */
float * ipcm; /** interleaved pcm for interfacing with user */
long max_pcm;
} FishSoundVorbisInfo;
int
fish_sound_vorbis_identify (unsigned char * buf, long bytes)
{
struct vorbis_info vi;
struct vorbis_comment vc;
ogg_packet op;
int ret, id = FISH_SOUND_UNKNOWN;
if (!strncmp ((char *)&buf[1], "vorbis", 6)) {
/* if only a short buffer was passed, do a weak identify */
if (bytes == 8) return FISH_SOUND_VORBIS;
/* otherwise, assume the buffer is an entire initial header and
* feed it to vorbis_synthesis_headerin() */
vorbis_info_init (&vi);
vorbis_comment_init (&vc);
op.packet = buf;
op.bytes = bytes;
op.b_o_s = 1;
op.e_o_s = 0;
op.granulepos = 0;
op.packetno = 0;
if ((ret = vorbis_synthesis_headerin (&vi, &vc, &op)) == 0) {
if (vi.rate != 0) id = FISH_SOUND_VORBIS;
} else {
debug_printf (1, "vorbis_synthesis_headerin returned %d", ret);
}
vorbis_info_clear (&vi);
}
return id;
}
static int
fs_vorbis_command (FishSound * fsound, int command, void * data,
int datasize)
{
return 0;
}
#if FS_DECODE
static long
fs_vorbis_decode (FishSound * fsound, unsigned char * buf, long bytes)
{
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
ogg_packet op;
long samples;
float * pcm_new;
int ret;
/* Make an ogg_packet structure to pass the data to libvorbis */
op.packet = buf;
op.bytes = bytes;
op.b_o_s = (fsv->packetno == 0) ? 1 : 0;
op.e_o_s = fsound->next_eos;
op.granulepos = fsound->next_granulepos;
op.packetno = fsv->packetno;
if (fsv->packetno < 3) {
if ((ret = vorbis_synthesis_headerin (&fsv->vi, &fsv->vc, &op)) == 0) {
if (fsv->vi.rate != 0) {
debug_printf (1, "Got vorbis info: version %d\tchannels %d\trate %ld",
fsv->vi.version, fsv->vi.channels, fsv->vi.rate);
fsound->info.samplerate = fsv->vi.rate;
fsound->info.channels = fsv->vi.channels;
}
}
/* Decode comments from packet 1. Vorbis has 7 bytes of marker at the
* start of vorbiscomment packet. */
if (fsv->packetno == 1 && bytes > 7 && buf[0] == 0x03 &&
!strncmp ((char *)&buf[1], "vorbis", 6)) {
if (fish_sound_comments_decode (fsound, buf+7, bytes-7) == FISH_SOUND_ERR_OUT_OF_MEMORY) {
fsv->packetno++;
return FISH_SOUND_ERR_OUT_OF_MEMORY;
}
} else if (fsv->packetno == 2) {
vorbis_synthesis_init (&fsv->vd, &fsv->vi);
vorbis_block_init (&fsv->vd, &fsv->vb);
}
} else {
FishSoundDecoded_FloatIlv df;
FishSoundDecoded_Float dfi;
int r;
if ((r = vorbis_synthesis (&fsv->vb, &op)) == 0)
vorbis_synthesis_blockin (&fsv->vd, &fsv->vb);
if (r == OV_EBADPACKET) {
return FISH_SOUND_ERR_GENERIC;
}
while ((samples = vorbis_synthesis_pcmout (&fsv->vd, &fsv->pcm)) > 0) {
vorbis_synthesis_read (&fsv->vd, samples);
if (fsound->frameno != -1)
fsound->frameno += samples;
if (fsound->interleave) {
if (samples > fsv->max_pcm) {
pcm_new = realloc (fsv->ipcm, sizeof(float) * samples *
fsound->info.channels);
if (pcm_new == NULL) {
/* Allocation failure; just truncate here, fail gracefully elsewhere */
samples = fsv->max_pcm;
} else {
fsv->ipcm = pcm_new;
fsv->max_pcm = samples;
}
}
_fs_interleave (fsv->pcm, (float **)fsv->ipcm, samples,
fsound->info.channels, 1.0);
dfi = (FishSoundDecoded_FloatIlv)fsound->callback.decoded_float_ilv;
dfi (fsound, (float **)fsv->ipcm, samples, fsound->user_data);
} else {
df = (FishSoundDecoded_Float)fsound->callback.decoded_float;
df (fsound, fsv->pcm, samples, fsound->user_data);
}
}
}
if (fsound->next_granulepos != -1) {
fsound->frameno = fsound->next_granulepos;
fsound->next_granulepos = -1;
}
fsv->packetno++;
return 0;
}
#else /* !FS_DECODE */
#define fs_vorbis_decode NULL
#endif
#if FS_ENCODE && HAVE_VORBISENC
static FishSound *
fs_vorbis_enc_headers (FishSound * fsound)
{
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
const FishSoundComment * comment;
ogg_packet header;
ogg_packet header_comm;
ogg_packet header_code;
/* Vorbis streams begin with three headers:
* 1. The initial header (with most of the codec setup parameters),
* which is mandated by the Ogg bitstream spec,
* 2. The second header which holds any comment fields,
* 3. The third header which contains the bitstream codebook.
* We merely need to make the headers, then pass them to libvorbis one at
* a time; libvorbis handles the additional Ogg bitstream constraints.
*/
/* Update the comments */
for (comment = fish_sound_comment_first (fsound); comment;
comment = fish_sound_comment_next (fsound, comment)) {
debug_printf (1, "%s = %s", comment->name, comment->value);
vorbis_comment_add_tag (&fsv->vc, comment->name, comment->value);
}
/* Generate the headers */
vorbis_analysis_headerout(&fsv->vd, &fsv->vc,
&header, &header_comm, &header_code);
/* Pass the generated headers to the user */
if (fsound->callback.encoded) {
FishSoundEncoded encoded = (FishSoundEncoded)fsound->callback.encoded;
encoded (fsound, header.packet, header.bytes, fsound->user_data);
encoded (fsound, header_comm.packet, header_comm.bytes,
fsound->user_data);
encoded (fsound, header_code.packet, header_code.bytes,
fsound->user_data);
fsv->packetno = 3;
}
return fsound;
}
static long
fs_vorbis_encode_write (FishSound * fsound, long len)
{
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
ogg_packet op;
vorbis_analysis_wrote (&fsv->vd, len);
while (vorbis_analysis_blockout (&fsv->vd, &fsv->vb) == 1) {
vorbis_analysis (&fsv->vb, NULL);
vorbis_bitrate_addblock (&fsv->vb);
while (vorbis_bitrate_flushpacket (&fsv->vd, &op)) {
if (fsound->callback.encoded) {
FishSoundEncoded encoded = (FishSoundEncoded)fsound->callback.encoded;
if (op.granulepos != -1)
fsound->frameno = op.granulepos;
encoded (fsound, op.packet, op.bytes, fsound->user_data);
fsv->packetno++;
}
}
}
return len;
}
static int
fs_vorbis_finish (FishSound * fsound)
{
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
if (!fsv->finished) {
if (fsound->mode == FISH_SOUND_ENCODE) {
fs_vorbis_encode_write (fsound, 0);
}
fsv->finished = 1;
}
return 0;
}
static long
fs_vorbis_encode_f_ilv (FishSound * fsound, float ** pcm, long frames)
{
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
float ** vpcm;
long len, remaining = frames;
float * d = (float *)pcm;
if (fsv->packetno == 0) {
fs_vorbis_enc_headers (fsound);
}
if (frames == 0) {
fs_vorbis_finish (fsound);
return 0;
}
while (remaining > 0) {
len = MIN (1024, remaining);
/* expose the buffer to submit data */
vpcm = vorbis_analysis_buffer (&fsv->vd, 1024);
_fs_deinterleave ((float **)d, vpcm, len, fsound->info.channels, 1.0);
d += (len * fsound->info.channels);
fs_vorbis_encode_write (fsound, len);
remaining -= len;
}
/**
* End of input. Tell libvorbis we're at the end of stream so that it can
* handle the last frame and mark the end of stream in the output properly.
*/
if (fsound->next_eos)
fs_vorbis_finish (fsound);
return 0;
}
static long
fs_vorbis_encode_f (FishSound * fsound, float * pcm[], long frames)
{
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
float ** vpcm;
long len, remaining = frames;
int i;
if (fsv->packetno == 0) {
fs_vorbis_enc_headers (fsound);
}
if (frames == 0) {
fs_vorbis_finish (fsound);
return 0;
}
while (remaining > 0) {
len = MIN (1024, remaining);
debug_printf (1, "processing %ld frames", len);
/* expose the buffer to submit data */
vpcm = vorbis_analysis_buffer (&fsv->vd, 1024);
for (i = 0; i < fsound->info.channels; i++) {
memcpy (vpcm[i], pcm[i], sizeof (float) * len);
}
fs_vorbis_encode_write (fsound, len);
remaining -= len;
}
/**
* End of input. Tell libvorbis we're at the end of stream so that it can
* handle the last frame and mark the end of stream in the output properly.
*/
if (fsound->next_eos)
fs_vorbis_finish (fsound);
return 0;
}
static FishSound *
fs_vorbis_enc_init (FishSound * fsound)
{
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
debug_printf (1, "Vorbis enc init: %d channels, %d Hz", fsound->info.channels,
fsound->info.samplerate);
vorbis_encode_init_vbr (&fsv->vi, fsound->info.channels,
fsound->info.samplerate, (float)0.3 /* quality */);
/* set up the analysis state and auxiliary encoding storage */
vorbis_analysis_init (&fsv->vd, &fsv->vi);
vorbis_block_init (&fsv->vd, &fsv->vb);
return fsound;
}
#else /* ! FS_ENCODE && HAVE_VORBISENC */
#define fs_vorbis_encode_f NULL
#define fs_vorbis_encode_f_ilv NULL
#define fs_vorbis_finish NULL
#endif /* ! FS_ENCODE && HAVE_VORBISENC */
static int
fs_vorbis_reset (FishSound * fsound)
{
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
vorbis_block_init (&fsv->vd, &fsv->vb);
fsv->packetno = 0;
return 0;
}
static FishSound *
fs_vorbis_init (FishSound * fsound)
{
FishSoundVorbisInfo * fsv;
fsv = fs_malloc (sizeof (FishSoundVorbisInfo));
if (fsv == NULL) return NULL;
fsv->packetno = 0;
fsv->finished = 0;
vorbis_info_init (&fsv->vi);
vorbis_comment_init (&fsv->vc);
memset(&fsv->vd, 0, sizeof(fsv->vd));
vorbis_block_init (&fsv->vd, &fsv->vb);
fsv->pcm = NULL;
fsv->ipcm = NULL;
fsv->max_pcm = 0;
fsound->codec_data = fsv;
#if FS_ENCODE && HAVE_VORBISENC
if (fsound->mode == FISH_SOUND_ENCODE) {
fs_vorbis_enc_init (fsound);
}
#endif /* FS_ENCODE && HAVE_VORBISENC */
return fsound;
}
static FishSound *
fs_vorbis_delete (FishSound * fsound)
{
FishSoundVorbisInfo * fsv = (FishSoundVorbisInfo *)fsound->codec_data;
#if FS_ENCODE && HAVE_VORBISENC
fs_vorbis_finish (fsound);
#endif /* FS_ENCODE && HAVE_VORBISENC */
if (fsv->ipcm) fs_free (fsv->ipcm);
vorbis_block_clear (&fsv->vb);
vorbis_dsp_clear (&fsv->vd);
vorbis_comment_clear (&fsv->vc);
vorbis_info_clear (&fsv->vi);
fs_free (fsv);
fsound->codec_data = NULL;
return fsound;
}
FishSoundCodec *
fish_sound_vorbis_codec (void)
{
FishSoundCodec * codec;
codec = (FishSoundCodec *) fs_malloc (sizeof (FishSoundCodec));
if (codec == NULL) return NULL;
codec->format.format = FISH_SOUND_VORBIS;
codec->format.name = "Vorbis (Xiph.Org)";
codec->format.extension = "ogg";
codec->init = fs_vorbis_init;
codec->del = fs_vorbis_delete;
codec->reset = fs_vorbis_reset;
codec->update = NULL; /* XXX */
codec->command = fs_vorbis_command;
codec->decode = fs_vorbis_decode;
codec->encode_f = fs_vorbis_encode_f;
codec->encode_f_ilv = fs_vorbis_encode_f_ilv;
codec->flush = NULL;
return codec;
}
#else /* !HAVE_VORBIS */
int
fish_sound_vorbis_identify (unsigned char * buf, long bytes)
{
return FISH_SOUND_UNKNOWN;
}
FishSoundCodec *
fish_sound_vorbis_codec (void)
{
return NULL;
}
#endif

Просмотреть файл

@ -1,57 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "config.h"
/* WINDOWS */
#ifdef _WIN32
#define inline __inline
#define alloca _alloca
#define strncasecmp _strnicmp
#define snprintf _snprintf
#ifndef __SYMBIAN32__
#define strcasecmp _stricmp
#endif /* ! __SYMBIAN32__ */
#endif
/* malloc/realloc/free macros */
#ifndef fs_malloc
#define fs_malloc malloc
#endif
#ifndef fs_realloc
#define fs_realloc realloc
#endif
#ifndef fs_free
#define fs_free free
#endif

Просмотреть файл

@ -1,237 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "fs_compat.h"
typedef int (*FishSoundFunc) (void * data);
typedef int (*FishSoundCmpFunc) (const void * data1, const void * data2);
typedef struct _FishSoundVector FishSoundVector;
struct _FishSoundVector {
int max_elements;
int nr_elements;
FishSoundCmpFunc cmp;
void ** data;
};
/*
* A vector of void *. New elements will be appended at the tail.
*/
FishSoundVector *
fs_vector_new (FishSoundCmpFunc cmp)
{
FishSoundVector * vector;
vector = fs_malloc (sizeof (FishSoundVector));
if (vector == NULL) return NULL;
vector->max_elements = 0;
vector->nr_elements = 0;
vector->cmp = cmp;
vector->data = NULL;
return vector;
}
static void
fs_vector_clear (FishSoundVector * vector)
{
fs_free (vector->data);
vector->data = NULL;
vector->nr_elements = 0;
vector->max_elements = 0;
}
void
fs_vector_delete (FishSoundVector * vector)
{
fs_vector_clear (vector);
fs_free (vector);
}
int
fs_vector_size (FishSoundVector * vector)
{
if (vector == NULL) return 0;
return vector->nr_elements;
}
void *
fs_vector_nth (FishSoundVector * vector, int n)
{
if (vector == NULL) return NULL;
if (n >= vector->nr_elements) return NULL;
return vector->data[n];
}
int
fs_vector_find_index (FishSoundVector * vector, const void * data)
{
void * v_data;
int i;
for (i = 0; i < vector->nr_elements; i++) {
v_data = vector->data[i];
if (vector->cmp (v_data, data))
return i;
}
return -1;
}
void *
fs_vector_find (FishSoundVector * vector, const void * data)
{
void * v_data;
int i;
for (i = 0; i < vector->nr_elements; i++) {
v_data = vector->data[i];
if (vector->cmp (v_data, data))
return v_data;
}
return NULL;
}
int
fs_vector_foreach (FishSoundVector * vector, FishSoundFunc func)
{
int i;
for (i = 0; i < vector->nr_elements; i++) {
func (vector->data[i]);
}
return 0;
}
static FishSoundVector *
fs_vector_grow (FishSoundVector * vector)
{
void * new_elements;
int new_max_elements;
vector->nr_elements++;
if (vector->nr_elements > vector->max_elements) {
if (vector->max_elements == 0) {
new_max_elements = 1;
} else {
new_max_elements = vector->max_elements * 2;
}
new_elements =
fs_realloc (vector->data, (size_t)new_max_elements * sizeof (void *));
if (new_elements == NULL) {
vector->nr_elements--;
return NULL;
}
vector->max_elements = new_max_elements;
vector->data = new_elements;
}
return vector;
}
void *
fs_vector_insert (FishSoundVector * vector, void * data)
{
if (vector == NULL) return NULL;
if (fs_vector_grow (vector) == NULL)
return NULL;
vector->data[vector->nr_elements-1] = data;
return data;
}
static void *
fs_vector_remove_nth (FishSoundVector * vector, int n)
{
int i;
void * new_elements;
int new_max_elements;
vector->nr_elements--;
if (vector->nr_elements == 0) {
fs_vector_clear (vector);
} else {
for (i = n; i < vector->nr_elements; i++) {
vector->data[i] = vector->data[i+1];
}
if (vector->nr_elements < vector->max_elements/2) {
new_max_elements = vector->max_elements/2;
new_elements =
fs_realloc (vector->data,
(size_t)new_max_elements * sizeof (void *));
if (new_elements == NULL)
return NULL;
vector->max_elements = new_max_elements;
vector->data = new_elements;
}
}
return vector;
}
FishSoundVector *
fs_vector_remove (FishSoundVector * vector, void * data)
{
int i;
for (i = 0; i < vector->nr_elements; i++) {
if (vector->data[i] == data) {
return fs_vector_remove_nth (vector, i);
}
}
return vector;
}

Просмотреть файл

@ -1,80 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FS_VECTOR_H__
#define __FS_VECTOR_H__
typedef void FishSoundVector;
typedef int (*FishSoundFunc) (void * data);
typedef int (*FishSoundCmpFunc) (void * data1, void * data2);
FishSoundVector *
fs_vector_new (FishSoundCmpFunc cmp);
void
fs_vector_delete (FishSoundVector * vector);
void *
fs_vector_nth (FishSoundVector * vector, int n);
int
fs_vector_find_index (FishSoundVector * vector, const void * data);
void *
fs_vector_find (FishSoundVector * vector, const void * data);
int
fs_vector_foreach (FishSoundVector * vector, FishSoundFunc func);
int
fs_vector_size (FishSoundVector * vector);
/**
* Add an element to a vector.
* \param vector An FishSoundVector
* \param data The new element to add
* \retval data If the element was successfully added
* \retval NULL If adding the element failed due to a realloc() error
*/
void *
fs_vector_insert (FishSoundVector * vector, void * data);
/**
* Remove a (void *) element of a vector
* \retval \a vector on success
* \retval NULL on failure (realloc error)
*/
FishSoundVector *
fs_vector_remove (FishSoundVector * vector, void * data);
#endif /* __FS_VECTOR_H__ */

Просмотреть файл

@ -1,189 +0,0 @@
/*
Copyright (C) 2003 Commonwealth Scientific and Industrial Research
Organisation (CSIRO) Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of CSIRO Australia nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __FISH_SOUND_PRIVATE_H__
#define __FISH_SOUND_PRIVATE_H__
#include <stdlib.h>
#include "fs_compat.h"
#include "fs_vector.h"
#include <fishsound/constants.h>
#undef MIN
#define MIN(a,b) (((a)<(b))?(a):(b))
typedef struct _FishSound FishSound;
typedef struct _FishSoundInfo FishSoundInfo;
typedef struct _FishSoundCodec FishSoundCodec;
typedef struct _FishSoundFormat FishSoundFormat;
typedef struct _FishSoundComment FishSoundComment;
typedef int (*FSCodecIdentify) (unsigned char * buf, long bytes);
typedef FishSound * (*FSCodecInit) (FishSound * fsound);
typedef FishSound * (*FSCodecDelete) (FishSound * fsound);
typedef int (*FSCodecReset) (FishSound * fsound);
typedef int (*FSCodecUpdate) (FishSound * fsound, int interleave);
typedef int (*FSCodecCommand) (FishSound * fsound, int command,
void * data, int datasize);
typedef long (*FSCodecDecode) (FishSound * fsound, unsigned char * buf,
long bytes);
typedef long (*FSCodecEncode_Float) (FishSound * fsound, float * pcm[],
long frames);
typedef long (*FSCodecEncode_FloatIlv) (FishSound * fsound,
float ** pcm, long frames);
typedef long (*FSCodecFlush) (FishSound * fsound);
#include <fishsound/decode.h>
#include <fishsound/encode.h>
struct _FishSoundFormat {
int format;
const char * name;
const char * extension;
};
struct _FishSoundCodec {
struct _FishSoundFormat format;
FSCodecInit init;
FSCodecDelete del;
FSCodecReset reset;
FSCodecUpdate update;
FSCodecCommand command;
FSCodecDecode decode;
FSCodecEncode_FloatIlv encode_f_ilv;
FSCodecEncode_Float encode_f;
FSCodecFlush flush;
};
struct _FishSoundInfo {
int samplerate;
int channels;
int format;
};
struct _FishSoundComment {
char * name;
char * value;
};
union FishSoundCallback {
FishSoundDecoded_Float decoded_float;
FishSoundDecoded_FloatIlv decoded_float_ilv;
FishSoundEncoded encoded;
};
struct _FishSound {
/** FISH_SOUND_DECODE or FISH_SOUND_ENCODE */
FishSoundMode mode;
/** General info related to sound */
FishSoundInfo info;
/** Interleave boolean */
int interleave;
/**
* Current frameno.
*/
long frameno;
/**
* Truncation frameno for the next block of data sent to decode.
* In Ogg encapsulation, this is represented by the Ogg packet's
* "granulepos" field.
*/
long next_granulepos;
/**
* Flag if the next block of data sent to decode will be the last one
* for this stream (eos = End Of Stream).
* In Ogg encapsulation, this is represented by the Ogg packet's
* "eos" field.
*/
int next_eos;
/** The codec class structure */
FishSoundCodec * codec;
/** codec specific data */
void * codec_data;
/* encode or decode callback */
union FishSoundCallback callback;
/** user data for encode/decode callback */
void * user_data;
/** The comments */
char * vendor;
FishSoundVector * comments;
};
int fish_sound_identify (unsigned char * buf, long bytes);
int fish_sound_set_format (FishSound * fsound, int format);
/* Format specific interfaces */
int fish_sound_vorbis_identify (unsigned char * buf, long bytes);
FishSoundCodec * fish_sound_vorbis_codec (void);
int fish_sound_speex_identify (unsigned char * buf, long bytes);
FishSoundCodec * fish_sound_speex_codec (void);
int fish_sound_flac_identify (unsigned char * buf, long bytes);
FishSoundCodec * fish_sound_flac_codec (void);
/* comments */
int fish_sound_comments_init (FishSound * fsound);
int fish_sound_comments_free (FishSound * fsound);
int fish_sound_comments_decode (FishSound * fsound, unsigned char * buf,
long bytes);
long fish_sound_comments_encode (FishSound * fsound, unsigned char * buf,
long length);
/**
* Set the vendor string.
* \param fsound A FishSound* handle (created with FISH_SOUND_ENCODE)
* \param vendor The vendor string.
* \retval 0 Success
* \retval FISH_SOUND_ERR_BAD \a fsound is not a valid FishSound* handle
* \retval FISH_SOUND_ERR_INVALID Operation not suitable for this FishSound
*/
int
fish_sound_comment_set_vendor (FishSound * fsound, const char * vendor);
const FishSoundComment * fish_sound_comment_first (FishSound * fsound);
const FishSoundComment *
fish_sound_comment_next (FishSound * fsound, const FishSoundComment * comment);
#endif /* __FISH_SOUND_PRIVATE_H__ */

Просмотреть файл

@ -1,47 +0,0 @@
diff --git a/media/libfishsound/src/libfishsound/fishsound_comments.c b/media/libfishsound/src/libfishsound/fishsound_comments.c
index b71164f..414e210 100644
--- a/media/libfishsound/src/libfishsound/fishsound_comments.c
+++ b/media/libfishsound/src/libfishsound/fishsound_comments.c
@@ -290,7 +290,9 @@ fish_sound_comment_next_byname (FishSound * fsound,
int
fish_sound_comment_add (FishSound * fsound, FishSoundComment * comment)
{
+#if FS_ENCODE
FishSoundComment * new_comment;
+#endif
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
@@ -317,7 +319,9 @@ int
fish_sound_comment_add_byname (FishSound * fsound, const char * name,
const char * value)
{
+#if FS_ENCODE
FishSoundComment * comment;
+#endif
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
@@ -346,7 +350,9 @@ fish_sound_comment_add_byname (FishSound * fsound, const char * name,
int
fish_sound_comment_remove (FishSound * fsound, FishSoundComment * comment)
{
+#if FS_ENCODE
FishSoundComment * v_comment;
+#endif
if (fsound == NULL) return FISH_SOUND_ERR_BAD;
@@ -372,8 +378,11 @@ fish_sound_comment_remove (FishSound * fsound, FishSoundComment * comment)
int
fish_sound_comment_remove_byname (FishSound * fsound, char * name)
{
+#if FS_ENCODE
FishSoundComment * comment;
- int i, ret = 0;
+ int i;
+#endif
+ int ret = 0;
if (fsound == NULL) return FISH_SOUND_ERR_BAD;

Просмотреть файл

@ -1,46 +0,0 @@
# Usage: cp $1/update.sh <libfishsound_src_directory>
#
# Copies the needed files from a directory containing the original
# libfishsound source that we need for the Mozilla HTML5 media support.
cp $1/config.h ./include/fishsound/config.h
echo "#undef FS_ENCODE" >>./include/fishsound/config.h
echo "#define FS_ENCODE 0" >>./include/fishsound/config.h
echo "#undef HAVE_FLAC" >>./include/fishsound/config.h
echo "#define HAVE_FLAC 0" >>./include/fishsound/config.h
echo "#undef HAVE_OGGZ" >>./include/fishsound/config.h
echo "#define HAVE_OGGZ 1" >>./include/fishsound/config.h
echo "#undef HAVE_SPEEX" >>./include/fishsound/config.h
echo "#define HAVE_SPEEX 0" >>./include/fishsound/config.h
echo "#undef HAVE_VORBIS" >>./include/fishsound/config.h
echo "#define HAVE_VORBIS 1" >>./include/fishsound/config.h
echo "#undef HAVE_VORBISENC" >>./include/fishsound/config.h
echo "#define HAVE_VORBISENC 0" >>./include/fishsound/config.h
echo "#undef DEBUG" >>./include/fishsound/config.h
cp $1/include/fishsound/encode.h ./include/fishsound/encode.h
cp $1/include/fishsound/comments.h ./include/fishsound/comments.h
cp $1/include/fishsound/deprecated.h ./include/fishsound/deprecated.h
cp $1/include/fishsound/fishsound.h ./include/fishsound/fishsound.h
cp $1/include/fishsound/constants.h ./include/fishsound/constants.h
cp $1/include/fishsound/decode.h ./include/fishsound/decode.h
cp $1/COPYING ./COPYING
cp $1/README ./README
cp ./include/fishsound/config.h ./src/libfishsound/config.h
cp $1/src/libfishsound/decode.c ./src/libfishsound/fishsound_decode.c
cp $1/src/libfishsound/fishsound.c ./src/libfishsound/fishsound.c
sed s/\#include\ \<vorbis\\/vorbisenc.h\>/\#if\ HAVE_VORBISENC\\n\#include\ \<vorbis\\/vorbisenc.h\>\\n\#endif/g $1/src/libfishsound/vorbis.c >./src/libfishsound/fishsound_vorbis.c
cp $1/src/libfishsound/flac.c ./src/libfishsound/fishsound_flac.c
cp $1/src/libfishsound/comments.c ./src/libfishsound/fishsound_comments.c
cp $1/src/libfishsound/private.h ./src/libfishsound/private.h
cp $1/src/libfishsound/fs_compat.h ./src/libfishsound/fs_compat.h
cp $1/src/libfishsound/speex.c ./src/libfishsound/fishsound_speex.c
cp $1/src/libfishsound/encode.c ./src/libfishsound/fishsound_encode.c
cp $1/src/libfishsound/fs_vector.h ./src/libfishsound/fs_vector.h
cp $1/src/libfishsound/fs_vector.c ./src/libfishsound/fs_vector.c
cp $1/src/libfishsound/convert.h ./src/libfishsound/convert.h
cp $1/src/libfishsound/debug.h ./src/libfishsound/debug.h
cp $1/AUTHORS ./AUTHORS
patch -p3 <endian.patch
patch -p3 <bug487519.patch
patch -p3 <trac497.patch
patch -p3 <fishsound_reset.patch
patch -p3 <bug520500.patch

Просмотреть файл

@ -1,29 +0,0 @@
Copyright (C) 2003 CSIRO Australia
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of the CSIRO nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ORGANISATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Просмотреть файл

@ -1,51 +0,0 @@
# ***** 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

Просмотреть файл

@ -1,68 +0,0 @@
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, libtheora, optionally libspeex -- from http://www.xiph.org/
svn co http://svn.xiph.org/trunk/ogg/ ogg
svn co http://svn.xiph.org/trunk/vorbis/ vorbis
svn co http://svn.xiph.org/trunk/theora/ theora
* liboggz and libfishsound -- from svn.annodex.net:
git clone git://git.xiph.org/liboggz.git
git clone git://git.xiph.org/libfishsound.git
Optionally, for Kate stream support, you need
* libkate -- from http://libkate.googlecode.com/
To render Kate streams as video overlays, you need
* libtiger -- from http://libtiger.googlecode.com/
Note that libtiger needs Pango and Cairo:
* Pango -- http://www.pango.org/
* Cairo -- http://cairographics.com/
See the README files associated with these libraries for installation
instructions.
To build src/examples/glut-player, you need:
* The core liboggplay dependencies (listed above)
* GLUT -- see http://www.opengl.org/resources/libraries/
To build src/examples/dump-all-streams, you need:
* The core liboggplay dependencies (listed above)
* libsndfile -- from http://www.mega-nerd.com/libsndfile/
To build src/tools/oggplay-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

Просмотреть файл

@ -1,48 +0,0 @@
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.
git://git.xiph.org/liboggplay.git
The git commit ID used was 404316e5957370b3c854a86910c237c90746c325.
The following local patches have been applied:
endian: pick up NSPR's little/big endian defines in oggplay's config.h.
bug481921: fix a crash in oggplay_callback_info_prepare().
aspect-ratio: Adds oggplay_get_video_aspect_ratio, used for bug 480058.
bug493678.patch: fix for infinite loop in oggplay_step_decode. See bug 493678.
seek_to_key_frame.patch: Adds oggplay_seek_to_keyframe(), as per bug 463358.
oggplay_os2.patch: Bug 448918 - add OS/2 support (this patch should be
removed when OS/2 support is added upstream)
bug496529.patch: Fix bug 496529.
bug500311.patch: Fix crash during decoder initialization.
faster_seek.patch: Fix for bug 501031, make seeking faster over HTTP.
fix-17ef4ca82df28.patch: Fix oggplay_callback_predetected() to return
value interpreted as success upon success.
Fixes liboggplay changeset 17ef4ca82df28.
handle-read-errors.patch: Make oggplay_initialise() handle closing of stream
while reading. Prevents infinite loop. Further fix
to 17ef4ca82df28.
bug515217.patch: Fix crash where presentation thread releases a buffer just
before decode thread tries to set that buffer as the last at EOF.
bug504843.patch: Abort when decoding video excessively large video frames.
fishsound_reset.patch: Fixes bug 516323.
bug520493.patch: Ensure liboggplay returns data when all tracks
are deactivated when a callback reaches EOF.
bug523816.patch: Correct CMML data buffer size calculation.

Просмотреть файл

@ -1,72 +0,0 @@
diff --git a/media/liboggplay/include/oggplay/oggplay.h b/media/liboggplay/include/oggplay/oggplay.h
--- a/media/liboggplay/include/oggplay/oggplay.h
+++ b/media/liboggplay/include/oggplay/oggplay.h
@@ -226,16 +226,19 @@ oggplay_get_audio_samplerate(OggPlay *me
* @retval E_OGGPLAY_BAD_TRACK the given track number does not exists
* @retval E_OGGPLAY_WRONG_TRACK_TYPE the given track is not an audio track
* @retval E_OGGPLAY_UNINITIALISED the OggPlay handle is uninitalised.
*/
OggPlayErrorCode
oggplay_get_video_fps(OggPlay *me, int track, int* fps_denom, int* fps_num);
OggPlayErrorCode
+oggplay_get_video_aspect_ratio(OggPlay *me, int track, int* aspect_denom, int* aspect_num);
+
+OggPlayErrorCode
oggplay_convert_video_to_rgb(OggPlay *me, int track, int convert, int swap_rgb);
OggPlayErrorCode
oggplay_get_kate_category(OggPlay *me, int track, const char** category);
OggPlayErrorCode
oggplay_get_kate_language(OggPlay *me, int track, const char** language);
diff --git a/media/liboggplay/src/liboggplay/oggplay.c b/media/liboggplay/src/liboggplay/oggplay.c
--- a/media/liboggplay/src/liboggplay/oggplay.c
+++ b/media/liboggplay/src/liboggplay/oggplay.c
@@ -297,16 +297,45 @@ oggplay_get_video_fps(OggPlay *me, int t
(*fps_denom) = decode->video_info.fps_denominator;
(*fps_num) = decode->video_info.fps_numerator;
return E_OGGPLAY_OK;
}
OggPlayErrorCode
+oggplay_get_video_aspect_ratio(OggPlay *me, int track, int* aspect_denom, int* aspect_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.aspect_denominator == 0)
+ || (decode->video_info.aspect_numerator == 0)) {
+ return E_OGGPLAY_UNINITIALISED;
+ }
+
+ (*aspect_denom) = decode->video_info.aspect_denominator;
+ (*aspect_num) = decode->video_info.aspect_numerator;
+
+ return E_OGGPLAY_OK;
+}
+
+OggPlayErrorCode
oggplay_convert_video_to_rgb(OggPlay *me, int track, int convert, int swap_rgb) {
OggPlayTheoraDecode *decode;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (track < 0 || track >= me->num_tracks) {

Просмотреть файл

@ -1,32 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_callback_info.c b/media/liboggplay/src/liboggplay/oggplay_callback_info.c
--- a/media/liboggplay/src/liboggplay/oggplay_callback_info.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback_info.c
@@ -133,21 +133,23 @@ oggplay_callback_info_prepare(OggPlay *m
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 (!p->has_been_presented) {
+ 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
*/

Просмотреть файл

@ -1,30 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c
--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
@@ -543,16 +543,26 @@ oggplay_callback_audio (OGGZ * oggz, ogg
}
default:
/* there was no problem with decoding */
if (!common->num_header_packets) common->initialised |= 1;
break;
}
+ if (bytes_read < 0) {
+ printf("\nERROR HADNLING MISMATCH BETWEEN liboggplay AND mozilla\n\n");
+ // Unrecoverable error, disable track
+ op->e_o_s = 1;
+ common->active = 0;
+ common->player->active_tracks--;
+ return OGGZ_ERR_HOLE_IN_DATA;
+ }
+
+
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--;

Просмотреть файл

@ -1,13 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c
index 7683b80..ad127a0 100644
--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
@@ -536,7 +536,7 @@ oggplay_initialise_decoder(OggPlay *me, int content_type, int serialno) {
decoder->content_type = content_type;
decoder->content_type_name =
oggz_stream_get_content_type (me->oggz, serialno);
- decoder->active = 1;
+ decoder->active = 0;
decoder->final_granulepos = -1;
decoder->player = me;
decoder->decoded_type = OGGPLAY_TYPE_UNKNOWN;

Просмотреть файл

@ -1,22 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c b/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
--- a/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
+++ b/media/liboggplay/src/liboggplay/oggplay_yuv2rgb.c
@@ -174,17 +174,17 @@ YUV_CONVERT(yuv444_to_argb_vanilla, CONV
* macros as there's no way e.g. we could compile a x86 asm code
* on a ppc machine and vica-versa
*/
#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64)
#if !defined(_M_AMD64)
#define ENABLE_MMX
#endif
#include "x86/oggplay_yuv2rgb_x86.c"
-#if defined(ATTRIBUTE_ALIGNED_MAX) && ATTRIBUTE_ALIGNED_MAX >= 16
+#if defined(_MSC_VER) || defined(ATTRIBUTE_ALIGNED_MAX) && ATTRIBUTE_ALIGNED_MAX >= 16
#define ENABLE_SSE2
#endif
#elif defined(__ppc__) || defined(__ppc64__)
#define ENABLE_ALTIVEC
//altivec intristics only working with -maltivec gcc flag,
//but we want runtime altivec detection, hence this has to be
//fixed!
//#include "oggplay_yuv2rgb_altivec.c"

Просмотреть файл

@ -1,79 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay.c b/media/liboggplay/src/liboggplay/oggplay.c
--- a/media/liboggplay/src/liboggplay/oggplay.c
+++ b/media/liboggplay/src/liboggplay/oggplay.c
@@ -149,16 +149,17 @@ oggplay_initialise(OggPlay *me, int bloc
}
/*
* set all the tracks to inactive
*/
for (i = 0; i < me->num_tracks; i++) {
me->decode_data[i]->active = 0;
}
+ me->active_tracks = 0;
/*
* if the buffer was set up before initialisation, prepare it now
*/
if (me->buffer != NULL) {
oggplay_buffer_prepare(me);
}
diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c
--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
@@ -60,16 +60,17 @@ oggplay_init_theora(void *user_data) {
theora_info_init(&(decoder->video_info));
theora_comment_init(&(decoder->video_comment));
decoder->granulepos_seen = 0;
decoder->frame_delta = 0;
decoder->y_width = 0;
decoder->convert_to_rgb = 0;
decoder->swap_rgb = 0;
decoder->decoder.decoded_type = OGGPLAY_YUV_VIDEO;
+ decoder->decoder.player->active_tracks++;
}
void
oggplay_shutdown_theora(void *user_data) {
OggPlayDecode * common;
OggPlayTheoraDecode * decoder = (OggPlayTheoraDecode *)user_data;
if (decoder == NULL) {
@@ -499,16 +500,17 @@ oggplay_init_audio (void * user_data) {
}
decoder->sound_info.channels = 0;
fish_sound_set_decoded_float_ilv(decoder->sound_handle,
oggplay_fish_sound_callback_floats,
(void *)decoder);
decoder->decoder.decoded_type = OGGPLAY_FLOATS_AUDIO;
+ decoder->decoder.player->active_tracks++;
}
void
oggplay_shutdown_audio(void *user_data) {
OggPlayAudioDecode * decoder = (OggPlayAudioDecode *)user_data;
if (decoder == NULL) {
@@ -814,17 +816,17 @@ oggplay_initialise_decoder(OggPlay *me,
if (decoder == NULL)
return NULL;
decoder->serialno = serialno;
decoder->content_type = content_type;
decoder->content_type_name =
oggz_stream_get_content_type (me->oggz, serialno);
- decoder->active = 0;
+ decoder->active = 1;
decoder->final_granulepos = -1;
decoder->player = me;
decoder->decoded_type = OGGPLAY_TYPE_UNKNOWN;
decoder->num_header_packets =
oggz_stream_get_numheaders (me->oggz, serialno);
/*
* set the StreamInfo to unitialised until we get some real data in

Просмотреть файл

@ -1,185 +0,0 @@
diff --git a/media/liboggplay/include/oggplay/oggplay.h b/media/liboggplay/include/oggplay/oggplay.h
--- a/media/liboggplay/include/oggplay/oggplay.h
+++ b/media/liboggplay/include/oggplay/oggplay.h
@@ -116,17 +116,17 @@ oggplay_new_with_reader(OggPlayReader *r
*
* @param me OggPlay handle
* @param block passed as the second argument to the OggPlayReader's initialise
* function. E.g. in case of OggPlayTCPReader block == 0 sets the socket to non-blocking
* mode.
* @retval E_OGGPLAY_OK on success
* @retval E_OGGPLAY_OGGZ_UNHAPPY something went wrong while calling oggz_io_set_* functions.
* @retval E_OGGPLAY_BAD_INPUT got EOF or OGGZ_ERR_HOLE_IN_DATA occured.
- * @retval E_OGGPLAY_OUT_OF_MEMORY ran out of memory
+ * @retval E_OGGPLAY_OUT_OF_MEMORY ran out of memory or video frame too large.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle.
*/
OggPlayErrorCode
oggplay_initialise(OggPlay *me, int block);
/**
* Sets a user defined OggPlayDataCallback function for the OggPlay handle.
*
@@ -344,13 +344,31 @@ oggplay_get_available(OggPlay *player);
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle
*/
ogg_int64_t
oggplay_get_duration(OggPlay * player);
int
oggplay_media_finished_retrieving(OggPlay * player);
+/**
+ * Sets the maximum video frame size, in pixels, which OggPlay will attempt to
+ * decode. Call this after oggplay_new_with_reader() but before
+ * oggplay_initialise() to prevent crashes with excessivly large video frame
+ * sizes. oggplay_initialise() will return E_OGGPLAY_OUT_OF_MEMORY if the
+ * decoded video's frame requires more than max_frame_pixels. Unless
+ * oggplay_set_max_video_size() is called, default maximum number of pixels
+ * per frame is INT_MAX.
+ *
+ * @param player OggPlay handle.
+ * @param max_frame_pixels max number of pixels per frame.
+ * @retval E_OGGPLAY_OK on success.
+ * @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle.
+ */
+int
+oggplay_set_max_video_frame_pixels(OggPlay *player,
+ int max_frame_pixels);
+
#ifdef __cplusplus
}
#endif
#endif /* __OGGPLAY_H__ */
diff --git a/media/liboggplay/src/liboggplay/oggplay.c b/media/liboggplay/src/liboggplay/oggplay.c
--- a/media/liboggplay/src/liboggplay/oggplay.c
+++ b/media/liboggplay/src/liboggplay/oggplay.c
@@ -68,16 +68,17 @@ oggplay_new_with_reader(OggPlayReader *r
me->target = 0L;
me->active_tracks = 0;
me->buffer = NULL;
me->shutdown = 0;
me->trash = NULL;
me->oggz = NULL;
me->pt_update_valid = 1;
me->duration = -1;
+ me->max_video_frame_pixels = OGGPLAY_TYPE_MAX_SIGNED(int);
return me;
}
OggPlayErrorCode
oggplay_initialise(OggPlay *me, int block) {
@@ -958,8 +959,16 @@ oggplay_media_finished_retrieving(OggPla
if (me->reader == NULL) {
return E_OGGPLAY_BAD_READER;
}
return me->reader->finished_retrieving(me->reader);
}
+int
+oggplay_set_max_video_frame_pixels(OggPlay *player,
+ int max_frame_pixels) {
+ if (!player)
+ return E_OGGPLAY_BAD_OGGPLAY;
+ player->max_video_frame_pixels = max_frame_pixels;
+ return E_OGGPLAY_OK;
+}
diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c
--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
@@ -83,16 +83,42 @@ oggplay_shutdown_theora(void *user_data)
if (common->initialised == 1 && decoder->decoder.num_header_packets == 0) {
theora_clear(&(decoder->video_handle));
}
theora_info_clear(&(decoder->video_info));
theora_comment_clear(&(decoder->video_comment));
}
+/**
+ * Returns 1 if the video as described by |info| requires more than
+ * max_video_pixels pixels per frame, otherwise returns 0.
+ */
+static int
+frame_is_too_large(theora_info *info, long max_video_pixels) {
+ int overflow = 0;
+ long frame_pixels = 0;
+ long display_pixels = 0;
+ if (!info) {
+ return 1;
+ }
+ overflow |= oggplay_mul_signed_overflow(info->frame_width,
+ info->frame_height,
+ &frame_pixels);
+ overflow |= oggplay_mul_signed_overflow(info->width,
+ info->height,
+ &display_pixels);
+ if (overflow ||
+ frame_pixels > max_video_pixels ||
+ display_pixels > max_video_pixels) {
+ return 1;
+ }
+ return 0;
+}
+
int
oggplay_callback_theora (OGGZ * oggz, ogg_packet * op, long serialno,
void * user_data) {
OggPlayTheoraDecode * decoder = (OggPlayTheoraDecode *)user_data;
OggPlayDecode * common = NULL;
ogg_int64_t granulepos = oggz_tell_granulepos(oggz);
yuv_buffer buffer;
@@ -184,17 +210,24 @@ oggplay_callback_theora (OGGZ * oggz, og
((decoder->video_info.height - decoder->video_info.offset_y)<decoder->video_info.frame_height)
||
((decoder->video_info.width - decoder->video_info.offset_x)<decoder->video_info.frame_width)
)
{
common->initialised |= -1;
return OGGZ_CONTINUE;
}
-
+
+ /* Ensure the video frames don't require more pixels than our
+ * allowed maximum. */
+ if (frame_is_too_large(&decoder->video_info,
+ common->player->max_video_frame_pixels)) {
+ return OGGZ_ERR_OUT_OF_MEMORY;
+ }
+
if (theora_decode_init(&(decoder->video_handle), &(decoder->video_info))) {
common->initialised |= -1;
return OGGZ_CONTINUE;
}
common->initialised |= 1;
}
return OGGZ_CONTINUE;
diff --git a/media/liboggplay/src/liboggplay/oggplay_private.h b/media/liboggplay/src/liboggplay/oggplay_private.h
--- a/media/liboggplay/src/liboggplay/oggplay_private.h
+++ b/media/liboggplay/src/liboggplay/oggplay_private.h
@@ -256,16 +256,17 @@ struct _OggPlay {
ogg_int64_t target; /**< */
int active_tracks; /**< number of active tracks */
volatile OggPlayBuffer * buffer; /**< @see OggPlayBuffer */
ogg_int64_t presentation_time; /**< */
OggPlaySeekTrash * trash; /**< @see OggPlaySeekTrash */
int shutdown; /**< "= 1" indicates shutdown event */
int pt_update_valid; /**< */
ogg_int64_t duration; /**< The value of the duration the last time it was retrieved.*/
+ int max_video_frame_pixels; /**< Maximum number of pixels we'll allow in a video frame.*/
};
void
oggplay_set_data_callback_force(OggPlay *me, OggPlayDataCallback callback,
void *user);
void
oggplay_take_out_trash(OggPlay *me, OggPlaySeekTrash *trash);

Просмотреть файл

@ -1,98 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay.c b/media/liboggplay/src/liboggplay/oggplay.c
--- a/media/liboggplay/src/liboggplay/oggplay.c
+++ b/media/liboggplay/src/liboggplay/oggplay.c
@@ -746,29 +746,27 @@ read_more_data:
* set all of the tracks to inactive
*/
for (i = 0; i < me->num_tracks; i++) {
me->decode_data[i]->active = 0;
}
me->active_tracks = 0;
if (info != NULL) {
+ /* ensure all tracks have their final data packet set to end_of_stream */
+ OggPlayCallbackInfo *p = info[0];
+ for (i = 0; i < me->num_tracks; i++) {
+ p->stream_info = OGGPLAY_STREAM_LAST_DATA;
+ p++;
+ }
+
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
- * But skip doing this if we're shutting down --- me->buffer may not
- * be in a safe state.
- */
- if (me->buffer != NULL && !me->shutdown) {
- oggplay_buffer_set_last_data(me, me->buffer);
- }
-
/* we reached the end of the stream */
return E_OGGPLAY_OK;
case OGGZ_ERR_HOLE_IN_DATA:
/* there was a whole in the data */
return E_OGGPLAY_BAD_INPUT;
case OGGZ_ERR_STOP_ERR:
diff --git a/media/liboggplay/src/liboggplay/oggplay_buffer.c b/media/liboggplay/src/liboggplay/oggplay_buffer.c
--- a/media/liboggplay/src/liboggplay/oggplay_buffer.c
+++ b/media/liboggplay/src/liboggplay/oggplay_buffer.c
@@ -138,38 +138,16 @@ oggplay_buffer_is_full(volatile OggPlayB
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;
diff --git a/media/liboggplay/src/liboggplay/oggplay_buffer.h b/media/liboggplay/src/liboggplay/oggplay_buffer.h
--- a/media/liboggplay/src/liboggplay/oggplay_buffer.h
+++ b/media/liboggplay/src/liboggplay/oggplay_buffer.h
@@ -53,12 +53,9 @@ 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

Просмотреть файл

@ -1,66 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay.c b/media/liboggplay/src/liboggplay/oggplay.c
--- a/media/liboggplay/src/liboggplay/oggplay.c
+++ b/media/liboggplay/src/liboggplay/oggplay.c
@@ -638,16 +638,17 @@ OggPlayErrorCode
oggplay_step_decoding(OggPlay *me) {
OggPlayCallbackInfo ** info;
int num_records;
int r;
int i;
int need_data = 0;
int chunk_count = 0;
+ int read_data = 0;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
/*
* check whether the OggPlayDataCallback is set for the given
* OggPlay handle. If not return with error as there's no callback
@@ -686,17 +687,21 @@ read_more_data:
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) {
+ if (remaining == 0 && !read_data) {
+ /*
+ * There's no more data to read, and we've not read any that needs
+ * to be sent to the buffer list via a callback, so exit.
+ */
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
*/
@@ -783,16 +788,21 @@ read_more_data:
* e.g. some buffer overflow.
*/
case OGGZ_ERR_OUT_OF_MEMORY:
/* ran out of memory during decoding! */
return E_OGGPLAY_OUT_OF_MEMORY;
default:
+ /*
+ * We read some data. Set a flag so that we're guaranteed to try to
+ * send it to the buffer list via a callback.
+ */
+ read_data = 1;
break;
}
}
/*
* prepare a callback
*/
num_records = oggplay_callback_info_prepare (me, &info);
if (info != NULL) {

Просмотреть файл

@ -1,29 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_data.c b/media/liboggplay/src/liboggplay/oggplay_data.c
--- a/media/liboggplay/src/liboggplay/oggplay_data.c
+++ b/media/liboggplay/src/liboggplay/oggplay_data.c
@@ -353,22 +353,19 @@ oggplay_data_handle_audio_data (OggPlayD
OggPlayErrorCode
oggplay_data_handle_cmml_data(OggPlayDecode *decode,
unsigned char *data,
long size) {
OggPlayTextRecord * record = NULL;
size_t record_size = sizeof(OggPlayTextRecord);
- /* check that the size we want to allocate doesn't overflow */
- if ((size < 0) || (size+1 < 0)) {
- return E_OGGPLAY_TYPE_OVERFLOW;
- }
- size += 1;
-
+ /* Include extra byte for null terminating record data buffer */
+ record_size += 1;
+
if
(
oggplay_check_add_overflow (record_size, size, &record_size)
==
E_OGGPLAY_TYPE_OVERFLOW
)
{
return E_OGGPLAY_TYPE_OVERFLOW;

Просмотреть файл

@ -1,18 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/config.h b/media/liboggplay/src/liboggplay/config.h
--- a/media/liboggplay/src/liboggplay/config.h
+++ b/media/liboggplay/src/liboggplay/config.h
@@ -102,8 +102,14 @@
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
#undef HAVE_GLUT
+
+#include "prcpucfg.h"
+#ifdef IS_BIG_ENDIAN
+#define WORDS_BIGENDIAN 1
+#endif
+

Просмотреть файл

@ -1,78 +0,0 @@
diff --git a/media/liboggplay/include/oggplay/oggplay_seek.h b/media/liboggplay/include/oggplay/oggplay_seek.h
--- a/media/liboggplay/include/oggplay/oggplay_seek.h
+++ b/media/liboggplay/include/oggplay/oggplay_seek.h
@@ -53,15 +53,13 @@
OggPlayErrorCode
oggplay_seek(OggPlay *me, ogg_int64_t milliseconds);
/**
* Seeks to key frame before |milliseconds|.
*/
OggPlayErrorCode
oggplay_seek_to_keyframe(OggPlay *me,
- int* tracks,
- int num_tracks,
ogg_int64_t milliseconds,
ogg_int64_t offset_begin,
ogg_int64_t offset_end);
#endif
diff --git a/media/liboggplay/src/liboggplay/oggplay_seek.c b/media/liboggplay/src/liboggplay/oggplay_seek.c
--- a/media/liboggplay/src/liboggplay/oggplay_seek.c
+++ b/media/liboggplay/src/liboggplay/oggplay_seek.c
@@ -186,54 +186,39 @@ oggplay_take_out_trash(OggPlay *me, OggP
if (p != NULL) {
oggplay_free(p);
}
}
OggPlayErrorCode
oggplay_seek_to_keyframe(OggPlay *me,
- int* tracks,
- int num_tracks,
ogg_int64_t milliseconds,
ogg_int64_t offset_begin,
ogg_int64_t offset_end)
{
- long *serial_nos;
- int i;
ogg_int64_t eof, time;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
- if (num_tracks > me->num_tracks || milliseconds < 0)
+ if (milliseconds < 0)
return E_OGGPLAY_CANT_SEEK;
eof = oggplay_get_duration(me);
if (eof > -1 && milliseconds > eof) {
return E_OGGPLAY_CANT_SEEK;
}
- // Get the serialnos for the tracks we're seeking.
- serial_nos = (long*)oggplay_malloc(sizeof(long)*num_tracks);
- if (!serial_nos) {
- return E_OGGPLAY_CANT_SEEK;
- }
- for (i=0; i<num_tracks; i++) {
- serial_nos[i] = me->decode_data[tracks[i]]->serialno;
- }
time = oggz_keyframe_seek_set(me->oggz,
- serial_nos,
- num_tracks,
milliseconds,
offset_begin,
offset_end);
- oggplay_free(serial_nos);
if (time == -1) {
return E_OGGPLAY_CANT_SEEK;
}
oggplay_seek_cleanup(me, time);
return E_OGGPLAY_OK;

Просмотреть файл

@ -1,24 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_seek.c b/media/liboggplay/src/liboggplay/oggplay_seek.c
--- a/media/liboggplay/src/liboggplay/oggplay_seek.c
+++ b/media/liboggplay/src/liboggplay/oggplay_seek.c
@@ -166,6 +166,20 @@ oggplay_seek_cleanup(OggPlay* me, ogg_in
*p = trash;
+ if (milliseconds == 0) {
+ for (i = 0; i < me->num_tracks; i++) {
+ OggPlayDecode *track = me->decode_data[i];
+ FishSound *sound_handle;
+ OggPlayAudioDecode *audio_decode;
+ if (track->content_type != OGGZ_CONTENT_VORBIS) {
+ continue;
+ }
+ audio_decode = (OggPlayAudioDecode*)track;
+ sound_handle = audio_decode->sound_handle;
+ fish_sound_reset(sound_handle);
+ }
+ }
+
return E_OGGPLAY_OK;
}

Просмотреть файл

@ -1,15 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_callback.c b/media/liboggplay/src/liboggplay/oggplay_callback.c
--- a/media/liboggplay/src/liboggplay/oggplay_callback.c
+++ b/media/liboggplay/src/liboggplay/oggplay_callback.c
@@ -977,10 +982,10 @@ oggplay_callback_predetected (OGGZ *oggz
}
}
/* disable the callback for unforeseen streams */
oggz_set_read_callback (me->oggz, -1, NULL, NULL);
}
/* read the header part of the ogg content in a packet-by-packet manner */
- return ((ret < 0) ? ret : OGGZ_STOP_OK);
+ return ((ret < 0) ? ret : OGGZ_CONTINUE);
}

Просмотреть файл

@ -1,26 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay.c b/media/liboggplay/src/liboggplay/oggplay.c
--- a/media/liboggplay/src/liboggplay/oggplay.c
+++ b/media/liboggplay/src/liboggplay/oggplay.c
@@ -136,16 +136,22 @@ oggplay_initialise(OggPlay *me, int bloc
case OGGZ_ERR_OUT_OF_MEMORY:
/* ran out of memory during decoding! */
return E_OGGPLAY_OUT_OF_MEMORY;
case OGGZ_ERR_STOP_ERR:
/* */
return E_OGGPLAY_BAD_OGGPLAY;
+
+ default:
+ /* If the read otherwise failed, bail out. */
+ if (i < 0)
+ return E_OGGPLAY_BAD_INPUT;
+ break;
}
if (me->all_tracks_initialised) {
break;
}
}
/*

Просмотреть файл

@ -1,47 +0,0 @@
# ***** 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

Просмотреть файл

@ -1,57 +0,0 @@
# ***** 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
EXPORTS_NAMESPACES = oggplay
EXPORTS_oggplay = \
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

Просмотреть файл

@ -1,78 +0,0 @@
/* 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. */
/* #undef HAVE_DLFCN_H */
/* Define to 1 if you have the <inttypes.h> header file. */
/* #undef HAVE_INTTYPES_H */
/* Define to 1 if you have the <memory.h> header file. */
/* #undef HAVE_MEMORY_H */
/* Define if have liboggz */
#define HAVE_OGGZ 1
/* Define to 1 if you have the <stdint.h> header file. */
/* #undef HAVE_STDINT_H */
/* 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. */
/* #undef HAVE_STRINGS_H */
/* 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. */
/* #undef HAVE_SYS_STAT_H */
/* Define to 1 if you have the <sys/types.h> header file. */
/* #undef HAVE_SYS_TYPES_H */
/* Define to 1 if you have the <unistd.h> header file. */
/* #undef HAVE_UNISTD_H */
/* 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.2.0"
/* 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 */
/* Maximum supported data alignment */
#define ATTRIBUTE_ALIGNED_MAX 16

Просмотреть файл

@ -1,374 +0,0 @@
/*
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.
*/
/** @file
*
* The liboggplay C API.
*
* @authors
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
* Viktor Gal
*/
#ifndef __OGGPLAY_H__
#define __OGGPLAY_H__
#ifdef __cplusplus
extern "C" {
#endif
#include <oggplay/oggplay_enums.h>
#include <oggplay/oggplay_reader.h>
/**
* This is returned by oggplay_open_with_reader() or oggplay_new_with_reader().
*/
typedef struct _OggPlay OggPlay;
/**
* A structure for storing the decoded frames for the various streams in the
* Ogg container.
*/
typedef struct _OggPlayCallbackInfo OggPlayCallbackInfo;
/**
* This is the signature of a callback which you must provide for OggPlay
* to call whenever there's any unpresented decoded frame available.
*
* @see oggplay_step_decoding
* @param player The OggPlay handle
* @param num_records size of the OggPlayCallbackInfo array
* @param records array of OggPlayCallbackInfo
* @param user A generic pointer for the data the user provided earlier.
* @returns 0 to continue, non-zero to instruct OggPlay to stop.
*
*/
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>
/**
* Create an OggPlay handle associated with the given reader.
*
* This functions creates a new OggPlay handle associated with
* the OggPlayReader and it calls oggplay_initialise to
* read the header packets of the Ogg container.
*
* @param reader an OggPlayReader handle associated with the Ogg content
* @return A new OggPlay handle
* @retval NULL in case of error.
*/
OggPlay *
oggplay_open_with_reader(OggPlayReader *reader);
/**
* Create a new OggPlay handle associated with the given reader.
*
* @param reader OggPlayReader handle associated with the Ogg content
* @return A new OggPlay handle
* @retval NULL in case of error.
*/
OggPlay *
oggplay_new_with_reader(OggPlayReader *reader);
/**
* Initialise the OggPlay handle.
*
* This function creates an Oggz handle and sets it's OggzIO*
* functions to the OggPlayReader's io_* functions. Moreover
* it reads the Ogg container's content until it hasn't got
* all the streams' headers.
*
* @param me OggPlay handle
* @param block passed as the second argument to the OggPlayReader's initialise
* function. E.g. in case of OggPlayTCPReader block == 0 sets the socket to non-blocking
* mode.
* @retval E_OGGPLAY_OK on success
* @retval E_OGGPLAY_OGGZ_UNHAPPY something went wrong while calling oggz_io_set_* functions.
* @retval E_OGGPLAY_BAD_INPUT got EOF or OGGZ_ERR_HOLE_IN_DATA occured.
* @retval E_OGGPLAY_OUT_OF_MEMORY ran out of memory or video frame too large.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle.
*/
OggPlayErrorCode
oggplay_initialise(OggPlay *me, int block);
/**
* Sets a user defined OggPlayDataCallback function for the OggPlay handle.
*
* @param me OggPlay handle.
* @param callback A custom callback function.
* @param user Arbitrary data one wishes to pass to the callback function.
* @retval E_OGGPLAY_OK on success
* @retval E_OGGPLAY_BUFFER_MODE We are running in buffer mode, i.e. oggplay_use_buffer
* has been called earlier.
* @retval E_OGGPLAY_BAD_OGGPLAY Invalid OggPlay handle.
*/
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_callback_period(OggPlay *me, int stream, int milliseconds);
OggPlayErrorCode
oggplay_set_offset(OggPlay *me, int track, ogg_int64_t offset);
/**
* Get the given video track's Y-plane's width and height.
*
* @param me OggPlay handle
* @param track the track number of the video track
* @param y_width the width of the Y-plane
* @param y_height the height of the Y-plane
* @retval E_OGGPLAY_OK on success.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle
* @retval E_OGGPLAY_BAD_TRACK the given track number does not exists
* @retval E_OGGPLAY_WRONG_TRACK_TYPE the given track is not an audio track
* @retval E_OGGPLAY_UNINITIALISED the OggPlay handle is uninitalised.
*/
OggPlayErrorCode
oggplay_get_video_y_size(OggPlay *me, int track, int *y_width, int *y_height);
/**
* Get the given video track's UV-plane's width and height.
*
* @param me OggPlay handle
* @param track the track number of the video track
* @param uv_width the width of the UV-plane
* @param uv_height the height of the UV-plane
* @retval E_OGGPLAY_OK on success.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle
* @retval E_OGGPLAY_BAD_TRACK the given track number does not exists
* @retval E_OGGPLAY_WRONG_TRACK_TYPE the given track is not an audio track
* @retval E_OGGPLAY_UNINITIALISED the OggPlay handle is uninitalised.
*/
OggPlayErrorCode
oggplay_get_video_uv_size(OggPlay *me, int track, int *uv_width, int *uv_height);
/**
* Get the number of channels of the audio track.
*
* @param me OggPlay handle
* @param track the track number of the audio track
* @param channels the number of channels of the given audio track.
* @retval E_OGGPLAY_OK on success.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle
* @retval E_OGGPLAY_BAD_TRACK the given track number does not exists
* @retval E_OGGPLAY_WRONG_TRACK_TYPE the given track is not an audio track
* @retval E_OGGPLAY_UNINITIALISED the OggPlay handle is uninitalised.
*/
OggPlayErrorCode
oggplay_get_audio_channels(OggPlay *me, int track, int *channels);
/**
* Get the sample rate of the of the audio track
*
* @param me OggPlay handle
* @param track the track number of the audio track
* @param samplerate the sample rate of the audio track.
* @retval E_OGGPLAY_OK on success.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle
* @retval E_OGGPLAY_BAD_TRACK the given track number does not exists
* @retval E_OGGPLAY_WRONG_TRACK_TYPE the given track is not an audio track
* @retval E_OGGPLAY_UNINITIALISED the OggPlay handle is uninitalised.
*/
OggPlayErrorCode
oggplay_get_audio_samplerate(OggPlay *me, int track, int *samplerate);
/**
* Get the frame-per-second value the of a given video track.
*
* @param me OggPlay handle
* @param track the track number of the audio track
* @param fps_denom the denumerator of the FPS
* @param fps_num the numerator of the FPS
* @retval E_OGGPLAY_OK on success.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle
* @retval E_OGGPLAY_BAD_TRACK the given track number does not exists
* @retval E_OGGPLAY_WRONG_TRACK_TYPE the given track is not an audio track
* @retval E_OGGPLAY_UNINITIALISED the OggPlay handle is uninitalised.
*/
OggPlayErrorCode
oggplay_get_video_fps(OggPlay *me, int track, int* fps_denom, int* fps_num);
OggPlayErrorCode
oggplay_get_video_aspect_ratio(OggPlay *me, int track, int* aspect_denom, int* aspect_num);
OggPlayErrorCode
oggplay_convert_video_to_rgb(OggPlay *me, int track, int convert, int swap_rgb);
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_set_kate_tiger_rendering(OggPlay *me, int track, int use_tiger, int swap_rgb, int default_width, int default_height);
OggPlayErrorCode
oggplay_overlay_kate_track_on_video(OggPlay *me, int kate_track, int video_track);
OggPlayErrorCode
oggplay_start_decoding(OggPlay *me);
/**
* Decode the streams in the Ogg container until we find data that hasn't
* been presented, yet.
*
* Whenever there is data that hasn't been presented the OggPlayDataCallback
* function will be called.
*
* @param me OggPlay handle
* @retval E_OGGPLAY_OK reached the end of the stream or shutdown detected
* @retval E_OGGPLAY_CONTINUE successfully decoded the frames.
* @retval E_OGGPLAY_BAD_INPUT OGGZ_ERR_HOLE_IN_DATA occured while decoding
* @retval E_OGGPLAY_UNINITIALISED the OggPlayDataCallback of the OggPlay handle is not set.
* @retval E_OGGPLAY_USER_INTERRUPT user interrupted the decoding
* @retval E_OGGPLAY_OUT_OF_MEMORY ran out of memory while decoding
*/
OggPlayErrorCode
oggplay_step_decoding(OggPlay *me);
/**
* Use the built-in OggPlayBuffer for buffering the decoded frames
*
* The built-in OggPlayBuffer implements a simple lock-free FIFO for
* storing the decoded frames.
*
* It tries to set the OggPlay handle's OggPlayDataCallback function to it's
* own implementation (oggplay_buffer_callback). Thus it will fail if
* a user already set OggPlayDataCallback of the OggPlay handle
* with oggplay_set_data_callback.
*
* One can retrive the next record in the queue by
* calling oggplay_buffer_retrieve_next.
*
* @param player the OggPlay handle
* @param size The size of the buffer, i.e. the number of records it can store
* @retval E_OGGPLAY_OK on succsess
* @retval E_OGGPLAY_BAD_OGGPLAY The supplied OggPlay handle is not valid
* @retval E_OGGPLAY_CALLBACK_MODE The given OggPlay handle's OggPlayDataCallback
* function is already set, i.e. running in callback-mode.
* @retval E_OGGPLAY_OUT_OF_MEMORY Ran out of memory while trying to allocate memory for the buffer.
*/
OggPlayErrorCode
oggplay_use_buffer(OggPlay *player, int size);
/**
* Retrive the next element in the buffer.
*
* @param player OggPlay handle
* @return array of OggPlayCallbackInfo - one per track.
* @retval NULL if there was no available.
*/
OggPlayCallbackInfo **
oggplay_buffer_retrieve_next(OggPlay *player);
/**
* Release the given buffer item.
*
* After retrieving and processing one buffer item, in order
* to remove the given item from the queue and release the
* memory allocated by the buffer item one needs to call this
* function.
*
* @param player OggPlay handle
* @param track_info OggPlayCallbackInfo array to release.
* @retval E_OGGPLAY_OK on success.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle.
*/
OggPlayErrorCode
oggplay_buffer_release(OggPlay *player, OggPlayCallbackInfo **track_info);
void
oggplay_prepare_for_close(OggPlay *me);
/**
* Destroys the OggPlay handle along with the associated OggPlayReader
* and clears out the buffer and shuts down the callback function.
*
* @param player an OggPlay handle
* @retval E_OGGPLAY_OK on success
*/
OggPlayErrorCode
oggplay_close(OggPlay *player);
int
oggplay_get_available(OggPlay *player);
/**
* Get the duration of the Ogg content.
*
* @param player OggPlay handle.
* @return The duration of the content in milliseconds.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle
*/
ogg_int64_t
oggplay_get_duration(OggPlay * player);
int
oggplay_media_finished_retrieving(OggPlay * player);
/**
* Sets the maximum video frame size, in pixels, which OggPlay will attempt to
* decode. Call this after oggplay_new_with_reader() but before
* oggplay_initialise() to prevent crashes with excessivly large video frame
* sizes. oggplay_initialise() will return E_OGGPLAY_OUT_OF_MEMORY if the
* decoded video's frame requires more than max_frame_pixels. Unless
* oggplay_set_max_video_size() is called, default maximum number of pixels
* per frame is INT_MAX.
*
* @param player OggPlay handle.
* @param max_frame_pixels max number of pixels per frame.
* @retval E_OGGPLAY_OK on success.
* @retval E_OGGPLAY_BAD_OGGPLAY invalid OggPlay handle.
*/
int
oggplay_set_max_video_frame_pixels(OggPlay *player,
int max_frame_pixels);
#ifdef __cplusplus
}
#endif
#endif /* __OGGPLAY_H__ */

Просмотреть файл

@ -1,173 +0,0 @@
/*
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.
*/
/** @file
* oggplay_callback_info.h
*
* @authors
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
* Viktor Gal
*/
#ifndef __OGGPLAY_CALLBACK_INFO__
#define __OGGPLAY_CALLBACK_INFO__
/** structure for storing a YUV video frame */
typedef struct {
unsigned char * y; /**< Y-plane */
unsigned char * u; /**< U-plane*/
unsigned char * v; /**< V-plane */
} OggPlayVideoData;
/** structure for storing a video frame in RGB fromat */
typedef struct {
unsigned char * rgba; /**< may be NULL if no alpha */
unsigned char * rgb; /**< may be NULL if alpha */
size_t width; /**< width in pixels */
size_t height; /**< height in pixels */
size_t stride; /**< stride */
} OggPlayOverlayData;
/** Type for representing audio data */
typedef void * OggPlayAudioData;
/** Type for representing text data */
typedef char OggPlayTextData;
struct _OggPlayDataHeader;
/** Header for the various data formats */
typedef struct _OggPlayDataHeader OggPlayDataHeader;
/**
* Get the data type of the given OggPlayCallbackInfo.
*
* @param info
* @returns The data type of the given OggPlayCallbackInfo
* @see OggPlayDataType
*/
OggPlayDataType
oggplay_callback_info_get_type(OggPlayCallbackInfo *info);
int
oggplay_callback_info_get_available(OggPlayCallbackInfo *info);
int
oggplay_callback_info_get_required(OggPlayCallbackInfo *info);
/**
* Get the array of records stored in the OggPlayCallbackInfo
*
* @param info
* @returns array of records
* @retval NULL if the supplied OggPlayCallbackInfo is a NULL pointer
*/
OggPlayDataHeader **
oggplay_callback_info_get_headers(OggPlayCallbackInfo *info);
/**
* Get the size of the given record.
*
* @param header
* @returns The number of samples in the record.
*/
ogg_int64_t
oggplay_callback_info_get_record_size(OggPlayDataHeader *header);
/**
* Extract the video frame from the supplied record.
*
* @param header
* @returns the video frame
* @retval NULL if the supplied OggPlayCallbackInfo is a NULL pointer
*/
OggPlayVideoData *
oggplay_callback_info_get_video_data(OggPlayDataHeader *header);
/**
* Extract the overlay data from the supplied record.
*
* @param header
* @returns OggPlayOverlayData
* @retval NULL if the supplied OggPlayCallbackInfo is a NULL pointer
*/
OggPlayOverlayData *
oggplay_callback_info_get_overlay_data(OggPlayDataHeader *header);
/**
* Extract the audio data from the supplied record.
*
* @param header
* @returns OggPlayAudioData.
* @retval NULL if the supplied OggPlayCallbackInfo is a NULL pointer
*/
OggPlayAudioData *
oggplay_callback_info_get_audio_data(OggPlayDataHeader *header);
/**
* Extract the text data from the supplied record.
*
* @param header
* @returns OggPlayTextData
* @retval NULL if the supplied OggPlayCallbackInfo is a NULL pointer
*/
OggPlayTextData *
oggplay_callback_info_get_text_data(OggPlayDataHeader *header);
/**
* Get the state of the stream.
*
* @param info
* @returns State of the given stream.
* @see OggPlayStreamInfo
*/
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);
/**
* Get the presentation time of the given record.
*
* @param header
* @returns presentation time of the given frame in milliseconds.
*/
long
oggplay_callback_info_get_presentation_time(OggPlayDataHeader *header);
#endif

Просмотреть файл

@ -1,103 +0,0 @@
/*
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.
*/
/** @file
* General constants used by liboggplay
*
* @authors
* Shane Stephens <shane.stephens@annodex.net>
* Michael Martin
* Viktor Gal
*/
#ifndef __OGGPLAY_ENUMS_H__
#define __OGGPLAY_ENUMS_H__
/**
* Definitions of error return values.
*/
typedef enum OggPlayErrorCode {
E_OGGPLAY_CONTINUE = 1,
E_OGGPLAY_OK = 0, /**< No error */
E_OGGPLAY_BAD_OGGPLAY = -1, /**< supplied oggplay is not a valid OggPlay */
E_OGGPLAY_BAD_READER = -2, /**< OggPlayReader is invalid */
E_OGGPLAY_BAD_INPUT = -3, /**< Error in the input */
E_OGGPLAY_NO_SUCH_CHUNK = -4,
E_OGGPLAY_BAD_TRACK = -5, /**< The requested track number does not exists */
E_OGGPLAY_TRACK_IS_SKELETON = -6, /**< Trying to activate a Skeleton track */
E_OGGPLAY_OGGZ_UNHAPPY = -7, /**< OGGZ error occured */
E_OGGPLAY_END_OF_FILE = -8, /**< End of file */
E_OGGPLAY_TRACK_IS_OVER = -9, /**< A given track has ended */
E_OGGPLAY_BAD_CALLBACK_INFO = -10, /**< Invalid OggPlayCallbackInfo */
E_OGGPLAY_WRONG_TRACK_TYPE = -11, /**< */
E_OGGPLAY_UNINITIALISED = -12, /**< The OggPlay handle is not initialised */
E_OGGPLAY_CALLBACK_MODE = -13, /**< OggPlay is used in callback mode */
E_OGGPLAY_BUFFER_MODE = -14, /**< OggPlay is used in buffer mode */
E_OGGPLAY_USER_INTERRUPT = -15, /**< User interrupt received */
E_OGGPLAY_SOCKET_ERROR = -16, /**< Error while creating socket */
E_OGGPLAY_TIMEOUT = -17, /**< TCP connection timeouted */
E_OGGPLAY_CANT_SEEK = -18, /**< Could not performed the requested seek */
E_OGGPLAY_NO_KATE_SUPPORT = -19, /**< LibKate is not supported */
E_OGGPLAY_NO_TIGER_SUPPORT = -20, /**< LibTiger is not supported */
E_OGGPLAY_OUT_OF_MEMORY = -21, /**< Out of memory */
E_OGGPLAY_TYPE_OVERFLOW = -22, /**< Integer overflow detected */
E_OGGPLAY_TRACK_IS_UNKNOWN = -23, /**< The selected track's content type is UNKNOWN */
E_OGGPLAY_TRACK_UNINITIALISED = -24, /**< Track is not initialised, i.e. bad headers or haven't seen them */
E_OGGPLAY_NOTCHICKENPAYBACK = -777
} OggPlayErrorCode;
/**
* Definitions of the various record types
*/
typedef enum OggPlayDataType {
OGGPLAY_INACTIVE = -1, /**< record is inactive */
OGGPLAY_YUV_VIDEO = 0, /**< record is a YUV format video */
OGGPLAY_RGBA_VIDEO = 1, /**< record is a video in RGB format */
OGGPLAY_SHORTS_AUDIO = 1000, /**< audio record in short format */
OGGPLAY_FLOATS_AUDIO = 1001, /**< audio record in float format */
OGGPLAY_CMML = 2000, /**< CMML record */
OGGPLAY_KATE = 3000, /**< KATE record */
OGGPLAY_TYPE_UNKNOWN = 9000 /**< content type of the record is unknown */
} OggPlayDataType;
/**
* Definitions of the various states of a stream.
*/
typedef enum OggPlayStreamInfo {
OGGPLAY_STREAM_UNINITIALISED = 0, /**< Stream is not initialised */
OGGPLAY_STREAM_FIRST_DATA = 1, /**< Stream received it's first data frame */
OGGPLAY_STREAM_INITIALISED = 2, /**< Stream is initialised */
OGGPLAY_STREAM_LAST_DATA = 3, /**< Stream received it's last data frame */
OGGPLAY_STREAM_JUST_SEEKED = 4 /**< We've just seeked in the stream */
} OggPlayStreamInfo;
#endif

Просмотреть файл

@ -1,116 +0,0 @@
/*
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.
*/
/** @file
* oggplay_query.h
*
* @authors
* Shane Stephens <shane.stephens@annodex.net>
* Viktor Gal
*/
#ifndef __OGGPLAY_QUERY_H__
#define __OGGPLAY_QUERY_H__
#include <oggz/oggz.h>
/**
* Get the number of tracks in the Ogg container.
*
* @param me OggPlay handle
* @retval "> 0" number of tracks
* @retval E_OGGPLAY_BAD_OGGPLAY the supplied OggPlay
* @retval E_OGGPLAY_BAD_READER
* @retval E_OGGPLAY_UNINITIALISED the is not initialised.
*/
int
oggplay_get_num_tracks (OggPlay * me);
/**
* Retrieve the type of a track.
*
* @param me OggPlay handle
* @param track_num the desired track's number
* @retval "> 0" the track's type (see OggzStreamContent)
* @retval "< 0" error occured
*/
OggzStreamContent
oggplay_get_track_type (OggPlay * me, int track_num);
/**
* Get a track's type name.
*
* @param me OggPlay handle
* @param track_num the desired track's number
* @retval typa name of the track
* @retval NULL in case of error.
*/
const char *
oggplay_get_track_typename (OggPlay * me, int track_num);
/**
* Set a track active.
*
* @param me OggPlay handle
* @param track_num the desired track's number for activation
* @retval E_OGGPLAY_OK on success
* @retval E_OGGPLAY_BAD_OGGPLAY the supplied OggPlay is invalid
* @retval E_OGGPLAY_BAD_READER the OggPlayReader associated with the Ogg
* container is invalid
* @retval E_OGGPLAY_UNINITIALISED the tracks are not initialised
* @retval E_OGGPLAY_BAD_TRACK invalid track number
* @retval E_OGGPLAY_TRACK_IS_SKELETON the chosen track is a Skeleton track
* @retval E_OGGPLAY_TRACK_IS_UNKNOWN the chosen track's content type is unknown
* @retval E_OGGPLAY_TRACK_UNINITIALISED the chosen track was not initialised
* @retval E_OGGPLAY_TRACK_IS_OVER the track is over.
*/
OggPlayErrorCode
oggplay_set_track_active(OggPlay *me, int track_num);
/**
* Inactivate a given track.
*
* @param me OggPlay handle
* @param track_num the desired track's number for inactivation
* @retval E_OGGPLAY_OK on success
* @retval E_OGGPLAY_BAD_OGGPLAY the supplied OggPlay is invalid
* @retval E_OGGPLAY_BAD_READER the OggPlayReader associated with the Ogg
* container is invalid
* @retval E_OGGPLAY_UNINITIALISED the tracks are not initialised
* @retval E_OGGPLAY_BAD_TRACK invalid track number
* @retval E_OGGPLAY_TRACK_IS_SKELETON the chosen track is a Skeleton track
* @retval E_OGGPLAY_TRACK_IS_UNKNOWN the chosen track's content type is unknown
*/
OggPlayErrorCode
oggplay_set_track_inactive(OggPlay *me, int track_num);
#endif

Просмотреть файл

@ -1,90 +0,0 @@
/*
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.
*/
/** @file
* oggplay_reader.h
*
* @authors
* 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);
ogg_int64_t (*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;
/**
* Create and initialise an OggPlayReader for a given Ogg file.
*
* @param filename The file to open
* @return A new OggPlayReader handle
* @retval NULL if error occured.
*/
OggPlayReader *
oggplay_file_reader_new(const char *filename);
/**
* Create and initialise an OggPlayReader for an Ogg content at a given URI.
*
* @param uri The URI to the Ogg file.
* @param proxy Proxy
* @param proxy_port Proxy port.
* @return A new OggPlayReader handle
* @retval NULL on error.
*/
OggPlayReader *
oggplay_tcp_reader_new(const char *uri, const char *proxy, int proxy_port);
#endif

Просмотреть файл

@ -1,65 +0,0 @@
/*
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.
*/
/** @file
* oggplay_seek.h
*
* @authors
* Shane Stephens <shane.stephens@annodex.net>
*/
#ifndef __OGGPLAY_SEEK_H__
#define __OGGPLAY_SEEK_H__
/**
* Seeks to a requested position.
*
* @param me OggPlay handle associated with the stream
* @param milliseconds
* @retval E_OGGPLAY_OK on success
* @retval E_OGGPLAY_BAD_OGGPLAY the supplied OggPlay handle was invalid
* @retval E_OGGPLAY_CANT_SEEK error occured while trying to seek
* @retval E_OGGPLAY_OUT_OF_MEMORY ran out of memory while trying to allocate the new buffer and trash.
*/
OggPlayErrorCode
oggplay_seek(OggPlay *me, ogg_int64_t milliseconds);
/**
* Seeks to key frame before |milliseconds|.
*/
OggPlayErrorCode
oggplay_seek_to_keyframe(OggPlay *me,
ogg_int64_t milliseconds,
ogg_int64_t offset_begin,
ogg_int64_t offset_end);
#endif

Просмотреть файл

@ -1,96 +0,0 @@
/*
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.
*/
/** @file
* oggplay_tools.h
*
* @authors
* 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; /**< Y channel */
unsigned char * ptru; /**< U channel */
unsigned char * ptrv; /**< V channel*/
int y_width; /**< the width of the Y plane */
int y_height; /**< the height of the Y plane */
int uv_width; /**< the width of the U/V plane */
int uv_height; /**< the height of the U/V plane*/
} OggPlayYUVChannels;
/** structure holds pointers to RGB packets */
typedef struct _OggPlayRGBChannels {
unsigned char * ptro; /**< the RGB stream in the requested packaging format */
int rgb_width; /**< width of the RGB frame */
int rgb_height; /**< height of the RGB frame */
} OggPlayRGBChannels;
void
oggplay_yuv2rgba(const OggPlayYUVChannels *yuv, OggPlayRGBChannels * rgb);
void
oggplay_yuv2bgra(const OggPlayYUVChannels* yuv, OggPlayRGBChannels * rgb);
void
oggplay_yuv2argb(const 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__*/

Просмотреть файл

@ -1,50 +0,0 @@
commit 199a8cea6c4fd6d765254e7a384ac9df21ee2656
Author: Viktor Gal <viktor.gal@maeth.com>
Date: Fri May 8 15:44:51 2009 +1000
In the commit of 34c82de a bug was introduced in 'oggplay_data_handle_audio_data' function:
the number of samples in the record was not the correct value! The value of it
was incorrectly the size of the samples in the record.
diff --git a/src/liboggplay/oggplay_data.c b/src/liboggplay/oggplay_data.c
index 4df5275..9376938 100644
--- a/src/liboggplay/oggplay_data.c
+++ b/src/liboggplay/oggplay_data.c
@@ -301,6 +301,7 @@ oggplay_data_handle_audio_data (OggPlayDecode *decode, void *data,
int num_channels, ret;
size_t record_size = sizeof(OggPlayAudioRecord);
+ long samples_size;
OggPlayAudioRecord * record = NULL;
num_channels = ((OggPlayAudioDecode *)decode)->sound_info.channels;
@@ -310,17 +311,17 @@ oggplay_data_handle_audio_data (OggPlayDecode *decode, void *data,
return E_OGGPLAY_TYPE_OVERFLOW;
}
- ret = oggplay_mul_signed_overflow (samples, num_channels, &samples);
+ ret = oggplay_mul_signed_overflow (samples, num_channels, &samples_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
- ret = oggplay_mul_signed_overflow (samples, samplesize, &samples);
+ ret = oggplay_mul_signed_overflow (samples_size, samplesize, &samples_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
- ret = oggplay_check_add_overflow (record_size, samples, &record_size);
+ ret = oggplay_check_add_overflow (record_size, samples_size, &record_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
@@ -339,7 +340,7 @@ oggplay_data_handle_audio_data (OggPlayDecode *decode, void *data,
record->data = (void *)(record + 1);
/* copy the received data - the header has been initialised! */
- memcpy (record->data, data, samples);
+ memcpy (record->data, data, samples_size);
/*
printf("[%f%f%f]\n", ((float *)record->data)[0], ((float *)record->data)[1],
((float *)record->data)[2]);

Просмотреть файл

@ -1,304 +0,0 @@
diff --git a/media/liboggplay/src/liboggplay/oggplay_private.h b/media/liboggplay/src/liboggplay/oggplay_private.h
--- a/media/liboggplay/src/liboggplay/oggplay_private.h
+++ b/media/liboggplay/src/liboggplay/oggplay_private.h
@@ -62,16 +62,22 @@
#ifdef WIN32
#ifdef HAVE_WINSOCK2
#include <winsock2.h>
#else
#include <winsock.h>
#endif
+#endif
+
+#ifdef OS2
+#define INCL_DOSSEMAPHORES
+#define INCL_DOSPROCESS
+#include <os2.h>
#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,
diff --git a/media/liboggplay/src/liboggplay/oggplay_tools.c b/media/liboggplay/src/liboggplay/oggplay_tools.c
--- a/media/liboggplay/src/liboggplay/oggplay_tools.c
+++ b/media/liboggplay/src/liboggplay/oggplay_tools.c
@@ -53,15 +53,17 @@ oggplay_sys_time_in_ms(void) {
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);
+#elif defined(OS2)
+ DosSleep(ms);
#else
struct timespec ts = {0, (ogg_int64_t)ms * 1000000LL};
nanosleep(&ts, NULL);
#endif
}
diff --git a/media/liboggplay/src/liboggplay/os2_semaphore.c b/media/liboggplay/src/liboggplay/os2_semaphore.c
new file mode 100644
--- /dev/null
+++ b/media/liboggplay/src/liboggplay/os2_semaphore.c
@@ -0,0 +1,163 @@
+/* ***** 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 the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Richard Walsh
+ * Portions created by the Initial Developer are Copyright (c) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 ***** *
+ */
+/*****************************************************************************/
+/*
+ * This is a conservative implementation of a posix counting semaphore.
+ * It relies on the state of the underlying OS/2 event semaphore to
+ * control whether sem_wait() blocks or returns immediately, and only
+ * uses its count to change the sem's state from posted to reset.
+ * (A more "activist" approach would use the count to decide whether
+ * to return immediately or to call DosWaitEventSem().)
+ *
+ */
+/*****************************************************************************/
+
+#include <stdlib.h>
+#define INCL_DOS
+#include <os2.h>
+#include "os2_semaphore.h"
+
+#ifndef ERROR_SEM_BUSY
+#define ERROR_SEM_BUSY 301
+#endif
+
+#define SEM_WAIT 20000
+
+/*****************************************************************************/
+
+int sem_init(sem_t *sem, int pshared, unsigned value)
+{
+ OS2SEM * psem;
+
+ if (!sem)
+ return -1;
+ *sem = 0;
+
+ psem = (OS2SEM*)malloc(sizeof(OS2SEM));
+ if (!psem)
+ return -1;
+
+ if (DosCreateMutexSem(0, &psem->hmtx, 0, 0)) {
+ free(psem);
+ return -1;
+ }
+
+ if (DosCreateEventSem(0, &psem->hev, 0, (value ? 1 : 0))) {
+ DosCloseMutexSem(psem->hmtx);
+ free(psem);
+ return -1;
+ }
+
+ psem->cnt = value;
+ *sem = psem;
+ return 0;
+}
+
+/*****************************************************************************/
+
+int sem_wait(sem_t *sem)
+{
+ OS2SEM * psem;
+ ULONG cnt;
+
+ if (!sem || !*sem)
+ return -1;
+ psem = *sem;
+
+ if (DosWaitEventSem(psem->hev, -1))
+ return -1;
+
+ if (DosRequestMutexSem(psem->hmtx, SEM_WAIT))
+ return -1;
+
+ if (psem->cnt)
+ psem->cnt--;
+ if (!psem->cnt)
+ DosResetEventSem(psem->hev, &cnt);
+ DosReleaseMutexSem(psem->hmtx);
+
+ return 0;
+}
+
+/*****************************************************************************/
+
+int sem_post(sem_t *sem)
+{
+ OS2SEM * psem;
+
+ if (!sem || !*sem)
+ return -1;
+ psem = *sem;
+
+ if (!DosRequestMutexSem(psem->hmtx, SEM_WAIT)) {
+ psem->cnt++;
+ DosPostEventSem(psem->hev);
+ DosReleaseMutexSem(psem->hmtx);
+ return 0;
+ }
+
+ return -1;
+}
+
+/*****************************************************************************/
+
+int sem_destroy(sem_t *sem)
+{
+ OS2SEM * psem;
+
+ if (!sem || !*sem)
+ return -1;
+ psem = *sem;
+
+ if (DosCloseMutexSem(psem->hmtx) == ERROR_SEM_BUSY) {
+ DosRequestMutexSem(psem->hmtx, SEM_WAIT);
+ DosReleaseMutexSem(psem->hmtx);
+ DosCloseMutexSem(psem->hmtx);
+ }
+
+ if (DosCloseEventSem(psem->hev) == ERROR_SEM_BUSY) {
+ DosPostEventSem(psem->hev);
+ DosSleep(1);
+ DosCloseEventSem(psem->hev);
+ }
+
+ free(psem);
+ return 0;
+}
+
+/*****************************************************************************/
+
diff --git a/media/liboggplay/src/liboggplay/os2_semaphore.h b/media/liboggplay/src/liboggplay/os2_semaphore.h
new file mode 100644
--- /dev/null
+++ b/media/liboggplay/src/liboggplay/os2_semaphore.h
@@ -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 the Mozilla browser.
+ *
+ * The Initial Developer of the Original Code is
+ * Richard Walsh
+ * Portions created by the Initial Developer are Copyright (c) 2008
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * 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 _os2_semaphore_
+#define _os2_semaphore_
+
+typedef struct _OS2SEM {
+ HMTX hmtx;
+ HEV hev;
+ ULONG cnt;
+} OS2SEM;
+
+typedef OS2SEM * sem_t;
+
+int sem_init(sem_t *sem, int pshared, unsigned value);
+int sem_wait(sem_t *sem);
+int sem_post(sem_t *sem);
+int sem_destroy(sem_t *sem);
+
+#endif
+/*****************************************************************************/
+
diff --git a/media/liboggplay/src/liboggplay/std_semaphore.h b/media/liboggplay/src/liboggplay/std_semaphore.h
--- a/media/liboggplay/src/liboggplay/std_semaphore.h
+++ b/media/liboggplay/src/liboggplay/std_semaphore.h
@@ -83,16 +83,23 @@ typedef sem_t semaphore;
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_CLOSE(p) (!CloseHandle(p))
typedef HANDLE semaphore;
+#elif defined(OS2)
+#include "os2_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(__APPLE__)
#include <Carbon/Carbon.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

Просмотреть файл

@ -1,87 +0,0 @@
diff --git a/media/liboggplay/include/oggplay/oggplay_seek.h b/media/liboggplay/include/oggplay/oggplay_seek.h
--- a/media/liboggplay/include/oggplay/oggplay_seek.h
+++ b/media/liboggplay/include/oggplay/oggplay_seek.h
@@ -48,9 +48,20 @@
* @retval E_OGGPLAY_OK on success
* @retval E_OGGPLAY_BAD_OGGPLAY the supplied OggPlay handle was invalid
* @retval E_OGGPLAY_CANT_SEEK error occured while trying to seek
* @retval E_OGGPLAY_OUT_OF_MEMORY ran out of memory while trying to allocate the new buffer and trash.
*/
OggPlayErrorCode
oggplay_seek(OggPlay *me, ogg_int64_t milliseconds);
+/**
+ * Seeks to key frame before |milliseconds|.
+ */
+OggPlayErrorCode
+oggplay_seek_to_keyframe(OggPlay *me,
+ int* tracks,
+ int num_tracks,
+ ogg_int64_t milliseconds,
+ ogg_int64_t offset_begin,
+ ogg_int64_t offset_end);
+
#endif
diff --git a/media/liboggplay/src/liboggplay/oggplay_seek.c b/media/liboggplay/src/liboggplay/oggplay_seek.c
--- a/media/liboggplay/src/liboggplay/oggplay_seek.c
+++ b/media/liboggplay/src/liboggplay/oggplay_seek.c
@@ -183,8 +183,59 @@ oggplay_take_out_trash(OggPlay *me, OggP
}
p = trash;
}
if (p != NULL) {
oggplay_free(p);
}
}
+
+OggPlayErrorCode
+oggplay_seek_to_keyframe(OggPlay *me,
+ int* tracks,
+ int num_tracks,
+ ogg_int64_t milliseconds,
+ ogg_int64_t offset_begin,
+ ogg_int64_t offset_end)
+{
+ long *serial_nos;
+ int i;
+ ogg_int64_t eof, time;
+
+ if (me == NULL) {
+ return E_OGGPLAY_BAD_OGGPLAY;
+ }
+
+ if (num_tracks > me->num_tracks || milliseconds < 0)
+ return E_OGGPLAY_CANT_SEEK;
+
+ eof = oggplay_get_duration(me);
+ if (eof > -1 && milliseconds > eof) {
+ return E_OGGPLAY_CANT_SEEK;
+ }
+
+ // Get the serialnos for the tracks we're seeking.
+ serial_nos = (long*)oggplay_malloc(sizeof(long)*num_tracks);
+ if (!serial_nos) {
+ return E_OGGPLAY_CANT_SEEK;
+ }
+ for (i=0; i<num_tracks; i++) {
+ serial_nos[i] = me->decode_data[tracks[i]]->serialno;
+ }
+
+ time = oggz_keyframe_seek_set(me->oggz,
+ serial_nos,
+ num_tracks,
+ milliseconds,
+ offset_begin,
+ offset_end);
+ oggplay_free(serial_nos);
+
+ if (time == -1) {
+ return E_OGGPLAY_CANT_SEEK;
+ }
+
+ oggplay_seek_cleanup(me, time);
+
+ return E_OGGPLAY_OK;
+
+}

Просмотреть файл

@ -1,47 +0,0 @@
# ***** 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

Просмотреть файл

@ -1,81 +0,0 @@
# ***** 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
DEFINES += -DHAVE_CONFIG_H
MODULE = oggplay
LIBRARY_NAME = oggplay
FORCE_STATIC_LIB= 1
EXPORTS = \
oggplay_buffer.h \
oggplay_callback.h \
oggplay_data.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)
ifeq ($(OS_ARCH),OS2)
EXPORTS += \
os2_semaphore.h \
$(NULL)
CSRCS += \
os2_semaphore.c \
$(NULL)
endif
include $(topsrcdir)/config/rules.mk
LOCAL_INCLUDES += -I$(srcdir)/../../include/oggplay

Просмотреть файл

@ -1,115 +0,0 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Define if building universal (internal helper macro) */
/* #undef AC_APPLE_UNIVERSAL_BUILD */
/* Maximum supported data alignment */
/* Define to 1 if you have the `assert' function. */
/* #undef HAVE_ASSERT */
/* 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 if have libtiger */
/* #undef HAVE_TIGER */
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 1
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#define LT_OBJDIR ".libs/"
/* 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.2.0"
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
/* # undef WORDS_BIGENDIAN */
# endif
#endif
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
#undef HAVE_GLUT
#include "prcpucfg.h"
#ifdef IS_BIG_ENDIAN
#define WORDS_BIGENDIAN 1
#endif

Просмотреть файл

@ -1,284 +0,0 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2008 *
* by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
* *
********************************************************************
CPU capability detection for x86 processors.
Originally written by Rudolf Marek.
function:
last mod: $Id$
********************************************************************/
#include "cpu.h"
/* for detecting AltiVec support */
# if (defined(__ppc__) || defined(__ppc64__))
# if defined(__APPLE__) || defined(__MACOSX__)
#include <sys/sysctl.h>
# else
#include <signal.h>
#include <setjmp.h>
# endif
# endif
# if (defined(__ppc__) || defined(__ppc64__)) && !(defined(__APPLE__) || defined(__MACOSX__))
static jmp_buf jmpbuf;
static void illegal_instruction(int sig)
{
longjmp(jmpbuf, 1);
}
# endif
#if defined(i386) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64)
# if !defined(_MSC_VER)
# if defined(__amd64__)||defined(__x86_64__)
/*On x86-64, gcc seems to be able to figure out how to save %rbx for us when
compiling with -fPIC.*/
# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
__asm__ __volatile__( \
"cpuid\n\t" \
:[eax]"=a"(_eax),[ebx]"=b"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
:"a"(_op) \
:"cc" \
)
# else
/*On x86-32, not so much.*/
# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
__asm__ __volatile__( \
"xchgl %%ebx,%[ebx]\n\t" \
"cpuid\n\t" \
"xchgl %%ebx,%[ebx]\n\t" \
:[eax]"=a"(_eax),[ebx]"=r"(_ebx),[ecx]"=c"(_ecx),[edx]"=d"(_edx) \
:"a"(_op) \
:"cc" \
)
# endif
# else
# if defined(_M_IX86)
/*Why does MSVC need this complicated rigamarole?
At this point I honestly do not care.*/
/*Visual C cpuid helper function.
For VS2005 we could as well use the _cpuid builtin, but that wouldn't work
for VS2003 users, so we do it in inline assembler.*/
static void oc_cpuid_helper(ogg_uint32_t _cpu_info[4],ogg_uint32_t _op){
_asm {
mov eax,[_op]
mov esi,_cpu_info
cpuid
mov [esi+0],eax
mov [esi+4],ebx
mov [esi+8],ecx
mov [esi+12],edx
}
}
# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
do{ \
ogg_uint32_t cpu_info[4]; \
oc_cpuid_helper(cpu_info,_op); \
(_eax)=cpu_info[0]; \
(_ebx)=cpu_info[1]; \
(_ecx)=cpu_info[2]; \
(_edx)=cpu_info[3]; \
}while(0)
static void oc_detect_cpuid_helper(ogg_uint32_t *_eax,ogg_uint32_t *_ebx){
_asm{
pushfd
pushfd
pop eax
mov ebx,eax
xor eax,200000h
push eax
popfd
pushfd
pop eax
popfd
mov ecx,_eax
mov [ecx],eax
mov ecx,_ebx
mov [ecx],ebx
}
}
# elif defined(_M_AMD64)
# include <intrin.h>
# define cpuid(_op,_eax,_ebx,_ecx,_edx) \
do{ \
int cpu_info[4]; \
__cpuid(cpu_info,_op); \
(_eax)=cpu_info[0]; \
(_ebx)=cpu_info[1]; \
(_ecx)=cpu_info[2]; \
(_edx)=cpu_info[3]; \
}while(0)
# endif
# endif
#endif /* x86-only cpuid */
static ogg_uint32_t oc_parse_intel_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
ogg_uint32_t flags;
/*If there isn't even MMX, give up.*/
if(!(_edx&0x00800000))return 0;
flags=OC_CPU_X86_MMX;
if(_edx&0x02000000)flags|=OC_CPU_X86_MMXEXT|OC_CPU_X86_SSE;
if(_edx&0x04000000)flags|=OC_CPU_X86_SSE2;
if(_ecx&0x00000001)flags|=OC_CPU_X86_PNI;
if(_ecx&0x00000100)flags|=OC_CPU_X86_SSSE3;
if(_ecx&0x00080000)flags|=OC_CPU_X86_SSE4_1;
if(_ecx&0x00100000)flags|=OC_CPU_X86_SSE4_2;
return flags;
}
static ogg_uint32_t oc_parse_amd_flags(ogg_uint32_t _edx,ogg_uint32_t _ecx){
ogg_uint32_t flags;
/*If there isn't even MMX, give up.*/
if(!(_edx&0x00800000))return 0;
flags=OC_CPU_X86_MMX;
if(_edx&0x00400000)flags|=OC_CPU_X86_MMXEXT;
if(_edx&0x80000000)flags|=OC_CPU_X86_3DNOW;
if(_edx&0x40000000)flags|=OC_CPU_X86_3DNOWEXT;
if(_ecx&0x00000040)flags|=OC_CPU_X86_SSE4A;
if(_ecx&0x00000800)flags|=OC_CPU_X86_SSE5;
return flags;
}
static ogg_uint32_t oc_cpu_flags_get(void){
ogg_uint32_t flags = 0;
# if defined(__ppc__) || defined(__ppc64__)
/* detect AltiVec extension if compiling it for ppc */
# if defined(__APPLE__) || defined(__MACOSX__) || defined(__DARWIN__)
int selectors[2] = { CTL_HW, HW_VECTORUNIT };
int i_has_altivec = 0;
size_t i_length = sizeof( i_has_altivec );
int i_error = sysctl( selectors, 2, &i_has_altivec, &i_length, NULL, 0);
if( i_error == 0 && i_has_altivec != 0 )
flags |= OC_CPU_PPC_ALTIVEC;
# else
void (*handler) (int sig);
handler = signal(SIGILL, illegal_instruction);
if (setjmp(jmpbuf) == 0)
{
__asm__ __volatile__ (
"mtspr 256, %0\n\t"
"vand %%v0, %%v0, %%v0"
: : "r"(-1) );
flags |= OC_CPU_PPC_ALTIVEC;
}
signal(SIGILL, handler);
# endif
/* detect x86 CPU extensions */
# elif defined(i386) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64)
ogg_uint32_t eax;
ogg_uint32_t ebx;
ogg_uint32_t ecx;
ogg_uint32_t edx;
# if !defined(__amd64__)&&!defined(__x86_64__)&&!defined(_M_AMD64)
/*Not all x86-32 chips support cpuid, so we have to check.*/
# if !defined(_MSC_VER)
__asm__ __volatile__(
"pushfl\n\t"
"pushfl\n\t"
"popl %[a]\n\t"
"movl %[a],%[b]\n\t"
"xorl $0x200000,%[a]\n\t"
"pushl %[a]\n\t"
"popfl\n\t"
"pushfl\n\t"
"popl %[a]\n\t"
"popfl\n\t"
:[a]"=r"(eax),[b]"=r"(ebx)
:
:"cc"
);
# else
oc_detect_cpuid_helper(&eax,&ebx);
# endif
/*No cpuid.*/
if(eax==ebx)return 0;
# endif
cpuid(0,eax,ebx,ecx,edx);
/* l e t n I e n i u n e G*/
if((ecx==0x6C65746E&&edx==0x49656E69&&ebx==0x756E6547)||
/* 6 8 x M T e n i u n e G*/
(ecx==0x3638784D&&edx==0x54656E69&&ebx==0x756E6547)) {
/*Intel, Transmeta (tested with Crusoe TM5800):*/
cpuid(1,eax,ebx,ecx,edx);
flags=oc_parse_intel_flags(edx,ecx);
}
/* D M A c i t n e h t u A*/
else if((ecx==0x444D4163&&edx==0x69746E65&&ebx==0x68747541)||
/* C S N y b e d o e G*/
(ecx==0x43534E20&&edx==0x79622065&&ebx==0x646F6547)){
/*AMD, Geode:*/
cpuid(0x80000000,eax,ebx,ecx,edx);
if(eax<0x80000001)flags=0;
else{
cpuid(0x80000001,eax,ebx,ecx,edx);
flags=oc_parse_amd_flags(edx,ecx);
}
/*Also check for SSE.*/
cpuid(1,eax,ebx,ecx,edx);
flags|=oc_parse_intel_flags(edx,ecx);
}
/*Technically some VIA chips can be configured in the BIOS to return any
string here the user wants.
There is a special detection method that can be used to identify such
processors, but in my opinion, if the user really wants to change it, they
deserve what they get.*/
/* s l u a H r u a t n e C*/
else if(ecx==0x736C7561&&edx==0x48727561&&ebx==0x746E6543){
/*VIA:*/
/*I only have documentation for the C7 (Esther) and Isaiah (forthcoming)
chips (thanks to the engineers from Centaur Technology who provided it).
These chips support Intel-like cpuid info.
The C3-2 (Nehemiah) cores appear to, as well.*/
cpuid(1,eax,ebx,ecx,edx);
flags=oc_parse_intel_flags(edx,ecx);
cpuid(0x80000000,eax,ebx,ecx,edx);
if(eax>=0x80000001){
/*The (non-Nehemiah) C3 processors support AMD-like cpuid info.
We need to check this even if the Intel test succeeds to pick up 3DNow!
support on these processors.
Unlike actual AMD processors, we cannot _rely_ on this info, since
some cores (e.g., the 693 stepping of the Nehemiah) claim to support
this function, yet return edx=0, despite the Intel test indicating
MMX support.
Therefore the features detected here are strictly added to those
detected by the Intel test.*/
/*TODO: How about earlier chips?*/
cpuid(0x80000001,eax,ebx,ecx,edx);
/*Note: As of the C7, this function returns Intel-style extended feature
flags, not AMD-style.
Currently, this only defines bits 11, 20, and 29 (0x20100800), which
do not conflict with any of the AMD flags we inspect.
For the remaining bits, Intel tells us, "Do not count on their value",
but VIA assures us that they will all be zero (at least on the C7 and
Isaiah chips).
In the (unlikely) event a future processor uses bits 18, 19, 30, or 31
(0xC0C00000) for something else, we will have to add code to detect
the model to decide when it is appropriate to inspect them.*/
flags|=oc_parse_amd_flags(edx,ecx);
}
}
else{
/*Implement me.*/
flags=0;
}
# else
/* not x86 or ppc */
# endif
return flags;
}

Просмотреть файл

@ -1,34 +0,0 @@
/********************************************************************
* *
* THIS FILE IS PART OF THE OggTheora SOFTWARE CODEC SOURCE CODE. *
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
* THE Theora SOURCE CODE IS COPYRIGHT (C) 2002-2007 *
* by the Xiph.Org Foundation and contributors http://www.xiph.org/ *
* *
********************************************************************
function:
last mod: $Id$
********************************************************************/
#ifndef __CPU_H__
#define __CPU_H__
#define OC_CPU_X86_MMX (1<<0)
#define OC_CPU_X86_3DNOW (1<<1)
#define OC_CPU_X86_3DNOWEXT (1<<2)
#define OC_CPU_X86_MMXEXT (1<<3)
#define OC_CPU_X86_SSE (1<<4)
#define OC_CPU_X86_SSE2 (1<<5)
#define OC_CPU_X86_PNI (1<<6)
#define OC_CPU_X86_SSSE3 (1<<7)
#define OC_CPU_X86_SSE4_1 (1<<8)
#define OC_CPU_X86_SSE4_2 (1<<9)
#define OC_CPU_X86_SSE4A (1<<10)
#define OC_CPU_X86_SSE5 (1<<11)
#define OC_CPU_PPC_ALTIVEC (1<<12)
#endif

Просмотреть файл

@ -1,982 +0,0 @@
/*
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 = NULL;
/* check whether the reader is valid. */
if (reader == NULL)
return NULL;
me = (OggPlay *)oggplay_malloc (sizeof(OggPlay));
if (me == NULL)
return NULL;
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;
me->duration = -1;
me->max_video_frame_pixels = OGGPLAY_TYPE_MAX_SIGNED(int);
return me;
}
OggPlayErrorCode
oggplay_initialise(OggPlay *me, int block) {
OggPlayErrorCode return_val;
int i;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
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);
if (me->oggz == NULL)
return E_OGGPLAY_OGGZ_UNHAPPY;
if (oggz_io_set_read(me->oggz, me->reader->io_read, me->reader) != 0)
return E_OGGPLAY_OGGZ_UNHAPPY;
if (oggz_io_set_seek(me->oggz, me->reader->io_seek, me->reader) != 0)
return E_OGGPLAY_OGGZ_UNHAPPY;
if (oggz_io_set_tell(me->oggz, me->reader->io_tell, me->reader) != 0)
return E_OGGPLAY_OGGZ_UNHAPPY;
if (oggz_set_read_callback(me->oggz, -1, oggplay_callback_predetected, me))
return E_OGGPLAY_OGGZ_UNHAPPY;
while (1) {
i = oggz_read (me->oggz, OGGZ_READ_CHUNK_SIZE);
switch (i) {
case 0:
/*
* EOF reached while processing headers,
* possible erroneous file, mark it as such.
*/
case OGGZ_ERR_HOLE_IN_DATA:
/* there was a whole in the data */
return E_OGGPLAY_BAD_INPUT;
case OGGZ_ERR_OUT_OF_MEMORY:
/* ran out of memory during decoding! */
return E_OGGPLAY_OUT_OF_MEMORY;
case OGGZ_ERR_STOP_ERR:
/* */
return E_OGGPLAY_BAD_OGGPLAY;
default:
/* If the read otherwise failed, bail out. */
if (i < 0)
return E_OGGPLAY_BAD_INPUT;
break;
}
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;
}
me->active_tracks = 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 = NULL;
int r = E_OGGPLAY_TIMEOUT;
if ((me = oggplay_new_with_reader(reader)) == NULL)
return NULL;
while (r == E_OGGPLAY_TIMEOUT) {
r = oggplay_initialise(me, 0);
}
if (r != E_OGGPLAY_OK) {
/* in case of error close the OggPlay handle */
oggplay_close(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_callback_period(OggPlay *me, int track, int milliseconds) {
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (track < 0 || track >= me->num_tracks) {
return E_OGGPLAY_BAD_TRACK;
}
me->callback_period = OGGPLAY_TIME_INT_TO_FP(((ogg_int64_t)milliseconds))/1000;
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 = OGGPLAY_TIME_INT_TO_FP(offset) / 1000;
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_aspect_ratio(OggPlay *me, int track, int* aspect_denom, int* aspect_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.aspect_denominator == 0)
|| (decode->video_info.aspect_numerator == 0)) {
return E_OGGPLAY_UNINITIALISED;
}
(*aspect_denom) = decode->video_info.aspect_denominator;
(*aspect_num) = decode->video_info.aspect_numerator;
return E_OGGPLAY_OK;
}
OggPlayErrorCode
oggplay_convert_video_to_rgb(OggPlay *me, int track, int convert, int swap_rgb) {
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]->content_type != OGGZ_CONTENT_THEORA) {
return E_OGGPLAY_WRONG_TRACK_TYPE;
}
decode = (OggPlayTheoraDecode *)(me->decode_data[track]);
if (decode->convert_to_rgb != convert || decode->swap_rgb != swap_rgb) {
decode->convert_to_rgb = convert;
decode->swap_rgb = swap_rgb;
me->decode_data[track]->decoded_type = convert ? OGGPLAY_RGBA_VIDEO : OGGPLAY_YUV_VIDEO;
/* flush any records created with previous type */
oggplay_data_free_list(me->decode_data[track]->data_list);
me->decode_data[track]->data_list = NULL;
}
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;
}
OggPlayErrorCode
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;
}
OggPlayErrorCode
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;
}
OggPlayErrorCode
oggplay_get_kate_category(OggPlay *me, int track, const char** category) {
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]->content_type != OGGZ_CONTENT_KATE) {
return E_OGGPLAY_WRONG_TRACK_TYPE;
}
decode = (OggPlayKateDecode *)(me->decode_data[track]);
#ifdef HAVE_KATE
if (decode->decoder.initialised) {
(*category) = decode->k_state.ki->category;
return E_OGGPLAY_OK;
}
else return E_OGGPLAY_UNINITIALISED;
#else
return E_OGGPLAY_NO_KATE_SUPPORT;
#endif
}
OggPlayErrorCode
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]->content_type != OGGZ_CONTENT_KATE) {
return E_OGGPLAY_WRONG_TRACK_TYPE;
}
decode = (OggPlayKateDecode *)(me->decode_data[track]);
#ifdef HAVE_KATE
if (decode->decoder.initialised) {
(*language) = decode->k_state.ki->language;
return E_OGGPLAY_OK;
}
else return E_OGGPLAY_UNINITIALISED;
#else
return E_OGGPLAY_NO_KATE_SUPPORT;
#endif
}
OggPlayErrorCode
oggplay_set_kate_tiger_rendering(OggPlay *me, int track, int use_tiger, int swap_rgb, int default_width, int default_height) {
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]->content_type != OGGZ_CONTENT_KATE) {
return E_OGGPLAY_WRONG_TRACK_TYPE;
}
decode = (OggPlayKateDecode *)(me->decode_data[track]);
#ifdef HAVE_KATE
#ifdef HAVE_TIGER
if (decode->decoder.initialised && decode->tr) {
decode->use_tiger = use_tiger;
decode->swap_rgb = swap_rgb;
decode->default_width = default_width;
decode->default_height = default_height;
decode->decoder.decoded_type = use_tiger ? OGGPLAY_RGBA_VIDEO : OGGPLAY_KATE;
return E_OGGPLAY_OK;
}
else return E_OGGPLAY_UNINITIALISED;
#else
return E_OGGPLAY_NO_TIGER_SUPPORT;
#endif
#else
return E_OGGPLAY_NO_KATE_SUPPORT;
#endif
}
OggPlayErrorCode
oggplay_overlay_kate_track_on_video(OggPlay *me, int kate_track, int video_track) {
OggPlayKateDecode * decode;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (kate_track < 0 || kate_track >= me->num_tracks) {
return E_OGGPLAY_BAD_TRACK;
}
if (video_track < 0 || video_track >= me->num_tracks) {
return E_OGGPLAY_BAD_TRACK;
}
if (me->decode_data[kate_track]->content_type != OGGZ_CONTENT_KATE) {
return E_OGGPLAY_WRONG_TRACK_TYPE;
}
if (me->decode_data[kate_track]->decoded_type != OGGPLAY_RGBA_VIDEO) {
return E_OGGPLAY_WRONG_TRACK_TYPE;
}
if (me->decode_data[video_track]->content_type != OGGZ_CONTENT_THEORA) {
return E_OGGPLAY_WRONG_TRACK_TYPE;
}
if (me->decode_data[video_track]->decoded_type != OGGPLAY_RGBA_VIDEO) {
return E_OGGPLAY_WRONG_TRACK_TYPE;
}
decode = (OggPlayKateDecode *)(me->decode_data[kate_track]);
#ifdef HAVE_KATE
#ifdef HAVE_TIGER
decode->overlay_dest = video_track;
return E_OGGPLAY_OK;
#else
return E_OGGPLAY_NO_TIGER_SUPPORT;
#endif
#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;
int read_data = 0;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
/*
* check whether the OggPlayDataCallback is set for the given
* OggPlay handle. If not return with error as there's no callback
* function processing the decoded data.
*/
if (me->callback == NULL) {
return E_OGGPLAY_UNINITIALISED;
}
/*
* 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 == 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 && !read_data) {
/*
* There's no more data to read, and we've not read any that needs
* to be sent to the buffer list via a callback, so exit.
*/
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;
if (me->decode_data[i]->content_type == OGGZ_CONTENT_KATE)
continue;
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);
switch (r) {
case 0:
/* end-of-file */
num_records = oggplay_callback_info_prepare(me, &info);
/*
* set all of the tracks to inactive
*/
for (i = 0; i < me->num_tracks; i++) {
me->decode_data[i]->active = 0;
}
me->active_tracks = 0;
if (info != NULL) {
/* ensure all tracks have their final data packet set to end_of_stream */
OggPlayCallbackInfo *p = info[0];
for (i = 0; i < me->num_tracks; i++) {
p->stream_info = OGGPLAY_STREAM_LAST_DATA;
p++;
}
me->callback (me, num_records, info, me->callback_user_ptr);
oggplay_callback_info_destroy(me, info);
}
/* we reached the end of the stream */
return E_OGGPLAY_OK;
case OGGZ_ERR_HOLE_IN_DATA:
/* there was a whole in the data */
return E_OGGPLAY_BAD_INPUT;
case OGGZ_ERR_STOP_ERR:
/*
* one of the callback functions requested us to stop.
* as this currently happens only when one of the
* OggzReadPacket callback functions does not receive
* the user provided data, i.e. the OggPlayDecode struct
* for the track mark it as a memory problem, since this
* could happen only if something is wrong with the memory,
* e.g. some buffer overflow.
*/
case OGGZ_ERR_OUT_OF_MEMORY:
/* ran out of memory during decoding! */
return E_OGGPLAY_OUT_OF_MEMORY;
default:
/*
* We read some data. Set a flag so that we're guaranteed to try to
* send it to the buffer list via a callback.
*/
read_data = 1;
break;
}
}
/*
* 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]);
}
/*
* there was an error during info prepare!
* abort decoding!
*/
if (num_records < 0) {
return num_records;
}
/* if we received an shutdown event, dont try to read more data...*/
if (me->shutdown) {
return E_OGGPLAY_OK;
}
/* we require more data for decoding */
if (info == NULL) {
goto read_more_data;
}
me->target += me->callback_period;
if (r == -1) {
return E_OGGPLAY_USER_INTERRUPT;
}
return E_OGGPLAY_CONTINUE;
}
OggPlayErrorCode
oggplay_start_decoding(OggPlay *me) {
int r;
while (1) {
r = oggplay_step_decoding(me);
if (r == E_OGGPLAY_CONTINUE || r == E_OGGPLAY_TIMEOUT) {
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);
}
/* */
if (me->decode_data != NULL) {
for (i = 0; i < me->num_tracks; i++) {
oggplay_callback_shutdown(me->decode_data[i]);
}
}
if (me->oggz)
oggz_close(me->oggz);
if (me->buffer != NULL) {
oggplay_buffer_shutdown(me, me->buffer);
}
if (me->callback_info != NULL) {
oggplay_free(me->callback_info);
}
oggplay_free(me->decode_data);
oggplay_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);
}
ogg_int64_t
oggplay_get_duration(OggPlay *me) {
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
/* If the reader has a duration function we always call that
* function to find the duration. We never cache the result
* of that function.
*
* If there is no reader duration function we use our cached
* duration value, or do a liboggz seek to find it and cache
* that.
*/
if (me->reader->duration) {
ogg_int64_t d = me->reader->duration(me->reader);
if (d >= 0) {
me->duration = d;
}
}
if (me->duration < 0) {
ogg_int64_t pos;
pos = oggz_tell_units(me->oggz);
me->duration = oggz_seek_units(me->oggz, 0, SEEK_END);
oggz_seek_units(me->oggz, pos, SEEK_SET);
oggplay_seek_cleanup(me, pos);
}
return me->duration;
}
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);
}
int
oggplay_set_max_video_frame_pixels(OggPlay *player,
int max_frame_pixels) {
if (!player)
return E_OGGPLAY_BAD_OGGPLAY;
player->max_video_frame_pixels = max_frame_pixels;
return E_OGGPLAY_OK;
}

Просмотреть файл

@ -1,372 +0,0 @@
/*
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 = NULL;
if (size < 0) {
size = OGGPLAY_DEFAULT_BUFFER_SIZE;
}
buffer = (OggPlayBuffer*)oggplay_calloc(1, sizeof (OggPlayBuffer));
if (buffer == NULL)
return NULL;
buffer->buffer_list = oggplay_calloc(size, sizeof (void *));
if (buffer->buffer_list == NULL)
goto error;
buffer->buffer_mirror = oggplay_calloc(size, sizeof (void *));
if (buffer->buffer_mirror == NULL)
goto error;
buffer->buffer_size = size;
buffer->last_filled = -1;
buffer->last_emptied = -1;
if (SEM_CREATE(buffer->frame_sem, size) != 0)
goto error;
return buffer;
error:
if (buffer->buffer_list != NULL)
oggplay_free (buffer->buffer_list);
if (buffer->buffer_mirror != NULL)
oggplay_free (buffer->buffer_mirror);
oggplay_free (buffer);
return NULL;
}
void
oggplay_buffer_shutdown(OggPlay *me, volatile OggPlayBuffer *vbuffer) {
int i;
int j;
OggPlayBuffer *buffer = (OggPlayBuffer *)vbuffer;
if (buffer == NULL) {
return;
}
if (buffer->buffer_mirror != NULL) {
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++) {
if ( (ti+j) != NULL) {
oggplay_free((ti + j)->records);
}
}
oggplay_free(ti);
}
}
oggplay_free(buffer->buffer_mirror);
}
if (buffer->buffer_list != NULL)
oggplay_free(buffer->buffer_list);
SEM_CLOSE(buffer->frame_sem);
oggplay_free(buffer);
buffer = NULL;
}
int
oggplay_buffer_is_full(volatile OggPlayBuffer *buffer) {
return
(
(buffer == NULL) || (
buffer->buffer_list[WRAP_INC(buffer->last_filled, buffer->buffer_size)]
!=
NULL
)
);
}
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;
if (me == NULL)
return -1;
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
*/
if ((ti + i) != NULL) {
oggplay_free((ti + i)->records);
}
}
oggplay_free(ti);
buffer->buffer_mirror[k] = NULL;
}
}
/*
* replace the decode_data buffer for the next callback
*/
me->callback_info =
(OggPlayCallbackInfo *)oggplay_calloc(me->num_tracks, sizeof (OggPlayCallbackInfo));
if (me->callback_info == NULL)
return -1;
/*
* 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 = NULL;
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 = oggplay_calloc(me->num_tracks, sizeof (OggPlayCallbackInfo *));
if (return_val == NULL) {
return NULL;
}
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 = NULL;
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;
}
if (track_info != NULL) {
oggplay_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;
}
if( (me->buffer = oggplay_buffer_new_buffer(size)) == NULL)
return E_OGGPLAY_OUT_OF_MEMORY;
/*
* 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;
if (me == NULL)
return;
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;
}
}
}

Просмотреть файл

@ -1,61 +0,0 @@
/*
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__
/**
* Creates a new buffer with the given size.
*
* @param size The number of frames the buffer can store.
* @return A new OggPlayBuffer.
* @retval NULL in case of error.
*/
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);
#endif

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,70 +0,0 @@
/*
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);
/**
* Create and initialise an OggPlayDecode handle.
*
*
*
* @param me OggPlay
* @param content_type
* @param serialno
* @return A new OggPlayDecode handle
* @retval NULL in case of error.
*/
OggPlayDecode *
oggplay_initialise_decoder(OggPlay *me, int content_type, long 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

Просмотреть файл

@ -1,506 +0,0 @@
/*
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>
extern void _print_list(char *name, OggPlayDataHeader *p);
static void
clear_callback_info (OggPlay *me, OggPlayCallbackInfo ***info) {
int i;
for (i = 0; i < me->num_tracks; ++i) {
if (((*info)[i] != NULL) && ((*info)[i]->records != NULL)) {
oggplay_free ((*info)[i]->records);
}
}
oggplay_free (*info);
*info = NULL;
}
int
oggplay_callback_info_prepare(OggPlay *me, OggPlayCallbackInfo ***info) {
int i;
int tcount = 0;
int added_required_record = me->num_tracks;
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) = oggplay_calloc (me->num_tracks, sizeof (OggPlayCallbackInfo *));
if ((*info) == NULL)
return E_OGGPLAY_OUT_OF_MEMORY;
/*
* 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;
size_t count = 0;
OggPlayDataHeader * p;
OggPlayDataHeader * q = NULL;
(*info)[i] = track_info;
#ifdef HAVE_TIGER
/* not so nice to have this here, but the tiger_renderer needs updating regularly
* as some items may be animated, so would yield data without the stream actually
* receiving any packets.
* In addition, Kate streams can now be overlayed on top of a video, so this needs
* calling to render the overlay.
* FIXME: is this the best place to put this ? Might do too much work if the info
* is going to be destroyed ?
*/
if (track->content_type == OGGZ_CONTENT_KATE) {
OggPlayKateDecode *decode = (OggPlayKateDecode *)track;
OggPlayCallbackInfo * video_info = NULL;
if (decode->overlay_dest >= 0)
video_info = me->callback_info + decode->overlay_dest;
oggplay_data_update_tiger(decode, track->active, me->target, video_info);
}
#endif
/*
* 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;
added_required_record --;
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;
}
/* check for overflow */
if
(
oggplay_check_add_overflow (count, 1, &count)
==
E_OGGPLAY_TYPE_OVERFLOW
)
{
clear_callback_info (me, info);
return E_OGGPLAY_TYPE_OVERFLOW;
}
}
}
/*
* 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;
}
if ((count+1) < count) {
clear_callback_info (me, info);
return E_OGGPLAY_TYPE_OVERFLOW;
}
/* null-terminate the record list for the python interface */
track_info->records =
oggplay_calloc ((count+1), sizeof (OggPlayDataHeader *));
if (track_info->records == NULL) {
clear_callback_info (me, info);
return E_OGGPLAY_OUT_OF_MEMORY;
}
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) {
if (!p->has_been_presented) {
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
*/
// TODO: I don't think that pt_update_valid is necessary any more, as this will only
// trigger now if there's no data in *ANY* of the tracks. Hence the audio timeslice case
// doesn't apply.
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 --;
}
} /* end of for loop, that fills each track */
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)
oggplay_free((*info)[i]->records);
}
oggplay_free(*info);
(*info) = NULL;
}
if (tcount == 0) {
for (i = 0; i < me->num_tracks; i++) {
if ((*info)[i]->records != NULL)
oggplay_free((*info)[i]->records);
}
oggplay_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)
oggplay_free(p->records);
}
oggplay_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;
}
return OGGPLAY_TIME_FP_TO_INT(header->presentation_time);
}
OggPlayVideoData *
oggplay_callback_info_get_video_data(OggPlayDataHeader *header) {
if (header == NULL) {
return NULL;
}
return &((OggPlayVideoRecord *)header)->data;
}
OggPlayOverlayData *
oggplay_callback_info_get_overlay_data(OggPlayDataHeader *header) {
if (header == NULL) {
return NULL;
}
return &((OggPlayOverlayRecord *)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;
}

Просмотреть файл

@ -1,736 +0,0 @@
/*
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 "oggplay/oggplay_callback_info.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) {
if (decode == NULL) {
return;
}
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) {
if (decode == NULL) {
return;
}
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;
}
}
/*
* helper function to append data packets to front of data_list
*/
void
oggplay_data_add_to_list_front(OggPlayDecode *decode, OggPlayDataHeader *data) {
if (decode == NULL) {
return;
}
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]", OGGPLAY_TIME_FP_TO_INT (p->presentation_time), 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;
if ((decode == NULL) || (data == NULL)) {
return;
}
//_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 {
oggplay_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;
oggplay_free(p);
}
}
void
oggplay_data_shutdown_list (OggPlayDecode *decode) {
if (decode == NULL) {
return;
}
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;
OggPlayDataHeader * header = NULL;
OggPlayDataHeader * p = NULL;
if (decode == NULL) {
return;
}
header = decode->data_list;
target = decode->player->target;
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;
oggplay_free (header);
header = decode->data_list;
} else {
if (header->next == NULL)
decode->end_of_data_list = p;
p->next = header->next;
oggplay_free (header);
header = p->next;
}
} else {
p = header;
header = header->next;
}
}
}
void
oggplay_data_initialise_header (const OggPlayDecode *decode,
OggPlayDataHeader *header) {
if ((decode == NULL) || (header == NULL)) {
return;
}
/*
* 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;
}
OggPlayErrorCode
oggplay_data_handle_audio_data (OggPlayDecode *decode, void *data,
long samples, size_t samplesize) {
int num_channels, ret;
size_t record_size = sizeof(OggPlayAudioRecord);
long samples_size;
OggPlayAudioRecord * record = NULL;
num_channels = ((OggPlayAudioDecode *)decode)->sound_info.channels;
/* check for possible integer overflows....*/
if ((samples < 0) || (num_channels < 0)) {
return E_OGGPLAY_TYPE_OVERFLOW;
}
ret = oggplay_mul_signed_overflow (samples, num_channels, &samples_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
ret = oggplay_mul_signed_overflow (samples_size, samplesize, &samples_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
ret = oggplay_check_add_overflow (record_size, samples_size, &record_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
/* try to allocate the memory for the record */
record = (OggPlayAudioRecord*)oggplay_calloc(record_size, 1);
if (record == NULL) {
return E_OGGPLAY_OUT_OF_MEMORY;
}
/* initialise the header of OggPlayAudioRecord struct */
oggplay_data_initialise_header(decode, &(record->header));
record->header.samples_in_record = samples;
record->data = (void *)(record + 1);
/* copy the received data - the header has been initialised! */
memcpy (record->data, data, samples_size);
/*
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));
return E_OGGPLAY_CONTINUE;
}
OggPlayErrorCode
oggplay_data_handle_cmml_data(OggPlayDecode *decode,
unsigned char *data,
long size) {
OggPlayTextRecord * record = NULL;
size_t record_size = sizeof(OggPlayTextRecord);
/* Include extra byte for null terminating record data buffer */
record_size += 1;
if
(
oggplay_check_add_overflow (record_size, size, &record_size)
==
E_OGGPLAY_TYPE_OVERFLOW
)
{
return E_OGGPLAY_TYPE_OVERFLOW;
}
/* allocate the memory for the record */
record = (OggPlayTextRecord*)oggplay_calloc (record_size, 1);
if (record == NULL) {
return E_OGGPLAY_OUT_OF_MEMORY;
}
/* initialise the record's header */
oggplay_data_initialise_header(decode, &(record->header));
record->header.samples_in_record = 1;
record->data = (char *)(record + 1);
/* copy the data */
memcpy(record->data, data, size);
record->data[size] = '\0';
oggplay_data_add_to_list(decode, &(record->header));
return E_OGGPLAY_CONTINUE;
}
static int
get_uv_offset(OggPlayTheoraDecode *decode, yuv_buffer *buffer)
{
int xo=0, yo = 0;
if (decode->y_width != 0 &&
decode->uv_width != 0 &&
decode->y_width/decode->uv_width != 0) {
xo = (decode->video_info.offset_x/(decode->y_width/decode->uv_width));
}
if (decode->y_height != 0 &&
decode->uv_height != 0 &&
decode->y_height/decode->uv_height != 0) {
yo = (buffer->uv_stride)*(decode->video_info.offset_y/(decode->y_height/decode->uv_height));
}
return xo + yo;
}
int
oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
const yuv_buffer *buffer) {
size_t size = sizeof (OggPlayVideoRecord);
int i, ret;
long y_size, uv_size, y_offset, uv_offset;
unsigned char * p;
unsigned char * q;
unsigned char * p2;
unsigned char * q2;
OggPlayVideoRecord * record;
OggPlayVideoData * data;
/* check for possible integer overflows */
ret =
oggplay_mul_signed_overflow (buffer->y_height, buffer->y_stride, &y_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
ret =
oggplay_mul_signed_overflow (buffer->uv_height, buffer->uv_stride, &uv_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
ret = oggplay_mul_signed_overflow (uv_size, 2, &uv_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
if (buffer->y_stride < 0) {
y_size *= -1;
uv_size *= -1;
}
ret = oggplay_check_add_overflow (size, y_size, &size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
ret = oggplay_check_add_overflow (size, uv_size, &size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
/*
* 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*)oggplay_malloc (size);
if (record == NULL) {
return E_OGGPLAY_OUT_OF_MEMORY;
}
record->header.samples_in_record = 1;
data = &(record->data);
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)
*/
y_offset = (decode->video_info.offset_x&~1)
+ buffer->y_stride*(decode->video_info.offset_y&~1);
p = data->y;
q = buffer->y + y_offset;
for (i = 0; i < decode->y_height; i++) {
memcpy(p, q, decode->y_width);
p += decode->y_width;
q += buffer->y_stride;
}
uv_offset = get_uv_offset(decode, buffer);
p = data->u;
q = buffer->u + uv_offset;
p2 = data->v;
q2 = buffer->v + uv_offset;
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;
}
/* if we're to send RGB video, convert here */
if (decode->convert_to_rgb) {
OggPlayYUVChannels yuv;
OggPlayRGBChannels rgb;
OggPlayOverlayRecord * orecord;
OggPlayOverlayData * odata;
long overlay_size;
yuv.ptry = data->y;
yuv.ptru = data->u;
yuv.ptrv = data->v;
yuv.y_width = decode->y_width;
yuv.y_height = decode->y_height;
yuv.uv_width = decode->uv_width;
yuv.uv_height = decode->uv_height;
size = sizeof(OggPlayOverlayRecord);
/* check for possible integer oveflows */
ret = oggplay_mul_signed_overflow(decode->y_width, decode->y_height,
&overlay_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
ret = oggplay_mul_signed_overflow(overlay_size, 4, &overlay_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
ret = oggplay_check_add_overflow (size, overlay_size, &size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
/* allocate memory for the overlay record */
orecord = (OggPlayOverlayRecord*) oggplay_malloc (size);
if (orecord != NULL) {
oggplay_data_initialise_header((OggPlayDecode *)decode, &(orecord->header));
orecord->header.samples_in_record = 1;
odata = &(orecord->data);
rgb.ptro = (unsigned char*)(orecord+1);
rgb.rgb_width = yuv.y_width;
rgb.rgb_height = yuv.y_height;
if (!decode->swap_rgb) {
oggplay_yuv2bgra(&yuv, &rgb);
} else {
oggplay_yuv2rgba(&yuv, &rgb);
}
odata->rgb = rgb.ptro;
odata->rgba = NULL;
odata->width = rgb.rgb_width;
odata->height = rgb.rgb_height;
odata->stride = rgb.rgb_width*4;
oggplay_free(record);
oggplay_data_add_to_list((OggPlayDecode *)decode, &(orecord->header));
} else {
/* memory allocation failed! */
oggplay_free (record);
return E_OGGPLAY_OUT_OF_MEMORY;
}
}
else {
oggplay_data_initialise_header((OggPlayDecode *)decode, &(record->header));
oggplay_data_add_to_list((OggPlayDecode *)decode, &(record->header));
}
return E_OGGPLAY_CONTINUE;
}
#ifdef HAVE_KATE
OggPlayErrorCode
oggplay_data_handle_kate_data(OggPlayKateDecode *decode, const kate_event *ev) {
OggPlayTextRecord * record = NULL;
size_t rec_size = sizeof(OggPlayTextRecord);
if (decode == NULL) {
return -1;
}
#ifdef HAVE_TIGER
tiger_renderer_add_event(decode->tr, ev->ki, ev);
if (decode->use_tiger) {
/* if rendering with Tiger, we don't add an event, a synthetic one will be
generated each "tick" with an updated tracker state */
}
else
#endif
{
/* check for integer overflow */
if
(
oggplay_check_add_overflow (rec_size, ev->len0, &rec_size)
==
E_OGGPLAY_TYPE_OVERFLOW
)
{
return E_OGGPLAY_TYPE_OVERFLOW;
}
record = (OggPlayTextRecord*)oggplay_calloc (rec_size, 1);
if (!record) {
return E_OGGPLAY_OUT_OF_MEMORY;
}
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));
}
return E_OGGPLAY_CONTINUE;
}
#endif
#ifdef HAVE_TIGER
OggPlayErrorCode
oggplay_data_update_tiger(OggPlayKateDecode *decode, int active, ogg_int64_t presentation_time, OggPlayCallbackInfo *info) {
OggPlayOverlayRecord * record = NULL;
OggPlayOverlayData * data = NULL;
size_t size = sizeof (OggPlayOverlayRecord);
int track = active && decode->use_tiger;
int ret;
kate_float t = OGGPLAY_TIME_FP_TO_INT(presentation_time) / 1000.0f;
if (!decode->decoder.initialised) return -1;
if (track) {
if (info) {
if (info->required_records>0) {
OggPlayDataHeader *header = info->records[0];
data = (OggPlayOverlayData*)(header+1);
if (decode->tr && data->rgb) {
#if WORDS_BIGENDIAN || IS_BIG_ENDIAN
tiger_renderer_set_buffer(decode->tr, data->rgb, data->width, data->height, data->stride, 0);
#else
tiger_renderer_set_buffer(decode->tr, data->rgb, data->width, data->height, data->stride, 1);
#endif
}
else {
/* we're supposed to overlay on a frame, but the available frame has no RGB buffer */
/* fprintf(stderr,"no RGB buffer found for video frame\n"); */
return -1;
}
}
else {
/* we're supposed to overlay on a frame, but there is no frame available */
/* fprintf(stderr,"no video frame to overlay on\n"); */
return -1;
}
}
else {
// TODO: some way of knowing the size of the video we'll be drawing onto, if any
int width = decode->k_state.ki->original_canvas_width;
int height = decode->k_state.ki->original_canvas_height;
long overlay_size;
if (width <= 0 || height <= 0) {
/* some default resolution if we're not overlaying onto a video and the canvas size is unknown */
if (decode->default_width > 0 && decode->default_height > 0) {
width = decode->default_width;
height = decode->default_height;
}
else {
width = 640;
height = 480;
}
}
/* check for integer overflow */
ret = oggplay_mul_signed_overflow (width, height, &overlay_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return ret;
}
ret = oggplay_mul_signed_overflow (overlay_size, 4, &overlay_size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return E_OGGPLAY_TYPE_OVERFLOW;
}
ret = oggplay_check_add_overflow (size, overlay_size, &size);
if (ret == E_OGGPLAY_TYPE_OVERFLOW) {
return E_OGGPLAY_TYPE_OVERFLOW;
}
record = (OggPlayOverlayRecord*)oggplay_calloc (1, size);
if (!record)
return E_OGGPLAY_OUT_OF_MEMORY;
record->header.samples_in_record = 1;
data= &(record->data);
oggplay_data_initialise_header((OggPlayDecode *)decode, &(record->header));
data->rgba = (unsigned char*)(record+1);
data->rgb = NULL;
data->width = width;
data->height = height;
data->stride = width*4;
if (decode->tr && data->rgba) {
tiger_renderer_set_buffer(decode->tr, data->rgba, data->width, data->height, data->stride, decode->swap_rgb);
}
oggplay_data_add_to_list(&decode->decoder, &(record->header));
record->header.presentation_time=presentation_time;
}
}
if (decode->tr) {
tiger_renderer_update(decode->tr, t, track);
}
if (track) {
/* buffer was either calloced, so already cleared, or already filled with video, so no clearing */
if (decode->tr) {
tiger_renderer_render(decode->tr);
}
}
return E_OGGPLAY_CONTINUE;
}
#endif

Просмотреть файл

@ -1,77 +0,0 @@
/*
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);
OggPlayErrorCode
oggplay_data_handle_theora_frame (OggPlayTheoraDecode *decode,
const yuv_buffer *buffer);
OggPlayErrorCode
oggplay_data_handle_audio_data (OggPlayDecode *decode,
void *data, long samples, size_t samplesize);
OggPlayErrorCode
oggplay_data_handle_cmml_data(OggPlayDecode *decode,
unsigned char *data, long size);
#ifdef HAVE_KATE
OggPlayErrorCode
oggplay_data_handle_kate_data(OggPlayKateDecode *decode,
const kate_event *ev);
#endif
#ifdef HAVE_TIGER
OggPlayErrorCode
oggplay_data_update_tiger(OggPlayKateDecode *decode,
int active, ogg_int64_t presentation_time,
OggPlayCallbackInfo *info);
#endif
void
oggplay_data_clean_list (OggPlayDecode *decode);
void
oggplay_data_free_list(OggPlayDataHeader *list);
void
oggplay_data_shutdown_list (OggPlayDecode *decode);
#endif

Просмотреть файл

@ -1,185 +0,0 @@
/*
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, 0L, SEEK_END);
me->size = ftell(me->file);
fseek(me->file, 0L, SEEK_SET);
me->current_position = 0;
return E_OGGPLAY_OK;
}
OggPlayErrorCode
oggplay_file_reader_destroy(OggPlayReader * opr) {
OggPlayFileReader * me;
if (opr == NULL) {
return E_OGGPLAY_BAD_READER;
}
me = (OggPlayFileReader *)opr;
if (me->file != NULL) {
fclose(me->file);
}
oggplay_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;
if (me == NULL) {
return -1;
}
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;
if (me == NULL) {
return -1;
}
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;
if (me == NULL) {
return -1;
}
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;
if (me == NULL) {
return -1;
}
return ftell(me->file);
}
OggPlayReader *
oggplay_file_reader_new(const char *file_name) {
OggPlayFileReader * me = oggplay_malloc (sizeof (OggPlayFileReader));
if (me == NULL)
return NULL;
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.duration = 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;
me->functions.duration = NULL;
return (OggPlayReader *)me;
}

Просмотреть файл

@ -1,56 +0,0 @@
/*
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;
const char * file_name;
FILE * file;
long current_position;
long size;
} OggPlayFileReader;
#endif

Просмотреть файл

@ -1,458 +0,0 @@
/*
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 HAVE_CONFIG_H
#ifdef WIN32
#include "config_win32.h"
#else
#include <config.h>
#endif
#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 HAVE_TIGER
#include <tiger/tiger.h>
#endif
#ifdef WIN32
#ifdef HAVE_WINSOCK2
#include <winsock2.h>
#else
#include <winsock.h>
#endif
#endif
#ifdef OS2
#define INCL_DOSSEMAPHORES
#define INCL_DOSPROCESS
#include <os2.h>
#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;
OggPlayOverlayData data;
} OggPlayOverlayRecord;
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; /**< identifies the logical bit stream */
int content_type;
const char * content_type_name;
OggPlayDataType decoded_type; /**< type of the track @see OggPlayDataType */
ogg_int64_t granuleperiod;
ogg_int64_t last_granulepos; /**< last seen granule position */
ogg_int64_t offset; /**< */
ogg_int64_t current_loc; /**< current location in the stream (in ) */
int active; /**< indicates whether the track is active or not */
ogg_int64_t final_granulepos; /**< */
struct _OggPlay * player; /**< reference to the OggPlay handle */
OggPlayDataHeader * data_list;
OggPlayDataHeader * end_of_data_list;
OggPlayDataHeader * untimed_data_list;
OggPlayStreamInfo stream_info; /**< @see OggPlayStreamInfo */
int preroll; /**< num. of past content packets to take into account when decoding the current Ogg page */
short initialised; /**< */
int num_header_packets; /**< number of header packets left to process for the stream.*/
} OggPlayDecode;
typedef struct {
OggPlayDecode decoder;
theora_state video_handle;
theora_info video_info;
theora_comment video_comment;
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;
int convert_to_rgb;
int swap_rgb;
} OggPlayTheoraDecode;
typedef struct {
OggPlayDecode decoder;
FishSound * sound_handle;
FishSoundInfo sound_info;
} OggPlayAudioDecode;
typedef struct {
OggPlayDecode decoder;
int granuleshift;
} OggPlayCmmlDecode;
/**
* OggPlaySkeletonDecode
*/
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_state;
kate_info k_info;
kate_comment k_comment;
int init;
#ifdef HAVE_TIGER
int use_tiger;
int overlay_dest;
tiger_renderer *tr;
int default_width;
int default_height;
int swap_rgb;
#endif
#endif
} OggPlayKateDecode;
struct OggPlaySeekTrash;
/**
*
*/
typedef struct OggPlaySeekTrash {
OggPlayDataHeader * old_data;
OggPlayBuffer * old_buffer;
struct OggPlaySeekTrash * next;
} OggPlaySeekTrash;
/**
*
*/
struct _OggPlay {
OggPlayReader * reader; /**< @see OggPlayReader */
OGGZ * oggz; /**< @see OGGZ */
OggPlayDecode ** decode_data; /**< */
OggPlayCallbackInfo * callback_info; /**< */
int num_tracks; /**< number of tracks in the Ogg container */
int all_tracks_initialised; /**< "= 1" indicates that all tracks are initialised */
ogg_int64_t callback_period; /**< */
OggPlayDataCallback * callback; /**< */
void * callback_user_ptr; /**< */
ogg_int64_t target; /**< */
int active_tracks; /**< number of active tracks */
volatile OggPlayBuffer * buffer; /**< @see OggPlayBuffer */
ogg_int64_t presentation_time; /**< */
OggPlaySeekTrash * trash; /**< @see OggPlaySeekTrash */
int shutdown; /**< "= 1" indicates shutdown event */
int pt_update_valid; /**< */
ogg_int64_t duration; /**< The value of the duration the last time it was retrieved.*/
int max_video_frame_pixels; /**< Maximum number of pixels we'll allow in a video frame.*/
};
void
oggplay_set_data_callback_force(OggPlay *me, OggPlayDataCallback callback,
void *user);
void
oggplay_take_out_trash(OggPlay *me, OggPlaySeekTrash *trash);
OggPlayErrorCode
oggplay_seek_cleanup(OggPlay *me, ogg_int64_t milliseconds);
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;
/**
* Conversion function for fixed point 32.32 representation of time.
*
* OGGPLAY_TIME_INT_TO_FP(x)
* converts 'x' to a 32.32 fixed point integer
*
* OGGPLAY_TIME_FP_TO_INT
* converts 'x' - a 32.32 fixed point integer - back to normal integer representation
* + changes the order of magnitude by 1000
* e.g. if the fixed point number - 32.32 format - represents seconds
* then the macro will convert it to milliseconds.
*/
#define OGGPLAY_TIME_INT_TO_FP(x) ((x) << 32)
#define OGGPLAY_TIME_FP_TO_INT(x) (((((x) >> 16) * 1000) >> 16) & 0xFFFFFFFF)
/* Allocate and free dynamic memory used by ogg.
* By default they are the ones from stdlib */
#define oggplay_malloc _ogg_malloc
#define oggplay_calloc _ogg_calloc
#define oggplay_realloc _ogg_realloc
#define oggplay_free _ogg_free
/**
* macros for obtaining a type's max and min values
* http://www.fefe.de/intof.html
*/
#define OGGPLAY_TYPE_HALF_MAX_SIGNED(type) ((type)1 << (sizeof(type)*8-2))
#define OGGPLAY_TYPE_MAX_SIGNED(type) (OGGPLAY_TYPE_HALF_MAX_SIGNED(type) - 1 + OGGPLAY_TYPE_HALF_MAX_SIGNED(type))
#define OGGPLAY_TYPE_MIN_SIGNED(type) (-1 - OGGPLAY_TYPE_MAX_SIGNED(type))
#define OGGPLAY_TYPE_MIN(type) ((type)-1 < 1?OGGPLAY_TYPE_MIN_SIGNED(type):(type)0)
#define OGGPLAY_TYPE_MAX(type) ((type)~OGGPLAY_TYPE_MIN(type))
static inline int
oggplay_check_add_overflow (size_t a, long b, size_t* r) {
/* we cannot assume that sizeof(size_t) >= sizeof(long) !!! */
if (sizeof(size_t) < sizeof(long)) {
/* check whether the number fits into a size_t */
if
(
(b < 0) ?
((OGGPLAY_TYPE_MAX(size_t)+b >= 0) ? 0 : 1) :
((OGGPLAY_TYPE_MAX(size_t)-b >= 0) ? 0 : 1)
)
{
return E_OGGPLAY_TYPE_OVERFLOW;
}
}
/* check whether the sum of the 'a' and 'b' fits into a size_t */
if
(
(b < 0) ?
((OGGPLAY_TYPE_MIN(size_t)-b <= a) ? 0 : 1) :
((OGGPLAY_TYPE_MAX(size_t)-b >= a) ? 0 : 1)
)
{
return E_OGGPLAY_TYPE_OVERFLOW;
}
/* if 'r' is supplied give back the sum of 'a' and 'b' */
if (r != NULL)
*r = a+b;
return 0;
}
static inline int
oggplay_mul_signed_overflow_generic(long a, long b, long *re) {
long _a, _b, ah, bh, x, y, r = 0;
int sign = 1;
_a = a;
_b = b;
ah = _a >> (sizeof(long)*4);
bh = _b >> (sizeof(long)*4);
if (a < 0) {
_a = -_a;
if (_a < 0) {
if (_b == 0 || _b == 1) {
r = _a*_b;
goto ok;
} else {
goto overflow;
}
}
sign = -sign;
ah = _a >> (sizeof(long)*4);
}
if (_b < 0) {
_b = -_b;
if (_b < 0) {
if (_a == 0 || (_a == 1 && sign == 1)) {
r = _a*_b;
goto ok;
} else {
goto overflow;
}
}
sign = -sign;
bh = _b >> (sizeof(long)*4);
}
if (ah != 0 && bh != 0) {
goto overflow;
}
if (ah == 0 && bh == 0) {
r = _a*_b;
if (r < 0)
goto overflow;
goto ok;
}
if (_a < _b) {
x = _a;
_a = _b;
_b = x;
ah = bh;
}
y = ah*_b;
if (y >= (1L << (sizeof(long)*4 - 1)))
goto overflow;
_a &= (1L << sizeof(long)*4) - 1;
x = _a*_b;
if (x < 0)
goto overflow;
x += (y << sizeof(long)*4);
if (x < 0)
goto overflow;
ok:
if (re != NULL) {
*re = sign*r;
}
return 0;
overflow:
return E_OGGPLAY_TYPE_OVERFLOW;
}
static inline int
oggplay_mul_signed_overflow(long a, long b, long *r) {
if (sizeof(long) > 4) {
return oggplay_mul_signed_overflow_generic (a, b, r);
} else {
ogg_int64_t c = (ogg_int64_t) a*b;
/* check whether the result fits in a long bit */
if
(
(c < 1) ?
((OGGPLAY_TYPE_MIN (long) > c) ? 1 : 0) :
((OGGPLAY_TYPE_MAX (long) < c) ? 1 : 0)
)
{
return E_OGGPLAY_TYPE_OVERFLOW;
}
if (r != NULL) {
*r = (long)c;
}
return 0;
}
}
#include "oggplay_callback.h"
#include "oggplay_data.h"
#include "oggplay_buffer.h"
#endif

Просмотреть файл

@ -1,207 +0,0 @@
/*
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 (me->decode_data[track_num]->content_type == OGGZ_CONTENT_UNKNOWN) {
return E_OGGPLAY_TRACK_IS_UNKNOWN;
}
/* there was an error while decoding the headers of this track! */
if (me->decode_data[track_num]->initialised != 1) {
return E_OGGPLAY_TRACK_UNINITIALISED;
}
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 && me->decode_data[track_num]->content_type != OGGZ_CONTENT_KATE) {
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]->content_type == OGGZ_CONTENT_UNKNOWN) {
return E_OGGPLAY_TRACK_IS_UNKNOWN;
}
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 && me->decode_data[track_num]->content_type != OGGZ_CONTENT_KATE) {
me->active_tracks --;
}
}
return E_OGGPLAY_OK;
}

Просмотреть файл

@ -1,240 +0,0 @@
/*
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) {
ogg_int64_t eof;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (milliseconds < 0) {
return E_OGGPLAY_CANT_SEEK;
}
eof = oggplay_get_duration(me);
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;
}
}
return oggplay_seek_cleanup(me, milliseconds);
}
OggPlayErrorCode
oggplay_seek_cleanup(OggPlay* me, ogg_int64_t milliseconds)
{
OggPlaySeekTrash * trash;
OggPlaySeekTrash ** p;
OggPlayDataHeader ** end_of_list_p;
int i;
if (me == NULL)
return E_OGGPLAY_BAD_OGGPLAY;
/*
* 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 = oggplay_calloc(1, sizeof(OggPlaySeekTrash));
if (trash == NULL)
return E_OGGPLAY_OUT_OF_MEMORY;
/*
* store the old buffer in it next.
*/
if (me->buffer != NULL) {
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);
if (me->buffer == NULL)
{
return E_OGGPLAY_OUT_OF_MEMORY;
}
}
/*
* 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->last_granulepos = -1;
track->stream_info = OGGPLAY_STREAM_JUST_SEEKED;
}
/*
* we need to notify the tiger renderer that we seeked, so that
* now obsolete events are discarded
*/
#ifdef HAVE_TIGER
for (i = 0; i < me->num_tracks; i++) {
OggPlayDecode *track = me->decode_data[i];
if (track && track->content_type == OGGZ_CONTENT_KATE) {
OggPlayKateDecode *decode = (OggPlayKateDecode *)(me->decode_data[i]);
if (decode->use_tiger) tiger_renderer_seek(decode->tr, milliseconds/1000.0);
}
}
#endif
/*
* 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;
if (milliseconds == 0) {
for (i = 0; i < me->num_tracks; i++) {
OggPlayDecode *track = me->decode_data[i];
FishSound *sound_handle;
OggPlayAudioDecode *audio_decode;
if (track->content_type != OGGZ_CONTENT_VORBIS) {
continue;
}
audio_decode = (OggPlayAudioDecode*)track;
sound_handle = audio_decode->sound_handle;
fish_sound_reset(sound_handle);
}
}
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) {
oggplay_free(p);
}
p = trash;
}
if (p != NULL) {
oggplay_free(p);
}
}
OggPlayErrorCode
oggplay_seek_to_keyframe(OggPlay *me,
ogg_int64_t milliseconds,
ogg_int64_t offset_begin,
ogg_int64_t offset_end)
{
ogg_int64_t eof, time;
if (me == NULL) {
return E_OGGPLAY_BAD_OGGPLAY;
}
if (milliseconds < 0)
return E_OGGPLAY_CANT_SEEK;
eof = oggplay_get_duration(me);
if (eof > -1 && milliseconds > eof) {
return E_OGGPLAY_CANT_SEEK;
}
time = oggz_keyframe_seek_set(me->oggz,
milliseconds,
offset_begin,
offset_end);
if (time == -1) {
return E_OGGPLAY_CANT_SEEK;
}
oggplay_seek_cleanup(me, time);
return E_OGGPLAY_OK;
}

Просмотреть файл

@ -1,773 +0,0 @@
/*
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
#if HAVE_ASSERT
#include <assert.h>
#else
#define assert(x)
#endif
#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
*
* @param location Location of the Ogg content
* @param proxy The proxy if there's any.
* @param proxy_port The port of the proxy if there's any.
* @param host The host to connect to; using proxy if set.
* @param port The port to connect to;
* @param path The path where the content resides on the server.
* @retval -1 in case of error, 0 otherwise.
*/
int
oggplay_hostname_and_path(const char *location, const 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) {
if ((*host = strdup(proxy)) == NULL)
goto error;
*port = proxy_port;
if ((*path = strdup(location)) == NULL)
goto error;
return 0;
}
/* 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) {
if ((*host = strdup(location)) == NULL)
goto error;
*port = 80;
if ((*path = strdup("/")) == NULL)
goto error;
return 0;
}
/*
* 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;
}
if ((*host = strdup(location)) == NULL)
goto error;
(*host)[end_of_host - location] = '\0';
if (slash == NULL) {
if ((*path = strdup("/")) == NULL)
goto error;
return 0;
}
if ((*path = strdup(slash)) == NULL)
goto error;
return 0;
error:
/* there has been an error while copying strings... */
if (*host != NULL)
oggplay_free(*host);
return -1;
}
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;
size_t 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.
*/
if (oggplay_hostname_and_path(me->location, me->proxy, me->proxy_port,
&host, &port, &path) != 0)
return E_OGGPLAY_OUT_OF_MEMORY;
/*
* 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);
oggplay_free(host);
oggplay_free(path);
if (he == NULL) {
printf("Host not found\n");
return E_OGGPLAY_BAD_INPUT;
}
/*
* currently we only support IPv4
* TODO: switch to getaddrinfo and support IPv6!
*/
if (sizeof(addr.sin_addr.s_addr) != he->h_length) {
printf("No IPv6 support, yet!\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*)oggplay_malloc(TCP_READER_MAX_IN_MEMORY);
if (me->buffer == NULL)
return E_OGGPLAY_OUT_OF_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 ", 13) != 0
&&
strncmp((char *)me->buffer, "HTTP/1.0 200 ", 13) != 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 == NULL) {
return E_OGGPLAY_BAD_READER;
}
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
}
if (me->buffer != NULL) oggplay_free(me->buffer);
if (me->location != NULL) oggplay_free(me->location);
if (me->backing_store != NULL) {
fclose(me->backing_store);
}
oggplay_free(me);
return E_OGGPLAY_OK;
}
OggPlayErrorCode
grab_some_data(OggPlayTCPReader *me, int block) {
int remaining;
int r;
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
}
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 == NULL) {
return E_OGGPLAY_BAD_READER;
}
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);
}
ogg_int64_t
oggplay_tcp_reader_duration(OggPlayReader * opr) {
OggPlayTCPReader *me = (OggPlayTCPReader *)opr;
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
}
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;
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
}
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;
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
}
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;
if (me == NULL) {
return E_OGGPLAY_BAD_READER;
}
return me->current_position;
}
OggPlayReader *
oggplay_tcp_reader_new(const char *location, const char *proxy, int proxy_port) {
OggPlayTCPReader * me = (OggPlayTCPReader *)oggplay_malloc (sizeof (OggPlayTCPReader));
if (me == NULL)
return NULL;
me->state = OTRS_UNINITIALISED;
me->socket = INVALID_SOCKET;
me->buffer = NULL;
me->buffer_size = 0;
me->current_position = 0;
/* if there's not enough memory to copy the URI cancel the initialisation */
if ( (me->location = strdup(location)) == NULL)
{
oggplay_tcp_reader_destroy ((OggPlayReader*)me);
return NULL;
}
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;
}

Просмотреть файл

@ -1,86 +0,0 @@
/*
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;
const char * proxy;
int proxy_port;
int amount_in_memory;
FILE * backing_store;
int stored_offset;
dataLocation mode;
int duration;
} OggPlayTCPReader;
#endif

Просмотреть файл

@ -1,69 +0,0 @@
/*
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);
#elif defined(OS2)
DosSleep(ms);
#else
struct timespec ts = {0, (ogg_int64_t)ms * 1000000LL};
nanosleep(&ts, NULL);
#endif
}

Просмотреть файл

@ -1,360 +0,0 @@
/*
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
* Viktor Gal
* Makoto Kato <m_kato@ga2.so-net.ne.jp>
*/
#include "oggplay_private.h"
#include "oggplay_yuv2rgb_template.h"
#ifdef __SUNPRO_C
#define DISABLE_CPU_FEATURES
/* gcc inline asm and intristics have problems with Sun Studio.
* We need to fix it.
*/
#else
/* cpu extension detection */
#include "cpu.c"
#endif
/**
* yuv_convert_fptr type is a function pointer type for
* the various yuv-rgb converters
*/
typedef void (*yuv_convert_fptr) (const OggPlayYUVChannels *yuv,
OggPlayRGBChannels *rgb);
/* it is useless to determine each YUV conversion run
* the cpu type/featurs, thus we save the conversion function
* pointers
*/
static struct OggPlayYUVConverters {
yuv_convert_fptr yuv420rgba; /**< YUV420 to RGBA */
yuv_convert_fptr yuv420bgra; /**< YUV420 to BGRA */
yuv_convert_fptr yuv420argb; /**< YUV420 to ARGB */
yuv_convert_fptr yuv422rgba; /**< YUV422 to RGBA */
yuv_convert_fptr yuv422bgra; /**< YUV422 to BGRA */
yuv_convert_fptr yuv422argb; /**< YUV422 to ARGB */
yuv_convert_fptr yuv444rgba; /**< YUV444 to RGBA */
yuv_convert_fptr yuv444bgra; /**< YUV444 to BGRA */
yuv_convert_fptr yuv444argb; /**< YUV444 to ARGB */
} yuv_conv = {NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL};
/**
* vanilla implementation of YUV-to-RGB conversion.
*
* - using table-lookups instead of multiplication
* - avoid CLAMPing by incorporating
*
*/
#define prec 15
static const int CoY = (int)(1.164 * (1 << prec) + 0.5);
static const int CoRV = (int)(1.596 * (1 << prec) + 0.5);
static const int CoGU = (int)(0.391 * (1 << prec) + 0.5);
static const int CoGV = (int)(0.813 * (1 << prec) + 0.5);
static const int CoBU = (int)(2.018 * (1 << prec) + 0.5);
static int CoefsGU[256] = {0};
static int CoefsGV[256];
static int CoefsBU[256];
static int CoefsRV[256];
static int CoefsY[256];
#define CLAMP(v) ((v) > 255 ? 255 : (v) < 0 ? 0 : (v))
#define VANILLA_YUV2RGB_PIXEL(y, ruv, guv, buv) \
r = (CoefsY[y] + ruv) >> prec; \
g = (CoefsY[y] + guv) >> prec; \
b = (CoefsY[y] + buv) >> prec; \
#define VANILLA_RGBA_OUT(out, r, g, b) \
out[0] = CLAMP(r); \
out[1] = CLAMP(g); \
out[2] = CLAMP(b); \
out[3] = 255;
#define VANILLA_BGRA_OUT(out, r, g, b) \
out[0] = CLAMP(b); \
out[1] = CLAMP(g); \
out[2] = CLAMP(r); \
out[3] = 255;
#define VANILLA_ARGB_OUT(out, r, g, b) \
out[0] = 255; \
out[1] = CLAMP(r); \
out[2] = CLAMP(g); \
out[3] = CLAMP(b);
#define VANILLA_ABGR_OUT(out, r, g, b) \
out[0] = 255; \
out[1] = CLAMP(b); \
out[2] = CLAMP(g); \
out[3] = CLAMP(r);
#define LOOKUP_COEFFS int ruv = CoefsRV[*pv]; \
int guv = CoefsGU[*pu] + CoefsGV[*pv]; \
int buv = CoefsBU[*pu]; \
int r, g, b;
/* yuv420p, yuv422p -> */
#define CONVERT(OUTPUT_FUNC) LOOKUP_COEFFS \
VANILLA_YUV2RGB_PIXEL(py[0], ruv, guv, buv) \
OUTPUT_FUNC(dst, r, g, b) \
VANILLA_YUV2RGB_PIXEL(py[1], ruv, guv, buv) \
OUTPUT_FUNC((dst+4), r, g, b)
#define CLEANUP
YUV_CONVERT(yuv420_to_rgba_vanilla, CONVERT(VANILLA_RGBA_OUT), VANILLA_RGBA_OUT, 2, 8, 2, 1, 2)
YUV_CONVERT(yuv420_to_bgra_vanilla, CONVERT(VANILLA_BGRA_OUT), VANILLA_BGRA_OUT, 2, 8, 2, 1, 2)
YUV_CONVERT(yuv420_to_abgr_vanilla, CONVERT(VANILLA_ABGR_OUT), VANILLA_ABGR_OUT, 2, 8, 2, 1, 2)
YUV_CONVERT(yuv420_to_argb_vanilla, CONVERT(VANILLA_ARGB_OUT), VANILLA_ARGB_OUT, 2, 8, 2, 1, 2)
YUV_CONVERT(yuv422_to_rgba_vanilla, CONVERT(VANILLA_RGBA_OUT), VANILLA_RGBA_OUT, 2, 8, 2, 1, 1)
YUV_CONVERT(yuv422_to_bgra_vanilla, CONVERT(VANILLA_BGRA_OUT), VANILLA_BGRA_OUT, 2, 8, 2, 1, 1)
YUV_CONVERT(yuv422_to_abgr_vanilla, CONVERT(VANILLA_ABGR_OUT), VANILLA_ABGR_OUT, 2, 8, 2, 1, 1)
YUV_CONVERT(yuv422_to_argb_vanilla, CONVERT(VANILLA_ARGB_OUT), VANILLA_ARGB_OUT, 2, 8, 2, 1, 1)
#undef CONVERT
/* yuv444p -> */
#define CONVERT(OUTPUT_FUNC) LOOKUP_COEFFS \
VANILLA_YUV2RGB_PIXEL(py[0], ruv, guv, buv) \
OUTPUT_FUNC(dst, r, g, b)
YUV_CONVERT(yuv444_to_rgba_vanilla, CONVERT(VANILLA_RGBA_OUT), VANILLA_RGBA_OUT, 1, 4, 1, 1, 1)
YUV_CONVERT(yuv444_to_bgra_vanilla, CONVERT(VANILLA_BGRA_OUT), VANILLA_BGRA_OUT, 1, 4, 1, 1, 1)
YUV_CONVERT(yuv444_to_abgr_vanilla, CONVERT(VANILLA_ABGR_OUT), VANILLA_ABGR_OUT, 1, 4, 1, 1, 1)
YUV_CONVERT(yuv444_to_argb_vanilla, CONVERT(VANILLA_ARGB_OUT), VANILLA_ARGB_OUT, 1, 4, 1, 1, 1)
#undef CONVERT
#undef CLEANUP
#ifndef DISABLE_CPU_FEATURES
/* although we use cpu runtime detection, we still need these
* macros as there's no way e.g. we could compile a x86 asm code
* on a ppc machine and vica-versa
*/
#if defined(i386) || defined(__x86__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_AMD64)
#if !defined(_M_AMD64)
#define ENABLE_MMX
#endif
#include "x86/oggplay_yuv2rgb_x86.c"
#if defined(_MSC_VER) || defined(ATTRIBUTE_ALIGNED_MAX) && ATTRIBUTE_ALIGNED_MAX >= 16
#define ENABLE_SSE2
#endif
#elif defined(__ppc__) || defined(__ppc64__)
#define ENABLE_ALTIVEC
//altivec intristics only working with -maltivec gcc flag,
//but we want runtime altivec detection, hence this has to be
//fixed!
//#include "oggplay_yuv2rgb_altivec.c"
#endif
#endif
/**
* Initialize the lookup-table for vanilla yuv to rgb conversion.
*/
static void
init_vanilla_coeffs (void)
{
int i;
for(i = 0; i < 256; ++i)
{
CoefsGU[i] = -CoGU * (i - 128);
CoefsGV[i] = -CoGV * (i - 128);
CoefsBU[i] = CoBU * (i - 128);
CoefsRV[i] = CoRV * (i - 128);
CoefsY[i] = CoY * (i - 16) + (prec/2);
}
}
/**
* Initialize the function pointers in yuv_conv.
*
* Initialize the function pointers in yuv_conv, based on the
* the available CPU extensions.
*/
static void
init_yuv_converters(void)
{
ogg_uint32_t features = 0;
if ( yuv_conv.yuv420rgba == NULL )
{
init_vanilla_coeffs ();
#ifndef DISABLE_CPU_FEATURES
features = oc_cpu_flags_get();
#endif
#ifdef ENABLE_SSE2
if (features & OC_CPU_X86_SSE2)
{
yuv_conv.yuv420rgba = yuv420_to_rgba_sse2;
yuv_conv.yuv420bgra = yuv420_to_bgra_sse2;
yuv_conv.yuv420argb = yuv420_to_argb_sse2;
yuv_conv.yuv422rgba = yuv422_to_rgba_sse2;
yuv_conv.yuv422bgra = yuv422_to_bgra_sse2;
yuv_conv.yuv422argb = yuv422_to_argb_sse2;
yuv_conv.yuv444rgba = yuv444_to_rgba_sse2;
yuv_conv.yuv444bgra = yuv444_to_bgra_sse2;
yuv_conv.yuv444argb = yuv444_to_argb_sse2;
return;
}
#endif /* SSE2 */
#ifdef ENABLE_MMX
#ifdef ENABLE_SSE2
else
#endif
if (features & OC_CPU_X86_MMXEXT)
{
yuv_conv.yuv420rgba = yuv420_to_rgba_sse;
yuv_conv.yuv420bgra = yuv420_to_bgra_sse;
yuv_conv.yuv420argb = yuv420_to_argb_sse;
yuv_conv.yuv422rgba = yuv422_to_rgba_sse;
yuv_conv.yuv422bgra = yuv422_to_bgra_sse;
yuv_conv.yuv422argb = yuv422_to_argb_sse;
yuv_conv.yuv444rgba = yuv444_to_rgba_sse;
yuv_conv.yuv444bgra = yuv444_to_bgra_sse;
yuv_conv.yuv444argb = yuv444_to_argb_sse;
return;
}
else if (features & OC_CPU_X86_MMX)
{
yuv_conv.yuv420rgba = yuv420_to_rgba_mmx;
yuv_conv.yuv420bgra = yuv420_to_bgra_mmx;
yuv_conv.yuv420argb = yuv420_to_argb_mmx;
yuv_conv.yuv422rgba = yuv422_to_rgba_mmx;
yuv_conv.yuv422bgra = yuv422_to_bgra_mmx;
yuv_conv.yuv422argb = yuv422_to_argb_mmx;
yuv_conv.yuv444rgba = yuv444_to_rgba_mmx;
yuv_conv.yuv444bgra = yuv444_to_bgra_mmx;
yuv_conv.yuv444argb = yuv444_to_argb_mmx;
return;
}
#elif defined(ENABLE_ALTIVEC)
if (features & OC_CPU_PPC_ALTIVEC)
{
yuv_conv.yuv420rgba = yuv420_to_abgr_vanilla;
yuv_conv.yuv420bgra = yuv420_to_argb_vanilla;
yuv_conv.yuv420argb = yuv420_to_bgra_vanilla;
yuv_conv.yuv422rgba = yuv422_to_abgr_vanilla;
yuv_conv.yuv422bgra = yuv422_to_argb_vanilla;
yuv_conv.yuv422argb = yuv422_to_bgra_vanilla;
yuv_conv.yuv444rgba = yuv444_to_abgr_vanilla;
yuv_conv.yuv444bgra = yuv444_to_argb_vanilla;
yuv_conv.yuv444argb = yuv444_to_bgra_vanilla;
return;
}
#endif
/*
* no CPU extension was found... using vanilla converter, with respect
* to the endianness of the host
*/
#if WORDS_BIGENDIAN || IS_BIG_ENDIAN
yuv_conv.yuv420rgba = yuv420_to_abgr_vanilla;
yuv_conv.yuv420bgra = yuv420_to_argb_vanilla;
yuv_conv.yuv420argb = yuv420_to_bgra_vanilla;
yuv_conv.yuv422rgba = yuv422_to_abgr_vanilla;
yuv_conv.yuv422bgra = yuv422_to_argb_vanilla;
yuv_conv.yuv422argb = yuv422_to_bgra_vanilla;
yuv_conv.yuv444rgba = yuv444_to_abgr_vanilla;
yuv_conv.yuv444bgra = yuv444_to_argb_vanilla;
yuv_conv.yuv444argb = yuv444_to_bgra_vanilla;
#else
yuv_conv.yuv420rgba = yuv420_to_rgba_vanilla;
yuv_conv.yuv420bgra = yuv420_to_bgra_vanilla;
yuv_conv.yuv420argb = yuv420_to_argb_vanilla;
yuv_conv.yuv422rgba = yuv422_to_rgba_vanilla;
yuv_conv.yuv422bgra = yuv422_to_bgra_vanilla;
yuv_conv.yuv422argb = yuv422_to_argb_vanilla;
yuv_conv.yuv444rgba = yuv444_to_rgba_vanilla;
yuv_conv.yuv444bgra = yuv444_to_bgra_vanilla;
yuv_conv.yuv444argb = yuv444_to_argb_vanilla;
#endif
}
}
void
oggplay_yuv2rgba(const OggPlayYUVChannels* yuv, OggPlayRGBChannels* rgb)
{
if (yuv_conv.yuv420rgba == NULL)
init_yuv_converters();
if (yuv->y_height!=yuv->uv_height)
yuv_conv.yuv420rgba(yuv, rgb);
else if (yuv->y_width!=yuv->uv_width)
yuv_conv.yuv422rgba(yuv,rgb);
else
yuv_conv.yuv444rgba(yuv,rgb);
}
void
oggplay_yuv2bgra(const OggPlayYUVChannels* yuv, OggPlayRGBChannels * rgb)
{
if (yuv_conv.yuv420bgra == NULL)
init_yuv_converters();
if (yuv->y_height!=yuv->uv_height)
yuv_conv.yuv420bgra(yuv, rgb);
else if (yuv->y_width!=yuv->uv_width)
yuv_conv.yuv422bgra(yuv,rgb);
else
yuv_conv.yuv444bgra(yuv,rgb);}
void
oggplay_yuv2argb(const OggPlayYUVChannels* yuv, OggPlayRGBChannels * rgb)
{
if (yuv_conv.yuv420argb == NULL)
init_yuv_converters();
if (yuv->y_height!=yuv->uv_height)
yuv_conv.yuv420argb(yuv, rgb);
else if (yuv->y_width!=yuv->uv_width)
yuv_conv.yuv422argb(yuv,rgb);
else
yuv_conv.yuv444argb(yuv,rgb);
}

Просмотреть файл

@ -1,108 +0,0 @@
#ifndef __OGGPLAY_YUV2RGB_TEMPLATE_H__
#define __OGGPLAY_YUV2RGB_TEMPLATE_H__
#if defined(WIN32)
#define restrict
#else
#ifndef restrict
#define restrict __restrict__
#endif
#endif
/**
* Template for YUV to RGB conversion
*
* @param FUNC function name
* @param CONVERT a macro that defines the actual conversion function
* @param VANILLA_OUT
* @param NUM_PIXELS number of pixels processed in one iteration
* @param OUT_SHIFT number of pixels to shift after one iteration in rgb data stream
* @param Y_SHIFT number of pixels to shift after one iteration in Y data stream
* @param UV_SHIFT
* @param UV_VERT_SUB
*/
#define YUV_CONVERT(FUNC, CONVERT, VANILLA_OUT, NUM_PIXELS, OUT_SHIFT, Y_SHIFT, UV_SHIFT, UV_VERT_SUB)\
static void \
(FUNC)(const OggPlayYUVChannels* yuv, OggPlayRGBChannels* rgb) \
{ \
int i,j, w, h, r; \
unsigned char* restrict ptry; \
unsigned char* restrict ptru; \
unsigned char* restrict ptrv; \
unsigned char* restrict ptro; \
unsigned char *dst, *py, *pu, *pv; \
\
ptro = rgb->ptro; \
ptry = yuv->ptry; \
ptru = yuv->ptru; \
ptrv = yuv->ptrv; \
\
w = yuv->y_width / NUM_PIXELS; \
h = yuv->y_height; \
r = yuv->y_width % NUM_PIXELS; \
for (i = 0; i < h; ++i) \
{ \
py = ptry; \
pu = ptru; \
pv = ptrv; \
dst = ptro; \
for (j = 0; j < w; ++j, \
dst += OUT_SHIFT, \
py += Y_SHIFT, \
pu += UV_SHIFT, \
pv += UV_SHIFT) \
{ \
/* use the given conversion function */ \
CONVERT \
} \
/* \
* the video frame is not the multiple of NUM_PIXELS, \
* thus we have to deal with remaning pixels using \
* vanilla implementation. \
*/ \
if (r) { \
if (r==1 && yuv->y_width&1) { \
pu -= 1; pv -= 1; \
} \
\
for \
( \
j=(yuv->y_width-r); j < yuv->y_width; \
++j, \
dst += 4, \
py += 1 \
) \
{ \
LOOKUP_COEFFS \
VANILLA_YUV2RGB_PIXEL(py[0], ruv, guv, buv) \
VANILLA_OUT(dst, r, g, b) \
if \
( \
(j%2 && !(j+1==yuv->y_width-1 && yuv->y_width&1)) \
|| \
UV_VERT_SUB==1 \
) { \
pu += 1; pv += 1; \
} \
} \
} \
\
ptro += rgb->rgb_width * 4; \
ptry += yuv->y_width; \
\
if \
( \
(i & 0x1 && !(i+1==h-1 && h&1)) \
|| \
UV_VERT_SUB==1 \
) \
{ \
ptru += yuv->uv_width; \
ptrv += yuv->uv_width; \
} \
} \
CLEANUP \
}
#endif

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше