aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/llmedia
diff options
context:
space:
mode:
Diffstat (limited to 'linden/indra/llmedia')
-rw-r--r--linden/indra/llmedia/CMakeLists.txt34
-rw-r--r--linden/indra/llmedia/llgstplaythread.cpp54
-rw-r--r--linden/indra/llmedia/llgstplaythread.h62
-rw-r--r--linden/indra/llmedia/llmediabase.h18
-rw-r--r--linden/indra/llmedia/llmediaimplcommon.cpp12
-rw-r--r--linden/indra/llmedia/llmediaimplcommon.h2
-rw-r--r--linden/indra/llmedia/llmediaimplgstreamer.cpp847
-rw-r--r--linden/indra/llmedia/llmediaimplgstreamer.h90
-rw-r--r--linden/indra/llmedia/llmediaimplgstreamer_syms.cpp169
-rw-r--r--linden/indra/llmedia/llmediaimplgstreamer_syms.h78
-rw-r--r--linden/indra/llmedia/llmediaimplgstreamer_syms_raw.inc46
-rw-r--r--linden/indra/llmedia/llmediaimplgstreamer_syms_rawv.inc5
-rw-r--r--linden/indra/llmedia/llmediaimplgstreamervidplug.cpp99
-rw-r--r--linden/indra/llmedia/llmediaimplgstreamervidplug.h5
-rw-r--r--linden/indra/llmedia/llmediamanager.cpp26
15 files changed, 770 insertions, 777 deletions
diff --git a/linden/indra/llmedia/CMakeLists.txt b/linden/indra/llmedia/CMakeLists.txt
index 0c892f9..c7b5cd1 100644
--- a/linden/indra/llmedia/CMakeLists.txt
+++ b/linden/indra/llmedia/CMakeLists.txt
@@ -11,7 +11,6 @@ include(LLMedia)
11include(LLMessage) 11include(LLMessage)
12include(LLWindow) 12include(LLWindow)
13include(Mozlib) 13include(Mozlib)
14include(QuickTime)
15 14
16include_directories( 15include_directories(
17 ${GSTREAMER_INCLUDE_DIRS} 16 ${GSTREAMER_INCLUDE_DIRS}
@@ -30,6 +29,9 @@ set(llmedia_SOURCE_FILES
30 llmediaimplexample2.cpp 29 llmediaimplexample2.cpp
31 llmediaimplfactory.cpp 30 llmediaimplfactory.cpp
32 llmediamanager.cpp 31 llmediamanager.cpp
32 llmediaimplgstreamer.cpp
33 llmediaimplgstreamervidplug.cpp
34 llgstplaythread.cpp
33 ) 35 )
34 36
35set(llmedia_HEADER_FILES 37set(llmedia_HEADER_FILES
@@ -44,21 +46,11 @@ set(llmedia_HEADER_FILES
44 llmediaimplregister.h 46 llmediaimplregister.h
45 llmediamanager.h 47 llmediamanager.h
46 llmediaobserver.h 48 llmediaobserver.h
49 llmediaimplgstreamer.h
50 llmediaimplgstreamervidplug.h
51 llgstplaythread.h
47 ) 52 )
48 53
49if (GSTREAMER)
50 list(APPEND llmedia_SOURCE_FILES
51 llmediaimplgstreamer.cpp
52 llmediaimplgstreamer_syms.cpp
53 llmediaimplgstreamervidplug.cpp
54 )
55
56 list(APPEND llmedia_HEADER_FILES
57 llmediaimplgstreamer.h
58 llmediaimplgstreamervidplug.h
59 llmediaimplgstreamer_syms.h
60 )
61
62 # Work around a bad interaction between broken gstreamer headers and 54 # Work around a bad interaction between broken gstreamer headers and
63 # g++ 4.3's increased strictness. 55 # g++ 4.3's increased strictness.
64 56
@@ -66,7 +58,6 @@ if (GSTREAMER)
66 set_source_files_properties(llmediaimplgstreamervidplug.cpp PROPERTIES 58 set_source_files_properties(llmediaimplgstreamervidplug.cpp PROPERTIES
67 COMPILE_FLAGS -Wno-error=write-strings) 59 COMPILE_FLAGS -Wno-error=write-strings)
68 endif (${CXX_VERSION} MATCHES "4.[23]") 60 endif (${CXX_VERSION} MATCHES "4.[23]")
69endif (GSTREAMER)
70 61
71if (MOZLIB) 62if (MOZLIB)
72 list(APPEND llmedia_SOURCE_FILES llmediaimplllmozlib.cpp) 63 list(APPEND llmedia_SOURCE_FILES llmediaimplllmozlib.cpp)
@@ -74,19 +65,6 @@ if (MOZLIB)
74 list(APPEND llmedia_HEADER_FILES llmediaimplllmozlib.h) 65 list(APPEND llmedia_HEADER_FILES llmediaimplllmozlib.h)
75endif (MOZLIB) 66endif (MOZLIB)
76 67
77if (QUICKTIME)
78 list(APPEND llmedia_SOURCE_FILES llmediaimplquicktime.cpp)
79 list(APPEND llmedia_HEADER_FILES llmediaimplquicktime.h)
80
81 # We use a bunch of deprecated system APIs.
82 if (DARWIN)
83 set_source_files_properties(
84 llmediaimplquicktime.cpp PROPERTIES
85 COMPILE_FLAGS -Wno-deprecated-declarations
86 )
87 endif (DARWIN)
88endif (QUICKTIME)
89
90set_source_files_properties(${llmedia_HEADER_FILES} 68set_source_files_properties(${llmedia_HEADER_FILES}
91 PROPERTIES HEADER_FILE_ONLY TRUE) 69 PROPERTIES HEADER_FILE_ONLY TRUE)
92 70
diff --git a/linden/indra/llmedia/llgstplaythread.cpp b/linden/indra/llmedia/llgstplaythread.cpp
new file mode 100644
index 0000000..152f9d9
--- /dev/null
+++ b/linden/indra/llmedia/llgstplaythread.cpp
@@ -0,0 +1,54 @@
1/**
2 * @file llgstplaythread.cpp
3 * @author Jacek Antonelli
4 * @brief GStreamer playback management thread class
5 *
6 * $LicenseInfo:firstyear=2009&license=viewergpl$
7 *
8 * Copyright (c) 2009, Jacek Antonelli
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of version 2 of the GNU General Public
12 * License as published by the Free Software Foundation. Terms of
13 * the GPL can be found in doc/GPL-license.txt in this distribution, or
14 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
15 *
16 * There are special exceptions to the terms and conditions of the GPL as
17 * it is applied to this Source Code. View the full text of the exception
18 * in the file doc/FLOSS-exception.txt in this software distribution, or
19 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 *
30 * $/LicenseInfo$
31 */
32
33#include "llgstplaythread.h"
34#include "llmediaimplgstreamer.h"
35
36LLGstPlayThread::
37LLGstPlayThread( LLMediaImplCommon *impl,
38 const std::string& name, apr_pool_t *poolp ):
39 LLThread( name, poolp ),
40 mMediaImpl( impl )
41{
42}
43
44
45LLGstPlayThread::~LLGstPlayThread()
46{
47}
48
49
50// virtual
51void LLGstPlayThread::run()
52{
53 ((LLMediaImplGStreamer *)mMediaImpl)->startPlay();
54}
diff --git a/linden/indra/llmedia/llgstplaythread.h b/linden/indra/llmedia/llgstplaythread.h
new file mode 100644
index 0000000..c3c36a7
--- /dev/null
+++ b/linden/indra/llmedia/llgstplaythread.h
@@ -0,0 +1,62 @@
1/**
2 * @file llgstplaythread.h
3 * @author Jacek Antonelli
4 * @brief GStreamer playback management thread class
5 *
6 * $LicenseInfo:firstyear=2009&license=viewergpl$
7 *
8 * Copyright (c) 2009, Jacek Antonelli
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of version 2 of the GNU General Public
12 * License as published by the Free Software Foundation. Terms of
13 * the GPL can be found in doc/GPL-license.txt in this distribution, or
14 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
15 *
16 * There are special exceptions to the terms and conditions of the GPL as
17 * it is applied to this Source Code. View the full text of the exception
18 * in the file doc/FLOSS-exception.txt in this software distribution, or
19 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License along
27 * with this program; if not, write to the Free Software Foundation, Inc.,
28 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
29 *
30 * $/LicenseInfo$
31 */
32
33
34#ifndef LL_LLGSTPLAYTHREAD_H
35#define LL_LLGSTPLAYTHREAD_H
36
37#include "linden_common.h"
38
39#include "llthread.h"
40#include "llmediaimplcommon.h"
41
42class LLGstPlayThread: public LLThread
43{
44 public:
45
46 LLGstPlayThread( LLMediaImplCommon *impl,
47 const std::string& name, apr_pool_t *poolp );
48
49 ~LLGstPlayThread();
50
51 virtual void run();
52
53 private:
54
55 // Actually, this will really only be an LLMediaImplGStreamer.
56 // But we have to jump through some hoops to mutual pointer-holding.
57 // There may be a better way, but I don't have the motivation to find it.
58 LLMediaImplCommon *mMediaImpl;
59};
60
61
62#endif // LL_LLGSTPLAYTHREAD_H
diff --git a/linden/indra/llmedia/llmediabase.h b/linden/indra/llmedia/llmediabase.h
index 68e6677..3bcee4e 100644
--- a/linden/indra/llmedia/llmediabase.h
+++ b/linden/indra/llmedia/llmediabase.h
@@ -62,6 +62,21 @@ class LLMediaBase
62 // undoes everything init() didm called by the media manager when destroying a source 62 // undoes everything init() didm called by the media manager when destroying a source
63 virtual bool reset() = 0; 63 virtual bool reset() = 0;
64 64
65
66 /* Mirrors GStreamer debug levels. */
67 enum EDebugLevel {
68 DEBUG_LEVEL_NONE = 0,
69 DEBUG_LEVEL_ERROR,
70 DEBUG_LEVEL_WARNING,
71 DEBUG_LEVEL_INFO,
72 DEBUG_LEVEL_DEBUG,
73 DEBUG_LEVEL_LOG,
74 DEBUG_LEVEL_COUNT,
75 };
76
77 /* Set the debug verbosity level. Only implemented for GStreamer. */
78 virtual bool setDebugLevel( EDebugLevel level ) = 0;
79
65 // accessor for MIME type 80 // accessor for MIME type
66 virtual bool setMimeType( const std::string mime_type ) = 0; 81 virtual bool setMimeType( const std::string mime_type ) = 0;
67 virtual std::string getMimeType() const = 0; 82 virtual std::string getMimeType() const = 0;
@@ -154,7 +169,8 @@ class LLMediaBase
154 STATUS_STARTED = 3, 169 STATUS_STARTED = 3,
155 STATUS_STOPPED = 4, 170 STATUS_STOPPED = 4,
156 STATUS_PAUSED = 6, 171 STATUS_PAUSED = 6,
157 STATUS_RESETTING = 7 172 STATUS_RESETTING = 7,
173 STATUS_DEAD = 8
158 }; 174 };
159 virtual bool addCommand( ECommand cmd ) = 0; 175 virtual bool addCommand( ECommand cmd ) = 0;
160 virtual bool clearCommand() = 0; 176 virtual bool clearCommand() = 0;
diff --git a/linden/indra/llmedia/llmediaimplcommon.cpp b/linden/indra/llmedia/llmediaimplcommon.cpp
index 87838f7..166e86d 100644
--- a/linden/indra/llmedia/llmediaimplcommon.cpp
+++ b/linden/indra/llmedia/llmediaimplcommon.cpp
@@ -67,7 +67,8 @@ LLMediaImplCommon::LLMediaImplCommon() :
67 mCommand( LLMediaBase::COMMAND_NONE ), 67 mCommand( LLMediaBase::COMMAND_NONE ),
68 mStatus( LLMediaBase::STATUS_UNKNOWN ), 68 mStatus( LLMediaBase::STATUS_UNKNOWN ),
69 mVolume( 0 ), 69 mVolume( 0 ),
70 mLooping( false ) 70 mLooping( false ),
71 mDebugLevel( LLMediaBase::DEBUG_LEVEL_NONE )
71{ 72{
72} 73}
73 74
@@ -93,6 +94,15 @@ bool LLMediaImplCommon::reset()
93 94
94//////////////////////////////////////////////////////////////////////////////// 95////////////////////////////////////////////////////////////////////////////////
95// virtual (derives from LLMediaBase) 96// virtual (derives from LLMediaBase)
97bool LLMediaImplCommon::setDebugLevel( LLMediaBase::EDebugLevel level )
98{
99 mDebugLevel = level;
100
101 return true;
102}
103
104////////////////////////////////////////////////////////////////////////////////
105// virtual (derives from LLMediaBase)
96bool LLMediaImplCommon::setMimeType( const std::string mime_type ) 106bool LLMediaImplCommon::setMimeType( const std::string mime_type )
97{ 107{
98 mMimeType = mime_type; 108 mMimeType = mime_type;
diff --git a/linden/indra/llmedia/llmediaimplcommon.h b/linden/indra/llmedia/llmediaimplcommon.h
index 2e60a1a..845429c 100644
--- a/linden/indra/llmedia/llmediaimplcommon.h
+++ b/linden/indra/llmedia/llmediaimplcommon.h
@@ -55,6 +55,7 @@ class LLMediaImplCommon :
55 // housekeeping 55 // housekeeping
56 virtual bool init(); 56 virtual bool init();
57 virtual bool reset(); 57 virtual bool reset();
58 virtual bool setDebugLevel( LLMediaBase::EDebugLevel level );
58 virtual bool setMimeType( const std::string url ); 59 virtual bool setMimeType( const std::string url );
59 virtual std::string getMimeType() const; 60 virtual std::string getMimeType() const;
60 virtual std::string getMediaURL() const; 61 virtual std::string getMediaURL() const;
@@ -157,6 +158,7 @@ class LLMediaImplCommon :
157 LLMediaBase::ECommand mCommand; 158 LLMediaBase::ECommand mCommand;
158 LLMediaBase::EStatus mStatus; 159 LLMediaBase::EStatus mStatus;
159 bool mLooping; 160 bool mLooping;
161 LLMediaBase::EDebugLevel mDebugLevel;
160}; 162};
161 163
162#endif // LLMEDIAIMPLCOMMON_H 164#endif // LLMEDIAIMPLCOMMON_H
diff --git a/linden/indra/llmedia/llmediaimplgstreamer.cpp b/linden/indra/llmedia/llmediaimplgstreamer.cpp
index a4fe930..d1bab29 100644
--- a/linden/indra/llmedia/llmediaimplgstreamer.cpp
+++ b/linden/indra/llmedia/llmediaimplgstreamer.cpp
@@ -18,8 +18,7 @@
18 * There are special exceptions to the terms and conditions of the GPL as 18 * There are special exceptions to the terms and conditions of the GPL as
19 * it is applied to this Source Code. View the full text of the exception 19 * it is applied to this Source Code. View the full text of the exception
20 * in the file doc/FLOSS-exception.txt in this software distribution, or 20 * in the file doc/FLOSS-exception.txt in this software distribution, or
21 * online at 21 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
23 * 22 *
24 * By copying, modifying or distributing this software, you acknowledge 23 * By copying, modifying or distributing this software, you acknowledge
25 * that you have read and understood your obligations described above, 24 * that you have read and understood your obligations described above,
@@ -31,20 +30,39 @@
31 * $/LicenseInfo$ 30 * $/LicenseInfo$
32 */ 31 */
33 32
34#include "llmediaimplgstreamer.h" 33///#if LL_GSTREAMER_ENABLED
34
35#if LL_WINDOWS
36 // GStreamer 0.10.22 - gstutils.h - conversion from 'guint64' to 'guint8'.
37 // This was an intentional change to make GStreamer more threadsafe, and
38 // is okay. Delete this bit if GStreamer ever gets more VS-friendly -- McCabe
39 #pragma warning(disable : 4244)
40#endif
35 41
36#if LL_GSTREAMER_ENABLED 42#include "linden_common.h"
43#include "llmediaimplgstreamer.h"
37 44
38extern "C" { 45extern "C" {
39#include <gst/gst.h> 46#include <gst/gst.h>
47#include <gst/gstelement.h>
40} 48}
41 49
50#if LL_WINDOWS
51 #pragma warning(default : 4244)
52#include <direct.h>
53#include <stdlib.h>
54#endif
55
42#include "llmediamanager.h" 56#include "llmediamanager.h"
43#include "llmediaimplregister.h" 57#include "llmediaimplregister.h"
44 58
45#include "llmediaimplgstreamervidplug.h" 59#include "llmediaimplgstreamervidplug.h"
60#include "llgstplaythread.h"
46 61
47#include "llmediaimplgstreamer_syms.h" 62
63#if LL_DARWIN
64#include <CoreFoundation/CoreFoundation.h> // For CF functions used in set_gst_plugin_path
65#endif
48 66
49// register this impl with media manager factory 67// register this impl with media manager factory
50static LLMediaImplRegister sLLMediaImplGStreamerReg( "LLMediaImplGStreamer", new LLMediaImplGStreamerMaker() ); 68static LLMediaImplRegister sLLMediaImplGStreamerReg( "LLMediaImplGStreamer", new LLMediaImplGStreamerMaker() );
@@ -64,21 +82,20 @@ LLMediaImplGStreamerMaker::LLMediaImplGStreamerMaker()
64// 82//
65LLMediaImplGStreamer:: 83LLMediaImplGStreamer::
66LLMediaImplGStreamer () : 84LLMediaImplGStreamer () :
67 mBusWatchID ( 0 ),
68 mediaData ( NULL ), 85 mediaData ( NULL ),
69 mMediaRowbytes ( 1 ), 86 mMediaRowbytes ( 1 ),
70 mTextureFormatPrimary ( LL_MEDIA_BGRA ), 87 mTextureFormatPrimary ( LL_MEDIA_BGRA ),
71 mTextureFormatType ( LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV ), 88 mTextureFormatType ( LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV ),
72 mPump ( NULL ), 89 mPump ( NULL ),
73 mPlaybin ( NULL ), 90 mPlaybin ( NULL ),
74 mVideoSink ( NULL ) 91 mVideoSink ( NULL ),
92 mState( GST_STATE_NULL ),
93 mPlayThread ( NULL )
75{ 94{
76 if (!mDoneInit) 95 startup( NULL ); // Startup gstreamer if it hasn't been already.
77 return; // error
78 96
79 DEBUGMSG("constructing media..."); 97 LL_DEBUGS("MediaManager") << "constructing media..." << LL_ENDL;
80 98 mVolume = -1.0; // XXX Hack to make the vould change happend first time
81 mVolume = 0.1234567; // minor hack to force an initial volume update
82 99
83 setMediaDepth(4); 100 setMediaDepth(4);
84 101
@@ -90,30 +107,24 @@ LLMediaImplGStreamer () :
90 } 107 }
91 108
92 // instantiate a playbin element to do the hard work 109 // instantiate a playbin element to do the hard work
93 mPlaybin = llgst_element_factory_make ("playbin", "play"); 110 mPlaybin = gst_element_factory_make ("playbin", "play");
94 if (!mPlaybin) 111 if (!mPlaybin)
95 { 112 {
113 // todo: cleanup pump
96 return; // error 114 return; // error
97 } 115 }
98 116
99 // get playbin's bus 117 if (NULL == getenv("LL_GSTREAMER_EXTERNAL"))
100 GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin));
101 if (!bus)
102 { 118 {
103 return; // error
104 }
105 mBusWatchID = llgst_bus_add_watch (bus,
106 llmediaimplgstreamer_bus_callback,
107 this);
108 llgst_object_unref (bus);
109
110 if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) {
111 // instantiate and connect a custom video sink 119 // instantiate and connect a custom video sink
120 LL_DEBUGS("MediaManager") << "extrenal video sink..." << LL_ENDL;
121
122 // Plays inworld instead of in external player
112 mVideoSink = 123 mVideoSink =
113 GST_SLVIDEO(llgst_element_factory_make ("private-slvideo", "slvideo")); 124 GST_SLVIDEO(gst_element_factory_make ("private-slvideo", "slvideo"));
114 if (!mVideoSink) 125 if (!mVideoSink)
115 { 126 {
116 WARNMSG("Could not instantiate private-slvideo element."); 127 LL_WARNS("MediaImpl") << "Could not instantiate private-slvideo element." << LL_ENDL;
117 // todo: cleanup. 128 // todo: cleanup.
118 return; // error 129 return; // error
119 } 130 }
@@ -145,7 +156,7 @@ int LLMediaImplGStreamer::getTextureFormatInternal() const
145LLMediaImplGStreamer:: 156LLMediaImplGStreamer::
146~LLMediaImplGStreamer () 157~LLMediaImplGStreamer ()
147{ 158{
148 DEBUGMSG("dtor of media..."); 159 LL_DEBUGS("MediaImpl") << ("dtor of media...") << LL_ENDL;
149 unload(); 160 unload();
150} 161}
151 162
@@ -153,116 +164,230 @@ LLMediaImplGStreamer::
153// virtual 164// virtual
154std::string LLMediaImplGStreamer::getVersion() 165std::string LLMediaImplGStreamer::getVersion()
155{ 166{
156 std::string rtn; 167 guint major, minor, micro, nano;
157 rtn = "[" + sLLMediaImplGStreamerReg.getImplName() + "] - GStreamer 0.10.x"; 168 gst_version(&major, &minor, &micro, &nano);
158 return rtn; 169 std::string version = llformat("%d.%d.%d.%d",major,minor,micro,nano);
170 return version;
159} 171}
160 172
173//
174// STARTUP
161/////////////////////////////////////////////////////////////////////////////// 175///////////////////////////////////////////////////////////////////////////////
162// (static) super-initialization - called once at application startup 176// (static) super-initialization - called once at application startup
163 177bool LLMediaImplGStreamer::startup (LLMediaManagerData* init_data)
164//static
165bool LLMediaImplGStreamer::mDoneInit = false;
166
167//static
168bool
169LLMediaImplGStreamer::
170startup ( LLMediaManagerData* init_data )
171{ 178{
172 // first - check if GStreamer is explicitly disabled 179 static bool done_init = false;
173 if (NULL != getenv("LL_DISABLE_GSTREAMER")) 180 if (!done_init)
174 return false;
175
176 // only do global GStreamer initialization once.
177 if (!mDoneInit)
178 { 181 {
179 // Init the glib type system - we need it. 182 // Init the glib type system - we need it.
180 g_type_init(); 183 g_type_init();
181 184
182 // Get symbols! 185 set_gst_plugin_path();
183 if (! grab_gst_syms("libgstreamer-0.10.so.0", 186
184 "libgstvideo-0.10.so.0") ) 187 // Protect against GStreamer resetting the locale, yuck.
188 static std::string saved_locale;
189 saved_locale = setlocale(LC_ALL, NULL);
190 if (0 == gst_init_check(NULL, NULL, NULL))
185 { 191 {
186 WARNMSG("Couldn't find suitable GStreamer 0.10 support on this system - video playback disabled."); 192 LL_WARNS("MediaImpl") << "GStreamer library failed to initialize and load standard plugins." << LL_ENDL;
193 setlocale(LC_ALL, saved_locale.c_str() );
187 return false; 194 return false;
188 } 195 }
196 setlocale(LC_ALL, saved_locale.c_str() );
189 197
190 if (llgst_segtrap_set_enabled) 198 // Set up logging facilities
191 { 199 gst_debug_remove_log_function( gst_debug_log_default );
192 llgst_segtrap_set_enabled(FALSE); 200 gst_debug_add_log_function( gstreamer_log, NULL );
193 }
194 else
195 {
196 WARNMSG("gst_segtrap_set_enabled() is not available; Automated crash-reporter may cease to function until next restart.");
197 }
198 201
199#if LL_LINUX 202 // Init our custom plugins - only really need do this once.
200 // Gstreamer tries a fork during init, waitpid-ing on it, 203 gst_slvideo_init_class();
201 // which conflicts with any installed SIGCHLD handler... 204
202 struct sigaction tmpact, oldact; 205
203 if (llgst_registry_fork_set_enabled) { 206 // List the plugins GStreamer can find
204 // if we can disable SIGCHLD-using forking behaviour, 207 LL_DEBUGS("MediaImpl") << "Found GStreamer plugins:" << LL_ENDL;
205 // do it. 208 GList *list;
206 llgst_registry_fork_set_enabled(false); 209 GstRegistry *registry = gst_registry_get_default();
207 } 210 std::string loaded = "";
208 else { 211 for (list = gst_registry_get_plugin_list(registry);
209 // else temporarily install default SIGCHLD handler 212 list != NULL;
210 // while GStreamer initialises 213 list = g_list_next(list))
211 tmpact.sa_handler = SIG_DFL; 214 {
212 sigemptyset( &tmpact.sa_mask ); 215 GstPlugin *list_plugin = (GstPlugin *)list->data;
213 tmpact.sa_flags = SA_SIGINFO; 216 (bool)gst_plugin_is_loaded(list_plugin) ? loaded = "Yes" : loaded = "No";
214 sigaction(SIGCHLD, &tmpact, &oldact); 217 LL_DEBUGS("MediaImpl") << gst_plugin_get_name(list_plugin) << ", loaded? " << loaded << LL_ENDL;
215 } 218 }
216#endif // LL_LINUX 219 gst_plugin_list_free(list);
217 220
218 // Protect against GStreamer resetting the locale, yuck.
219 static std::string saved_locale;
220 saved_locale = setlocale(LC_ALL, NULL);
221 221
222 // finally, try to initialize GStreamer! 222 done_init = true;
223 GError *err = NULL; 223 }
224 gboolean init_gst_success = llgst_init_check(NULL, NULL, &err); 224 return true;
225}
226
225 227
226 // restore old locale 228void LLMediaImplGStreamer::set_gst_plugin_path()
227 setlocale(LC_ALL, saved_locale.c_str() ); 229{
230 // Linux sets GST_PLUGIN_PATH in wrapper.sh, not here.
231#if LL_WINDOWS || LL_DARWIN
228 232
229#if LL_LINUX 233 std::string imp_dir = "";
230 // restore old SIGCHLD handler
231 if (!llgst_registry_fork_set_enabled)
232 sigaction(SIGCHLD, &oldact, NULL);
233#endif // LL_LINUX
234 234
235 if (!init_gst_success) // fail 235 // Get the current working directory:
236#if LL_WINDOWS
237 char* raw_dir;
238 raw_dir = _getcwd(NULL,0);
239 if( raw_dir != NULL )
240 {
241 imp_dir = std::string( raw_dir );
242 }
243#elif LL_DARWIN
244 CFBundleRef main_bundle = CFBundleGetMainBundle();
245 if( main_bundle != NULL )
246 {
247 CFURLRef bundle_url = CFBundleCopyBundleURL( main_bundle );
248 if( bundle_url != NULL )
236 { 249 {
237 if (err) 250 #ifndef MAXPATHLEN
238 { 251 #define MAXPATHLEN 1024
239 WARNMSG("GST init failed: %s", err->message); 252 #endif
240 g_error_free(err); 253 char raw_dir[MAXPATHLEN];
241 } 254 if( CFURLGetFileSystemRepresentation( bundle_url, true, (UInt8 *)raw_dir, MAXPATHLEN) )
242 else
243 { 255 {
244 WARNMSG("GST init failed for unspecified reason."); 256 imp_dir = std::string( raw_dir ) + "/Contents/MacOS/";
245 } 257 }
246 return false; 258 CFRelease(bundle_url);
247 } 259 }
260 }
261#endif
262
263 if( imp_dir == "" )
264 {
265 LL_WARNS("MediaImpl") << "Could not get application directory, not setting GST_PLUGIN_PATH."
266 << LL_ENDL;
267 return;
268 }
269
270 LL_DEBUGS("MediaImpl") << "Imprudence is installed at "
271 << imp_dir << LL_ENDL;
272
273 // ":" on Mac and 'Nix, ";" on Windows
274 std::string separator = G_SEARCHPATH_SEPARATOR_S;
275
276 // Grab the current path, if it's set.
277 std::string old_plugin_path = "";
278 char *old_path = getenv("GST_PLUGIN_PATH");
279 if(old_path == NULL)
280 {
281 LL_DEBUGS("MediaImpl") << "Did not find user-set GST_PLUGIN_PATH."
282 << LL_ENDL;
283 }
284 else
285 {
286 old_plugin_path = separator + std::string( old_path );
287 }
288
289
290 // Search both Imprudence and Imprudence\lib\gstreamer-plugins.
291 // But we also want to search the path the user has set, if any.
292 std::string plugin_path =
293 "GST_PLUGIN_PATH=" +
294#if LL_WINDOWS
295 imp_dir + "\\lib\\gstreamer-plugins" +
296#elif LL_DARWIN
297 imp_dir + separator +
298 imp_dir + "/../Resources/lib/gstreamer-plugins" +
299#endif
300 old_plugin_path;
301
302 int put_result;
303
304 // Place GST_PLUGIN_PATH in the environment settings
305#if LL_WINDOWS
306 put_result = _putenv( (char*)plugin_path.c_str() );
307#elif LL_DARWIN
308 put_result = putenv( (char*)plugin_path.c_str() );
309#endif
310
311 if( put_result == -1 )
312 {
313 LL_WARNS("MediaImpl") << "Setting GST_PLUGIN_PATH failed!" << LL_ENDL;
314 }
315 else
316 {
317 LL_DEBUGS("MediaImpl") << "GST_PLUGIN_PATH set to "
318 << getenv("GST_PLUGIN_PATH") << LL_ENDL;
319 }
248 320
249 // Init our custom plugins - only really need do this once. 321 // Don't load system plugins. We only want to use ours, to avoid conflicts.
250 gst_slvideo_init_class(); 322#if LL_WINDOWS
323 put_result = _putenv( "GST_PLUGIN_SYSTEM_PATH=\"\"" );
324#elif LL_DARWIN
325 put_result = putenv( "GST_PLUGIN_SYSTEM_PATH=\"\"" );
326#endif
327
328 if( put_result == -1 )
329 {
330 LL_WARNS("MediaImpl") << "Setting GST_PLUGIN_SYSTEM_PATH=\"\" failed!"
331 << LL_ENDL;
332 }
333
334#endif // LL_WINDOWS || LL_DARWIN
335}
336
337
338void LLMediaImplGStreamer::gstreamer_log(GstDebugCategory *category,
339 GstDebugLevel level,
340 const gchar *file,
341 const gchar *function,
342 gint line,
343 GObject *object,
344 GstDebugMessage *message,
345 gpointer data)
346{
347 std::stringstream log(std::stringstream::out);
348
349 // Log format example:
350 //
351 // GST_ELEMENT_PADS: removing pad 'sink' (in gstelement.c:757:gst_element_remove_pad)
352 //
353 log << gst_debug_category_get_name( category ) << ": "
354 << gst_debug_message_get(message) << " "
355 << "(in " << file << ":" << line << ":" << function << ")";
251 356
252 mDoneInit = true; 357 switch( level )
358 {
359 case GST_LEVEL_ERROR:
360 LL_WARNS("MediaImpl") << "(ERROR) " << log.str() << LL_ENDL;
361 break;
362 case GST_LEVEL_WARNING:
363 LL_WARNS("MediaImpl") << log.str() << LL_ENDL;
364 break;
365 case GST_LEVEL_DEBUG:
366 LL_DEBUGS("MediaImpl") << log.str() << LL_ENDL;
367 break;
368 case GST_LEVEL_INFO:
369 LL_INFOS("MediaImpl") << log.str() << LL_ENDL;
370 break;
371 default:
372 // Do nothing.
373 break;
253 } 374 }
375}
376
254 377
378bool LLMediaImplGStreamer::closedown()
379{
255 return true; 380 return true;
256} 381}
257 382
258 383
259bool LLMediaImplGStreamer:: 384bool LLMediaImplGStreamer::setDebugLevel( LLMediaBase::EDebugLevel level )
260closedown()
261{ 385{
262 if (!mDoneInit) 386 // Do parent class stuff.
263 return false; // error 387 LLMediaImplCommon::setDebugLevel(level);
264 388
265 ungrab_gst_syms(); 389 // Set GStreamer verbosity.
390 gst_debug_set_default_threshold( (GstDebugLevel)level );
266 391
267 return true; 392 return true;
268} 393}
@@ -270,230 +395,215 @@ closedown()
270 395
271/////////////////////////////////////////////////////////////////////////////// 396///////////////////////////////////////////////////////////////////////////////
272// 397//
398// Uncomment the line below to enable spammy debug data.
273//#define LL_GST_REPORT_STATE_CHANGES 399//#define LL_GST_REPORT_STATE_CHANGES
274#ifdef LL_GST_REPORT_STATE_CHANGES 400#ifdef LL_GST_REPORT_STATE_CHANGES
275static char* get_gst_state_name(GstState state) 401static const char* get_gst_state_name(GstState state)
276{ 402{
277 switch (state) { 403 switch (state)
278 case GST_STATE_VOID_PENDING: return "VOID_PENDING"; 404 {
279 case GST_STATE_NULL: return "NULL"; 405 case GST_STATE_VOID_PENDING: return "VOID_PENDING";
280 case GST_STATE_READY: return "READY"; 406 case GST_STATE_NULL: return "NULL";
281 case GST_STATE_PAUSED: return "PAUSED"; 407 case GST_STATE_READY: return "READY";
282 case GST_STATE_PLAYING: return "PLAYING"; 408 case GST_STATE_PAUSED: return "PAUSED";
409 case GST_STATE_PLAYING: return "PLAYING";
283 } 410 }
284 return "(unknown)"; 411 return "(unknown)";
285} 412}
286#endif // LL_GST_REPORT_STATE_CHANGES 413#endif // LL_GST_REPORT_STATE_CHANGES
287 414
288extern "C" { 415//static
289gboolean 416gboolean LLMediaImplGStreamer::bus_callback(GstBus *bus, GstMessage *message, gpointer data)
290llmediaimplgstreamer_bus_callback (GstBus *bus,
291 GstMessage *message,
292 gpointer data)
293{ 417{
294 if (!message) 418#ifdef LL_GST_REPORT_STATE_CHANGES
295 return TRUE; // shield against GStreamer bug 419 LL_DEBUGS("MediaCallback") << "Got GST message type: " << GST_MESSAGE_TYPE_NAME (message) << LL_ENDL;
296 420#endif
297 if (GST_MESSAGE_TYPE(message) != GST_MESSAGE_STATE_CHANGED &&
298 GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING)
299 {
300 DEBUGMSG("Got GST message type: %s",
301 LLGST_MESSAGE_TYPE_NAME (message));
302 }
303 else
304 {
305 DEBUGMSG("Got GST message type: %s",
306 LLGST_MESSAGE_TYPE_NAME (message));
307 }
308 421
309 LLMediaImplGStreamer *impl = (LLMediaImplGStreamer*)data; 422 LLMediaImplGStreamer *impl = (LLMediaImplGStreamer*)data;
310 423
311 switch (GST_MESSAGE_TYPE (message)) { 424 switch (GST_MESSAGE_TYPE (message))
312 case GST_MESSAGE_BUFFERING: { 425 {
313 // NEEDS GST 0.10.11+ 426 case GST_MESSAGE_BUFFERING:
314 if (llgst_message_parse_buffering)
315 { 427 {
316 gint percent = 0; 428 gint percent = 0;
317 llgst_message_parse_buffering(message, &percent); 429 gst_message_parse_buffering(message, &percent);
318 DEBUGMSG("GST buffering: %d%%", percent); 430#ifdef LL_GST_REPORT_STATE_CHANGES
431 LL_DEBUGS("MediaBuffering") << "GST buffering: " << percent << "%%" << LL_ENDL;
432#endif
319 LLMediaEvent event( impl, percent ); 433 LLMediaEvent event( impl, percent );
320 impl->getEventEmitter().update( &LLMediaObserver::onUpdateProgress, event ); 434 impl->getEventEmitter().update( &LLMediaObserver::onUpdateProgress, event );
321
322 } 435 }
323 break; 436 break;
324 } 437 case GST_MESSAGE_STATE_CHANGED:
325 case GST_MESSAGE_STATE_CHANGED: { 438 {
326 GstState old_state; 439 GstState old_state;
327 GstState new_state; 440 GstState new_state;
328 GstState pending_state; 441 GstState pending_state;
329 llgst_message_parse_state_changed(message, 442 gst_message_parse_state_changed(message,
330 &old_state, 443 &old_state,
331 &new_state, 444 &new_state,
332 &pending_state); 445 &pending_state);
333#ifdef LL_GST_REPORT_STATE_CHANGES 446#ifdef LL_GST_REPORT_STATE_CHANGES
334 // not generally very useful, and rather spammy. 447 // not generally very useful, and rather spammy.
335 DEBUGMSG("state change (old,<new>,pending): %s,<%s>,%s", 448 LL_DEBUGS("MediaState") << "GST state change (old,<new>,pending): "<< get_gst_state_name(old_state) << ",<" << get_gst_state_name(new_state) << ">," << get_gst_state_name(pending_state) << LL_ENDL;
336 get_gst_state_name(old_state),
337 get_gst_state_name(new_state),
338 get_gst_state_name(pending_state));
339#endif // LL_GST_REPORT_STATE_CHANGES 449#endif // LL_GST_REPORT_STATE_CHANGES
340 450
341 switch (new_state) { 451 switch (new_state)
342 case GST_STATE_VOID_PENDING: 452 {
343 break; 453 case GST_STATE_VOID_PENDING:
344 case GST_STATE_NULL: 454 break;
345 break; 455 case GST_STATE_NULL:
346 case GST_STATE_READY: 456#ifdef LL_GST_REPORT_STATE_CHANGES
347 break; 457 LL_DEBUGS("MediaImpl") << "State changed to NULL" << LL_ENDL;
348 case GST_STATE_PAUSED: 458#endif
349 break; 459 if (impl->getState() == GST_STATE_PLAYING)
350 case GST_STATE_PLAYING: 460 {
351 LLMediaEvent event( impl, 100 ); 461 // Stream was probably dropped, trying to restart
352 impl->getEventEmitter().update( &LLMediaObserver::onUpdateProgress, event ); 462 impl->play();
353 // emit an event to say that a media source was loaded 463#ifdef LL_GST_REPORT_STATE_CHANGES
354 LLMediaEvent event2( impl ); 464 LL_DEBUGS("MediaImpl") << "Trying to restart." << LL_ENDL;
355 impl->getEventEmitter().update( &LLMediaObserver::onMediaLoaded, event2 ); 465#endif
466 }
467 break;
468 case GST_STATE_READY:
469 break;
470 case GST_STATE_PAUSED:
471 break;
472 case GST_STATE_PLAYING:
473 LLMediaEvent event( impl, 100 );
474 impl->getEventEmitter().update( &LLMediaObserver::onUpdateProgress, event );
475 // emit an event to say that a media source was loaded
476 LLMediaEvent event2( impl );
477 impl->getEventEmitter().update( &LLMediaObserver::onMediaLoaded, event2 );
478 break;
479 }
356 break; 480 break;
357 } 481 }
358 break; 482 case GST_MESSAGE_ERROR:
359 } 483 {
360 case GST_MESSAGE_ERROR: { 484 GError *err = NULL;
361 GError *err = NULL; 485 gchar *debug = NULL;
362 gchar *debug = NULL;
363 486
364 llgst_message_parse_error (message, &err, &debug); 487 gst_message_parse_error (message, &err, &debug);
365 WARNMSG("GST error: %s", err->message); 488 LL_WARNS("MediaImpl") << "GST Error: " << err->message << LL_ENDL;
366 g_error_free (err); 489 g_error_free (err);
367 g_free (debug); 490 g_free (debug);
368 491
369 impl->addCommand(LLMediaBase::COMMAND_STOP); 492 impl->addCommand(LLMediaBase::COMMAND_STOP);
493 //impl->addCommand(LLMediaBase::COMMAND_START);
370 494
371 break; 495 break;
372 } 496 }
373 case GST_MESSAGE_INFO: { 497 case GST_MESSAGE_INFO:
374 if (llgst_message_parse_info)
375 { 498 {
376 GError *err = NULL; 499 GError *err = NULL;
377 gchar *debug = NULL; 500 gchar *debug = NULL;
378 501
379 llgst_message_parse_info (message, &err, &debug); 502 gst_message_parse_info (message, &err, &debug);
380 INFOMSG("GST info: %s", err->message); 503 LL_INFOS("MediaImpl") << "GST info: " << err->message
504 << LL_ENDL;
381 g_error_free (err); 505 g_error_free (err);
382 g_free (debug); 506 g_free (debug);
507 break;
383 } 508 }
384 break; 509 case GST_MESSAGE_WARNING:
385 } 510 {
386 case GST_MESSAGE_WARNING: { 511 GError *err = NULL;
387 GError *err = NULL; 512 gchar *debug = NULL;
388 gchar *debug = NULL;
389 513
390 llgst_message_parse_warning (message, &err, &debug); 514 gst_message_parse_warning (message, &err, &debug);
391 WARNMSG("GST warning: %s", err->message); 515 LL_WARNS("MediaImpl") << "GST warning: " << err->message
392 g_error_free (err); 516 << LL_ENDL;
393 g_free (debug); 517 g_error_free (err);
518 g_free (debug);
394 519
395 break; 520 break;
396 } 521 }
397 case GST_MESSAGE_EOS: 522 case GST_MESSAGE_TAG:
398 /* end-of-stream */
399 DEBUGMSG("GST end-of-stream.");
400 if (impl->isLooping())
401 { 523 {
402 DEBUGMSG("looping media..."); 524 GstTagList *tag_list;
403 double eos_pos_sec = 0.0F; 525 gchar *title;
404 bool got_eos_position = impl->getTimePos(eos_pos_sec); 526 gchar *artist;
405 527 gst_message_parse_tag(message, &tag_list);
406 if (got_eos_position && eos_pos_sec < impl->MIN_LOOP_SEC) 528 gboolean hazTitle = gst_tag_list_get_string(tag_list,
529 GST_TAG_TITLE, &title);
530 gboolean hazArtist = gst_tag_list_get_string(tag_list,
531 GST_TAG_ARTIST, &artist);
532 if(hazTitle)
533 LL_INFOS("MediaInfo") << "Title: " << title << LL_ENDL;
534 if(hazArtist)
535 LL_INFOS("MediaInfo") << "Artist: " << artist << LL_ENDL;
536 break;
537 }
538 case GST_MESSAGE_EOS:
539 {
540 /* end-of-stream */
541 LL_DEBUGS("MediaImpl") << "GST end-of-stream." << LL_ENDL;
542 if (impl->isLooping())
407 { 543 {
408 // if we know that the movie is really short, don't 544 LL_DEBUGS("MediaImpl") << "looping media..." << LL_ENDL;
409 // loop it else it can easily become a time-hog 545 impl->stop();
410 // because of GStreamer spin-up overhead 546 impl->play();
411 DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec);
412 // inject a COMMAND_PAUSE
413 impl->addCommand(LLMediaBase::COMMAND_PAUSE);
414 } 547 }
415 else 548 else
416 { 549 {
417 // first try looping by an explicit rewind 550 // inject a COMMAND_STOP
418 bool seeksuccess = impl->seek(0.0); 551 impl->addCommand(LLMediaBase::COMMAND_STOP);
419 if (seeksuccess)
420 {
421 impl->play();
422 }
423 else // use clumsy stop-start to loop
424 {
425 DEBUGMSG("couldn't loop by rewinding - stopping and starting instead...");
426 impl->stop();
427 impl->play();
428 }
429 } 552 }
553 break;
554 default:
555 /* unhandled message */
556 break;
430 } 557 }
431 else // not a looping media
432 {
433 // inject a COMMAND_STOP
434 impl->addCommand(LLMediaBase::COMMAND_STOP);
435 }
436 break;
437 default:
438 /* unhandled message */
439 break;
440 } 558 }
441
442 /* we want to be notified again the next time there is a message 559 /* we want to be notified again the next time there is a message
443 * on the bus, so return true (false means we want to stop watching 560 * on the bus, so return true (false means we want to stop watching
444 * for messages on the bus and our callback should not be called again) 561 * for messages on the bus and our callback should not be called again)
445 */ 562 */
446 return TRUE; 563 return TRUE;
447} 564}
448} // extern "C"
449 565
450/////////////////////////////////////////////////////////// 566///////////////////////////////////////////////////////////
451// virtual 567// virtual
452bool 568bool LLMediaImplGStreamer::navigateTo (const std::string urlIn)
453LLMediaImplGStreamer::
454navigateTo ( const std::string urlIn )
455{ 569{
456 if (!mDoneInit) 570 LL_DEBUGS("MediaImpl") << "Setting media URI: " << urlIn.c_str()
457 return false; // error 571 << LL_ENDL;
458
459 DEBUGMSG("Setting media URI: %s", urlIn.c_str());
460 572
461 if (NULL == mPump || 573 if (mPump == NULL || mPlaybin == NULL)
462 NULL == mPlaybin)
463 { 574 {
464 return false; // error 575 return false;
465 } 576 }
466 577
467 setStatus( LLMediaBase::STATUS_NAVIGATING ); 578 setStatus( LLMediaBase::STATUS_NAVIGATING );
468 579
469 // set URI 580 // set URI
470 g_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), NULL); 581 g_object_set (G_OBJECT (mPlaybin), "uri", urlIn.c_str(), NULL);
471 //g_object_set (G_OBJECT (mPlaybin), "uri", "file:///tmp/movie", NULL);
472 582
473 // navigateTo implicitly plays, too. 583 // get playbin's bus - perhaps this can/should be done in ctor
474 play(); 584 GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mPlaybin));
585 if (!bus)
586 {
587 return false;
588 }
589 gst_bus_add_watch (bus, bus_callback, this);
590 gst_object_unref (bus);
591
592 mState = GST_STATE_READY;
475 593
476 return true; 594 return true;
477} 595}
478 596
479/////////////////////////////////////////////////////////////////////////////// 597///////////////////////////////////////////////////////////////////////////////
480// 598//
481bool 599bool LLMediaImplGStreamer::unload()
482LLMediaImplGStreamer::
483unload ()
484{ 600{
485 if (!mDoneInit) 601 LL_DEBUGS("MediaImpl") << "unloading media..." << LL_ENDL;
486 return false; // error
487
488 DEBUGMSG("unloading media...");
489
490 // stop getting callbacks for this bus
491 g_source_remove(mBusWatchID);
492
493 if (mPlaybin) 602 if (mPlaybin)
494 { 603 {
495 llgst_element_set_state (mPlaybin, GST_STATE_NULL); 604 gst_element_set_state (mPlaybin, GST_STATE_NULL);
496 llgst_object_unref (GST_OBJECT (mPlaybin)); 605 mState = GST_STATE_NULL;
606 gst_object_unref (GST_OBJECT (mPlaybin));
497 mPlaybin = NULL; 607 mPlaybin = NULL;
498 } 608 }
499 609
@@ -510,63 +620,63 @@ unload ()
510 } 620 }
511 621
512 mVideoSink = NULL; 622 mVideoSink = NULL;
623 mState = GST_STATE_NULL;
624 setStatus(LLMediaBase::STATUS_UNKNOWN);
513 625
514 return true; 626 return true;
515} 627}
516 628
517/////////////////////////////////////////////////////////////////////////////// 629///////////////////////////////////////////////////////////////////////////////
518// virtual 630// virtual
519bool 631bool LLMediaImplGStreamer::updateMedia()
520LLMediaImplGStreamer::
521updateMedia ()
522{ 632{
523 if (!mDoneInit) 633 //LL_DEBUGS("MediaImpl") << "updating media..." << LL_ENDL;
524 return false; // error
525
526 DEBUGMSG("updating media...");
527 634
528 // sanity check 635 // sanity check
529 if (NULL == mPump || 636 if (mPump == NULL || mPlaybin == NULL)
530 NULL == mPlaybin)
531 { 637 {
532 DEBUGMSG("dead media..."); 638#ifdef LL_GST_REPORT_STATE_CHANGES
639 LL_DEBUGS("MediaImpl") << "dead media..." << LL_ENDL;
640#endif
641 mState = GST_STATE_NULL;
642 setStatus(LLMediaBase::STATUS_DEAD);
533 return false; 643 return false;
534 } 644 }
535 645
646 if (mState == GST_STATE_VOID_PENDING || mState == GST_STATE_NULL)
647 return false;
648
536 // process next outstanding command 649 // process next outstanding command
537 switch (nextCommand()) 650 switch (nextCommand())
538 { 651 {
539 case LLMediaBase::COMMAND_START: 652 case LLMediaBase::COMMAND_START:
540 DEBUGMSG("COMMAND_START"); 653 LL_DEBUGS("MediaImpl") << "COMMAND_START" << LL_ENDL;
541 if (getStatus() == LLMediaBase::STATUS_PAUSED || 654 if (getStatus() == LLMediaBase::STATUS_PAUSED ||
542 getStatus() == LLMediaBase::STATUS_NAVIGATING || 655 getStatus() == LLMediaBase::STATUS_NAVIGATING ||
543 getStatus() == LLMediaBase::STATUS_STOPPED) 656 getStatus() == LLMediaBase::STATUS_STOPPED)
544 { 657 {
545 DEBUGMSG("doing COMMAND_START");
546 play(); 658 play();
547 setStatus(LLMediaBase::STATUS_STARTED); 659 setStatus(LLMediaBase::STATUS_STARTED);
548 clearCommand(); 660 clearCommand();
549 } 661 }
550 break; 662 break;
551 case LLMediaBase::COMMAND_STOP: 663 case LLMediaBase::COMMAND_STOP:
552 DEBUGMSG("COMMAND_STOP"); 664 LL_DEBUGS("MediaImpl") << "COMMAND_STOP" << LL_ENDL;
553 DEBUGMSG("doing COMMAND_STOP");
554 stop(); 665 stop();
555 setStatus(LLMediaBase::STATUS_STOPPED); 666 setStatus(LLMediaBase::STATUS_STOPPED);
556 clearCommand(); 667 clearCommand();
557 break; 668 break;
558 case LLMediaBase::COMMAND_PAUSE: 669 case LLMediaBase::COMMAND_PAUSE:
559 DEBUGMSG("COMMAND_PAUSE"); 670 LL_DEBUGS("MediaImpl") << "COMMAND_PAUSE" << LL_ENDL;
560 if (getStatus() == LLMediaBase::STATUS_STARTED) 671 if (getStatus() == LLMediaBase::STATUS_STARTED)
561 { 672 {
562 DEBUGMSG("doing COMMAND_PAUSE");
563 pause(); 673 pause();
564 setStatus(LLMediaBase::STATUS_PAUSED); 674 setStatus(LLMediaBase::STATUS_PAUSED);
565 clearCommand(); 675 clearCommand();
566 } 676 }
567 break; 677 break;
568 default: 678 default:
569 DEBUGMSG("COMMAND_?"); 679 LL_INFOS("MediaImpl") << "Unknown command" << LL_ENDL;
570 clearCommand(); 680 clearCommand();
571 break; 681 break;
572 case LLMediaBase::COMMAND_NONE: 682 case LLMediaBase::COMMAND_NONE:
@@ -584,12 +694,14 @@ updateMedia ()
584 GST_OBJECT_LOCK(mVideoSink); 694 GST_OBJECT_LOCK(mVideoSink);
585 if (mVideoSink->retained_frame_ready) 695 if (mVideoSink->retained_frame_ready)
586 { 696 {
587 DEBUGMSG("NEW FRAME "); 697#ifdef LL_GST_REPORT_STATE_CHANGES
698 LL_DEBUGS("MediaImpl") <<"NEW FRAME " << LL_ENDL;
699#endif
588 if (mVideoSink->retained_frame_width != getMediaWidth() || 700 if (mVideoSink->retained_frame_width != getMediaWidth() ||
589 mVideoSink->retained_frame_height != getMediaHeight()) 701 mVideoSink->retained_frame_height != getMediaHeight())
590 // *TODO: also check for change in format 702 // *TODO: also check for change in format
591 { 703 {
592 // just resize container 704 // just resize containe
593 int neww = mVideoSink->retained_frame_width; 705 int neww = mVideoSink->retained_frame_width;
594 int newh = mVideoSink->retained_frame_height; 706 int newh = mVideoSink->retained_frame_height;
595 int newd = SLVPixelFormatBytes[mVideoSink->retained_frame_format]; 707 int newd = SLVPixelFormatBytes[mVideoSink->retained_frame_format];
@@ -604,8 +716,9 @@ updateMedia ()
604 mTextureFormatType = LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV; 716 mTextureFormatType = LL_MEDIA_UNSIGNED_INT_8_8_8_8_REV;
605 } 717 }
606 mMediaRowbytes = neww * newd; 718 mMediaRowbytes = neww * newd;
607 DEBUGMSG("video container resized to %dx%d", 719 LL_DEBUGS("MediaImpl")
608 neww, newh); 720 << "video container resized to " <<
721 neww <<"x"<< newh << LL_ENDL;
609 722
610 delete[] mediaData; 723 delete[] mediaData;
611 mediaData = new unsigned char[mMediaRowbytes * 724 mediaData = new unsigned char[mMediaRowbytes *
@@ -641,46 +754,119 @@ updateMedia ()
641 754
642/////////////////////////////////////////////////////////////////////////////// 755///////////////////////////////////////////////////////////////////////////////
643// 756//
644bool 757bool LLMediaImplGStreamer::stop()
645LLMediaImplGStreamer::
646stop ()
647{ 758{
648 DEBUGMSG("stopping media..."); 759 LL_DEBUGS("MediaImpl") << "attempting to stop..." << LL_ENDL;
649 // todo: error-check this? 760
650 llgst_element_set_state(mPlaybin, GST_STATE_READY); 761 if (!mPlaybin || mState == GST_STATE_NULL)
651 return true; 762 return true;
763
764 GstStateChangeReturn state_change;
765
766 state_change = gst_element_set_state(mPlaybin, GST_STATE_READY);
767
768 LL_DEBUGS("MediaImpl") << gst_element_state_change_return_get_name(state_change) << LL_ENDL;
769
770 if (state_change == GST_STATE_CHANGE_FAILURE)
771 {
772 LL_WARNS("MediaImpl") << "could not stop stream!" << LL_ENDL;
773 return false;
774 }
775 else
776 {
777 // Going into pending after play keeps dead streams from looping
778 (mState == GST_STATE_PLAYING) ? (mState = GST_STATE_VOID_PENDING) : (mState = GST_STATE_READY);
779 return true;
780 }
652} 781}
653 782
654/////////////////////////////////////////////////////////////////////////////// 783///////////////////////////////////////////////////////////////////////////////
655// 784//
656bool 785bool LLMediaImplGStreamer::play()
657LLMediaImplGStreamer::
658play ()
659{ 786{
660 DEBUGMSG("playing media..."); 787 LL_DEBUGS("MediaImpl") << "attempting to play..." << LL_ENDL;
661 // todo: error-check this? 788
662 llgst_element_set_state(mPlaybin, GST_STATE_PLAYING); 789 if (!mPlaybin || mState == GST_STATE_NULL)
790 return true;
791
792
793 if( getState() == GST_STATE_PLAYING )
794 {
795 LL_DEBUGS("MediaImpl") << "... but already playing." << LL_ENDL;
796 return true;
797 }
798
799 // Clean up the existing thread, if any.
800 if( mPlayThread != NULL && mPlayThread->isStopped())
801 {
802 delete mPlayThread;
803 mPlayThread = NULL;
804 }
805
806 if( mPlayThread == NULL )
807 {
808 // Make a new thread to start playing. This keeps the viewer
809 // responsive while the stream is resolved and buffered.
810 mPlayThread = new LLGstPlayThread( (LLMediaImplCommon *)this, "GstPlayThread", NULL);
811 mPlayThread->start();
812 }
813
663 return true; 814 return true;
664} 815}
665 816
817
818void LLMediaImplGStreamer::startPlay()
819{
820 GstStateChangeReturn state_change;
821
822 state_change = gst_element_set_state(mPlaybin, GST_STATE_PLAYING);
823 mState = GST_STATE_PLAYING;
824
825 LL_DEBUGS("MediaImpl") << gst_element_state_change_return_get_name(state_change) << LL_ENDL;
826
827 // Check to make sure playing was successful. If not, stop.
828 // NOTE: state_change is almost always GST_STATE_CHANGE_ASYNC
829 if (state_change == GST_STATE_CHANGE_FAILURE)
830 {
831 // If failing from a bad stream, go into an unknown
832 // state to stop bus_callback from looping back.
833 // We also force a stop in case the operations don't sync
834 setStatus(LLMediaBase::STATUS_UNKNOWN);
835 stop();
836 }
837}
838
666/////////////////////////////////////////////////////////////////////////////// 839///////////////////////////////////////////////////////////////////////////////
667// 840//
668bool 841bool LLMediaImplGStreamer::pause()
669LLMediaImplGStreamer::
670pause ()
671{ 842{
672 DEBUGMSG("pausing media..."); 843 LL_DEBUGS("MediaImpl") << "attempting to pause..." << LL_ENDL;
673 // todo: error-check this? 844
674 llgst_element_set_state(mPlaybin, GST_STATE_PAUSED); 845 if (!mPlaybin || mState == GST_STATE_NULL)
675 return true; 846 return true;
847
848 GstStateChangeReturn state_change;
849
850 state_change = gst_element_set_state(mPlaybin, GST_STATE_PAUSED);
851
852 LL_DEBUGS("MediaImpl") << gst_element_state_change_return_get_name(state_change) << LL_ENDL;
853
854 if (state_change == GST_STATE_CHANGE_FAILURE)
855 {
856 LL_WARNS("MediaImpl") << "could not pause stream!" << LL_ENDL;
857 return false;
858 }
859 else
860 {
861 mState = GST_STATE_PAUSED;
862 return true;
863 }
676}; 864};
677 865
678 866
679/////////////////////////////////////////////////////////////////////////////// 867///////////////////////////////////////////////////////////////////////////////
680// virtual 868// virtual
681unsigned char* 869unsigned char* LLMediaImplGStreamer::getMediaData()
682LLMediaImplGStreamer::
683getMediaData ()
684{ 870{
685 return mediaData; 871 return mediaData;
686} 872}
@@ -688,73 +874,26 @@ getMediaData ()
688 874
689/////////////////////////////////////////////////////////////////////////////// 875///////////////////////////////////////////////////////////////////////////////
690// virtual 876// virtual
691bool 877bool LLMediaImplGStreamer::seek(double time)
692LLMediaImplGStreamer::
693seek( double time )
694{ 878{
695 bool success = false; 879 bool success = false;
696 if (mDoneInit && mPlaybin) 880 if (mPlaybin)
697 { 881 {
698 success = llgst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME, 882 success = gst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME,
699 GstSeekFlags(GST_SEEK_FLAG_FLUSH | 883 GstSeekFlags(GST_SEEK_FLAG_FLUSH |
700 GST_SEEK_FLAG_KEY_UNIT), 884 GST_SEEK_FLAG_KEY_UNIT),
701 GST_SEEK_TYPE_SET, gint64(time*GST_SECOND), 885 GST_SEEK_TYPE_SET, gint64(time*1000000000.0F),
702 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE); 886 GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE);
703 } 887 }
704 DEBUGMSG("MEDIA SEEK REQUEST to %fsec result was %d", 888 LL_DEBUGS("MediaImpl") << "MEDIA SEEK REQUEST to " << float(time)
705 float(time), int(success)); 889 << "sec result was " << int(success) << LL_ENDL;
706 return success; 890 return success;
707} 891}
708 892
709bool
710LLMediaImplGStreamer::
711getTimePos(double &sec_out)
712{
713 bool got_position = false;
714 if (mPlaybin)
715 {
716 gint64 pos;
717 GstFormat timefmt = GST_FORMAT_TIME;
718 got_position =
719 llgst_element_query_position &&
720 llgst_element_query_position(mPlaybin,
721 &timefmt,
722 &pos);
723 got_position = got_position
724 && (timefmt == GST_FORMAT_TIME);
725 // GStreamer may have other ideas, but we consider the current position
726 // undefined if not PLAYING or PAUSED
727 got_position = got_position &&
728 (GST_STATE(mPlaybin) == GST_STATE_PLAYING ||
729 GST_STATE(mPlaybin) == GST_STATE_PAUSED);
730 if (got_position && !GST_CLOCK_TIME_IS_VALID(pos))
731 {
732 if (GST_STATE(mPlaybin) == GST_STATE_PLAYING)
733 {
734 // if we're playing then we treat an invalid clock time
735 // as 0, for complicated reasons (insert reason here)
736 pos = 0;
737 }
738 else
739 {
740 got_position = false;
741 }
742
743 }
744 // If all the preconditions succeeded... we can trust the result.
745 if (got_position)
746 {
747 sec_out = double(pos) / double(GST_SECOND); // gst to sec
748 }
749 }
750 return got_position;
751}
752 893
753/////////////////////////////////////////////////////////////////////////////// 894///////////////////////////////////////////////////////////////////////////////
754// virtual 895// virtual
755bool 896bool LLMediaImplGStreamer::setVolume(float volume)
756LLMediaImplGStreamer::
757setVolume(float volume)
758{ 897{
759 // we try to only update volume as conservatively as 898 // we try to only update volume as conservatively as
760 // possible, as many gst-plugins-base versions up to at least 899 // possible, as many gst-plugins-base versions up to at least
@@ -763,7 +902,7 @@ setVolume(float volume)
763 return true; // nothing to do, everything's fine 902 return true; // nothing to do, everything's fine
764 903
765 mVolume = volume; 904 mVolume = volume;
766 if (mDoneInit && mPlaybin) 905 if (mPlaybin)
767 { 906 {
768 g_object_set(mPlaybin, "volume", mVolume, NULL); 907 g_object_set(mPlaybin, "volume", mVolume, NULL);
769 return true; 908 return true;
@@ -772,4 +911,6 @@ setVolume(float volume)
772 return false; 911 return false;
773} 912}
774 913
775#endif // LL_GSTREAMER_ENABLED 914
915
916///#endif // LL_GSTREAMER_ENABLED
diff --git a/linden/indra/llmedia/llmediaimplgstreamer.h b/linden/indra/llmedia/llmediaimplgstreamer.h
index 07b698d..baefdaf 100644
--- a/linden/indra/llmedia/llmediaimplgstreamer.h
+++ b/linden/indra/llmedia/llmediaimplgstreamer.h
@@ -18,8 +18,7 @@
18 * There are special exceptions to the terms and conditions of the GPL as 18 * There are special exceptions to the terms and conditions of the GPL as
19 * it is applied to this Source Code. View the full text of the exception 19 * it is applied to this Source Code. View the full text of the exception
20 * in the file doc/FLOSS-exception.txt in this software distribution, or 20 * in the file doc/FLOSS-exception.txt in this software distribution, or
21 * online at 21 * online at http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
23 * 22 *
24 * By copying, modifying or distributing this software, you acknowledge 23 * By copying, modifying or distributing this software, you acknowledge
25 * that you have read and understood your obligations described above, 24 * that you have read and understood your obligations described above,
@@ -38,7 +37,7 @@
38#include "llmediaimplcommon.h" 37#include "llmediaimplcommon.h"
39#include "llmediaimplfactory.h" 38#include "llmediaimplfactory.h"
40 39
41#if LL_GSTREAMER_ENABLED 40///#if LL_GSTREAMER_ENABLED
42 41
43extern "C" { 42extern "C" {
44#include <stdio.h> 43#include <stdio.h>
@@ -49,6 +48,7 @@ extern "C" {
49} 48}
50 49
51#include "llmediaimplgstreamervidplug.h" 50#include "llmediaimplgstreamervidplug.h"
51#include "llgstplaythread.h"
52 52
53class LLMediaManagerData; 53class LLMediaManagerData;
54class LLMediaImplMaker; 54class LLMediaImplMaker;
@@ -57,6 +57,8 @@ class LLMediaImplMaker;
57class LLMediaImplGStreamer: 57class LLMediaImplGStreamer:
58 public LLMediaImplCommon 58 public LLMediaImplCommon
59{ 59{
60 friend class LLGstPlayThread;
61
60 public: 62 public:
61 LLMediaImplGStreamer (); 63 LLMediaImplGStreamer ();
62 virtual ~LLMediaImplGStreamer (); 64 virtual ~LLMediaImplGStreamer ();
@@ -67,6 +69,26 @@ class LLMediaImplGStreamer:
67 static bool startup( LLMediaManagerData* init_data ); 69 static bool startup( LLMediaManagerData* init_data );
68 static bool closedown(); 70 static bool closedown();
69 71
72 // Sets GST_PLUGIN_PATH env var for GStreamer.
73 static void set_gst_plugin_path();
74
75 /* virtual */ bool setDebugLevel( LLMediaBase::EDebugLevel level );
76
77 // Function given to GStreamer for handling debug messages
78 static void gstreamer_log(GstDebugCategory *category,
79 GstDebugLevel level,
80 const gchar *file,
81 const gchar *function,
82 gint line,
83 GObject *object,
84 GstDebugMessage *message,
85 gpointer data)
86#if __GNUC__
87 // recommended by the gstreamer docs
88 G_GNUC_NO_INSTRUMENT
89#endif
90 ;
91
70 /* virtual */ std::string getVersion(); 92 /* virtual */ std::string getVersion();
71 /* virtual */ bool navigateTo( const std::string url ); 93 /* virtual */ bool navigateTo( const std::string url );
72 /* virtual */ bool updateMedia(); 94 /* virtual */ bool updateMedia();
@@ -75,50 +97,50 @@ class LLMediaImplGStreamer:
75 /* virtual */ int getTextureFormatType() const; 97 /* virtual */ int getTextureFormatType() const;
76 /* virtual */ int getTextureFormatInternal() const; 98 /* virtual */ int getTextureFormatInternal() const;
77 /* virtual */ bool seek( double time ); 99 /* virtual */ bool seek( double time );
78 /* virtual */ bool setVolume( float volume ); 100 /* virtual */ bool setVolume( float volume );
101
102 LLMediaEmitter< LLMediaObserver > getEventEmitter() const {return mEventEmitter;};
79 103
80 LLMediaEmitter< LLMediaObserver > getEventEmitter() const {return mEventEmitter;}; 104 protected:
105
106 void startPlay();
81 107
82 // misc
83 bool pause();
84 bool stop();
85 bool play();
86 bool getTimePos(double &sec_out);
87 static const double MIN_LOOP_SEC = 1.0F;
88 108
89 private: 109 private:
90 bool unload();
91 110
92 static bool mDoneInit; 111 // misc
112 bool unload();
113 bool pause();
114 bool stop();
115 bool play();
93 116
94 guint mBusWatchID; 117 static gboolean bus_callback (GstBus *bus,
118 GstMessage *message,
119 gpointer data);
95 120
96 unsigned char* mediaData; 121 unsigned char* mediaData;
97 int mMediaRowbytes; 122 int mMediaRowbytes;
98 123 int mTextureFormatPrimary;
99 int mTextureFormatPrimary; 124 int mTextureFormatType;
100 int mTextureFormatType;
101 125
102 // Very GStreamer-specific 126 // GStreamer-specific
103 GMainLoop *mPump; // event pump for this media 127 GMainLoop *mPump; // event pump for this media
104 GstElement *mPlaybin; 128 GstElement *mPlaybin;
105 GstSLVideo *mVideoSink; 129 GstSLVideo *mVideoSink;
106}; 130 GstState mState;
131 GstState getState() const { return mState; }
107 132
108extern "C" { 133 LLGstPlayThread *mPlayThread;
109gboolean llmediaimplgstreamer_bus_callback (GstBus *bus, 134};
110 GstMessage *message,
111 gpointer data);
112}
113 135
114class LLMediaImplGStreamerMaker : public LLMediaImplMaker 136class LLMediaImplGStreamerMaker : public LLMediaImplMaker
115{ 137{
116public: 138 public:
117 LLMediaImplGStreamerMaker(); 139 LLMediaImplGStreamerMaker();
118 LLMediaImplGStreamer* create() 140 LLMediaImplGStreamer* create()
119 { 141 {
120 return new LLMediaImplGStreamer(); 142 return new LLMediaImplGStreamer();
121 } 143 }
122}; 144};
123 145
124///////////////////////////////////////////////////////////////////////// 146/////////////////////////////////////////////////////////////////////////
@@ -135,6 +157,6 @@ public:
135#define WARNMSG STDERRMSG 157#define WARNMSG STDERRMSG
136///////////////////////////////////////////////////////////////////////// 158/////////////////////////////////////////////////////////////////////////
137 159
138#endif // LL_GSTREAMER_ENABLED 160///#endif // LL_GSTREAMER_ENABLED
139 161
140#endif // llmediaimplgstreamer_h 162#endif // llmediaimplgstreamer_h
diff --git a/linden/indra/llmedia/llmediaimplgstreamer_syms.cpp b/linden/indra/llmedia/llmediaimplgstreamer_syms.cpp
deleted file mode 100644
index db26dda..0000000
--- a/linden/indra/llmedia/llmediaimplgstreamer_syms.cpp
+++ /dev/null
@@ -1,169 +0,0 @@
1/**
2 * @file llmediaimplgstreamer_syms.cpp
3 * @brief dynamic GStreamer symbol-grabbing code
4 *
5 * $LicenseInfo:firstyear=2007&license=viewergpl$
6 *
7 * Copyright (c) 2007-2009, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at
21 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 *
23 * By copying, modifying or distributing this software, you acknowledge
24 * that you have read and understood your obligations described above,
25 * and agree to abide by those obligations.
26 *
27 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
28 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
29 * COMPLETENESS OR PERFORMANCE.
30 * $/LicenseInfo$
31 */
32
33#if LL_GSTREAMER_ENABLED
34
35extern "C" {
36#include <gst/gst.h>
37
38#include "apr_pools.h"
39#include "apr_dso.h"
40}
41
42#include "llmediaimplgstreamer.h"
43
44#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) RTN (*ll##GSTSYM)(__VA_ARGS__) = NULL
45#include "llmediaimplgstreamer_syms_raw.inc"
46#include "llmediaimplgstreamer_syms_rawv.inc"
47#undef LL_GST_SYM
48
49// a couple of stubs for disgusting reasons
50GstDebugCategory*
51ll_gst_debug_category_new(gchar *name, guint color, gchar *description)
52{
53 static GstDebugCategory dummy;
54 return &dummy;
55}
56void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname)
57{
58}
59
60static bool sSymsGrabbed = false;
61static apr_pool_t *sSymGSTDSOMemoryPool = NULL;
62static apr_dso_handle_t *sSymGSTDSOHandleG = NULL;
63static apr_dso_handle_t *sSymGSTDSOHandleV = NULL;
64
65
66bool grab_gst_syms(std::string gst_dso_name,
67 std::string gst_dso_name_vid)
68{
69 if (sSymsGrabbed)
70 {
71 // already have grabbed good syms
72 return TRUE;
73 }
74
75 bool sym_error = false;
76 bool rtn = false;
77 apr_status_t rv;
78 apr_dso_handle_t *sSymGSTDSOHandle = NULL;
79
80#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{rv = apr_dso_sym((apr_dso_handle_sym_t*)&ll##GSTSYM, sSymGSTDSOHandle, #GSTSYM); if (rv != APR_SUCCESS) {INFOMSG("Failed to grab symbol: %s", #GSTSYM); if (REQ) sym_error = true;} else DEBUGMSG("grabbed symbol: %s from %p", #GSTSYM, (void*)ll##GSTSYM);}while(0)
81
82 //attempt to load the shared libraries
83 apr_pool_create(&sSymGSTDSOMemoryPool, NULL);
84
85 if ( APR_SUCCESS == (rv = apr_dso_load(&sSymGSTDSOHandle,
86 gst_dso_name.c_str(),
87 sSymGSTDSOMemoryPool) ))
88 {
89 INFOMSG("Found DSO: %s", gst_dso_name.c_str());
90#include "llmediaimplgstreamer_syms_raw.inc"
91
92 if ( sSymGSTDSOHandle )
93 {
94 sSymGSTDSOHandleG = sSymGSTDSOHandle;
95 sSymGSTDSOHandle = NULL;
96 }
97
98 if ( APR_SUCCESS ==
99 (rv = apr_dso_load(&sSymGSTDSOHandle,
100 gst_dso_name_vid.c_str(),
101 sSymGSTDSOMemoryPool) ))
102 {
103 INFOMSG("Found DSO: %s", gst_dso_name_vid.c_str());
104#include "llmediaimplgstreamer_syms_rawv.inc"
105 rtn = !sym_error;
106 }
107 else
108 {
109 INFOMSG("Couldn't load DSO: %s", gst_dso_name_vid.c_str());
110 rtn = false; // failure
111 }
112 }
113 else
114 {
115 INFOMSG("Couldn't load DSO: %s", gst_dso_name.c_str());
116 rtn = false; // failure
117 }
118
119 if (sym_error)
120 {
121 WARNMSG("Failed to find necessary symbols in GStreamer libraries.");
122 }
123
124 if ( sSymGSTDSOHandle )
125 {
126 sSymGSTDSOHandleV = sSymGSTDSOHandle;
127 sSymGSTDSOHandle = NULL;
128 }
129#undef LL_GST_SYM
130
131 sSymsGrabbed = !!rtn;
132 return rtn;
133}
134
135
136void ungrab_gst_syms()
137{
138 // should be safe to call regardless of whether we've
139 // actually grabbed syms.
140
141 if ( sSymGSTDSOHandleG )
142 {
143 apr_dso_unload(sSymGSTDSOHandleG);
144 sSymGSTDSOHandleG = NULL;
145 }
146
147 if ( sSymGSTDSOHandleV )
148 {
149 apr_dso_unload(sSymGSTDSOHandleV);
150 sSymGSTDSOHandleV = NULL;
151 }
152
153 if ( sSymGSTDSOMemoryPool )
154 {
155 apr_pool_destroy(sSymGSTDSOMemoryPool);
156 sSymGSTDSOMemoryPool = NULL;
157 }
158
159 // NULL-out all of the symbols we'd grabbed
160#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{ll##GSTSYM = NULL;}while(0)
161#include "llmediaimplgstreamer_syms_raw.inc"
162#include "llmediaimplgstreamer_syms_rawv.inc"
163#undef LL_GST_SYM
164
165 sSymsGrabbed = false;
166}
167
168
169#endif // LL_GSTREAMER_ENABLED
diff --git a/linden/indra/llmedia/llmediaimplgstreamer_syms.h b/linden/indra/llmedia/llmediaimplgstreamer_syms.h
deleted file mode 100644
index 4220bdb..0000000
--- a/linden/indra/llmedia/llmediaimplgstreamer_syms.h
+++ /dev/null
@@ -1,78 +0,0 @@
1/**
2 * @file llmediaimplgstreamer_syms.h
3 * @brief dynamic GStreamer symbol-grabbing code
4 *
5 * $LicenseInfo:firstyear=2007&license=viewergpl$
6 *
7 * Copyright (c) 2007-2009, Linden Research, Inc.
8 *
9 * Second Life Viewer Source Code
10 * The source code in this file ("Source Code") is provided by Linden Lab
11 * to you under the terms of the GNU General Public License, version 2.0
12 * ("GPL"), unless you have obtained a separate licensing agreement
13 * ("Other License"), formally executed by you and Linden Lab. Terms of
14 * the GPL can be found in doc/GPL-license.txt in this distribution, or
15 * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
16 *
17 * There are special exceptions to the terms and conditions of the GPL as
18 * it is applied to this Source Code. View the full text of the exception
19 * in the file doc/FLOSS-exception.txt in this software distribution, or
20 * online at
21 * http://secondlifegrid.net/programs/open_source/licensing/flossexception
22 *
23 * By copying, modifying or distributing this software, you acknowledge
24 * that you have read and understood your obligations described above,
25 * and agree to abide by those obligations.
26 *
27 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
28 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
29 * COMPLETENESS OR PERFORMANCE.
30 * $/LicenseInfo$
31 */
32
33#include "linden_common.h"
34
35#if LL_GSTREAMER_ENABLED
36
37extern "C" {
38#include <gst/gst.h>
39}
40
41bool grab_gst_syms(std::string gst_dso_name,
42 std::string gst_dso_name_vid);
43void ungrab_gst_syms();
44
45#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) extern RTN (*ll##GSTSYM)(__VA_ARGS__)
46#include "llmediaimplgstreamer_syms_raw.inc"
47#include "llmediaimplgstreamer_syms_rawv.inc"
48#undef LL_GST_SYM
49
50// regrettable hacks to give us better runtime compatibility with older systems
51#define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0)
52#define llg_return_val_if_fail(COND,V) do{if (!(COND)) return V;}while(0)
53
54// regrettable hacks because GStreamer was not designed for runtime loading
55#undef GST_TYPE_MESSAGE
56#define GST_TYPE_MESSAGE (llgst_message_get_type())
57#undef GST_TYPE_OBJECT
58#define GST_TYPE_OBJECT (llgst_object_get_type())
59#undef GST_TYPE_PIPELINE
60#define GST_TYPE_PIPELINE (llgst_pipeline_get_type())
61#undef GST_TYPE_ELEMENT
62#define GST_TYPE_ELEMENT (llgst_element_get_type())
63#undef GST_TYPE_VIDEO_SINK
64#define GST_TYPE_VIDEO_SINK (llgst_video_sink_get_type())
65// more regrettable hacks to stub-out these .h-exposed GStreamer internals
66void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname);
67#undef _gst_debug_register_funcptr
68#define _gst_debug_register_funcptr ll_gst_debug_register_funcptr
69GstDebugCategory* ll_gst_debug_category_new(gchar *name, guint color, gchar *description);
70#undef _gst_debug_category_new
71#define _gst_debug_category_new ll_gst_debug_category_new
72#undef __gst_debug_enabled
73#define __gst_debug_enabled (0)
74
75// more hacks
76#define LLGST_MESSAGE_TYPE_NAME(M) (llgst_message_type_get_name(GST_MESSAGE_TYPE(M)))
77
78#endif // LL_GSTREAMER_ENABLED
diff --git a/linden/indra/llmedia/llmediaimplgstreamer_syms_raw.inc b/linden/indra/llmedia/llmediaimplgstreamer_syms_raw.inc
deleted file mode 100644
index b81872a..0000000
--- a/linden/indra/llmedia/llmediaimplgstreamer_syms_raw.inc
+++ /dev/null
@@ -1,46 +0,0 @@
1
2// required symbols to grab
3LL_GST_SYM(true, gst_init_check, gboolean, int *argc, char **argv[], GError ** err);
4LL_GST_SYM(true, gst_message_get_type, GType, void);
5LL_GST_SYM(true, gst_message_type_get_name, const gchar*, GstMessageType type);
6LL_GST_SYM(true, gst_message_parse_error, void, GstMessage *message, GError **gerror, gchar **debug);
7LL_GST_SYM(true, gst_message_parse_warning, void, GstMessage *message, GError **gerror, gchar **debug);
8LL_GST_SYM(true, gst_message_parse_state_changed, void, GstMessage *message, GstState *oldstate, GstState *newstate, GstState *pending);
9LL_GST_SYM(true, gst_element_set_state, GstStateChangeReturn, GstElement *element, GstState state);
10LL_GST_SYM(true, gst_object_unref, void, gpointer object);
11LL_GST_SYM(true, gst_object_get_type, GType, void);
12LL_GST_SYM(true, gst_pipeline_get_type, GType, void);
13LL_GST_SYM(true, gst_pipeline_get_bus, GstBus*, GstPipeline *pipeline);
14LL_GST_SYM(true, gst_bus_add_watch, guint, GstBus * bus, GstBusFunc func, gpointer user_data);
15LL_GST_SYM(true, gst_element_factory_make, GstElement*, const gchar *factoryname, const gchar *name);
16LL_GST_SYM(true, gst_element_get_type, GType, void);
17LL_GST_SYM(true, gst_static_pad_template_get, GstPadTemplate*, GstStaticPadTemplate *pad_template);
18LL_GST_SYM(true, gst_element_class_add_pad_template, void, GstElementClass *klass, GstPadTemplate *temp);
19LL_GST_SYM(true, gst_element_class_set_details, void, GstElementClass *klass, const GstElementDetails *details);
20LL_GST_SYM(true, gst_caps_unref, void, GstCaps* caps);
21LL_GST_SYM(true, gst_caps_ref, GstCaps *, GstCaps* caps);
22LL_GST_SYM(true, gst_caps_is_empty, gboolean, const GstCaps *caps);
23LL_GST_SYM(true, gst_caps_from_string, GstCaps *, const gchar *string);
24LL_GST_SYM(true, gst_caps_replace, void, GstCaps **caps, GstCaps *newcaps);
25LL_GST_SYM(true, gst_caps_get_structure, GstStructure *, const GstCaps *caps, guint index);
26LL_GST_SYM(true, gst_caps_copy, GstCaps *, const GstCaps * caps);
27LL_GST_SYM(true, gst_caps_intersect, GstCaps *, const GstCaps *caps1, const GstCaps *caps2);
28LL_GST_SYM(true, gst_element_register, gboolean, GstPlugin *plugin, const gchar *name, guint rank, GType type);
29LL_GST_SYM(true, _gst_plugin_register_static, void, GstPluginDesc *desc);
30LL_GST_SYM(true, gst_structure_get_int, gboolean, const GstStructure *structure, const gchar *fieldname, gint *value);
31LL_GST_SYM(true, gst_structure_get_value, G_CONST_RETURN GValue *, const GstStructure *structure, const gchar *fieldname);
32LL_GST_SYM(true, gst_value_get_fraction_numerator, gint, const GValue *value);
33LL_GST_SYM(true, gst_value_get_fraction_denominator, gint, const GValue *value);
34LL_GST_SYM(true, gst_structure_get_name, G_CONST_RETURN gchar *, const GstStructure *structure);
35LL_GST_SYM(true, gst_element_seek, bool, GstElement *, gdouble, GstFormat, GstSeekFlags, GstSeekType, gint64, GstSeekType, gint64);
36
37// optional symbols to grab
38LL_GST_SYM(false, gst_registry_fork_set_enabled, void, gboolean enabled);
39LL_GST_SYM(false, gst_segtrap_set_enabled, void, gboolean enabled);
40LL_GST_SYM(false, gst_message_parse_buffering, void, GstMessage *message, gint *percent);
41LL_GST_SYM(false, gst_message_parse_info, void, GstMessage *message, GError **gerror, gchar **debug);
42LL_GST_SYM(false, gst_element_query_position, gboolean, GstElement *element, GstFormat *format, gint64 *cur);
43
44// GStreamer 'internal' symbols which may not be visible in some runtimes but are still used in expanded GStreamer header macros - yuck! We'll substitute our own stubs for these.
45//LL_GST_SYM(true, _gst_debug_register_funcptr, void, GstDebugFuncPtr func, gchar* ptrname);
46//LL_GST_SYM(true, _gst_debug_category_new, GstDebugCategory *, gchar *name, guint color, gchar *description);
diff --git a/linden/indra/llmedia/llmediaimplgstreamer_syms_rawv.inc b/linden/indra/llmedia/llmediaimplgstreamer_syms_rawv.inc
deleted file mode 100644
index 14fbcb4..0000000
--- a/linden/indra/llmedia/llmediaimplgstreamer_syms_rawv.inc
+++ /dev/null
@@ -1,5 +0,0 @@
1
2// required symbols to grab
3LL_GST_SYM(true, gst_video_sink_get_type, GType, void);
4
5// optional symbols to grab
diff --git a/linden/indra/llmedia/llmediaimplgstreamervidplug.cpp b/linden/indra/llmedia/llmediaimplgstreamervidplug.cpp
index 5e96666..36c503a 100644
--- a/linden/indra/llmedia/llmediaimplgstreamervidplug.cpp
+++ b/linden/indra/llmedia/llmediaimplgstreamervidplug.cpp
@@ -30,7 +30,7 @@
30 * $/LicenseInfo$ 30 * $/LicenseInfo$
31 */ 31 */
32 32
33#if LL_GSTREAMER_ENABLED 33///#if LL_GSTREAMER_ENABLED
34 34
35#include "linden_common.h" 35#include "linden_common.h"
36 36
@@ -38,8 +38,6 @@
38#include <gst/video/video.h> 38#include <gst/video/video.h>
39#include <gst/video/gstvideosink.h> 39#include <gst/video/gstvideosink.h>
40 40
41#include "llmediaimplgstreamer_syms.h"
42
43#include "llthread.h" 41#include "llthread.h"
44 42
45#include "llmediaimplgstreamervidplug.h" 43#include "llmediaimplgstreamervidplug.h"
@@ -89,9 +87,9 @@ gst_slvideo_base_init (gpointer gclass)
89 }; 87 };
90 GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); 88 GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
91 89
92 llgst_element_class_add_pad_template (element_class, 90 gst_element_class_add_pad_template (element_class,
93 llgst_static_pad_template_get (&sink_factory)); 91 gst_static_pad_template_get (&sink_factory));
94 llgst_element_class_set_details (element_class, &element_details); 92 gst_element_class_set_details (element_class, &element_details);
95} 93}
96 94
97 95
@@ -102,7 +100,7 @@ gst_slvideo_finalize (GObject * object)
102 slvideo = GST_SLVIDEO (object); 100 slvideo = GST_SLVIDEO (object);
103 if (slvideo->caps) 101 if (slvideo->caps)
104 { 102 {
105 llgst_caps_unref(slvideo->caps); 103 gst_caps_unref(slvideo->caps);
106 } 104 }
107 105
108 G_OBJECT_CLASS(parent_class)->finalize (object); 106 G_OBJECT_CLASS(parent_class)->finalize (object);
@@ -113,7 +111,7 @@ static GstFlowReturn
113gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf) 111gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf)
114{ 112{
115 GstSLVideo *slvideo; 113 GstSLVideo *slvideo;
116 llg_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); 114 g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
117 115
118 slvideo = GST_SLVIDEO(bsink); 116 slvideo = GST_SLVIDEO(bsink);
119 117
@@ -206,7 +204,7 @@ gst_slvideo_get_caps (GstBaseSink * bsink)
206 GstSLVideo *slvideo; 204 GstSLVideo *slvideo;
207 slvideo = GST_SLVIDEO(bsink); 205 slvideo = GST_SLVIDEO(bsink);
208 206
209 return llgst_caps_ref (slvideo->caps); 207 return gst_caps_ref (slvideo->caps);
210} 208}
211 209
212 210
@@ -222,35 +220,36 @@ gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps)
222 220
223 filter = GST_SLVIDEO(bsink); 221 filter = GST_SLVIDEO(bsink);
224 222
225 intersection = llgst_caps_intersect (filter->caps, caps); 223 intersection = gst_caps_intersect (filter->caps, caps);
226 if (llgst_caps_is_empty (intersection)) 224 if (gst_caps_is_empty (intersection))
227 { 225 {
228 // no overlap between our caps and requested caps 226 // no overlap between our caps and requested caps
229 return FALSE; 227 return FALSE;
230 } 228 }
231 llgst_caps_unref(intersection); 229 gst_caps_unref(intersection);
232 230
233 int width, height; 231 int width = 0;
232 int height = 0;
234 gboolean ret; 233 gboolean ret;
235 const GValue *fps; 234 const GValue *fps;
236 const GValue *par; 235 const GValue *par;
237 structure = llgst_caps_get_structure (caps, 0); 236 structure = gst_caps_get_structure (caps, 0);
238 ret = llgst_structure_get_int (structure, "width", &width); 237 ret = gst_structure_get_int (structure, "width", &width);
239 ret = ret && llgst_structure_get_int (structure, "height", &height); 238 ret = ret && gst_structure_get_int (structure, "height", &height);
240 fps = llgst_structure_get_value (structure, "framerate"); 239 fps = gst_structure_get_value (structure, "framerate");
241 ret = ret && (fps != NULL); 240 ret = ret && (fps != NULL);
242 par = llgst_structure_get_value (structure, "pixel-aspect-ratio"); 241 par = gst_structure_get_value (structure, "pixel-aspect-ratio");
243 if (!ret) 242 if (!ret)
244 return FALSE; 243 return FALSE;
245 244
246 filter->width = width; 245 filter->width = width;
247 filter->height = height; 246 filter->height = height;
248 filter->fps_n = llgst_value_get_fraction_numerator(fps); 247 filter->fps_n = gst_value_get_fraction_numerator(fps);
249 filter->fps_d = llgst_value_get_fraction_denominator(fps); 248 filter->fps_d = gst_value_get_fraction_denominator(fps);
250 if (par) 249 if (par)
251 { 250 {
252 filter->par_n = llgst_value_get_fraction_numerator(par); 251 filter->par_n = gst_value_get_fraction_numerator(par);
253 filter->par_d = llgst_value_get_fraction_denominator(par); 252 filter->par_d = gst_value_get_fraction_denominator(par);
254 } 253 }
255 else 254 else
256 { 255 {
@@ -261,15 +260,15 @@ gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps)
261 GST_VIDEO_SINK_HEIGHT(filter) = height; 260 GST_VIDEO_SINK_HEIGHT(filter) = height;
262 261
263 filter->format = SLV_PF_UNKNOWN; 262 filter->format = SLV_PF_UNKNOWN;
264 if (0 == strcmp(llgst_structure_get_name(structure), 263 if (0 == strcmp(gst_structure_get_name(structure),
265 "video/x-raw-rgb")) 264 "video/x-raw-rgb"))
266 { 265 {
267 int red_mask; 266 int red_mask;
268 int green_mask; 267 int green_mask;
269 int blue_mask; 268 int blue_mask;
270 llgst_structure_get_int(structure, "red_mask", &red_mask); 269 gst_structure_get_int(structure, "red_mask", &red_mask);
271 llgst_structure_get_int(structure, "green_mask", &green_mask); 270 gst_structure_get_int(structure, "green_mask", &green_mask);
272 llgst_structure_get_int(structure, "blue_mask", &blue_mask); 271 gst_structure_get_int(structure, "blue_mask", &blue_mask);
273 if ((unsigned int)red_mask == 0xFF000000 && 272 if ((unsigned int)red_mask == 0xFF000000 &&
274 (unsigned int)green_mask == 0x00FF0000 && 273 (unsigned int)green_mask == 0x00FF0000 &&
275 (unsigned int)blue_mask == 0x0000FF00) 274 (unsigned int)blue_mask == 0x0000FF00)
@@ -360,9 +359,9 @@ gst_slvideo_update_caps (GstSLVideo * slvideo)
360 // GStreamer will automatically convert colourspace if necessary. 359 // GStreamer will automatically convert colourspace if necessary.
361 // GStreamer will automatically resize media to one of these enumerated 360 // GStreamer will automatically resize media to one of these enumerated
362 // powers-of-two that we ask for (yay GStreamer!) 361 // powers-of-two that we ask for (yay GStreamer!)
363 caps = llgst_caps_from_string (SLV_ALLCAPS); 362 caps = gst_caps_from_string (SLV_ALLCAPS);
364 363
365 llgst_caps_replace (&slvideo->caps, caps); 364 gst_caps_replace (&slvideo->caps, caps);
366} 365}
367 366
368 367
@@ -395,12 +394,10 @@ static void
395gst_slvideo_set_property (GObject * object, guint prop_id, 394gst_slvideo_set_property (GObject * object, guint prop_id,
396 const GValue * value, GParamSpec * pspec) 395 const GValue * value, GParamSpec * pspec)
397{ 396{
398 llg_return_if_fail (GST_IS_SLVIDEO (object)); 397 g_return_if_fail (GST_IS_SLVIDEO (object));
399 398
400 switch (prop_id) { 399 if (prop_id) {
401 default:
402 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 400 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
403 break;
404 } 401 }
405} 402}
406 403
@@ -408,12 +405,10 @@ static void
408gst_slvideo_get_property (GObject * object, guint prop_id, 405gst_slvideo_get_property (GObject * object, guint prop_id,
409 GValue * value, GParamSpec * pspec) 406 GValue * value, GParamSpec * pspec)
410{ 407{
411 llg_return_if_fail (GST_IS_SLVIDEO (object)); 408 g_return_if_fail (GST_IS_SLVIDEO (object));
412 409
413 switch (prop_id) { 410 if (prop_id) {
414 default:
415 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 411 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
416 break;
417 } 412 }
418} 413}
419 414
@@ -431,29 +426,23 @@ plugin_init (GstPlugin * plugin)
431 GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin", 426 GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin",
432 0, (gchar*)"Second Life Video Sink"); 427 0, (gchar*)"Second Life Video Sink");
433 428
434 return llgst_element_register (plugin, "private-slvideo", 429 return gst_element_register (plugin, "private-slvideo",
435 GST_RANK_NONE, GST_TYPE_SLVIDEO); 430 GST_RANK_NONE, GST_TYPE_SLVIDEO);
436} 431}
437 432
438/* this is the structure that gstreamer looks for to register plugins 433
439 */
440/* NOTE: Can't rely upon GST_PLUGIN_DEFINE_STATIC to self-register, since
441 some g++ versions buggily avoid __attribute__((constructor)) functions -
442 so we provide an explicit plugin init function.
443 */
444void gst_slvideo_init_class (void) 434void gst_slvideo_init_class (void)
445{ 435{
446#define PACKAGE "packagehack" 436 gst_plugin_register_static( GST_VERSION_MAJOR,
447 static GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, 437 GST_VERSION_MINOR,
448 GST_VERSION_MINOR, 438 "private-slvideoplugin",
449 "private-slvideoplugin", 439 "SL Video sink plugin",
450 "SL Video sink plugin", 440 plugin_init,
451 plugin_init, "0.1", GST_LICENSE_UNKNOWN, 441 "0.1",
452 "Second Life", 442 GST_LICENSE_UNKNOWN,
453 "http://www.secondlife.com/"); 443 "Second Life",
454#undef PACKAGE 444 "Second Life",
455 ll_gst_plugin_register_static (&gst_plugin_desc); 445 "http://www.secondlife.com/" );
456 //fprintf(stderr, "\n\n\nCLASS INIT\n\n\n");
457} 446}
458 447
459#endif // LL_GSTREAMER_ENABLED 448///#endif // LL_GSTREAMER_ENABLED
diff --git a/linden/indra/llmedia/llmediaimplgstreamervidplug.h b/linden/indra/llmedia/llmediaimplgstreamervidplug.h
index 3db064c..3a984a9 100644
--- a/linden/indra/llmedia/llmediaimplgstreamervidplug.h
+++ b/linden/indra/llmedia/llmediaimplgstreamervidplug.h
@@ -33,12 +33,13 @@
33#ifndef __GST_SLVIDEO_H__ 33#ifndef __GST_SLVIDEO_H__
34#define __GST_SLVIDEO_H__ 34#define __GST_SLVIDEO_H__
35 35
36#if LL_GSTREAMER_ENABLED 36///#if LL_GSTREAMER_ENABLED
37 37
38extern "C" { 38extern "C" {
39#include <gst/gst.h> 39#include <gst/gst.h>
40#include <gst/video/video.h> 40#include <gst/video/video.h>
41#include <gst/video/gstvideosink.h> 41#include <gst/video/gstvideosink.h>
42#include <glib/gthread.h>
42} 43}
43 44
44G_BEGIN_DECLS 45G_BEGIN_DECLS
@@ -100,6 +101,6 @@ void gst_slvideo_init_class (void);
100 101
101G_END_DECLS 102G_END_DECLS
102 103
103#endif // LL_GSTREAMER_ENABLED 104///#endif // LL_GSTREAMER_ENABLED
104 105
105#endif /* __GST_SLVIDEO_H__ */ 106#endif /* __GST_SLVIDEO_H__ */
diff --git a/linden/indra/llmedia/llmediamanager.cpp b/linden/indra/llmedia/llmediamanager.cpp
index e1c7608..48da808 100644
--- a/linden/indra/llmedia/llmediamanager.cpp
+++ b/linden/indra/llmedia/llmediamanager.cpp
@@ -31,16 +31,29 @@
31 */ 31 */
32 32
33#include "llmediamanager.h" 33#include "llmediamanager.h"
34
35#if LL_WINDOWS
36 // GStreamer 0.10.22 - gstutils.h - conversion from 'guint64' to 'guint8'.
37 // This was an intentional change to make GStreamer more threadsafe, and
38 // is okay. Delete this bit if GStreamer ever gets more VS-friendly -- McCabe
39 #pragma warning(disable : 4244)
40#endif
41#include "llmediaimplgstreamer.h"
42#if LL_WINDOWS
43 #pragma warning(default : 4244)
44#endif
45
34#include "llmediaimplfactory.h" 46#include "llmediaimplfactory.h"
35 47
36#include "llmediaimplexample1.h" 48#include "llmediaimplexample1.h"
37#include "llmediaimplexample2.h" 49#include "llmediaimplexample2.h"
38#include "llmediaimplquicktime.h" 50#include "llmediaimplquicktime.h"
39#include "llmediaimplgstreamer.h" 51
40#if LL_LLMOZLIB_ENABLED 52#if LL_LLMOZLIB_ENABLED
41# include "llmediaimplllmozlib.h" 53# include "llmediaimplllmozlib.h"
42#endif 54#endif
43 55
56#include "llerror.h"
44LLMediaManager* LLMediaManager::sInstance = 0; 57LLMediaManager* LLMediaManager::sInstance = 0;
45 58
46 59
@@ -76,6 +89,7 @@ void LLMediaManager::initClass( LLMediaManagerData* init_data )
76 if ( ! sInstance ) 89 if ( ! sInstance )
77 sInstance = new LLMediaManager(); 90 sInstance = new LLMediaManager();
78 91
92 LL_DEBUGS("MediaManager") << "LLMediaManager::initClass" << LL_ENDL;
79 // Initialize impl classes here - this breaks the encapsulation model 93 // Initialize impl classes here - this breaks the encapsulation model
80 // but some of the initialization takes a long time and we only want to 94 // but some of the initialization takes a long time and we only want to
81 // do it once at app startup before any of the impls have been created 95 // do it once at app startup before any of the impls have been created
@@ -85,12 +99,14 @@ void LLMediaManager::initClass( LLMediaManagerData* init_data )
85 LLMediaImplExample2::startup( init_data ); 99 LLMediaImplExample2::startup( init_data );
86 100
87#if LL_QUICKTIME_ENABLED 101#if LL_QUICKTIME_ENABLED
102 LL_DEBUGS("MediaManager") << "LLMediaManager::initClass: starting quicktime." << LL_ENDL;
88 LLMediaImplQuickTime::startup( init_data ); 103 LLMediaImplQuickTime::startup( init_data );
89#endif // LL_QUICKTIME_ENABLED 104#endif // LL_QUICKTIME_ENABLED
90 105
91#if LL_GSTREAMER_ENABLED 106///#if LL_GSTREAMER_ENABLED
107 LL_DEBUGS("MediaManager") << "LLMediaManager::initClass: starting gstreamer" << LL_ENDL;
92 LLMediaImplGStreamer::startup( init_data ); 108 LLMediaImplGStreamer::startup( init_data );
93#endif // LL_GSTREAMER_ENABLED 109///#endif // LL_GSTREAMER_ENABLED
94} 110}
95 111
96//////////////////////////////////////////////////////////////////////////////// 112////////////////////////////////////////////////////////////////////////////////
@@ -130,9 +146,9 @@ void LLMediaManager::cleanupClass()
130 LLMediaImplQuickTime::closedown(); 146 LLMediaImplQuickTime::closedown();
131#endif // LL_QUICKTIME_ENABLED 147#endif // LL_QUICKTIME_ENABLED
132 148
133#if LL_GSTREAMER_ENABLED 149///#if LL_GSTREAMER_ENABLED
134 LLMediaImplGStreamer::closedown(); 150 LLMediaImplGStreamer::closedown();
135#endif // LL_QUICKTIME_ENABLED 151///#endif // LL_QUICKTIME_ENABLED
136 152
137 if ( sInstance ) 153 if ( sInstance )
138 delete sInstance; 154 delete sInstance;