diff options
Diffstat (limited to 'sys/pvr2d/gstpvrvideosink.c')
-rw-r--r-- | sys/pvr2d/gstpvrvideosink.c | 1479 |
1 files changed, 0 insertions, 1479 deletions
diff --git a/sys/pvr2d/gstpvrvideosink.c b/sys/pvr2d/gstpvrvideosink.c deleted file mode 100644 index 4e32a8c06..000000000 --- a/sys/pvr2d/gstpvrvideosink.c +++ /dev/null @@ -1,1479 +0,0 @@ -/* GStreamer - * - * Copyright (C) 2011 Collabora Ltda - * Copyright (C) 2011 Texas Instruments - * @author: Luciana Fujii Pontello <luciana.fujii@collabora.co.uk> - * @author: Edward Hervey <edward@collabora.com> - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser 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., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/* Object header */ -#include "gstpvrvideosink.h" -#include "gstpvrbufferpool.h" - -#include <gst/video/gstvideosink.h> -#include <gst/video/videooverlay.h> -/* Helper functions */ -#include <gst/video/gstvideometa.h> - -/* Debugging category */ -#include <gst/gstinfo.h> - -#define LINUX -#include <dri2_ws.h> -#include <services.h> -#include <img_defs.h> -#include <servicesext.h> - -#define DEFAULT_QUEUE_SIZE 12 - -GST_DEBUG_CATEGORY_EXTERN (gst_debug_pvrvideosink); -#define GST_CAT_DEFAULT gst_debug_pvrvideosink - -#define PVR2DMEMINFO_INITIALISE(d, s) \ -{ \ - (d)->hPrivateData = (IMG_VOID *)(s); \ - (d)->hPrivateMapData = (IMG_VOID *)(s->hKernelMemInfo); \ - (d)->ui32DevAddr = (IMG_UINT32) (s)->sDevVAddr.uiAddr; \ - (d)->ui32MemSize = (s)->uAllocSize; \ - (d)->pBase = (s)->pvLinAddr;\ - (d)->ulFlags = (s)->ui32Flags;\ -} - -/* end of internal definitions */ - -static void gst_pvrvideosink_reset (GstPVRVideoSink * pvrvideosink); -static void gst_pvrvideosink_xwindow_draw_borders (GstPVRVideoSink * - pvrvideosink, GstXWindow * xwindow, GstVideoRectangle rect); -static void gst_pvrvideosink_expose (GstVideoOverlay * overlay); -static void gst_pvrvideosink_xwindow_destroy (GstPVRVideoSink * pvrvideosink, - GstXWindow * xwindow); -static void gst_pvrvideosink_dcontext_free (GstDrawContext * dcontext); - -static void gst_pvrvideosink_videooverlay_init (GstVideoOverlayInterface * - iface); - -#define gst_pvrvideosink_parent_class parent_class -G_DEFINE_TYPE_WITH_CODE (GstPVRVideoSink, gst_pvrvideosink, GST_TYPE_VIDEO_SINK, - G_IMPLEMENT_INTERFACE (GST_TYPE_VIDEO_OVERLAY, - gst_pvrvideosink_videooverlay_init)); - - -static GstStaticPadTemplate gst_pvrvideosink_sink_template_factory = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE ("NV12"))); - -enum -{ - PROP_0, - PROP_FORCE_ASPECT_RATIO, - PROP_WINDOW_WIDTH, - PROP_WINDOW_HEIGHT -}; - -/* ============================================================= */ -/* */ -/* Private Methods */ -/* */ -/* ============================================================= */ - -/* pvrvideo buffers */ - -static void -gst_pvrvideosink_xwindow_update_geometry (GstPVRVideoSink * pvrvideosink) -{ - XWindowAttributes attr; - WSEGLError glerror; - WSEGLDrawableParams source_params; - PVRSRV_CLIENT_MEM_INFO *client_mem_info; - - /* Update the window geometry */ - g_mutex_lock (pvrvideosink->dcontext->x_lock); - if (G_UNLIKELY (pvrvideosink->xwindow == NULL)) { - g_mutex_unlock (pvrvideosink->dcontext->x_lock); - return; - } - pvrvideosink->redraw_borders = TRUE; - - XGetWindowAttributes (pvrvideosink->dcontext->x_display, - pvrvideosink->xwindow->window, &attr); - - pvrvideosink->xwindow->width = attr.width; - pvrvideosink->xwindow->height = attr.height; - - if (!pvrvideosink->have_render_rect) { - pvrvideosink->render_rect.x = pvrvideosink->render_rect.y = 0; - pvrvideosink->render_rect.w = attr.width; - pvrvideosink->render_rect.h = attr.height; - } - if (pvrvideosink->dcontext != NULL) { - glerror = - pvrvideosink->dcontext->wsegl_table-> - pfnWSEGL_DeleteDrawable (pvrvideosink->dcontext->drawable_handle); - if (glerror != WSEGL_SUCCESS) { - GST_ERROR_OBJECT (pvrvideosink, "Error destroying drawable"); - return; - } - glerror = - pvrvideosink->dcontext->wsegl_table-> - pfnWSEGL_CreateWindowDrawable (pvrvideosink->dcontext->display_handle, - pvrvideosink->dcontext->glconfig, - &pvrvideosink->dcontext->drawable_handle, - (NativeWindowType) pvrvideosink->xwindow->window, - &pvrvideosink->dcontext->rotation); - if (glerror != WSEGL_SUCCESS) { - GST_ERROR_OBJECT (pvrvideosink, "Error creating drawable"); - return; - } - glerror = - pvrvideosink->dcontext->wsegl_table-> - pfnWSEGL_GetDrawableParameters (pvrvideosink->dcontext->drawable_handle, - &source_params, &pvrvideosink->render_params); - if (glerror != WSEGL_SUCCESS) { - GST_ERROR_OBJECT (pvrvideosink, "Error getting Drawable params"); - return; - } - - client_mem_info = - (PVRSRV_CLIENT_MEM_INFO *) pvrvideosink->render_params.hPrivateData; - PVR2DMEMINFO_INITIALISE (&pvrvideosink->dcontext->dst_mem, client_mem_info); - } - - g_mutex_unlock (pvrvideosink->dcontext->x_lock); -} - -/* This function handles XEvents that might be in the queue. It generates - GstEvent that will be sent upstream in the pipeline to handle interactivity - and navigation. It will also listen for configure events on the window to - trigger caps renegotiation so on the fly software scaling can work. */ -static void -gst_pvrvideosink_handle_xevents (GstPVRVideoSink * pvrvideosink) -{ - XEvent e; - gboolean exposed = FALSE; - gboolean configured = FALSE; - - g_mutex_lock (pvrvideosink->flow_lock); - g_mutex_lock (pvrvideosink->dcontext->x_lock); - - /* Handle Expose */ - while (XCheckWindowEvent (pvrvideosink->dcontext->x_display, - pvrvideosink->xwindow->window, ExposureMask | StructureNotifyMask, - &e)) { - switch (e.type) { - case Expose: - exposed = TRUE; - break; - case ConfigureNotify: - g_mutex_unlock (pvrvideosink->dcontext->x_lock); - gst_pvrvideosink_xwindow_update_geometry (pvrvideosink); - g_mutex_lock (pvrvideosink->dcontext->x_lock); - configured = TRUE; - break; - default: - break; - } - } - - if (exposed || configured) { - g_mutex_unlock (pvrvideosink->dcontext->x_lock); - g_mutex_unlock (pvrvideosink->flow_lock); - - gst_pvrvideosink_expose (GST_VIDEO_OVERLAY (pvrvideosink)); - - g_mutex_lock (pvrvideosink->flow_lock); - g_mutex_lock (pvrvideosink->dcontext->x_lock); - } - - /* Handle Display events */ - while (XPending (pvrvideosink->dcontext->x_display)) { - XNextEvent (pvrvideosink->dcontext->x_display, &e); - - switch (e.type) { - case ClientMessage:{ - Atom wm_delete; - - wm_delete = XInternAtom (pvrvideosink->dcontext->x_display, - "WM_DELETE_WINDOW", True); - if (wm_delete != None && wm_delete == (Atom) e.xclient.data.l[0]) { - /* Handle window deletion by posting an error on the bus */ - GST_ELEMENT_ERROR (pvrvideosink, RESOURCE, NOT_FOUND, - ("Output window was closed"), (NULL)); - - g_mutex_unlock (pvrvideosink->dcontext->x_lock); - gst_pvrvideosink_xwindow_destroy (pvrvideosink, - pvrvideosink->xwindow); - pvrvideosink->xwindow = NULL; - g_mutex_lock (pvrvideosink->dcontext->x_lock); - } - break; - } - default: - break; - } - } - - g_mutex_unlock (pvrvideosink->dcontext->x_lock); - g_mutex_unlock (pvrvideosink->flow_lock); -} - -static gpointer -gst_pvrvideosink_event_thread (GstPVRVideoSink * pvrvideosink) -{ - GST_OBJECT_LOCK (pvrvideosink); - while (pvrvideosink->running) { - GST_OBJECT_UNLOCK (pvrvideosink); - - if (pvrvideosink->xwindow) { - gst_pvrvideosink_handle_xevents (pvrvideosink); - } - g_usleep (G_USEC_PER_SEC / 20); - - GST_OBJECT_LOCK (pvrvideosink); - } - GST_OBJECT_UNLOCK (pvrvideosink); - - return NULL; -} - -static void -gst_pvrvideosink_manage_event_thread (GstPVRVideoSink * pvrvideosink) -{ - GThread *thread = NULL; - - /* don't start the thread too early */ - if (pvrvideosink->dcontext == NULL) { - return; - } - - GST_OBJECT_LOCK (pvrvideosink); - if (!pvrvideosink->event_thread) { - /* Setup our event listening thread */ - GST_DEBUG_OBJECT (pvrvideosink, "run xevent thread"); - pvrvideosink->running = TRUE; - pvrvideosink->event_thread = g_thread_create ( - (GThreadFunc) gst_pvrvideosink_event_thread, pvrvideosink, TRUE, NULL); - } - GST_OBJECT_UNLOCK (pvrvideosink); - - /* Wait for our event thread to finish */ - if (thread) - g_thread_join (thread); -} - - -static GstDrawContext * -gst_pvrvideosink_get_dcontext (GstPVRVideoSink * pvrvideosink) -{ - GstDrawContext *dcontext = NULL; - PVR2DERROR pvr_error; - gint refresh_rate; - DRI2WSDisplay *displayImpl; - WSEGLError glerror; - const WSEGLCaps *glcaps; - - GST_DEBUG_OBJECT (pvrvideosink, "Getting draw context"); - - dcontext = g_new0 (GstDrawContext, 1); - dcontext->x_lock = g_mutex_new (); - - dcontext->p_blt_info = g_new0 (PVR2D_3DBLT_EXT, 1); - if (!dcontext->p_blt_info) - goto p_blt_info_alloc_failed; - - dcontext->p_blt2d_info = g_new0 (PVR2DBLTINFO, 1); - - GST_LOG_OBJECT (pvrvideosink, "Opening X Display"); - dcontext->x_display = XOpenDisplay (NULL); - - if (dcontext->x_display == NULL) - goto fail_open_display; - - GST_LOG_OBJECT (pvrvideosink, "WSEGL_GetFunctionTablePointer()"); - dcontext->wsegl_table = WSEGL_GetFunctionTablePointer (); - - GST_LOG_OBJECT (pvrvideosink, "pfnWSEGL_IsDisplayValid()"); - glerror = dcontext->wsegl_table->pfnWSEGL_IsDisplayValid ( - (NativeDisplayType) dcontext->x_display); - - if (glerror != WSEGL_SUCCESS) - goto display_invalid; - - GST_LOG_OBJECT (pvrvideosink, "pfnWSEGL_InitialiseDisplay()"); - - glerror = dcontext->wsegl_table->pfnWSEGL_InitialiseDisplay ( - (NativeDisplayType) dcontext->x_display, &dcontext->display_handle, - &glcaps, &dcontext->glconfig); - if (glerror != WSEGL_SUCCESS) - goto display_init_failed; - - displayImpl = (DRI2WSDisplay *) dcontext->display_handle; - dcontext->pvr_context = displayImpl->hContext; - - GST_LOG_OBJECT (pvrvideosink, "PVR2DGetScreenMode()"); - - pvr_error = PVR2DGetScreenMode (dcontext->pvr_context, - &dcontext->display_format, &dcontext->display_width, - &dcontext->display_height, &dcontext->stride, &refresh_rate); - if (pvr_error != PVR2D_OK) - goto screen_mode_failed; - - GST_DEBUG_OBJECT (pvrvideosink, - "Got format:%d, width:%d, height:%d, stride:%d, refresh_rate:%d", - dcontext->display_format, dcontext->display_width, - dcontext->display_height, dcontext->stride, refresh_rate); - - dcontext->screen_num = DefaultScreen (dcontext->x_display); - dcontext->black = XBlackPixel (dcontext->x_display, dcontext->screen_num); - - GST_DEBUG_OBJECT (pvrvideosink, "Returning dcontext %p", dcontext); - - return dcontext; - -p_blt_info_alloc_failed: - { - GST_ERROR_OBJECT (pvrvideosink, "Alloc of bltinfo failed"); - gst_pvrvideosink_dcontext_free (dcontext); - return NULL; - } - -fail_open_display: - { - GST_ERROR_OBJECT (pvrvideosink, "Failed to open X Display"); - gst_pvrvideosink_dcontext_free (dcontext); - return NULL; - } - -display_invalid: - { - GST_ERROR_OBJECT (pvrvideosink, "Display is not valid (glerror:%d)", - glerror); - gst_pvrvideosink_dcontext_free (dcontext); - return NULL; - } - -display_init_failed: - { - GST_ERROR_OBJECT (pvrvideosink, "Error initializing display (glerror:%d)", - glerror); - gst_pvrvideosink_dcontext_free (dcontext); - return NULL; - } - -screen_mode_failed: - { - GST_ERROR_OBJECT (pvrvideosink, "Failed to get screen mode. error : %s", - gst_pvr2d_error_get_string (pvr_error)); - gst_pvrvideosink_dcontext_free (dcontext); - return NULL; - } -} - -static void -gst_pvrvideosink_xwindow_set_title (GstPVRVideoSink * pvrvideosink, - GstXWindow * xwindow, const gchar * media_title) -{ - if (media_title) { - g_free (pvrvideosink->media_title); - pvrvideosink->media_title = g_strdup (media_title); - } - if (xwindow) { - /* we have a window */ - if (xwindow->internal) { - XTextProperty xproperty; - const gchar *app_name; - const gchar *title = NULL; - gchar *title_mem = NULL; - - /* set application name as a title */ - app_name = g_get_application_name (); - - if (app_name && pvrvideosink->media_title) { - title = title_mem = g_strconcat (pvrvideosink->media_title, " : ", - app_name, NULL); - } else if (app_name) { - title = app_name; - } else if (pvrvideosink->media_title) { - title = pvrvideosink->media_title; - } - - if (title) { - if ((XStringListToTextProperty (((char **) &title), 1, - &xproperty)) != 0) { - XSetWMName (pvrvideosink->dcontext->x_display, xwindow->window, - &xproperty); - XFree (xproperty.value); - } - - g_free (title_mem); - } - } - } -} - -static GstXWindow * -gst_pvrvideosink_create_window (GstPVRVideoSink * pvrvideosink, gint width, - gint height) -{ - WSEGLError glerror; - WSEGLDrawableParams source_params; - Window root; - GstXWindow *xwindow; - GstDrawContext *dcontext; - XGCValues values; - Atom wm_delete; - PVRSRV_CLIENT_MEM_INFO *client_mem_info; - - GST_DEBUG_OBJECT (pvrvideosink, "begin"); - - dcontext = pvrvideosink->dcontext; - xwindow = g_new0 (GstXWindow, 1); - - xwindow->internal = TRUE; - pvrvideosink->render_rect.x = pvrvideosink->render_rect.y = 0; - pvrvideosink->render_rect.w = width; - pvrvideosink->render_rect.h = height; - xwindow->width = width; - xwindow->height = height; - xwindow->internal = TRUE; - - g_mutex_lock (pvrvideosink->dcontext->x_lock); - - root = DefaultRootWindow (dcontext->x_display); - xwindow->window = XCreateSimpleWindow (dcontext->x_display, root, 0, 0, - width, height, 2, 2, pvrvideosink->dcontext->black); - XSelectInput (dcontext->x_display, xwindow->window, - ExposureMask | StructureNotifyMask); - - /* Tell the window manager we'd like delete client messages instead of - * being killed */ - wm_delete = XInternAtom (pvrvideosink->dcontext->x_display, - "WM_DELETE_WINDOW", True); - if (wm_delete != None) { - (void) XSetWMProtocols (pvrvideosink->dcontext->x_display, xwindow->window, - &wm_delete, 1); - } - - XMapWindow (dcontext->x_display, xwindow->window); - - /* We have to do that to prevent X from redrawing the background on - * ConfigureNotify. This takes away flickering of video when resizing. */ - XSetWindowBackgroundPixmap (pvrvideosink->dcontext->x_display, - xwindow->window, None); - - gst_pvrvideosink_xwindow_set_title (pvrvideosink, xwindow, NULL); - - xwindow->gc = XCreateGC (pvrvideosink->dcontext->x_display, - xwindow->window, 0, &values); - - g_mutex_unlock (pvrvideosink->dcontext->x_lock); - - glerror = - dcontext->wsegl_table-> - pfnWSEGL_CreateWindowDrawable (dcontext->display_handle, - dcontext->glconfig, &(dcontext->drawable_handle), - (NativeWindowType) xwindow->window, &(dcontext->rotation)); - - if (glerror != WSEGL_SUCCESS) { - GST_ERROR_OBJECT (pvrvideosink, "Error creating drawable"); - return NULL; - } - glerror = - dcontext->wsegl_table-> - pfnWSEGL_GetDrawableParameters (dcontext->drawable_handle, &source_params, - &pvrvideosink->render_params); - client_mem_info = - (PVRSRV_CLIENT_MEM_INFO *) pvrvideosink->render_params.hPrivateData; - PVR2DMEMINFO_INITIALISE (&dcontext->dst_mem, client_mem_info); - - GST_DEBUG_OBJECT (pvrvideosink, "end"); - return xwindow; -} - -static void -gst_pvrvideosink_blit (GstPVRVideoSink * pvrvideosink, GstBuffer * buffer) -{ - PVR2DERROR pvr_error; - GstDrawContext *dcontext = pvrvideosink->dcontext; - gint video_width; - gint video_height; - gboolean draw_border = FALSE; - PPVR2D_3DBLT_EXT p_blt_3d; - PVR2DMEMINFO *src_mem; - PVR2DFORMAT pvr_format; - GstVideoRectangle result; - GstPVRMeta *meta; - GstVideoCropMeta *cropmeta; - - GST_DEBUG_OBJECT (pvrvideosink, "buffer %p", buffer); - - pvr_format = - GST_VIDEO_INFO_FORMAT (&pvrvideosink->info) == - GST_VIDEO_FORMAT_NV12 ? PVR2D_YUV420_2PLANE : PVR2D_ARGB8888; - - g_mutex_lock (pvrvideosink->flow_lock); - if (buffer == NULL) - buffer = pvrvideosink->current_buffer; - - if (buffer == NULL) - goto done; - - meta = gst_buffer_get_pvr_meta (buffer); - if (G_UNLIKELY (meta == NULL)) - goto no_pvr_meta; - - src_mem = meta->src_mem; - p_blt_3d = dcontext->p_blt_info; - - video_width = GST_VIDEO_SINK_WIDTH (pvrvideosink); - video_height = GST_VIDEO_SINK_HEIGHT (pvrvideosink); - - g_mutex_lock (pvrvideosink->dcontext->x_lock); - - /* Draw borders when displaying the first frame. After this - draw borders only on expose event or after a size change. */ - if (!(pvrvideosink->current_buffer) || pvrvideosink->redraw_borders) { - draw_border = TRUE; - } - - /* Store a reference to the last image we put, lose the previous one */ - if (buffer && pvrvideosink->current_buffer != buffer) { - if (pvrvideosink->current_buffer) { - GST_LOG_OBJECT (pvrvideosink, "unreffing %p", - pvrvideosink->current_buffer); - gst_buffer_unref (GST_BUFFER_CAST (pvrvideosink->current_buffer)); - } - GST_LOG_OBJECT (pvrvideosink, "reffing %p as our current buffer", buffer); - pvrvideosink->current_buffer = gst_buffer_ref (buffer); - } - - if (pvrvideosink->keep_aspect) { - GstVideoRectangle src = { 0, }; - GstVideoRectangle dst = { 0, }; - - src.w = GST_VIDEO_SINK_WIDTH (pvrvideosink); - src.h = GST_VIDEO_SINK_HEIGHT (pvrvideosink); - dst.w = pvrvideosink->render_rect.w; - dst.h = pvrvideosink->render_rect.h; - gst_video_sink_center_rect (src, dst, &result, TRUE); - result.x += pvrvideosink->render_rect.x; - result.y += pvrvideosink->render_rect.y; - } else { - memcpy (&result, &pvrvideosink->render_rect, sizeof (GstVideoRectangle)); - } - - p_blt_3d->sDst.pSurfMemInfo = &dcontext->dst_mem; - p_blt_3d->sDst.SurfOffset = 0; - p_blt_3d->sDst.Stride = 4 * pvrvideosink->render_params.ui32Stride; - p_blt_3d->sDst.Format = PVR2D_ARGB8888; - p_blt_3d->sDst.SurfWidth = pvrvideosink->xwindow->width; - p_blt_3d->sDst.SurfHeight = pvrvideosink->xwindow->height; - - p_blt_3d->rcDest.left = result.x; - p_blt_3d->rcDest.top = result.y; - p_blt_3d->rcDest.right = result.w + result.x; - p_blt_3d->rcDest.bottom = result.h + result.y; - - p_blt_3d->sSrc.pSurfMemInfo = src_mem; - p_blt_3d->sSrc.SurfOffset = 0; - p_blt_3d->sSrc.Stride = GST_VIDEO_INFO_COMP_STRIDE (&pvrvideosink->info, 0); - p_blt_3d->sSrc.Format = pvr_format; - p_blt_3d->sSrc.SurfWidth = video_width; - p_blt_3d->sSrc.SurfHeight = video_height; - - /* If buffer has crop information, use that */ - if ((cropmeta = gst_buffer_get_video_crop_meta (buffer))) { - p_blt_3d->rcSource.left = cropmeta->x; - p_blt_3d->rcSource.top = cropmeta->y; - p_blt_3d->rcSource.right = cropmeta->x + cropmeta->width; - p_blt_3d->rcSource.bottom = cropmeta->y + cropmeta->height; - } else { - p_blt_3d->rcSource.left = 0; - p_blt_3d->rcSource.top = 0; - p_blt_3d->rcSource.right = video_width; - p_blt_3d->rcSource.bottom = video_height; - } - - p_blt_3d->hUseCode = NULL; - - if (GST_VIDEO_INFO_FORMAT (&pvrvideosink->info) == GST_VIDEO_FORMAT_NV12) - p_blt_3d->bDisableDestInput = TRUE; - else - /* blit fails for RGB without this... not sure why yet... */ - p_blt_3d->bDisableDestInput = FALSE; - - GST_DEBUG_OBJECT (pvrvideosink, "about to blit"); - - pvr_error = PVR2DBlt3DExt (pvrvideosink->dcontext->pvr_context, - dcontext->p_blt_info); - - if (pvr_error != PVR2D_OK) { - GST_ERROR_OBJECT (pvrvideosink, "Failed to blit. Error : %s", - gst_pvr2d_error_get_string (pvr_error)); - goto done; - } - dcontext->wsegl_table->pfnWSEGL_SwapDrawable (dcontext->drawable_handle, 1); - - if (draw_border) { - gst_pvrvideosink_xwindow_draw_borders (pvrvideosink, pvrvideosink->xwindow, - result); - pvrvideosink->redraw_borders = FALSE; - } - g_mutex_unlock (pvrvideosink->dcontext->x_lock); - -done: - GST_DEBUG_OBJECT (pvrvideosink, "end"); - g_mutex_unlock (pvrvideosink->flow_lock); - return; - - /* Error cases */ - -no_pvr_meta: - { - g_mutex_unlock (pvrvideosink->flow_lock); - GST_ERROR_OBJECT (pvrvideosink, "Got a buffer without GstPVRMeta"); - return; - } -} - -static void -gst_pvrvideosink_destroy_drawable (GstPVRVideoSink * pvrvideosink) -{ - GST_DEBUG_OBJECT (pvrvideosink, "dcontext : %p", pvrvideosink->dcontext); - - if (pvrvideosink->dcontext != NULL) { - if (pvrvideosink->dcontext->drawable_handle) { - GST_DEBUG_OBJECT (pvrvideosink, "Deleting Drawable (drawable_handle:%p)", - pvrvideosink->dcontext->drawable_handle); - pvrvideosink->dcontext->wsegl_table-> - pfnWSEGL_DeleteDrawable (pvrvideosink->dcontext->drawable_handle); - } - - GST_DEBUG_OBJECT (pvrvideosink, "Closing display (display_handle:%p)", - pvrvideosink->dcontext->display_handle); - pvrvideosink->dcontext->wsegl_table-> - pfnWSEGL_CloseDisplay (pvrvideosink->dcontext->display_handle); - } -} - -/* We are called with the x_lock taken */ -static void -gst_pvrvideosink_pvrfill_rectangle (GstPVRVideoSink * pvrvideosink, - GstVideoRectangle rect) -{ - PVR2DERROR pvr_error; - PPVR2DBLTINFO p_blt2d_info = 0; - GstDrawContext *dcontext = pvrvideosink->dcontext; - - GST_DEBUG_OBJECT (pvrvideosink, "begin"); - - p_blt2d_info = dcontext->p_blt2d_info; - - p_blt2d_info->pDstMemInfo = &dcontext->dst_mem; - p_blt2d_info->BlitFlags = PVR2D_BLIT_DISABLE_ALL; - p_blt2d_info->DstOffset = 0; - p_blt2d_info->CopyCode = PVR2DROPclear; - p_blt2d_info->DstStride = 4 * pvrvideosink->render_params.ui32Stride; - p_blt2d_info->DstFormat = PVR2D_ARGB8888; - p_blt2d_info->DstSurfWidth = pvrvideosink->xwindow->width; - p_blt2d_info->DstSurfHeight = pvrvideosink->xwindow->height; - p_blt2d_info->DstX = rect.x; - p_blt2d_info->DstY = rect.y; - p_blt2d_info->DSizeX = rect.w; - p_blt2d_info->DSizeY = rect.h; - - pvr_error = PVR2DBlt (pvrvideosink->dcontext->pvr_context, p_blt2d_info); - - if (pvr_error != PVR2D_OK) { - GST_ERROR_OBJECT (pvrvideosink, "Failed to blit. Error : %s", - gst_pvr2d_error_get_string (pvr_error)); - goto done; - } - dcontext->wsegl_table->pfnWSEGL_SwapDrawable (dcontext->drawable_handle, 1); - -done: - GST_DEBUG_OBJECT (pvrvideosink, "end"); -} - -/* We are called with the x_lock taken */ -static void -gst_pvrvideosink_xwindow_draw_borders (GstPVRVideoSink * pvrvideosink, - GstXWindow * xwindow, GstVideoRectangle rect) -{ - gint t1, t2; - GstVideoRectangle result; - - g_return_if_fail (GST_IS_PVRVIDEOSINK (pvrvideosink)); - g_return_if_fail (xwindow != NULL); - - /* Left border */ - result.x = pvrvideosink->render_rect.x; - result.y = pvrvideosink->render_rect.y; - result.w = rect.x - pvrvideosink->render_rect.x; - result.h = pvrvideosink->render_rect.h; - if (rect.x > pvrvideosink->render_rect.x) - gst_pvrvideosink_pvrfill_rectangle (pvrvideosink, result); - - /* Right border */ - t1 = rect.x + rect.w; - t2 = pvrvideosink->render_rect.x + pvrvideosink->render_rect.w; - result.x = t1; - result.y = pvrvideosink->render_rect.y; - result.w = t2 - t1; - result.h = pvrvideosink->render_rect.h; - if (t1 < t2) - gst_pvrvideosink_pvrfill_rectangle (pvrvideosink, result); - - /* Top border */ - result.x = pvrvideosink->render_rect.x; - result.y = pvrvideosink->render_rect.y; - result.w = pvrvideosink->render_rect.w; - result.h = rect.y - pvrvideosink->render_rect.y; - if (rect.y > pvrvideosink->render_rect.y) - gst_pvrvideosink_pvrfill_rectangle (pvrvideosink, result); - - /* Bottom border */ - t1 = rect.y + rect.h; - t2 = pvrvideosink->render_rect.y + pvrvideosink->render_rect.h; - result.x = pvrvideosink->render_rect.x; - result.y = t1; - result.w = pvrvideosink->render_rect.w; - result.h = t2 - t1; - if (t1 < t2) - gst_pvrvideosink_pvrfill_rectangle (pvrvideosink, result); -} - -/* Element stuff */ - -static gboolean -gst_pvrvideosink_setcaps (GstBaseSink * bsink, GstCaps * caps) -{ - GstPVRVideoSink *pvrvideosink; - GstVideoInfo info; - GstStructure *structure; - GstBufferPool *oldpool, *newpool; - - pvrvideosink = GST_PVRVIDEOSINK (bsink); - - GST_DEBUG_OBJECT (pvrvideosink, - "sinkconnect possible caps with given caps %" GST_PTR_FORMAT, caps); - - if (!gst_video_info_from_caps (&info, caps)) - goto invalid_format; - - GST_VIDEO_SINK_WIDTH (pvrvideosink) = info.width; - GST_VIDEO_SINK_HEIGHT (pvrvideosink) = info.height; - - /* Notify application to set xwindow id now */ - g_mutex_lock (pvrvideosink->flow_lock); - if (!pvrvideosink->xwindow) { - g_mutex_unlock (pvrvideosink->flow_lock); - gst_video_overlay_prepare_window_handle (GST_VIDEO_OVERLAY (pvrvideosink)); - } else { - g_mutex_unlock (pvrvideosink->flow_lock); - } - - g_mutex_lock (pvrvideosink->flow_lock); - if (!pvrvideosink->xwindow) - pvrvideosink->xwindow = gst_pvrvideosink_create_window (pvrvideosink, - GST_VIDEO_SINK_WIDTH (pvrvideosink), - GST_VIDEO_SINK_HEIGHT (pvrvideosink)); - g_mutex_unlock (pvrvideosink->flow_lock); - - pvrvideosink->info = info; - - /* After a resize, we want to redraw the borders in case the new frame size - * doesn't cover the same area */ - pvrvideosink->redraw_borders = TRUE; - - /* create a new pool for the new configuration */ - newpool = gst_pvr_buffer_pool_new (GST_ELEMENT_CAST (pvrvideosink)); - - /* PVR needs at least 3 buffers */ - structure = gst_buffer_pool_get_config (newpool); - gst_buffer_pool_config_set (structure, caps, GST_VIDEO_INFO_SIZE (&info), 3, - 0, 0, 15); - if (!gst_buffer_pool_set_config (newpool, structure)) - goto config_failed; - - oldpool = pvrvideosink->pool; - pvrvideosink->pool = newpool; - g_mutex_unlock (pvrvideosink->flow_lock); - - /* unref the old sink */ - if (oldpool) { - /* we don't deactivate, some elements might still be using it, it will - * be deactivated when the last ref is gone */ - gst_object_unref (oldpool); - } - - return TRUE; - -config_failed: - { - GST_ERROR_OBJECT (pvrvideosink, "failed to set config."); - g_mutex_unlock (pvrvideosink->flow_lock); - return FALSE; - } - -invalid_format: - { - GST_DEBUG_OBJECT (pvrvideosink, - "Could not locate image format from caps %" GST_PTR_FORMAT, caps); - return FALSE; - } -} - -static GstCaps * -gst_pvrvideosink_getcaps (GstBaseSink * bsink, GstCaps * filter) -{ - GstPVRVideoSink *pvrvideosink; - GstCaps *caps; - - GST_DEBUG_OBJECT (bsink, "filter:%" GST_PTR_FORMAT, filter); - - pvrvideosink = GST_PVRVIDEOSINK (bsink); - - /* FIXME : If we have curently configured caps, we should return those - * intersected with the filter*/ - - caps = gst_pad_get_pad_template_caps (GST_BASE_SINK (pvrvideosink)->sinkpad); - if (filter) { - GstCaps *intersection; - - intersection = - gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST); - gst_caps_unref (caps); - caps = intersection; - } - - GST_DEBUG_OBJECT (bsink, "Returning %" GST_PTR_FORMAT, caps); - - return caps; -} - -static GstStateChangeReturn -gst_pvrvideosink_change_state (GstElement * element, GstStateChange transition) -{ - GstPVRVideoSink *pvrvideosink; - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - GstDrawContext *dcontext; - - pvrvideosink = GST_PVRVIDEOSINK (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - if (pvrvideosink->dcontext == NULL) { - dcontext = gst_pvrvideosink_get_dcontext (pvrvideosink); - if (dcontext == NULL) - return GST_STATE_CHANGE_FAILURE; - GST_OBJECT_LOCK (pvrvideosink); - pvrvideosink->dcontext = dcontext; - GST_OBJECT_UNLOCK (pvrvideosink); - } - gst_pvrvideosink_manage_event_thread (pvrvideosink); - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - GST_VIDEO_SINK_WIDTH (pvrvideosink) = 0; - GST_VIDEO_SINK_HEIGHT (pvrvideosink) = 0; - break; - case GST_STATE_CHANGE_READY_TO_NULL: - gst_pvrvideosink_reset (pvrvideosink); - break; - default: - break; - } - - return ret; -} - -static void -gst_pvrvideosink_get_times (GstBaseSink * bsink, GstBuffer * buf, - GstClockTime * start, GstClockTime * end) -{ - GstPVRVideoSink *pvrvideosink; - - pvrvideosink = GST_PVRVIDEOSINK (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 { - gint fps_n, fps_d; - fps_n = GST_VIDEO_INFO_FPS_N (&pvrvideosink->info); - fps_d = GST_VIDEO_INFO_FPS_D (&pvrvideosink->info); - if (fps_n > 0) { - *end = *start + gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n); - } - } - } -} - -static GstFlowReturn -gst_pvrvideosink_show_frame (GstVideoSink * vsink, GstBuffer * buf) -{ - GstPVRVideoSink *pvrvideosink = GST_PVRVIDEOSINK (vsink); - GstPVRMeta *meta; - - GST_DEBUG_OBJECT (pvrvideosink, "render buffer: %p", buf); - - meta = gst_buffer_get_pvr_meta (buf); - - if (G_UNLIKELY (meta == NULL)) { - meta = gst_buffer_add_pvr_meta (buf, GST_ELEMENT_CAST (pvrvideosink)); - if (meta == NULL) - goto meta_failure; - } - - gst_pvrvideosink_blit (pvrvideosink, buf); - - return GST_FLOW_OK; - -meta_failure: - { - GST_WARNING_OBJECT (pvrvideosink, "Failed to map incoming buffer"); - return GST_FLOW_ERROR; - } -} - -static gboolean -gst_pvrvideosink_propose_allocation (GstBaseSink * bsink, GstQuery * query) -{ - GstPVRVideoSink *pvrvideosink = (GstPVRVideoSink *) bsink; - GstBufferPool *pool; - GstStructure *config; - GstCaps *caps; - guint size; - gboolean need_pool; - - gst_query_parse_allocation (query, &caps, &need_pool); - - if (caps == NULL) - goto no_caps; - - g_mutex_lock (pvrvideosink->flow_lock); - if ((pool = pvrvideosink->pool)) - gst_object_ref (pool); - g_mutex_unlock (pvrvideosink->flow_lock); - - if (pool != NULL) { - const GstCaps *pcaps; - - /* we had a pool, check caps */ - GST_DEBUG_OBJECT (pvrvideosink, "check existing pool caps"); - config = gst_buffer_pool_get_config (pool); - gst_buffer_pool_config_get (config, &pcaps, &size, NULL, NULL, NULL, NULL); - gst_structure_free (config); - - if (!gst_caps_is_equal (caps, pcaps)) { - GST_DEBUG_OBJECT (pvrvideosink, "pool has different caps"); - /* different caps, we can't use this pool */ - gst_object_unref (pool); - pool = NULL; - } - } - - if (pool == NULL && need_pool) { - GstVideoInfo info; - - GST_DEBUG_OBJECT (pvrvideosink, "create new pool"); - pool = gst_pvr_buffer_pool_new (GST_ELEMENT_CAST (pvrvideosink)); - - if (!gst_video_info_from_caps (&info, caps)) - goto invalid_caps; - - /* the normal size of a frame */ - size = info.size; - - config = gst_buffer_pool_get_config (pool); - gst_buffer_pool_config_set (config, caps, size, 0, 0, 0, 0); - if (!gst_buffer_pool_set_config (pool, config)) - goto config_failed; - } - /* we need at least 3 buffers */ - gst_query_set_allocation_params (query, size, 3, 0, 0, 0, pool); - - /* we also support various metadata */ - gst_query_add_allocation_meta (query, GST_VIDEO_CROP_META_API, NULL); - - gst_object_unref (pool); - - return TRUE; - - /* ERRORS */ -no_caps: - { - GST_DEBUG_OBJECT (bsink, "no caps specified"); - return FALSE; - } -invalid_caps: - { - GST_DEBUG_OBJECT (bsink, "invalid caps specified"); - return FALSE; - } -config_failed: - { - GST_DEBUG_OBJECT (bsink, "failed setting config"); - return FALSE; - } -} - -/* Interfaces stuff */ - -/* This function destroys a GstXWindow */ -static void -gst_pvrvideosink_xwindow_destroy (GstPVRVideoSink * pvrvideosink, - GstXWindow * xwindow) -{ - g_return_if_fail (xwindow != NULL); - - g_mutex_lock (pvrvideosink->dcontext->x_lock); - - /* If we did not create that window we just free the GC and let it live */ - if (xwindow->internal) - XDestroyWindow (pvrvideosink->dcontext->x_display, xwindow->window); - else - XSelectInput (pvrvideosink->dcontext->x_display, xwindow->window, 0); - - XFreeGC (pvrvideosink->dcontext->x_display, xwindow->gc); - - XSync (pvrvideosink->dcontext->x_display, FALSE); - - g_mutex_unlock (pvrvideosink->dcontext->x_lock); - - g_free (xwindow); -} - -static void -gst_pvrvideosink_set_window_handle (GstVideoOverlay * overlay, guintptr id) -{ - XID window_handle = id; - GstPVRVideoSink *pvrvideosink = GST_PVRVIDEOSINK (overlay); - GstXWindow *xwindow = NULL; - - g_return_if_fail (GST_IS_PVRVIDEOSINK (pvrvideosink)); - - g_mutex_lock (pvrvideosink->flow_lock); - - /* If we already use that window return */ - if (pvrvideosink->xwindow && (window_handle == pvrvideosink->xwindow->window)) { - g_mutex_unlock (pvrvideosink->flow_lock); - return; - } - - /* If the element has not initialized the X11 context try to do so */ - if (!pvrvideosink->dcontext && !(pvrvideosink->dcontext = - gst_pvrvideosink_get_dcontext (pvrvideosink))) { - g_mutex_unlock (pvrvideosink->flow_lock); - /* we have thrown a GST_ELEMENT_ERROR now */ - return; - } - - /* If a window is there already we destroy it */ - if (pvrvideosink->xwindow) { - gst_pvrvideosink_xwindow_destroy (pvrvideosink, pvrvideosink->xwindow); - pvrvideosink->xwindow = NULL; - } - - /* If the xid is 0 we will create an internal one in buffer_alloc */ - if (window_handle != 0) { - XWindowAttributes attr; - WSEGLError glerror; - WSEGLDrawableParams source_params; - PVRSRV_CLIENT_MEM_INFO *client_mem_info; - - xwindow = g_new0 (GstXWindow, 1); - xwindow->window = window_handle; - - /* Set the event we want to receive and create a GC */ - g_mutex_lock (pvrvideosink->dcontext->x_lock); - - XGetWindowAttributes (pvrvideosink->dcontext->x_display, xwindow->window, - &attr); - - xwindow->width = attr.width; - xwindow->height = attr.height; - xwindow->internal = FALSE; - if (!pvrvideosink->have_render_rect) { - pvrvideosink->render_rect.x = pvrvideosink->render_rect.y = 0; - pvrvideosink->render_rect.w = attr.width; - pvrvideosink->render_rect.h = attr.height; - } - XSelectInput (pvrvideosink->dcontext->x_display, xwindow->window, - ExposureMask | StructureNotifyMask); - - XSetWindowBackgroundPixmap (pvrvideosink->dcontext->x_display, - xwindow->window, None); - - XMapWindow (pvrvideosink->dcontext->x_display, xwindow->window); - xwindow->gc = XCreateGC (pvrvideosink->dcontext->x_display, - xwindow->window, 0, NULL); - g_mutex_unlock (pvrvideosink->dcontext->x_lock); - - glerror = - pvrvideosink->dcontext->wsegl_table-> - pfnWSEGL_CreateWindowDrawable (pvrvideosink->dcontext->display_handle, - pvrvideosink->dcontext->glconfig, - &(pvrvideosink->dcontext->drawable_handle), - (NativeWindowType) xwindow->window, - &(pvrvideosink->dcontext->rotation)); - - if (glerror != WSEGL_SUCCESS) { - GST_ERROR_OBJECT (pvrvideosink, "Error creating drawable"); - return; - } - glerror = - pvrvideosink->dcontext->wsegl_table-> - pfnWSEGL_GetDrawableParameters (pvrvideosink->dcontext->drawable_handle, - &source_params, &pvrvideosink->render_params); - - client_mem_info = - (PVRSRV_CLIENT_MEM_INFO *) pvrvideosink->render_params.hPrivateData; - PVR2DMEMINFO_INITIALISE (&pvrvideosink->dcontext->dst_mem, client_mem_info); - } - - if (xwindow) - pvrvideosink->xwindow = xwindow; - - g_mutex_unlock (pvrvideosink->flow_lock); -} - -static void -gst_pvrvideosink_expose (GstVideoOverlay * overlay) -{ - GstPVRVideoSink *pvrvideosink = GST_PVRVIDEOSINK (overlay); - - gst_pvrvideosink_blit (pvrvideosink, NULL); -} - -static void -gst_pvrvideosink_set_event_handling (GstVideoOverlay * overlay, - gboolean handle_events) -{ - GstPVRVideoSink *pvrvideosink = GST_PVRVIDEOSINK (overlay); - - g_mutex_lock (pvrvideosink->flow_lock); - - if (G_UNLIKELY (!pvrvideosink->xwindow)) { - g_mutex_unlock (pvrvideosink->flow_lock); - return; - } - - g_mutex_lock (pvrvideosink->dcontext->x_lock); - - XSelectInput (pvrvideosink->dcontext->x_display, - pvrvideosink->xwindow->window, ExposureMask | StructureNotifyMask); - - g_mutex_unlock (pvrvideosink->dcontext->x_lock); - - g_mutex_unlock (pvrvideosink->flow_lock); -} - -static void -gst_pvrvideosink_set_render_rectangle (GstVideoOverlay * overlay, gint x, - gint y, gint width, gint height) -{ - GstPVRVideoSink *pvrvideosink = GST_PVRVIDEOSINK (overlay); - - /* FIXME: how about some locking? */ - if (width >= 0 && height >= 0) { - pvrvideosink->render_rect.x = x; - pvrvideosink->render_rect.y = y; - pvrvideosink->render_rect.w = width; - pvrvideosink->render_rect.h = height; - pvrvideosink->have_render_rect = TRUE; - } else { - pvrvideosink->render_rect.x = 0; - pvrvideosink->render_rect.y = 0; - pvrvideosink->render_rect.w = pvrvideosink->xwindow->width; - pvrvideosink->render_rect.h = pvrvideosink->xwindow->height; - pvrvideosink->have_render_rect = FALSE; - } -} - -static void -gst_pvrvideosink_videooverlay_init (GstVideoOverlayInterface * iface) -{ - iface->set_window_handle = gst_pvrvideosink_set_window_handle; - iface->expose = gst_pvrvideosink_expose; - iface->handle_events = gst_pvrvideosink_set_event_handling; - iface->set_render_rectangle = gst_pvrvideosink_set_render_rectangle; -} - -/* =========================================== */ -/* */ -/* Init & Class init */ -/* */ -/* =========================================== */ - -static void -gst_pvrvideosink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstPVRVideoSink *pvrvideosink; - - g_return_if_fail (GST_IS_PVRVIDEOSINK (object)); - - pvrvideosink = GST_PVRVIDEOSINK (object); - - switch (prop_id) { - case PROP_FORCE_ASPECT_RATIO: - pvrvideosink->keep_aspect = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_pvrvideosink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstPVRVideoSink *pvrvideosink; - - g_return_if_fail (GST_IS_PVRVIDEOSINK (object)); - - pvrvideosink = GST_PVRVIDEOSINK (object); - - switch (prop_id) { - case PROP_FORCE_ASPECT_RATIO: - g_value_set_boolean (value, pvrvideosink->keep_aspect); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -void -gst_pvrvideosink_track_buffer (GstPVRVideoSink * pvrsink, GstBuffer * buffer) -{ - GST_DEBUG_OBJECT (pvrsink, "Adding buffer %p to tracked buffers", buffer); - pvrsink->metabuffers = g_list_prepend (pvrsink->metabuffers, buffer); -} - -void -gst_pvrvideosink_untrack_buffer (GstPVRVideoSink * pvrsink, GstBuffer * buffer) -{ - GST_DEBUG_OBJECT (pvrsink, "Removing buffer %p from tracked buffers", buffer); - pvrsink->metabuffers = g_list_remove_all (pvrsink->metabuffers, buffer); -} - -static void -gst_pvrvideosink_release_pvr_metas (GstPVRVideoSink * pvrsink) -{ - GstBuffer *buf; - GstPVRMeta *pvrmeta; - - GST_DEBUG_OBJECT (pvrsink, "Releasing pending PVR metas"); - - while (pvrsink->metabuffers) { - buf = (GstBuffer *) pvrsink->metabuffers->data; - - pvrmeta = gst_buffer_get_pvr_meta (buf); - if (pvrmeta) - gst_buffer_remove_meta (buf, (GstMeta *) pvrmeta); - } - - GST_DEBUG_OBJECT (pvrsink, "Done"); -} - -static void -gst_pvrvideosink_dcontext_free (GstDrawContext * dcontext) -{ - GST_DEBUG ("Freeing dcontext %p", dcontext); - - g_free (dcontext->p_blt_info); - g_free (dcontext->p_blt2d_info); - - if (dcontext->x_lock) - g_mutex_lock (dcontext->x_lock); - if (dcontext->x_display) { - GST_LOG ("Closing display"); - XCloseDisplay (dcontext->x_display); - } - if (dcontext->x_lock) { - g_mutex_unlock (dcontext->x_lock); - g_mutex_free (dcontext->x_lock); - } - - g_free (dcontext); -} - -static void -gst_pvrvideosink_dcontext_clear (GstPVRVideoSink * pvrvideosink) -{ - GstDrawContext *dcontext; - - GST_DEBUG_OBJECT (pvrvideosink, "Clearing dcontext %p", - pvrvideosink->dcontext); - - GST_OBJECT_LOCK (pvrvideosink); - if (!pvrvideosink->dcontext) { - GST_OBJECT_UNLOCK (pvrvideosink); - return; - } - - dcontext = pvrvideosink->dcontext; - pvrvideosink->dcontext = NULL; - GST_OBJECT_UNLOCK (pvrvideosink); - - gst_pvrvideosink_dcontext_free (dcontext); -} - -static void -gst_pvrvideosink_reset (GstPVRVideoSink * pvrvideosink) -{ - GThread *thread; - - GST_DEBUG_OBJECT (pvrvideosink, "Resetting"); - - GST_OBJECT_LOCK (pvrvideosink); - pvrvideosink->running = FALSE; - thread = pvrvideosink->event_thread; - pvrvideosink->event_thread = NULL; - GST_OBJECT_UNLOCK (pvrvideosink); - - if (thread) - g_thread_join (thread); - - if (pvrvideosink->current_buffer) { - GST_LOG_OBJECT (pvrvideosink, "Removing cached buffer"); - gst_buffer_unref (pvrvideosink->current_buffer); - pvrvideosink->current_buffer = NULL; - } - - if (pvrvideosink->pool) { - GST_LOG_OBJECT (pvrvideosink, "Unreffing pool"); - gst_object_unref (pvrvideosink->pool); - pvrvideosink->pool = NULL; - } - memset (&pvrvideosink->render_params, 0, sizeof (WSEGLDrawableParams)); - - pvrvideosink->render_rect.x = pvrvideosink->render_rect.y = 0; - pvrvideosink->render_rect.w = pvrvideosink->render_rect.h = 0; - pvrvideosink->have_render_rect = FALSE; - - gst_pvrvideosink_release_pvr_metas (pvrvideosink); - - gst_pvrvideosink_destroy_drawable (pvrvideosink); - - if (pvrvideosink->xwindow) { - gst_pvrvideosink_xwindow_destroy (pvrvideosink, pvrvideosink->xwindow); - pvrvideosink->xwindow = NULL; - } - - gst_pvrvideosink_dcontext_clear (pvrvideosink); -} - -static void -gst_pvrvideosink_finalize (GObject * object) -{ - GstPVRVideoSink *pvrvideosink; - - pvrvideosink = GST_PVRVIDEOSINK (object); - - gst_pvrvideosink_reset (pvrvideosink); - - if (pvrvideosink->flow_lock) { - g_mutex_free (pvrvideosink->flow_lock); - pvrvideosink->flow_lock = NULL; - } - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_pvrvideosink_init (GstPVRVideoSink * pvrvideosink) -{ - pvrvideosink->running = FALSE; - - pvrvideosink->flow_lock = g_mutex_new (); - pvrvideosink->pool = NULL; - - pvrvideosink->keep_aspect = FALSE; - pvrvideosink->current_caps = NULL; - pvrvideosink->dcontext = NULL; - pvrvideosink->xwindow = NULL; - pvrvideosink->redraw_borders = TRUE; - pvrvideosink->current_buffer = NULL; - pvrvideosink->event_thread = NULL; - memset (&pvrvideosink->render_params, 0, sizeof (WSEGLDrawableParams)); -} - -static void -gst_pvrvideosink_class_init (GstPVRVideoSinkClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSinkClass *gstbasesink_class; - GstVideoSinkClass *videosink_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - gstbasesink_class = (GstBaseSinkClass *) klass; - videosink_class = (GstVideoSinkClass *) klass; - - parent_class = g_type_class_peek_parent (klass); - - gobject_class->finalize = gst_pvrvideosink_finalize; - gobject_class->set_property = gst_pvrvideosink_set_property; - gobject_class->get_property = gst_pvrvideosink_get_property; - - g_object_class_install_property (gobject_class, PROP_FORCE_ASPECT_RATIO, - g_param_spec_boolean ("force-aspect-ratio", "Force aspect ratio", - "When enabled, reverse caps negotiation (scaling) will respect " - "original aspect ratio", TRUE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - gst_element_class_set_static_metadata (gstelement_class, - "PVR Video sink", "Sink/Video", - "A PVR videosink", - "Luciana Fujii Pontello <luciana.fujii@collabora.co.uk"); - - gst_element_class_add_static_pad_template (gstelement_class, - &gst_pvrvideosink_sink_template_factory); - - gstelement_class->change_state = gst_pvrvideosink_change_state; - - gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_pvrvideosink_setcaps); - gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_pvrvideosink_getcaps); - gstbasesink_class->propose_allocation = - GST_DEBUG_FUNCPTR (gst_pvrvideosink_propose_allocation); - gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_pvrvideosink_get_times); - - videosink_class->show_frame = GST_DEBUG_FUNCPTR (gst_pvrvideosink_show_frame); -} |