2011-06-05 01:43:45 +00:00
|
|
|
/* GStreamer
|
2012-12-22 10:24:28 +00:00
|
|
|
* Copyright (C) 2012 Roland Krikava <info@bluedigits.com>
|
2011-06-05 01:43:45 +00:00
|
|
|
* Copyright (C) 2010-2011 David Hoyt <dhoyt@hoytsoft.org>
|
|
|
|
* Copyright (C) 2010 Andoni Morales <ylatuya@gmail.com>
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Library General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Library General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Library General Public
|
|
|
|
* License along with this library; if not, write to the
|
2012-12-22 10:24:28 +00:00
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
2011-06-05 01:43:45 +00:00
|
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "d3dvideosink.h"
|
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
#define ELEMENT_NAME "d3dvideosink"
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
enum
|
2011-06-05 01:43:45 +00:00
|
|
|
{
|
2012-12-22 10:24:28 +00:00
|
|
|
PROP_0,
|
2012-12-22 10:34:43 +00:00
|
|
|
PROP_FORCE_ASPECT_RATIO,
|
2012-12-22 10:24:28 +00:00
|
|
|
PROP_CREATE_RENDER_WINDOW,
|
|
|
|
PROP_STREAM_STOP_ON_CLOSE,
|
|
|
|
PROP_ENABLE_NAVIGATION_EVENTS,
|
|
|
|
PROP_LAST
|
2011-06-05 01:43:45 +00:00
|
|
|
};
|
|
|
|
|
2012-12-22 10:34:43 +00:00
|
|
|
#define DEFAULT_FORCE_ASPECT_RATIO TRUE
|
2012-12-22 10:24:28 +00:00
|
|
|
#define DEFAULT_CREATE_RENDER_WINDOW TRUE
|
|
|
|
#define DEFAULT_STREAM_STOP_ON_CLOSE TRUE
|
|
|
|
#define DEFAULT_ENABLE_NAVIGATION_EVENTS TRUE
|
2011-06-05 01:43:45 +00:00
|
|
|
|
|
|
|
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
|
|
|
|
GST_PAD_SINK,
|
|
|
|
GST_PAD_ALWAYS,
|
2012-04-25 17:21:43 +00:00
|
|
|
GST_STATIC_CAPS ("video/x-raw, "
|
2012-12-22 10:24:28 +00:00
|
|
|
"format = (string) { I420, YV12, UYVY, YUY2, NV12, BGRx, BGRx, xRGB, xBGR, RGBA, BGRA, ARGB, ABGR, RGB, BGR, RGB16, BGR16, RGB15, BGR15 }, "
|
2012-04-25 17:21:43 +00:00
|
|
|
"framerate = (fraction) [ 0, MAX ], "
|
2012-08-02 12:26:32 +00:00
|
|
|
"width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
|
2011-06-05 01:43:45 +00:00
|
|
|
);
|
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
GST_DEBUG_CATEGORY (gst_d3dvideosink_debug);
|
|
|
|
#define GST_CAT_DEFAULT gst_d3dvideosink_debug
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
/** FWD DECLS **/
|
|
|
|
/* Interfaces */
|
|
|
|
static void gst_d3dvideosink_init_interfaces (GType type);
|
|
|
|
/* GstXOverlay Interface */
|
|
|
|
static void
|
|
|
|
gst_d3dvideosink_video_overlay_interface_init (GstVideoOverlayInterface *
|
|
|
|
iface);
|
|
|
|
static void gst_d3dvideosink_set_window_handle (GstVideoOverlay * overlay,
|
|
|
|
guintptr window_id);
|
|
|
|
static void gst_d3dvideosink_set_render_rectangle (GstVideoOverlay * overlay,
|
|
|
|
gint x, gint y, gint width, gint height);
|
|
|
|
static void gst_d3dvideosink_expose (GstVideoOverlay * overlay);
|
|
|
|
/* GstNavigation Interface */
|
|
|
|
static void gst_d3dvideosink_navigation_interface_init (GstNavigationInterface *
|
|
|
|
iface);
|
|
|
|
static void gst_d3dvideosink_navigation_send_event (GstNavigation * navigation,
|
|
|
|
GstStructure * structure);
|
|
|
|
/* GObject */
|
2011-06-05 01:43:45 +00:00
|
|
|
static void gst_d3dvideosink_set_property (GObject * object, guint prop_id,
|
|
|
|
const GValue * value, GParamSpec * pspec);
|
|
|
|
static void gst_d3dvideosink_get_property (GObject * object, guint prop_id,
|
|
|
|
GValue * value, GParamSpec * pspec);
|
2012-12-22 10:24:28 +00:00
|
|
|
static void gst_d3dvideosink_finalize (GObject * gobject);
|
|
|
|
/* GstBaseSink */
|
|
|
|
static GstCaps *gst_d3dvideosink_get_caps (GstBaseSink * basesink,
|
2012-08-02 12:26:32 +00:00
|
|
|
GstCaps * filter);
|
2012-12-22 10:24:28 +00:00
|
|
|
static gboolean gst_d3dvideosink_set_caps (GstBaseSink * bsink, GstCaps * caps);
|
|
|
|
static gboolean gst_d3dvideosink_stop (GstBaseSink * sink);
|
|
|
|
/* GstVideoSink */
|
|
|
|
static GstFlowReturn gst_d3dvideosink_show_frame (GstVideoSink * vsink,
|
2011-06-05 01:43:45 +00:00
|
|
|
GstBuffer * buffer);
|
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
#define _do_init \
|
|
|
|
G_IMPLEMENT_INTERFACE (GST_TYPE_NAVIGATION, gst_d3dvideosink_navigation_interface_init); \
|
|
|
|
G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY, gst_d3dvideosink_video_overlay_interface_init); \
|
|
|
|
GST_DEBUG_CATEGORY_INIT (gst_d3dvideosink_debug, ELEMENT_NAME, 0, "Direct3D Video");
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
G_DEFINE_TYPE_WITH_CODE (GstD3DVideoSink, gst_d3dvideosink, GST_TYPE_VIDEO_SINK,
|
|
|
|
_do_init);
|
2011-06-05 01:43:45 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_d3dvideosink_class_init (GstD3DVideoSinkClass * klass)
|
|
|
|
{
|
|
|
|
GObjectClass *gobject_class;
|
|
|
|
GstElementClass *gstelement_class;
|
|
|
|
GstVideoSinkClass *gstvideosink_class;
|
2012-12-22 10:24:28 +00:00
|
|
|
GstBaseSinkClass *gstbasesink_class;
|
2011-06-05 01:43:45 +00:00
|
|
|
|
|
|
|
gobject_class = (GObjectClass *) klass;
|
|
|
|
gstelement_class = (GstElementClass *) klass;
|
|
|
|
gstvideosink_class = (GstVideoSinkClass *) klass;
|
2012-12-22 10:24:28 +00:00
|
|
|
gstbasesink_class = (GstBaseSinkClass *) klass;
|
2011-06-05 01:43:45 +00:00
|
|
|
|
|
|
|
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_d3dvideosink_finalize);
|
|
|
|
gobject_class->set_property =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_d3dvideosink_set_property);
|
|
|
|
gobject_class->get_property =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_d3dvideosink_get_property);
|
|
|
|
|
|
|
|
gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_d3dvideosink_get_caps);
|
|
|
|
gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_d3dvideosink_set_caps);
|
|
|
|
gstbasesink_class->stop = GST_DEBUG_FUNCPTR (gst_d3dvideosink_stop);
|
|
|
|
|
|
|
|
gstvideosink_class->show_frame =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_d3dvideosink_show_frame);
|
|
|
|
|
|
|
|
/* Add properties */
|
|
|
|
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
2012-12-22 10:34:43 +00:00
|
|
|
PROP_FORCE_ASPECT_RATIO, g_param_spec_boolean ("force-aspect-ratio",
|
2011-06-05 01:43:45 +00:00
|
|
|
"Force aspect ratio",
|
2012-12-22 10:24:28 +00:00
|
|
|
"When enabled, scaling will respect original aspect ratio",
|
2012-12-22 10:35:55 +00:00
|
|
|
DEFAULT_FORCE_ASPECT_RATIO,
|
|
|
|
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
2012-12-22 10:24:28 +00:00
|
|
|
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
|
|
|
PROP_CREATE_RENDER_WINDOW, g_param_spec_boolean ("create-render-window",
|
|
|
|
"Create render window",
|
|
|
|
"If no window ID is given, a new render window is created",
|
2012-12-22 10:35:55 +00:00
|
|
|
DEFAULT_CREATE_RENDER_WINDOW,
|
|
|
|
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
2012-12-22 10:24:28 +00:00
|
|
|
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
|
|
|
PROP_STREAM_STOP_ON_CLOSE, g_param_spec_boolean ("stream-stop-on-close",
|
|
|
|
"Stop streaming on window close",
|
|
|
|
"If the render window is closed stop stream",
|
2012-12-22 10:35:55 +00:00
|
|
|
DEFAULT_STREAM_STOP_ON_CLOSE,
|
|
|
|
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
2012-12-22 10:24:28 +00:00
|
|
|
#if 0
|
2011-06-05 01:43:45 +00:00
|
|
|
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
|
|
|
PROP_PIXEL_ASPECT_RATIO, g_param_spec_string ("pixel-aspect-ratio",
|
|
|
|
"Pixel Aspect Ratio",
|
|
|
|
"The pixel aspect ratio of the device", "1/1",
|
|
|
|
(GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
|
2012-12-22 10:24:28 +00:00
|
|
|
#endif
|
2011-06-05 01:43:45 +00:00
|
|
|
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
|
|
|
PROP_ENABLE_NAVIGATION_EVENTS,
|
|
|
|
g_param_spec_boolean ("enable-navigation-events",
|
|
|
|
"Enable navigation events",
|
2012-12-22 10:24:28 +00:00
|
|
|
"When enabled, navigation events are sent upstream",
|
2012-12-22 10:35:55 +00:00
|
|
|
DEFAULT_ENABLE_NAVIGATION_EVENTS,
|
|
|
|
(GParamFlags) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
2012-04-25 17:21:43 +00:00
|
|
|
|
2012-08-02 12:26:32 +00:00
|
|
|
gst_element_class_set_static_metadata (gstelement_class,
|
|
|
|
"Direct3D video sink", "Sink/Video",
|
2012-04-25 17:21:43 +00:00
|
|
|
"Display data using a Direct3D video renderer",
|
2012-12-22 10:24:28 +00:00
|
|
|
"David Hoyt <dhoyt@hoytsoft.org>, Roland Krikava <info@bluedigits.com>");
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
gst_element_class_add_pad_template (gstelement_class,
|
|
|
|
gst_static_pad_template_get (&sink_template));
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:42:52 +00:00
|
|
|
g_rec_mutex_init (&klass->lock);
|
2011-06-05 01:43:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-04-25 17:21:43 +00:00
|
|
|
gst_d3dvideosink_init (GstD3DVideoSink * sink)
|
2011-06-05 01:43:45 +00:00
|
|
|
{
|
2012-12-22 10:24:28 +00:00
|
|
|
GST_DEBUG_OBJECT (sink, " ");
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
d3d_class_init (sink);
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
g_value_init (&sink->par, GST_TYPE_FRACTION);
|
|
|
|
gst_value_set_fraction (&sink->par, 1, 1);
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
/* Init Properties */
|
2012-12-22 10:34:43 +00:00
|
|
|
sink->force_aspect_ratio = DEFAULT_FORCE_ASPECT_RATIO;
|
2012-12-22 10:24:28 +00:00
|
|
|
sink->create_internal_window = DEFAULT_CREATE_RENDER_WINDOW;
|
|
|
|
sink->stream_stop_on_close = DEFAULT_STREAM_STOP_ON_CLOSE;
|
|
|
|
sink->enable_navigation_events = DEFAULT_ENABLE_NAVIGATION_EVENTS;
|
|
|
|
|
2012-12-22 10:42:52 +00:00
|
|
|
g_rec_mutex_init (&sink->lock);
|
2011-06-05 01:43:45 +00:00
|
|
|
}
|
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
/** GObject Functions **/
|
|
|
|
|
2011-06-05 01:43:45 +00:00
|
|
|
static void
|
|
|
|
gst_d3dvideosink_finalize (GObject * gobject)
|
|
|
|
{
|
|
|
|
GstD3DVideoSink *sink = GST_D3DVIDEOSINK (gobject);
|
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
GST_DEBUG_OBJECT (sink, " ");
|
|
|
|
|
|
|
|
d3d_class_destroy (sink);
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:42:52 +00:00
|
|
|
g_rec_mutex_clear (&sink->lock);
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
G_OBJECT_CLASS (gst_d3dvideosink_parent_class)->finalize (gobject);
|
2011-06-05 01:43:45 +00:00
|
|
|
}
|
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
|
2011-06-05 01:43:45 +00:00
|
|
|
static void
|
|
|
|
gst_d3dvideosink_set_property (GObject * object, guint prop_id,
|
|
|
|
const GValue * value, GParamSpec * pspec)
|
|
|
|
{
|
|
|
|
GstD3DVideoSink *sink = GST_D3DVIDEOSINK (object);
|
|
|
|
|
|
|
|
switch (prop_id) {
|
2012-12-22 10:34:43 +00:00
|
|
|
case PROP_FORCE_ASPECT_RATIO:
|
|
|
|
sink->force_aspect_ratio = g_value_get_boolean (value);
|
2011-06-05 01:43:45 +00:00
|
|
|
break;
|
2012-12-22 10:24:28 +00:00
|
|
|
case PROP_CREATE_RENDER_WINDOW:
|
|
|
|
sink->create_internal_window = g_value_get_boolean (value);
|
|
|
|
break;
|
|
|
|
case PROP_STREAM_STOP_ON_CLOSE:
|
|
|
|
sink->stream_stop_on_close = g_value_get_boolean (value);
|
|
|
|
break;
|
|
|
|
case PROP_ENABLE_NAVIGATION_EVENTS:
|
|
|
|
sink->enable_navigation_events = g_value_get_boolean (value);
|
2011-06-05 01:43:45 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-12-22 10:24:28 +00:00
|
|
|
gst_d3dvideosink_get_property (GObject * object, guint prop_id, GValue * value,
|
|
|
|
GParamSpec * pspec)
|
2011-06-05 01:43:45 +00:00
|
|
|
{
|
|
|
|
GstD3DVideoSink *sink = GST_D3DVIDEOSINK (object);
|
|
|
|
|
|
|
|
switch (prop_id) {
|
2012-12-22 10:34:43 +00:00
|
|
|
case PROP_FORCE_ASPECT_RATIO:
|
|
|
|
g_value_set_boolean (value, sink->force_aspect_ratio);
|
2011-06-05 01:43:45 +00:00
|
|
|
break;
|
2012-12-22 10:24:28 +00:00
|
|
|
case PROP_CREATE_RENDER_WINDOW:
|
|
|
|
g_value_set_boolean (value, sink->create_internal_window);
|
|
|
|
break;
|
|
|
|
case PROP_STREAM_STOP_ON_CLOSE:
|
|
|
|
g_value_set_boolean (value, sink->stream_stop_on_close);
|
|
|
|
break;
|
|
|
|
case PROP_ENABLE_NAVIGATION_EVENTS:
|
|
|
|
g_value_set_boolean (value, sink->enable_navigation_events);
|
2011-06-05 01:43:45 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
/** GstBaseSinkClass Functions **/
|
2012-04-25 17:21:43 +00:00
|
|
|
|
|
|
|
static GstCaps *
|
|
|
|
gst_d3dvideosink_get_caps (GstBaseSink * basesink, GstCaps * filter)
|
2011-06-05 01:43:45 +00:00
|
|
|
{
|
|
|
|
GstD3DVideoSink *sink = GST_D3DVIDEOSINK (basesink);
|
2012-03-12 11:23:34 +00:00
|
|
|
GstCaps *caps;
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
caps = d3d_supported_caps (sink);
|
|
|
|
if (!caps)
|
2012-04-25 17:21:43 +00:00
|
|
|
caps = gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD (sink));
|
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
if (caps && filter) {
|
|
|
|
GstCaps *isect;
|
|
|
|
isect = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
|
|
|
|
gst_caps_unref (caps);
|
|
|
|
caps = isect;
|
2011-08-22 12:30:43 +00:00
|
|
|
}
|
2012-12-22 10:24:28 +00:00
|
|
|
|
2011-08-22 12:30:43 +00:00
|
|
|
return caps;
|
2011-06-05 01:43:45 +00:00
|
|
|
}
|
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
static guint16
|
|
|
|
flip_b16 (guint16 b)
|
2011-06-05 01:43:45 +00:00
|
|
|
{
|
2012-12-22 10:24:28 +00:00
|
|
|
guint16 ret = 0, tmp = 0x8000;
|
|
|
|
gint i;
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
for (i = 0, tmp = 1; tmp != 0; i++) {
|
|
|
|
//printf("%x\n", tmp);
|
|
|
|
if (b & tmp)
|
|
|
|
ret |= (0x8000 >> i);
|
|
|
|
tmp <<= 1;
|
2011-06-05 01:43:45 +00:00
|
|
|
}
|
2012-12-22 10:24:28 +00:00
|
|
|
return ret;
|
2011-06-05 01:43:45 +00:00
|
|
|
}
|
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
static guint32
|
|
|
|
flip_b32 (guint32 b, gboolean bitshift)
|
2011-06-05 01:43:45 +00:00
|
|
|
{
|
2012-12-22 10:24:28 +00:00
|
|
|
guint32 ret = 0, tmp = 0x80000000;
|
|
|
|
gint i;
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
for (i = 0, tmp = 1; tmp != 0; i++) {
|
|
|
|
//printf("%x\n", tmp);
|
|
|
|
if (b & tmp)
|
|
|
|
ret |= (0x80000000 >> i);
|
|
|
|
tmp <<= 1;
|
|
|
|
}
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
if (bitshift && G_BYTE_ORDER == G_LITTLE_ENDIAN)
|
|
|
|
ret >>= 8;
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
typedef enum
|
|
|
|
{
|
|
|
|
VFMT_RGBx = 0,
|
|
|
|
VFMT_BGRx,
|
|
|
|
VFMT_xRGB,
|
|
|
|
VFMT_xBGR,
|
|
|
|
VFMT_RGBA,
|
|
|
|
VFMT_BGRA,
|
|
|
|
VFMT_ARGB,
|
|
|
|
VFMT_ABGR,
|
|
|
|
VFMT_RGB,
|
|
|
|
VFMT_BGR,
|
|
|
|
VFMT_RGB16,
|
|
|
|
VFMT_BGR16,
|
|
|
|
VFMT_RGB15,
|
|
|
|
VFMT_BGR15,
|
|
|
|
} VFmtMap;
|
|
|
|
|
|
|
|
static GstVideoFormatDetails vfmt_details[] = {
|
|
|
|
{ // GST_VIDEO_FORMAT_RGBx
|
|
|
|
0xff000000, 0x00ff0000, 0x0000ff00, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 8, 16, 0,
|
|
|
|
8, 8, 8, 0,
|
|
|
|
32, 24, G_BIG_ENDIAN, 4},
|
|
|
|
{ // GST_VIDEO_FORMAT_BGRx
|
|
|
|
0x0000ff00, 0x00ff0000, 0xff000000, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
16, 8, 0, 0,
|
|
|
|
8, 8, 8, 0,
|
|
|
|
32, 24, G_BIG_ENDIAN, 4},
|
|
|
|
{ // GST_VIDEO_FORMAT_xRGB
|
|
|
|
0x00ff0000, 0x0000ff00, 0x000000ff, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
8, 16, 24, 0,
|
|
|
|
8, 8, 8, 0,
|
|
|
|
32, 24, G_BIG_ENDIAN, 4},
|
|
|
|
{ // GST_VIDEO_FORMAT_xBGR
|
|
|
|
0x000000ff, 0x0000ff00, 0x00ff0000, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
24, 16, 8, 0,
|
|
|
|
8, 8, 8, 0,
|
|
|
|
32, 24, G_BIG_ENDIAN, 4},
|
|
|
|
{ // GST_VIDEO_FORMAT_RGBA
|
|
|
|
0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 8, 16, 24,
|
|
|
|
8, 8, 8, 8,
|
|
|
|
32, 32, G_BIG_ENDIAN, 4},
|
|
|
|
{ // GST_VIDEO_FORMAT_BGRA
|
|
|
|
0x0000ff00, 0x00ff0000, 0xff000000, 0x000000ff,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
16, 8, 0, 24,
|
|
|
|
8, 8, 8, 8,
|
|
|
|
32, 32, G_BIG_ENDIAN, 4},
|
|
|
|
{ // GST_VIDEO_FORMAT_ARGB
|
|
|
|
0x00ff0000, 0x0000ff00, 0x000000ff, 0xff000000,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
8, 16, 24, 0,
|
|
|
|
8, 8, 8, 8,
|
|
|
|
32, 32, G_BIG_ENDIAN, 4},
|
|
|
|
{ // GST_VIDEO_FORMAT_ABGR
|
|
|
|
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
24, 16, 8, 0,
|
|
|
|
8, 8, 8, 8,
|
|
|
|
32, 32, G_BIG_ENDIAN, 4},
|
|
|
|
{ // GST_VIDEO_FORMAT_RGB
|
|
|
|
0x00ff0000, 0x0000ff00, 0x000000ff, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0, 8, 16, 0,
|
|
|
|
8, 8, 8, 0,
|
|
|
|
24, 24, G_BIG_ENDIAN, 3},
|
|
|
|
{ // GST_VIDEO_FORMAT_BGR
|
|
|
|
0x000000ff, 0x0000ff00, 0x00ff0000, 0,
|
|
|
|
0, 0, 0, 0,
|
|
|
|
16, 8, 0, 0,
|
|
|
|
8, 8, 8, 0,
|
|
|
|
24, 24, G_BIG_ENDIAN, 3},
|
|
|
|
{ // GST_VIDEO_FORMAT_RGB16
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0xf800, 0x07e0, 0x001f, 0,
|
|
|
|
11, 5, 0, 0,
|
|
|
|
5, 6, 5, 0,
|
|
|
|
16, 16, G_LITTLE_ENDIAN, 2},
|
|
|
|
{ // GST_VIDEO_FORMAT_BGR16
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0x001f, 0x07e0, 0xf800, 0,
|
|
|
|
0, 5, 11, 0,
|
|
|
|
5, 6, 5, 0,
|
|
|
|
16, 16, G_LITTLE_ENDIAN, 2},
|
|
|
|
{ // GST_VIDEO_FORMAT_RGB15
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0x7c00, 0x03e0, 0x001f, 0,
|
|
|
|
10, 5, 0, 0,
|
|
|
|
5, 5, 5, 0,
|
|
|
|
16, 15, G_LITTLE_ENDIAN, 2},
|
|
|
|
{ // GST_VIDEO_FORMAT_BGR15
|
|
|
|
0, 0, 0, 0,
|
|
|
|
0x001f, 0x03e0, 0x7c00, 0,
|
|
|
|
0, 5, 10, 0,
|
|
|
|
5, 5, 5, 0,
|
|
|
|
16, 15, G_LITTLE_ENDIAN, 2}
|
|
|
|
};
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
static gboolean
|
|
|
|
gst_video_format_get_rgb_masks (GstD3DVideoSink * sink, GstVideoFormat fmt,
|
|
|
|
GstVideoFormatDetails * details)
|
|
|
|
{
|
|
|
|
gboolean ret = FALSE;
|
|
|
|
|
|
|
|
g_return_val_if_fail (details != NULL, FALSE);
|
|
|
|
|
|
|
|
switch (fmt) {
|
|
|
|
case GST_VIDEO_FORMAT_RGBx:
|
|
|
|
memcpy (details, &vfmt_details[VFMT_RGBx],
|
|
|
|
sizeof (GstVideoFormatDetails));
|
|
|
|
ret = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_BGRx:
|
|
|
|
memcpy (details, &vfmt_details[VFMT_BGRx],
|
|
|
|
sizeof (GstVideoFormatDetails));
|
|
|
|
ret = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_xRGB:
|
|
|
|
memcpy (details, &vfmt_details[VFMT_xRGB],
|
|
|
|
sizeof (GstVideoFormatDetails));
|
|
|
|
ret = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_xBGR:
|
|
|
|
memcpy (details, &vfmt_details[VFMT_xBGR],
|
|
|
|
sizeof (GstVideoFormatDetails));
|
|
|
|
ret = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_RGBA:
|
|
|
|
memcpy (details, &vfmt_details[VFMT_RGBA],
|
|
|
|
sizeof (GstVideoFormatDetails));
|
|
|
|
ret = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_BGRA:
|
|
|
|
memcpy (details, &vfmt_details[VFMT_BGRA],
|
|
|
|
sizeof (GstVideoFormatDetails));
|
|
|
|
ret = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_ARGB:
|
|
|
|
memcpy (details, &vfmt_details[VFMT_ARGB],
|
|
|
|
sizeof (GstVideoFormatDetails));
|
|
|
|
ret = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_ABGR:
|
|
|
|
memcpy (details, &vfmt_details[VFMT_ABGR],
|
|
|
|
sizeof (GstVideoFormatDetails));
|
|
|
|
ret = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_RGB:
|
|
|
|
memcpy (details, &vfmt_details[VFMT_RGB], sizeof (GstVideoFormatDetails));
|
|
|
|
ret = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_BGR:
|
|
|
|
memcpy (details, &vfmt_details[VFMT_BGR], sizeof (GstVideoFormatDetails));
|
|
|
|
ret = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_RGB16:
|
|
|
|
memcpy (details, &vfmt_details[VFMT_RGB16],
|
|
|
|
sizeof (GstVideoFormatDetails));
|
|
|
|
ret = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_BGR16:
|
|
|
|
memcpy (details, &vfmt_details[VFMT_BGR16],
|
|
|
|
sizeof (GstVideoFormatDetails));
|
|
|
|
ret = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_RGB15:
|
|
|
|
memcpy (details, &vfmt_details[VFMT_RGB15],
|
|
|
|
sizeof (GstVideoFormatDetails));
|
|
|
|
ret = TRUE;
|
|
|
|
break;
|
|
|
|
case GST_VIDEO_FORMAT_BGR15:
|
|
|
|
memcpy (details, &vfmt_details[VFMT_BGR15],
|
|
|
|
sizeof (GstVideoFormatDetails));
|
|
|
|
ret = TRUE;
|
|
|
|
break;
|
|
|
|
default:;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ret) {
|
|
|
|
if (details->endianness != G_BYTE_ORDER) {
|
|
|
|
gboolean bitshift = (details->bpp == 24 && details->depth == 24);
|
|
|
|
GST_DEBUG_OBJECT (sink, "Flipping masks%s, byte order missmatch",
|
|
|
|
bitshift ? " (w/ bitshift)" : "");
|
|
|
|
details->r_mask = flip_b32 (details->r_mask, bitshift);
|
|
|
|
details->g_mask = flip_b32 (details->g_mask, bitshift);
|
|
|
|
details->b_mask = flip_b32 (details->b_mask, bitshift);
|
|
|
|
details->a_mask = flip_b32 (details->a_mask, bitshift);
|
|
|
|
details->r_mask16 = flip_b16 (details->r_mask16);
|
|
|
|
details->g_mask16 = flip_b16 (details->g_mask16);
|
|
|
|
details->b_mask16 = flip_b16 (details->b_mask16);
|
|
|
|
details->a_mask16 = flip_b16 (details->a_mask16);
|
|
|
|
}
|
|
|
|
if (details->bpp == 16) {
|
|
|
|
GST_DEBUG_OBJECT (sink, "RED MASK: 0x%04x SHIFT: %2u BITS: %u (%u)",
|
|
|
|
details->r_mask16, details->r_shift, details->r_bits,
|
|
|
|
details->r_mask16);
|
|
|
|
GST_DEBUG_OBJECT (sink, "GREEN MASK: 0x%04x SHIFT: %2u BITS: %u (%u)",
|
|
|
|
details->g_mask16, details->g_shift, details->g_bits,
|
|
|
|
details->g_mask16);
|
|
|
|
GST_DEBUG_OBJECT (sink, "BLUE MASK: 0x%04x SHIFT: %2u BITS: %u (%u)",
|
|
|
|
details->b_mask16, details->b_shift, details->b_bits,
|
|
|
|
details->b_mask16);
|
|
|
|
GST_DEBUG_OBJECT (sink, "ALPHA MASK: 0x%04x SHIFT: %2u BITS: %u (%u)",
|
|
|
|
details->a_mask16, details->a_shift, details->a_bits,
|
|
|
|
details->a_mask16);
|
|
|
|
} else {
|
|
|
|
GST_DEBUG_OBJECT (sink, "RED MASK: 0x%08x SHIFT: %2u BITS: %u (%u)",
|
|
|
|
details->r_mask, details->r_shift, details->r_bits, details->r_mask);
|
|
|
|
GST_DEBUG_OBJECT (sink, "GREEN MASK: 0x%08x SHIFT: %2u BITS: %u (%u)",
|
|
|
|
details->g_mask, details->g_shift, details->g_bits, details->g_mask);
|
|
|
|
GST_DEBUG_OBJECT (sink, "BLUE MASK: 0x%08x SHIFT: %2u BITS: %u (%u)",
|
|
|
|
details->b_mask, details->b_shift, details->b_bits, details->b_mask);
|
|
|
|
GST_DEBUG_OBJECT (sink, "ALPHA MASK: 0x%08x SHIFT: %2u BITS: %u (%u)",
|
|
|
|
details->a_mask, details->a_shift, details->a_bits, details->a_mask);
|
|
|
|
}
|
|
|
|
GST_DEBUG_OBJECT (sink, "ENDIANESS: %s",
|
|
|
|
(details->endianness ==
|
|
|
|
G_BIG_ENDIAN) ? "G_BIG_ENDIAN" : "G_LITTLE_ENDIAN");
|
|
|
|
GST_DEBUG_OBJECT (sink, "PIXEL WIDTH: %d", details->pixel_width);
|
|
|
|
}
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
return ret;
|
2011-06-05 01:43:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2012-12-22 10:24:28 +00:00
|
|
|
gst_d3dvideosink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
2011-06-05 01:43:45 +00:00
|
|
|
{
|
2012-12-22 10:24:28 +00:00
|
|
|
GstD3DVideoSink *sink;
|
|
|
|
GstCaps *sink_caps;
|
|
|
|
gint video_width, video_height;
|
|
|
|
gint video_par_n, video_par_d; /* video's PAR */
|
|
|
|
gint display_par_n, display_par_d; /* display's PAR */
|
|
|
|
guint num, den;
|
|
|
|
gchar *tmp = NULL;
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
GST_DEBUG_OBJECT (bsink, " ");
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
GST_DEBUG_OBJECT (bsink, "Caps: %s", (tmp = gst_caps_to_string (caps)));
|
|
|
|
sink = GST_D3DVIDEOSINK (bsink);
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
sink_caps = d3d_supported_caps (sink);
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
if (!gst_caps_can_intersect (sink_caps, caps))
|
|
|
|
goto incompatible_caps;
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
memset (&sink->info, 0, sizeof (GstVideoInfo));
|
|
|
|
if (!gst_video_info_from_caps (&sink->info, caps))
|
|
|
|
goto invalid_format;
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
sink->format = sink->info.finfo->format;
|
|
|
|
video_width = sink->info.width;
|
|
|
|
video_height = sink->info.height;
|
|
|
|
video_par_n = sink->info.par_n;
|
|
|
|
video_par_d = sink->info.par_d;
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
GST_DEBUG_OBJECT (bsink, "Set Caps Format: %s",
|
|
|
|
gst_video_format_to_string (sink->format));
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
if (GST_VIDEO_INFO_IS_RGB (&sink->info)) {
|
|
|
|
if (!gst_video_format_get_rgb_masks (sink, sink->format,
|
|
|
|
&sink->fmt_details)) {
|
|
|
|
GST_ERROR_OBJECT (sink, "No RGB mapping found for format: %s",
|
|
|
|
gst_video_format_to_string (sink->format));
|
|
|
|
goto incompatible_caps;
|
2011-06-05 01:43:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
/* get aspect ratio from caps if it's present, and
|
|
|
|
* convert video width and height to a display width and height
|
|
|
|
* using wd / hd = wv / hv * PARv / PARd */
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
/* get video's PAR */
|
|
|
|
display_par_n = gst_value_get_fraction_numerator (&sink->par);
|
|
|
|
display_par_d = gst_value_get_fraction_denominator (&sink->par);
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
if (!gst_video_calculate_display_ratio (&num, &den, video_width,
|
|
|
|
video_height, video_par_n, video_par_d, display_par_n, display_par_d))
|
|
|
|
goto no_disp_ratio;
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
GST_DEBUG_OBJECT (sink,
|
|
|
|
"video width/height: %dx%d, calculated display ratio: %d/%d format: %u",
|
|
|
|
video_width, video_height, num, den, sink->format);
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
/* now find a width x height that respects this display ratio.
|
|
|
|
* prefer those that have one of w/h the same as the incoming video
|
|
|
|
* using wd / hd = num / den
|
|
|
|
*/
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
/* start with same height, because of interlaced video
|
|
|
|
* check hd / den is an integer scale factor, and scale wd with the PAR
|
|
|
|
*/
|
|
|
|
if (video_height % den == 0) {
|
|
|
|
GST_DEBUG_OBJECT (sink, "keeping video height");
|
|
|
|
GST_VIDEO_SINK_WIDTH (sink) = (guint)
|
|
|
|
gst_util_uint64_scale_int (video_height, num, den);
|
|
|
|
GST_VIDEO_SINK_HEIGHT (sink) = video_height;
|
|
|
|
} else if (video_width % num == 0) {
|
|
|
|
GST_DEBUG_OBJECT (sink, "keeping video width");
|
|
|
|
GST_VIDEO_SINK_WIDTH (sink) = video_width;
|
|
|
|
GST_VIDEO_SINK_HEIGHT (sink) = (guint)
|
|
|
|
gst_util_uint64_scale_int (video_width, den, num);
|
|
|
|
} else {
|
|
|
|
GST_DEBUG_OBJECT (sink, "approximating while keeping video height");
|
|
|
|
GST_VIDEO_SINK_WIDTH (sink) = (guint)
|
|
|
|
gst_util_uint64_scale_int (video_height, num, den);
|
|
|
|
GST_VIDEO_SINK_HEIGHT (sink) = video_height;
|
|
|
|
}
|
|
|
|
GST_DEBUG_OBJECT (sink, "scaling to %dx%d",
|
|
|
|
GST_VIDEO_SINK_WIDTH (sink), GST_VIDEO_SINK_HEIGHT (sink));
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
if (GST_VIDEO_SINK_WIDTH (sink) <= 0 || GST_VIDEO_SINK_HEIGHT (sink) <= 0)
|
|
|
|
goto no_display_size;
|
2011-08-22 14:31:38 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
sink->width = video_width;
|
|
|
|
sink->height = video_height;
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
GST_DEBUG_OBJECT (bsink, "Selected caps: %s", (tmp =
|
|
|
|
gst_caps_to_string (caps)));
|
|
|
|
g_free (tmp);
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
if (!d3d_set_render_format (sink))
|
|
|
|
goto incompatible_caps;
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
/* Create a window (or start using an application-supplied one, then connect the graph */
|
|
|
|
d3d_prepare_window (sink);
|
2012-06-19 18:03:02 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
return TRUE;
|
|
|
|
/* ERRORS */
|
|
|
|
incompatible_caps:
|
|
|
|
{
|
|
|
|
GST_ERROR_OBJECT (sink, "caps incompatible");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
invalid_format:
|
|
|
|
{
|
|
|
|
gchar *caps_txt = gst_caps_to_string (caps);
|
|
|
|
GST_DEBUG_OBJECT (sink,
|
|
|
|
"Could not locate image format from caps %s", caps_txt);
|
|
|
|
g_free (caps_txt);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
no_disp_ratio:
|
|
|
|
{
|
|
|
|
GST_ELEMENT_ERROR (sink, CORE, NEGOTIATION, (NULL),
|
|
|
|
("Error calculating the output display ratio of the video."));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
no_display_size:
|
|
|
|
{
|
|
|
|
GST_ELEMENT_ERROR (sink, CORE, NEGOTIATION, (NULL),
|
|
|
|
("Error calculating the output display ratio of the video."));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
}
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
static gboolean
|
|
|
|
gst_d3dvideosink_stop (GstBaseSink * bsink)
|
|
|
|
{
|
|
|
|
GstD3DVideoSink *sink = GST_D3DVIDEOSINK (bsink);
|
|
|
|
GST_DEBUG_OBJECT (bsink, "Stop() called");
|
|
|
|
d3d_stop (sink);
|
|
|
|
return TRUE;
|
|
|
|
}
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
/** PUBLIC FUNCTIONS **/
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
/* Iterface Registrations */
|
2012-06-19 18:03:02 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
static void
|
|
|
|
gst_d3dvideosink_video_overlay_interface_init (GstVideoOverlayInterface * iface)
|
|
|
|
{
|
|
|
|
iface->set_window_handle = gst_d3dvideosink_set_window_handle;
|
|
|
|
iface->set_render_rectangle = gst_d3dvideosink_set_render_rectangle;
|
|
|
|
iface->expose = gst_d3dvideosink_expose;
|
|
|
|
}
|
2012-06-19 18:03:02 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
static void
|
|
|
|
gst_d3dvideosink_navigation_interface_init (GstNavigationInterface * iface)
|
|
|
|
{
|
|
|
|
iface->send_event = gst_d3dvideosink_navigation_send_event;
|
|
|
|
}
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
/* Video Render Code */
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
static void
|
|
|
|
gst_d3dvideosink_set_window_handle (GstVideoOverlay * overlay,
|
|
|
|
guintptr window_id)
|
|
|
|
{
|
|
|
|
d3d_set_window_handle (GST_D3DVIDEOSINK (overlay), window_id, FALSE);
|
2011-06-05 01:43:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-12-22 10:24:28 +00:00
|
|
|
gst_d3dvideosink_set_render_rectangle (GstVideoOverlay * overlay, gint x,
|
|
|
|
gint y, gint width, gint height)
|
2011-06-05 01:43:45 +00:00
|
|
|
{
|
2012-12-22 10:24:28 +00:00
|
|
|
GstD3DVideoSink *sink = GST_D3DVIDEOSINK (overlay);
|
|
|
|
sink->render_rect.x = x;
|
|
|
|
sink->render_rect.y = y;
|
|
|
|
sink->render_rect.w = width;
|
|
|
|
sink->render_rect.h = height;
|
|
|
|
d3d_set_render_rectangle (sink);
|
|
|
|
}
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
static void
|
|
|
|
gst_d3dvideosink_expose (GstVideoOverlay * overlay)
|
|
|
|
{
|
|
|
|
GstD3DVideoSink *sink = GST_D3DVIDEOSINK (overlay);
|
|
|
|
d3d_expose_window (sink);
|
2011-06-05 01:43:45 +00:00
|
|
|
}
|
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
static GstFlowReturn
|
|
|
|
gst_d3dvideosink_show_frame (GstVideoSink * vsink, GstBuffer * buffer)
|
2011-06-05 01:43:45 +00:00
|
|
|
{
|
2012-12-22 10:24:28 +00:00
|
|
|
GstD3DVideoSink *sink = GST_D3DVIDEOSINK (vsink);
|
|
|
|
return d3d_render_buffer (sink, buffer);
|
|
|
|
}
|
2011-06-05 01:43:45 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
/* Video Navigation Events */
|
2012-03-15 21:12:59 +00:00
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
static void
|
|
|
|
gst_d3dvideosink_navigation_send_event (GstNavigation * navigation,
|
|
|
|
GstStructure * structure)
|
|
|
|
{
|
|
|
|
GstD3DVideoSink *sink = GST_D3DVIDEOSINK (navigation);
|
|
|
|
GstEvent *e;
|
|
|
|
|
|
|
|
if ((e = gst_event_new_navigation (structure))) {
|
|
|
|
GstPad *pad;
|
|
|
|
if ((pad = gst_pad_get_peer (GST_VIDEO_SINK_PAD (sink)))) {
|
|
|
|
gst_pad_send_event (pad, e);
|
|
|
|
gst_object_unref (pad);
|
2011-06-05 01:43:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-12-22 10:24:28 +00:00
|
|
|
/** PRIVATE FUNCTIONS **/
|
2011-06-05 01:43:45 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* Plugin entry point */
|
|
|
|
static gboolean
|
|
|
|
plugin_init (GstPlugin * plugin)
|
|
|
|
{
|
|
|
|
/* PRIMARY: this is the best videosink to use on windows */
|
2012-12-22 10:24:28 +00:00
|
|
|
if (!gst_element_register (plugin, ELEMENT_NAME,
|
2011-06-05 01:43:45 +00:00
|
|
|
GST_RANK_PRIMARY, GST_TYPE_D3DVIDEOSINK))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
|
|
|
|
GST_VERSION_MINOR,
|
2012-04-05 16:02:56 +00:00
|
|
|
d3dsinkwrapper,
|
2011-06-05 01:43:45 +00:00
|
|
|
"Direct3D sink wrapper plugin",
|
|
|
|
plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
|