diff options
Diffstat (limited to 'linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp')
-rwxr-xr-x | linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp | 572 |
1 files changed, 572 insertions, 0 deletions
diff --git a/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp new file mode 100755 index 0000000..1fee545 --- /dev/null +++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp | |||
@@ -0,0 +1,572 @@ | |||
1 | /** | ||
2 | * @file llmediaimplgstreamervidplug.h | ||
3 | * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl | ||
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 "linden_common.h" | ||
39 | |||
40 | #include <gst/gst.h> | ||
41 | #include <gst/video/video.h> | ||
42 | #include <gst/video/gstvideosink.h> | ||
43 | |||
44 | #include "llmediaimplgstreamertriviallogging.h" | ||
45 | // #include "llthread.h" | ||
46 | |||
47 | #include "llmediaimplgstreamervidplug.h" | ||
48 | |||
49 | GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug); | ||
50 | #define GST_CAT_DEFAULT gst_slvideo_debug | ||
51 | |||
52 | /* Filter signals and args *//* | ||
53 | enum | ||
54 | { | ||
55 | *//* FILL ME *//* | ||
56 | LAST_SIGNAL | ||
57 | }; | ||
58 | |||
59 | enum | ||
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 | */ | ||
67 | |||
68 | #define SLV_SIZECAPS ", width=(int)[1,2048], height=(int)[1,2048] " | ||
69 | #define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS | ||
70 | |||
71 | static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ( | ||
72 | (gchar*)"sink", | ||
73 | GST_PAD_SINK, | ||
74 | GST_PAD_ALWAYS, | ||
75 | GST_STATIC_CAPS (SLV_ALLCAPS) | ||
76 | ); | ||
77 | |||
78 | GST_BOILERPLATE (GstSLVideo, gst_slvideo, GstVideoSink, | ||
79 | GST_TYPE_VIDEO_SINK); | ||
80 | |||
81 | static void gst_slvideo_set_property (GObject * object, guint prop_id, | ||
82 | const GValue * value, | ||
83 | GParamSpec * pspec); | ||
84 | static void gst_slvideo_get_property (GObject * object, guint prop_id, | ||
85 | GValue * value, GParamSpec * pspec); | ||
86 | |||
87 | static void | ||
88 | gst_slvideo_base_init (gpointer gclass) | ||
89 | { | ||
90 | static GstElementDetails element_details = { | ||
91 | (gchar*)"PluginTemplate", | ||
92 | (gchar*)"Generic/PluginTemplate", | ||
93 | (gchar*)"Generic Template Element", | ||
94 | (gchar*)"Linden Lab" | ||
95 | }; | ||
96 | GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); | ||
97 | |||
98 | gst_element_class_add_pad_template (element_class, | ||
99 | gst_static_pad_template_get (&sink_factory)); | ||
100 | gst_element_class_set_details (element_class, &element_details); | ||
101 | } | ||
102 | |||
103 | |||
104 | static void | ||
105 | gst_slvideo_finalize (GObject * object) | ||
106 | { | ||
107 | GstSLVideo *slvideo; | ||
108 | slvideo = GST_SLVIDEO (object); | ||
109 | if (slvideo->caps) | ||
110 | { | ||
111 | gst_caps_unref(slvideo->caps); | ||
112 | } | ||
113 | |||
114 | G_OBJECT_CLASS(parent_class)->finalize (object); | ||
115 | } | ||
116 | |||
117 | |||
118 | static GstFlowReturn | ||
119 | gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf) | ||
120 | { | ||
121 | GstSLVideo *slvideo; | ||
122 | g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); | ||
123 | |||
124 | slvideo = GST_SLVIDEO(bsink); | ||
125 | |||
126 | DEBUGMSG("transferring a frame of %dx%d <- %p (%d)", | ||
127 | slvideo->width, slvideo->height, GST_BUFFER_DATA(buf), | ||
128 | slvideo->format); | ||
129 | |||
130 | if (GST_BUFFER_DATA(buf)) | ||
131 | { | ||
132 | // copy frame and frame info into neutral territory | ||
133 | GST_OBJECT_LOCK(slvideo); | ||
134 | slvideo->retained_frame_ready = TRUE; | ||
135 | slvideo->retained_frame_width = slvideo->width; | ||
136 | slvideo->retained_frame_height = slvideo->height; | ||
137 | slvideo->retained_frame_format = slvideo->format; | ||
138 | int rowbytes = | ||
139 | SLVPixelFormatBytes[slvideo->retained_frame_format] * | ||
140 | slvideo->retained_frame_width; | ||
141 | int needbytes = rowbytes * slvideo->retained_frame_width; | ||
142 | // resize retained frame hunk only if necessary | ||
143 | if (needbytes != slvideo->retained_frame_allocbytes) | ||
144 | { | ||
145 | delete[] slvideo->retained_frame_data; | ||
146 | slvideo->retained_frame_data = new unsigned char[needbytes]; | ||
147 | slvideo->retained_frame_allocbytes = needbytes; | ||
148 | |||
149 | } | ||
150 | // copy the actual frame data to neutral territory - | ||
151 | // flipped, for GL reasons | ||
152 | for (int ypos=0; ypos<slvideo->height; ++ypos) | ||
153 | { | ||
154 | memcpy(&slvideo->retained_frame_data[(slvideo->height-1-ypos)*rowbytes], | ||
155 | &(((unsigned char*)GST_BUFFER_DATA(buf))[ypos*rowbytes]), | ||
156 | rowbytes); | ||
157 | } | ||
158 | // done with the shared data | ||
159 | GST_OBJECT_UNLOCK(slvideo); | ||
160 | } | ||
161 | |||
162 | return GST_FLOW_OK; | ||
163 | } | ||
164 | |||
165 | |||
166 | static GstStateChangeReturn | ||
167 | gst_slvideo_change_state(GstElement * element, GstStateChange transition) | ||
168 | { | ||
169 | GstSLVideo *slvideo; | ||
170 | GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; | ||
171 | |||
172 | slvideo = GST_SLVIDEO (element); | ||
173 | |||
174 | switch (transition) { | ||
175 | case GST_STATE_CHANGE_NULL_TO_READY: | ||
176 | break; | ||
177 | case GST_STATE_CHANGE_READY_TO_PAUSED: | ||
178 | break; | ||
179 | case GST_STATE_CHANGE_PAUSED_TO_PLAYING: | ||
180 | break; | ||
181 | default: | ||
182 | break; | ||
183 | } | ||
184 | |||
185 | ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); | ||
186 | if (ret == GST_STATE_CHANGE_FAILURE) | ||
187 | return ret; | ||
188 | |||
189 | switch (transition) { | ||
190 | case GST_STATE_CHANGE_PLAYING_TO_PAUSED: | ||
191 | break; | ||
192 | case GST_STATE_CHANGE_PAUSED_TO_READY: | ||
193 | slvideo->fps_n = 0; | ||
194 | slvideo->fps_d = 1; | ||
195 | GST_VIDEO_SINK_WIDTH(slvideo) = 0; | ||
196 | GST_VIDEO_SINK_HEIGHT(slvideo) = 0; | ||
197 | break; | ||
198 | case GST_STATE_CHANGE_READY_TO_NULL: | ||
199 | break; | ||
200 | default: | ||
201 | break; | ||
202 | } | ||
203 | |||
204 | return ret; | ||
205 | } | ||
206 | |||
207 | |||
208 | static GstCaps * | ||
209 | gst_slvideo_get_caps (GstBaseSink * bsink) | ||
210 | { | ||
211 | GstSLVideo *slvideo; | ||
212 | slvideo = GST_SLVIDEO(bsink); | ||
213 | |||
214 | return gst_caps_ref (slvideo->caps); | ||
215 | } | ||
216 | |||
217 | |||
218 | /* this function handles the link with other elements */ | ||
219 | static gboolean | ||
220 | gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps) | ||
221 | { | ||
222 | GstSLVideo *filter; | ||
223 | GstStructure *structure; | ||
224 | // GstCaps *intersection; | ||
225 | |||
226 | GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps); | ||
227 | |||
228 | filter = GST_SLVIDEO(bsink); | ||
229 | |||
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; | ||
241 | gboolean ret; | ||
242 | const GValue *fps; | ||
243 | const GValue *par; | ||
244 | structure = gst_caps_get_structure (caps, 0); | ||
245 | ret = gst_structure_get_int (structure, "width", &width); | ||
246 | ret = ret && gst_structure_get_int (structure, "height", &height); | ||
247 | fps = gst_structure_get_value (structure, "framerate"); | ||
248 | ret = ret && (fps != NULL); | ||
249 | par = gst_structure_get_value (structure, "pixel-aspect-ratio"); | ||
250 | if (!ret) | ||
251 | return FALSE; | ||
252 | |||
253 | INFOMSG("** filter caps set with width=%d, height=%d", width, height); | ||
254 | |||
255 | GST_OBJECT_LOCK(filter); | ||
256 | |||
257 | filter->width = width; | ||
258 | filter->height = height; | ||
259 | filter->fps_n = gst_value_get_fraction_numerator(fps); | ||
260 | filter->fps_d = gst_value_get_fraction_denominator(fps); | ||
261 | if (par) | ||
262 | { | ||
263 | filter->par_n = gst_value_get_fraction_numerator(par); | ||
264 | filter->par_d = gst_value_get_fraction_denominator(par); | ||
265 | } | ||
266 | else | ||
267 | { | ||
268 | filter->par_n = 1; | ||
269 | filter->par_d = 1; | ||
270 | } | ||
271 | |||
272 | GST_VIDEO_SINK_WIDTH(filter) = width; | ||
273 | GST_VIDEO_SINK_HEIGHT(filter) = height; | ||
274 | |||
275 | // crufty lump - we *always* accept *only* RGBX now. | ||
276 | /* | ||
277 | |||
278 | filter->format = SLV_PF_UNKNOWN; | ||
279 | if (0 == strcmp(gst_structure_get_name(structure), | ||
280 | "video/x-raw-rgb")) | ||
281 | { | ||
282 | int red_mask; | ||
283 | int green_mask; | ||
284 | int blue_mask; | ||
285 | gst_structure_get_int(structure, "red_mask", &red_mask); | ||
286 | gst_structure_get_int(structure, "green_mask", &green_mask); | ||
287 | gst_structure_get_int(structure, "blue_mask", &blue_mask); | ||
288 | if ((unsigned int)red_mask == 0xFF000000 && | ||
289 | (unsigned int)green_mask == 0x00FF0000 && | ||
290 | (unsigned int)blue_mask == 0x0000FF00) | ||
291 | { | ||
292 | filter->format = SLV_PF_RGBX; | ||
293 | //fprintf(stderr, "\n\nPIXEL FORMAT RGB\n\n"); | ||
294 | } else if ((unsigned int)red_mask == 0x0000FF00 && | ||
295 | (unsigned int)green_mask == 0x00FF0000 && | ||
296 | (unsigned int)blue_mask == 0xFF000000) | ||
297 | { | ||
298 | filter->format = SLV_PF_BGRX; | ||
299 | //fprintf(stderr, "\n\nPIXEL FORMAT BGR\n\n"); | ||
300 | } | ||
301 | |||
302 | }*/ | ||
303 | |||
304 | filter->format = SLV_PF_RGBX; | ||
305 | |||
306 | GST_OBJECT_UNLOCK(filter); | ||
307 | |||
308 | return TRUE; | ||
309 | } | ||
310 | |||
311 | |||
312 | static gboolean | ||
313 | gst_slvideo_start (GstBaseSink * bsink) | ||
314 | { | ||
315 | GstSLVideo *slvideo; | ||
316 | gboolean ret = TRUE; | ||
317 | |||
318 | slvideo = GST_SLVIDEO(bsink); | ||
319 | |||
320 | return ret; | ||
321 | } | ||
322 | |||
323 | static gboolean | ||
324 | gst_slvideo_stop (GstBaseSink * bsink) | ||
325 | { | ||
326 | GstSLVideo *slvideo; | ||
327 | slvideo = GST_SLVIDEO(bsink); | ||
328 | |||
329 | // free-up retained frame buffer | ||
330 | GST_OBJECT_LOCK(slvideo); | ||
331 | slvideo->retained_frame_ready = FALSE; | ||
332 | delete[] slvideo->retained_frame_data; | ||
333 | slvideo->retained_frame_data = NULL; | ||
334 | slvideo->retained_frame_allocbytes = 0; | ||
335 | GST_OBJECT_UNLOCK(slvideo); | ||
336 | |||
337 | return TRUE; | ||
338 | } | ||
339 | |||
340 | |||
341 | static GstFlowReturn | ||
342 | gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size, | ||
343 | GstCaps * caps, GstBuffer ** buf) | ||
344 | { | ||
345 | gint width, height; | ||
346 | GstStructure *structure = NULL; | ||
347 | GstSLVideo *slvideo; | ||
348 | slvideo = GST_SLVIDEO(bsink); | ||
349 | |||
350 | // caps == requested caps | ||
351 | // we can ignore these and reverse-negotiate our preferred dimensions with | ||
352 | // the peer if we like - we need to do this to obey dynamic resize requests | ||
353 | // flowing in from the app. | ||
354 | structure = gst_caps_get_structure (caps, 0); | ||
355 | if (!gst_structure_get_int(structure, "width", &width) || | ||
356 | !gst_structure_get_int(structure, "height", &height)) | ||
357 | { | ||
358 | GST_WARNING_OBJECT (slvideo, "no width/height in caps %" GST_PTR_FORMAT, caps); | ||
359 | return GST_FLOW_NOT_NEGOTIATED; | ||
360 | } | ||
361 | |||
362 | GstBuffer *newbuf = gst_buffer_new(); | ||
363 | bool made_bufferdata_ptr = false; | ||
364 | #define MAXDEPTHHACK 4 | ||
365 | |||
366 | GST_OBJECT_LOCK(slvideo); | ||
367 | if (slvideo->resize_forced_always) // app is giving us a fixed size to work with | ||
368 | { | ||
369 | gint slwantwidth, slwantheight; | ||
370 | slwantwidth = slvideo->resize_try_width; | ||
371 | slwantheight = slvideo->resize_try_height; | ||
372 | |||
373 | if (slwantwidth != width || | ||
374 | slwantheight != height) | ||
375 | { | ||
376 | // don't like requested caps, we will issue our own suggestion - copy | ||
377 | // the requested caps but substitute our own width and height and see | ||
378 | // if our peer is happy with that. | ||
379 | |||
380 | GstCaps *desired_caps; | ||
381 | GstStructure *desired_struct; | ||
382 | desired_caps = gst_caps_copy (caps); | ||
383 | desired_struct = gst_caps_get_structure (desired_caps, 0); | ||
384 | |||
385 | GValue value = {0}; | ||
386 | g_value_init(&value, G_TYPE_INT); | ||
387 | g_value_set_int(&value, slwantwidth); | ||
388 | gst_structure_set_value (desired_struct, "width", &value); | ||
389 | g_value_unset(&value); | ||
390 | g_value_init(&value, G_TYPE_INT); | ||
391 | g_value_set_int(&value, slwantheight); | ||
392 | gst_structure_set_value (desired_struct, "height", &value); | ||
393 | |||
394 | if (gst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (slvideo), | ||
395 | desired_caps)) | ||
396 | { | ||
397 | // todo: re-use buffers from a pool? | ||
398 | // todo: set MALLOCDATA to null, set DATA to point straight to shm? | ||
399 | |||
400 | // peer likes our cap suggestion | ||
401 | DEBUGMSG("peer loves us :)"); | ||
402 | GST_BUFFER_SIZE(newbuf) = slwantwidth * slwantheight * MAXDEPTHHACK; | ||
403 | GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf)); | ||
404 | GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf); | ||
405 | gst_buffer_set_caps (GST_BUFFER_CAST(newbuf), desired_caps); | ||
406 | |||
407 | made_bufferdata_ptr = true; | ||
408 | } else { | ||
409 | // peer hates our cap suggestion | ||
410 | INFOMSG("peer hates us :("); | ||
411 | gst_caps_unref(desired_caps); | ||
412 | } | ||
413 | } | ||
414 | } | ||
415 | |||
416 | GST_OBJECT_UNLOCK(slvideo); | ||
417 | |||
418 | if (!made_bufferdata_ptr) // need to fallback to malloc at original size | ||
419 | { | ||
420 | GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK; | ||
421 | GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf)); | ||
422 | GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf); | ||
423 | gst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps); | ||
424 | } | ||
425 | |||
426 | *buf = GST_BUFFER_CAST(newbuf); | ||
427 | |||
428 | return GST_FLOW_OK; | ||
429 | } | ||
430 | |||
431 | |||
432 | /* initialize the plugin's class */ | ||
433 | static void | ||
434 | gst_slvideo_class_init (GstSLVideoClass * klass) | ||
435 | { | ||
436 | GObjectClass *gobject_class; | ||
437 | GstElementClass *gstelement_class; | ||
438 | GstBaseSinkClass *gstbasesink_class; | ||
439 | |||
440 | gobject_class = (GObjectClass *) klass; | ||
441 | gstelement_class = (GstElementClass *) klass; | ||
442 | gstbasesink_class = (GstBaseSinkClass *) klass; | ||
443 | |||
444 | gobject_class->finalize = gst_slvideo_finalize; | ||
445 | gobject_class->set_property = gst_slvideo_set_property; | ||
446 | gobject_class->get_property = gst_slvideo_get_property; | ||
447 | |||
448 | gstelement_class->change_state = gst_slvideo_change_state; | ||
449 | |||
450 | #define LLGST_DEBUG_FUNCPTR(p) (p) | ||
451 | gstbasesink_class->get_caps = LLGST_DEBUG_FUNCPTR (gst_slvideo_get_caps); | ||
452 | gstbasesink_class->set_caps = LLGST_DEBUG_FUNCPTR( gst_slvideo_set_caps); | ||
453 | gstbasesink_class->buffer_alloc=LLGST_DEBUG_FUNCPTR(gst_slvideo_buffer_alloc); | ||
454 | //gstbasesink_class->get_times = LLGST_DEBUG_FUNCPTR (gst_slvideo_get_times); | ||
455 | gstbasesink_class->preroll = LLGST_DEBUG_FUNCPTR (gst_slvideo_show_frame); | ||
456 | gstbasesink_class->render = LLGST_DEBUG_FUNCPTR (gst_slvideo_show_frame); | ||
457 | |||
458 | gstbasesink_class->start = LLGST_DEBUG_FUNCPTR (gst_slvideo_start); | ||
459 | gstbasesink_class->stop = LLGST_DEBUG_FUNCPTR (gst_slvideo_stop); | ||
460 | |||
461 | // gstbasesink_class->unlock = LLGST_DEBUG_FUNCPTR (gst_slvideo_unlock); | ||
462 | #undef LLGST_DEBUG_FUNCPTR | ||
463 | } | ||
464 | |||
465 | /* | ||
466 | static void | ||
467 | gst_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 | */ | ||
479 | |||
480 | /* initialize the new element | ||
481 | * instantiate pads and add them to element | ||
482 | * set functions | ||
483 | * initialize structure | ||
484 | */ | ||
485 | static void | ||
486 | gst_slvideo_init (GstSLVideo * filter, | ||
487 | GstSLVideoClass * gclass) | ||
488 | { | ||
489 | filter->caps = NULL; | ||
490 | filter->width = -1; | ||
491 | filter->height = -1; | ||
492 | |||
493 | // this is the info we share with the client app | ||
494 | GST_OBJECT_LOCK(filter); | ||
495 | filter->retained_frame_ready = FALSE; | ||
496 | filter->retained_frame_data = NULL; | ||
497 | filter->retained_frame_allocbytes = 0; | ||
498 | filter->retained_frame_width = filter->width; | ||
499 | filter->retained_frame_height = filter->height; | ||
500 | filter->retained_frame_format = SLV_PF_UNKNOWN; | ||
501 | GstCaps *caps = gst_caps_from_string (SLV_ALLCAPS); | ||
502 | gst_caps_replace (&filter->caps, caps); | ||
503 | filter->resize_forced_always = false; | ||
504 | filter->resize_try_width = -1; | ||
505 | filter->resize_try_height = -1; | ||
506 | GST_OBJECT_UNLOCK(filter); | ||
507 | |||
508 | //gst_slvideo_update_caps(filter); | ||
509 | } | ||
510 | |||
511 | static void | ||
512 | gst_slvideo_set_property (GObject * object, guint prop_id, | ||
513 | const GValue * value, GParamSpec * pspec) | ||
514 | { | ||
515 | g_return_if_fail (GST_IS_SLVIDEO (object)); | ||
516 | |||
517 | if (prop_id) { | ||
518 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||
519 | } | ||
520 | } | ||
521 | |||
522 | static void | ||
523 | gst_slvideo_get_property (GObject * object, guint prop_id, | ||
524 | GValue * value, GParamSpec * pspec) | ||
525 | { | ||
526 | g_return_if_fail (GST_IS_SLVIDEO (object)); | ||
527 | |||
528 | if (prop_id) { | ||
529 | G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); | ||
530 | } | ||
531 | } | ||
532 | |||
533 | |||
534 | /* entry point to initialize the plug-in | ||
535 | * initialize the plug-in itself | ||
536 | * register the element factories and pad templates | ||
537 | * register the features | ||
538 | */ | ||
539 | static gboolean | ||
540 | plugin_init (GstPlugin * plugin) | ||
541 | { | ||
542 | DEBUGMSG("PLUGIN INIT"); | ||
543 | |||
544 | GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin", | ||
545 | 0, (gchar*)"Second Life Video Sink"); | ||
546 | |||
547 | return gst_element_register (plugin, "private-slvideo", | ||
548 | GST_RANK_NONE, GST_TYPE_SLVIDEO); | ||
549 | } | ||
550 | |||
551 | /* this is the structure that gstreamer looks for to register plugins | ||
552 | */ | ||
553 | /* NOTE: Can't rely upon GST_PLUGIN_DEFINE_STATIC to self-register, since | ||
554 | some g++ versions buggily avoid __attribute__((constructor)) functions - | ||
555 | so we provide an explicit plugin init function. | ||
556 | */ | ||
557 | |||
558 | void gst_slvideo_init_class (void) | ||
559 | { | ||
560 | gst_plugin_register_static( GST_VERSION_MAJOR, | ||
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/" ); | ||
570 | } | ||
571 | |||
572 | ///#endif // LL_GSTREAMER010_ENABLED | ||