aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
diff options
context:
space:
mode:
authorArmin Weatherwax2010-06-14 12:04:49 +0200
committerArmin Weatherwax2010-09-23 15:38:25 +0200
commit35df5441d3e2789663532c948731aff3a1e04728 (patch)
treeac7674289784a5f96106ea507637055a8dada78a /linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
parentChanged version to Experimental 2010.09.18 (diff)
downloadmeta-impy-35df5441d3e2789663532c948731aff3a1e04728.zip
meta-impy-35df5441d3e2789663532c948731aff3a1e04728.tar.gz
meta-impy-35df5441d3e2789663532c948731aff3a1e04728.tar.bz2
meta-impy-35df5441d3e2789663532c948731aff3a1e04728.tar.xz
llmediaplugins first step
Diffstat (limited to '')
-rw-r--r--linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp (renamed from linden/indra/llmedia/llmediaimplgstreamervidplug.cpp)252
1 files changed, 168 insertions, 84 deletions
diff --git a/linden/indra/llmedia/llmediaimplgstreamervidplug.cpp b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
index f2c0e88..25e96d4 100644
--- a/linden/indra/llmedia/llmediaimplgstreamervidplug.cpp
+++ b/linden/indra/media_plugins/gstreamer010/llmediaimplgstreamervidplug.cpp
@@ -1,5 +1,5 @@
1/** 1/**
2 * @file llmediaimplgstreamervidplug.h 2 * @file llmediaimplgstreamervidplug.cpp
3 * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl 3 * @brief Video-consuming static GStreamer plugin for gst-to-LLMediaImpl
4 * 4 *
5 * $LicenseInfo:firstyear=2007&license=viewergpl$ 5 * $LicenseInfo:firstyear=2007&license=viewergpl$
@@ -30,7 +30,7 @@
30 * $/LicenseInfo$ 30 * $/LicenseInfo$
31 */ 31 */
32 32
33///#if LL_GSTREAMER_ENABLED 33#if LL_GSTREAMER010_ENABLED
34 34
35#include "linden_common.h" 35#include "linden_common.h"
36 36
@@ -38,30 +38,21 @@
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 "llthread.h" 41#include "llmediaimplgstreamer_syms.h"
42#include "llmediaimplgstreamertriviallogging.h"
42 43
43#include "llmediaimplgstreamervidplug.h" 44#include "llmediaimplgstreamervidplug.h"
44 45
46
45GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug); 47GST_DEBUG_CATEGORY_STATIC (gst_slvideo_debug);
46#define GST_CAT_DEFAULT gst_slvideo_debug 48#define GST_CAT_DEFAULT gst_slvideo_debug
47 49
48/* Filter signals and args */
49enum
50{
51 /* FILL ME */
52 LAST_SIGNAL
53};
54
55enum
56{
57 ARG_0
58};
59 50
60#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} " 51#define SLV_SIZECAPS ", width=(int)[1,2048], height=(int)[1,2048] "
61#define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS ";" GST_VIDEO_CAPS_BGRx SLV_SIZECAPS 52#define SLV_ALLCAPS GST_VIDEO_CAPS_RGBx SLV_SIZECAPS
62 53
63static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ( 54static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE (
64 "sink", 55 (gchar*)"sink",
65 GST_PAD_SINK, 56 GST_PAD_SINK,
66 GST_PAD_ALWAYS, 57 GST_PAD_ALWAYS,
67 GST_STATIC_CAPS (SLV_ALLCAPS) 58 GST_STATIC_CAPS (SLV_ALLCAPS)
@@ -87,9 +78,9 @@ gst_slvideo_base_init (gpointer gclass)
87 }; 78 };
88 GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); 79 GstElementClass *element_class = GST_ELEMENT_CLASS (gclass);
89 80
90 gst_element_class_add_pad_template (element_class, 81 llgst_element_class_add_pad_template (element_class,
91 gst_static_pad_template_get (&sink_factory)); 82 llgst_static_pad_template_get (&sink_factory));
92 gst_element_class_set_details (element_class, &element_details); 83 llgst_element_class_set_details (element_class, &element_details);
93} 84}
94 85
95 86
@@ -100,7 +91,7 @@ gst_slvideo_finalize (GObject * object)
100 slvideo = GST_SLVIDEO (object); 91 slvideo = GST_SLVIDEO (object);
101 if (slvideo->caps) 92 if (slvideo->caps)
102 { 93 {
103 gst_caps_unref(slvideo->caps); 94 llgst_caps_unref(slvideo->caps);
104 } 95 }
105 96
106 G_OBJECT_CLASS(parent_class)->finalize (object); 97 G_OBJECT_CLASS(parent_class)->finalize (object);
@@ -111,7 +102,7 @@ static GstFlowReturn
111gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf) 102gst_slvideo_show_frame (GstBaseSink * bsink, GstBuffer * buf)
112{ 103{
113 GstSLVideo *slvideo; 104 GstSLVideo *slvideo;
114 g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); 105 llg_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
115 106
116 slvideo = GST_SLVIDEO(bsink); 107 slvideo = GST_SLVIDEO(bsink);
117 108
@@ -204,7 +195,7 @@ gst_slvideo_get_caps (GstBaseSink * bsink)
204 GstSLVideo *slvideo; 195 GstSLVideo *slvideo;
205 slvideo = GST_SLVIDEO(bsink); 196 slvideo = GST_SLVIDEO(bsink);
206 197
207 return gst_caps_ref (slvideo->caps); 198 return llgst_caps_ref (slvideo->caps);
208} 199}
209 200
210 201
@@ -214,42 +205,37 @@ gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps)
214{ 205{
215 GstSLVideo *filter; 206 GstSLVideo *filter;
216 GstStructure *structure; 207 GstStructure *structure;
217 GstCaps *intersection;
218 208
219 GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps); 209 GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps);
220 210
221 filter = GST_SLVIDEO(bsink); 211 filter = GST_SLVIDEO(bsink);
222 212
223 intersection = gst_caps_intersect (filter->caps, caps); 213 int width, height;
224 if (gst_caps_is_empty (intersection))
225 {
226 // no overlap between our caps and requested caps
227 return FALSE;
228 }
229 gst_caps_unref(intersection);
230
231 int width = 0;
232 int height = 0;
233 gboolean ret; 214 gboolean ret;
234 const GValue *fps; 215 const GValue *fps;
235 const GValue *par; 216 const GValue *par;
236 structure = gst_caps_get_structure (caps, 0); 217 structure = llgst_caps_get_structure (caps, 0);
237 ret = gst_structure_get_int (structure, "width", &width); 218 ret = llgst_structure_get_int (structure, "width", &width);
238 ret = ret && gst_structure_get_int (structure, "height", &height); 219 ret = ret && llgst_structure_get_int (structure, "height", &height);
239 fps = gst_structure_get_value (structure, "framerate"); 220 fps = llgst_structure_get_value (structure, "framerate");
240 ret = ret && (fps != NULL); 221 ret = ret && (fps != NULL);
241 par = gst_structure_get_value (structure, "pixel-aspect-ratio"); 222 par = llgst_structure_get_value (structure, "pixel-aspect-ratio");
242 if (!ret) 223 if (!ret)
243 return FALSE; 224 return FALSE;
244 225
226 INFOMSG("** filter caps set with width=%d, height=%d", width, height);
227
228 GST_OBJECT_LOCK(filter);
229
245 filter->width = width; 230 filter->width = width;
246 filter->height = height; 231 filter->height = height;
247 filter->fps_n = gst_value_get_fraction_numerator(fps); 232
248 filter->fps_d = gst_value_get_fraction_denominator(fps); 233 filter->fps_n = llgst_value_get_fraction_numerator(fps);
234 filter->fps_d = llgst_value_get_fraction_denominator(fps);
249 if (par) 235 if (par)
250 { 236 {
251 filter->par_n = gst_value_get_fraction_numerator(par); 237 filter->par_n = llgst_value_get_fraction_numerator(par);
252 filter->par_d = gst_value_get_fraction_denominator(par); 238 filter->par_d = llgst_value_get_fraction_denominator(par);
253 } 239 }
254 else 240 else
255 { 241 {
@@ -259,16 +245,18 @@ gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps)
259 GST_VIDEO_SINK_WIDTH(filter) = width; 245 GST_VIDEO_SINK_WIDTH(filter) = width;
260 GST_VIDEO_SINK_HEIGHT(filter) = height; 246 GST_VIDEO_SINK_HEIGHT(filter) = height;
261 247
248 // crufty lump - we *always* accept *only* RGBX now.
249 /*
262 filter->format = SLV_PF_UNKNOWN; 250 filter->format = SLV_PF_UNKNOWN;
263 if (0 == strcmp(gst_structure_get_name(structure), 251 if (0 == strcmp(llgst_structure_get_name(structure),
264 "video/x-raw-rgb")) 252 "video/x-raw-rgb"))
265 { 253 {
266 int red_mask; 254 int red_mask;
267 int green_mask; 255 int green_mask;
268 int blue_mask; 256 int blue_mask;
269 gst_structure_get_int(structure, "red_mask", &red_mask); 257 llgst_structure_get_int(structure, "red_mask", &red_mask);
270 gst_structure_get_int(structure, "green_mask", &green_mask); 258 llgst_structure_get_int(structure, "green_mask", &green_mask);
271 gst_structure_get_int(structure, "blue_mask", &blue_mask); 259 llgst_structure_get_int(structure, "blue_mask", &blue_mask);
272 if ((unsigned int)red_mask == 0xFF000000 && 260 if ((unsigned int)red_mask == 0xFF000000 &&
273 (unsigned int)green_mask == 0x00FF0000 && 261 (unsigned int)green_mask == 0x00FF0000 &&
274 (unsigned int)blue_mask == 0x0000FF00) 262 (unsigned int)blue_mask == 0x0000FF00)
@@ -282,8 +270,12 @@ gst_slvideo_set_caps (GstBaseSink * bsink, GstCaps * caps)
282 filter->format = SLV_PF_BGRX; 270 filter->format = SLV_PF_BGRX;
283 //fprintf(stderr, "\n\nPIXEL FORMAT BGR\n\n"); 271 //fprintf(stderr, "\n\nPIXEL FORMAT BGR\n\n");
284 } 272 }
285 } 273 }*/
286 274
275 filter->format = SLV_PF_RGBX;
276
277 GST_OBJECT_UNLOCK(filter);
278
287 return TRUE; 279 return TRUE;
288} 280}
289 281
@@ -317,6 +309,97 @@ gst_slvideo_stop (GstBaseSink * bsink)
317} 309}
318 310
319 311
312static GstFlowReturn
313gst_slvideo_buffer_alloc (GstBaseSink * bsink, guint64 offset, guint size,
314 GstCaps * caps, GstBuffer ** buf)
315{
316 gint width, height;
317 GstStructure *structure = NULL;
318 GstSLVideo *slvideo;
319 slvideo = GST_SLVIDEO(bsink);
320
321 // caps == requested caps
322 // we can ignore these and reverse-negotiate our preferred dimensions with
323 // the peer if we like - we need to do this to obey dynamic resize requests
324 // flowing in from the app.
325 structure = llgst_caps_get_structure (caps, 0);
326 if (!llgst_structure_get_int(structure, "width", &width) ||
327 !llgst_structure_get_int(structure, "height", &height))
328 {
329 GST_WARNING_OBJECT (slvideo, "no width/height in caps %" GST_PTR_FORMAT, caps);
330 return GST_FLOW_NOT_NEGOTIATED;
331 }
332
333 GstBuffer *newbuf = llgst_buffer_new();
334 bool made_bufferdata_ptr = false;
335#define MAXDEPTHHACK 4
336
337 GST_OBJECT_LOCK(slvideo);
338 if (slvideo->resize_forced)
339 {
340 gint slwantwidth, slwantheight;
341 slwantwidth = slvideo->resize_try_width;
342 slwantheight = slvideo->resize_try_height;
343
344 if (slwantwidth != width ||
345 slwantheight != height)
346 {
347 // don't like requested caps, we will issue our own suggestion - copy
348 // the requested caps but substitute our own width and height and see
349 // if our peer is happy with that.
350
351 GstCaps *desired_caps;
352 GstStructure *desired_struct;
353 desired_caps = llgst_caps_copy (caps);
354 desired_struct = llgst_caps_get_structure (desired_caps, 0);
355
356 GValue value = {0};
357 g_value_init(&value, G_TYPE_INT);
358 g_value_set_int(&value, slwantwidth);
359 llgst_structure_set_value (desired_struct, "width", &value);
360 g_value_unset(&value);
361 g_value_init(&value, G_TYPE_INT);
362 g_value_set_int(&value, slwantheight);
363 llgst_structure_set_value (desired_struct, "height", &value);
364
365 if (llgst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (slvideo),
366 desired_caps))
367 {
368 // todo: re-use buffers from a pool?
369 // todo: set MALLOCDATA to null, set DATA to point straight to shm?
370
371 // peer likes our cap suggestion
372 DEBUGMSG("peer loves us :)");
373 GST_BUFFER_SIZE(newbuf) = slwantwidth * slwantheight * MAXDEPTHHACK;
374 GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf));
375 GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf);
376 llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), desired_caps);
377
378 made_bufferdata_ptr = true;
379 } else {
380 // peer hates our cap suggestion
381 INFOMSG("peer hates us :(");
382 llgst_caps_unref(desired_caps);
383 }
384 }
385 }
386
387 if (!made_bufferdata_ptr) // need to fallback to malloc at original size
388 {
389 GST_BUFFER_SIZE(newbuf) = width * height * MAXDEPTHHACK;
390 GST_BUFFER_MALLOCDATA(newbuf) = (guint8*)g_malloc(GST_BUFFER_SIZE(newbuf));
391 GST_BUFFER_DATA(newbuf) = GST_BUFFER_MALLOCDATA(newbuf);
392 llgst_buffer_set_caps (GST_BUFFER_CAST(newbuf), caps);
393 }
394
395 GST_OBJECT_UNLOCK(slvideo);
396
397 *buf = GST_BUFFER_CAST(newbuf);
398
399 return GST_FLOW_OK;
400}
401
402
320/* initialize the plugin's class */ 403/* initialize the plugin's class */
321static void 404static void
322gst_slvideo_class_init (GstSLVideoClass * klass) 405gst_slvideo_class_init (GstSLVideoClass * klass)
@@ -338,7 +421,7 @@ gst_slvideo_class_init (GstSLVideoClass * klass)
338#define LLGST_DEBUG_FUNCPTR(p) (p) 421#define LLGST_DEBUG_FUNCPTR(p) (p)
339 gstbasesink_class->get_caps = LLGST_DEBUG_FUNCPTR (gst_slvideo_get_caps); 422 gstbasesink_class->get_caps = LLGST_DEBUG_FUNCPTR (gst_slvideo_get_caps);
340 gstbasesink_class->set_caps = LLGST_DEBUG_FUNCPTR( gst_slvideo_set_caps); 423 gstbasesink_class->set_caps = LLGST_DEBUG_FUNCPTR( gst_slvideo_set_caps);
341 //gstbasesink_class->buffer_alloc=LLGST_DEBUG_FUNCPTR(gst_slvideo_buffer_alloc); 424 gstbasesink_class->buffer_alloc=LLGST_DEBUG_FUNCPTR(gst_slvideo_buffer_alloc);
342 //gstbasesink_class->get_times = LLGST_DEBUG_FUNCPTR (gst_slvideo_get_times); 425 //gstbasesink_class->get_times = LLGST_DEBUG_FUNCPTR (gst_slvideo_get_times);
343 gstbasesink_class->preroll = LLGST_DEBUG_FUNCPTR (gst_slvideo_show_frame); 426 gstbasesink_class->preroll = LLGST_DEBUG_FUNCPTR (gst_slvideo_show_frame);
344 gstbasesink_class->render = LLGST_DEBUG_FUNCPTR (gst_slvideo_show_frame); 427 gstbasesink_class->render = LLGST_DEBUG_FUNCPTR (gst_slvideo_show_frame);
@@ -351,20 +434,6 @@ gst_slvideo_class_init (GstSLVideoClass * klass)
351} 434}
352 435
353 436
354static void
355gst_slvideo_update_caps (GstSLVideo * slvideo)
356{
357 GstCaps *caps;
358
359 // GStreamer will automatically convert colourspace if necessary.
360 // GStreamer will automatically resize media to one of these enumerated
361 // powers-of-two that we ask for (yay GStreamer!)
362 caps = gst_caps_from_string (SLV_ALLCAPS);
363
364 gst_caps_replace (&slvideo->caps, caps);
365}
366
367
368/* initialize the new element 437/* initialize the new element
369 * instantiate pads and add them to element 438 * instantiate pads and add them to element
370 * set functions 439 * set functions
@@ -374,6 +443,7 @@ static void
374gst_slvideo_init (GstSLVideo * filter, 443gst_slvideo_init (GstSLVideo * filter,
375 GstSLVideoClass * gclass) 444 GstSLVideoClass * gclass)
376{ 445{
446 filter->caps = NULL;
377 filter->width = -1; 447 filter->width = -1;
378 filter->height = -1; 448 filter->height = -1;
379 449
@@ -385,19 +455,24 @@ gst_slvideo_init (GstSLVideo * filter,
385 filter->retained_frame_width = filter->width; 455 filter->retained_frame_width = filter->width;
386 filter->retained_frame_height = filter->height; 456 filter->retained_frame_height = filter->height;
387 filter->retained_frame_format = SLV_PF_UNKNOWN; 457 filter->retained_frame_format = SLV_PF_UNKNOWN;
458 GstCaps *caps = llgst_caps_from_string (SLV_ALLCAPS);
459 llgst_caps_replace (&filter->caps, caps);
460 filter->resize_forced = false;
461 filter->resize_try_width = -1;
462 filter->resize_try_height = -1;
388 GST_OBJECT_UNLOCK(filter); 463 GST_OBJECT_UNLOCK(filter);
389
390 gst_slvideo_update_caps(filter);
391} 464}
392 465
393static void 466static void
394gst_slvideo_set_property (GObject * object, guint prop_id, 467gst_slvideo_set_property (GObject * object, guint prop_id,
395 const GValue * value, GParamSpec * pspec) 468 const GValue * value, GParamSpec * pspec)
396{ 469{
397 g_return_if_fail (GST_IS_SLVIDEO (object)); 470 llg_return_if_fail (GST_IS_SLVIDEO (object));
398 471
399 if (prop_id) { 472 switch (prop_id) {
473 default:
400 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 474 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
475 break;
401 } 476 }
402} 477}
403 478
@@ -405,10 +480,12 @@ static void
405gst_slvideo_get_property (GObject * object, guint prop_id, 480gst_slvideo_get_property (GObject * object, guint prop_id,
406 GValue * value, GParamSpec * pspec) 481 GValue * value, GParamSpec * pspec)
407{ 482{
408 g_return_if_fail (GST_IS_SLVIDEO (object)); 483 llg_return_if_fail (GST_IS_SLVIDEO (object));
409 484
410 if (prop_id) { 485 switch (prop_id) {
486 default:
411 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 487 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
488 break;
412 } 489 }
413} 490}
414 491
@@ -421,28 +498,35 @@ gst_slvideo_get_property (GObject * object, guint prop_id,
421static gboolean 498static gboolean
422plugin_init (GstPlugin * plugin) 499plugin_init (GstPlugin * plugin)
423{ 500{
424 //fprintf(stderr, "\n\n\nPLUGIN INIT\n\n\n"); 501 DEBUGMSG("\n\n\nPLUGIN INIT\n\n\n");
425 502
426 GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin", 503 GST_DEBUG_CATEGORY_INIT (gst_slvideo_debug, (gchar*)"private-slvideo-plugin",
427 0, (gchar*)"Second Life Video Sink"); 504 0, (gchar*)"Second Life Video Sink");
428 505
429 return gst_element_register (plugin, "private-slvideo", 506 return llgst_element_register (plugin, (gchar*)"private-slvideo",
430 GST_RANK_NONE, GST_TYPE_SLVIDEO); 507 GST_RANK_NONE, GST_TYPE_SLVIDEO);
431} 508}
432 509
433 510/* this is the structure that gstreamer looks for to register plugins
511 */
512/* NOTE: Can't rely upon GST_PLUGIN_DEFINE_STATIC to self-register, since
513 some g++ versions buggily avoid __attribute__((constructor)) functions -
514 so we provide an explicit plugin init function.
515 */
434void gst_slvideo_init_class (void) 516void gst_slvideo_init_class (void)
435{ 517{
436 gst_plugin_register_static( GST_VERSION_MAJOR, 518#define PACKAGE "packagehack"
437 GST_VERSION_MINOR, 519 // this macro quietly refers to PACKAGE internally
438 (const gchar *)"private-slvideoplugin", 520 static GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
439 (gchar *)"SL Video sink plugin", 521 GST_VERSION_MINOR,
440 plugin_init, 522 (gchar*)"private-slvideoplugin",
441 (const gchar *)"0.1", 523 (gchar*)"SL Video sink plugin",
442 GST_LICENSE_UNKNOWN, 524 plugin_init, (gchar*)"0.1", (gchar*)GST_LICENSE_UNKNOWN,
443 (const gchar *)"Second Life", 525 (gchar*)"Second Life",
444 (const gchar *)"Second Life", 526 (gchar*)"http://www.secondlife.com/");
445 (const gchar *)"http://www.secondlife.com/" ); 527#undef PACKAGE
528 ll_gst_plugin_register_static (&gst_plugin_desc);
529 DEBUGMSG(stderr, "\n\n\nCLASS INIT\n\n\n");
446} 530}
447 531
448///#endif // LL_GSTREAMER_ENABLED 532#endif // LL_GSTREAMER010_ENABLED