blob: 2abe481432d9c6520e91b54ab2ab189b90aa4892 [file] [log] [blame]
/*
* Copyright (c) 2013, Freescale Semiconductor, Inc. All rights reserved.
*
* 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.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "gstimxvideooverlay.h"
#ifdef USE_X11
extern void gst_x_video_overlay_init(ImxVideoOverlay * imxxoverlay);
extern void gst_x_video_overlay_deinit(ImxVideoOverlay * imxxoverlay);
extern void gst_x_video_overlay_interface_init (GstVideoOverlayInterface * iface);
#endif
GST_DEBUG_CATEGORY_STATIC (imxvideooverlay_debug);
#define GST_CAT_DEFAULT imxvideooverlay_debug
void
gst_imx_video_overlay_interface_init (GstVideoOverlayInterface * iface)
{
GST_DEBUG_CATEGORY_INIT (imxvideooverlay_debug, "imxvideooverlay", 0,
"IMX General video overlay interface debugging");
#ifdef USE_X11
gst_x_video_overlay_interface_init (iface);
#else
#endif
}
ImxVideoOverlay *
gst_imx_video_overlay_init(GstElement *element,
VideoUpdateCallback update_video_geometry,
ColorkeySetCallback set_color_key,
AlphaSetCallback set_alpha)
{
ImxVideoOverlay *overlay = NULL;
if (!element) {
GST_ERROR("NULL element parameter");
return NULL;
}
overlay = g_new0(ImxVideoOverlay, 1);
memset(overlay, 0, sizeof (ImxVideoOverlay));
overlay->parent = element;
#ifdef USE_X11
gst_x_video_overlay_init(overlay);
#else
#endif
overlay->set_color_key = set_color_key;
overlay->set_global_alpha = set_alpha;
overlay->update_video_geo = update_video_geometry;
if (!update_video_geometry)
GST_ERROR("Parent and video geometry function not applied");
if (!set_color_key)
GST_ERROR("Color key setting callback NULL, video overlay may not work");
if (!set_alpha)
GST_ERROR("Alpha setting callback NULL, video overlay may not work");
const gchar *colorkey = (gchar *)getenv ("COLORKEY");
if (colorkey && (strlen(colorkey) > 1)) {
overlay->colorkey = strtol(colorkey, NULL, 16);
} else {
overlay->colorkey = DEFAULT_COLORKEY;
gchar str[10] = {0};
sprintf(str, "%08x", overlay->colorkey);
setenv("COLORKEY", str, TRUE);
GST_INFO("set color key:%s\n", str);
}
return overlay;
}
void
gst_imx_video_overlay_finalize(ImxVideoOverlay * imxxoverlay)
{
GST_DEBUG ("event_id %d", imxxoverlay->event_id);
if (imxxoverlay) {
#ifdef USE_X11
gst_x_video_overlay_deinit(imxxoverlay);
#else
#endif
if (imxxoverlay->event_id)
g_source_remove (imxxoverlay->event_id);
imxxoverlay->set_color_key = NULL;
imxxoverlay->set_global_alpha = NULL;
imxxoverlay->update_video_geo = NULL;
g_free(imxxoverlay);
}
}
void
gst_imx_video_overlay_start (ImxVideoOverlay * imxxoverlay)
{
GST_DEBUG ("START");
if (imxxoverlay) {
imxxoverlay->running = TRUE;
if (imxxoverlay->update_win_geo && imxxoverlay->video_win) {
if (imxxoverlay->set_global_alpha)
imxxoverlay->set_global_alpha(imxxoverlay->parent, 255);
if (imxxoverlay->set_color_key)
imxxoverlay->set_color_key (imxxoverlay->parent, TRUE, imxxoverlay->colorkey);
imxxoverlay->update_win_geo (imxxoverlay);
}
}
}
void
gst_imx_video_overlay_stop (ImxVideoOverlay * imxxoverlay)
{
GST_DEBUG ("STOP");
if (imxxoverlay) {
imxxoverlay->running = FALSE;
}
}
void
gst_imx_video_overlay_set_window_handle (ImxVideoOverlay *imxxoverlay,
gulong id)
{
GST_DEBUG ("winid %lu", id);
if (!imxxoverlay || !imxxoverlay->parent ||
!GST_IS_VIDEO_OVERLAY(imxxoverlay->parent)) {
GST_ERROR ("Parent object is not video overlay");
return;
}
if (imxxoverlay->video_win != id) {
if (imxxoverlay->internal_win && id != imxxoverlay->internal_win) {
if (imxxoverlay->destroy_win)
imxxoverlay->destroy_win(imxxoverlay);
}
imxxoverlay->video_win = id;
GST_DEBUG ("Setting XID to %lu", id);
}
if (id != 0) {
if (imxxoverlay->set_global_alpha)
imxxoverlay->set_global_alpha(imxxoverlay->parent, 255);
if (imxxoverlay->set_color_key)
imxxoverlay->set_color_key (imxxoverlay->parent, TRUE, imxxoverlay->colorkey);
if (imxxoverlay->update_win_geo)
imxxoverlay->update_win_geo (imxxoverlay);
/* handle the X event always, we need events to update video geometry */
if (imxxoverlay->handle_events)
imxxoverlay->handle_events(imxxoverlay, TRUE);
if (imxxoverlay->event_polling) {
if (imxxoverlay->event_id)
g_source_remove (imxxoverlay->event_id);
imxxoverlay->event_id = g_timeout_add (EVENT_REFRESH_INTERVAL,
imxxoverlay->event_polling, imxxoverlay);
GST_DEBUG ("event_id %d", imxxoverlay->event_id);
}
} else {
if (imxxoverlay->set_global_alpha)
imxxoverlay->set_global_alpha(imxxoverlay->parent, 0);
if (imxxoverlay->set_color_key)
imxxoverlay->set_color_key (imxxoverlay->parent, FALSE, 0);
}
}
/*
* required: TRUE if display is required (ie. TRUE for v4l2sink, but
* FALSE for any other element with optional overlay capabilities)
*/
void
gst_imx_video_overlay_prepare_window_handle (ImxVideoOverlay * imxxoverlay,
gboolean required)
{
GST_DEBUG ("video-win %lu", imxxoverlay->video_win);
#ifdef ENABLE_PREPARE_WINDOW_INTERFACE
if (!imxxoverlay || !imxxoverlay->parent ||
!GST_IS_VIDEO_OVERLAY(imxxoverlay->parent))
return;
gst_video_overlay_prepare_window_handle(GST_VIDEO_OVERLAY(imxxoverlay->parent));
if (required && !imxxoverlay->video_win && imxxoverlay->create_win) {
/* video_overlay is supported, but we don't have a window.. so create one */
imxxoverlay->internal_win = imxxoverlay->create_win(imxxoverlay);
gst_imx_video_overlay_set_window_handle (imxxoverlay, imxxoverlay->internal_win);
}
#endif
}
void
gst_imx_video_overlay_handle_events (ImxVideoOverlay * imxxoverlay,
gboolean handle_events)
{
GST_DEBUG ("handle events:%s", handle_events ? "TRUE" : "FALSE");
if (!imxxoverlay || !imxxoverlay->video_win)
return;
if (imxxoverlay->handle_events)
imxxoverlay->handle_events(imxxoverlay, handle_events);
}
void
gst_imx_video_overlay_expose (ImxVideoOverlay * imxxoverlay)
{
GST_DEBUG ("EXPOSE");
if (!imxxoverlay || !imxxoverlay->parent ||
!GST_IS_VIDEO_OVERLAY(imxxoverlay->parent))
return;
if (imxxoverlay->video_win) {
if (imxxoverlay->update_win_geo)
imxxoverlay->update_win_geo (imxxoverlay);
} else if (imxxoverlay->update_video_geo) {
// no window applied
imxxoverlay->update_video_geo(imxxoverlay->parent,imxxoverlay->render_rect);
}
}
gboolean
gst_imx_video_overlay_set_render_rectangle (ImxVideoOverlay * imxxoverlay,
gint x, gint y, gint width, gint height) {
GstVideoRectangle rect = {0};
gint w, h;
GST_DEBUG ("SET Render Rect : %d:%d:%d:%d", x, y, width, height);
if (!imxxoverlay || !imxxoverlay->parent ||
!GST_IS_VIDEO_OVERLAY(imxxoverlay->parent))
return FALSE;
imxxoverlay->render_rect.w = width;
imxxoverlay->render_rect.h = height;
imxxoverlay->render_rect.x = x;
imxxoverlay->render_rect.y = y;
return TRUE;
}