2 * Copyright (C) 2012 Roland Krikava <info@bluedigits.com>
3 * Copyright (C) 2010-2011 David Hoyt <dhoyt@hoytsoft.org>
4 * Copyright (C) 2010 Andoni Morales <ylatuya@gmail.com>
5 * Copyright (C) 2012 Sebastian Dröge <sebastian.droege@collabora.co.uk>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
26 #include "d3dvideosink.h"
27 #include "gstd3d9overlay.h"
29 #define ELEMENT_NAME "d3dvideosink"
34 PROP_FORCE_ASPECT_RATIO,
35 PROP_CREATE_RENDER_WINDOW,
36 PROP_STREAM_STOP_ON_CLOSE,
37 PROP_ENABLE_NAVIGATION_EVENTS,
41 #define DEFAULT_FORCE_ASPECT_RATIO TRUE
42 #define DEFAULT_CREATE_RENDER_WINDOW TRUE
43 #define DEFAULT_STREAM_STOP_ON_CLOSE TRUE
44 #define DEFAULT_ENABLE_NAVIGATION_EVENTS TRUE
46 #define GST_D3D9_VIDEO_FORMATS \
47 "{ I420, YV12, UYVY, YUY2, NV12, BGRx, RGBx, BGRA, RGBA, BGR, RGB16, RGB15 }"
48 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
51 GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE (GST_D3D9_VIDEO_FORMATS) ";"
52 GST_VIDEO_CAPS_MAKE_WITH_FEATURES (GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY
53 ", " GST_CAPS_FEATURE_META_GST_VIDEO_OVERLAY_COMPOSITION,
54 GST_D3D9_VIDEO_FORMATS)));
56 GST_DEBUG_CATEGORY (gst_d3dvideosink_debug);
57 #define GST_CAT_DEFAULT gst_d3dvideosink_debug
60 /* GstXOverlay Interface */
62 gst_d3dvideosink_video_overlay_interface_init (GstVideoOverlayInterface *
64 static void gst_d3dvideosink_set_window_handle (GstVideoOverlay * overlay,
66 static void gst_d3dvideosink_set_render_rectangle (GstVideoOverlay * overlay,
67 gint x, gint y, gint width, gint height);
68 static void gst_d3dvideosink_expose (GstVideoOverlay * overlay);
69 /* GstNavigation Interface */
70 static void gst_d3dvideosink_navigation_interface_init (GstNavigationInterface *
72 static void gst_d3dvideosink_navigation_send_event (GstNavigation * navigation,
73 GstStructure * structure);
75 static void gst_d3dvideosink_set_property (GObject * object, guint prop_id,
76 const GValue * value, GParamSpec * pspec);
77 static void gst_d3dvideosink_get_property (GObject * object, guint prop_id,
78 GValue * value, GParamSpec * pspec);
79 static void gst_d3dvideosink_finalize (GObject * gobject);
81 static GstCaps *gst_d3dvideosink_get_caps (GstBaseSink * basesink,
83 static gboolean gst_d3dvideosink_set_caps (GstBaseSink * bsink, GstCaps * caps);
84 static gboolean gst_d3dvideosink_start (GstBaseSink * sink);
85 static gboolean gst_d3dvideosink_stop (GstBaseSink * sink);
86 static GstFlowReturn gst_d3dvideosink_prepare (GstBaseSink * bsink,
88 static gboolean gst_d3dvideosink_propose_allocation (GstBaseSink * bsink,
91 static GstFlowReturn gst_d3dvideosink_show_frame (GstVideoSink * vsink,
95 G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION, gst_d3dvideosink_navigation_interface_init); \
96 G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY, gst_d3dvideosink_video_overlay_interface_init); \
97 GST_DEBUG_CATEGORY_INIT (gst_d3dvideosink_debug, ELEMENT_NAME, 0, "Direct3D Video");
99 G_DEFINE_TYPE_WITH_CODE (GstD3DVideoSink, gst_d3dvideosink, GST_TYPE_VIDEO_SINK,
103 gst_d3dvideosink_class_init (GstD3DVideoSinkClass * klass)
105 GObjectClass *gobject_class;
106 GstElementClass *gstelement_class;
107 GstVideoSinkClass *gstvideosink_class;
108 GstBaseSinkClass *gstbasesink_class;
110 gobject_class = (GObjectClass *) klass;
111 gstelement_class = (GstElementClass *) klass;
112 gstvideosink_class = (GstVideoSinkClass *) klass;
113 gstbasesink_class = (GstBaseSinkClass *) klass;
115 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_d3dvideosink_finalize);
116 gobject_class->set_property =
117 GST_DEBUG_FUNCPTR (gst_d3dvideosink_set_property);
118 gobject_class->get_property =
119 GST_DEBUG_FUNCPTR (gst_d3dvideosink_get_property);
121 gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_d3dvideosink_get_caps);
122 gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_d3dvideosink_set_caps);
123 gstbasesink_class->start = GST_DEBUG_FUNCPTR (gst_d3dvideosink_start);
124 gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_d3dvideosink_stop);
125 gstbasesink_class->prepare = GST_DEBUG_FUNCPTR (gst_d3dvideosink_prepare);
126 gstbasesink_class->propose_allocation =
127 GST_DEBUG_FUNCPTR (gst_d3dvideosink_propose_allocation);
129 gstvideosink_class->show_frame =
130 GST_DEBUG_FUNCPTR (gst_d3dvideosink_show_frame);
133 g_object_class_install_property (G_OBJECT_CLASS (klass),
134 PROP_FORCE_ASPECT_RATIO, g_param_spec_boolean ("force-aspect-ratio",
135 "Force aspect ratio",
136 "When enabled, scaling will respect original aspect ratio",
137 DEFAULT_FORCE_ASPECT_RATIO,
138 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
139 g_object_class_install_property (G_OBJECT_CLASS (klass),
140 PROP_CREATE_RENDER_WINDOW, g_param_spec_boolean ("create-render-window",
141 "Create render window",
142 "If no window ID is given, a new render window is created",
143 DEFAULT_CREATE_RENDER_WINDOW,
144 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
145 g_object_class_install_property (G_OBJECT_CLASS (klass),
146 PROP_STREAM_STOP_ON_CLOSE, g_param_spec_boolean ("stream-stop-on-close",
147 "Stop streaming on window close",
148 "If the render window is closed stop stream",
149 DEFAULT_STREAM_STOP_ON_CLOSE,
150 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
151 g_object_class_install_property (G_OBJECT_CLASS (klass),
152 PROP_ENABLE_NAVIGATION_EVENTS,
153 g_param_spec_boolean ("enable-navigation-events",
154 "Enable navigation events",
155 "When enabled, navigation events are sent upstream",
156 DEFAULT_ENABLE_NAVIGATION_EVENTS,
157 (GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
159 gst_element_class_set_static_metadata (gstelement_class,
160 "Direct3D video sink", "Sink/Video",
161 "Display data using a Direct3D video renderer",
162 "David Hoyt <dhoyt@hoytsoft.org>, Roland Krikava <info@bluedigits.com>");
164 gst_element_class_add_static_pad_template (gstelement_class, &sink_template);
166 g_rec_mutex_init (&klass->lock);
170 gst_d3dvideosink_init (GstD3DVideoSink * sink)
172 GST_DEBUG_OBJECT (sink, " ");
174 /* Init Properties */
175 sink->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO;
176 sink->create_internal_window = DEFAULT_CREATE_RENDER_WINDOW;
177 sink->stream_stop_on_close = DEFAULT_STREAM_STOP_ON_CLOSE;
178 sink->enable_navigation_events = DEFAULT_ENABLE_NAVIGATION_EVENTS;
179 sink->d3d.surface = NULL;
180 sink->d3d.overlay = NULL;
181 sink->d3d.overlay_needs_resize = FALSE;
182 g_rec_mutex_init (&sink->lock);
185 /* GObject Functions */
188 gst_d3dvideosink_finalize (GObject * gobject)
190 GstD3DVideoSink *sink = GST_D3DVIDEOSINK (gobject);
192 GST_DEBUG_OBJECT (sink, " ");
194 gst_object_replace ((GstObject **) & sink->pool, NULL);
195 gst_object_replace ((GstObject **) & sink->fallback_pool, NULL);
197 gst_caps_replace (&sink->supported_caps, NULL);
199 g_rec_mutex_clear (&sink->lock);
201 G_OBJECT_CLASS (gst_d3dvideosink_parent_class)->finalize (gobject);
205 gst_d3dvideosink_set_property (GObject * object, guint prop_id,
206 const GValue * value, GParamSpec * pspec)
208 GstD3DVideoSink *sink = GST_D3DVIDEOSINK (object);
211 case PROP_FORCE_ASPECT_RATIO:
212 sink->force_aspect_ratio = g_value_get_boolean (value);
214 case PROP_CREATE_RENDER_WINDOW:
215 sink->create_internal_window = g_value_get_boolean (value);
217 case PROP_STREAM_STOP_ON_CLOSE:
218 sink->stream_stop_on_close = g_value_get_boolean (value);
220 case PROP_ENABLE_NAVIGATION_EVENTS:
221 sink->enable_navigation_events = g_value_get_boolean (value);
224 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
230 gst_d3dvideosink_get_property (GObject * object, guint prop_id, GValue * value,
233 GstD3DVideoSink *sink = GST_D3DVIDEOSINK (object);
236 case PROP_FORCE_ASPECT_RATIO:
237 g_value_set_boolean (value, sink->force_aspect_ratio);
239 case PROP_CREATE_RENDER_WINDOW:
240 g_value_set_boolean (value, sink->create_internal_window);
242 case PROP_STREAM_STOP_ON_CLOSE:
243 g_value_set_boolean (value, sink->stream_stop_on_close);
245 case PROP_ENABLE_NAVIGATION_EVENTS:
246 g_value_set_boolean (value, sink->enable_navigation_events);
249 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
254 /* GstBaseSinkClass Functions */
257 gst_d3dvideosink_get_caps (GstBaseSink * basesink, GstCaps * filter)
259 GstD3DVideoSink *sink = GST_D3DVIDEOSINK (basesink);
262 caps = d3d_supported_caps (sink);
264 caps = gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD (sink));
266 if (caps && filter) {
268 isect = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
269 gst_caps_unref (caps);
277 gst_d3dvideosink_set_caps (GstBaseSink * bsink, GstCaps * caps)
279 GstD3DVideoSink *sink;
281 gint video_width, video_height;
282 gint video_par_n, video_par_d; /* video's PAR */
283 gint display_par_n = 1, display_par_d = 1; /* display's PAR */
285 GstBufferPool *newpool, *oldpool;
286 GstBufferPool *newfbpool, *oldfbpool;
287 GstStructure *config;
289 GST_DEBUG_OBJECT (bsink, "Caps: %" GST_PTR_FORMAT, caps);
290 sink = GST_D3DVIDEOSINK (bsink);
292 sink_caps = d3d_supported_caps (sink);
294 if (!gst_caps_can_intersect (sink_caps, caps))
295 goto incompatible_caps;
296 gst_caps_replace (&sink_caps, NULL);
298 memset (&sink->info, 0, sizeof (GstVideoInfo));
299 if (!gst_video_info_from_caps (&sink->info, caps))
302 sink->format = sink->info.finfo->format;
303 video_width = sink->info.width;
304 video_height = sink->info.height;
305 video_par_n = sink->info.par_n;
306 video_par_d = sink->info.par_d;
308 GST_DEBUG_OBJECT (bsink, "Set Caps Format: %s",
309 gst_video_format_to_string (sink->format));
311 /* get aspect ratio from caps if it's present, and
312 * convert video width and height to a display width and height
313 * using wd / hd = wv / hv * PARv / PARd */
315 /* TODO: Get display PAR */
317 if (!gst_video_calculate_display_ratio (&num, &den, video_width,
318 video_height, video_par_n, video_par_d, display_par_n, display_par_d))
321 GST_DEBUG_OBJECT (sink,
322 "video width/height: %dx%d, calculated display ratio: %d/%d format: %u",
323 video_width, video_height, num, den, sink->format);
325 /* now find a width x height that respects this display ratio.
326 * prefer those that have one of w/h the same as the incoming video
327 * using wd / hd = num / den
330 /* start with same height, because of interlaced video
331 * check hd / den is an integer scale factor, and scale wd with the PAR
333 if (video_height % den == 0) {
334 GST_DEBUG_OBJECT (sink, "keeping video height");
335 GST_VIDEO_SINK_WIDTH (sink) = (guint)
336 gst_util_uint64_scale_int (video_height, num, den);
337 GST_VIDEO_SINK_HEIGHT (sink) = video_height;
338 } else if (video_width % num == 0) {
339 GST_DEBUG_OBJECT (sink, "keeping video width");
340 GST_VIDEO_SINK_WIDTH (sink) = video_width;
341 GST_VIDEO_SINK_HEIGHT (sink) = (guint)
342 gst_util_uint64_scale_int (video_width, den, num);
344 GST_DEBUG_OBJECT (sink, "approximating while keeping video height");
345 GST_VIDEO_SINK_WIDTH (sink) = (guint)
346 gst_util_uint64_scale_int (video_height, num, den);
347 GST_VIDEO_SINK_HEIGHT (sink) = video_height;
349 GST_DEBUG_OBJECT (sink, "scaling to %dx%d",
350 GST_VIDEO_SINK_WIDTH (sink), GST_VIDEO_SINK_HEIGHT (sink));
352 if (GST_VIDEO_SINK_WIDTH (sink) <= 0 || GST_VIDEO_SINK_HEIGHT (sink) <= 0)
353 goto no_display_size;
355 memset (&sink->crop_rect, 0, sizeof (sink->crop_rect));
356 sink->crop_rect.w = sink->info.width;
357 sink->crop_rect.h = sink->info.height;
359 sink->width = video_width;
360 sink->height = video_height;
362 GST_DEBUG_OBJECT (bsink, "Selected caps: %" GST_PTR_FORMAT, caps);
364 if (!d3d_set_render_format (sink))
365 goto incompatible_caps;
367 /* Create a window (or start using an application-supplied one, then connect the graph */
368 d3d_prepare_window (sink);
370 newpool = gst_d3dsurface_buffer_pool_new (sink);
371 config = gst_buffer_pool_get_config (newpool);
372 /* we need at least 2 buffer because we hold on to the last one */
373 gst_buffer_pool_config_set_params (config, caps, sink->info.size, 2, 0);
374 if (!gst_buffer_pool_set_config (newpool, config)) {
375 gst_object_unref (newpool);
376 GST_ERROR_OBJECT (sink, "Failed to set buffer pool configuration");
380 newfbpool = gst_d3dsurface_buffer_pool_new (sink);
381 config = gst_buffer_pool_get_config (newfbpool);
382 /* we need at least 2 buffer because we hold on to the last one */
383 gst_buffer_pool_config_set_params (config, caps, sink->info.size, 2, 0);
384 /* Fallback pool must use videometa */
385 gst_buffer_pool_config_add_option (config, GST_BUFFER_POOL_OPTION_VIDEO_META);
386 if (!gst_buffer_pool_set_config (newfbpool, config)) {
387 gst_object_unref (newfbpool);
388 GST_ERROR_OBJECT (sink, "Failed to set buffer pool configuration");
392 GST_OBJECT_LOCK (sink);
393 oldpool = sink->pool;
394 sink->pool = newpool;
395 oldfbpool = sink->fallback_pool;
396 sink->fallback_pool = newfbpool;
397 GST_OBJECT_UNLOCK (sink);
400 gst_object_unref (oldpool);
402 gst_buffer_pool_set_active (oldfbpool, FALSE);
403 gst_object_unref (oldfbpool);
410 GST_ERROR_OBJECT (sink, "caps incompatible");
411 gst_caps_unref (sink_caps);
416 GST_DEBUG_OBJECT (sink,
417 "Could not locate image format from caps %" GST_PTR_FORMAT, caps);
422 GST_ELEMENT_ERROR (sink, CORE, NEGOTIATION, (NULL),
423 ("Error calculating the output display ratio of the video."));
428 GST_ELEMENT_ERROR (sink, CORE, NEGOTIATION, (NULL),
429 ("Error calculating the output display ratio of the video."));
435 gst_d3dvideosink_start (GstBaseSink * bsink)
437 GstD3DVideoSink *sink = GST_D3DVIDEOSINK (bsink);
439 GST_DEBUG_OBJECT (bsink, "Start() called");
441 return d3d_class_init (sink);
445 gst_d3dvideosink_stop (GstBaseSink * bsink)
447 GstD3DVideoSink *sink = GST_D3DVIDEOSINK (bsink);
449 GST_DEBUG_OBJECT (bsink, "Stop() called");
451 d3d_class_destroy (sink);
457 gst_d3dvideosink_prepare (GstBaseSink * bsink, GstBuffer * buf)
459 GstD3DVideoSink *sink = GST_D3DVIDEOSINK (bsink);
460 GstFlowReturn ret = GST_FLOW_OK;
462 GST_TRACE ("preparing buffer:%p", buf);
464 if (GST_VIDEO_SINK_WIDTH (sink) < 1 || GST_VIDEO_SINK_HEIGHT (sink) < 1) {
465 return GST_FLOW_NOT_NEGOTIATED;
468 GST_OBJECT_LOCK (sink);
469 ret = gst_d3d9_overlay_prepare (sink, buf);
470 GST_OBJECT_UNLOCK (sink);
475 gst_d3dvideosink_propose_allocation (GstBaseSink * bsink, GstQuery * query)
477 GstD3DVideoSink *sink = GST_D3DVIDEOSINK (bsink);
479 GstStructure *config;
483 GstStructure *allocation_meta = NULL;
485 gst_query_parse_allocation (query, &caps, &need_pool);
487 GST_DEBUG_OBJECT (sink, "no caps specified");
490 #ifdef DISABLE_BUFFER_POOL
494 /* FIXME re-using buffer pool breaks renegotiation */
495 GST_OBJECT_LOCK (sink);
496 pool = sink->pool ? gst_object_ref (sink->pool) : NULL;
497 GST_OBJECT_UNLOCK (sink);
502 /* we had a pool, check caps */
503 GST_DEBUG_OBJECT (sink, "check existing pool caps");
504 config = gst_buffer_pool_get_config (pool);
505 gst_buffer_pool_config_get_params (config, &pcaps, &size, NULL, NULL);
507 if (!gst_caps_is_equal (caps, pcaps)) {
508 GST_DEBUG_OBJECT (sink, "pool has different caps");
509 /* different caps, we can't use this pool */
510 gst_object_unref (pool);
513 gst_structure_free (config);
517 if (!gst_video_info_from_caps (&info, caps)) {
518 GST_ERROR_OBJECT (sink, "allocation query has invalid caps %"
519 GST_PTR_FORMAT, caps);
523 /* the normal size of a frame */
527 if (pool == NULL && need_pool) {
528 GST_DEBUG_OBJECT (sink, "create new pool");
529 pool = gst_d3dsurface_buffer_pool_new (sink);
531 config = gst_buffer_pool_get_config (pool);
532 /* we need at least 2 buffer because we hold on to the last one */
533 gst_buffer_pool_config_set_params (config, caps, size, 2, 0);
534 if (!gst_buffer_pool_set_config (pool, config)) {
535 gst_object_unref (pool);
536 GST_ERROR_OBJECT (sink, "failed to set pool configuration");
541 /* we need at least 2 buffer because we hold on to the last one */
542 gst_query_add_allocation_pool (query, pool, size, 2, 0);
544 gst_object_unref (pool);
546 if (sink->width != 0 && sink->height != 0) {
548 gst_structure_new ("GstVideoOverlayCompositionMeta",
549 "width", G_TYPE_UINT, sink->width,
550 "height", G_TYPE_UINT, sink->height, NULL);
551 GST_DEBUG ("sending allocation query with size %dx%d",
552 sink->width, sink->height);
554 gst_query_add_allocation_meta (query,
555 GST_VIDEO_OVERLAY_COMPOSITION_META_API_TYPE, allocation_meta);
557 gst_structure_free (allocation_meta);
559 gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL);
560 gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API_TYPE, NULL);
565 /* PUBLIC FUNCTIONS */
567 /* Interface Registrations */
570 gst_d3dvideosink_video_overlay_interface_init (GstVideoOverlayInterface * iface)
572 iface->set_window_handle = gst_d3dvideosink_set_window_handle;
573 iface->set_render_rectangle = gst_d3dvideosink_set_render_rectangle;
574 iface->expose = gst_d3dvideosink_expose;
578 gst_d3dvideosink_navigation_interface_init (GstNavigationInterface * iface)
580 iface->send_event = gst_d3dvideosink_navigation_send_event;
583 /* Video Render Code */
586 gst_d3dvideosink_set_window_handle (GstVideoOverlay * overlay,
589 d3d_set_window_handle (GST_D3DVIDEOSINK (overlay), window_id, FALSE);
593 gst_d3dvideosink_set_render_rectangle (GstVideoOverlay * overlay, gint x,
594 gint y, gint width, gint height)
596 GstD3DVideoSink *sink = GST_D3DVIDEOSINK (overlay);
597 sink->render_rect.x = x;
598 sink->render_rect.y = y;
599 sink->render_rect.w = width;
600 sink->render_rect.h = height;
601 d3d_set_render_rectangle (sink);
605 gst_d3dvideosink_expose (GstVideoOverlay * overlay)
607 GstD3DVideoSink *sink = GST_D3DVIDEOSINK (overlay);
608 d3d_expose_window (sink);
612 gst_d3dvideosink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
614 GstD3DVideoSink *sink = GST_D3DVIDEOSINK (vsink);
615 return d3d_render_buffer (sink, buffer);
618 /* Video Navigation Events */
621 gst_d3dvideosink_navigation_send_event (GstNavigation * navigation,
622 GstStructure * structure)
624 GstD3DVideoSink *sink = GST_D3DVIDEOSINK (navigation);
627 if ((e = gst_event_new_navigation (structure))) {
629 if ((pad = gst_pad_get_peer (GST_VIDEO_SINK_PAD (sink)))) {
630 if (!gst_pad_send_event (pad, gst_event_ref (e))) {
631 /* If upstream didn't handle the event we'll post a message with it
632 * for the application in case it wants to do something with it */
633 gst_element_post_message (GST_ELEMENT_CAST (sink),
634 gst_navigation_message_new_event (GST_OBJECT_CAST (sink), e));
637 gst_object_unref (pad);
642 /* PRIVATE FUNCTIONS */
645 /* Plugin entry point */
647 plugin_init (GstPlugin * plugin)
649 /* PRIMARY: this is the best videosink to use on windows */
650 if (!gst_element_register (plugin, ELEMENT_NAME,
651 GST_RANK_PRIMARY, GST_TYPE_D3DVIDEOSINK))
657 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
661 plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)