[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Gnash-commit] gnash ChangeLog libmedia/AudioDecoderNellymoser...
From: |
Bastiaan Jacques |
Subject: |
[Gnash-commit] gnash ChangeLog libmedia/AudioDecoderNellymoser... |
Date: |
Fri, 08 Feb 2008 15:27:32 +0000 |
CVSROOT: /sources/gnash
Module name: gnash
Changes by: Bastiaan Jacques <bjacques> 08/02/08 15:27:32
Modified files:
. : ChangeLog
libmedia : AudioDecoderNellymoser.cpp
AudioDecoderNellymoser.h Makefile.am
sound_handler.h
server : Makefile.am
server/asobj : NetStreamGst.cpp
Added files:
libmedia/gst : SoundGst.cpp SoundGst.h SoundHandlerGst.cpp
SoundHandlerGst.h gstbuffersrc.c gstbuffersrc.h
Removed files:
libmedia/gst : gstgnashsrc.c gstgnashsrc.h
Log message:
* libmedia/gst/SoundHandlerGst.{h,cpp}: New Gstreamer
sound_handler
implementation. Manages SoundGst objects.
* libmedia/gst/SoundGst{h,cpp}: Sound class representing a
single
sound.
* libmedia/gst/gstbuffersrc.{c,h}: Home-grown element derived
from
gstappsrc; it is a random-access element. Used for SoundGsts.
* libmedia/AudioDecoderNellymoser.{cpp,h}: Add another decode()
that returns floats, since Gstreamer can handle them.
* libmedia/Makefile.am: Compile new files; stop compiling
removed
files.
* libmedia/sound_handler.h: Drop unused (and evil)
{att,de}tach_aux_streamer methods.
* server/Makefile.am: Link in Gstreamer libs if requested.
* server/asobj/NetStreamGst.cpp: Remove unused include.
This fixes blockers #22092 and #21162.
CVSWeb URLs:
http://cvs.savannah.gnu.org/viewcvs/gnash/ChangeLog?cvsroot=gnash&r1=1.5593&r2=1.5594
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/AudioDecoderNellymoser.cpp?cvsroot=gnash&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/AudioDecoderNellymoser.h?cvsroot=gnash&r1=1.7&r2=1.8
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/Makefile.am?cvsroot=gnash&r1=1.11&r2=1.12
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/sound_handler.h?cvsroot=gnash&r1=1.8&r2=1.9
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/SoundGst.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/SoundGst.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/SoundHandlerGst.cpp?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/SoundHandlerGst.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstbuffersrc.c?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstbuffersrc.h?cvsroot=gnash&rev=1.1
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstgnashsrc.c?cvsroot=gnash&r1=1.2&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/libmedia/gst/gstgnashsrc.h?cvsroot=gnash&r1=1.2&r2=0
http://cvs.savannah.gnu.org/viewcvs/gnash/server/Makefile.am?cvsroot=gnash&r1=1.137&r2=1.138
http://cvs.savannah.gnu.org/viewcvs/gnash/server/asobj/NetStreamGst.cpp?cvsroot=gnash&r1=1.77&r2=1.78
Patches:
Index: ChangeLog
===================================================================
RCS file: /sources/gnash/gnash/ChangeLog,v
retrieving revision 1.5593
retrieving revision 1.5594
diff -u -b -r1.5593 -r1.5594
--- ChangeLog 8 Feb 2008 13:22:07 -0000 1.5593
+++ ChangeLog 8 Feb 2008 15:27:30 -0000 1.5594
@@ -1,3 +1,20 @@
+2008-02-08 Bastiaan Jacques <address@hidden>
+
+ * libmedia/gst/SoundHandlerGst.{h,cpp}: New Gstreamer sound_handler
+ implementation. Manages SoundGst objects.
+ * libmedia/gst/SoundGst{h,cpp}: Sound class representing a single
+ sound.
+ * libmedia/gst/gstbuffersrc.{c,h}: Home-grown element derived from
+ gstappsrc; it is a random-access element. Used for SoundGsts.
+ * libmedia/AudioDecoderNellymoser.{cpp,h}: Add another decode()
+ that returns floats, since Gstreamer can handle them.
+ * libmedia/Makefile.am: Compile new files; stop compiling removed
+ files.
+ * libmedia/sound_handler.h: Drop unused (and evil)
+ {att,de}tach_aux_streamer methods.
+ * server/Makefile.am: Link in Gstreamer libs if requested.
+ * server/asobj/NetStreamGst.cpp: Remove unused include.
+
2008-02-08 Sandro Santilli <address@hidden>
* testsuite/misc-mtasc.all/level87.as, testsuite/swfdec/PASSING:
Index: libmedia/AudioDecoderNellymoser.cpp
===================================================================
RCS file: /sources/gnash/gnash/libmedia/AudioDecoderNellymoser.cpp,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- libmedia/AudioDecoderNellymoser.cpp 21 Jan 2008 23:10:13 -0000 1.7
+++ libmedia/AudioDecoderNellymoser.cpp 8 Feb 2008 15:27:30 -0000 1.8
@@ -17,7 +17,7 @@
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
//
-// $Id: AudioDecoderNellymoser.cpp,v 1.7 2008/01/21 23:10:13 rsavoye Exp $
+// $Id: AudioDecoderNellymoser.cpp,v 1.8 2008/02/08 15:27:30 bjacques Exp $
// This file incorporates work covered by the following copyright and
permission
// notice:
@@ -769,6 +769,25 @@
}
}
+float* AudioDecoderNellymoser::decode(boost::uint8_t* in_buf, boost::uint32_t
inputSize, boost::uint32_t* outputSize)
+{
+ size_t out_buf_size = (inputSize / NELLY_BLOCK_LEN) * 256;
+ float* out_buf = new float[out_buf_size];
+
+ boost::uint8_t* input_ptr = in_buf;
+ float* output_ptr = out_buf;
+
+ while (inputSize > 0) {
+ nelly_decode_block(_nh, input_ptr, output_ptr);
+ input_ptr += NELLY_BLOCK_LEN;
+ inputSize -= NELLY_BLOCK_LEN;
+ output_ptr += 256;
+ }
+
+ *outputSize = out_buf_size;
+
+ return out_buf;
+}
boost::uint8_t* AudioDecoderNellymoser::decode(boost::uint8_t* input,
boost::uint32_t inputSize, boost::uint32_t& outputSize, boost::uint32_t&
decodedBytes, bool /*parse*/)
{
@@ -788,7 +807,7 @@
boost::uint8_t* tmp_raw_buffer =
reinterpret_cast<boost::uint8_t*>(out_buf_start);
boost::uint32_t tmp_raw_buffer_size = out_buf_size * 2;
-
+#if 0
// If we need to convert samplerate or/and from mono to stereo...
if (out_buf_size > 0 && (_sampleRate != 44100 || !_stereo)) {
@@ -816,8 +835,11 @@
tmp_raw_buffer_size = adjusted_size;
} else {
+#endif
tmp_raw_buffer_size = out_buf_size;
+#if 0
}
+#endif
outputSize = tmp_raw_buffer_size;
decodedBytes = inputSize;
Index: libmedia/AudioDecoderNellymoser.h
===================================================================
RCS file: /sources/gnash/gnash/libmedia/AudioDecoderNellymoser.h,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -b -r1.7 -r1.8
--- libmedia/AudioDecoderNellymoser.h 21 Jan 2008 23:10:13 -0000 1.7
+++ libmedia/AudioDecoderNellymoser.h 8 Feb 2008 15:27:30 -0000 1.8
@@ -16,7 +16,7 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-// $Id: AudioDecoderNellymoser.h,v 1.7 2008/01/21 23:10:13 rsavoye Exp $
+// $Id: AudioDecoderNellymoser.h,v 1.8 2008/02/08 15:27:30 bjacques Exp $
// This file incorporates work covered by the following copyright and
permission
// notice:
@@ -81,6 +81,9 @@
boost::uint8_t* decode(boost::uint8_t* input, boost::uint32_t
inputSize, boost::uint32_t& outputSize, boost::uint32_t& decodedBytes, bool
parse);
+ /// @return a new[]-allocated pointer to decoded data in floats.
+ float* decode(boost::uint8_t* in_buf, boost::uint32_t inputSize,
boost::uint32_t* outputSize);
+
private:
// The handle used by the decoder
Index: libmedia/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/libmedia/Makefile.am,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -b -r1.11 -r1.12
--- libmedia/Makefile.am 21 Jan 2008 23:10:14 -0000 1.11
+++ libmedia/Makefile.am 8 Feb 2008 15:27:30 -0000 1.12
@@ -38,6 +38,9 @@
-I$(top_srcdir)/backend \
-I$(top_srcdir)/libbase \
-I$(top_srcdir)/server \
+ -I$(top_srcdir)/server/vm \
+ -I$(top_srcdir)/server/parser \
+ -I$(top_srcdir)/libgeometry \
$(PTHREAD_CFLAGS) \
$(OPENGL_CFLAGS) \
$(LIBXML_CFLAGS) \
@@ -95,28 +98,30 @@
if USE_SOUND_GST
libgnashmedia_la_SOURCES += \
- gst/gstgnashsrc.c \
gst/VideoDecoderGst.cpp \
gst/AudioDecoderGst.cpp \
gst/gstappbuffer.c \
gst/gstappsink.c \
gst/gstappsrc.c \
- gst/sound_handler_gst.cpp \
+ gst/SoundHandlerGst.cpp \
+ gst/SoundGst.cpp \
gst/MediaDecoderGst.cpp \
gst/gstflvdemux.c \
- gst/gstflvparse.c
+ gst/gstflvparse.c \
+ gst/gstbuffersrc.c
noinst_HEADERS += \
- gst/gstgnashsrc.h \
gst/gstappbuffer.h \
gst/AudioDecoderGst.h \
gst/VideoDecoderGst.h \
gst/gstappsink.h \
gst/gstappsrc.h \
- gst/sound_handler_gst.h \
+ gst/SoundHandlerGst.h \
+ gst/SoundGst.h \
gst/MediaDecoderGst.h \
gst/gstflvdemux.h \
- gst/gstflvparse.h
+ gst/gstflvparse.h \
+ gst/gstbuffersrc.h
libgnashmedia_la_CPPFLAGS += \
$(GSTREAMER_CFLAGS)
Index: libmedia/sound_handler.h
===================================================================
RCS file: /sources/gnash/gnash/libmedia/sound_handler.h,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -b -r1.8 -r1.9
--- libmedia/sound_handler.h 21 Jan 2008 23:10:14 -0000 1.8
+++ libmedia/sound_handler.h 8 Feb 2008 15:27:31 -0000 1.9
@@ -15,7 +15,7 @@
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-/* $Id: sound_handler.h,v 1.8 2008/01/21 23:10:14 rsavoye Exp $ */
+/* $Id: sound_handler.h,v 1.9 2008/02/08 15:27:31 bjacques Exp $ */
/// \page sound_handler_intro Sound handler introduction
///
@@ -355,45 +355,7 @@
///
virtual bool is_muted() = 0;
- /// This is called by AS classes NetStream or Sound to attach callback,
so
- /// that audio from the classes will be played through the soundhandler.
- //
- /// This is actually only used by the SDL sound_handler. It uses these
"auxiliary"
- /// streamers to fetch decoded audio data to mix and send to the output
channel.
- ///
- /// The "aux streamer" will be called with the 'udata' pointer as first
argument,
- /// then will be passed a buffer pointer as second argument and it's
length
- /// as third. The callbacks should fill the given buffer if possible.
- /// The callback should return true if wants to remain attached, false
if wants
- /// to be detached.
- ///
- /// @param ptr
- /// The pointer to the callback function
- ///
- /// @param udata
- /// User data pointer, passed as first argument to the registered
callback.
- /// WARNING: this is currently also used to *identify* the callback
for later
- /// removal, see detach_aux_streamer. TODO: stop using the data
pointer for
- /// identification purposes and use the callback pointer directly
instead.
- ///
- virtual void attach_aux_streamer(aux_streamer_ptr ptr, void* owner)
= 0;
-
- /// This is called by AS classes NetStream or Sound to dettach
callback, so
- /// that audio from the classes no longer will be played through the
- /// soundhandler.
- //
- /// @param udata
- /// The key identifying the auxiliary streamer.
- /// WARNING: this need currently be the 'udata' pointer passed to
attach_aux_streamer.
- /// TODO: get the aux_streamer_ptr as key !!
- ///
- virtual void detach_aux_streamer(void* udata) = 0;
- sound_handler()
- :
- _soundsStarted(0),
- _soundsStopped(0)
- {}
virtual ~sound_handler() {};
@@ -425,6 +387,13 @@
protected:
+
+ sound_handler()
+ :
+ _soundsStarted(0),
+ _soundsStopped(0)
+ {}
+
/// Special test-member. Stores count of started sounds.
size_t _soundsStarted;
Index: server/Makefile.am
===================================================================
RCS file: /sources/gnash/gnash/server/Makefile.am,v
retrieving revision 1.137
retrieving revision 1.138
diff -u -b -r1.137 -r1.138
--- server/Makefile.am 21 Jan 2008 20:55:47 -0000 1.137
+++ server/Makefile.am 8 Feb 2008 15:27:32 -0000 1.138
@@ -203,6 +203,7 @@
if USE_SOUND_GST
AM_CPPFLAGS += $(GSTREAMER_CFLAGS)
+libgnashserver_la_LIBADD += $(GSTREAMER_LIBS)
endif
Index: server/asobj/NetStreamGst.cpp
===================================================================
RCS file: /sources/gnash/gnash/server/asobj/NetStreamGst.cpp,v
retrieving revision 1.77
retrieving revision 1.78
diff -u -b -r1.77 -r1.78
--- server/asobj/NetStreamGst.cpp 3 Feb 2008 09:18:50 -0000 1.77
+++ server/asobj/NetStreamGst.cpp 8 Feb 2008 15:27:32 -0000 1.78
@@ -25,7 +25,6 @@
#include "string_table.h"
#include <boost/algorithm/string/case_conv.hpp> // for PROPNAME (shouldn't
this include be in the header actualy defining PROPNAME, btw?)
-#include "gstgnashsrc.h"
#include "Object.h"
#include "gstflvdemux.h"
#include <gst/gstelement.h>
Index: libmedia/gst/SoundGst.cpp
===================================================================
RCS file: libmedia/gst/SoundGst.cpp
diff -N libmedia/gst/SoundGst.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/SoundGst.cpp 8 Feb 2008 15:27:31 -0000 1.1
@@ -0,0 +1,537 @@
+//
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+// derives from code subject to the following license:
+
+/* GStreamer
+ * Copyright (C) 1999,2000 Erik Walthinsen <address@hidden>
+ * 2000 Wim Taymans <address@hidden>
+ * 2004 Thomas Vander Stichele <address@hidden>
+ *
+ * gst-inspect.c: tool to inspect the GStreamer registry
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+// TODO:
+//
+// * Decode NellyMoser (easy)
+// * Implement "envelopes" (not so easy)
+
+#include "SoundGst.h"
+#include <iostream>
+#include "log.h"
+#include "AudioDecoderNellymoser.h"
+
+#include "gstbuffersrc.h"
+
+namespace gnash {
+namespace media {
+
+
+SoundGst::SoundGst(std::auto_ptr<SoundInfo>& sinfo)
+: _info(sinfo),
+ _dataSize(0)
+{
+ if (!gstBuildPipeline()) {
+ log_error("Failed to build an audio pipeline; no playback.");
+ }
+}
+
+SoundGst::SoundGst(void* data, unsigned int data_bytes,
+ std::auto_ptr<SoundInfo>& sinfo)
+: _info(sinfo),
+ _dataSize(0),
+ _loop_count(0)
+{
+ assert(data_bytes);
+
+ boost::uint8_t* data_ptr = reinterpret_cast<boost::uint8_t*>(data);
+
+
+ if (!gstBuildPipeline()) {
+ log_error("Failed to build an audio pipeline; no playback.");
+ }
+
+ pushData(data_ptr, data_bytes, 0);
+}
+
+SoundGst::~SoundGst()
+{
+ gst_element_set_state (_pipeline, GST_STATE_NULL);
+
+ gst_element_get_state (_pipeline, NULL, NULL, 0);
+
+ gst_object_unref(GST_OBJECT(_pipeline));
+
+ std::for_each(_data_vec.begin(), _data_vec.end(),
+ boost::checked_array_deleter<boost::uint8_t>());
+
+}
+
+
+long
+SoundGst::pushData(unsigned char* data, unsigned int data_bytes,
+ unsigned int sample_count)
+{
+ assert(data);
+
+ if (_info->getFormat() == AUDIO_CODEC_NELLYMOSER_8HZ_MONO ||
+ _info->getFormat() == AUDIO_CODEC_NELLYMOSER) {
+
+ AudioDecoderNellymoser decoder;
+ boost::uint32_t decoded_size;
+ float* decoded_data = decoder.decode(data, data_bytes, &decoded_size);
+
+ delete [] data;
+
+ // *whistles*
+ data = reinterpret_cast<unsigned char*>(decoded_data);
+ data_bytes = decoded_size * sizeof(float);
+ }
+
+ _data_vec.push_back(data);
+
+ GstBuffer* buffer = gst_buffer_new();
+ GST_BUFFER_DATA(buffer) = data;
+ GST_BUFFER_SIZE(buffer) = data_bytes;
+ GST_BUFFER_MALLOCDATA(buffer) = NULL;
+
+ gst_buffer_src_push_buffer_unowned (GST_BUFFER_SRC(_buffersrc), buffer);
+
+ long ret = _dataSize;
+ _dataSize += data_bytes;
+
+ return ret;
+}
+
+// The offset parameter is used for ActionScript calls, while start is
+// used by the parser. The offset parameter is in seconds, while the start
+// parameter is in samples.
+void
+SoundGst::play(int loop_count, int offset, long start,
+ const std::vector<sound_handler::sound_envelope>* envelopes)
+{
+ GstState state = GST_STATE_NULL;
+ gst_element_get_state (_pipeline, &state, NULL, 0);
+
+ if (state == GST_STATE_PLAYING) {
+ log_debug(_("Play request while we're already playing: repeat."));
+ if (_loop_count <= 0) {
+ _loop_count++;
+ }
+ return;
+ }
+
+ _loop_count = loop_count;
+
+ gst_element_set_state (_pipeline, GST_STATE_PAUSED);
+
+ gst_element_get_state (_pipeline, &state, NULL, 0);
+
+ gst_element_seek(_pipeline, 1.0, GST_FORMAT_BYTES,
+ GstSeekFlags(GST_SEEK_FLAG_SEGMENT |
GST_SEEK_FLAG_FLUSH),
+ GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, -1);
+
+ gst_element_set_state (_pipeline, GST_STATE_PLAYING);
+
+}
+
+
+// FIXME: check (and verify) the semantics of this call.
+void
+SoundGst::stop()
+{
+ gst_element_set_state (_pipeline, GST_STATE_NULL);
+}
+
+unsigned int
+SoundGst::getVolume()
+{
+ gdouble volume = 10;
+ g_object_get(G_OBJECT(_volume), "volume", &volume, NULL);
+ return unsigned(volume * 10);
+}
+
+void
+SoundGst::setVolume(unsigned int new_volume)
+{
+ gdouble volume = new_volume / 10;
+ g_object_set(G_OBJECT(_volume), "volume", volume, NULL);
+}
+
+void
+SoundGst::mute()
+{
+ g_object_set(G_OBJECT(_volume), "mute", TRUE, NULL);
+}
+
+void
+SoundGst::unmute()
+{
+ g_object_set(G_OBJECT(_volume), "mute", FALSE, NULL);
+}
+
+bool
+SoundGst::muted()
+{
+ gboolean mute = FALSE;
+ g_object_get(G_OBJECT(_volume), "mute", &mute, NULL);
+ return mute;
+}
+
+unsigned int
+SoundGst::duration()
+{
+ GstFormat format = GST_FORMAT_TIME;
+ gint64 duration;
+ bool success = gst_element_query_duration(_pipeline, &format, &duration);
+
+ if (!success) {
+ return 0;
+ }
+
+ return unsigned(duration / GST_MSECOND);
+}
+
+unsigned int
+SoundGst::position()
+{
+ GstFormat format = GST_FORMAT_TIME;
+ gint64 position;
+ bool success = gst_element_query_position(_pipeline, &format, &position);
+
+ if (!success) {
+ return 0;
+ }
+
+ return unsigned(position / GST_MSECOND);
+}
+
+SoundInfo*
+SoundGst::getSoundInfo()
+{
+ return _info.get();
+}
+
+/// Creates a GstCaps corresponding to the SoundInfo attached to this SoundGst.
+/// @return a GstCaps pointer, or NULL if the codec type is invalid. The caller
+/// owns the returned pointer.
+GstCaps*
+SoundGst::getCaps()
+{
+ GstCaps* caps = NULL;
+ switch(_info->getFormat())
+ {
+ case AUDIO_CODEC_ADPCM:
+ {
+ caps = gst_caps_new_simple ("audio/x-adpcm",
+ "rate", G_TYPE_INT, _info->getSampleRate(),
+ "channels", G_TYPE_INT, _info->isStereo() ?
2 : 1,
+ "layout", G_TYPE_STRING, "swf",
+ NULL);
+ break;
+ }
+ case AUDIO_CODEC_MP3:
+ {
+ caps = gst_caps_new_simple ("audio/mpeg",
+ "mpegversion", G_TYPE_INT, 1,
+ "layer", G_TYPE_INT, 3,
+ "rate", G_TYPE_INT, _info->getSampleRate(),
+ "channels", G_TYPE_INT, _info->isStereo() ?
2 : 1,
+ NULL);
+ break;
+ }
+ case AUDIO_CODEC_RAW:
+ case AUDIO_CODEC_UNCOMPRESSED:
+ {
+
+ caps = gst_caps_new_simple ("audio/x-raw-int",
+ "rate", G_TYPE_INT, _info->getSampleRate(),
+ "channels", G_TYPE_INT, _info->isStereo() ?
2 : 1,
+ "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
// FIXME: how do we know?
+ "width", G_TYPE_INT, (_info->is16bit() ? 16
: 8),
+ "depth", G_TYPE_INT, (_info->is16bit() ? 16
: 7), // 7 magic?
+ "signed", G_TYPE_BOOLEAN, TRUE, // FIXME:
how do we know?
+ NULL);
+ break;
+ }
+ case AUDIO_CODEC_NELLYMOSER_8HZ_MONO:
+ case AUDIO_CODEC_NELLYMOSER:
+ {
+ std::cout << "nellymoser found" << std::endl;
+ caps = gst_caps_new_simple ("audio/x-raw-float",
+ "rate", G_TYPE_INT, _info->getSampleRate(),
+ "channels", G_TYPE_INT, _info->isStereo() ?
2 : 1,
+ "endianness", G_TYPE_INT, G_LITTLE_ENDIAN,
// FIXME: how do we know?
+ "width", G_TYPE_INT, 32,
+ NULL);
+ break;
+ }
+ default:
+ {
+ break;
+ }
+ }
+
+ return caps;
+}
+
+
+// This function is inspired by Gstreamer's gst-inspect.c.
+
+/// This function searches the default Gstreamer registry for a decoder that
+/// can sink the given caps.
+/// @param caps The capabilities to search for.
+/// @param name The name to create the new element with.
+/// @return A GstElement with the highest autoplugging rank that can sink the
+/// given caps. The caller owns the returned pointer. NULL if no
+/// capable factory was found.
+GstElement*
+SoundGst::gstFindDecoder(const GstCaps* caps, const gchar* name)
+{
+ GList *features, *l;
+ GstElementFactory *factory = NULL;
+
+ features = gst_registry_get_feature_list (gst_registry_get_default (),
+ GST_TYPE_ELEMENT_FACTORY);
+
+ for (l = features; l != NULL; l = l->next) {
+ GstPluginFeature *feature;
+
+ feature = GST_PLUGIN_FEATURE (l->data);
+
+ GstElementFactory* cur_factory;
+
+ cur_factory = GST_ELEMENT_FACTORY (feature);
+
+ if (gst_element_factory_can_sink_caps(cur_factory, caps)) {
+
+ const gchar* klass = gst_element_factory_get_klass(cur_factory);
+ if (!g_strrstr(klass, "Codec/Decoder/Audio")) {
+ continue;
+ }
+
+ if (factory) {
+ guint oldrank =
gst_plugin_feature_get_rank(GST_PLUGIN_FEATURE(factory));
+ guint newrank = gst_plugin_feature_get_rank(feature);
+ if (newrank < oldrank) {
+ continue;
+ }
+ }
+
+ factory = cur_factory;
+ }
+ }
+
+ GstElement* decoder = NULL;
+
+ if (factory) {
+ decoder = gst_element_factory_create(factory, NULL);
+ } else {
+ log_error(_("Gnash was unable to find an appropriate Gstreamer audio "
+ "decoder. Please consider installing gstreamer-ffmpeg and/or "
+ "gstreamer-plugins-bad."));
+ }
+
+ g_list_foreach (features, (GFunc) gst_object_unref, NULL);
+ g_list_free (features);
+
+ return decoder;
+}
+
+bool
+SoundGst::needDecoder()
+{
+ switch(_info->getFormat())
+ {
+ case AUDIO_CODEC_ADPCM:
+ case AUDIO_CODEC_MP3:
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+bool
+SoundGst::gstBuildPipeline()
+{
+ _pipeline = gst_pipeline_new(NULL);
+
+ _buffersrc = gst_element_factory_make ("buffersrc", NULL);
+
+ GstCaps* src_caps = getCaps();
+
+ gst_buffer_src_set_caps (GST_BUFFER_SRC(_buffersrc), src_caps);
+
+ GstElement* decoder = NULL;
+
+ if (needDecoder()) {
+ if (_info->getFormat() == AUDIO_CODEC_MP3) {
+ decoder = gstFindDecoder(src_caps, NULL);
+ } else {
+ decoder = gst_bin_new(NULL);
+
+ GstElement* audioparse = gst_element_factory_make ("mp3parse", NULL);
+ GstElement* actual_decoder = gstFindDecoder(src_caps, NULL);
+ gst_bin_add_many(GST_BIN(decoder), audioparse, actual_decoder, NULL);
+ gst_element_link(audioparse, actual_decoder);
+
+ GstPad* srcpad = gst_element_get_static_pad (audioparse, "src");
+ GstPad* sinkpad = gst_element_get_static_pad (actual_decoder, "sink");
+
+ gst_element_add_pad (decoder, gst_ghost_pad_new ("sink", sinkpad));
+ gst_element_add_pad (decoder, gst_ghost_pad_new ("src", srcpad));
+
+ gst_object_unref (GST_OBJECT (srcpad));
+ gst_object_unref (GST_OBJECT (sinkpad));
+ }
+
+
+ // FIXME: if we fail to find a decoder, should we stop here?
+ }
+
+ GstElement* audioconvert = gst_element_factory_make ("audioconvert", NULL);
+
+ GstElement* audioresample = gst_element_factory_make ("audioresample", NULL);
+
+ _volume = gst_element_factory_make ("volume", NULL);
+
+ GstElement* audiosink = gst_element_factory_make ("autoaudiosink", NULL);
+
+
+ if (decoder) {
+
+ gst_bin_add_many(GST_BIN(_pipeline), _buffersrc, decoder, _volume,
+ audioconvert, audioresample, audiosink, NULL);
+
+ gst_element_link_many(_buffersrc, decoder, _volume, audioconvert,
+ audioresample, audiosink, NULL);
+ } else {
+ gst_bin_add_many(GST_BIN(_pipeline), _buffersrc,
+ audioconvert, audioresample, _volume, audiosink, NULL);
+
+ gst_element_link_many(_buffersrc, audioconvert, audioresample,
+ _volume, audiosink, NULL);
+
+ }
+
+ gst_caps_unref(src_caps);
+
+ if (!_volume || !audioconvert || !audioresample || !audiosink) {
+ log_error("Couldn't load the necessary Gstreamer modules for playback. "
+ "Please ensure a proper gstreamer-plugins-base installation.");
+ return false;
+ }
+
+ return true;
+}
+
+void SoundGst::poll()
+{
+ if (!_pipeline) {
+ return;
+ }
+
+ GstBus* bus = gst_element_get_bus(_pipeline);
+
+ while (gst_bus_have_pending(bus)) {
+ GstMessage* msg = gst_bus_pop(bus);
+ handleMessage(msg);
+
+ gst_message_unref(msg);
+ }
+
+ gst_object_unref(GST_OBJECT(bus));
+}
+
+
+
+void
+SoundGst::handleMessage (GstMessage *message)
+{
+
+ switch (GST_MESSAGE_TYPE (message)) {
+ case GST_MESSAGE_ERROR:
+ {
+ GError *err;
+ gchar *debug;
+ gst_message_parse_error (message, &err, &debug);
+
+ log_error(_("Embedded audio playback halted; module %s reported: %s\n"),
+ gst_element_get_name(GST_MESSAGE_SRC (message)), err->message);
+
+ g_error_free (err);
+ g_free (debug);
+
+ // Clear any buffers.
+ gst_element_set_state (_pipeline, GST_STATE_NULL);
+
+ break;
+ }
+ case GST_MESSAGE_EOS:
+ gst_element_set_state (_pipeline, GST_STATE_NULL);
+
+ break;
+ case GST_MESSAGE_SEGMENT_DONE:
+ {
+ if (_loop_count <= 0) {
+ // This seek from 0 to 0 obviously doesn't do much seeking. However, it
+ // makes sure that we will receive an EOS, since this is a non-flushing
+ // seek which will wait until the segment being played is done.
+ gst_element_seek(_pipeline, 1.0, GST_FORMAT_BYTES,
+ GST_SEEK_FLAG_NONE,
+ GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, 0);
+ break;
+ }
+
+ _loop_count--;
+
+ gst_element_seek(_pipeline, 1.0, GST_FORMAT_BYTES,
+ GST_SEEK_FLAG_SEGMENT /* non-flushing: seamless seek */,
+ GST_SEEK_TYPE_SET, 0, GST_SEEK_TYPE_SET, -1);
+ break;
+ }
+ default:
+ {
+#if 0
+ g_print("unhandled message\n");
+#endif
+ }
+ }
+
+}
+
+
+
+} // namespace media
+} // namespace gnash
+
Index: libmedia/gst/SoundGst.h
===================================================================
RCS file: libmedia/gst/SoundGst.h
diff -N libmedia/gst/SoundGst.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/SoundGst.h 8 Feb 2008 15:27:31 -0000 1.1
@@ -0,0 +1,105 @@
+//
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+#ifndef __GNASH_SOUND_GST_H
+#define __GNASH_SOUND_GST_H
+
+#include <gst/gst.h>
+#include "sound_handler.h"
+#include <boost/utility.hpp>
+#include <boost/scoped_array.hpp>
+
+
+namespace gnash {
+namespace media {
+
+
+/// This class is intended to control a single sound (corresponding to a single
+/// SWF DefineSound or SoundStream set). Objects of this type will be managed
+/// by the sound_handler.
+
+class SoundGst : public boost::noncopyable
+{
+public:
+ SoundGst(std::auto_ptr<SoundInfo>& sinfo);
+ SoundGst(void* data, unsigned int data_bytes,
+ std::auto_ptr<SoundInfo>& sinfo);
+ ~SoundGst();
+
+
+ long pushData(unsigned char* data, unsigned int data_bytes,
+ unsigned int sample_count);
+ void play(int loop_count, int secondOffset, long start,
+ const std::vector<sound_handler::sound_envelope>* envelopes);
+ void stop();
+
+ unsigned int getVolume();
+ void setVolume(unsigned int new_volume);
+
+ void mute();
+ void unmute();
+ bool muted();
+
+
+ unsigned int duration();
+ unsigned int position();
+
+ SoundInfo* getSoundInfo();
+
+ static void message_received (GstBus * bus, GstMessage * message,
+ SoundGst* sound);
+
+ void poll();
+private: // methods
+
+ GstElement* gstFindDecoder(const GstCaps* caps, const gchar *name);
+
+ bool gstBuildPipeline();
+
+ GstCaps* getCaps();
+
+ void handleMessage (GstMessage *message);
+
+
+
+ bool needDecoder();
+
+ void setLoopCount(int count);
+
+private: // data fields
+
+ /// A vector of data pointers. There may be only one pointer in this vector
+ /// (in the case of a DefineSound), or several (in the case of a SoundStream)
+ /// This class has ownership of the new[]-allocated pointers.
+ std::vector<uint8_t*> _data_vec;
+
+ std::auto_ptr<SoundInfo> _info;
+
+ GstElement* _pipeline;
+ GstElement* _volume;
+ GstElement* _buffersrc;
+
+ long _dataSize;
+
+ int _loop_count;
+};
+
+
+} // namespace media
+} // namespace gnash
+
+#endif //__GNASH_SOUND_GST_H
Index: libmedia/gst/SoundHandlerGst.cpp
===================================================================
RCS file: libmedia/gst/SoundHandlerGst.cpp
diff -N libmedia/gst/SoundHandlerGst.cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/SoundHandlerGst.cpp 8 Feb 2008 15:27:31 -0000 1.1
@@ -0,0 +1,262 @@
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+#include "SoundHandlerGst.h"
+
+#include <boost/bind.hpp>
+#include <boost/checked_delete.hpp>
+#include <boost/mem_fn.hpp>
+#include "log.h"
+#include "vm/VM.h"
+#include "builtin_function.h"
+#include "gnash.h"
+
+namespace gnash {
+namespace media {
+
+#define RETURN_IF_BAD_HANDLE(handle) \
+ if (handle < 0 || handle > int(_sounds.size()) - 1) { \
+ return; \
+ }
+
+#define RV_IF_BAD_HANDLE(handle, value) \
+ if (handle < 0 || handle > int(_sounds.size()) - 1) { \
+ return value; \
+ }
+
+
+SoundHandlerGst::SoundHandlerGst()
+ : _timer_id(0)
+{
+ gst_init(NULL, NULL);
+ GNASH_REPORT_FUNCTION;
+}
+
+
+SoundHandlerGst::~SoundHandlerGst()
+{
+ std::for_each(_sounds.begin(), _sounds.end(),
boost::checked_deleter<SoundGst>());
+
+ _sounds.clear();
+
+ VM::get().getRoot().clear_interval_timer(_timer_id);
+}
+
+void
+SoundHandlerGst::poll_sounds()
+{
+ std::for_each(_sounds.begin(), _sounds.end(),
+ boost::mem_fn(&SoundGst::poll));
+}
+
+
+void
+SoundHandlerGst::start_timer()
+{
+ if (_timer_id) {
+ // Timer is already running.
+ return;
+ }
+
+ boost::intrusive_ptr<builtin_function> poller =
+ new builtin_function(&SoundHandlerGst::poll_cb);
+
+
+ boost::intrusive_ptr<as_object> obj(new as_object);
+
+ std::auto_ptr<Timer> timer (new Timer());
+
+ timer->setInterval(*poller, 50, obj);
+ _timer_id = VM::get().getRoot().add_interval_timer(timer, true);
+}
+
+
+int
+SoundHandlerGst::create_sound(void* data, unsigned int data_bytes,
+ std::auto_ptr<SoundInfo> sinfo)
+{
+ if (!data) {
+ _sounds.push_back(new SoundGst(sinfo));
+ } else {
+ assert(data_bytes);
+
+ _sounds.push_back(new SoundGst(data, data_bytes, sinfo));
+ }
+
+ // This is our "unique identifier" or "handle".
+ return _sounds.size()-1;
+}
+
+long
+SoundHandlerGst::fill_stream_data(unsigned char* data, unsigned int bytes,
+ unsigned int sample_count, int handle)
+{
+ RV_IF_BAD_HANDLE(handle, 0);
+
+ return _sounds[handle]->pushData(data, bytes, sample_count);
+}
+
+SoundInfo*
+SoundHandlerGst::get_sound_info(int handle)
+{
+ RV_IF_BAD_HANDLE(handle, NULL);
+
+ return _sounds[handle]->getSoundInfo();
+}
+
+void
+SoundHandlerGst::play_sound(int handle, int loop_count, int offset,
+ long start, const std::vector<sound_envelope>* envelopes)
+{
+ RETURN_IF_BAD_HANDLE(handle);
+
+ start_timer();
+
+ _sounds[handle]->play(loop_count, offset, start, envelopes);
+
+ _soundsStarted++;
+}
+
+void
+SoundHandlerGst::stop_all_sounds()
+{
+ std::for_each(_sounds.begin(), _sounds.end(),
boost::mem_fn(&SoundGst::stop));
+}
+
+
+int
+SoundHandlerGst::get_volume(int handle)
+{
+ RV_IF_BAD_HANDLE(handle, 0);
+
+ return _sounds[handle]->getVolume();
+}
+
+void
+SoundHandlerGst::set_volume(int handle, int volume)
+{
+ RETURN_IF_BAD_HANDLE(handle);
+
+ _sounds[handle]->setVolume(volume);
+}
+
+void
+SoundHandlerGst::stop_sound(int handle)
+{
+ RETURN_IF_BAD_HANDLE(handle);
+
+ _sounds[handle]->stop();
+
+ _soundsStopped++;
+}
+
+void
+SoundHandlerGst::delete_sound(int handle)
+{
+ RETURN_IF_BAD_HANDLE(handle);
+
+ std::vector<SoundGst*>::iterator it =
+ std::find(_sounds.begin(), _sounds.end(), _sounds[handle]);
+
+ SoundGst* sound = *it;
+
+ _sounds.erase(it);
+
+ delete sound;
+}
+
+unsigned int
+SoundHandlerGst::get_duration(int handle)
+{
+ RV_IF_BAD_HANDLE(handle, 0);
+
+ return _sounds[handle]->duration();
+
+}
+
+unsigned int
+SoundHandlerGst::get_position(int handle)
+{
+ RV_IF_BAD_HANDLE(handle, 0);
+
+ return _sounds[handle]->position();
+}
+
+
+void
+SoundHandlerGst::reset()
+{
+ stop_all_sounds();
+}
+
+void
+SoundHandlerGst::mute()
+{
+ std::for_each(_sounds.begin(), _sounds.end(),
+ boost::mem_fn(&SoundGst::mute));
+}
+
+void
+SoundHandlerGst::unmute()
+{
+ std::for_each(_sounds.begin(), _sounds.end(),
+ boost::mem_fn(&SoundGst::unmute));
+}
+
+
+bool
+SoundHandlerGst::is_muted()
+{
+ using namespace boost;
+
+ std::vector<SoundGst*>::iterator it = std::find_if(_sounds.begin(),
+ _sounds.end(), bind( std::logical_not<bool>(),
+ bind(&SoundGst::muted, _1) ) );
+
+ return (it == _sounds.end());
+}
+
+#undef RETURN_IF_BAD_HANDLE
+#undef RV_IF_BAD_HANDLE
+
+/* static */ as_value
+SoundHandlerGst::poll_cb(const fn_call& /*fn*/)
+{
+ sound_handler* handler = get_sound_handler();
+ SoundHandlerGst* handler_gst = dynamic_cast<SoundHandlerGst*>(handler);
+ assert(handler_gst);
+
+ handler_gst->poll_sounds();
+
+ return as_value();
+}
+
+
+
+sound_handler* create_sound_handler_gst()
+// Factory.
+{
+ GNASH_REPORT_FUNCTION;
+ return new SoundHandlerGst;
+}
+
+
+} // namespace media
+} // namespace gnash
+
+
+
+
Index: libmedia/gst/SoundHandlerGst.h
===================================================================
RCS file: libmedia/gst/SoundHandlerGst.h
diff -N libmedia/gst/SoundHandlerGst.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/SoundHandlerGst.h 8 Feb 2008 15:27:31 -0000 1.1
@@ -0,0 +1,82 @@
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+#ifndef __SOUND_HANDLER_GST_H
+#define __SOUND_HANDLER_GST_H
+
+#include "SoundGst.h"
+#include "timers.h"
+#include "as_value.h"
+
+namespace gnash {
+namespace media {
+
+class SoundHandlerGst : public sound_handler
+{
+public:
+ SoundHandlerGst();
+ ~SoundHandlerGst();
+
+ int create_sound(void* data, unsigned int data_bytes,
+ std::auto_ptr<SoundInfo> sinfo);
+
+ long fill_stream_data(unsigned char* data, unsigned int data_bytes,
+ unsigned int sample_count, int handle_id);
+
+ SoundInfo* get_sound_info(int sound_handle);
+
+ void play_sound(int sound_handle, int loop_count, int secondOffset,
+ long start, const std::vector<sound_envelope>* envelopes);
+
+ void stop_all_sounds();
+
+ int get_volume(int sound_handle);
+
+ void set_volume(int sound_handle, int volume);
+
+ void stop_sound(int sound_handle);
+
+ void delete_sound(int sound_handle);
+
+ void poll_sounds();
+
+ void reset();
+
+ void mute();
+
+ void unmute();
+
+ bool is_muted();
+
+ unsigned int get_duration(int sound_handle);
+
+ unsigned int get_position(int sound_handle);
+
+ void start_timer();
+
+ static as_value poll_cb(const fn_call& fn);
+
+private:
+ std::vector<SoundGst*> _sounds;
+ unsigned int _timer_id;
+}; // SoundHandlerGst
+
+} // namespace media
+} // namespace gnash
+
+
+#endif // __SOUND_HANDLER_GST_H
+
Index: libmedia/gst/gstbuffersrc.c
===================================================================
RCS file: libmedia/gst/gstbuffersrc.c
diff -N libmedia/gst/gstbuffersrc.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/gstbuffersrc.c 8 Feb 2008 15:27:31 -0000 1.1
@@ -0,0 +1,424 @@
+//
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+// This file incorporates work covered by the following copyright and
permission
+// notice:
+
+/* GStreamer
+ * Copyright (C) 2007 David Schleef <address@hidden>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "gnashconfig.h"
+#endif
+
+#include <string.h>
+#include <assert.h>
+
+#include "gstbuffersrc.h"
+
+
+GST_DEBUG_CATEGORY (buffer_src_debug);
+#define GST_CAT_DEFAULT buffer_src_debug
+
+static const GstElementDetails buffer_src_details = GST_ELEMENT_DETAILS
("BufferSrc",
+ "FIXME",
+ "FIXME",
+ "autogenerated by makefilter");
+
+enum
+{
+ PROP_0
+};
+
+static GstStaticPadTemplate gst_buffer_src_template =
+GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+static void gst_buffer_src_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec);
+static void gst_buffer_src_get_property (GObject * object, guint prop_id,
+ GValue * value, GParamSpec * pspec);
+static void gst_buffer_src_dispose (GObject * object);
+static GstFlowReturn gst_buffer_src_create (GstBaseSrc *src, guint64 offset,
guint size, GstBuffer **buf);
+static gboolean gst_buffer_src_start (GstBaseSrc * psrc);
+static gboolean gst_buffer_src_stop (GstBaseSrc * psrc);
+static gboolean gst_buffer_is_seekable (GstBaseSrc *src);
+static gboolean gst_buffer_get_size (GstBaseSrc *src, guint64 *size);
+static gboolean gst_buffer_check_get_range (GstBaseSrc *src);
+
+GST_BOILERPLATE (GstBufferSrc, gst_buffer_src, GstBaseSrc, GST_TYPE_BASE_SRC);
+
+
+static void
+gst_buffer_src_base_init (gpointer g_class)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
+
+ GST_DEBUG_CATEGORY_INIT (buffer_src_debug, "buffersrc", 0, "buffersrc
element");
+
+ gst_element_class_set_details (element_class, &buffer_src_details);
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&gst_buffer_src_template));
+
+}
+
+static void
+gst_buffer_src_class_init (GstBufferSrcClass * klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GstBaseSrcClass *basesrc_class = (GstBaseSrcClass *) klass;
+
+ gobject_class->set_property = gst_buffer_src_set_property;
+ gobject_class->get_property = gst_buffer_src_get_property;
+ gobject_class->dispose = gst_buffer_src_dispose;
+
+ basesrc_class->create = gst_buffer_src_create;
+ basesrc_class->is_seekable = gst_buffer_is_seekable;
+ basesrc_class->start = gst_buffer_src_start;
+ basesrc_class->stop = gst_buffer_src_stop;
+ basesrc_class->get_size = gst_buffer_get_size;
+ basesrc_class->check_get_range = gst_buffer_check_get_range;
+}
+
+static void
+gst_buffer_src_dispose (GObject * obj)
+{
+ GstBufferSrc *buffersrc = GST_BUFFER_SRC (obj);
+
+ if (buffersrc->queue) {
+ gst_buffer_src_flush (buffersrc);
+ g_queue_free (buffersrc->queue);
+ buffersrc->queue = NULL;
+ }
+ if (buffersrc->caps) {
+ gst_caps_unref (buffersrc->caps);
+ buffersrc->caps = NULL;
+ }
+ if (buffersrc->mutex) {
+ g_mutex_free (buffersrc->mutex);
+ buffersrc->mutex = NULL;
+ }
+ if (buffersrc->cond) {
+ g_cond_free (buffersrc->cond);
+ buffersrc->cond = NULL;
+ }
+
+
+ G_OBJECT_CLASS (parent_class)->dispose (obj);
+}
+
+static void
+gst_buffer_src_init (GstBufferSrc * buffersrc, GstBufferSrcClass * klass)
+{
+ UNUSEDPAR(klass);
+
+ buffersrc->mutex = g_mutex_new ();
+ buffersrc->cond = g_cond_new ();
+ buffersrc->queue = g_queue_new ();
+ buffersrc->total_size = 0;
+}
+
+static void
+gst_buffer_src_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ UNUSEDPAR(value);
+ GstBufferSrc *buffersrc = GST_BUFFER_SRC (object);
+
+ GST_OBJECT_LOCK (buffersrc);
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+ GST_OBJECT_UNLOCK (buffersrc);
+}
+
+static void
+gst_buffer_src_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ UNUSEDPAR(value);
+ GstBufferSrc *buffersrc = GST_BUFFER_SRC (object);
+
+ GST_OBJECT_LOCK (buffersrc);
+ switch (prop_id) {
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+ GST_OBJECT_UNLOCK (buffersrc);
+}
+
+static gboolean
+gst_buffer_src_start (GstBaseSrc * psrc)
+{
+ UNUSEDPAR(psrc);
+
+#if 0
+ /* FIXME: I don't know if this makes sense */
+ buffersrc->end_of_stream = FALSE;
+ buffersrc->flush = FALSE;
+#endif
+
+ return TRUE;
+}
+
+static gboolean
+gst_buffer_src_stop (GstBaseSrc * psrc)
+{
+ UNUSEDPAR(psrc);
+
+ return TRUE;
+}
+
+
+static GstBuffer*
+gst_buffer_src_find_offset (GstBufferSrc * buffersrc, guint64* offset)
+{
+ guint i;
+
+ guint64 bytes = 0;
+ guint64 prev_bytes = 0;
+
+ for (i = 0; i < g_queue_get_length(buffersrc->queue); ++i) {
+ GstBuffer* buf = g_queue_peek_nth(buffersrc->queue, i);
+ assert(buf);
+
+ prev_bytes = bytes;
+ bytes += GST_BUFFER_SIZE(buf);
+
+ if (bytes > *offset) {
+ *offset = *offset - prev_bytes;
+ return buf;
+ }
+ }
+
+ return NULL;
+}
+
+static GstFlowReturn
+gst_buffer_src_create (GstBaseSrc *src, guint64 offset, guint size,
+ GstBuffer **buf)
+{
+ GstBufferSrc *buffersrc = GST_BUFFER_SRC (src);
+ int ret = GST_FLOW_ERROR;
+
+ g_mutex_lock (buffersrc->mutex);
+
+ while (1) {
+ if (!g_queue_is_empty (buffersrc->queue)) {
+
+ guint64 buf_offset = offset;
+ GstBuffer* bigbuf = gst_buffer_src_find_offset (buffersrc, &buf_offset);
+
+ if (!bigbuf) {
+ ret = GST_FLOW_UNEXPECTED; // EOS
+ break;
+ }
+
+ guint avail_size = GST_BUFFER_SIZE(bigbuf) - buf_offset;
+
+ guint subsize = MIN(avail_size, size);
+
+ *buf = gst_buffer_create_sub (bigbuf, buf_offset, subsize);
+
+ GST_BUFFER_OFFSET(*buf) = offset;
+ GST_BUFFER_OFFSET_END(*buf) = offset + subsize;
+
+ gst_buffer_set_caps (*buf, buffersrc->caps);
+
+ ret = GST_FLOW_OK;
+ break;
+ }
+ if (buffersrc->end_of_stream) {
+ buffersrc->end_of_stream = FALSE;
+ ret = GST_FLOW_UNEXPECTED;
+ break;
+ }
+ if (buffersrc->flush) {
+ buffersrc->flush = FALSE;
+ /* FIXME: I don't really know how to do this */
+ break;
+ }
+ g_cond_wait (buffersrc->cond, buffersrc->mutex);
+ }
+
+ g_mutex_unlock (buffersrc->mutex);
+ return ret;
+}
+
+static gboolean
+gst_buffer_is_seekable (GstBaseSrc *src)
+{
+ UNUSEDPAR(src);
+
+ return TRUE;
+}
+
+static gboolean
+gst_buffer_get_size (GstBaseSrc *src, guint64 *size)
+{
+ GstBufferSrc* buffersrc = (GstBufferSrc*)src;
+
+ g_mutex_lock (buffersrc->mutex);
+
+ *size = buffersrc->total_size;
+
+ g_mutex_unlock (buffersrc->mutex);
+
+ return TRUE;
+}
+
+static gboolean
+gst_buffer_check_get_range (GstBaseSrc* src)
+{
+ UNUSEDPAR(src);
+ return TRUE;
+}
+
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ GST_DEBUG_CATEGORY_INIT (buffer_src_debug, "buffersrc", 0, "Application
source");
+
+ if (!gst_element_register (plugin, "buffersrc", GST_RANK_PRIMARY,
+ gst_buffer_src_get_type ()))
+ return FALSE;
+
+ return TRUE;
+}
+
+GST_PLUGIN_DEFINE_STATIC (GST_VERSION_MAJOR, GST_VERSION_MINOR,
+ "buffersrc", "Element application source",
+ plugin_init, VERSION, "LGPL", "Gnash's buffer source", "Gnash")
+
+
+/* external API */
+
+/**
+ * gst_buffer_src_push_buffer_unowned:
+ * @buffersrc:
+ * @buffer:
+ *
+ * Adds a buffer to the queue of buffers that the buffersrc element will
+ * push to its source pad, when requested.
+ *
+ * This function does NOT take ownership of the buffer. The caller is
+ * responsible for destroying the buffer, but can only do so after it has
+ * cleared the pipeline and the buffer_src's internal queue has been flushed.
+ *
+ * This function will create sub-buffers of the passed buffer as needed, so
+ * its size does not matter.
+ */
+void
+gst_buffer_src_push_buffer_unowned (GstBufferSrc * buffersrc, GstBuffer *
buffer)
+{
+ g_return_if_fail (buffersrc);
+ g_return_if_fail (GST_IS_BUFFER_SRC (buffersrc));
+
+ g_mutex_lock (buffersrc->mutex);
+
+ g_queue_push_tail (buffersrc->queue, buffer);
+ buffersrc->total_size += GST_BUFFER_SIZE(buffer);
+
+ g_cond_signal (buffersrc->cond);
+ g_mutex_unlock (buffersrc->mutex);
+}
+
+
+/**
+ * gst_buffer_src_set_caps:
+ * @buffersrc:
+ * @caps:
+ *
+ * Set the capabilities on the buffersrc element. This function takes
+ * ownership of the caps structure.
+ */
+void
+gst_buffer_src_set_caps (GstBufferSrc * buffersrc, GstCaps * caps)
+{
+ g_return_if_fail (buffersrc);
+ g_return_if_fail (GST_IS_BUFFER_SRC (buffersrc));
+
+ gst_caps_replace (&buffersrc->caps, caps);
+}
+
+/**
+ * gst_buffer_src_flush:
+ * @buffersrc:
+ *
+ * Flushes all queued buffers from the buffersrc element.
+ */
+void
+gst_buffer_src_flush (GstBufferSrc * buffersrc)
+{
+ GstBuffer *buffer;
+
+ g_return_if_fail (buffersrc);
+ g_return_if_fail (GST_IS_BUFFER_SRC (buffersrc));
+
+ g_mutex_lock (buffersrc->mutex);
+
+ while ((buffer = g_queue_pop_head (buffersrc->queue))) {
+ gst_buffer_unref (buffer);
+ }
+ buffersrc->flush = TRUE;
+
+ g_cond_signal (buffersrc->cond);
+ g_mutex_unlock (buffersrc->mutex);
+}
+
+/**
+ * gst_buffer_src_end_of_stream:
+ * @buffersrc:
+ *
+ * Indicates to the buffersrc element that the last buffer queued in the
+ * element is the last buffer of the stream.
+ */
+void
+gst_buffer_src_end_of_stream (GstBufferSrc * buffersrc)
+{
+ g_return_if_fail (buffersrc);
+ g_return_if_fail (GST_IS_BUFFER_SRC (buffersrc));
+
+ g_mutex_lock (buffersrc->mutex);
+
+ buffersrc->end_of_stream = TRUE;
+
+ g_cond_signal (buffersrc->cond);
+ g_mutex_unlock (buffersrc->mutex);
+}
Index: libmedia/gst/gstbuffersrc.h
===================================================================
RCS file: libmedia/gst/gstbuffersrc.h
diff -N libmedia/gst/gstbuffersrc.h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ libmedia/gst/gstbuffersrc.h 8 Feb 2008 15:27:31 -0000 1.1
@@ -0,0 +1,95 @@
+//
+// Copyright (C) 2008 Free Software Foundation, Inc.
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+// This file incorporates work covered by the following copyright and
permission
+// notice:
+
+/* GStreamer
+ * Copyright (C) 2007 David Schleef <address@hidden>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _GNASH_BUFFER_SRC_H_
+#define _GNASH_BUFFER_SRC_H_
+
+#define UNUSEDPAR(x) { x = x; }
+
+#include <gst/gst.h>
+#include <gst/base/gstbasesrc.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_BUFFER_SRC \
+ (gst_buffer_src_get_type())
+#define GST_BUFFER_SRC(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BUFFER_SRC,GstBufferSrc))
+#define GST_BUFFER_SRC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BUFFER_SRC,GstBufferSrcClass))
+#define GST_IS_BUFFER_SRC(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BUFFER_SRC))
+#define GST_IS_BUFFER_SRC_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BUFFER_SRC))
+
+typedef struct _GstBufferSrc GstBufferSrc;
+typedef struct _GstBufferSrcClass GstBufferSrcClass;
+
+struct _GstBufferSrc
+{
+ GstBaseSrc basesrc;
+
+ /*< private >*/
+ GCond *cond;
+ GMutex *mutex;
+ GQueue *queue;
+ GstCaps *caps;
+ gboolean end_of_stream;
+ gboolean flush;
+ guint64 total_size;
+};
+
+struct _GstBufferSrcClass
+{
+ GstBaseSrcClass basesrc_class;
+};
+
+GType gst_buffer_src_get_type(void);
+
+GST_DEBUG_CATEGORY_EXTERN (buffer_src_debug);
+
+
+void gst_buffer_src_push_buffer_unowned (GstBufferSrc *buffersrc, GstBuffer
*buffer);
+void gst_buffer_src_set_caps (GstBufferSrc *buffersrc, GstCaps *caps);
+void gst_buffer_src_end_of_stream (GstBufferSrc *buffersrc);
+void gst_buffer_src_flush (GstBufferSrc * buffersrc);
+
+G_END_DECLS
+
+#endif
+
Index: libmedia/gst/gstgnashsrc.c
===================================================================
RCS file: libmedia/gst/gstgnashsrc.c
diff -N libmedia/gst/gstgnashsrc.c
--- libmedia/gst/gstgnashsrc.c 21 Jan 2008 23:10:15 -0000 1.2
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,328 +0,0 @@
-//
-// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-//
-// Based on the filesrc and fdsrc element in Gstreamer-core.
-//
-
-/* $Id: gstgnashsrc.c,v 1.2 2008/01/21 23:10:15 rsavoye Exp $ */
-
-#ifdef HAVE_CONFIG_H
-#include "gnashconfig.h"
-#endif
-
-#include "gstgnashsrc.h"
-
-static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-
-GST_DEBUG_CATEGORY_STATIC (gst_gnash_src_debug);
-#define GST_CAT_DEFAULT gst_gnash_src_debug
-
-static const GstElementDetails gst_gnash_src_details =
-GST_ELEMENT_DETAILS ("Gnash source",
- "Gnash",
- "Use callback to read from Gnash",
- "Gnash team");
-
-/* GnashSrc signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-
-#define DEFAULT_BLOCKSIZE 4*1024
-#define DEFAULT_DATA NULL
-#define DEFAULT_CALLBACKS NULL
-
-enum
-{
- ARG_0,
- ARG_DATA,
- ARG_CALLBACKS
-};
-
-static void gst_gnash_src_finalize (GObject * object);
-
-static void gst_gnash_src_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec);
-static void gst_gnash_src_get_property (GObject * object, guint prop_id,
- GValue * value, GParamSpec * pspec);
-
-static gboolean gst_gnash_src_start (GstBaseSrc * basesrc);
-static gboolean gst_gnash_src_stop (GstBaseSrc * basesrc);
-
-static gboolean gst_gnash_src_is_seekable (GstBaseSrc * src);
-static gboolean gst_gnash_src_get_size (GstBaseSrc * src, guint64 * size);
-static GstFlowReturn gst_gnash_src_create (GstPushSrc * src, GstBuffer **
buffer);
-static gboolean gst_gnash_src_do_seek (GstBaseSrc * src, GstSegment * s);
-
-static void
-_do_init (GType gnashsrc_type)
-{
- UNUSEDPAR(gnashsrc_type);
-/* static const GInterfaceInfo urihandler_info = {
- gst_gnash_src_uri_handler_init,
- NULL,
- NULL
- };*/
-
- GST_DEBUG_CATEGORY_INIT (gst_gnash_src_debug, "gnashsrc", 0, "gnashsrc
element");
-}
-
-GST_BOILERPLATE_FULL (GstGnashSrc, gst_gnash_src, GstElement,
GST_TYPE_PUSH_SRC, _do_init);
-
-static void
-gst_gnash_src_base_init (gpointer g_class)
-{
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_add_pad_template (gstelement_class,
- gst_static_pad_template_get (&srctemplate));
-
- gst_element_class_set_details (gstelement_class, &gst_gnash_src_details);
-}
-
-static void
-gst_gnash_src_class_init (GstGnashSrcClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
- GstBaseSrcClass *gstbasesrc_class;
- GstPushSrcClass *gstpush_src_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
- gstelement_class = GST_ELEMENT_CLASS (klass);
- gstbasesrc_class = GST_BASE_SRC_CLASS (klass);
- gstpush_src_class = GST_PUSH_SRC_CLASS (klass);
-
- gobject_class->set_property = gst_gnash_src_set_property;
- gobject_class->get_property = gst_gnash_src_get_property;
-
- g_object_class_install_property (gobject_class, ARG_DATA,
- g_param_spec_pointer ("data", NULL, NULL,
(GParamFlags)G_PARAM_READWRITE));
-
- g_object_class_install_property (gobject_class, ARG_CALLBACKS,
- g_param_spec_pointer ("callbacks", NULL, NULL,
(GParamFlags)G_PARAM_READWRITE));
-
- gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_gnash_src_finalize);
-
- gstbasesrc_class->start = GST_DEBUG_FUNCPTR (gst_gnash_src_start);
- gstbasesrc_class->stop = GST_DEBUG_FUNCPTR (gst_gnash_src_stop);
- gstbasesrc_class->is_seekable = GST_DEBUG_FUNCPTR
(gst_gnash_src_is_seekable);
- gstbasesrc_class->get_size = GST_DEBUG_FUNCPTR (gst_gnash_src_get_size);
- gstbasesrc_class->do_seek = GST_DEBUG_FUNCPTR (gst_gnash_src_do_seek);
-
- gstpush_src_class->create = GST_DEBUG_FUNCPTR (gst_gnash_src_create);
-}
-
-static void
-gst_gnash_src_init (GstGnashSrc * src, GstGnashSrcClass * g_class)
-{
- UNUSEDPAR(g_class);
- src->data = NULL;
- src->callbacks = NULL;
- src->read_position = 0;
-}
-
-static void
-gst_gnash_src_finalize (GObject * object)
-{
- GstGnashSrc *src;
-
- src = GST_GNASH_SRC (object);
-
- free (src->callbacks);
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_gnash_src_set_property (GObject * object, guint prop_id,
- const GValue * value, GParamSpec * pspec)
-{
- GstGnashSrc *src;
-
- g_return_if_fail (GST_IS_GNASH_SRC (object));
-
- src = GST_GNASH_SRC (object);
-
- switch (prop_id) {
- case ARG_DATA:
- src->data = g_value_get_pointer (value);
- break;
- case ARG_CALLBACKS:
- src->callbacks = g_value_get_pointer (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-static void
-gst_gnash_src_get_property (GObject * object, guint prop_id, GValue * value,
- GParamSpec * pspec)
-{
- GstGnashSrc *src;
- UNUSEDPAR(value);
- g_return_if_fail (GST_IS_GNASH_SRC (object));
-
- src = GST_GNASH_SRC (object);
-
- switch (prop_id) {
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-}
-
-//
-// Below is the functions used get make this plugin work.
-//
-
-// Used for seeking
-static gboolean
-gst_gnash_src_do_seek (GstBaseSrc * basesrc, GstSegment * seg)
-{
-
- GstGnashSrc *src;
- off_t res;
- src = GST_GNASH_SRC (basesrc);
-
- if (seg->format != GST_FORMAT_BYTES) return FALSE;
-
- struct gnashsrc_callback *gc;
- gc = src->callbacks;
- res = gc->seek (src->data, seg->start, SEEK_CUR);
- return TRUE;
-
-}
-
-// Output the next buffer
-static GstFlowReturn
-gst_gnash_src_create (GstPushSrc * psrc, GstBuffer ** outbuf)
-{
- GstGnashSrc *src;
- src = GST_GNASH_SRC (psrc);
- int ret, blocksize;
- GstBuffer *buf;
-
- struct gnashsrc_callback *gc;
- gc = src->callbacks;
-
- blocksize = GST_BASE_SRC (src)->blocksize;
- buf = gst_buffer_new_and_alloc (blocksize);
-
- GST_LOG_OBJECT (src, "Reading %d bytes", blocksize);
-
- ret = gc->read(src->data, (void*)GST_BUFFER_DATA(buf), blocksize);
-
- if (G_UNLIKELY (ret < 0)) goto could_not_read;
-
- /* other files should eos if they read 0 and more was requested */
- if (G_UNLIKELY (ret == 0 && blocksize > 0))
- goto eos;
-
- blocksize = ret;
-
- GST_BUFFER_SIZE (buf) = blocksize;
- GST_BUFFER_OFFSET (buf) = src->read_position;
- GST_BUFFER_OFFSET_END (buf) = src->read_position + blocksize;
-
- *outbuf = buf;
-
- src->read_position += blocksize;
-
- return GST_FLOW_OK;
-
- /* ERROR */
-could_not_read:
- {
- GST_ELEMENT_ERROR (src, RESOURCE, READ, (NULL), GST_ERROR_SYSTEM);
- gst_buffer_unref (buf);
- return GST_FLOW_ERROR;
- }
-eos:
- {
- GST_DEBUG ("non-regular file hits EOS");
- gst_buffer_unref (buf);
- return GST_FLOW_UNEXPECTED;
- }
-}
-
-static gboolean
-gst_gnash_src_is_seekable (GstBaseSrc * basesrc)
-{
- GstGnashSrc *src = GST_GNASH_SRC (basesrc);
-
- return src->seekable;
-}
-
-// Get size of the file. Not sure how we shall handles this...
-static gboolean
-gst_gnash_src_get_size (GstBaseSrc * basesrc, guint64 * size)
-{
- GstGnashSrc *src;
-
- src = GST_GNASH_SRC (basesrc);
-
- if (!src->seekable) {
- /* If it isn't seekable, we won't know the length (but fstat will still
- * succeed, and wrongly say our length is zero. */
- return FALSE;
- }
- return FALSE;
-
- // Since it's a streamed video file we probably don't know the length, so we
- // tell it's 50000. Maybe we should just return FALSE?
- *size = 500000;
- return TRUE;
-
-}
-
-/* open the file and mmap it, necessary to go to READY state */
-static gboolean
-gst_gnash_src_start (GstBaseSrc * basesrc)
-{
- GstGnashSrc *src = GST_GNASH_SRC (basesrc);
-
- if (src->data == NULL || src->callbacks == NULL) {
- GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND,(("No data or callback struct
supplied.")), (NULL));
- return FALSE;
- }
-
- src->read_position = 0;
- GST_INFO_OBJECT (src, "Ready for reading using callbacks");
-
- // TODO: set seekable to false when real streaming
- src->seekable = TRUE;
-
- return TRUE;
-
-}
-
-/* stop and free */
-static gboolean
-gst_gnash_src_stop (GstBaseSrc * basesrc)
-{
- GstGnashSrc *src = GST_GNASH_SRC (basesrc);
- UNUSEDPAR(src);
- return TRUE;
-}
-
Index: libmedia/gst/gstgnashsrc.h
===================================================================
RCS file: libmedia/gst/gstgnashsrc.h
diff -N libmedia/gst/gstgnashsrc.h
--- libmedia/gst/gstgnashsrc.h 21 Jan 2008 23:10:15 -0000 1.2
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,81 +0,0 @@
-//
-// Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
-//
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; either version 3 of the License, or
-// (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU General Public License for more details.
-//
-// You should have received a copy of the GNU General Public License
-// along with this program; if not, write to the Free Software
-// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-//
-// Based on the filesrc and fdsrc element in Gstreamer-core
-//
-
-/* $Id: gstgnashsrc.h,v 1.2 2008/01/21 23:10:15 rsavoye Exp $ */
-
-#ifndef __GST_GNASH_SRC_H__
-#define __GST_GNASH_SRC_H__
-
-#define UNUSEDPAR(x) { x = x; }
-
-
-#include <gst/gst.h>
-#include <gst/base/gstpushsrc.h>
-
-// Struct to contain the callback functions
-struct gnashsrc_callback {
- int (*read)(void* data, char* buf, int buf_size);
- int (*seek)(void* data, int offset, int whence);
-};
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_GNASH_SRC \
- (gst_gnash_src_get_type())
-#define GST_GNASH_SRC(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_GNASH_SRC,GstGnashSrc))
-#define GST_GNASH_SRC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_GNASH_SRC,GstGnashSrcClass))
-#define GST_IS_GNASH_SRC(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_GNASH_SRC))
-#define GST_IS_GNASH_SRC_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_GNASH_SRC))
-
-typedef struct _GstGnashSrc GstGnashSrc;
-typedef struct _GstGnashSrcClass GstGnashSrcClass;
-
-/**
- * GstGnashSrc:
- *
- * Opaque #GstGnashSrc structure.
- */
-struct _GstGnashSrc {
- GstPushSrc element;
-
- /*< private >*/
-
- guint64 read_position; // position in the stream
-
- gpointer data; // data passes with the callbacks
- gpointer callbacks; // struct with the callbacks
-
- gboolean seekable; // seekable or not
-
-};
-
-struct _GstGnashSrcClass {
- GstPushSrcClass parent_class;
-};
-
-GType gst_gnash_src_get_type (void);
-
-G_END_DECLS
-
-#endif /* __GST_GNASH_SRC_H__ */
- [Gnash-commit] gnash ChangeLog libmedia/AudioDecoderNellymoser...,
Bastiaan Jacques <=