aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/media_plugins/gstreamer010
diff options
context:
space:
mode:
authorArmin Weatherwax2010-07-10 14:35:58 +0200
committerArmin Weatherwax2010-09-23 15:47:28 +0200
commitf41c6363087f95ce5f7d99385e455d7e0105d883 (patch)
tree7574f66a2e8123610588e8b66f2e444850163801 /linden/indra/media_plugins/gstreamer010
parentFixed plugin compile issues on windows (diff)
downloadmeta-impy-f41c6363087f95ce5f7d99385e455d7e0105d883.zip
meta-impy-f41c6363087f95ce5f7d99385e455d7e0105d883.tar.gz
meta-impy-f41c6363087f95ce5f7d99385e455d7e0105d883.tar.bz2
meta-impy-f41c6363087f95ce5f7d99385e455d7e0105d883.tar.xz
Imprudence style gstreamer plugin (remove llgst, syms and such)
Diffstat (limited to '')
-rw-r--r--linden/indra/media_plugins/gstreamer010/CMakeLists.txt2
-rwxr-xr-xlinden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp174
-rwxr-xr-xlinden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h81
-rwxr-xr-xlinden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc51
-rwxr-xr-xlinden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc5
-rwxr-xr-xlinden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp166
-rwxr-xr-xlinden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h5
-rwxr-xr-xlinden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp454
8 files changed, 410 insertions, 528 deletions
diff --git a/linden/indra/media_plugins/gstreamer010/CMakeLists.txt b/linden/indra/media_plugins/gstreamer010/CMakeLists.txt
index 6eab49c..a031157 100644
--- a/linden/indra/media_plugins/gstreamer010/CMakeLists.txt
+++ b/linden/indra/media_plugins/gstreamer010/CMakeLists.txt
@@ -44,13 +44,11 @@ endif (NOT CMAKE_SIZEOF_VOID_P MATCHES 4)
44 44
45set(media_plugin_gstreamer010_SOURCE_FILES 45set(media_plugin_gstreamer010_SOURCE_FILES
46 media_plugin_gstreamer010.cpp 46 media_plugin_gstreamer010.cpp
47 llmediaimplgstreamer_syms.cpp
48 llmediaimplgstreamervidplug.cpp 47 llmediaimplgstreamervidplug.cpp
49 ) 48 )
50 49
51set(media_plugin_gstreamer010_HEADER_FILES 50set(media_plugin_gstreamer010_HEADER_FILES
52 llmediaimplgstreamervidplug.h 51 llmediaimplgstreamervidplug.h
53 llmediaimplgstreamer_syms.h
54 llmediaimplgstreamertriviallogging.h 52 llmediaimplgstreamertriviallogging.h
55 ) 53 )
56 54
diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp
deleted file mode 100755
index 82978ad..0000000
--- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.cpp
+++ /dev/null
@@ -1,174 +0,0 @@
1/**
2 * @file llmediaimplgstreamer_syms.cpp
3 * @brief dynamic GStreamer symbol-grabbing code
4 *
5 * @cond
6 * $LicenseInfo:firstyear=2007&license=viewergpl$
7 *
8 * Copyright (c) 2007-2010, Linden Research, Inc.
9 *
10 * Second Life Viewer Source Code
11 * The source code in this file ("Source Code") is provided by Linden Lab
12 * to you under the terms of the GNU General Public License, version 2.0
13 * ("GPL"), unless you have obtained a separate licensing agreement
14 * ("Other License"), formally executed by you and Linden Lab. Terms of
15 * the GPL can be found in doc/GPL-license.txt in this distribution, or
16 * online at http://secondlife.com/developers/opensource/gplv2
17 *
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
20 * in the file doc/FLOSS-exception.txt in this software distribution, or
21 * online at
22 * http://secondlife.com/developers/opensource/flossexception
23 *
24 * By copying, modifying or distributing this software, you acknowledge
25 * that you have read and understood your obligations described above,
26 * and agree to abide by those obligations.
27 *
28 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
29 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
30 * COMPLETENESS OR PERFORMANCE.
31 * $/LicenseInfo$
32 *
33 * @endcond
34 */
35
36#if LL_GSTREAMER010_ENABLED
37
38#include <string>
39
40extern "C" {
41#include <gst/gst.h>
42
43#include "apr_pools.h"
44#include "apr_dso.h"
45}
46
47#include "llmediaimplgstreamertriviallogging.h"
48
49#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) RTN (*ll##GSTSYM)(__VA_ARGS__) = NULL
50#include "llmediaimplgstreamer_syms_raw.inc"
51#include "llmediaimplgstreamer_syms_rawv.inc"
52#undef LL_GST_SYM
53
54// a couple of stubs for disgusting reasons
55GstDebugCategory*
56ll_gst_debug_category_new(gchar *name, guint color, gchar *description)
57{
58 static GstDebugCategory dummy;
59 return &dummy;
60}
61void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname)
62{
63}
64
65static bool sSymsGrabbed = false;
66static apr_pool_t *sSymGSTDSOMemoryPool = NULL;
67static apr_dso_handle_t *sSymGSTDSOHandleG = NULL;
68static apr_dso_handle_t *sSymGSTDSOHandleV = NULL;
69
70
71bool grab_gst_syms(std::string gst_dso_name,
72 std::string gst_dso_name_vid)
73{
74 if (sSymsGrabbed)
75 {
76 // already have grabbed good syms
77 return TRUE;
78 }
79
80 bool sym_error = false;
81 bool rtn = false;
82 apr_status_t rv;
83 apr_dso_handle_t *sSymGSTDSOHandle = NULL;
84
85#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)
86
87 //attempt to load the shared libraries
88 apr_pool_create(&sSymGSTDSOMemoryPool, NULL);
89
90 if ( APR_SUCCESS == (rv = apr_dso_load(&sSymGSTDSOHandle,
91 gst_dso_name.c_str(),
92 sSymGSTDSOMemoryPool) ))
93 {
94 INFOMSG("Found DSO: %s", gst_dso_name.c_str());
95#include "llmediaimplgstreamer_syms_raw.inc"
96
97 if ( sSymGSTDSOHandle )
98 {
99 sSymGSTDSOHandleG = sSymGSTDSOHandle;
100 sSymGSTDSOHandle = NULL;
101 }
102
103 if ( APR_SUCCESS ==
104 (rv = apr_dso_load(&sSymGSTDSOHandle,
105 gst_dso_name_vid.c_str(),
106 sSymGSTDSOMemoryPool) ))
107 {
108 INFOMSG("Found DSO: %s", gst_dso_name_vid.c_str());
109#include "llmediaimplgstreamer_syms_rawv.inc"
110 rtn = !sym_error;
111 }
112 else
113 {
114 INFOMSG("Couldn't load DSO: %s", gst_dso_name_vid.c_str());
115 rtn = false; // failure
116 }
117 }
118 else
119 {
120 INFOMSG("Couldn't load DSO: %s", gst_dso_name.c_str());
121 rtn = false; // failure
122 }
123
124 if (sym_error)
125 {
126 WARNMSG("Failed to find necessary symbols in GStreamer libraries.");
127 }
128
129 if ( sSymGSTDSOHandle )
130 {
131 sSymGSTDSOHandleV = sSymGSTDSOHandle;
132 sSymGSTDSOHandle = NULL;
133 }
134#undef LL_GST_SYM
135
136 sSymsGrabbed = !!rtn;
137 return rtn;
138}
139
140
141void ungrab_gst_syms()
142{
143 // should be safe to call regardless of whether we've
144 // actually grabbed syms.
145
146 if ( sSymGSTDSOHandleG )
147 {
148 apr_dso_unload(sSymGSTDSOHandleG);
149 sSymGSTDSOHandleG = NULL;
150 }
151
152 if ( sSymGSTDSOHandleV )
153 {
154 apr_dso_unload(sSymGSTDSOHandleV);
155 sSymGSTDSOHandleV = NULL;
156 }
157
158 if ( sSymGSTDSOMemoryPool )
159 {
160 apr_pool_destroy(sSymGSTDSOMemoryPool);
161 sSymGSTDSOMemoryPool = NULL;
162 }
163
164 // NULL-out all of the symbols we'd grabbed
165#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) do{ll##GSTSYM = NULL;}while(0)
166#include "llmediaimplgstreamer_syms_raw.inc"
167#include "llmediaimplgstreamer_syms_rawv.inc"
168#undef LL_GST_SYM
169
170 sSymsGrabbed = false;
171}
172
173
174#endif // LL_GSTREAMER010_ENABLED
diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h
deleted file mode 100755
index c309043..0000000
--- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms.h
+++ /dev/null
@@ -1,81 +0,0 @@
1/**
2 * @file llmediaimplgstreamer_syms.h
3 * @brief dynamic GStreamer symbol-grabbing code
4 *
5 * @cond
6 * $LicenseInfo:firstyear=2007&license=viewergpl$
7 *
8 * Copyright (c) 2007-2010, Linden Research, Inc.
9 *
10 * Second Life Viewer Source Code
11 * The source code in this file ("Source Code") is provided by Linden Lab
12 * to you under the terms of the GNU General Public License, version 2.0
13 * ("GPL"), unless you have obtained a separate licensing agreement
14 * ("Other License"), formally executed by you and Linden Lab. Terms of
15 * the GPL can be found in doc/GPL-license.txt in this distribution, or
16 * online at http://secondlife.com/developers/opensource/gplv2
17 *
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
20 * in the file doc/FLOSS-exception.txt in this software distribution, or
21 * online at
22 * http://secondlife.com/developers/opensource/flossexception
23 *
24 * By copying, modifying or distributing this software, you acknowledge
25 * that you have read and understood your obligations described above,
26 * and agree to abide by those obligations.
27 *
28 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
29 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
30 * COMPLETENESS OR PERFORMANCE.
31 * $/LicenseInfo$
32 *
33 * @endcond
34 */
35
36#include "linden_common.h"
37
38#if LL_GSTREAMER010_ENABLED
39
40extern "C" {
41#include <gst/gst.h>
42}
43
44bool grab_gst_syms(std::string gst_dso_name,
45 std::string gst_dso_name_vid);
46void ungrab_gst_syms();
47
48#define LL_GST_SYM(REQ, GSTSYM, RTN, ...) extern RTN (*ll##GSTSYM)(__VA_ARGS__)
49#include "llmediaimplgstreamer_syms_raw.inc"
50#include "llmediaimplgstreamer_syms_rawv.inc"
51#undef LL_GST_SYM
52
53// regrettable hacks to give us better runtime compatibility with older systems
54#define llg_return_if_fail(COND) do{if (!(COND)) return;}while(0)
55#define llg_return_val_if_fail(COND,V) do{if (!(COND)) return V;}while(0)
56
57// regrettable hacks because GStreamer was not designed for runtime loading
58#undef GST_TYPE_MESSAGE
59#define GST_TYPE_MESSAGE (llgst_message_get_type())
60#undef GST_TYPE_OBJECT
61#define GST_TYPE_OBJECT (llgst_object_get_type())
62#undef GST_TYPE_PIPELINE
63#define GST_TYPE_PIPELINE (llgst_pipeline_get_type())
64#undef GST_TYPE_ELEMENT
65#define GST_TYPE_ELEMENT (llgst_element_get_type())
66#undef GST_TYPE_VIDEO_SINK
67#define GST_TYPE_VIDEO_SINK (llgst_video_sink_get_type())
68// more regrettable hacks to stub-out these .h-exposed GStreamer internals
69void ll_gst_debug_register_funcptr(GstDebugFuncPtr func, gchar* ptrname);
70#undef _gst_debug_register_funcptr
71#define _gst_debug_register_funcptr ll_gst_debug_register_funcptr
72GstDebugCategory* ll_gst_debug_category_new(gchar *name, guint color, gchar *description);
73#undef _gst_debug_category_new
74#define _gst_debug_category_new ll_gst_debug_category_new
75#undef __gst_debug_enabled
76#define __gst_debug_enabled (0)
77
78// more hacks
79#define LLGST_MESSAGE_TYPE_NAME(M) (llgst_message_type_get_name(GST_MESSAGE_TYPE(M)))
80
81#endif // LL_GSTREAMER010_ENABLED
diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc
deleted file mode 100755
index b33e593..0000000
--- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_raw.inc
+++ /dev/null
@@ -1,51 +0,0 @@
1
2// required symbols to grab
3LL_GST_SYM(true, gst_pad_peer_accept_caps, gboolean, GstPad *pad, GstCaps *caps);
4LL_GST_SYM(true, gst_buffer_new, GstBuffer*, void);
5LL_GST_SYM(true, gst_buffer_set_caps, void, GstBuffer*, GstCaps *);
6LL_GST_SYM(true, gst_structure_set_value, void, GstStructure *, const gchar *, const GValue*);
7LL_GST_SYM(true, gst_init_check, gboolean, int *argc, char **argv[], GError ** err);
8LL_GST_SYM(true, gst_message_get_type, GType, void);
9LL_GST_SYM(true, gst_message_type_get_name, const gchar*, GstMessageType type);
10LL_GST_SYM(true, gst_message_parse_error, void, GstMessage *message, GError **gerror, gchar **debug);
11LL_GST_SYM(true, gst_message_parse_warning, void, GstMessage *message, GError **gerror, gchar **debug);
12LL_GST_SYM(true, gst_message_parse_state_changed, void, GstMessage *message, GstState *oldstate, GstState *newstate, GstState *pending);
13LL_GST_SYM(true, gst_element_set_state, GstStateChangeReturn, GstElement *element, GstState state);
14LL_GST_SYM(true, gst_object_unref, void, gpointer object);
15LL_GST_SYM(true, gst_object_get_type, GType, void);
16LL_GST_SYM(true, gst_pipeline_get_type, GType, void);
17LL_GST_SYM(true, gst_pipeline_get_bus, GstBus*, GstPipeline *pipeline);
18LL_GST_SYM(true, gst_bus_add_watch, guint, GstBus * bus, GstBusFunc func, gpointer user_data);
19LL_GST_SYM(true, gst_element_factory_make, GstElement*, const gchar *factoryname, const gchar *name);
20LL_GST_SYM(true, gst_element_get_type, GType, void);
21LL_GST_SYM(true, gst_static_pad_template_get, GstPadTemplate*, GstStaticPadTemplate *pad_template);
22LL_GST_SYM(true, gst_element_class_add_pad_template, void, GstElementClass *klass, GstPadTemplate *temp);
23LL_GST_SYM(true, gst_element_class_set_details, void, GstElementClass *klass, const GstElementDetails *details);
24LL_GST_SYM(true, gst_caps_unref, void, GstCaps* caps);
25LL_GST_SYM(true, gst_caps_ref, GstCaps *, GstCaps* caps);
26//LL_GST_SYM(true, gst_caps_is_empty, gboolean, const GstCaps *caps);
27LL_GST_SYM(true, gst_caps_from_string, GstCaps *, const gchar *string);
28LL_GST_SYM(true, gst_caps_replace, void, GstCaps **caps, GstCaps *newcaps);
29LL_GST_SYM(true, gst_caps_get_structure, GstStructure *, const GstCaps *caps, guint index);
30LL_GST_SYM(true, gst_caps_copy, GstCaps *, const GstCaps * caps);
31//LL_GST_SYM(true, gst_caps_intersect, GstCaps *, const GstCaps *caps1, const GstCaps *caps2);
32LL_GST_SYM(true, gst_element_register, gboolean, GstPlugin *plugin, const gchar *name, guint rank, GType type);
33LL_GST_SYM(true, _gst_plugin_register_static, void, GstPluginDesc *desc);
34LL_GST_SYM(true, gst_structure_get_int, gboolean, const GstStructure *structure, const gchar *fieldname, gint *value);
35LL_GST_SYM(true, gst_structure_get_value, G_CONST_RETURN GValue *, const GstStructure *structure, const gchar *fieldname);
36LL_GST_SYM(true, gst_value_get_fraction_numerator, gint, const GValue *value);
37LL_GST_SYM(true, gst_value_get_fraction_denominator, gint, const GValue *value);
38LL_GST_SYM(true, gst_structure_get_name, G_CONST_RETURN gchar *, const GstStructure *structure);
39LL_GST_SYM(true, gst_element_seek, bool, GstElement *, gdouble, GstFormat, GstSeekFlags, GstSeekType, gint64, GstSeekType, gint64);
40
41// optional symbols to grab
42LL_GST_SYM(false, gst_registry_fork_set_enabled, void, gboolean enabled);
43LL_GST_SYM(false, gst_segtrap_set_enabled, void, gboolean enabled);
44LL_GST_SYM(false, gst_message_parse_buffering, void, GstMessage *message, gint *percent);
45LL_GST_SYM(false, gst_message_parse_info, void, GstMessage *message, GError **gerror, gchar **debug);
46LL_GST_SYM(false, gst_element_query_position, gboolean, GstElement *element, GstFormat *format, gint64 *cur);
47LL_GST_SYM(false, gst_version, void, guint *major, guint *minor, guint *micro, guint *nano);
48
49// 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.
50//LL_GST_SYM(true, _gst_debug_register_funcptr, void, GstDebugFuncPtr func, gchar* ptrname);
51//LL_GST_SYM(true, _gst_debug_category_new, GstDebugCategory *, gchar *name, guint color, gchar *description);
diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamer_syms_rawv.inc
deleted file mode 100755
index 14fbcb4..0000000
--- a/linden/indra/media_plugins/gstreamer010/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/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
index 9242830..1fee545 100755
--- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
+++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
@@ -33,7 +33,7 @@
33 * @endcond 33 * @endcond
34 */ 34 */
35 35
36#if LL_GSTREAMER010_ENABLED 36///#if LL_GSTREAMER010_ENABLED
37 37
38#include "linden_common.h" 38#include "linden_common.h"
39 39
@@ -41,15 +41,29 @@
41#include <gst/video/video.h> 41#include <gst/video/video.h>
42#include <gst/video/gstvideosink.h> 42#include <gst/video/gstvideosink.h>
43 43
44#include "llmediaimplgstreamer_syms.h"
45#include "llmediaimplgstreamertriviallogging.h" 44#include "llmediaimplgstreamertriviallogging.h"
45// #include "llthread.h"
46 46
47#include "llmediaimplgstreamervidplug.h" 47#include "llmediaimplgstreamervidplug.h"
48 48
49
50GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug); 49GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug);
51#define GST_CAT_DEFAULT gst_slvideo_debug 50#define GST_CAT_DEFAULT gst_slvideo_debug
52 51
52/* Filter signals and args *//*
53enum
54{
55 *//* FILL ME *//*
56 LAST_SIGNAL
57};
58
59enum
60{
61 ARG_0
62};
63
64#define SLV_SIZECAPS ", width=(int){1,2,4,8,16,32,64,128,256,512,1024}, height=(int){1,2,4,8,16,32,64,128,256,512,1024} "
65#define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS ";" GST_VIDEO_CAPS_BGRx SLV_SIZECAPS
66*/
53 67
54#define SLV_SIZECAPS ", width=(int)[1,2048], height=(int)[1,2048] " 68#define SLV_SIZECAPS ", width=(int)[1,2048], height=(int)[1,2048] "
55#define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS 69#define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS
@@ -81,9 +95,9 @@ gst_slvideo_base_init (gpointer gclass)
81 }; 95 };
82 GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); 96 GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
83 97
84 llgst_element_class_add_pad_template (element_class, 98 gst_element_class_add_pad_template (element_class,
85 llgst_static_pad_template_get (&sink_factory)); 99 gst_static_pad_template_get (&sink_factory));
86 llgst_element_class_set_details (element_class, &element_details); 100 gst_element_class_set_details (element_class, &element_details);
87} 101}
88 102
89 103
@@ -94,7 +108,7 @@ gst_slvideo_finalize (GObject * object)
94 slvideo = GST_SLVIDEO (object); 108 slvideo = GST_SLVIDEO (object);
95 if (slvideo->caps) 109 if (slvideo->caps)
96 { 110 {
97 llgst_caps_unref(slvideo->caps); 111 gst_caps_unref(slvideo->caps);
98 } 112 }
99 113
100 G_OBJECT_CLASS(parent_class)->finalize (object); 114 G_OBJECT_CLASS(parent_class)->finalize (object);
@@ -105,7 +119,7 @@ static GstFlowReturn
105gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf) 119gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf)
106{ 120{
107 GstSLVideo *slvideo; 121 GstSLVideo *slvideo;
108 llg_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); 122 g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
109 123
110 slvideo = GST_SLVIDEO(bsink); 124 slvideo = GST_SLVIDEO(bsink);
111 125
@@ -197,7 +211,7 @@ gst_slvideo_get_caps (GstBaseSink * bsink)
197 GstSLVideo *slvideo; 211 GstSLVideo *slvideo;
198 slvideo = GST_SLVIDEO(bsink); 212 slvideo = GST_SLVIDEO(bsink);
199 213
200 return llgst_caps_ref (slvideo->caps); 214 return gst_caps_ref (slvideo->caps);
201} 215}
202 216
203 217
@@ -207,21 +221,32 @@ gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps)
207{ 221{
208 GstSLVideo *filter; 222 GstSLVideo *filter;
209 GstStructure *structure; 223 GstStructure *structure;
224// GstCaps *intersection;
210 225
211 GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps); 226 GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps);
212 227
213 filter = GST_SLVIDEO(bsink); 228 filter = GST_SLVIDEO(bsink);
214 229
215 int width, height; 230/*
231 intersection = gst_caps_intersect (filter->caps, caps);
232 if (gst_caps_is_empty (intersection))
233 {
234 // no overlap between our caps and requested caps
235 return FALSE;
236 }
237 gst_caps_unref(intersection);
238*/
239 int width = 0;
240 int height = 0;
216 gboolean ret; 241 gboolean ret;
217 const GValue *fps; 242 const GValue *fps;
218 const GValue *par; 243 const GValue *par;
219 structure = llgst_caps_get_structure (caps, 0); 244 structure = gst_caps_get_structure (caps, 0);
220 ret = llgst_structure_get_int (structure, "width", &width); 245 ret = gst_structure_get_int (structure, "width", &width);
221 ret = ret && llgst_structure_get_int (structure, "height", &height); 246 ret = ret && gst_structure_get_int (structure, "height", &height);
222 fps = llgst_structure_get_value (structure, "framerate"); 247 fps = gst_structure_get_value (structure, "framerate");
223 ret = ret && (fps != NULL); 248 ret = ret && (fps != NULL);
224 par = llgst_structure_get_value (structure, "pixel-aspect-ratio"); 249 par = gst_structure_get_value (structure, "pixel-aspect-ratio");
225 if (!ret) 250 if (!ret)
226 return FALSE; 251 return FALSE;
227 252
@@ -231,34 +256,35 @@ gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps)
231 256
232 filter->width = width; 257 filter->width = width;
233 filter->height = height; 258 filter->height = height;
234 259 filter->fps_n = gst_value_get_fraction_numerator(fps);
235 filter->fps_n = llgst_value_get_fraction_numerator(fps); 260 filter->fps_d = gst_value_get_fraction_denominator(fps);
236 filter->fps_d = llgst_value_get_fraction_denominator(fps);
237 if (par) 261 if (par)
238 { 262 {
239 filter->par_n = llgst_value_get_fraction_numerator(par); 263 filter->par_n = gst_value_get_fraction_numerator(par);
240 filter->par_d = llgst_value_get_fraction_denominator(par); 264 filter->par_d = gst_value_get_fraction_denominator(par);
241 } 265 }
242 else 266 else
243 { 267 {
244 filter->par_n = 1; 268 filter->par_n = 1;
245 filter->par_d = 1; 269 filter->par_d = 1;
246 } 270 }
271
247 GST_VIDEO_SINK_WIDTH(filter) = width; 272 GST_VIDEO_SINK_WIDTH(filter) = width;
248 GST_VIDEO_SINK_HEIGHT(filter) = height; 273 GST_VIDEO_SINK_HEIGHT(filter) = height;
249 274
250 // crufty lump - we *always* accept *only* RGBX now. 275 // crufty lump - we *always* accept *only* RGBX now.
251 /* 276 /*
277
252 filter->format = SLV_PF_UNKNOWN; 278 filter->format = SLV_PF_UNKNOWN;
253 if (0 == strcmp(llgst_structure_get_name(structure), 279 if (0 == strcmp(gst_structure_get_name(structure),
254 "video/x-raw-rgb")) 280 "video/x-raw-rgb"))
255 { 281 {
256 int red_mask; 282 int red_mask;
257 int green_mask; 283 int green_mask;
258 int blue_mask; 284 int blue_mask;
259 llgst_structure_get_int(structure, "red_mask", &red_mask); 285 gst_structure_get_int(structure, "red_mask", &red_mask);
260 llgst_structure_get_int(structure, "green_mask", &green_mask); 286 gst_structure_get_int(structure, "green_mask", &green_mask);
261 llgst_structure_get_int(structure, "blue_mask", &blue_mask); 287 gst_structure_get_int(structure, "blue_mask", &blue_mask);
262 if ((unsigned int)red_mask == 0xFF000000 && 288 if ((unsigned int)red_mask == 0xFF000000 &&
263 (unsigned int)green_mask == 0x00FF0000 && 289 (unsigned int)green_mask == 0x00FF0000 &&
264 (unsigned int)blue_mask == 0x0000FF00) 290 (unsigned int)blue_mask == 0x0000FF00)
@@ -272,12 +298,13 @@ gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps)
272 filter->format = SLV_PF_BGRX; 298 filter->format = SLV_PF_BGRX;
273 //fprintf(stderr, "\n\nPIXEL FORMAT BGR\n\n"); 299 //fprintf(stderr, "\n\nPIXEL FORMAT BGR\n\n");
274 } 300 }
275 }*/ 301
276 302 }*/
303
277 filter->format = SLV_PF_RGBX; 304 filter->format = SLV_PF_RGBX;
278 305
279 GST_OBJECT_UNLOCK(filter); 306 GST_OBJECT_UNLOCK(filter);
280 307
281 return TRUE; 308 return TRUE;
282} 309}
283 310
@@ -324,15 +351,15 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
324 // we can ignore these and reverse-negotiate our preferred dimensions with 351 // we can ignore these and reverse-negotiate our preferred dimensions with
325 // the peer if we like - we need to do this to obey dynamic resize requests 352 // the peer if we like - we need to do this to obey dynamic resize requests
326 // flowing in from the app. 353 // flowing in from the app.
327 structure = llgst_caps_get_structure (caps, 0); 354 structure = gst_caps_get_structure (caps, 0);
328 if (!llgst_structure_get_int(structure, "width", &width) || 355 if (!gst_structure_get_int(structure, "width", &width) ||
329 !llgst_structure_get_int(structure, "height", &height)) 356 !gst_structure_get_int(structure, "height", &height))
330 { 357 {
331 GST_WARNING_OBJECT (slvideo, "no width/height in caps %" GST_PTR_FORMAT, caps); 358 GST_WARNING_OBJECT (slvideo, "no width/height in caps %" GST_PTR_FORMAT, caps);
332 return GST_FLOW_NOT_NEGOTIATED; 359 return GST_FLOW_NOT_NEGOTIATED;
333 } 360 }
334 361
335 GstBuffer *newbuf = llgst_buffer_new(); 362 GstBuffer *newbuf = gst_buffer_new();
336 bool made_bufferdata_ptr = false; 363 bool made_bufferdata_ptr = false;
337#define MAXDEPTHHACK 4 364#define MAXDEPTHHACK 4
338 365
@@ -352,19 +379,19 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
352 379
353 GstCaps *desired_caps; 380 GstCaps *desired_caps;
354 GstStructure *desired_struct; 381 GstStructure *desired_struct;
355 desired_caps = llgst_caps_copy (caps); 382 desired_caps = gst_caps_copy (caps);
356 desired_struct = llgst_caps_get_structure (desired_caps, 0); 383 desired_struct = gst_caps_get_structure (desired_caps, 0);
357 384
358 GValue value = {0}; 385 GValue value = {0};
359 g_value_init(&value, G_TYPE_INT); 386 g_value_init(&value, G_TYPE_INT);
360 g_value_set_int(&value, slwantwidth); 387 g_value_set_int(&value, slwantwidth);
361 llgst_structure_set_value (desired_struct, "width", &value); 388 gst_structure_set_value (desired_struct, "width", &value);
362 g_value_unset(&value); 389 g_value_unset(&value);
363 g_value_init(&value, G_TYPE_INT); 390 g_value_init(&value, G_TYPE_INT);
364 g_value_set_int(&value, slwantheight); 391 g_value_set_int(&value, slwantheight);
365 llgst_structure_set_value (desired_struct, "height", &value); 392 gst_structure_set_value (desired_struct, "height", &value);
366 393
367 if (llgst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (slvideo), 394 if (gst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (slvideo),
368 desired_caps)) 395 desired_caps))
369 { 396 {
370 // todo: re-use buffers from a pool? 397 // todo: re-use buffers from a pool?
@@ -375,13 +402,13 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
375 GST_BUFFER_SIZE(newbuf) = slwantwidth * slwantheight * MAXDEPTHHACK; 402 GST_BUFFER_SIZE(newbuf) = slwantwidth * slwantheight * MAXDEPTHHACK;
376 GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf)); 403 GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf));
377 GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf); 404 GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf);
378 llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), desired_caps); 405 gst_buffer_set_caps (GST_BUFFER_CAST(newbuf), desired_caps);
379 406
380 made_bufferdata_ptr = true; 407 made_bufferdata_ptr = true;
381 } else { 408 } else {
382 // peer hates our cap suggestion 409 // peer hates our cap suggestion
383 INFOMSG("peer hates us :("); 410 INFOMSG("peer hates us :(");
384 llgst_caps_unref(desired_caps); 411 gst_caps_unref(desired_caps);
385 } 412 }
386 } 413 }
387 } 414 }
@@ -393,7 +420,7 @@ gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
393 GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK; 420 GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK;
394 GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf)); 421 GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf));
395 GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf); 422 GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf);
396 llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps); 423 gst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps);
397 } 424 }
398 425
399 *buf = GST_BUFFER_CAST(newbuf); 426 *buf = GST_BUFFER_CAST(newbuf);
@@ -435,6 +462,20 @@ gst_slvideo_class_init (GstSLVideoClass * klass)
435#undef LLGST_DEBUG_FUNCPTR 462#undef LLGST_DEBUG_FUNCPTR
436} 463}
437 464
465/*
466static void
467gst_slvideo_update_caps (GstSLVideo * slvideo)
468{
469 GstCaps *caps;
470
471 // GStreamer will automatically convert colourspace if necessary.
472 // GStreamer will automatically resize media to one of these enumerated
473 // powers-of-two that we ask for (yay GStreamer!)
474 caps = gst_caps_from_string (SLV_ALLCAPS);
475
476 gst_caps_replace (&slvideo->caps, caps);
477}
478*/
438 479
439/* initialize the new element 480/* initialize the new element
440 * instantiate pads and add them to element 481 * instantiate pads and add them to element
@@ -457,24 +498,24 @@ gst_slvideo_init (GstSLVideo * filter,
457 filter->retained_frame_width = filter->width; 498 filter->retained_frame_width = filter->width;
458 filter->retained_frame_height = filter->height; 499 filter->retained_frame_height = filter->height;
459 filter->retained_frame_format = SLV_PF_UNKNOWN; 500 filter->retained_frame_format = SLV_PF_UNKNOWN;
460 GstCaps *caps = llgst_caps_from_string (SLV_ALLCAPS); 501 GstCaps *caps = gst_caps_from_string (SLV_ALLCAPS);
461 llgst_caps_replace (&filter->caps, caps); 502 gst_caps_replace (&filter->caps, caps);
462 filter->resize_forced_always = false; 503 filter->resize_forced_always = false;
463 filter->resize_try_width = -1; 504 filter->resize_try_width = -1;
464 filter->resize_try_height = -1; 505 filter->resize_try_height = -1;
465 GST_OBJECT_UNLOCK(filter); 506 GST_OBJECT_UNLOCK(filter);
507
508 //gst_slvideo_update_caps(filter);
466} 509}
467 510
468static void 511static void
469gst_slvideo_set_property (GObject * object, guint prop_id, 512gst_slvideo_set_property (GObject * object, guint prop_id,
470 const GValue * value, GParamSpec * pspec) 513 const GValue * value, GParamSpec * pspec)
471{ 514{
472 llg_return_if_fail (GST_IS_SLVIDEO (object)); 515 g_return_if_fail (GST_IS_SLVIDEO (object));
473 516
474 switch (prop_id) { 517 if (prop_id) {
475 default:
476 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 518 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
477 break;
478 } 519 }
479} 520}
480 521
@@ -482,12 +523,10 @@ static void
482gst_slvideo_get_property (GObject * object, guint prop_id, 523gst_slvideo_get_property (GObject * object, guint prop_id,
483 GValue * value, GParamSpec * pspec) 524 GValue * value, GParamSpec * pspec)
484{ 525{
485 llg_return_if_fail (GST_IS_SLVIDEO (object)); 526 g_return_if_fail (GST_IS_SLVIDEO (object));
486 527
487 switch (prop_id) { 528 if (prop_id) {
488 default:
489 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 529 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
490 break;
491 } 530 }
492} 531}
493 532
@@ -505,7 +544,7 @@ plugin_init (GstPlugin * plugin)
505 GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin", 544 GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin",
506 0, (gchar*)"Second Life Video Sink"); 545 0, (gchar*)"Second Life Video Sink");
507 546
508 return llgst_element_register (plugin, "private-slvideo", 547 return gst_element_register (plugin, "private-slvideo",
509 GST_RANK_NONE, GST_TYPE_SLVIDEO); 548 GST_RANK_NONE, GST_TYPE_SLVIDEO);
510} 549}
511 550
@@ -515,20 +554,19 @@ plugin_init (GstPlugin * plugin)
515 some g++ versions buggily avoid __attribute__((constructor)) functions - 554 some g++ versions buggily avoid __attribute__((constructor)) functions -
516 so we provide an explicit plugin init function. 555 so we provide an explicit plugin init function.
517 */ 556 */
518#define PACKAGE (gchar*)"packagehack" 557
519 // this macro quietly refers to PACKAGE internally
520 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
521 GST_VERSION_MINOR,
522 (gchar*)"private-slvideoplugin",
523 (gchar*)"SL Video sink plugin",
524 plugin_init, (gchar*)"0.1", (gchar*)GST_LICENSE_UNKNOWN,
525 (gchar*)"Second Life",
526 (gchar*)"http://www.secondlife.com/");
527#undef PACKAGE
528void gst_slvideo_init_class (void) 558void gst_slvideo_init_class (void)
529{ 559{
530 ll_gst_plugin_register_static (&gst_plugin_desc); 560 gst_plugin_register_static( GST_VERSION_MAJOR,
531 DEBUGMSG("CLASS INIT"); 561 GST_VERSION_MINOR,
562 (const gchar *)"private-slvideoplugin",
563 (gchar *)"SL Video sink plugin",
564 plugin_init,
565 (const gchar *)"0.1",
566 GST_LICENSE_UNKNOWN,
567 (const gchar *)"Second Life",
568 (const gchar *)"Second Life",
569 (const gchar *)"http://www.secondlife.com/" );
532} 570}
533 571
534#endif // LL_GSTREAMER010_ENABLED 572///#endif // LL_GSTREAMER010_ENABLED
diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
index 56f6db9..0ad8cf1 100755
--- a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
+++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.h
@@ -36,12 +36,13 @@
36#ifndef __GST_SLVIDEO_H__ 36#ifndef __GST_SLVIDEO_H__
37#define __GST_SLVIDEO_H__ 37#define __GST_SLVIDEO_H__
38 38
39#if LL_GSTREAMER010_ENABLED 39///#if LL_GSTREAMER010_ENABLED
40 40
41extern "C" { 41extern "C" {
42#include <gst/gst.h> 42#include <gst/gst.h>
43#include <gst/video/video.h> 43#include <gst/video/video.h>
44#include <gst/video/gstvideosink.h> 44#include <gst/video/gstvideosink.h>
45// #include <glib/gthread.h>
45} 46}
46 47
47G_BEGIN_DECLS 48G_BEGIN_DECLS
@@ -107,6 +108,6 @@ void gst_slvideo_init_class (void);
107 108
108G_END_DECLS 109G_END_DECLS
109 110
110#endif // LL_GSTREAMER010_ENABLED 111///#endif // LL_GSTREAMER010_ENABLED
111 112
112#endif /* __GST_SLVIDEO_H__ */ 113#endif /* __GST_SLVIDEO_H__ */
diff --git a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
index 7d34a1e..4dd182e 100755
--- a/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
+++ b/linden/indra/media_plugins/gstreamer010/media_plugin_gstreamer010.cpp
@@ -46,6 +46,7 @@
46 46
47extern "C" { 47extern "C" {
48#include <gst/gst.h> 48#include <gst/gst.h>
49#include <gst/gstelement.h>
49} 50}
50 51
51#include "llmediaimplgstreamer.h" 52#include "llmediaimplgstreamer.h"
@@ -53,8 +54,6 @@ extern "C" {
53 54
54#include "llmediaimplgstreamervidplug.h" 55#include "llmediaimplgstreamervidplug.h"
55 56
56#include "llmediaimplgstreamer_syms.h"
57
58////////////////////////////////////////////////////////////////////////////// 57//////////////////////////////////////////////////////////////////////////////
59// 58//
60class MediaPluginGStreamer010 : public MediaPluginBase 59class MediaPluginGStreamer010 : public MediaPluginBase
@@ -68,6 +67,8 @@ public:
68 static bool startup(); 67 static bool startup();
69 static bool closedown(); 68 static bool closedown();
70 69
70 static void set_gst_plugin_path();
71
71 gboolean processGSTEvents(GstBus *bus, 72 gboolean processGSTEvents(GstBus *bus,
72 GstMessage *message); 73 GstMessage *message);
73 74
@@ -139,6 +140,8 @@ private:
139 140
140 bool mSeekWanted; 141 bool mSeekWanted;
141 double mSeekDestination; 142 double mSeekDestination;
143
144 std::string mLastTitle;
142 145
143 // Very GStreamer-specific 146 // Very GStreamer-specific
144 GMainLoop *mPump; // event pump for this media 147 GMainLoop *mPump; // event pump for this media
@@ -196,149 +199,179 @@ MediaPluginGStreamer010::processGSTEvents(GstBus *bus,
196 GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING) 199 GST_MESSAGE_TYPE(message) != GST_MESSAGE_BUFFERING)
197 { 200 {
198 DEBUGMSG("Got GST message type: %s", 201 DEBUGMSG("Got GST message type: %s",
199 LLGST_MESSAGE_TYPE_NAME (message)); 202 GST_MESSAGE_TYPE_NAME (message));
200 } 203 }
201 else 204 else
202 { 205 {
203 // TODO: grok 'duration' message type 206 // TODO: grok 'duration' message type
204 DEBUGMSG("Got GST message type: %s", 207 DEBUGMSG("Got GST message type: %s",
205 LLGST_MESSAGE_TYPE_NAME (message)); 208 GST_MESSAGE_TYPE_NAME (message));
206 } 209 }
207 210
208 switch (GST_MESSAGE_TYPE (message)) { 211 switch (GST_MESSAGE_TYPE (message))
209 case GST_MESSAGE_BUFFERING: { 212 {
210 // NEEDS GST 0.10.11+ 213 case GST_MESSAGE_BUFFERING:
211 if (llgst_message_parse_buffering)
212 { 214 {
215 // NEEDS GST 0.10.11+ and America discovered by C.Columbus
213 gint percent = 0; 216 gint percent = 0;
214 llgst_message_parse_buffering(message, &percent); 217 gst_message_parse_buffering(message, &percent);
215 DEBUGMSG("GST buffering: %d%%", percent); 218 DEBUGMSG("GST buffering: %d%%", percent);
216 }
217 break;
218 }
219 case GST_MESSAGE_STATE_CHANGED: {
220 GstState old_state;
221 GstState new_state;
222 GstState pending_state;
223 llgst_message_parse_state_changed(message,
224 &old_state,
225 &new_state,
226 &pending_state);
227#ifdef LL_GST_REPORT_STATE_CHANGES
228 // not generally very useful, and rather spammy.
229 DEBUGMSG("state change (old,<new>,pending): %s,<%s>,%s",
230 get_gst_state_name(old_state),
231 get_gst_state_name(new_state),
232 get_gst_state_name(pending_state));
233#endif // LL_GST_REPORT_STATE_CHANGES
234 219
235 switch (new_state) {
236 case GST_STATE_VOID_PENDING:
237 break;
238 case GST_STATE_NULL:
239 break; 220 break;
240 case GST_STATE_READY: 221 }
241 setStatus(STATUS_LOADED); 222 case GST_MESSAGE_STATE_CHANGED: {
242 break; 223 GstState old_state;
243 case GST_STATE_PAUSED: 224 GstState new_state;
244 setStatus(STATUS_PAUSED); 225 GstState pending_state;
226 gst_message_parse_state_changed(message,
227 &old_state,
228 &new_state,
229 &pending_state);
230 #ifdef LL_GST_REPORT_STATE_CHANGES
231 // not generally very useful, and rather spammy.
232 DEBUGMSG("state change (old,<new>,pending): %s,<%s>,%s",
233 get_gst_state_name(old_state),
234 get_gst_state_name(new_state),
235 get_gst_state_name(pending_state));
236 #endif // LL_GST_REPORT_STATE_CHANGES
237
238 switch (new_state)
239 {
240 case GST_STATE_VOID_PENDING:
241 break;
242 case GST_STATE_NULL:
243 break;
244 case GST_STATE_READY:
245 setStatus(STATUS_LOADED);
246 break;
247 case GST_STATE_PAUSED:
248 setStatus(STATUS_PAUSED);
249 break;
250 case GST_STATE_PLAYING:
251 setStatus(STATUS_PLAYING);
252 break;
253 }
245 break; 254 break;
246 case GST_STATE_PLAYING: 255 }
247 setStatus(STATUS_PLAYING); 256 case GST_MESSAGE_ERROR:
257 {
258 GError *err = NULL;
259 gchar *debug = NULL;
260
261 gst_message_parse_error (message, &err, &debug);
262 WARNMSG("GST error: %s", err?err->message:"(unknown)");
263 if (err)
264 g_error_free (err);
265 g_free (debug);
266
267 mCommand = COMMAND_STOP;
268
269 setStatus(STATUS_ERROR);
270
248 break; 271 break;
249 } 272 }
250 break; 273 case GST_MESSAGE_INFO:
251 }
252 case GST_MESSAGE_ERROR: {
253 GError *err = NULL;
254 gchar *debug = NULL;
255
256 llgst_message_parse_error (message, &err, &debug);
257 WARNMSG("GST error: %s", err?err->message:"(unknown)");
258 if (err)
259 g_error_free (err);
260 g_free (debug);
261
262 mCommand = COMMAND_STOP;
263
264 setStatus(STATUS_ERROR);
265
266 break;
267 }
268 case GST_MESSAGE_INFO: {
269 if (llgst_message_parse_info)
270 { 274 {
271 GError *err = NULL; 275 GError *err = NULL;
272 gchar *debug = NULL; 276 gchar *debug = NULL;
273 277
274 llgst_message_parse_info (message, &err, &debug); 278 gst_message_parse_info (message, &err, &debug);
275 INFOMSG("GST info: %s", err?err->message:"(unknown)"); 279 INFOMSG("GST info: %s", err?err->message:"(unknown)");
276 if (err) 280 if (err)
277 g_error_free (err); 281 g_error_free (err);
278 g_free (debug); 282 g_free (debug);
283
284 break;
279 } 285 }
280 break; 286 case GST_MESSAGE_WARNING:
281 } 287 {
282 case GST_MESSAGE_WARNING: { 288 GError *err = NULL;
283 GError *err = NULL; 289 gchar *debug = NULL;
284 gchar *debug = NULL; 290
291 gst_message_parse_warning (message, &err, &debug);
292 WARNMSG("GST warning: %s", err?err->message:"(unknown)");
293 if (err)
294 g_error_free (err);
295 g_free (debug);
296
297 break;
298 }
299 case GST_MESSAGE_TAG:
300 {
301 GstTagList *new_tags;
285 302
286 llgst_message_parse_warning (message, &err, &debug); 303 gst_message_parse_tag( message, &new_tags );
287 WARNMSG("GST warning: %s", err?err->message:"(unknown)");
288 if (err)
289 g_error_free (err);
290 g_free (debug);
291 304
292 break; 305 gchar *title = NULL;
293 }
294 case GST_MESSAGE_EOS:
295 /* end-of-stream */
296 DEBUGMSG("GST end-of-stream.");
297 if (mIsLooping)
298 {
299 DEBUGMSG("looping media...");
300 double eos_pos_sec = 0.0F;
301 bool got_eos_position = getTimePos(eos_pos_sec);
302 306
303 if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC) 307 if ( gst_tag_list_get_string(new_tags, GST_TAG_TITLE, &title) )
304 { 308 {
305 // if we know that the movie is really short, don't 309 //WARMING("Title: %s", title);
306 // loop it else it can easily become a time-hog 310 std::string newtitle(title);
307 // because of GStreamer spin-up overhead 311 gst_tag_list_free(new_tags);
308 DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec); 312
309 // inject a COMMAND_PAUSE 313 if ( newtitle != mLastTitle && !newtitle.empty() )
310 mCommand = COMMAND_PAUSE; 314 {
315 LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
316 message.setValue("name", newtitle );
317 sendMessage( message );
318 mLastTitle = newtitle;
319 }
320 g_free(title);
311 } 321 }
312 else 322
323 break;
324 }
325 case GST_MESSAGE_EOS:
326 {
327 /* end-of-stream */
328 DEBUGMSG("GST end-of-stream.");
329 if (mIsLooping)
313 { 330 {
314#undef LLGST_LOOP_BY_SEEKING 331 DEBUGMSG("looping media...");
315// loop with a stop-start instead of a seek, because it actually seems rather 332 double eos_pos_sec = 0.0F;
316// faster than seeking on remote streams. 333 bool got_eos_position = getTimePos(eos_pos_sec);
317#ifdef LLGST_LOOP_BY_SEEKING 334
318 // first, try looping by an explicit rewind 335 if (got_eos_position && eos_pos_sec < MIN_LOOP_SEC)
319 bool seeksuccess = seek(0.0);
320 if (seeksuccess)
321 { 336 {
322 play(1.0); 337 // if we know that the movie is really short, don't
338 // loop it else it can easily become a time-hog
339 // because of GStreamer spin-up overhead
340 DEBUGMSG("really short movie (%0.3fsec) - not gonna loop this, pausing instead.", eos_pos_sec);
341 // inject a COMMAND_PAUSE
342 mCommand = COMMAND_PAUSE;
323 } 343 }
324 else 344 else
325#endif // LLGST_LOOP_BY_SEEKING 345 {
326 { // use clumsy stop-start to loop 346 #undef LLGST_LOOP_BY_SEEKING
327 DEBUGMSG("didn't loop by rewinding - stopping and starting instead..."); 347 // loop with a stop-start instead of a seek, because it actually seems rather
328 stop(); 348 // faster than seeking on remote streams.
329 play(1.0); 349 #ifdef LLGST_LOOP_BY_SEEKING
350 // first, try looping by an explicit rewind
351 bool seeksuccess = seek(0.0);
352 if (seeksuccess)
353 {
354 play(1.0);
355 }
356 else
357 #endif // LLGST_LOOP_BY_SEEKING
358 { // use clumsy stop-start to loop
359 DEBUGMSG("didn't loop by rewinding - stopping and starting instead...");
360 stop();
361 play(1.0);
362 }
330 } 363 }
331 } 364 }
332 } 365 else // not a looping media
333 else // not a looping media 366 {
334 { 367 // inject a COMMAND_STOP
335 // inject a COMMAND_STOP 368 mCommand = COMMAND_STOP;
336 mCommand = COMMAND_STOP; 369 }
337 } 370 } break;
338 break; 371
339 default: 372 default:
340 /* unhandled message */ 373 /* unhandled message */
341 break; 374 break;
342 } 375 }
343 376
344 /* we want to be notified again the next time there is a message 377 /* we want to be notified again the next time there is a message
@@ -544,7 +577,7 @@ MediaPluginGStreamer010::pause()
544{ 577{
545 DEBUGMSG("pausing media..."); 578 DEBUGMSG("pausing media...");
546 // todo: error-check this? 579 // todo: error-check this?
547 llgst_element_set_state(mPlaybin, GST_STATE_PAUSED); 580 gst_element_set_state(mPlaybin, GST_STATE_PAUSED);
548 return true; 581 return true;
549} 582}
550 583
@@ -553,7 +586,7 @@ MediaPluginGStreamer010::stop()
553{ 586{
554 DEBUGMSG("stopping media..."); 587 DEBUGMSG("stopping media...");
555 // todo: error-check this? 588 // todo: error-check this?
556 llgst_element_set_state(mPlaybin, GST_STATE_READY); 589 gst_element_set_state(mPlaybin, GST_STATE_READY);
557 return true; 590 return true;
558} 591}
559 592
@@ -564,7 +597,7 @@ MediaPluginGStreamer010::play(double rate)
564 597
565 DEBUGMSG("playing media... rate=%f", rate); 598 DEBUGMSG("playing media... rate=%f", rate);
566 // todo: error-check this? 599 // todo: error-check this?
567 llgst_element_set_state(mPlaybin, GST_STATE_PLAYING); 600 gst_element_set_state(mPlaybin, GST_STATE_PLAYING);
568 return true; 601 return true;
569} 602}
570 603
@@ -593,7 +626,7 @@ MediaPluginGStreamer010::seek(double time_sec)
593 bool success = false; 626 bool success = false;
594 if (mDoneInit && mPlaybin) 627 if (mDoneInit && mPlaybin)
595 { 628 {
596 success = llgst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME, 629 success = gst_element_seek(mPlaybin, 1.0F, GST_FORMAT_TIME,
597 GstSeekFlags(GST_SEEK_FLAG_FLUSH | 630 GstSeekFlags(GST_SEEK_FLAG_FLUSH |
598 GST_SEEK_FLAG_KEY_UNIT), 631 GST_SEEK_FLAG_KEY_UNIT),
599 GST_SEEK_TYPE_SET, gint64(time_sec*GST_SECOND), 632 GST_SEEK_TYPE_SET, gint64(time_sec*GST_SECOND),
@@ -612,11 +645,9 @@ MediaPluginGStreamer010::getTimePos(double &sec_out)
612 { 645 {
613 gint64 pos; 646 gint64 pos;
614 GstFormat timefmt = GST_FORMAT_TIME; 647 GstFormat timefmt = GST_FORMAT_TIME;
615 got_position = 648 got_position = gst_element_query_position(mPlaybin,
616 llgst_element_query_position && 649 &timefmt,
617 llgst_element_query_position(mPlaybin, 650 &pos);
618 &timefmt,
619 &pos);
620 got_position = got_position 651 got_position = got_position
621 && (timefmt == GST_FORMAT_TIME); 652 && (timefmt == GST_FORMAT_TIME);
622 // GStreamer may have other ideas, but we consider the current position 653 // GStreamer may have other ideas, but we consider the current position
@@ -669,7 +700,7 @@ MediaPluginGStreamer010::load()
669 } 700 }
670 701
671 // instantiate a playbin element to do the hard work 702 // instantiate a playbin element to do the hard work
672 mPlaybin = llgst_element_factory_make ("playbin", "play"); 703 mPlaybin = gst_element_factory_make ("playbin", "play");
673 if (!mPlaybin) 704 if (!mPlaybin)
674 { 705 {
675 setStatus(STATUS_ERROR); 706 setStatus(STATUS_ERROR);
@@ -677,21 +708,21 @@ MediaPluginGStreamer010::load()
677 } 708 }
678 709
679 // get playbin's bus 710 // get playbin's bus
680 GstBus *bus = llgst_pipeline_get_bus (GST_PIPELINE (mPlaybin)); 711 GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (mPlaybin));
681 if (!bus) 712 if (!bus)
682 { 713 {
683 setStatus(STATUS_ERROR); 714 setStatus(STATUS_ERROR);
684 return false; // error 715 return false; // error
685 } 716 }
686 mBusWatchID = llgst_bus_add_watch (bus, 717 mBusWatchID = gst_bus_add_watch (bus,
687 llmediaimplgstreamer_bus_callback, 718 llmediaimplgstreamer_bus_callback,
688 this); 719 this);
689 llgst_object_unref (bus); 720 gst_object_unref (bus);
690 721
691 if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) { 722 if (NULL == getenv("LL_GSTREAMER_EXTERNAL")) {
692 // instantiate a custom video sink 723 // instantiate a custom video sink
693 mVideoSink = 724 mVideoSink =
694 GST_SLVIDEO(llgst_element_factory_make ("private-slvideo", "slvideo")); 725 GST_SLVIDEO(gst_element_factory_make ("private-slvideo", "slvideo"));
695 if (!mVideoSink) 726 if (!mVideoSink)
696 { 727 {
697 WARNMSG("Could not instantiate private-slvideo element."); 728 WARNMSG("Could not instantiate private-slvideo element.");
@@ -721,8 +752,8 @@ MediaPluginGStreamer010::unload ()
721 752
722 if (mPlaybin) 753 if (mPlaybin)
723 { 754 {
724 llgst_element_set_state (mPlaybin, GST_STATE_NULL); 755 gst_element_set_state (mPlaybin, GST_STATE_NULL);
725 llgst_object_unref (GST_OBJECT (mPlaybin)); 756 gst_object_unref (GST_OBJECT (mPlaybin));
726 mPlaybin = NULL; 757 mPlaybin = NULL;
727 } 758 }
728 759
@@ -755,7 +786,10 @@ MediaPluginGStreamer010::startup()
755 786
756 // Init the glib type system - we need it. 787 // Init the glib type system - we need it.
757 g_type_init(); 788 g_type_init();
789 set_gst_plugin_path();
790
758 791
792/*
759 // Get symbols! 793 // Get symbols!
760#if LL_DARWIN 794#if LL_DARWIN
761 if (! grab_gst_syms("libgstreamer-0.10.dylib", 795 if (! grab_gst_syms("libgstreamer-0.10.dylib",
@@ -771,24 +805,24 @@ MediaPluginGStreamer010::startup()
771 WARNMSG("Couldn't find suitable GStreamer 0.10 support on this system - video playback disabled."); 805 WARNMSG("Couldn't find suitable GStreamer 0.10 support on this system - video playback disabled.");
772 return false; 806 return false;
773 } 807 }
774 808*/
775 if (llgst_segtrap_set_enabled) 809// if (gst_segtrap_set_enabled)
776 { 810// {
777 llgst_segtrap_set_enabled(FALSE); 811 gst_segtrap_set_enabled(FALSE);
778 } 812// }
779 else 813// else
780 { 814// {
781 WARNMSG("gst_segtrap_set_enabled() is not available; plugin crashes won't be caught."); 815// WARNMSG("gst_segtrap_set_enabled() is not available; plugin crashes won't be caught.");
782 } 816// }
783 817/*
784#if LL_LINUX 818#if LL_LINUX
785 // Gstreamer tries a fork during init, waitpid-ing on it, 819 // Gstreamer tries a fork during init, waitpid-ing on it,
786 // which conflicts with any installed SIGCHLD handler... 820 // which conflicts with any installed SIGCHLD handler...
787 struct sigaction tmpact, oldact; 821 struct sigaction tmpact, oldact;
788 if (llgst_registry_fork_set_enabled) { 822 if (gst_registry_fork_set_enabled) {
789 // if we can disable SIGCHLD-using forking behaviour, 823 // if we can disable SIGCHLD-using forking behaviour,
790 // do it. 824 // do it.
791 llgst_registry_fork_set_enabled(false); 825 gst_registry_fork_set_enabled(false);
792 } 826 }
793 else { 827 else {
794 // else temporarily install default SIGCHLD handler 828 // else temporarily install default SIGCHLD handler
@@ -799,24 +833,24 @@ MediaPluginGStreamer010::startup()
799 sigaction(SIGCHLD, &tmpact, &oldact); 833 sigaction(SIGCHLD, &tmpact, &oldact);
800 } 834 }
801#endif // LL_LINUX 835#endif // LL_LINUX
802 836*/
803 // Protect against GStreamer resetting the locale, yuck. 837 // Protect against GStreamer resetting the locale, yuck.
804 static std::string saved_locale; 838 static std::string saved_locale;
805 saved_locale = setlocale(LC_ALL, NULL); 839 saved_locale = setlocale(LC_ALL, NULL);
806 840
807 // finally, try to initialize GStreamer! 841 // finally, try to initialize GStreamer!
808 GError *err = NULL; 842 GError *err = NULL;
809 gboolean init_gst_success = llgst_init_check(NULL, NULL, &err); 843 gboolean init_gst_success = gst_init_check(NULL, NULL, &err);
810 844
811 // restore old locale 845 // restore old locale
812 setlocale(LC_ALL, saved_locale.c_str() ); 846 setlocale(LC_ALL, saved_locale.c_str() );
813 847/*
814#if LL_LINUX 848#if LL_LINUX
815 // restore old SIGCHLD handler 849 // restore old SIGCHLD handler
816 if (!llgst_registry_fork_set_enabled) 850 if (!gst_registry_fork_set_enabled)
817 sigaction(SIGCHLD, &oldact, NULL); 851 sigaction(SIGCHLD, &oldact, NULL);
818#endif // LL_LINUX 852#endif // LL_LINUX
819 853*/
820 if (!init_gst_success) // fail 854 if (!init_gst_success) // fail
821 { 855 {
822 if (err) 856 if (err)
@@ -830,16 +864,139 @@ MediaPluginGStreamer010::startup()
830 } 864 }
831 return false; 865 return false;
832 } 866 }
833 867
868 // Set up logging facilities
869 gst_debug_remove_log_function( gst_debug_log_default );
870// gst_debug_add_log_function( gstreamer_log, NULL );
871
834 // Init our custom plugins - only really need do this once. 872 // Init our custom plugins - only really need do this once.
835 gst_slvideo_init_class(); 873 gst_slvideo_init_class();
836 874/*
875 // List the plugins GStreamer can find
876 LL_DEBUGS("MediaImpl") << "Found GStreamer plugins:" << LL_ENDL;
877 GList *list;
878 GstRegistry *registry = gst_registry_get_default();
879 std::string loaded = "";
880 for (list = gst_registry_get_plugin_list(registry);
881 list != NULL;
882 list = g_list_next(list))
883 {
884 GstPlugin *list_plugin = (GstPlugin *)list->data;
885 (bool)gst_plugin_is_loaded(list_plugin) ? loaded = "Yes" : loaded = "No";
886 LL_DEBUGS("MediaImpl") << gst_plugin_get_name(list_plugin) << ", loaded? " << loaded << LL_ENDL;
887 }
888 gst_plugin_list_free(list);
889*/
837 mDoneInit = true; 890 mDoneInit = true;
838 } 891 }
839 892
840 return true; 893 return true;
841} 894}
842 895
896void MediaPluginGStreamer010::set_gst_plugin_path()
897{
898 // Linux sets GST_PLUGIN_PATH in wrapper.sh, not here.
899#if LL_WINDOWS || LL_DARWIN
900
901 std::string imp_dir = "";
902
903 // Get the current working directory:
904#if LL_WINDOWS
905 char* raw_dir;
906 raw_dir = _getcwd(NULL,0);
907 if( raw_dir != NULL )
908 {
909 imp_dir = std::string( raw_dir );
910 }
911#elif LL_DARWIN
912 CFBundleRef main_bundle = CFBundleGetMainBundle();
913 if( main_bundle != NULL )
914 {
915 CFURLRef bundle_url = CFBundleCopyBundleURL( main_bundle );
916 if( bundle_url != NULL )
917 {
918 #ifndef MAXPATHLEN
919 #define MAXPATHLEN 1024
920 #endif
921 char raw_dir[MAXPATHLEN];
922 if( CFURLGetFileSystemRepresentation( bundle_url, true, (UInt8 *)raw_dir, MAXPATHLEN) )
923 {
924 imp_dir = std::string( raw_dir ) + "/Contents/MacOS/";
925 }
926 CFRelease(bundle_url);
927 }
928 }
929#endif
930
931 if( imp_dir == "" )
932 {
933 WARNMSG("Could not get application directory, not setting GST_PLUGIN_PATH.");
934 return;
935 }
936
937 DEBUGMSG("Imprudence is installed at %s", imp_dir);
938
939 // ":" on Mac and 'Nix, ";" on Windows
940 std::string separator = G_SEARCHPATH_SEPARATOR_S;
941
942 // Grab the current path, if it's set.
943 std::string old_plugin_path = "";
944 char *old_path = getenv("GST_PLUGIN_PATH");
945 if(old_path == NULL)
946 {
947 DEBUGMSG("Did not find user-set GST_PLUGIN_PATH.");
948 }
949 else
950 {
951 old_plugin_path = separator + std::string( old_path );
952 }
953
954
955 // Search both Imprudence and Imprudence\lib\gstreamer-plugins.
956 // But we also want to search the path the user has set, if any.
957 std::string plugin_path =
958 "GST_PLUGIN_PATH=" +
959#if LL_WINDOWS
960 imp_dir + "\\lib\\gstreamer-plugins" +
961#elif LL_DARWIN
962 imp_dir + separator +
963 imp_dir + "/../Resources/lib/gstreamer-plugins" +
964#endif
965 old_plugin_path;
966
967 int put_result;
968
969 // Place GST_PLUGIN_PATH in the environment settings
970#if LL_WINDOWS
971 put_result = _putenv( (char*)plugin_path.c_str() );
972#elif LL_DARWIN
973 put_result = putenv( (char*)plugin_path.c_str() );
974#endif
975
976 if( put_result == -1 )
977 {
978 WARNMSG("Setting GST_PLUGIN_PATH failed!");
979 }
980 else
981 {
982 DEBUGMSG("GST_PLUGIN_PATH set to %s", getenv("GST_PLUGIN_PATH"));
983 }
984
985 // Don't load system plugins. We only want to use ours, to avoid conflicts.
986#if LL_WINDOWS
987 put_result = _putenv( "GST_PLUGIN_SYSTEM_PATH=\"\"" );
988#elif LL_DARWIN
989 put_result = putenv( "GST_PLUGIN_SYSTEM_PATH=\"\"" );
990#endif
991
992 if( put_result == -1 )
993 {
994 WARNMSG("Setting GST_PLUGIN_SYSTEM_PATH=\"\" failed!");
995 }
996
997#endif // LL_WINDOWS || LL_DARWIN
998}
999
843 1000
844void 1001void
845MediaPluginGStreamer010::sizeChanged() 1002MediaPluginGStreamer010::sizeChanged()
@@ -881,7 +1038,7 @@ MediaPluginGStreamer010::closedown()
881 if (!mDoneInit) 1038 if (!mDoneInit)
882 return false; // error 1039 return false; // error
883 1040
884 ungrab_gst_syms(); 1041// ungrab_gst_syms();
885 1042
886 mDoneInit = false; 1043 mDoneInit = false;
887 1044
@@ -902,11 +1059,10 @@ std::string
902MediaPluginGStreamer010::getVersion() 1059MediaPluginGStreamer010::getVersion()
903{ 1060{
904 std::string plugin_version = "GStreamer010 media plugin, GStreamer version "; 1061 std::string plugin_version = "GStreamer010 media plugin, GStreamer version ";
905 if (mDoneInit && 1062 if (mDoneInit) // && gst_version)
906 llgst_version)
907 { 1063 {
908 guint major, minor, micro, nano; 1064 guint major, minor, micro, nano;
909 llgst_version(&major, &minor, &micro, &nano); 1065 gst_version(&major, &minor, &micro, &nano);
910 plugin_version += llformat("%u.%u.%u.%u (runtime), %u.%u.%u.%u (headers)", (unsigned int)major, (unsigned int)minor, (unsigned int)micro, (unsigned int)nano, (unsigned int)GST_VERSION_MAJOR, (unsigned int)GST_VERSION_MINOR, (unsigned int)GST_VERSION_MICRO, (unsigned int)GST_VERSION_NANO); 1066 plugin_version += llformat("%u.%u.%u.%u (runtime), %u.%u.%u.%u (headers)", (unsigned int)major, (unsigned int)minor, (unsigned int)micro, (unsigned int)nano, (unsigned int)GST_VERSION_MAJOR, (unsigned int)GST_VERSION_MINOR, (unsigned int)GST_VERSION_MICRO, (unsigned int)GST_VERSION_NANO);
911 } 1067 }
912 else 1068 else