| /* GStreamer SDL plugin |
| * Copyright (C) 2001-2002 Ronald Bultje <rbultje@ronald.bitfreak.net> |
| * |
| * 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. |
| */ |
| |
| /* let's not forget to mention that all this was based on aasink ;-) */ |
| |
| #ifdef HAVE_CONFIG_H |
| #include "config.h" |
| #endif |
| |
| #include <signal.h> |
| #include <string.h> |
| #include <sys/time.h> |
| #include <stdlib.h> |
| |
| #include <gst/xoverlay/xoverlay.h> |
| |
| #include "sdlvideosink.h" |
| |
| /* elementfactory information */ |
| static GstElementDetails gst_sdlvideosink_details = { |
| "Video sink", |
| "Sink/Video", |
| "An SDL-based videosink", |
| "Ronald Bultje <rbultje@ronald.bitfreak.net>", |
| }; |
| |
| static void gst_sdlvideosink_base_init (gpointer g_class); |
| static void gst_sdlvideosink_class_init (GstSDLVideoSinkClass *klass); |
| static void gst_sdlvideosink_init (GstSDLVideoSink *sdl); |
| |
| static void gst_sdlvideosink_interface_init (GstImplementsInterfaceClass *klass); |
| static gboolean gst_sdlvideosink_supported (GstImplementsInterface *iface, |
| GType type); |
| |
| static void gst_sdlvideosink_xoverlay_init (GstXOverlayClass *klass); |
| static void gst_sdlvideosink_xoverlay_set_xwindow_id |
| (GstXOverlay *overlay, |
| XID parent); |
| |
| static gboolean gst_sdlvideosink_lock (GstSDLVideoSink *sdl); |
| static void gst_sdlvideosink_unlock (GstSDLVideoSink *sdl); |
| |
| static gboolean gst_sdlvideosink_initsdl (GstSDLVideoSink *sdl); |
| static void gst_sdlvideosink_deinitsdl (GstSDLVideoSink *sdl); |
| |
| static gboolean gst_sdlvideosink_create (GstSDLVideoSink *sdl); |
| static void gst_sdlvideosink_destroy (GstSDLVideoSink *sdl); |
| |
| static GstPadLinkReturn |
| gst_sdlvideosink_sinkconnect (GstPad *pad, |
| const GstCaps *caps); |
| static void gst_sdlvideosink_chain (GstPad *pad, |
| GstData *data); |
| |
| static void gst_sdlvideosink_set_property (GObject *object, |
| guint prop_id, |
| const GValue *value, |
| GParamSpec *pspec); |
| static void gst_sdlvideosink_get_property (GObject *object, |
| guint prop_id, |
| GValue *value, |
| GParamSpec *pspec); |
| static GstElementStateReturn |
| gst_sdlvideosink_change_state (GstElement *element); |
| |
| |
| static GstPadTemplate *sink_template; |
| |
| static GstElementClass *parent_class = NULL; |
| |
| GType |
| gst_sdlvideosink_get_type (void) |
| { |
| static GType sdlvideosink_type = 0; |
| |
| if (!sdlvideosink_type) { |
| static const GTypeInfo sdlvideosink_info = { |
| sizeof (GstSDLVideoSinkClass), |
| gst_sdlvideosink_base_init, |
| NULL, |
| (GClassInitFunc) gst_sdlvideosink_class_init, |
| NULL, |
| NULL, |
| sizeof (GstSDLVideoSink), |
| 0, |
| (GInstanceInitFunc) gst_sdlvideosink_init, |
| }; |
| static const GInterfaceInfo iface_info = { |
| (GInterfaceInitFunc) gst_sdlvideosink_interface_init, |
| NULL, |
| NULL, |
| }; |
| static const GInterfaceInfo xoverlay_info = { |
| (GInterfaceInitFunc) gst_sdlvideosink_xoverlay_init, |
| NULL, |
| NULL, |
| }; |
| |
| sdlvideosink_type = g_type_register_static(GST_TYPE_VIDEOSINK, |
| "GstSDLVideoSink", |
| &sdlvideosink_info, 0); |
| g_type_add_interface_static(sdlvideosink_type, GST_TYPE_IMPLEMENTS_INTERFACE, |
| &iface_info); |
| g_type_add_interface_static(sdlvideosink_type, GST_TYPE_X_OVERLAY, |
| &xoverlay_info); |
| } |
| |
| return sdlvideosink_type; |
| } |
| |
| static void |
| gst_sdlvideosink_base_init (gpointer g_class) |
| { |
| GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); |
| GstCaps *capslist; |
| gint i; |
| gulong format[6] = { GST_MAKE_FOURCC('I','4','2','0'), |
| GST_MAKE_FOURCC('Y','V','1','2'), |
| GST_MAKE_FOURCC('Y','U','Y','2'), |
| GST_MAKE_FOURCC('Y','V','Y','U'), |
| GST_MAKE_FOURCC('U','Y','V','Y') |
| }; |
| |
| /* make a list of all available caps */ |
| capslist = gst_caps_new_empty(); |
| for (i = 0; i < 5; i++) { |
| gst_caps_append_structure (capslist, |
| gst_structure_new ("video/x-raw-yuv", |
| "format", GST_TYPE_FOURCC, format[i], |
| "width", GST_TYPE_INT_RANGE, 1, G_MAXINT, |
| "height", GST_TYPE_INT_RANGE, 1, G_MAXINT, |
| "framerate", GST_TYPE_DOUBLE_RANGE, 0.0, G_MAXDOUBLE, |
| NULL)); |
| } |
| |
| sink_template = gst_pad_template_new ("sink", |
| GST_PAD_SINK, |
| GST_PAD_ALWAYS, |
| capslist); |
| |
| gst_element_class_add_pad_template (element_class, sink_template); |
| gst_element_class_set_details (element_class, &gst_sdlvideosink_details); |
| } |
| |
| static void |
| gst_sdlvideosink_dispose (GObject *obj) |
| { |
| g_mutex_free (GST_SDLVIDEOSINK (obj)->lock); |
| |
| if (((GObjectClass *) parent_class)->dispose) |
| ((GObjectClass *) parent_class)->dispose (obj); |
| } |
| |
| static void |
| gst_sdlvideosink_class_init (GstSDLVideoSinkClass *klass) |
| { |
| GObjectClass *gobject_class; |
| GstElementClass *gstelement_class; |
| GstVideoSinkClass *gstvs_class; |
| |
| gobject_class = (GObjectClass*) klass; |
| gstelement_class = (GstElementClass*) klass; |
| gstvs_class = (GstVideoSinkClass*) klass; |
| |
| parent_class = g_type_class_ref (GST_TYPE_ELEMENT); |
| |
| gobject_class->set_property = gst_sdlvideosink_set_property; |
| gobject_class->get_property = gst_sdlvideosink_get_property; |
| gobject_class->dispose = gst_sdlvideosink_dispose; |
| |
| gstelement_class->change_state = gst_sdlvideosink_change_state; |
| |
| /*gstvs_class->set_video_out = gst_sdlvideosink_set_video_out; |
| gstvs_class->push_ui_event = gst_sdlvideosink_push_ui_event; |
| gstvs_class->set_geometry = gst_sdlvideosink_set_geometry;*/ |
| } |
| |
| #if 0 |
| /* FIXME */ |
| static GstBuffer * |
| gst_sdlvideosink_buffer_new (GstBufferPool *pool, |
| gint64 location, |
| guint size, |
| gpointer user_data) |
| { |
| GstSDLVideoSink *sdlvideosink = GST_SDLVIDEOSINK (user_data); |
| GstBuffer *buffer; |
| |
| if (!sdlvideosink->overlay) |
| return NULL; |
| |
| if (!gst_sdlvideosink_lock(sdlvideosink)) { |
| return NULL; |
| } |
| |
| /* this protects the buffer from being written over multiple times */ |
| g_mutex_lock (sdlvideosink->lock); |
| |
| buffer = gst_buffer_new (); |
| GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_DONTFREE); |
| GST_BUFFER_DATA (buffer) = sdlvideosink->overlay->pixels[0]; |
| if (sdlvideosink->format == SDL_YV12_OVERLAY || |
| sdlvideosink->format == SDL_IYUV_OVERLAY) { |
| GST_BUFFER_SIZE (buffer) = |
| sdlvideosink->width * sdlvideosink->height * 3/2; |
| } else { |
| GST_BUFFER_SIZE (buffer) = |
| sdlvideosink->width * sdlvideosink->height * 2; |
| } |
| GST_BUFFER_MAXSIZE (buffer) = GST_BUFFER_SIZE (buffer); |
| |
| return buffer; |
| } |
| |
| static void |
| gst_sdlvideosink_buffer_free (GstBufferPool *pool, |
| GstBuffer *buffer, |
| gpointer user_data) |
| { |
| GstSDLVideoSink *sdlvideosink = GST_SDLVIDEOSINK (user_data); |
| |
| g_mutex_unlock (sdlvideosink->lock); |
| gst_sdlvideosink_unlock(sdlvideosink); |
| |
| gst_buffer_default_free (buffer); |
| } |
| |
| |
| static GstBufferPool * |
| gst_sdlvideosink_get_bufferpool (GstPad *pad) |
| { |
| GstSDLVideoSink *sdlvideosink = GST_SDLVIDEOSINK (gst_pad_get_parent (pad)); |
| |
| if (sdlvideosink->overlay) |
| return sdlvideosink->bufferpool; |
| |
| return NULL; |
| } |
| #endif |
| |
| static void |
| gst_sdlvideosink_init (GstSDLVideoSink *sdlvideosink) |
| { |
| GST_VIDEOSINK_PAD (sdlvideosink) = gst_pad_new_from_template (sink_template, |
| "sink"); |
| gst_element_add_pad (GST_ELEMENT (sdlvideosink), |
| GST_VIDEOSINK_PAD (sdlvideosink)); |
| |
| gst_pad_set_chain_function (GST_VIDEOSINK_PAD (sdlvideosink), |
| gst_sdlvideosink_chain); |
| gst_pad_set_link_function (GST_VIDEOSINK_PAD (sdlvideosink), |
| gst_sdlvideosink_sinkconnect); |
| |
| sdlvideosink->width = -1; |
| sdlvideosink->height = -1; |
| |
| sdlvideosink->overlay = NULL; |
| sdlvideosink->screen = NULL; |
| |
| sdlvideosink->xwindow_id = 0; |
| |
| //sdlvideosink->capslist = capslist; |
| |
| sdlvideosink->init = FALSE; |
| |
| sdlvideosink->lock = g_mutex_new (); |
| |
| #if 0 |
| sdlvideosink->bufferpool = gst_buffer_pool_new ( |
| NULL, /* free */ |
| NULL, /* copy */ |
| (GstBufferPoolBufferNewFunction) gst_sdlvideosink_buffer_new, |
| NULL, /* buffer copy, the default is fine */ |
| (GstBufferPoolBufferFreeFunction) gst_sdlvideosink_buffer_free, |
| sdlvideosink); |
| #endif |
| |
| GST_FLAG_SET(sdlvideosink, GST_ELEMENT_THREAD_SUGGESTED); |
| GST_FLAG_SET(sdlvideosink, GST_ELEMENT_EVENT_AWARE); |
| } |
| |
| static void |
| gst_sdlvideosink_interface_init (GstImplementsInterfaceClass *klass) |
| { |
| klass->supported = gst_sdlvideosink_supported; |
| } |
| |
| static gboolean |
| gst_sdlvideosink_supported (GstImplementsInterface *interface, |
| GType iface_type) |
| { |
| g_assert (iface_type == GST_TYPE_X_OVERLAY); |
| |
| /* FIXME: check SDL for whether it was compiled against X, FB, etc. */ |
| return (GST_STATE (interface) != GST_STATE_NULL); |
| } |
| |
| static void |
| gst_sdlvideosink_xoverlay_init (GstXOverlayClass *klass) |
| { |
| klass->set_xwindow_id = gst_sdlvideosink_xoverlay_set_xwindow_id; |
| } |
| |
| static void |
| gst_sdlvideosink_xoverlay_set_xwindow_id (GstXOverlay *overlay, XID parent) |
| { |
| GstSDLVideoSink *sdlvideosink = GST_SDLVIDEOSINK (overlay); |
| |
| sdlvideosink->xwindow_id = parent; |
| |
| /* are we running yet? */ |
| if (sdlvideosink->init) { |
| gboolean negotiated = (sdlvideosink->overlay != NULL); |
| |
| if (negotiated) |
| gst_sdlvideosink_destroy (sdlvideosink); |
| |
| gst_sdlvideosink_initsdl (sdlvideosink); |
| |
| if (negotiated) |
| gst_sdlvideosink_create (sdlvideosink); |
| } |
| } |
| |
| |
| static guint32 |
| gst_sdlvideosink_get_sdl_from_fourcc (GstSDLVideoSink *sdlvideosink, |
| guint32 code) |
| { |
| switch (code) |
| { |
| case GST_MAKE_FOURCC('I','4','2','0'): |
| return SDL_IYUV_OVERLAY; |
| case GST_MAKE_FOURCC('Y','V','1','2'): |
| return SDL_YV12_OVERLAY; |
| case GST_MAKE_FOURCC('Y','U','Y','2'): |
| return SDL_YUY2_OVERLAY; |
| case GST_MAKE_FOURCC('U','Y','V','Y'): |
| return SDL_UYVY_OVERLAY; |
| case GST_MAKE_FOURCC('Y','V','Y','U'): |
| return SDL_YVYU_OVERLAY; |
| default: |
| return 0; |
| } |
| } |
| |
| |
| static gboolean |
| gst_sdlvideosink_lock (GstSDLVideoSink *sdlvideosink) |
| { |
| /* assure that we've got a screen */ |
| if (!sdlvideosink->screen || !sdlvideosink->overlay) { |
| gst_element_error (GST_ELEMENT (sdlvideosink), |
| "Tried to lock screen without being set-up"); |
| return FALSE; |
| } |
| |
| /* Lock SDL/yuv-overlay */ |
| if (SDL_MUSTLOCK(sdlvideosink->screen)) |
| { |
| if (SDL_LockSurface(sdlvideosink->screen) < 0) |
| { |
| gst_element_error(GST_ELEMENT(sdlvideosink), |
| "SDL: couldn\'t lock the SDL video window: %s", SDL_GetError()); |
| return FALSE; |
| } |
| } |
| if (SDL_LockYUVOverlay(sdlvideosink->overlay) < 0) |
| { |
| gst_element_error(GST_ELEMENT(sdlvideosink), |
| "SDL: couldn\'t lock the SDL YUV overlay: %s", SDL_GetError()); |
| return FALSE; |
| } |
| |
| sdlvideosink->init = TRUE; |
| |
| return TRUE; |
| } |
| |
| |
| static void |
| gst_sdlvideosink_unlock (GstSDLVideoSink *sdlvideosink) |
| { |
| /* Unlock SDL_overlay */ |
| SDL_UnlockYUVOverlay(sdlvideosink->overlay); |
| if (SDL_MUSTLOCK(sdlvideosink->screen)) |
| SDL_UnlockSurface(sdlvideosink->screen); |
| } |
| |
| static void |
| gst_sdlvideosink_deinitsdl (GstSDLVideoSink *sdlvideosink) |
| { |
| if (sdlvideosink->init) { |
| SDL_Quit (); |
| sdlvideosink->init = FALSE; |
| } |
| } |
| |
| static gboolean |
| gst_sdlvideosink_initsdl (GstSDLVideoSink *sdlvideosink) |
| { |
| gst_sdlvideosink_deinitsdl (sdlvideosink); |
| |
| if (!sdlvideosink->xwindow_id) { |
| unsetenv("SDL_WINDOWID"); |
| } else { |
| char SDL_hack[32]; |
| sprintf(SDL_hack, "%lu", sdlvideosink->xwindow_id); |
| setenv("SDL_WINDOWID", SDL_hack, 1); |
| } |
| |
| /* Initialize the SDL library */ |
| if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE) < 0 ) { |
| gst_element_error(GST_ELEMENT (sdlvideosink), |
| "Couldn't initialize SDL: %s", |
| SDL_GetError()); |
| return FALSE; |
| } |
| |
| return TRUE; |
| } |
| |
| static void |
| gst_sdlvideosink_destroy (GstSDLVideoSink *sdlvideosink) |
| { |
| if (sdlvideosink->overlay) { |
| SDL_FreeYUVOverlay(sdlvideosink->overlay); |
| sdlvideosink->overlay = NULL; |
| } |
| |
| if (sdlvideosink->screen) { |
| SDL_FreeSurface (sdlvideosink->screen); |
| sdlvideosink->screen = NULL; |
| } |
| } |
| |
| static gboolean |
| gst_sdlvideosink_create (GstSDLVideoSink *sdlvideosink) |
| { |
| if (GST_VIDEOSINK_HEIGHT (sdlvideosink) <= 0) |
| GST_VIDEOSINK_HEIGHT (sdlvideosink) = sdlvideosink->height; |
| if (GST_VIDEOSINK_WIDTH (sdlvideosink) <= 0) |
| GST_VIDEOSINK_WIDTH (sdlvideosink) = sdlvideosink->width; |
| |
| gst_sdlvideosink_destroy (sdlvideosink); |
| |
| /* create a SDL window of the size requested by the user */ |
| sdlvideosink->screen = SDL_SetVideoMode(GST_VIDEOSINK_WIDTH (sdlvideosink), |
| GST_VIDEOSINK_HEIGHT (sdlvideosink), 0, SDL_HWSURFACE | SDL_RESIZABLE); |
| if (sdlvideosink->screen == NULL) |
| { |
| gst_element_error(GST_ELEMENT(sdlvideosink), |
| "SDL: Couldn't set %dx%d: %s", GST_VIDEOSINK_WIDTH (sdlvideosink), |
| GST_VIDEOSINK_HEIGHT (sdlvideosink), SDL_GetError()); |
| return FALSE; |
| } |
| |
| /* create a new YUV overlay */ |
| sdlvideosink->overlay = SDL_CreateYUVOverlay(sdlvideosink->width, |
| sdlvideosink->height, sdlvideosink->format, sdlvideosink->screen); |
| if ( sdlvideosink->overlay == NULL ) |
| { |
| gst_element_error(GST_ELEMENT(sdlvideosink), |
| "SDL: Couldn't create SDL YUV overlay (%dx%d \'" GST_FOURCC_FORMAT "\'): %s", |
| sdlvideosink->width, sdlvideosink->height, |
| GST_FOURCC_ARGS(sdlvideosink->format), SDL_GetError()); |
| return FALSE; |
| } |
| else |
| { |
| GST_DEBUG("Using a %dx%d %dbpp SDL screen with a %dx%d \'" GST_FOURCC_FORMAT "\' YUV overlay", |
| GST_VIDEOSINK_WIDTH (sdlvideosink), GST_VIDEOSINK_HEIGHT (sdlvideosink), |
| sdlvideosink->screen->format->BitsPerPixel, |
| sdlvideosink->width, sdlvideosink->height, |
| GST_FOURCC_ARGS(sdlvideosink->format)); |
| } |
| |
| sdlvideosink->rect.x = 0; |
| sdlvideosink->rect.y = 0; |
| sdlvideosink->rect.w = GST_VIDEOSINK_WIDTH (sdlvideosink); |
| sdlvideosink->rect.h = GST_VIDEOSINK_HEIGHT (sdlvideosink); |
| |
| SDL_DisplayYUVOverlay(sdlvideosink->overlay, &(sdlvideosink->rect)); |
| |
| GST_DEBUG ("sdlvideosink: setting %08x (" GST_FOURCC_FORMAT ")", |
| sdlvideosink->format, GST_FOURCC_ARGS(sdlvideosink->format)); |
| |
| gst_video_sink_got_video_size (GST_VIDEOSINK (sdlvideosink), |
| GST_VIDEOSINK_WIDTH (sdlvideosink), |
| GST_VIDEOSINK_HEIGHT (sdlvideosink)); |
| return TRUE; |
| } |
| |
| static GstPadLinkReturn |
| gst_sdlvideosink_sinkconnect (GstPad *pad, |
| const GstCaps *vscapslist) |
| { |
| GstSDLVideoSink *sdlvideosink; |
| guint32 format; |
| GstStructure *structure; |
| |
| sdlvideosink = GST_SDLVIDEOSINK (gst_pad_get_parent (pad)); |
| |
| structure = gst_caps_get_structure (vscapslist, 0); |
| gst_structure_get_fourcc (structure, "format", &format); |
| sdlvideosink->format = |
| gst_sdlvideosink_get_sdl_from_fourcc (sdlvideosink, format); |
| gst_structure_get_int (structure, "width", &sdlvideosink->width); |
| gst_structure_get_int (structure, "height", &sdlvideosink->height); |
| |
| if (!sdlvideosink->format || !gst_sdlvideosink_create(sdlvideosink)) |
| return GST_PAD_LINK_REFUSED; |
| |
| return GST_PAD_LINK_OK; |
| } |
| |
| |
| static void |
| gst_sdlvideosink_chain (GstPad *pad, GstData *_data) |
| { |
| GstBuffer *buf = GST_BUFFER (_data); |
| GstSDLVideoSink *sdlvideosink; |
| SDL_Event sdl_event; |
| |
| g_return_if_fail (pad != NULL); |
| g_return_if_fail (GST_IS_PAD (pad)); |
| g_return_if_fail (buf != NULL); |
| |
| sdlvideosink = GST_SDLVIDEOSINK (gst_pad_get_parent (pad)); |
| |
| if (GST_IS_EVENT (buf)) { |
| GstEvent *event = GST_EVENT (buf); |
| gint64 offset; |
| |
| switch (GST_EVENT_TYPE (event)) { |
| case GST_EVENT_DISCONTINUOUS: |
| offset = GST_EVENT_DISCONT_OFFSET (event, 0).value; |
| /*gst_clock_handle_discont (sdlvideosink->clock, |
| (guint64) GST_EVENT_DISCONT_OFFSET (event, 0).value);*/ |
| break; |
| default: |
| gst_pad_event_default (pad, event); |
| return; |
| } |
| gst_event_unref (event); |
| return; |
| } |
| |
| if (GST_VIDEOSINK_CLOCK (sdlvideosink)) { |
| GstClockID id = gst_clock_new_single_shot_id ( |
| GST_VIDEOSINK_CLOCK (sdlvideosink), |
| GST_BUFFER_TIMESTAMP (buf)); |
| |
| gst_element_clock_wait (GST_ELEMENT (sdlvideosink), id, NULL); |
| gst_clock_id_free (id); |
| } |
| |
| if (GST_BUFFER_DATA (buf) != sdlvideosink->overlay->pixels[0]) { |
| if (!gst_sdlvideosink_lock(sdlvideosink)) { |
| return; |
| } |
| |
| /* buf->yuv - FIXME: bufferpool! */ |
| if (sdlvideosink->format == SDL_IYUV_OVERLAY || |
| sdlvideosink->format == SDL_YV12_OVERLAY) |
| { |
| memcpy (sdlvideosink->overlay->pixels[0], GST_BUFFER_DATA (buf), |
| sdlvideosink->width * sdlvideosink->height); |
| memcpy (sdlvideosink->overlay->pixels[1], |
| GST_BUFFER_DATA (buf) + sdlvideosink->width*sdlvideosink->height, |
| sdlvideosink->width * sdlvideosink->height / 4); |
| memcpy (sdlvideosink->overlay->pixels[2], |
| GST_BUFFER_DATA (buf) + sdlvideosink->width*sdlvideosink->height*5/4, |
| sdlvideosink->width * sdlvideosink->height / 4); |
| } else { |
| memcpy (sdlvideosink->overlay->pixels[0], GST_BUFFER_DATA (buf), |
| sdlvideosink->width * sdlvideosink->height * 2); |
| } |
| |
| gst_sdlvideosink_unlock(sdlvideosink); |
| } |
| |
| gst_buffer_unref(buf); |
| |
| /* Show, baby, show! */ |
| SDL_DisplayYUVOverlay(sdlvideosink->overlay, &(sdlvideosink->rect)); |
| |
| while (SDL_PollEvent(&sdl_event)) |
| { |
| switch(sdl_event.type) |
| { |
| case SDL_VIDEORESIZE: |
| /* create a SDL window of the size requested by the user */ |
| GST_VIDEOSINK_WIDTH (sdlvideosink) = sdl_event.resize.w; |
| GST_VIDEOSINK_HEIGHT (sdlvideosink) = sdl_event.resize.h; |
| gst_sdlvideosink_create(sdlvideosink); |
| break; |
| } |
| } |
| } |
| |
| |
| static void |
| gst_sdlvideosink_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) |
| { |
| GstSDLVideoSink *sdlvideosink; |
| |
| /* it's not null if we got it, but it might not be ours */ |
| g_return_if_fail (GST_IS_SDLVIDEOSINK (object)); |
| sdlvideosink = GST_SDLVIDEOSINK(object); |
| |
| switch (prop_id) |
| { |
| default: |
| G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
| break; |
| } |
| } |
| |
| |
| static void |
| gst_sdlvideosink_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) |
| { |
| GstSDLVideoSink *sdlvideosink; |
| |
| /* it's not null if we got it, but it might not be ours */ |
| g_return_if_fail (GST_IS_SDLVIDEOSINK (object)); |
| sdlvideosink = GST_SDLVIDEOSINK(object); |
| |
| switch (prop_id) { |
| default: |
| G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
| break; |
| } |
| } |
| |
| |
| static GstElementStateReturn |
| gst_sdlvideosink_change_state (GstElement *element) |
| { |
| GstSDLVideoSink *sdlvideosink; |
| g_return_val_if_fail (GST_IS_SDLVIDEOSINK (element), GST_STATE_FAILURE); |
| sdlvideosink = GST_SDLVIDEOSINK(element); |
| |
| switch (GST_STATE_TRANSITION (element)) |
| { |
| case GST_STATE_NULL_TO_READY: |
| if (!gst_sdlvideosink_initsdl (sdlvideosink)) |
| return GST_STATE_FAILURE; |
| GST_FLAG_SET (sdlvideosink, GST_SDLVIDEOSINK_OPEN); |
| break; |
| case GST_STATE_PAUSED_TO_READY: |
| gst_sdlvideosink_destroy (sdlvideosink); |
| break; |
| case GST_STATE_READY_TO_NULL: |
| gst_sdlvideosink_deinitsdl (sdlvideosink); |
| GST_FLAG_UNSET (sdlvideosink, GST_SDLVIDEOSINK_OPEN); |
| break; |
| default: /* do nothing */ |
| break; |
| } |
| |
| if (GST_ELEMENT_CLASS (parent_class)->change_state) |
| return GST_ELEMENT_CLASS (parent_class)->change_state (element); |
| |
| return GST_STATE_SUCCESS; |
| } |
| |
| |
| static gboolean |
| plugin_init (GstPlugin *plugin) |
| { |
| /* Loading the library containing GstVideoSink, our parent object */ |
| if (!gst_library_load ("gstvideo")) |
| return FALSE; |
| |
| if (!gst_element_register (plugin, "sdlvideosink", GST_RANK_NONE, GST_TYPE_SDLVIDEOSINK)) |
| return FALSE; |
| |
| return TRUE; |
| } |
| |
| GST_PLUGIN_DEFINE ( |
| GST_VERSION_MAJOR, |
| GST_VERSION_MINOR, |
| "sdlvideosink", |
| "SDL Video Sink", |
| plugin_init, |
| VERSION, |
| "LGPL", |
| GST_PACKAGE, |
| GST_ORIGIN) |