2006-01-05 23:17:44 +00:00
|
|
|
/* GStreamer
|
2007-09-22 08:12:57 +00:00
|
|
|
* Copyright (C) 2005 Sebastien Moutte <sebastien@moutte.net>
|
|
|
|
* Copyright (C) 2007 Pioneers of the Inevitable <songbird@songbirdnest.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
|
|
|
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
* Boston, MA 02111-1307, USA.
|
|
|
|
*
|
|
|
|
* The development of this code was made possible due to the involvement
|
|
|
|
* of Pioneers of the Inevitable, the creators of the Songbird Music player
|
|
|
|
*
|
|
|
|
*/
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2007-02-11 15:26:49 +00:00
|
|
|
/**
|
|
|
|
* SECTION:element-directdrawsink
|
|
|
|
*
|
|
|
|
* <refsect2>
|
|
|
|
* <para>
|
2007-04-29 13:56:18 +00:00
|
|
|
* DirectdrawSink renders video RGB frames to any win32 window. This element
|
|
|
|
* can receive a window ID from the application through the XOverlay interface
|
|
|
|
* and will then render video frames in this window.
|
2007-02-11 15:26:49 +00:00
|
|
|
* If no Window ID was provided by the application, the element will create its
|
|
|
|
* own internal window and render into it.
|
|
|
|
* </para>
|
2007-02-18 18:00:51 +00:00
|
|
|
* <title>Examples</title>
|
|
|
|
* <para>
|
|
|
|
* Here is a simple pipeline to test the sink :
|
|
|
|
* <programlisting>
|
|
|
|
* gst-launch-0.10 -v videotestsrc ! directdrawsink
|
|
|
|
* </programlisting>
|
|
|
|
* </para>
|
2007-02-11 15:26:49 +00:00
|
|
|
* </refsect2>
|
|
|
|
*/
|
|
|
|
|
2006-01-05 23:17:44 +00:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
#include "config.h"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include "gstdirectdrawsink.h"
|
|
|
|
|
|
|
|
GST_DEBUG_CATEGORY_STATIC (directdrawsink_debug);
|
|
|
|
#define GST_CAT_DEFAULT directdrawsink_debug
|
|
|
|
|
|
|
|
/* elementfactory information */
|
2007-02-18 18:00:51 +00:00
|
|
|
static const GstElementDetails gst_directdraw_sink_details =
|
|
|
|
GST_ELEMENT_DETAILS ("Direct Draw Video Sink",
|
2006-01-05 23:17:44 +00:00
|
|
|
"Sink/Video",
|
2007-02-18 18:00:51 +00:00
|
|
|
"Output to a video card via Direct Draw",
|
2006-01-05 23:17:44 +00:00
|
|
|
"Sebastien Moutte <sebastien@moutte.net>");
|
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
static void gst_directdraw_sink_init_interfaces (GType type);
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_BOILERPLATE_FULL (GstDirectDrawSink, gst_directdraw_sink, GstVideoSink,
|
|
|
|
GST_TYPE_VIDEO_SINK, gst_directdraw_sink_init_interfaces);
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
static void gst_directdraw_sink_finalize (GObject * object);
|
|
|
|
static void gst_directdraw_sink_set_property (GObject * object,
|
2006-01-05 23:17:44 +00:00
|
|
|
guint prop_id, const GValue * value, GParamSpec * pspec);
|
2007-02-18 18:00:51 +00:00
|
|
|
static void gst_directdraw_sink_get_property (GObject * object,
|
2006-01-05 23:17:44 +00:00
|
|
|
guint prop_id, GValue * value, GParamSpec * pspec);
|
2007-02-18 18:00:51 +00:00
|
|
|
static GstCaps *gst_directdraw_sink_get_caps (GstBaseSink * bsink);
|
|
|
|
static gboolean gst_directdraw_sink_set_caps (GstBaseSink * bsink,
|
2006-01-05 23:17:44 +00:00
|
|
|
GstCaps * caps);
|
2007-02-18 18:00:51 +00:00
|
|
|
static GstStateChangeReturn gst_directdraw_sink_change_state (GstElement *
|
|
|
|
element, GstStateChange transition);
|
|
|
|
static GstFlowReturn gst_directdraw_sink_buffer_alloc (GstBaseSink * bsink,
|
|
|
|
guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf);
|
|
|
|
static void gst_directdraw_sink_get_times (GstBaseSink * bsink, GstBuffer * buf,
|
2006-01-05 23:17:44 +00:00
|
|
|
GstClockTime * start, GstClockTime * end);
|
2007-02-18 18:00:51 +00:00
|
|
|
static GstFlowReturn gst_directdraw_sink_show_frame (GstBaseSink * bsink,
|
|
|
|
GstBuffer * buf);
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
/* utils */
|
|
|
|
static gboolean gst_directdraw_sink_setup_ddraw (GstDirectDrawSink * ddrawsink);
|
|
|
|
static gboolean gst_directdraw_sink_create_default_window (GstDirectDrawSink *
|
2006-01-05 23:17:44 +00:00
|
|
|
ddrawsink);
|
2007-03-11 22:23:04 +00:00
|
|
|
static gboolean gst_directdraw_sink_check_primary_surface (GstDirectDrawSink *
|
|
|
|
ddrawsink);
|
|
|
|
static gboolean gst_directdraw_sink_check_offscreen_surface (GstDirectDrawSink *
|
2006-01-05 23:17:44 +00:00
|
|
|
ddrawsink);
|
2007-02-18 18:00:51 +00:00
|
|
|
static GstCaps *gst_directdraw_sink_get_ddrawcaps (GstDirectDrawSink *
|
2006-01-05 23:17:44 +00:00
|
|
|
ddrawsink);
|
2007-03-11 22:23:04 +00:00
|
|
|
static GstCaps
|
2007-04-29 13:56:18 +00:00
|
|
|
* gst_directdraw_sink_create_caps_from_surfacedesc (LPDDSURFACEDESC2 desc);
|
2007-02-18 18:00:51 +00:00
|
|
|
static void gst_directdraw_sink_cleanup (GstDirectDrawSink * ddrawsink);
|
|
|
|
static void gst_directdraw_sink_bufferpool_clear (GstDirectDrawSink *
|
|
|
|
ddrawsink);
|
2007-05-20 14:59:46 +00:00
|
|
|
static int gst_directdraw_sink_get_depth (LPDDPIXELFORMAT lpddpfPixelFormat);
|
2007-03-11 22:23:04 +00:00
|
|
|
static gboolean gst_ddrawvideosink_get_format_from_caps (GstDirectDrawSink *
|
|
|
|
ddrawsink, GstCaps * caps, DDPIXELFORMAT * pPixelFormat);
|
|
|
|
static void gst_directdraw_sink_center_rect (GstDirectDrawSink * ddrawsink,
|
|
|
|
RECT src, RECT dst, RECT * result);
|
|
|
|
char *DDErrorString (HRESULT hr);
|
2007-02-11 15:26:49 +00:00
|
|
|
|
|
|
|
/* surfaces management functions */
|
2007-02-18 18:00:51 +00:00
|
|
|
static void gst_directdraw_sink_surface_destroy (GstDirectDrawSink * ddrawsink,
|
2006-01-05 23:17:44 +00:00
|
|
|
GstDDrawSurface * surface);
|
2007-02-18 18:00:51 +00:00
|
|
|
static GstDDrawSurface *gst_directdraw_sink_surface_create (GstDirectDrawSink *
|
2006-01-05 23:17:44 +00:00
|
|
|
ddrawsink, GstCaps * caps, size_t size);
|
2007-03-11 22:23:04 +00:00
|
|
|
static gboolean gst_directdraw_sink_surface_check (GstDirectDrawSink *
|
|
|
|
ddrawsink, GstDDrawSurface * surface);
|
2006-01-05 23:17:44 +00:00
|
|
|
|
|
|
|
static GstStaticPadTemplate directdrawsink_sink_factory =
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_STATIC_PAD_TEMPLATE ("sink",
|
2006-01-05 23:17:44 +00:00
|
|
|
GST_PAD_SINK,
|
|
|
|
GST_PAD_ALWAYS,
|
|
|
|
GST_STATIC_CAPS ("video/x-raw-rgb, "
|
|
|
|
"framerate = (fraction) [ 0, MAX ], "
|
2007-02-18 18:00:51 +00:00
|
|
|
"width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")
|
2006-01-05 23:17:44 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_0,
|
2006-07-24 21:43:06 +00:00
|
|
|
PROP_KEEP_ASPECT_RATIO
|
2006-01-05 23:17:44 +00:00
|
|
|
};
|
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
/* XOverlay interface implementation */
|
2007-02-11 15:26:49 +00:00
|
|
|
static gboolean
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_interface_supported (GstImplementsInterface * iface,
|
2007-02-11 15:26:49 +00:00
|
|
|
GType type)
|
|
|
|
{
|
|
|
|
g_assert (type == GST_TYPE_X_OVERLAY);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_interface_init (GstImplementsInterfaceClass * klass)
|
2007-02-11 15:26:49 +00:00
|
|
|
{
|
2007-02-18 18:00:51 +00:00
|
|
|
klass->supported = gst_directdraw_sink_interface_supported;
|
2007-02-11 15:26:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_set_window_id (GstXOverlay * overlay, ULONG window_id)
|
2007-02-11 15:26:49 +00:00
|
|
|
{
|
|
|
|
GstDirectDrawSink *ddrawsink = GST_DIRECTDRAW_SINK (overlay);
|
|
|
|
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
GST_OBJECT_LOCK (ddrawsink);
|
2007-02-11 15:26:49 +00:00
|
|
|
/* check if we are already using this window id */
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
if (ddrawsink->video_window == (HWND) window_id) {
|
|
|
|
GST_OBJECT_UNLOCK (ddrawsink);
|
2007-02-11 15:26:49 +00:00
|
|
|
return;
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
}
|
2007-02-11 15:26:49 +00:00
|
|
|
|
|
|
|
if (window_id) {
|
|
|
|
HRESULT hres;
|
|
|
|
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
/* If we had an internal window, close it first */
|
|
|
|
if (ddrawsink->video_window && ddrawsink->our_video_window) {
|
|
|
|
/* Trick to let the event thread know that it has to die silently */
|
|
|
|
ddrawsink->our_video_window = FALSE;
|
|
|
|
/* Post quit message and wait for our event window thread */
|
|
|
|
PostMessage (ddrawsink->video_window, WM_QUIT, 0, 0);
|
|
|
|
}
|
|
|
|
|
2007-02-11 15:26:49 +00:00
|
|
|
ddrawsink->video_window = (HWND) window_id;
|
|
|
|
ddrawsink->our_video_window = FALSE;
|
|
|
|
if (ddrawsink->setup) {
|
|
|
|
/* update the clipper object with the new window */
|
|
|
|
hres = IDirectDrawClipper_SetHWnd (ddrawsink->clipper, 0,
|
|
|
|
ddrawsink->video_window);
|
|
|
|
}
|
|
|
|
}
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
/* FIXME: Handle the case where window_id is 0 and we want the sink to
|
|
|
|
* create a new window when playback was already started (after set_caps) */
|
|
|
|
GST_OBJECT_UNLOCK (ddrawsink);
|
2007-02-11 15:26:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_expose (GstXOverlay * overlay)
|
2007-02-11 15:26:49 +00:00
|
|
|
{
|
2007-03-11 22:23:04 +00:00
|
|
|
GstDirectDrawSink *ddrawsink = GST_DIRECTDRAW_SINK (overlay);
|
|
|
|
|
|
|
|
gst_directdraw_sink_show_frame (GST_BASE_SINK (ddrawsink), NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_directdraw_sink_xoverlay_interface_init (GstXOverlayClass * iface)
|
|
|
|
{
|
|
|
|
iface->set_xwindow_id = gst_directdraw_sink_set_window_id;
|
|
|
|
iface->expose = gst_directdraw_sink_expose;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_directdraw_sink_init_interfaces (GType type)
|
|
|
|
{
|
|
|
|
static const GInterfaceInfo iface_info = {
|
|
|
|
(GInterfaceInitFunc) gst_directdraw_sink_interface_init,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
static const GInterfaceInfo xoverlay_info = {
|
|
|
|
(GInterfaceInitFunc) gst_directdraw_sink_xoverlay_interface_init,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
g_type_add_interface_static (type, GST_TYPE_IMPLEMENTS_INTERFACE,
|
|
|
|
&iface_info);
|
|
|
|
g_type_add_interface_static (type, GST_TYPE_X_OVERLAY, &xoverlay_info);
|
2007-02-18 18:00:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Subclass of GstBuffer which manages buffer_pool surfaces lifetime */
|
2007-05-20 14:59:46 +00:00
|
|
|
static void gst_ddrawsurface_finalize (GstMiniObject * mini_object);
|
2008-02-12 12:22:48 +00:00
|
|
|
static GstBufferClass *ddrawsurface_parent_class = NULL;
|
2007-02-18 18:00:51 +00:00
|
|
|
|
|
|
|
static void
|
|
|
|
gst_ddrawsurface_init (GstDDrawSurface * surface, gpointer g_class)
|
|
|
|
{
|
|
|
|
surface->surface = NULL;
|
|
|
|
surface->width = 0;
|
|
|
|
surface->height = 0;
|
|
|
|
surface->ddrawsink = NULL;
|
|
|
|
surface->locked = FALSE;
|
|
|
|
surface->system_memory = FALSE;
|
|
|
|
memset (&surface->dd_pixel_format, 0, sizeof (DDPIXELFORMAT));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_ddrawsurface_class_init (gpointer g_class, gpointer class_data)
|
|
|
|
{
|
|
|
|
GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class);
|
|
|
|
|
2008-02-12 12:22:48 +00:00
|
|
|
ddrawsurface_parent_class = g_type_class_peek_parent (g_class);
|
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
mini_object_class->finalize = GST_DEBUG_FUNCPTR (gst_ddrawsurface_finalize);
|
|
|
|
}
|
|
|
|
|
|
|
|
GType
|
|
|
|
gst_ddrawsurface_get_type (void)
|
|
|
|
{
|
|
|
|
static GType _gst_ddrawsurface_type;
|
|
|
|
|
|
|
|
if (G_UNLIKELY (_gst_ddrawsurface_type == 0)) {
|
|
|
|
static const GTypeInfo ddrawsurface_info = {
|
|
|
|
sizeof (GstBufferClass),
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
gst_ddrawsurface_class_init,
|
|
|
|
NULL,
|
|
|
|
NULL,
|
|
|
|
sizeof (GstDDrawSurface),
|
|
|
|
0,
|
|
|
|
(GInstanceInitFunc) gst_ddrawsurface_init,
|
|
|
|
NULL
|
|
|
|
};
|
|
|
|
_gst_ddrawsurface_type = g_type_register_static (GST_TYPE_BUFFER,
|
|
|
|
"GstDDrawSurface", &ddrawsurface_info, 0);
|
|
|
|
}
|
|
|
|
return _gst_ddrawsurface_type;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-05-20 14:59:46 +00:00
|
|
|
gst_ddrawsurface_finalize (GstMiniObject * mini_object)
|
2007-02-18 18:00:51 +00:00
|
|
|
{
|
|
|
|
GstDirectDrawSink *ddrawsink = NULL;
|
2007-05-20 14:59:46 +00:00
|
|
|
GstDDrawSurface *surface;
|
2007-02-18 18:00:51 +00:00
|
|
|
|
2007-05-20 14:59:46 +00:00
|
|
|
surface = (GstDDrawSurface *) mini_object;
|
2007-02-18 18:00:51 +00:00
|
|
|
|
|
|
|
ddrawsink = surface->ddrawsink;
|
|
|
|
if (!ddrawsink)
|
|
|
|
goto no_sink;
|
|
|
|
|
|
|
|
/* If our geometry changed we can't reuse that image. */
|
|
|
|
if ((surface->width != ddrawsink->video_width) ||
|
|
|
|
(surface->height != ddrawsink->video_height) ||
|
|
|
|
(memcmp (&surface->dd_pixel_format, &ddrawsink->dd_pixel_format,
|
2007-03-11 22:23:04 +00:00
|
|
|
sizeof (DDPIXELFORMAT)) != 0 ||
|
|
|
|
!gst_directdraw_sink_surface_check (ddrawsink, surface))
|
2007-02-18 18:00:51 +00:00
|
|
|
) {
|
|
|
|
GST_CAT_INFO_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"destroy image as its size changed %dx%d vs current %dx%d",
|
|
|
|
surface->width, surface->height, ddrawsink->video_width,
|
|
|
|
ddrawsink->video_height);
|
|
|
|
gst_directdraw_sink_surface_destroy (ddrawsink, surface);
|
2008-02-12 12:22:48 +00:00
|
|
|
GST_MINI_OBJECT_CLASS (ddrawsurface_parent_class)->finalize (mini_object);
|
2007-02-18 18:00:51 +00:00
|
|
|
} else {
|
|
|
|
/* In that case we can reuse the image and add it to our image pool. */
|
|
|
|
GST_CAT_INFO_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"recycling image in pool");
|
|
|
|
|
|
|
|
/* need to increment the refcount again to recycle */
|
|
|
|
gst_buffer_ref (GST_BUFFER (surface));
|
|
|
|
|
|
|
|
g_mutex_lock (ddrawsink->pool_lock);
|
|
|
|
ddrawsink->buffer_pool = g_slist_prepend (ddrawsink->buffer_pool, surface);
|
|
|
|
g_mutex_unlock (ddrawsink->pool_lock);
|
|
|
|
}
|
2008-02-12 12:22:48 +00:00
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
return;
|
|
|
|
|
|
|
|
no_sink:
|
2007-05-20 14:59:46 +00:00
|
|
|
GST_CAT_WARNING (directdrawsink_debug, "no sink found");
|
2008-02-12 12:22:48 +00:00
|
|
|
GST_MINI_OBJECT_CLASS (ddrawsurface_parent_class)->finalize (mini_object);
|
2007-02-18 18:00:51 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/************************************************************************/
|
|
|
|
/* Directdraw sink functions */
|
|
|
|
/************************************************************************/
|
|
|
|
static void
|
|
|
|
gst_directdraw_sink_base_init (gpointer g_class)
|
|
|
|
{
|
|
|
|
GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
|
|
|
|
|
|
|
|
gst_element_class_set_details (element_class, &gst_directdraw_sink_details);
|
|
|
|
gst_element_class_add_pad_template (element_class,
|
|
|
|
gst_static_pad_template_get (&directdrawsink_sink_factory));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_directdraw_sink_class_init (GstDirectDrawSinkClass * klass)
|
|
|
|
{
|
|
|
|
GObjectClass *gobject_class;
|
|
|
|
GstElementClass *gstelement_class;
|
|
|
|
GstBaseSinkClass *gstbasesink_class;
|
|
|
|
|
|
|
|
gobject_class = (GObjectClass *) klass;
|
|
|
|
gstbasesink_class = (GstBaseSinkClass *) klass;
|
|
|
|
gstelement_class = (GstElementClass *) klass;
|
|
|
|
|
|
|
|
GST_DEBUG_CATEGORY_INIT (directdrawsink_debug, "directdrawsink", 0,
|
|
|
|
"Directdraw sink");
|
|
|
|
|
|
|
|
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_directdraw_sink_finalize);
|
|
|
|
gobject_class->get_property =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_directdraw_sink_get_property);
|
|
|
|
gobject_class->set_property =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_directdraw_sink_set_property);
|
|
|
|
gstelement_class->change_state =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_directdraw_sink_change_state);
|
|
|
|
gstbasesink_class->get_caps =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_directdraw_sink_get_caps);
|
|
|
|
gstbasesink_class->set_caps =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_directdraw_sink_set_caps);
|
|
|
|
gstbasesink_class->preroll =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_directdraw_sink_show_frame);
|
|
|
|
gstbasesink_class->render =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_directdraw_sink_show_frame);
|
|
|
|
gstbasesink_class->get_times =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_directdraw_sink_get_times);
|
|
|
|
gstbasesink_class->buffer_alloc =
|
|
|
|
GST_DEBUG_FUNCPTR (gst_directdraw_sink_buffer_alloc);
|
|
|
|
|
|
|
|
/* install properties */
|
|
|
|
/* setup aspect ratio mode */
|
|
|
|
g_object_class_install_property (G_OBJECT_CLASS (klass),
|
2007-06-08 16:31:15 +00:00
|
|
|
PROP_KEEP_ASPECT_RATIO, g_param_spec_boolean ("force-aspect-ratio",
|
|
|
|
"Force aspect ratio",
|
|
|
|
"When enabled, scaling will respect original aspect ratio", FALSE,
|
2007-02-18 18:00:51 +00:00
|
|
|
G_PARAM_READWRITE));
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_directdraw_sink_set_property (GObject * object, guint prop_id,
|
|
|
|
const GValue * value, GParamSpec * pspec)
|
|
|
|
{
|
|
|
|
GstDirectDrawSink *ddrawsink = GST_DIRECTDRAW_SINK (object);
|
|
|
|
|
|
|
|
switch (prop_id) {
|
|
|
|
case PROP_KEEP_ASPECT_RATIO:
|
|
|
|
ddrawsink->keep_aspect_ratio = g_value_get_boolean (value);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_directdraw_sink_get_property (GObject * object, guint prop_id,
|
|
|
|
GValue * value, GParamSpec * pspec)
|
|
|
|
{
|
|
|
|
GstDirectDrawSink *ddrawsink = GST_DIRECTDRAW_SINK (object);
|
|
|
|
|
|
|
|
switch (prop_id) {
|
|
|
|
case PROP_KEEP_ASPECT_RATIO:
|
|
|
|
g_value_set_boolean (value, ddrawsink->keep_aspect_ratio);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_directdraw_sink_finalize (GObject * object)
|
|
|
|
{
|
|
|
|
GstDirectDrawSink *ddrawsink = GST_DIRECTDRAW_SINK (object);
|
|
|
|
|
|
|
|
if (ddrawsink->pool_lock) {
|
|
|
|
g_mutex_free (ddrawsink->pool_lock);
|
|
|
|
ddrawsink->pool_lock = NULL;
|
|
|
|
}
|
|
|
|
if (ddrawsink->caps) {
|
|
|
|
gst_caps_unref (ddrawsink->caps);
|
|
|
|
ddrawsink->caps = NULL;
|
|
|
|
}
|
|
|
|
if (ddrawsink->setup) {
|
|
|
|
gst_directdraw_sink_cleanup (ddrawsink);
|
|
|
|
}
|
2008-02-12 12:22:48 +00:00
|
|
|
|
|
|
|
G_OBJECT_CLASS (parent_class)->finalize (object);
|
2007-02-18 18:00:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_directdraw_sink_init (GstDirectDrawSink * ddrawsink,
|
|
|
|
GstDirectDrawSinkClass * g_class)
|
|
|
|
{
|
|
|
|
/*init members variables */
|
|
|
|
ddrawsink->ddraw_object = NULL;
|
|
|
|
ddrawsink->primary_surface = NULL;
|
|
|
|
ddrawsink->offscreen_surface = NULL;
|
|
|
|
ddrawsink->clipper = NULL;
|
|
|
|
ddrawsink->video_window = NULL;
|
|
|
|
ddrawsink->our_video_window = TRUE;
|
|
|
|
ddrawsink->last_buffer = NULL;
|
|
|
|
ddrawsink->caps = NULL;
|
|
|
|
ddrawsink->window_thread = NULL;
|
|
|
|
ddrawsink->setup = FALSE;
|
|
|
|
ddrawsink->buffer_pool = NULL;
|
|
|
|
ddrawsink->keep_aspect_ratio = FALSE;
|
|
|
|
ddrawsink->pool_lock = g_mutex_new ();
|
2007-03-11 22:23:04 +00:00
|
|
|
ddrawsink->can_blit_between_colorspace = TRUE;
|
|
|
|
ddrawsink->must_recreate_offscreen = FALSE;
|
2007-02-18 18:00:51 +00:00
|
|
|
memset (&ddrawsink->dd_pixel_format, 0, sizeof (DDPIXELFORMAT));
|
|
|
|
|
|
|
|
/*video default values */
|
|
|
|
ddrawsink->video_height = 0;
|
|
|
|
ddrawsink->video_width = 0;
|
|
|
|
ddrawsink->fps_n = 0;
|
|
|
|
ddrawsink->fps_d = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static GstCaps *
|
|
|
|
gst_directdraw_sink_get_caps (GstBaseSink * bsink)
|
|
|
|
{
|
|
|
|
GstDirectDrawSink *ddrawsink = GST_DIRECTDRAW_SINK (bsink);
|
|
|
|
GstCaps *caps = NULL;
|
|
|
|
|
|
|
|
if (!ddrawsink->setup) {
|
|
|
|
caps = gst_caps_copy (gst_pad_get_pad_template_caps (GST_VIDEO_SINK_PAD
|
|
|
|
(ddrawsink)));
|
|
|
|
GST_CAT_INFO_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"getcaps called and we are not setup yet, " "returning template %"
|
|
|
|
GST_PTR_FORMAT, caps);
|
|
|
|
} else {
|
|
|
|
caps = gst_caps_ref (ddrawsink->caps);
|
|
|
|
}
|
|
|
|
|
|
|
|
return caps;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gst_directdraw_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
|
|
|
|
{
|
|
|
|
GstDirectDrawSink *ddrawsink = GST_DIRECTDRAW_SINK (bsink);
|
|
|
|
GstStructure *structure = NULL;
|
|
|
|
gboolean ret;
|
|
|
|
const GValue *fps;
|
|
|
|
|
|
|
|
structure = gst_caps_get_structure (caps, 0);
|
|
|
|
if (!structure)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
ret = gst_structure_get_int (structure, "width", &ddrawsink->video_width);
|
|
|
|
ret &= gst_structure_get_int (structure, "height", &ddrawsink->video_height);
|
|
|
|
fps = gst_structure_get_value (structure, "framerate");
|
|
|
|
ret &= (fps != NULL);
|
|
|
|
ret &=
|
|
|
|
gst_ddrawvideosink_get_format_from_caps (ddrawsink, caps,
|
|
|
|
&ddrawsink->dd_pixel_format);
|
|
|
|
if (!ret) {
|
|
|
|
GST_ELEMENT_ERROR (ddrawsink, CORE, NEGOTIATION,
|
|
|
|
("Failed to get caps properties from caps"), (NULL));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ddrawsink->fps_n = gst_value_get_fraction_numerator (fps);
|
|
|
|
ddrawsink->fps_d = gst_value_get_fraction_denominator (fps);
|
|
|
|
|
|
|
|
/* Notify application to set window id now */
|
|
|
|
if (!ddrawsink->video_window) {
|
|
|
|
gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (ddrawsink));
|
|
|
|
}
|
|
|
|
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
/* If we still don't have a window at that stage we create our own */
|
|
|
|
if (!ddrawsink->video_window) {
|
|
|
|
gst_directdraw_sink_create_default_window (ddrawsink);
|
|
|
|
}
|
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
/* if we are rendering to our own window, resize it to video size */
|
|
|
|
if (ddrawsink->video_window && ddrawsink->our_video_window) {
|
|
|
|
SetWindowPos (ddrawsink->video_window, NULL,
|
|
|
|
0, 0, ddrawsink->video_width + (GetSystemMetrics (SM_CXSIZEFRAME) * 2),
|
|
|
|
ddrawsink->video_height + GetSystemMetrics (SM_CYCAPTION) +
|
|
|
|
(GetSystemMetrics (SM_CYSIZEFRAME) * 2), SWP_SHOWWINDOW | SWP_NOMOVE);
|
|
|
|
}
|
|
|
|
|
2008-05-07 15:09:10 +00:00
|
|
|
/* release the surface, we have to recreate it! */
|
|
|
|
if (ddrawsink->offscreen_surface) {
|
|
|
|
IDirectDrawSurface7_Release (ddrawsink->offscreen_surface);
|
|
|
|
ddrawsink->offscreen_surface = NULL;
|
|
|
|
}
|
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
/* create an offscreen surface with the caps */
|
2007-03-11 22:23:04 +00:00
|
|
|
ret = gst_directdraw_sink_check_offscreen_surface (ddrawsink);
|
2007-02-18 18:00:51 +00:00
|
|
|
if (!ret) {
|
|
|
|
GST_ELEMENT_ERROR (ddrawsink, CORE, NEGOTIATION,
|
|
|
|
("Can't create a directdraw offscreen surface with the input caps"),
|
|
|
|
(NULL));
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
2006-01-05 23:17:44 +00:00
|
|
|
}
|
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
static GstStateChangeReturn
|
|
|
|
gst_directdraw_sink_change_state (GstElement * element,
|
|
|
|
GstStateChange transition)
|
|
|
|
{
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
GstDirectDrawSink *ddrawsink = GST_DIRECTDRAW_SINK (element);
|
|
|
|
GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
|
2007-02-18 18:00:51 +00:00
|
|
|
|
|
|
|
switch (transition) {
|
|
|
|
case GST_STATE_CHANGE_NULL_TO_READY:
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
if (!gst_directdraw_sink_setup_ddraw (ddrawsink)) {
|
|
|
|
ret = GST_STATE_CHANGE_FAILURE;
|
|
|
|
goto beach;
|
|
|
|
}
|
2007-02-18 18:00:51 +00:00
|
|
|
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
if (!(ddrawsink->caps = gst_directdraw_sink_get_ddrawcaps (ddrawsink))) {
|
|
|
|
ret = GST_STATE_CHANGE_FAILURE;
|
|
|
|
goto beach;
|
|
|
|
}
|
2007-02-18 18:00:51 +00:00
|
|
|
break;
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
default:
|
2007-02-18 18:00:51 +00:00
|
|
|
break;
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
|
|
|
|
|
|
|
|
switch (transition) {
|
2007-02-18 18:00:51 +00:00
|
|
|
case GST_STATE_CHANGE_PAUSED_TO_READY:
|
|
|
|
ddrawsink->fps_n = 0;
|
|
|
|
ddrawsink->fps_d = 1;
|
|
|
|
ddrawsink->video_width = 0;
|
|
|
|
ddrawsink->video_height = 0;
|
|
|
|
if (ddrawsink->buffer_pool)
|
|
|
|
gst_directdraw_sink_bufferpool_clear (ddrawsink);
|
|
|
|
break;
|
|
|
|
case GST_STATE_CHANGE_READY_TO_NULL:
|
|
|
|
if (ddrawsink->setup)
|
|
|
|
gst_directdraw_sink_cleanup (ddrawsink);
|
|
|
|
break;
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
default:
|
|
|
|
break;
|
2007-02-18 18:00:51 +00:00
|
|
|
}
|
|
|
|
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
beach:
|
|
|
|
return ret;
|
2007-02-18 18:00:51 +00:00
|
|
|
}
|
2006-01-05 23:17:44 +00:00
|
|
|
|
|
|
|
static GstFlowReturn
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_buffer_alloc (GstBaseSink * bsink, guint64 offset,
|
2006-01-05 23:17:44 +00:00
|
|
|
guint size, GstCaps * caps, GstBuffer ** buf)
|
|
|
|
{
|
2007-02-18 18:00:51 +00:00
|
|
|
GstDirectDrawSink *ddrawsink = GST_DIRECTDRAW_SINK (bsink);
|
2008-05-07 14:56:22 +00:00
|
|
|
GstStructure *structure;
|
|
|
|
gint width, height;
|
2006-01-05 23:17:44 +00:00
|
|
|
GstDDrawSurface *surface = NULL;
|
|
|
|
GstFlowReturn ret = GST_FLOW_OK;
|
2007-03-11 22:23:04 +00:00
|
|
|
GstCaps *buffer_caps = caps;
|
|
|
|
gboolean buffercaps_unref = FALSE;
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_CAT_INFO_OBJECT (directdrawsink_debug, ddrawsink,
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
"a buffer of %u bytes was requested", size);
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2008-05-07 14:56:22 +00:00
|
|
|
structure = gst_caps_get_structure (caps, 0);
|
|
|
|
if (!gst_structure_get_int (structure, "width", &width) ||
|
|
|
|
!gst_structure_get_int (structure, "height", &height)) {
|
|
|
|
GST_WARNING_OBJECT (ddrawsink, "invalid caps for buffer allocation %"
|
|
|
|
GST_PTR_FORMAT, caps);
|
|
|
|
return GST_FLOW_UNEXPECTED;
|
|
|
|
}
|
|
|
|
|
2006-01-05 23:17:44 +00:00
|
|
|
g_mutex_lock (ddrawsink->pool_lock);
|
|
|
|
|
|
|
|
/* Inspect our buffer pool */
|
|
|
|
while (ddrawsink->buffer_pool) {
|
|
|
|
surface = (GstDDrawSurface *) ddrawsink->buffer_pool->data;
|
|
|
|
if (surface) {
|
|
|
|
/* Removing from the pool */
|
|
|
|
ddrawsink->buffer_pool = g_slist_delete_link (ddrawsink->buffer_pool,
|
|
|
|
ddrawsink->buffer_pool);
|
|
|
|
|
|
|
|
/* If the surface is invalid for our need, destroy */
|
2008-05-07 14:56:22 +00:00
|
|
|
if ((surface->width != width) ||
|
|
|
|
(surface->height != height) ||
|
2006-01-05 23:17:44 +00:00
|
|
|
(memcmp (&surface->dd_pixel_format, &ddrawsink->dd_pixel_format,
|
2007-03-11 22:23:04 +00:00
|
|
|
sizeof (DDPIXELFORMAT)) ||
|
|
|
|
!gst_directdraw_sink_surface_check (ddrawsink, surface))
|
2006-01-05 23:17:44 +00:00
|
|
|
) {
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_surface_destroy (ddrawsink, surface);
|
2006-01-05 23:17:44 +00:00
|
|
|
surface = NULL;
|
|
|
|
} else {
|
|
|
|
/* We found a suitable surface */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2007-03-11 22:23:04 +00:00
|
|
|
if (!ddrawsink->can_blit_between_colorspace) {
|
|
|
|
/* Hardware doesn't support blit from one colorspace to another.
|
|
|
|
* Check if the colorspace of the current display mode has changed since
|
|
|
|
* the last negociation. If it's the case, we will have to renegociate
|
|
|
|
*/
|
|
|
|
guint depth;
|
|
|
|
HRESULT hres;
|
|
|
|
DDSURFACEDESC2 surface_desc;
|
2007-05-24 08:35:23 +00:00
|
|
|
DDSURFACEDESC2 *sd;
|
2007-03-11 22:23:04 +00:00
|
|
|
|
|
|
|
if (!gst_structure_get_int (structure, "depth", &depth)) {
|
|
|
|
GST_CAT_DEBUG_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"Can't get depth from buffer_alloc caps");
|
|
|
|
return GST_FLOW_ERROR;
|
|
|
|
}
|
2007-05-24 08:35:23 +00:00
|
|
|
surface_desc.dwSize = sizeof (surface_desc);
|
|
|
|
sd = &surface_desc;
|
|
|
|
hres =
|
|
|
|
IDirectDraw7_GetDisplayMode (ddrawsink->ddraw_object,
|
|
|
|
(DDSURFACEDESC *) sd);
|
2007-03-11 22:23:04 +00:00
|
|
|
if (hres != DD_OK) {
|
|
|
|
GST_CAT_DEBUG_OBJECT (directdrawsink_debug, ddrawsink,
|
2007-05-20 14:59:46 +00:00
|
|
|
"Can't get current display mode (error=%ld)", (glong) hres);
|
2007-03-11 22:23:04 +00:00
|
|
|
return GST_FLOW_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (depth != gst_directdraw_sink_get_depth (&surface_desc.ddpfPixelFormat)) {
|
|
|
|
GstCaps *copy_caps = NULL;
|
|
|
|
GstStructure *copy_structure = NULL;
|
|
|
|
GstCaps *display_caps = NULL;
|
|
|
|
GstStructure *display_structure = NULL;
|
|
|
|
|
|
|
|
/* make a copy of the original caps */
|
|
|
|
copy_caps = gst_caps_copy (caps);
|
|
|
|
copy_structure = gst_caps_get_structure (copy_caps, 0);
|
|
|
|
|
|
|
|
display_caps =
|
|
|
|
gst_directdraw_sink_create_caps_from_surfacedesc (&surface_desc);
|
|
|
|
if (display_caps) {
|
|
|
|
display_structure = gst_caps_get_structure (display_caps, 0);
|
|
|
|
if (display_structure) {
|
|
|
|
gint bpp, endianness, red_mask, green_mask, blue_mask;
|
|
|
|
|
|
|
|
/* get new display mode properties */
|
|
|
|
gst_structure_get_int (display_structure, "depth", &depth);
|
|
|
|
gst_structure_get_int (display_structure, "bpp", &bpp);
|
|
|
|
gst_structure_get_int (display_structure, "endianness", &endianness);
|
|
|
|
gst_structure_get_int (display_structure, "red_mask", &red_mask);
|
|
|
|
gst_structure_get_int (display_structure, "green_mask", &green_mask);
|
|
|
|
gst_structure_get_int (display_structure, "blue_mask", &blue_mask);
|
|
|
|
|
|
|
|
/* apply the new display mode changes to the previous caps */
|
|
|
|
gst_structure_set (copy_structure,
|
|
|
|
"bpp", G_TYPE_INT, bpp,
|
|
|
|
"depth", G_TYPE_INT, depth,
|
|
|
|
"endianness", G_TYPE_INT, endianness,
|
|
|
|
"red_mask", G_TYPE_INT, red_mask,
|
|
|
|
"green_mask", G_TYPE_INT, green_mask,
|
|
|
|
"blue_mask", G_TYPE_INT, blue_mask, NULL);
|
|
|
|
|
|
|
|
if (gst_pad_peer_accept_caps (GST_VIDEO_SINK_PAD (ddrawsink),
|
|
|
|
copy_caps)) {
|
|
|
|
buffer_caps = copy_caps;
|
|
|
|
buffercaps_unref = TRUE;
|
|
|
|
/* update buffer size needed to store video frames according to new caps */
|
2008-05-07 14:56:22 +00:00
|
|
|
size = width * height * (bpp / 8);
|
2007-03-11 22:23:04 +00:00
|
|
|
|
|
|
|
/* update our member pixel format */
|
|
|
|
gst_ddrawvideosink_get_format_from_caps (ddrawsink, buffer_caps,
|
|
|
|
&ddrawsink->dd_pixel_format);
|
|
|
|
ddrawsink->must_recreate_offscreen = TRUE;
|
|
|
|
|
|
|
|
GST_CAT_DEBUG_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
" desired caps %s \n\n new caps %s", gst_caps_to_string (caps),
|
|
|
|
gst_caps_to_string (buffer_caps));
|
|
|
|
} else {
|
|
|
|
GST_CAT_DEBUG_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"peer refused caps re-negociation "
|
|
|
|
"and we can't render with the current caps.");
|
|
|
|
ret = GST_FLOW_ERROR;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
gst_caps_unref (display_caps);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!buffercaps_unref)
|
|
|
|
gst_caps_unref (copy_caps);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-05 23:17:44 +00:00
|
|
|
/* We haven't found anything, creating a new one */
|
|
|
|
if (!surface) {
|
2007-03-11 22:23:04 +00:00
|
|
|
surface = gst_directdraw_sink_surface_create (ddrawsink, buffer_caps, size);
|
2006-01-05 23:17:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Now we should have a surface, set appropriate caps on it */
|
|
|
|
if (surface) {
|
2008-05-07 14:43:39 +00:00
|
|
|
GST_BUFFER_FLAGS (GST_BUFFER (surface)) = 0;
|
2007-03-11 22:23:04 +00:00
|
|
|
gst_buffer_set_caps (GST_BUFFER (surface), buffer_caps);
|
2006-01-05 23:17:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
g_mutex_unlock (ddrawsink->pool_lock);
|
|
|
|
|
|
|
|
*buf = GST_BUFFER (surface);
|
|
|
|
|
2007-03-11 22:23:04 +00:00
|
|
|
if (buffercaps_unref)
|
|
|
|
gst_caps_unref (buffer_caps);
|
|
|
|
|
2006-01-05 23:17:44 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
static void
|
|
|
|
gst_directdraw_sink_draw_borders (GstDirectDrawSink * ddrawsink, RECT dst_rect)
|
|
|
|
{
|
|
|
|
RECT win_rect, fill_rect;
|
|
|
|
POINT win_point;
|
|
|
|
HDC hdc;
|
|
|
|
|
|
|
|
g_return_if_fail (GST_IS_DIRECTDRAW_SINK (ddrawsink));
|
|
|
|
|
|
|
|
/* Get the target window rect */
|
|
|
|
win_point.x = 0;
|
|
|
|
win_point.y = 0;
|
|
|
|
ClientToScreen (ddrawsink->video_window, &win_point);
|
|
|
|
GetClientRect (ddrawsink->video_window, &win_rect);
|
|
|
|
OffsetRect (&win_rect, win_point.x, win_point.y);
|
|
|
|
|
|
|
|
/* We acquire a drawing context */
|
|
|
|
if (IDirectDrawSurface7_GetDC (ddrawsink->primary_surface, &hdc) == DD_OK) {
|
|
|
|
HBRUSH brush = CreateSolidBrush (RGB (0, 0, 0));
|
|
|
|
|
|
|
|
/* Left border */
|
|
|
|
if (dst_rect.left > win_rect.left) {
|
|
|
|
fill_rect.left = win_rect.left;
|
|
|
|
fill_rect.top = win_rect.top;
|
|
|
|
fill_rect.bottom = win_rect.bottom;
|
|
|
|
fill_rect.right = dst_rect.left;
|
|
|
|
FillRect (hdc, &fill_rect, brush);
|
|
|
|
}
|
|
|
|
/* Right border */
|
|
|
|
if (dst_rect.right < win_rect.right) {
|
|
|
|
fill_rect.top = win_rect.top;
|
|
|
|
fill_rect.left = dst_rect.right;
|
|
|
|
fill_rect.bottom = win_rect.bottom;
|
|
|
|
fill_rect.right = win_rect.right;
|
|
|
|
FillRect (hdc, &fill_rect, brush);
|
|
|
|
}
|
|
|
|
/* Top border */
|
|
|
|
if (dst_rect.top > win_rect.top) {
|
|
|
|
fill_rect.top = win_rect.top;
|
|
|
|
fill_rect.left = win_rect.left;
|
|
|
|
fill_rect.right = win_rect.right;
|
|
|
|
fill_rect.bottom = dst_rect.top;
|
|
|
|
FillRect (hdc, &fill_rect, brush);
|
|
|
|
}
|
|
|
|
/* Bottom border */
|
|
|
|
if (dst_rect.bottom < win_rect.bottom) {
|
|
|
|
fill_rect.top = dst_rect.bottom;
|
|
|
|
fill_rect.left = win_rect.left;
|
|
|
|
fill_rect.right = win_rect.right;
|
|
|
|
fill_rect.bottom = win_rect.bottom;
|
|
|
|
FillRect (hdc, &fill_rect, brush);
|
|
|
|
}
|
|
|
|
DeleteObject (brush);
|
|
|
|
IDirectDrawSurface7_ReleaseDC (ddrawsink->primary_surface, hdc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-01-05 23:17:44 +00:00
|
|
|
static GstFlowReturn
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_show_frame (GstBaseSink * bsink, GstBuffer * buf)
|
2006-01-05 23:17:44 +00:00
|
|
|
{
|
2007-02-18 18:00:51 +00:00
|
|
|
GstDirectDrawSink *ddrawsink = GST_DIRECTDRAW_SINK (bsink);
|
2006-01-05 23:17:44 +00:00
|
|
|
HRESULT hRes;
|
|
|
|
RECT destsurf_rect, src_rect;
|
|
|
|
POINT dest_surf_point;
|
2007-02-11 15:26:49 +00:00
|
|
|
|
|
|
|
if (buf) {
|
2007-02-18 18:00:51 +00:00
|
|
|
/* save a reference to the input buffer */
|
2007-02-11 15:26:49 +00:00
|
|
|
if (ddrawsink->last_buffer != buf) {
|
|
|
|
if (ddrawsink->last_buffer) {
|
|
|
|
gst_buffer_unref (ddrawsink->last_buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ddrawsink->last_buffer = gst_buffer_ref (buf);
|
|
|
|
} else {
|
2007-02-18 18:00:51 +00:00
|
|
|
/* use last buffer */
|
2007-02-11 15:26:49 +00:00
|
|
|
buf = ddrawsink->last_buffer;
|
|
|
|
}
|
2008-05-07 15:19:47 +00:00
|
|
|
|
|
|
|
if (buf == NULL) {
|
|
|
|
GST_ERROR_OBJECT (ddrawsink, "No buffer to render.");
|
|
|
|
return GST_FLOW_ERROR;
|
|
|
|
} else if (!ddrawsink->video_window) {
|
|
|
|
GST_WARNING_OBJECT (ddrawsink, "No video window to render to.");
|
2007-02-11 15:26:49 +00:00
|
|
|
return GST_FLOW_ERROR;
|
2008-05-07 15:19:47 +00:00
|
|
|
}
|
2007-02-11 15:26:49 +00:00
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
/* get the video window position */
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
GST_OBJECT_LOCK (ddrawsink);
|
|
|
|
if (G_UNLIKELY (!ddrawsink->video_window)) {
|
|
|
|
GST_OBJECT_UNLOCK (ddrawsink);
|
|
|
|
GST_CAT_WARNING_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"gst_directdraw_sink_show_frame our video window disappeared");
|
|
|
|
GST_ELEMENT_ERROR (ddrawsink, RESOURCE, NOT_FOUND,
|
|
|
|
("Output window was closed"), (NULL));
|
|
|
|
return GST_FLOW_ERROR;
|
|
|
|
}
|
2007-02-18 18:00:51 +00:00
|
|
|
dest_surf_point.x = 0;
|
|
|
|
dest_surf_point.y = 0;
|
|
|
|
ClientToScreen (ddrawsink->video_window, &dest_surf_point);
|
|
|
|
GetClientRect (ddrawsink->video_window, &destsurf_rect);
|
|
|
|
OffsetRect (&destsurf_rect, dest_surf_point.x, dest_surf_point.y);
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2006-07-24 21:43:06 +00:00
|
|
|
if (ddrawsink->keep_aspect_ratio) {
|
2007-02-11 15:26:49 +00:00
|
|
|
/* center image to dest image keeping aspect ratio */
|
2006-07-24 21:43:06 +00:00
|
|
|
src_rect.top = 0;
|
|
|
|
src_rect.left = 0;
|
|
|
|
src_rect.bottom = ddrawsink->video_height;
|
|
|
|
src_rect.right = ddrawsink->video_width;
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_center_rect (ddrawsink, src_rect, destsurf_rect,
|
|
|
|
&destsurf_rect);
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
gst_directdraw_sink_draw_borders (ddrawsink, destsurf_rect);
|
2006-01-05 23:17:44 +00:00
|
|
|
}
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
GST_OBJECT_UNLOCK (ddrawsink);
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2007-03-11 22:23:04 +00:00
|
|
|
if (ddrawsink->must_recreate_offscreen && ddrawsink->offscreen_surface) {
|
|
|
|
IDirectDrawSurface7_Release (ddrawsink->offscreen_surface);
|
|
|
|
ddrawsink->offscreen_surface = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* check for surfaces lost */
|
|
|
|
if (!gst_directdraw_sink_check_primary_surface (ddrawsink) ||
|
|
|
|
!gst_directdraw_sink_check_offscreen_surface (ddrawsink)) {
|
|
|
|
return GST_FLOW_ERROR;
|
|
|
|
}
|
|
|
|
|
2006-01-05 23:17:44 +00:00
|
|
|
if (!GST_IS_DDRAWSURFACE (buf) ||
|
|
|
|
((GST_IS_DDRAWSURFACE (buf)) && (GST_BUFFER (buf)->malloc_data))) {
|
2007-02-18 18:00:51 +00:00
|
|
|
/* We are receiving a system memory buffer so we will copy
|
|
|
|
to the memory of our offscreen surface and next blit this surface
|
|
|
|
on the primary surface */
|
2006-01-05 23:17:44 +00:00
|
|
|
LPBYTE data = NULL;
|
2007-02-18 18:00:51 +00:00
|
|
|
guint src_pitch, line;
|
|
|
|
DDSURFACEDESC2 surf_desc;
|
2007-05-24 08:35:23 +00:00
|
|
|
DDSURFACEDESC2 *sd;
|
2006-01-05 23:17:44 +00:00
|
|
|
|
|
|
|
ZeroMemory (&surf_desc, sizeof (surf_desc));
|
|
|
|
surf_desc.dwSize = sizeof (surf_desc);
|
2007-05-24 08:35:23 +00:00
|
|
|
sd = &surf_desc;
|
2006-01-05 23:17:44 +00:00
|
|
|
|
|
|
|
/* Lock the surface */
|
|
|
|
hRes =
|
2007-02-18 18:00:51 +00:00
|
|
|
IDirectDrawSurface7_Lock (ddrawsink->offscreen_surface, NULL,
|
2007-05-24 08:35:23 +00:00
|
|
|
(DDSURFACEDESC *) sd, DDLOCK_WAIT, NULL);
|
2006-01-05 23:17:44 +00:00
|
|
|
if (hRes != DD_OK) {
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_CAT_WARNING_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"gst_directdraw_sink_show_frame failed locking surface %s",
|
2006-01-05 23:17:44 +00:00
|
|
|
DDErrorString (hRes));
|
2008-05-07 15:28:06 +00:00
|
|
|
|
|
|
|
if (IDirectDrawSurface7_IsLost (ddrawsink->offscreen_surface) == DD_OK)
|
|
|
|
return GST_FLOW_OK;
|
|
|
|
else
|
|
|
|
return GST_FLOW_ERROR;
|
2006-01-05 23:17:44 +00:00
|
|
|
}
|
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
/* Write each line respecting the destination surface pitch */
|
2006-01-05 23:17:44 +00:00
|
|
|
data = surf_desc.lpSurface;
|
|
|
|
src_pitch = GST_BUFFER_SIZE (buf) / ddrawsink->video_height;
|
2007-02-18 18:00:51 +00:00
|
|
|
for (line = 0; line < surf_desc.dwHeight; line++) {
|
|
|
|
memcpy (data, GST_BUFFER_DATA (buf) + (line * src_pitch), src_pitch);
|
2006-01-05 23:17:44 +00:00
|
|
|
data += surf_desc.lPitch;
|
2007-02-18 18:00:51 +00:00
|
|
|
}
|
2006-01-05 23:17:44 +00:00
|
|
|
|
|
|
|
/* Unlock the surface */
|
2007-02-18 18:00:51 +00:00
|
|
|
hRes = IDirectDrawSurface7_Unlock (ddrawsink->offscreen_surface, NULL);
|
2006-01-05 23:17:44 +00:00
|
|
|
if (hRes != DD_OK) {
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_CAT_WARNING_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"gst_directdraw_sink_show_frame failed unlocking surface %s",
|
2006-01-05 23:17:44 +00:00
|
|
|
DDErrorString (hRes));
|
|
|
|
return GST_FLOW_ERROR;
|
|
|
|
}
|
|
|
|
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
/* blit to primary surface ( Blt will scale the video the dest rect surface
|
|
|
|
* if needed */
|
2007-02-18 18:00:51 +00:00
|
|
|
hRes = IDirectDrawSurface7_Blt (ddrawsink->primary_surface, &destsurf_rect,
|
|
|
|
ddrawsink->offscreen_surface, NULL, DDBLT_WAIT, NULL);
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
if (hRes != DD_OK) /* FIXME: Is it really safe to continue past here ? */
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_CAT_WARNING_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"IDirectDrawSurface7_Blt (object's offscreen surface) " "returned %s",
|
|
|
|
DDErrorString (hRes));
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
} else {
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
/* We are receiving a directdraw surface (previously returned by our buffer
|
|
|
|
* pool so we will simply blit it on the primary surface */
|
2006-01-05 23:17:44 +00:00
|
|
|
GstDDrawSurface *surface = NULL;
|
|
|
|
|
|
|
|
surface = GST_DDRAWSURFACE (buf);
|
|
|
|
|
|
|
|
/* Unlocking surface before blit */
|
2007-02-11 15:26:49 +00:00
|
|
|
IDirectDrawSurface7_Unlock (surface->surface, NULL);
|
2006-01-05 23:17:44 +00:00
|
|
|
surface->locked = FALSE;
|
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
/* blit to our primary surface */
|
|
|
|
hRes = IDirectDrawSurface7_Blt (ddrawsink->primary_surface, &destsurf_rect,
|
|
|
|
surface->surface, NULL, DDBLT_WAIT, NULL);
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
if (hRes != DD_OK) /* FIXME: Is it really safe to continue past here ? */
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_CAT_WARNING_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"IDirectDrawSurface7_Blt (offscreen surface from buffer_alloc) "
|
|
|
|
"returned %s", DDErrorString (hRes));
|
2006-01-05 23:17:44 +00:00
|
|
|
}
|
2007-03-11 22:23:04 +00:00
|
|
|
|
|
|
|
return GST_FLOW_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
gst_directdraw_sink_get_times (GstBaseSink * bsink, GstBuffer * buf,
|
|
|
|
GstClockTime * start, GstClockTime * end)
|
|
|
|
{
|
|
|
|
GstDirectDrawSink *ddrawsink;
|
|
|
|
|
|
|
|
ddrawsink = GST_DIRECTDRAW_SINK (bsink);
|
|
|
|
|
|
|
|
if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) {
|
|
|
|
*start = GST_BUFFER_TIMESTAMP (buf);
|
|
|
|
if (GST_BUFFER_DURATION_IS_VALID (buf)) {
|
|
|
|
*end = *start + GST_BUFFER_DURATION (buf);
|
|
|
|
} else {
|
|
|
|
if (ddrawsink->fps_n > 0) {
|
|
|
|
*end = *start + (GST_SECOND * ddrawsink->fps_d) / ddrawsink->fps_n;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Utility functions */
|
|
|
|
|
|
|
|
/* this function fill a DDPIXELFORMAT using Gstreamer caps */
|
|
|
|
static gboolean
|
|
|
|
gst_ddrawvideosink_get_format_from_caps (GstDirectDrawSink * ddrawsink,
|
|
|
|
GstCaps * caps, DDPIXELFORMAT * pPixelFormat)
|
|
|
|
{
|
|
|
|
GstStructure *structure = NULL;
|
|
|
|
gboolean ret = TRUE;
|
|
|
|
|
|
|
|
/* check params */
|
|
|
|
g_return_val_if_fail (pPixelFormat, FALSE);
|
|
|
|
g_return_val_if_fail (caps, FALSE);
|
|
|
|
|
|
|
|
/* init structure */
|
|
|
|
memset (pPixelFormat, 0, sizeof (DDPIXELFORMAT));
|
|
|
|
pPixelFormat->dwSize = sizeof (DDPIXELFORMAT);
|
|
|
|
|
|
|
|
if (!(structure = gst_caps_get_structure (caps, 0))) {
|
|
|
|
GST_CAT_ERROR_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"can't get structure pointer from caps");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gst_structure_has_name (structure, "video/x-raw-rgb")) {
|
|
|
|
gint depth, bitcount, bitmask, endianness;
|
|
|
|
|
|
|
|
pPixelFormat->dwFlags = DDPF_RGB;
|
|
|
|
ret &= gst_structure_get_int (structure, "bpp", &bitcount);
|
|
|
|
pPixelFormat->dwRGBBitCount = bitcount;
|
|
|
|
ret &= gst_structure_get_int (structure, "depth", &depth);
|
|
|
|
ret &= gst_structure_get_int (structure, "red_mask", &bitmask);
|
|
|
|
pPixelFormat->dwRBitMask = bitmask;
|
|
|
|
ret &= gst_structure_get_int (structure, "green_mask", &bitmask);
|
|
|
|
pPixelFormat->dwGBitMask = bitmask;
|
|
|
|
ret &= gst_structure_get_int (structure, "blue_mask", &bitmask);
|
|
|
|
pPixelFormat->dwBBitMask = bitmask;
|
|
|
|
|
|
|
|
gst_structure_get_int (structure, "endianness", &endianness);
|
|
|
|
if (endianness == G_BIG_ENDIAN) {
|
|
|
|
endianness = G_LITTLE_ENDIAN;
|
|
|
|
pPixelFormat->dwRBitMask = GUINT32_TO_BE (pPixelFormat->dwRBitMask);
|
|
|
|
pPixelFormat->dwGBitMask = GUINT32_TO_BE (pPixelFormat->dwGBitMask);
|
|
|
|
pPixelFormat->dwBBitMask = GUINT32_TO_BE (pPixelFormat->dwBBitMask);
|
|
|
|
}
|
|
|
|
} else if (gst_structure_has_name (structure, "video/x-raw-yuv")) {
|
|
|
|
gint fourcc;
|
|
|
|
|
|
|
|
pPixelFormat->dwFlags = DDPF_FOURCC;
|
|
|
|
ret &= gst_structure_get_fourcc (structure, "format", &fourcc);
|
|
|
|
pPixelFormat->dwFourCC = fourcc;
|
|
|
|
} else {
|
|
|
|
GST_CAT_WARNING_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"unknown caps name received %" GST_PTR_FORMAT, caps);
|
|
|
|
ret = FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* This function centers the RECT of source surface to
|
|
|
|
a dest surface and set the result RECT into result */
|
|
|
|
static void
|
|
|
|
gst_directdraw_sink_center_rect (GstDirectDrawSink * ddrawsink, RECT src,
|
|
|
|
RECT dst, RECT * result)
|
|
|
|
{
|
|
|
|
gdouble src_ratio, dst_ratio;
|
|
|
|
long src_width = src.right;
|
|
|
|
long src_height = src.bottom;
|
|
|
|
long dst_width = dst.right - dst.left;
|
|
|
|
long dst_heigth = dst.bottom - dst.top;
|
|
|
|
long result_width = 0, result_height = 0;
|
|
|
|
|
|
|
|
g_return_if_fail (result != NULL);
|
|
|
|
|
|
|
|
src_ratio = (gdouble) src_width / src_height;
|
|
|
|
dst_ratio = (gdouble) dst_width / dst_heigth;
|
|
|
|
|
|
|
|
if (src_ratio > dst_ratio) {
|
|
|
|
/* new height */
|
|
|
|
result_height = (long) (dst_width / src_ratio);
|
|
|
|
|
|
|
|
result->left = dst.left;
|
|
|
|
result->right = dst.right;
|
|
|
|
result->top = dst.top + (dst_heigth - result_height) / 2;
|
|
|
|
result->bottom = result->top + result_height;
|
|
|
|
|
|
|
|
} else if (src_ratio < dst_ratio) {
|
|
|
|
/* new width */
|
|
|
|
result_width = (long) (dst_heigth * src_ratio);
|
|
|
|
|
|
|
|
result->top = dst.top;
|
|
|
|
result->bottom = dst.bottom;
|
|
|
|
result->left = dst.left + (dst_width - result_width) / 2;
|
|
|
|
result->right = result->left + result_width;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
/* same ratio */
|
|
|
|
memcpy (result, &dst, sizeof (RECT));
|
|
|
|
}
|
|
|
|
|
|
|
|
GST_CAT_INFO_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"source is %ldx%ld dest is %ldx%ld, result is %ldx%ld with x,y %ldx%ld",
|
|
|
|
src_width, src_height, dst_width, dst_heigth,
|
|
|
|
result->right - result->left, result->bottom - result->top, result->left,
|
|
|
|
result->right);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get DirectDraw error message.
|
|
|
|
* @hr: HRESULT code
|
|
|
|
* Returns: Text representation of the error.
|
|
|
|
*/
|
|
|
|
char *
|
|
|
|
DDErrorString (HRESULT hr)
|
|
|
|
{
|
|
|
|
switch (hr) {
|
|
|
|
case DDERR_ALREADYINITIALIZED:
|
|
|
|
return "DDERR_ALREADYINITIALIZED";
|
|
|
|
case DDERR_CANNOTATTACHSURFACE:
|
|
|
|
return "DDERR_CANNOTATTACHSURFACE";
|
|
|
|
case DDERR_CANNOTDETACHSURFACE:
|
|
|
|
return "DDERR_CANNOTDETACHSURFACE";
|
|
|
|
case DDERR_CURRENTLYNOTAVAIL:
|
|
|
|
return "DDERR_CURRENTLYNOTAVAIL";
|
|
|
|
case DDERR_EXCEPTION:
|
|
|
|
return "DDERR_EXCEPTION";
|
|
|
|
case DDERR_GENERIC:
|
|
|
|
return "DDERR_GENERIC";
|
|
|
|
case DDERR_HEIGHTALIGN:
|
|
|
|
return "DDERR_HEIGHTALIGN";
|
|
|
|
case DDERR_INCOMPATIBLEPRIMARY:
|
|
|
|
return "DDERR_INCOMPATIBLEPRIMARY";
|
|
|
|
case DDERR_INVALIDCAPS:
|
|
|
|
return "DDERR_INVALIDCAPS";
|
|
|
|
case DDERR_INVALIDCLIPLIST:
|
|
|
|
return "DDERR_INVALIDCLIPLIST";
|
|
|
|
case DDERR_INVALIDMODE:
|
|
|
|
return "DDERR_INVALIDMODE";
|
|
|
|
case DDERR_INVALIDOBJECT:
|
|
|
|
return "DDERR_INVALIDOBJECT";
|
|
|
|
case DDERR_INVALIDPARAMS:
|
|
|
|
return "DDERR_INVALIDPARAMS";
|
|
|
|
case DDERR_INVALIDPIXELFORMAT:
|
|
|
|
return "DDERR_INVALIDPIXELFORMAT";
|
|
|
|
case DDERR_INVALIDRECT:
|
|
|
|
return "DDERR_INVALIDRECT";
|
|
|
|
case DDERR_LOCKEDSURFACES:
|
|
|
|
return "DDERR_LOCKEDSURFACES";
|
|
|
|
case DDERR_NO3D:
|
|
|
|
return "DDERR_NO3D";
|
|
|
|
case DDERR_NOALPHAHW:
|
|
|
|
return "DDERR_NOALPHAHW";
|
|
|
|
case DDERR_NOCLIPLIST:
|
|
|
|
return "DDERR_NOCLIPLIST";
|
|
|
|
case DDERR_NOCOLORCONVHW:
|
|
|
|
return "DDERR_NOCOLORCONVHW";
|
|
|
|
case DDERR_NOCOOPERATIVELEVELSET:
|
|
|
|
return "DDERR_NOCOOPERATIVELEVELSET";
|
|
|
|
case DDERR_NOCOLORKEY:
|
|
|
|
return "DDERR_NOCOLORKEY";
|
|
|
|
case DDERR_NOCOLORKEYHW:
|
|
|
|
return "DDERR_NOCOLORKEYHW";
|
|
|
|
case DDERR_NODIRECTDRAWSUPPORT:
|
|
|
|
return "DDERR_NODIRECTDRAWSUPPORT";
|
|
|
|
case DDERR_NOEXCLUSIVEMODE:
|
|
|
|
return "DDERR_NOEXCLUSIVEMODE";
|
|
|
|
case DDERR_NOFLIPHW:
|
|
|
|
return "DDERR_NOFLIPHW";
|
|
|
|
case DDERR_NOGDI:
|
|
|
|
return "DDERR_NOGDI";
|
|
|
|
case DDERR_NOMIRRORHW:
|
|
|
|
return "DDERR_NOMIRRORHW";
|
|
|
|
case DDERR_NOTFOUND:
|
|
|
|
return "DDERR_NOTFOUND";
|
|
|
|
case DDERR_NOOVERLAYHW:
|
|
|
|
return "DDERR_NOOVERLAYHW";
|
|
|
|
case DDERR_NORASTEROPHW:
|
|
|
|
return "DDERR_NORASTEROPHW";
|
|
|
|
case DDERR_NOROTATIONHW:
|
|
|
|
return "DDERR_NOROTATIONHW";
|
|
|
|
case DDERR_NOSTRETCHHW:
|
|
|
|
return "DDERR_NOSTRETCHHW";
|
|
|
|
case DDERR_NOT4BITCOLOR:
|
|
|
|
return "DDERR_NOT4BITCOLOR";
|
|
|
|
case DDERR_NOT4BITCOLORINDEX:
|
|
|
|
return "DDERR_NOT4BITCOLORINDEX";
|
|
|
|
case DDERR_NOT8BITCOLOR:
|
|
|
|
return "DDERR_NOT8BITCOLOR";
|
|
|
|
case DDERR_NOTEXTUREHW:
|
|
|
|
return "DDERR_NOTEXTUREHW";
|
|
|
|
case DDERR_NOVSYNCHW:
|
|
|
|
return "DDERR_NOVSYNCHW";
|
|
|
|
case DDERR_NOZBUFFERHW:
|
|
|
|
return "DDERR_NOZBUFFERHW";
|
|
|
|
case DDERR_NOZOVERLAYHW:
|
|
|
|
return "DDERR_NOZOVERLAYHW";
|
|
|
|
case DDERR_OUTOFCAPS:
|
|
|
|
return "DDERR_OUTOFCAPS";
|
|
|
|
case DDERR_OUTOFMEMORY:
|
|
|
|
return "DDERR_OUTOFMEMORY";
|
|
|
|
case DDERR_OUTOFVIDEOMEMORY:
|
|
|
|
return "DDERR_OUTOFVIDEOMEMORY";
|
|
|
|
case DDERR_OVERLAYCANTCLIP:
|
|
|
|
return "DDERR_OVERLAYCANTCLIP";
|
|
|
|
case DDERR_OVERLAYCOLORKEYONLYONEACTIVE:
|
|
|
|
return "DDERR_OVERLAYCOLORKEYONLYONEACTIVE";
|
|
|
|
case DDERR_PALETTEBUSY:
|
|
|
|
return "DDERR_PALETTEBUSY";
|
|
|
|
case DDERR_COLORKEYNOTSET:
|
|
|
|
return "DDERR_COLORKEYNOTSET";
|
|
|
|
case DDERR_SURFACEALREADYATTACHED:
|
|
|
|
return "DDERR_SURFACEALREADYATTACHED";
|
|
|
|
case DDERR_SURFACEALREADYDEPENDENT:
|
|
|
|
return "DDERR_SURFACEALREADYDEPENDENT";
|
|
|
|
case DDERR_SURFACEBUSY:
|
|
|
|
return "DDERR_SURFACEBUSY";
|
|
|
|
case DDERR_CANTLOCKSURFACE:
|
|
|
|
return "DDERR_CANTLOCKSURFACE";
|
|
|
|
case DDERR_SURFACEISOBSCURED:
|
|
|
|
return "DDERR_SURFACEISOBSCURED";
|
|
|
|
case DDERR_SURFACELOST:
|
|
|
|
return "DDERR_SURFACELOST";
|
|
|
|
case DDERR_SURFACENOTATTACHED:
|
|
|
|
return "DDERR_SURFACENOTATTACHED";
|
|
|
|
case DDERR_TOOBIGHEIGHT:
|
|
|
|
return "DDERR_TOOBIGHEIGHT";
|
|
|
|
case DDERR_TOOBIGSIZE:
|
|
|
|
return "DDERR_TOOBIGSIZE";
|
|
|
|
case DDERR_TOOBIGWIDTH:
|
|
|
|
return "DDERR_TOOBIGWIDTH";
|
|
|
|
case DDERR_UNSUPPORTED:
|
|
|
|
return "DDERR_UNSUPPORTED";
|
|
|
|
case DDERR_UNSUPPORTEDFORMAT:
|
|
|
|
return "DDERR_UNSUPPORTEDFORMAT";
|
|
|
|
case DDERR_UNSUPPORTEDMASK:
|
|
|
|
return "DDERR_UNSUPPORTEDMASK";
|
|
|
|
case DDERR_VERTICALBLANKINPROGRESS:
|
|
|
|
return "DDERR_VERTICALBLANKINPROGRESS";
|
|
|
|
case DDERR_WASSTILLDRAWING:
|
|
|
|
return "DDERR_WASSTILLDRAWING";
|
|
|
|
case DDERR_XALIGN:
|
|
|
|
return "DDERR_XALIGN";
|
|
|
|
case DDERR_INVALIDDIRECTDRAWGUID:
|
|
|
|
return "DDERR_INVALIDDIRECTDRAWGUID";
|
|
|
|
case DDERR_DIRECTDRAWALREADYCREATED:
|
|
|
|
return "DDERR_DIRECTDRAWALREADYCREATED";
|
|
|
|
case DDERR_NODIRECTDRAWHW:
|
|
|
|
return "DDERR_NODIRECTDRAWHW";
|
|
|
|
case DDERR_PRIMARYSURFACEALREADYEXISTS:
|
|
|
|
return "DDERR_PRIMARYSURFACEALREADYEXISTS";
|
|
|
|
case DDERR_NOEMULATION:
|
|
|
|
return "DDERR_NOEMULATION";
|
|
|
|
case DDERR_REGIONTOOSMALL:
|
|
|
|
return "DDERR_REGIONTOOSMALL";
|
|
|
|
case DDERR_CLIPPERISUSINGHWND:
|
|
|
|
return "DDERR_CLIPPERISUSINGHWND";
|
|
|
|
case DDERR_NOCLIPPERATTACHED:
|
|
|
|
return "DDERR_NOCLIPPERATTACHED";
|
|
|
|
case DDERR_NOHWND:
|
|
|
|
return "DDERR_NOHWND";
|
|
|
|
case DDERR_HWNDSUBCLASSED:
|
|
|
|
return "DDERR_HWNDSUBCLASSED";
|
|
|
|
case DDERR_HWNDALREADYSET:
|
|
|
|
return "DDERR_HWNDALREADYSET";
|
|
|
|
case DDERR_NOPALETTEATTACHED:
|
|
|
|
return "DDERR_NOPALETTEATTACHED";
|
|
|
|
case DDERR_NOPALETTEHW:
|
|
|
|
return "DDERR_NOPALETTEHW";
|
|
|
|
case DDERR_BLTFASTCANTCLIP:
|
|
|
|
return "DDERR_BLTFASTCANTCLIP";
|
|
|
|
case DDERR_NOBLTHW:
|
|
|
|
return "DDERR_NOBLTHW";
|
|
|
|
case DDERR_NODDROPSHW:
|
|
|
|
return "DDERR_NODDROPSHW";
|
|
|
|
case DDERR_OVERLAYNOTVISIBLE:
|
|
|
|
return "DDERR_OVERLAYNOTVISIBLE";
|
|
|
|
case DDERR_NOOVERLAYDEST:
|
|
|
|
return "DDERR_NOOVERLAYDEST";
|
|
|
|
case DDERR_INVALIDPOSITION:
|
|
|
|
return "DDERR_INVALIDPOSITION";
|
|
|
|
case DDERR_NOTAOVERLAYSURFACE:
|
|
|
|
return "DDERR_NOTAOVERLAYSURFACE";
|
|
|
|
case DDERR_EXCLUSIVEMODEALREADYSET:
|
|
|
|
return "DDERR_EXCLUSIVEMODEALREADYSET";
|
|
|
|
case DDERR_NOTFLIPPABLE:
|
|
|
|
return "DDERR_NOTFLIPPABLE";
|
|
|
|
case DDERR_CANTDUPLICATE:
|
|
|
|
return "DDERR_CANTDUPLICATE";
|
|
|
|
case DDERR_NOTLOCKED:
|
|
|
|
return "DDERR_NOTLOCKED";
|
|
|
|
case DDERR_CANTCREATEDC:
|
|
|
|
return "DDERR_CANTCREATEDC";
|
|
|
|
case DDERR_NODC:
|
|
|
|
return "DDERR_NODC";
|
|
|
|
case DDERR_WRONGMODE:
|
|
|
|
return "DDERR_WRONGMODE";
|
|
|
|
case DDERR_IMPLICITLYCREATED:
|
|
|
|
return "DDERR_IMPLICITLYCREATED";
|
|
|
|
case DDERR_NOTPALETTIZED:
|
|
|
|
return "DDERR_NOTPALETTIZED";
|
|
|
|
case DDERR_UNSUPPORTEDMODE:
|
|
|
|
return "DDERR_UNSUPPORTEDMODE";
|
|
|
|
case DDERR_NOMIPMAPHW:
|
|
|
|
return "DDERR_NOMIPMAPHW";
|
|
|
|
case DDERR_INVALIDSURFACETYPE:
|
|
|
|
return "DDERR_INVALIDSURFACETYPE";
|
|
|
|
case DDERR_DCALREADYCREATED:
|
|
|
|
return "DDERR_DCALREADYCREATED";
|
|
|
|
case DDERR_CANTPAGELOCK:
|
|
|
|
return "DDERR_CANTPAGELOCK";
|
|
|
|
case DDERR_CANTPAGEUNLOCK:
|
|
|
|
return "DDERR_CANTPAGEUNLOCK";
|
|
|
|
case DDERR_NOTPAGELOCKED:
|
|
|
|
return "DDERR_NOTPAGELOCKED";
|
|
|
|
case DDERR_NOTINITIALIZED:
|
|
|
|
return "DDERR_NOTINITIALIZED";
|
|
|
|
}
|
|
|
|
return "Unknown Error";
|
2006-01-05 23:17:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_setup_ddraw (GstDirectDrawSink * ddrawsink)
|
2006-01-05 23:17:44 +00:00
|
|
|
{
|
|
|
|
gboolean bRet = TRUE;
|
|
|
|
HRESULT hRes;
|
|
|
|
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
/* create an instance of the ddraw object use DDCREATE_EMULATIONONLY as first
|
|
|
|
* parameter to force Directdraw to use the hardware emulation layer */
|
2007-02-27 12:02:03 +00:00
|
|
|
hRes = DirectDrawCreateEx ( /*DDCREATE_EMULATIONONLY */ 0,
|
2007-02-11 15:26:49 +00:00
|
|
|
(void **) &ddrawsink->ddraw_object, &IID_IDirectDraw7, NULL);
|
2006-07-24 21:43:06 +00:00
|
|
|
if (hRes != DD_OK || ddrawsink->ddraw_object == NULL) {
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_ELEMENT_ERROR (ddrawsink, RESOURCE, WRITE,
|
|
|
|
("Failed to create the DirectDraw object error=%s",
|
|
|
|
DDErrorString (hRes)), (NULL));
|
2006-01-05 23:17:44 +00:00
|
|
|
return FALSE;
|
2006-07-24 21:43:06 +00:00
|
|
|
}
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2007-02-11 15:26:49 +00:00
|
|
|
/* set cooperative level */
|
|
|
|
hRes = IDirectDraw7_SetCooperativeLevel (ddrawsink->ddraw_object,
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
NULL, DDSCL_NORMAL);
|
2006-07-24 21:43:06 +00:00
|
|
|
if (hRes != DD_OK) {
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_ELEMENT_ERROR (ddrawsink, RESOURCE, WRITE,
|
|
|
|
("Failed to set the set the cooperative level error=%s",
|
|
|
|
DDErrorString (hRes)), (NULL));
|
|
|
|
return FALSE;
|
2006-07-24 21:43:06 +00:00
|
|
|
}
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
/* setup the clipper object */
|
|
|
|
hRes = IDirectDraw7_CreateClipper (ddrawsink->ddraw_object, 0,
|
|
|
|
&ddrawsink->clipper, NULL);
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2008-05-07 15:33:52 +00:00
|
|
|
if (hRes == DD_OK && ddrawsink->video_window)
|
|
|
|
IDirectDrawClipper_SetHWnd (ddrawsink->clipper, 0, ddrawsink->video_window);
|
|
|
|
|
2007-03-11 22:23:04 +00:00
|
|
|
/* create our primary surface */
|
|
|
|
if (!gst_directdraw_sink_check_primary_surface (ddrawsink))
|
|
|
|
return FALSE;
|
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
/* directdraw objects are setup */
|
2006-01-05 23:17:44 +00:00
|
|
|
ddrawsink->setup = TRUE;
|
|
|
|
|
|
|
|
return bRet;
|
|
|
|
}
|
|
|
|
|
|
|
|
long FAR PASCAL
|
|
|
|
WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|
|
|
{
|
|
|
|
switch (message) {
|
2007-02-11 15:26:49 +00:00
|
|
|
case WM_ERASEBKGND:
|
|
|
|
return TRUE;
|
2006-01-05 23:17:44 +00:00
|
|
|
case WM_CLOSE:
|
|
|
|
DestroyWindow (hWnd);
|
2008-05-07 15:19:47 +00:00
|
|
|
case WM_DESTROY:
|
|
|
|
PostQuitMessage (0);
|
2006-01-05 23:17:44 +00:00
|
|
|
return 0;
|
|
|
|
}
|
2008-05-07 15:19:47 +00:00
|
|
|
|
2006-01-05 23:17:44 +00:00
|
|
|
return DefWindowProc (hWnd, message, wParam, lParam);
|
|
|
|
}
|
|
|
|
|
|
|
|
static gpointer
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_window_thread (GstDirectDrawSink * ddrawsink)
|
2006-01-05 23:17:44 +00:00
|
|
|
{
|
|
|
|
WNDCLASS WndClass;
|
2008-05-07 15:19:47 +00:00
|
|
|
MSG msg;
|
2006-01-05 23:17:44 +00:00
|
|
|
|
|
|
|
memset (&WndClass, 0, sizeof (WNDCLASS));
|
|
|
|
WndClass.style = CS_HREDRAW | CS_VREDRAW;
|
|
|
|
WndClass.hInstance = GetModuleHandle (NULL);
|
|
|
|
WndClass.lpszClassName = "GStreamer-DirectDraw";
|
|
|
|
WndClass.hbrBackground = (HBRUSH) GetStockObject (BLACK_BRUSH);
|
|
|
|
WndClass.cbClsExtra = 0;
|
|
|
|
WndClass.cbWndExtra = 0;
|
|
|
|
WndClass.lpfnWndProc = WndProc;
|
|
|
|
WndClass.hCursor = LoadCursor (NULL, IDC_ARROW);
|
|
|
|
RegisterClass (&WndClass);
|
|
|
|
|
|
|
|
ddrawsink->video_window = CreateWindowEx (0, "GStreamer-DirectDraw",
|
|
|
|
"GStreamer-DirectDraw sink default window",
|
|
|
|
WS_OVERLAPPEDWINDOW | WS_SIZEBOX, 0, 0, 640, 480, NULL, NULL,
|
|
|
|
WndClass.hInstance, NULL);
|
|
|
|
if (ddrawsink->video_window == NULL)
|
2008-01-07 16:41:00 +00:00
|
|
|
return NULL;
|
2006-01-05 23:17:44 +00:00
|
|
|
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
/* Set the clipper on that window */
|
|
|
|
IDirectDrawClipper_SetHWnd (ddrawsink->clipper, 0, ddrawsink->video_window);
|
|
|
|
|
2008-01-07 16:41:00 +00:00
|
|
|
/* signal application we created a window */
|
2007-02-11 15:26:49 +00:00
|
|
|
gst_x_overlay_got_xwindow_id (GST_X_OVERLAY (ddrawsink),
|
2007-02-18 18:00:51 +00:00
|
|
|
(gulong) ddrawsink->video_window);
|
2007-02-11 15:26:49 +00:00
|
|
|
|
2006-11-01 10:19:18 +00:00
|
|
|
ReleaseSemaphore (ddrawsink->window_created_signal, 1, NULL);
|
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
/* start message loop processing our default window messages */
|
2008-05-07 15:19:47 +00:00
|
|
|
while (GetMessage (&msg, NULL, 0, 0) != FALSE) {
|
|
|
|
TranslateMessage (&msg);
|
2006-01-05 23:17:44 +00:00
|
|
|
DispatchMessage (&msg);
|
|
|
|
}
|
|
|
|
|
2008-05-07 15:19:47 +00:00
|
|
|
GST_CAT_LOG_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"our window received WM_QUIT or error.");
|
|
|
|
/* The window could have changed, if it is not ours anymore we don't
|
|
|
|
* overwrite the current video window with NULL */
|
|
|
|
if (ddrawsink->our_video_window) {
|
|
|
|
GST_OBJECT_LOCK (ddrawsink);
|
|
|
|
ddrawsink->video_window = NULL;
|
|
|
|
GST_OBJECT_UNLOCK (ddrawsink);
|
|
|
|
}
|
|
|
|
|
2006-01-05 23:17:44 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_create_default_window (GstDirectDrawSink * ddrawsink)
|
2006-01-05 23:17:44 +00:00
|
|
|
{
|
2006-11-01 10:19:18 +00:00
|
|
|
ddrawsink->window_created_signal = CreateSemaphore (NULL, 0, 1, NULL);
|
|
|
|
if (ddrawsink->window_created_signal == NULL)
|
|
|
|
return FALSE;
|
|
|
|
|
2006-01-05 23:17:44 +00:00
|
|
|
ddrawsink->window_thread = g_thread_create (
|
2007-02-18 18:00:51 +00:00
|
|
|
(GThreadFunc) gst_directdraw_sink_window_thread, ddrawsink, TRUE, NULL);
|
2006-01-05 23:17:44 +00:00
|
|
|
|
|
|
|
if (ddrawsink->window_thread == NULL)
|
2006-11-01 10:19:18 +00:00
|
|
|
goto failed;
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2006-11-01 10:19:18 +00:00
|
|
|
/* wait maximum 10 seconds for windows creating */
|
|
|
|
if (WaitForSingleObject (ddrawsink->window_created_signal,
|
|
|
|
10000) != WAIT_OBJECT_0)
|
|
|
|
goto failed;
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2006-11-01 10:19:18 +00:00
|
|
|
CloseHandle (ddrawsink->window_created_signal);
|
2006-01-05 23:17:44 +00:00
|
|
|
return TRUE;
|
2006-11-01 10:19:18 +00:00
|
|
|
|
|
|
|
failed:
|
|
|
|
CloseHandle (ddrawsink->window_created_signal);
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_ELEMENT_ERROR (ddrawsink, RESOURCE, WRITE,
|
|
|
|
("Error creating our default window"), (NULL));
|
|
|
|
|
2006-11-01 10:19:18 +00:00
|
|
|
return FALSE;
|
2006-01-05 23:17:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
2007-03-11 22:23:04 +00:00
|
|
|
gst_directdraw_sink_check_primary_surface (GstDirectDrawSink * ddrawsink)
|
2006-01-05 23:17:44 +00:00
|
|
|
{
|
2007-03-11 22:23:04 +00:00
|
|
|
HRESULT hres;
|
2007-02-11 15:26:49 +00:00
|
|
|
DDSURFACEDESC2 dd_surface_desc;
|
2007-05-24 08:35:23 +00:00
|
|
|
DDSURFACEDESC2 *sd;
|
2007-03-11 22:23:04 +00:00
|
|
|
|
|
|
|
/* if our primary surface already exist, check if it's not lost */
|
|
|
|
if (ddrawsink->primary_surface) {
|
|
|
|
if (IDirectDrawSurface7_IsLost (ddrawsink->primary_surface) == DD_OK) {
|
|
|
|
/* no problem with our primary surface */
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
/* our primary surface was lost, try to restore it */
|
|
|
|
if (IDirectDrawSurface7_Restore (ddrawsink->primary_surface) == DD_OK) {
|
|
|
|
/* restore is done */
|
|
|
|
GST_CAT_LOG_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"Our primary surface" " was restored after lost");
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
/* failed to restore our primary surface,
|
|
|
|
* probably because the display mode was changed.
|
|
|
|
* Release this surface and recreate a new one.
|
|
|
|
*/
|
|
|
|
GST_CAT_LOG_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"Our primary surface"
|
|
|
|
" was lost and display mode has changed. Destroy and recreate our surface.");
|
|
|
|
IDirectDrawSurface7_Release (ddrawsink->primary_surface);
|
|
|
|
ddrawsink->primary_surface = NULL;
|
|
|
|
|
|
|
|
/* also release offscreen surface */
|
|
|
|
IDirectDrawSurface7_Release (ddrawsink->offscreen_surface);
|
|
|
|
ddrawsink->offscreen_surface = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* create our primary surface */
|
|
|
|
memset (&dd_surface_desc, 0, sizeof (dd_surface_desc));
|
|
|
|
dd_surface_desc.dwSize = sizeof (dd_surface_desc);
|
|
|
|
dd_surface_desc.dwFlags = DDSD_CAPS;
|
|
|
|
dd_surface_desc.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
|
2007-05-24 08:35:23 +00:00
|
|
|
sd = &dd_surface_desc;
|
|
|
|
hres =
|
|
|
|
IDirectDraw7_CreateSurface (ddrawsink->ddraw_object, (DDSURFACEDESC *) sd,
|
2007-03-11 22:23:04 +00:00
|
|
|
&ddrawsink->primary_surface, NULL);
|
|
|
|
if (hres != DD_OK) {
|
|
|
|
GST_ELEMENT_ERROR (ddrawsink, RESOURCE, WRITE,
|
|
|
|
("Failed to create our primary surface error=%s", DDErrorString (hres)),
|
|
|
|
(NULL));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* attach our clipper object to the new primary surface */
|
|
|
|
if (ddrawsink->clipper) {
|
|
|
|
hres = IDirectDrawSurface7_SetClipper (ddrawsink->primary_surface,
|
|
|
|
ddrawsink->clipper);
|
|
|
|
}
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
gst_directdraw_sink_check_offscreen_surface (GstDirectDrawSink * ddrawsink)
|
|
|
|
{
|
|
|
|
DDSURFACEDESC2 dd_surface_desc;
|
2007-05-24 08:35:23 +00:00
|
|
|
DDSURFACEDESC2 *sd;
|
2007-03-11 22:23:04 +00:00
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
/* if our offscreen surface already exist, check if it's not lost */
|
|
|
|
if (ddrawsink->offscreen_surface) {
|
|
|
|
if (IDirectDrawSurface7_IsLost (ddrawsink->offscreen_surface) == DD_OK) {
|
|
|
|
/* no problem with our offscreen surface */
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
/* our offscreen surface was lost, try to restore it */
|
|
|
|
if (IDirectDrawSurface7_Restore (ddrawsink->offscreen_surface) == DD_OK) {
|
|
|
|
/* restore is done */
|
|
|
|
GST_CAT_LOG_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"Our offscreen surface" " was restored after lost");
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
/* failed to restore our offscreen surface,
|
|
|
|
* probably because the display mode was changed.
|
|
|
|
* Release this surface and recreate a new one.
|
|
|
|
*/
|
|
|
|
GST_CAT_LOG_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"Our offscreen surface"
|
|
|
|
" was lost and display mode has changed. Destroy and recreate our surface.");
|
|
|
|
IDirectDrawSurface7_Release (ddrawsink->offscreen_surface);
|
|
|
|
ddrawsink->offscreen_surface = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-01-05 23:17:44 +00:00
|
|
|
|
|
|
|
memset (&dd_surface_desc, 0, sizeof (dd_surface_desc));
|
|
|
|
dd_surface_desc.dwSize = sizeof (dd_surface_desc);
|
|
|
|
dd_surface_desc.dwFlags =
|
|
|
|
DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
|
|
|
|
dd_surface_desc.dwHeight = ddrawsink->video_height;
|
|
|
|
dd_surface_desc.dwWidth = ddrawsink->video_width;
|
|
|
|
memcpy (&(dd_surface_desc.ddpfPixelFormat), &ddrawsink->dd_pixel_format,
|
|
|
|
sizeof (DDPIXELFORMAT));
|
|
|
|
|
2007-03-11 22:23:04 +00:00
|
|
|
dd_surface_desc.ddsCaps.dwCaps = DDSCAPS_OFFSCREENPLAIN;
|
2007-05-24 08:35:23 +00:00
|
|
|
sd = &dd_surface_desc;
|
|
|
|
hres =
|
|
|
|
IDirectDraw7_CreateSurface (ddrawsink->ddraw_object, (DDSURFACEDESC *) sd,
|
2007-02-18 18:00:51 +00:00
|
|
|
&ddrawsink->offscreen_surface, NULL);
|
2007-03-11 22:23:04 +00:00
|
|
|
if (hres != DD_OK) {
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_CAT_WARNING_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"create_ddraw_surface:CreateSurface (offscreen surface for buffer_pool) failed %s",
|
2007-03-11 22:23:04 +00:00
|
|
|
DDErrorString (hres));
|
2007-02-18 18:00:51 +00:00
|
|
|
return FALSE;
|
2006-01-05 23:17:44 +00:00
|
|
|
}
|
|
|
|
|
2007-03-11 22:23:04 +00:00
|
|
|
ddrawsink->must_recreate_offscreen = FALSE;
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2007-03-11 22:23:04 +00:00
|
|
|
return TRUE;
|
2006-01-05 23:17:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_get_depth (LPDDPIXELFORMAT lpddpfPixelFormat)
|
2006-01-05 23:17:44 +00:00
|
|
|
{
|
|
|
|
gint order = 0, binary;
|
|
|
|
|
|
|
|
binary =
|
|
|
|
lpddpfPixelFormat->dwRBitMask | lpddpfPixelFormat->
|
|
|
|
dwGBitMask | lpddpfPixelFormat->dwBBitMask | lpddpfPixelFormat->
|
|
|
|
dwRGBAlphaBitMask;
|
|
|
|
while (binary != 0) {
|
|
|
|
if ((binary % 2) == 1)
|
|
|
|
order++;
|
|
|
|
binary = binary >> 1;
|
|
|
|
}
|
|
|
|
return order;
|
|
|
|
}
|
|
|
|
|
|
|
|
HRESULT WINAPI
|
2007-05-24 08:35:23 +00:00
|
|
|
EnumModesCallback2 (LPDDSURFACEDESC lpDDSurfaceDesc, LPVOID lpContext)
|
2006-01-05 23:17:44 +00:00
|
|
|
{
|
|
|
|
GstDirectDrawSink *ddrawsink = (GstDirectDrawSink *) lpContext;
|
|
|
|
GstCaps *format_caps = NULL;
|
2007-05-24 08:35:23 +00:00
|
|
|
LPDDSURFACEDESC2 sd;
|
2006-01-05 23:17:44 +00:00
|
|
|
|
|
|
|
if (!ddrawsink || !lpDDSurfaceDesc)
|
|
|
|
return DDENUMRET_CANCEL;
|
|
|
|
|
2007-05-24 08:35:23 +00:00
|
|
|
sd = (LPDDSURFACEDESC2) lpDDSurfaceDesc;
|
|
|
|
if ((sd->dwFlags & DDSD_PIXELFORMAT) != DDSD_PIXELFORMAT) {
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_CAT_INFO_OBJECT (directdrawsink_debug, ddrawsink,
|
2006-07-24 21:43:06 +00:00
|
|
|
"Display mode found with DDSD_PIXELFORMAT not set");
|
2006-01-05 23:17:44 +00:00
|
|
|
return DDENUMRET_OK;
|
|
|
|
}
|
|
|
|
|
2007-05-24 08:35:23 +00:00
|
|
|
if ((sd->ddpfPixelFormat.dwFlags & DDPF_RGB) != DDPF_RGB)
|
2006-01-05 23:17:44 +00:00
|
|
|
return DDENUMRET_OK;
|
|
|
|
|
2007-05-24 08:35:23 +00:00
|
|
|
format_caps = gst_directdraw_sink_create_caps_from_surfacedesc (sd);
|
2006-01-05 23:17:44 +00:00
|
|
|
|
|
|
|
if (format_caps) {
|
|
|
|
gst_caps_append (ddrawsink->caps, format_caps);
|
|
|
|
}
|
|
|
|
|
|
|
|
return DDENUMRET_OK;
|
|
|
|
}
|
|
|
|
|
2007-03-11 22:23:04 +00:00
|
|
|
static GstCaps *
|
|
|
|
gst_directdraw_sink_create_caps_from_surfacedesc (LPDDSURFACEDESC2 desc)
|
|
|
|
{
|
|
|
|
GstCaps *caps = NULL;
|
|
|
|
gint endianness = G_LITTLE_ENDIAN;
|
|
|
|
gint depth;
|
|
|
|
|
|
|
|
if ((desc->ddpfPixelFormat.dwFlags & DDPF_RGB) != DDPF_RGB)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
depth = gst_directdraw_sink_get_depth (&desc->ddpfPixelFormat);
|
|
|
|
|
|
|
|
if (desc->ddpfPixelFormat.dwRGBBitCount == 24 ||
|
|
|
|
desc->ddpfPixelFormat.dwRGBBitCount == 32) {
|
|
|
|
/* ffmpegcolorspace handles 24/32 bpp RGB as big-endian. */
|
|
|
|
endianness = G_BIG_ENDIAN;
|
|
|
|
desc->ddpfPixelFormat.dwRBitMask =
|
|
|
|
GUINT32_TO_BE (desc->ddpfPixelFormat.dwRBitMask);
|
|
|
|
desc->ddpfPixelFormat.dwGBitMask =
|
|
|
|
GUINT32_TO_BE (desc->ddpfPixelFormat.dwGBitMask);
|
|
|
|
desc->ddpfPixelFormat.dwBBitMask =
|
|
|
|
GUINT32_TO_BE (desc->ddpfPixelFormat.dwBBitMask);
|
|
|
|
if (desc->ddpfPixelFormat.dwRGBBitCount == 24) {
|
|
|
|
desc->ddpfPixelFormat.dwRBitMask >>= 8;
|
|
|
|
desc->ddpfPixelFormat.dwGBitMask >>= 8;
|
|
|
|
desc->ddpfPixelFormat.dwBBitMask >>= 8;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
caps = gst_caps_new_simple ("video/x-raw-rgb",
|
|
|
|
"width", GST_TYPE_INT_RANGE, 1, G_MAXINT,
|
|
|
|
"height", GST_TYPE_INT_RANGE, 1, G_MAXINT,
|
|
|
|
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1,
|
|
|
|
"bpp", G_TYPE_INT, desc->ddpfPixelFormat.dwRGBBitCount,
|
|
|
|
"depth", G_TYPE_INT, depth,
|
|
|
|
"endianness", G_TYPE_INT, endianness,
|
|
|
|
"red_mask", G_TYPE_INT, desc->ddpfPixelFormat.dwRBitMask,
|
|
|
|
"green_mask", G_TYPE_INT, desc->ddpfPixelFormat.dwGBitMask,
|
|
|
|
"blue_mask", G_TYPE_INT, desc->ddpfPixelFormat.dwBBitMask, NULL);
|
|
|
|
|
|
|
|
return caps;
|
|
|
|
}
|
|
|
|
|
2006-01-05 23:17:44 +00:00
|
|
|
static GstCaps *
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_get_ddrawcaps (GstDirectDrawSink * ddrawsink)
|
2006-01-05 23:17:44 +00:00
|
|
|
{
|
|
|
|
HRESULT hRes = S_OK;
|
2007-02-11 15:26:49 +00:00
|
|
|
DDCAPS ddcaps_hardware;
|
|
|
|
DDCAPS ddcaps_emulation;
|
2006-01-05 23:17:44 +00:00
|
|
|
GstCaps *format_caps = NULL;
|
|
|
|
|
|
|
|
ddrawsink->caps = gst_caps_new_empty ();
|
|
|
|
if (!ddrawsink->caps)
|
|
|
|
return FALSE;
|
|
|
|
|
2007-02-11 15:26:49 +00:00
|
|
|
/* get hardware caps */
|
|
|
|
ddcaps_hardware.dwSize = sizeof (DDCAPS);
|
|
|
|
ddcaps_emulation.dwSize = sizeof (DDCAPS);
|
|
|
|
IDirectDraw7_GetCaps (ddrawsink->ddraw_object, &ddcaps_hardware,
|
|
|
|
&ddcaps_emulation);
|
|
|
|
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
/* we don't test for DDCAPS_BLTSTRETCH on the hardware as the directdraw
|
|
|
|
* emulation layer can do it */
|
2007-02-11 15:26:49 +00:00
|
|
|
if (!(ddcaps_hardware.dwCaps & DDCAPS_BLTFOURCC)) {
|
|
|
|
DDSURFACEDESC2 surface_desc;
|
2007-05-24 08:35:23 +00:00
|
|
|
DDSURFACEDESC2 *sd;
|
2007-02-11 15:26:49 +00:00
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_CAT_INFO_OBJECT (directdrawsink_debug, ddrawsink,
|
2007-02-11 15:26:49 +00:00
|
|
|
"hardware doesn't support blit from one colorspace to another one. "
|
|
|
|
"so we will create a caps with only the current display mode");
|
|
|
|
|
2007-03-11 22:23:04 +00:00
|
|
|
/* save blit caps */
|
|
|
|
ddrawsink->can_blit_between_colorspace = FALSE;
|
|
|
|
|
2007-05-24 08:35:23 +00:00
|
|
|
surface_desc.dwSize = sizeof (surface_desc);
|
|
|
|
sd = &surface_desc;
|
|
|
|
hRes =
|
|
|
|
IDirectDraw7_GetDisplayMode (ddrawsink->ddraw_object,
|
|
|
|
(DDSURFACEDESC *) sd);
|
2007-02-11 15:26:49 +00:00
|
|
|
if (hRes != DD_OK) {
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_ELEMENT_ERROR (ddrawsink, CORE, NEGOTIATION,
|
|
|
|
("Error getting the current display mode error=%s",
|
|
|
|
DDErrorString (hRes)), (NULL));
|
2007-02-11 15:26:49 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-03-11 22:23:04 +00:00
|
|
|
format_caps =
|
|
|
|
gst_directdraw_sink_create_caps_from_surfacedesc (&surface_desc);
|
2007-02-11 15:26:49 +00:00
|
|
|
if (format_caps) {
|
|
|
|
gst_caps_append (ddrawsink->caps, format_caps);
|
|
|
|
}
|
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_CAT_INFO_OBJECT (directdrawsink_debug, ddrawsink, "returning caps %s",
|
2007-02-11 15:26:49 +00:00
|
|
|
gst_caps_to_string (ddrawsink->caps));
|
|
|
|
return ddrawsink->caps;
|
|
|
|
}
|
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_CAT_INFO_OBJECT (directdrawsink_debug, ddrawsink,
|
2007-02-11 15:26:49 +00:00
|
|
|
"the hardware can blit from one colorspace to another, "
|
|
|
|
"then enumerate the colorspace supported by the hardware");
|
|
|
|
|
2007-03-11 22:23:04 +00:00
|
|
|
/* save blit caps */
|
|
|
|
ddrawsink->can_blit_between_colorspace = TRUE;
|
|
|
|
|
2007-02-11 15:26:49 +00:00
|
|
|
/* enumerate display modes exposed by directdraw object
|
2007-02-18 18:00:51 +00:00
|
|
|
to know supported RGB modes */
|
2006-01-05 23:17:44 +00:00
|
|
|
hRes =
|
2007-02-11 15:26:49 +00:00
|
|
|
IDirectDraw7_EnumDisplayModes (ddrawsink->ddraw_object,
|
|
|
|
DDEDM_REFRESHRATES, NULL, ddrawsink, EnumModesCallback2);
|
2006-01-05 23:17:44 +00:00
|
|
|
if (hRes != DD_OK) {
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_ELEMENT_ERROR (ddrawsink, CORE, NEGOTIATION,
|
|
|
|
("Error enumerating display modes error=%s", DDErrorString (hRes)),
|
|
|
|
(NULL));
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2007-02-18 18:00:51 +00:00
|
|
|
return NULL;
|
2006-01-05 23:17:44 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (gst_caps_is_empty (ddrawsink->caps)) {
|
|
|
|
gst_caps_unref (ddrawsink->caps);
|
2007-02-18 18:00:51 +00:00
|
|
|
ddrawsink->caps = NULL;
|
|
|
|
GST_ELEMENT_ERROR (ddrawsink, CORE, NEGOTIATION,
|
|
|
|
("No supported caps found."), (NULL));
|
2006-01-05 23:17:44 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
2007-03-11 22:23:04 +00:00
|
|
|
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
/*GST_CAT_INFO_OBJECT (directdrawsink_debug, ddrawsink, "returning caps %s",
|
|
|
|
* gst_caps_to_string (ddrawsink->caps)); */
|
2006-01-05 23:17:44 +00:00
|
|
|
|
|
|
|
return ddrawsink->caps;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Creates miniobject and our internal surface */
|
|
|
|
static GstDDrawSurface *
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_surface_create (GstDirectDrawSink * ddrawsink,
|
2006-01-05 23:17:44 +00:00
|
|
|
GstCaps * caps, size_t size)
|
|
|
|
{
|
|
|
|
GstDDrawSurface *surface = NULL;
|
|
|
|
GstStructure *structure = NULL;
|
2006-03-03 23:45:23 +00:00
|
|
|
gint pitch;
|
2007-05-24 08:35:23 +00:00
|
|
|
|
|
|
|
#if 0
|
2006-01-05 23:17:44 +00:00
|
|
|
HRESULT hRes;
|
2007-05-24 08:35:23 +00:00
|
|
|
#endif
|
2007-02-11 15:26:49 +00:00
|
|
|
DDSURFACEDESC2 surf_desc, surf_lock_desc;
|
2006-01-05 23:17:44 +00:00
|
|
|
|
|
|
|
g_return_val_if_fail (GST_IS_DIRECTDRAW_SINK (ddrawsink), NULL);
|
|
|
|
|
|
|
|
/*init structures */
|
|
|
|
memset (&surf_desc, 0, sizeof (surf_desc));
|
|
|
|
memset (&surf_lock_desc, 0, sizeof (surf_desc));
|
|
|
|
surf_desc.dwSize = sizeof (surf_desc);
|
|
|
|
surf_lock_desc.dwSize = sizeof (surf_lock_desc);
|
|
|
|
|
|
|
|
/*create miniobject and initialize it */
|
|
|
|
surface = (GstDDrawSurface *) gst_mini_object_new (GST_TYPE_DDRAWSURFACE);
|
|
|
|
surface->locked = FALSE;
|
|
|
|
|
|
|
|
structure = gst_caps_get_structure (caps, 0);
|
|
|
|
if (!gst_structure_get_int (structure, "width", &surface->width) ||
|
|
|
|
!gst_structure_get_int (structure, "height", &surface->height)) {
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_CAT_WARNING_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"failed getting geometry from caps %" GST_PTR_FORMAT, caps);
|
2006-01-05 23:17:44 +00:00
|
|
|
}
|
|
|
|
|
2006-03-03 23:45:23 +00:00
|
|
|
pitch = GST_ROUND_UP_8 (size / surface->height);
|
2007-02-18 18:00:51 +00:00
|
|
|
if (!gst_ddrawvideosink_get_format_from_caps (ddrawsink, caps,
|
2006-01-05 23:17:44 +00:00
|
|
|
&surface->dd_pixel_format)) {
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_CAT_WARNING_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"failed getting pixel format from caps %" GST_PTR_FORMAT, caps);
|
2006-01-05 23:17:44 +00:00
|
|
|
}
|
|
|
|
|
sys/directdraw/gstdirectdrawsink.c: Make sure we create our internal window only when we need it. That will give a ch...
Original commit message from CVS:
2008-01-05 Julien Moutte <julien@fluendo.com>
* sys/directdraw/gstdirectdrawsink.c:
(gst_directdraw_sink_set_window_id),
(gst_directdraw_sink_set_caps),
(gst_directdraw_sink_change_state),
(gst_directdraw_sink_buffer_alloc),
(gst_directdraw_sink_draw_borders),
(gst_directdraw_sink_show_frame),
(gst_directdraw_sink_setup_ddraw),
(gst_directdraw_sink_window_thread),
(gst_directdraw_sink_get_ddrawcaps),
(gst_directdraw_sink_surface_create): Make sure we create our
internal window only when we need it. That will give a chance to
the application to get the prepare-xwindow-id bus message. Draw
black borders when keeping aspect ratio. Handle the case where
our
rendering window disappears (closed or errors) like other sinks
do. Various 80 columns fixes, improve state change order. That
element could need some more love.
2008-01-05 21:20:08 +00:00
|
|
|
/* disable return of directdraw surface to buffer alloc because actually I
|
|
|
|
* have no solution to handle display mode changes. The problem is that when
|
|
|
|
* the display mode is changed surface's memory is freed then the upstream
|
|
|
|
* filter would crash trying to write to this memory. Directdraw has a system
|
|
|
|
* lock (DDLOCK_NOSYSLOCK to disable it) to prevent display mode changes
|
|
|
|
* when a surface memory is locked but we need to disable this lock to return
|
|
|
|
* multiple buffers (surfaces) and do not lock directdraw API calls.
|
2007-03-11 22:23:04 +00:00
|
|
|
*/
|
2007-05-20 14:59:46 +00:00
|
|
|
#if 0
|
2007-03-11 22:23:04 +00:00
|
|
|
/* if (ddrawsink->ddraw_object) {*/
|
2007-05-20 14:59:46 +00:00
|
|
|
/* Creating an internal surface which will be used as GstBuffer, we used
|
|
|
|
the detected pixel format and video dimensions */
|
|
|
|
|
|
|
|
surf_desc.ddsCaps.dwCaps =
|
|
|
|
DDSCAPS_OFFSCREENPLAIN /* | DDSCAPS_SYSTEMMEMORY */ ;
|
|
|
|
surf_desc.dwFlags =
|
|
|
|
DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT | DDSD_PITCH;
|
|
|
|
surf_desc.dwHeight = surface->height;
|
|
|
|
surf_desc.dwWidth = surface->width;
|
|
|
|
memcpy (&(surf_desc.ddpfPixelFormat), &surface->dd_pixel_format,
|
|
|
|
sizeof (DDPIXELFORMAT));
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2007-05-20 14:59:46 +00:00
|
|
|
hRes = IDirectDraw7_CreateSurface (ddrawsink->ddraw_object, &surf_desc,
|
|
|
|
&surface->surface, NULL);
|
|
|
|
if (hRes != DD_OK) {
|
|
|
|
goto surface_pitch_bad;
|
|
|
|
}
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2007-05-20 14:59:46 +00:00
|
|
|
/* Locking the surface to acquire the memory pointer.
|
|
|
|
Use DDLOCK_NOSYSLOCK to disable syslock which can cause a deadlock
|
|
|
|
if directdraw api is used while a buffer is lock */
|
|
|
|
lock:
|
|
|
|
hRes = IDirectDrawSurface7_Lock (surface->surface, NULL, &surf_lock_desc,
|
|
|
|
DDLOCK_WAIT | DDLOCK_NOSYSLOCK, NULL);
|
|
|
|
if (hRes == DDERR_SURFACELOST) {
|
|
|
|
IDirectDrawSurface7_Restore (surface->surface);
|
|
|
|
goto lock;
|
|
|
|
}
|
|
|
|
surface->locked = TRUE;
|
2006-03-03 23:45:23 +00:00
|
|
|
|
2007-05-20 14:59:46 +00:00
|
|
|
if (surf_lock_desc.lPitch != pitch) {
|
2007-02-18 18:00:51 +00:00
|
|
|
GST_CAT_INFO_OBJECT (directdrawsink_debug, ddrawsink,
|
2007-05-20 14:59:46 +00:00
|
|
|
"DDraw stride/pitch %ld isn't as expected value %d, let's continue allocating a system memory buffer.",
|
|
|
|
surf_lock_desc.lPitch, pitch);
|
2006-01-05 23:17:44 +00:00
|
|
|
|
2007-05-20 14:59:46 +00:00
|
|
|
/*Unlock the surface as we will change it to use system memory with a GStreamer compatible pitch */
|
|
|
|
hRes = IDirectDrawSurface_Unlock (surface->surface, NULL);
|
|
|
|
goto surface_pitch_bad;
|
2006-01-05 23:17:44 +00:00
|
|
|
}
|
2007-05-20 14:59:46 +00:00
|
|
|
GST_BUFFER_DATA (surface) = surf_lock_desc.lpSurface;
|
|
|
|
GST_BUFFER_SIZE (surface) = surf_lock_desc.lPitch * surface->height;
|
|
|
|
GST_CAT_INFO_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"allocating a surface of %d bytes (stride=%ld)\n", size,
|
|
|
|
surf_lock_desc.lPitch);
|
|
|
|
|
|
|
|
surface_pitch_bad:
|
2007-05-24 08:35:23 +00:00
|
|
|
#else
|
2007-05-20 14:59:46 +00:00
|
|
|
GST_BUFFER (surface)->malloc_data = g_malloc (size);
|
|
|
|
GST_BUFFER_DATA (surface) = GST_BUFFER (surface)->malloc_data;
|
|
|
|
GST_BUFFER_SIZE (surface) = size;
|
|
|
|
surface->surface = NULL;
|
|
|
|
GST_CAT_INFO_OBJECT (directdrawsink_debug, ddrawsink,
|
|
|
|
"allocating a system memory buffer of %d bytes", size);
|
|
|
|
|
|
|
|
#endif
|
2006-01-05 23:17:44 +00:00
|
|
|
|
|
|
|
/* Keep a ref to our sink */
|
|
|
|
surface->ddrawsink = gst_object_ref (ddrawsink);
|
|
|
|
|
|
|
|
return surface;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* We are called from the finalize method of miniobject, the object will be
|
|
|
|
* destroyed so we just have to clean our internal stuff */
|
|
|
|
static void
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_surface_destroy (GstDirectDrawSink * ddrawsink,
|
2006-01-05 23:17:44 +00:00
|
|
|
GstDDrawSurface * surface)
|
|
|
|
{
|
|
|
|
g_return_if_fail (GST_IS_DIRECTDRAW_SINK (ddrawsink));
|
|
|
|
|
|
|
|
/* Release our internal surface */
|
|
|
|
if (surface->surface) {
|
|
|
|
if (surface->locked) {
|
2007-02-11 15:26:49 +00:00
|
|
|
IDirectDrawSurface7_Unlock (surface->surface, NULL);
|
2006-01-05 23:17:44 +00:00
|
|
|
surface->locked = FALSE;
|
|
|
|
}
|
2007-02-11 15:26:49 +00:00
|
|
|
IDirectDrawSurface7_Release (surface->surface);
|
2006-01-05 23:17:44 +00:00
|
|
|
surface->surface = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (GST_BUFFER (surface)->malloc_data) {
|
|
|
|
g_free (GST_BUFFER (surface)->malloc_data);
|
|
|
|
GST_BUFFER (surface)->malloc_data = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!surface->ddrawsink) {
|
|
|
|
goto no_sink;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Release the ref to our sink */
|
|
|
|
surface->ddrawsink = NULL;
|
|
|
|
gst_object_unref (ddrawsink);
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
no_sink:
|
|
|
|
GST_WARNING ("no sink found in surface");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2007-03-11 22:23:04 +00:00
|
|
|
static gboolean
|
|
|
|
gst_directdraw_sink_surface_check (GstDirectDrawSink * ddrawsink,
|
|
|
|
GstDDrawSurface * surface)
|
|
|
|
{
|
|
|
|
if (!surface->surface)
|
|
|
|
return TRUE; /* system memory buffer */
|
|
|
|
|
|
|
|
if (IDirectDrawSurface7_IsLost (surface->surface) == DD_OK) {
|
|
|
|
/* no problem with this surface */
|
|
|
|
return TRUE;
|
|
|
|
} else {
|
|
|
|
/* this surface was lost, try to restore it */
|
|
|
|
if (IDirectDrawSurface7_Restore (ddrawsink->offscreen_surface) == DD_OK) {
|
|
|
|
/* restore is done */
|
|
|
|
GST_CAT_LOG_OBJECT (directdrawsink_debug, ddrawsink, "A surface from our"
|
|
|
|
" bufferpool was restored after lost");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2006-01-05 23:17:44 +00:00
|
|
|
static void
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_bufferpool_clear (GstDirectDrawSink * ddrawsink)
|
2006-01-05 23:17:44 +00:00
|
|
|
{
|
|
|
|
g_mutex_lock (ddrawsink->pool_lock);
|
|
|
|
while (ddrawsink->buffer_pool) {
|
|
|
|
GstDDrawSurface *surface = ddrawsink->buffer_pool->data;
|
|
|
|
|
|
|
|
ddrawsink->buffer_pool = g_slist_delete_link (ddrawsink->buffer_pool,
|
|
|
|
ddrawsink->buffer_pool);
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_surface_destroy (ddrawsink, surface);
|
2006-01-05 23:17:44 +00:00
|
|
|
}
|
|
|
|
g_mutex_unlock (ddrawsink->pool_lock);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_cleanup (GstDirectDrawSink * ddrawsink)
|
2006-01-05 23:17:44 +00:00
|
|
|
{
|
|
|
|
/* Post quit message and wait for our event window thread */
|
2007-02-11 15:26:49 +00:00
|
|
|
if (ddrawsink->video_window && ddrawsink->our_video_window)
|
2006-01-05 23:17:44 +00:00
|
|
|
PostMessage (ddrawsink->video_window, WM_QUIT, 0, 0);
|
2007-02-11 15:26:49 +00:00
|
|
|
|
2006-01-05 23:17:44 +00:00
|
|
|
if (ddrawsink->window_thread) {
|
|
|
|
g_thread_join (ddrawsink->window_thread);
|
|
|
|
ddrawsink->window_thread = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ddrawsink->buffer_pool) {
|
2007-02-18 18:00:51 +00:00
|
|
|
gst_directdraw_sink_bufferpool_clear (ddrawsink);
|
2006-01-05 23:17:44 +00:00
|
|
|
ddrawsink->buffer_pool = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ddrawsink->offscreen_surface) {
|
2007-02-11 15:26:49 +00:00
|
|
|
IDirectDrawSurface7_Release (ddrawsink->offscreen_surface);
|
2006-01-05 23:17:44 +00:00
|
|
|
ddrawsink->offscreen_surface = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ddrawsink->clipper) {
|
|
|
|
IDirectDrawClipper_Release (ddrawsink->clipper);
|
|
|
|
ddrawsink->clipper = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ddrawsink->primary_surface) {
|
2007-02-11 15:26:49 +00:00
|
|
|
IDirectDrawSurface7_Release (ddrawsink->primary_surface);
|
2006-01-05 23:17:44 +00:00
|
|
|
ddrawsink->primary_surface = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ddrawsink->ddraw_object) {
|
2007-02-11 15:26:49 +00:00
|
|
|
IDirectDraw7_Release (ddrawsink->ddraw_object);
|
2006-01-05 23:17:44 +00:00
|
|
|
ddrawsink->ddraw_object = NULL;
|
|
|
|
}
|
|
|
|
|
2007-02-11 15:26:49 +00:00
|
|
|
if (ddrawsink->last_buffer) {
|
|
|
|
gst_buffer_unref (ddrawsink->last_buffer);
|
|
|
|
ddrawsink->last_buffer = NULL;
|
|
|
|
}
|
|
|
|
|
2006-01-05 23:17:44 +00:00
|
|
|
ddrawsink->setup = FALSE;
|
|
|
|
}
|