G_MODULE_EXPORT gboolean preview_draw_cb( GtkWidget *widget, cairo_t *cr, signal_user_data_t *ud) { #if defined(_ENABLE_GST) #if GST_CHECK_VERSION(1, 0, 0) if (ud->preview->live_enabled && ud->preview->state == PREVIEW_STATE_LIVE) { if (GST_STATE(ud->preview->play) >= GST_STATE_PAUSED) { GstElement *vsink; GstVideoOverlay *vover; g_object_get(ud->preview->play, "video-sink", &vsink, NULL); if (GST_IS_BIN(vsink)) vover = GST_VIDEO_OVERLAY(gst_bin_get_by_interface( GST_BIN(vsink), GST_TYPE_VIDEO_OVERLAY)); else vover = GST_VIDEO_OVERLAY(vsink); gst_video_overlay_expose(vover); // For some reason, the exposed region doesn't always get // cleaned up here. But a delayed gst_x_overlay_expose() // takes care of it. g_idle_add((GSourceFunc)delayed_expose_cb, ud); } return FALSE; } #else if (ud->preview->live_enabled && ud->preview->state == PREVIEW_STATE_LIVE) { if (GST_STATE(ud->preview->play) >= GST_STATE_PAUSED) { GstElement *vsink; GstXOverlay *xover; g_object_get(ud->preview->play, "video-sink", &vsink, NULL); if (GST_IS_BIN(vsink)) xover = GST_X_OVERLAY(gst_bin_get_by_interface( GST_BIN(vsink), GST_TYPE_X_OVERLAY)); else xover = GST_X_OVERLAY(vsink); gst_x_overlay_expose(xover); // For some reason, the exposed region doesn't always get // cleaned up here. But a delayed gst_x_overlay_expose() // takes care of it. g_idle_add((GSourceFunc)delayed_expose_cb, ud); } return FALSE; } #endif #endif if (ud->preview->pix != NULL) { _draw_pixbuf(cr, ud->preview->pix); } return FALSE; }
static GstBusSyncReply create_window (GstBus* bus, GstMessage* message, GtkWidget* widget) { GtkAllocation allocation; if (gst_gtk_handle_need_context (bus, message, NULL)) return GST_BUS_DROP; // ignore anything but 'prepare-window-handle' element messages if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) return GST_BUS_PASS; if (!gst_is_video_overlay_prepare_window_handle_message (message)) return GST_BUS_PASS; g_print ("setting window handle %p\n", widget); gst_video_overlay_set_gtk_window (GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message)), widget); gtk_widget_get_allocation (widget, &allocation); gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message)), allocation.x, allocation.y, allocation.width, allocation.height); gst_message_unref (message); return GST_BUS_DROP; }
static gboolean on_click_drawing_area(GtkWidget* widget, GdkEventButton* event, GstElement* videosink) { GtkAllocation allocation; g_print ("switch the drawing area %p\n", widget); gst_video_overlay_set_gtk_window (GST_VIDEO_OVERLAY (videosink), widget); gtk_widget_get_allocation (widget, &allocation); gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (videosink), allocation.x, allocation.y, allocation.width, allocation.height); return FALSE; }
static GstBusSyncReply create_window(GstBus *bus, GstMessage *msg, gpointer data) { preview_t *preview = (preview_t*)data; switch (GST_MESSAGE_TYPE(msg)) { case GST_MESSAGE_ELEMENT: { #if GST_CHECK_VERSION(1, 0, 0) if (!gst_is_video_overlay_prepare_window_handle_message(msg)) return GST_BUS_PASS; gst_video_overlay_set_window_handle( GST_VIDEO_OVERLAY(GST_MESSAGE_SRC(msg)), preview->xid); #else if (!gst_structure_has_name(msg->structure, "prepare-xwindow-id")) return GST_BUS_PASS; #if !defined(_WIN32) gst_x_overlay_set_xwindow_id( GST_X_OVERLAY(GST_MESSAGE_SRC(msg)), preview->xid); #else gst_directdraw_sink_set_window_id( GST_X_OVERLAY(GST_MESSAGE_SRC(msg)), preview->xid); #endif #endif gst_message_unref(msg); return GST_BUS_DROP; } break; default: { } break; } return GST_BUS_PASS; }
void GStreamerGWorld::setWindowOverlay(GstMessage* message) { GstObject* sink = GST_MESSAGE_SRC(message); #ifndef GST_API_VERSION_1 if (!GST_IS_X_OVERLAY(sink)) #else if (!GST_IS_VIDEO_OVERLAY(sink)) #endif return; if (g_object_class_find_property(G_OBJECT_GET_CLASS(sink), "force-aspect-ratio")) g_object_set(sink, "force-aspect-ratio", TRUE, NULL); if (m_videoWindow) { m_videoWindow->prepareForOverlay(message); #ifndef GST_API_VERSION_1 // gst_x_overlay_set_window_handle was introduced in -plugins-base // 0.10.31, just like the macro for checking the version. #ifdef GST_CHECK_PLUGINS_BASE_VERSION gst_x_overlay_set_window_handle(GST_X_OVERLAY(sink), m_videoWindow->videoWindowId()); #else gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(sink), m_videoWindow->videoWindowId()); #endif #else gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(sink), m_videoWindow->videoWindowId()); #endif } }
static GstBusSyncReply create_window (GstBus * bus, GstMessage * message, gpointer data) { GstGLClutterActor **actor = (GstGLClutterActor **) data; static gint count = 0; static GMutex mutex; // ignore anything but 'prepare-window-handle' element messages if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) return GST_BUS_PASS; if (!gst_is_video_overlay_prepare_window_handle_message (message)) return GST_BUS_PASS; g_mutex_lock (&mutex); if (count < N_ACTORS) { g_message ("adding actor %d", count); gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message)), actor[count]->win); clutter_threads_add_idle ((GSourceFunc) create_actor, actor[count]); count++; } g_mutex_unlock (&mutex); gst_message_unref (message); return GST_BUS_DROP; }
/**************************************************** * Video Overlay vmethods implementation * ****************************************************/ static void _overlay_expose (GstVideoOverlay * overlay) { GESPipeline *pipeline = GES_PIPELINE (overlay); gst_video_overlay_expose (GST_VIDEO_OVERLAY (pipeline->priv->playsink)); }
static gboolean expose_cb(GtkWidget* widget, cairo_t *cr, GstElement* videosink) { g_print ("expose %p\n", widget); g_print ("event mask: 0x%x, button_press 0x%x\n", gtk_widget_get_events (widget), GDK_BUTTON_PRESS_MASK); gst_video_overlay_expose (GST_VIDEO_OVERLAY (videosink)); return FALSE; }
static void _overlay_handle_events (GstVideoOverlay * overlay, gboolean handle_events) { GESPipeline *pipeline = GES_PIPELINE (overlay); gst_video_overlay_handle_events (GST_VIDEO_OVERLAY (pipeline->priv->playsink), handle_events); }
static void _overlay_set_window_handle (GstVideoOverlay * overlay, guintptr handle) { GESPipeline *pipeline = GES_PIPELINE (overlay); gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (pipeline-> priv->playsink), handle); }
static gboolean on_click_drawing_area(GtkWidget* widget, GdkEventButton* event, GstElement* videosink) { GtkAllocation allocation; GtkWidget *parent = gtk_widget_get_parent (widget); g_print ("switch the drawing area %p\n", widget); gst_video_overlay_set_gtk_window (GST_VIDEO_OVERLAY (videosink), widget); gtk_widget_get_allocation (widget, &allocation); gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (videosink), allocation.x, allocation.y, allocation.width, allocation.height); /* XXX: required on wayland as changing the window handle (subsurface) * requires a wl_surface::commit from the parent */ if (parent) gtk_widget_queue_draw (parent); return FALSE; }
static void _overlay_set_render_rectangle (GstVideoOverlay * overlay, gint x, gint y, gint width, gint height) { GESPipeline *pipeline = GES_PIPELINE (overlay); gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (pipeline->priv-> playsink), x, y, width, height); }
int tsmf_window_create(TSMFGstreamerDecoder* decoder) { struct X11Handle* hdl; if (decoder->media_type != TSMF_MAJOR_TYPE_VIDEO) { decoder->ready = TRUE; return -3; } else { #if GST_VERSION_MAJOR > 0 GstVideoOverlay *overlay = GST_VIDEO_OVERLAY(decoder->outsink); #else GstXOverlay *overlay = GST_X_OVERLAY(decoder->outsink); #endif if (!decoder) return -1; if (!decoder->platform) return -1; hdl = (struct X11Handle*) decoder->platform; if (!hdl->subwin) { int event, error; hdl->subwin = XCreateSimpleWindow(hdl->disp, *(int *)hdl->xfwin, 0, 0, 1, 1, 0, 0, 0); if (!hdl->subwin) { WLog_ERR(TAG, "Could not create subwindow!"); } XMapWindow(hdl->disp, hdl->subwin); XSync(hdl->disp, FALSE); #if GST_VERSION_MAJOR > 0 gst_video_overlay_set_window_handle(overlay, hdl->subwin); #else gst_x_overlay_set_window_handle(overlay, hdl->subwin); #endif decoder->ready = TRUE; #if defined(WITH_XEXT) hdl->has_shape = XShapeQueryExtension(hdl->disp, &event, &error); #endif } #if GST_VERSION_MAJOR > 0 gst_video_overlay_handle_events(overlay, TRUE); #else gst_x_overlay_handle_events(overlay, TRUE); #endif return 0; } }
static gboolean resize_cb (GtkWidget * widget, GdkEvent * event, gpointer sink) { GtkAllocation allocation; gtk_widget_get_allocation (widget, &allocation); gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (sink), allocation.x, allocation.y, allocation.width, allocation.height); return FALSE; }
static gboolean bus_call (GstBus *bus,GstMessage *msg, gpointer data) { if (gst_is_video_overlay_prepare_window_handle_message (msg)) { if (0 != g_video_xid) { GstVideoOverlay *overlay; // GST_MESSAGE_SRC (message) will be the video sink element overlay = GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (msg)); gst_video_overlay_set_window_handle (overlay, g_video_xid); } else { g_warning ("Should have obtained video_window_handle by now!"); } } switch (GST_MESSAGE_TYPE (msg)) { case GST_MESSAGE_EOS: g_print ("####################### Stream Ends\n"); gtk_main_quit(); break; case GST_MESSAGE_ERROR: { gchar *debug; GError *error; gst_message_parse_error (msg, &error, &debug); g_free (debug); g_printerr ("####################### Error: %s\n", error->message); g_error_free (error); gtk_main_quit(); break; } case GST_MESSAGE_STATE_CHANGED: { GstState oldState; GstState newState; GstState pendingState; gst_message_parse_state_changed(msg, &oldState, &newState, &pendingState); g_printf("####################### oldState:%d, newState:%d, pendingState:%d!\n", oldState, newState, pendingState); break; } case GST_MESSAGE_STREAM_STATUS: { GstStreamStatusType statusType; GstElement* owner = NULL; gst_message_parse_stream_status(msg, &statusType, &owner); g_printf("####################### statusType:%d, owner:%p!\n", statusType, owner); break; } default: break; } return TRUE; }
static gboolean gst_switch_ptz_prepare (GstSwitchPTZ * ptz) { GstWorker *worker = GST_WORKER (ptz); GstElement *sink = gst_worker_get_element_unlocked (worker, "sink"); gulong handle = GDK_WINDOW_XID (gtk_widget_get_window (ptz->video_view)); g_return_val_if_fail (GST_IS_ELEMENT (sink), FALSE); gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink), handle); gst_object_unref (sink); return TRUE; }
/* TODO: use video overlay in the proper way (like suggested in docs, see gtkvideooverlay example) */ static gboolean expose_cb (GtkWidget * widget, gpointer data) { GstVideoOverlay *overlay = GST_VIDEO_OVERLAY (gst_bin_get_by_interface (GST_BIN (data), GST_TYPE_VIDEO_OVERLAY)); gst_video_overlay_set_gtk_window (overlay, widget); return FALSE; }
bool CGstPlayback::SetWindow(void *window) { returnb_assert(m_playbin); g_print("%s, get GST_TYPE_VIDEO_OVERLAY", __func__); m_video_sink = gst_bin_get_by_interface(GST_BIN(m_playbin), GST_TYPE_VIDEO_OVERLAY); returnb_assert(m_video_sink); g_print("%s, set native window=(%x)", __func__, window); gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (m_video_sink), (guintptr)window); return true; }
static GstBusSyncReply bus_sync_handler(GstBus *bus, GstMessage *msg, gpointer data) { if (!gst_is_video_overlay_prepare_window_handle_message(msg)) return GST_BUS_PASS; guintptr video_window_handle = gui_get_video_window_handle(); g_assert(video_window_handle != 0); // GST_MESSAGE_SRC (message) will be the video sink element. video_window_overlay = GST_VIDEO_OVERLAY(GST_MESSAGE_SRC(msg)); gst_video_overlay_set_window_handle(video_window_overlay, video_window_handle); int x, y, w, h; gui_get_render_rectangle(&x, &y, &w, &h); gst_video_overlay_set_render_rectangle(video_window_overlay, x, y, w, h); return GST_BUS_DROP; }
G_MODULE_EXPORT gboolean delayed_expose_cb(signal_user_data_t *ud) { GstElement *vsink; GstVideoOverlay *vover; if (!ud->preview->live_enabled) return FALSE; g_object_get(ud->preview->play, "video-sink", &vsink, NULL); if (vsink == NULL) return FALSE; if (GST_IS_BIN(vsink)) vover = GST_VIDEO_OVERLAY(gst_bin_get_by_interface( GST_BIN(vsink), GST_TYPE_VIDEO_OVERLAY)); else vover = GST_VIDEO_OVERLAY(vsink); gst_video_overlay_expose(vover); // This function is initiated by g_idle_add. Must return false // so that it is not called again return FALSE; }
static void gst_native_surface_finalize (JNIEnv *env, jobject thiz) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); if (!data) return; GST_DEBUG ("Releasing Native Window %p", data->native_window); if (data->video_sink) { gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (data->video_sink), (guintptr)NULL); gst_element_set_state (data->pipeline, GST_STATE_READY); } ANativeWindow_release (data->native_window); data->native_window = NULL; data->initialized = FALSE; }
static GstBusSyncReply gst_sync_watch (GstBus *bus, GstMessage *message, gpointer data) { gstPlay *play = (gstPlay *)data; if (play == NULL) return FALSE; if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT) { if (gst_is_video_overlay_prepare_window_handle_message(message)) { play->overlay = GST_VIDEO_OVERLAY (GST_MESSAGE_SRC (message)); gst_video_overlay_set_window_handle (play->overlay, play->xid); } } return TRUE; }
static void gst_native_surface_init (JNIEnv *env, jobject thiz, jobject surface) { CustomData *data = GET_CUSTOM_DATA (env, thiz, custom_data_field_id); if (!data) return; ANativeWindow *new_native_window = ANativeWindow_fromSurface(env, surface); GST_DEBUG ("Received surface %p (native window %p)", surface, new_native_window); if (data->native_window) { ANativeWindow_release (data->native_window); if (data->native_window == new_native_window) { GST_DEBUG ("New native window is the same as the previous one %p", data->native_window); if (data->video_sink) { gst_video_overlay_expose(GST_VIDEO_OVERLAY (data->video_sink)); gst_video_overlay_expose(GST_VIDEO_OVERLAY (data->video_sink)); } return; } else { GST_DEBUG ("Released previous native window %p", data->native_window); data->initialized = FALSE; } } data->native_window = new_native_window; check_initialization_complete (data); }
/** * @brief * @param disp The GstVideoDisp instance. * @memberof GstVideoDisp */ static gboolean gst_video_disp_prepare (GstVideoDisp * disp) { GstWorker *worker = GST_WORKER (disp); GstElement *sink = gst_worker_get_element_unlocked (worker, "sink"); g_return_val_if_fail (GST_IS_ELEMENT (sink), FALSE); gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink), disp->handle); gst_object_unref (sink); //INFO ("prepared display video on %ld", disp->handle); return TRUE; }
static void gst_gl_sink_bin_overlay_expose (GstVideoOverlay * overlay) { GstGLSinkBin *self = GST_GL_SINK_BIN (overlay); GstVideoOverlay *overlay_element = NULL; overlay_element = GST_VIDEO_OVERLAY (gst_bin_get_by_interface (GST_BIN (self), GST_TYPE_VIDEO_OVERLAY)); if (overlay_element) { gst_video_overlay_expose (overlay_element); gst_object_unref (overlay_element); } }
/* Check if all conditions are met to report GStreamer as initialized. * These conditions will change depending on the application */ static void check_initialization_complete (CustomData *data) { JNIEnv *env = get_jni_env (); if (!data->initialized && data->native_window && data->main_loop) { GST_DEBUG ("Initialization complete, notifying application. native_window:%p main_loop:%p", data->native_window, data->main_loop); /* The main loop is running and we received a native window, inform the sink about it */ gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (data->video_sink), (guintptr)data->native_window); (*env)->CallVoidMethod (env, data->app, on_gstreamer_initialized_method_id); if ((*env)->ExceptionCheck (env)) { GST_ERROR ("Failed to call Java method"); (*env)->ExceptionClear (env); } data->initialized = TRUE; } }
static void gst_gl_sink_bin_overlay_set_render_rectangle (GstVideoOverlay * overlay, gint x, gint y, gint width, gint height) { GstGLSinkBin *self = GST_GL_SINK_BIN (overlay); GstVideoOverlay *overlay_element = NULL; overlay_element = GST_VIDEO_OVERLAY (gst_bin_get_by_interface (GST_BIN (self), GST_TYPE_VIDEO_OVERLAY)); if (overlay_element) { gst_video_overlay_set_render_rectangle (overlay_element, x, y, width, height); gst_object_unref (overlay_element); } }
static gboolean resize_cb (GtkWidget * widget, GdkEvent * event, gpointer sink) { GtkAllocation allocation; gint scale = 1; #if GTK_CHECK_VERSION(3, 10, 0) scale = gtk_widget_get_scale_factor (widget); #endif gtk_widget_get_allocation (widget, &allocation); gst_video_overlay_set_render_rectangle (GST_VIDEO_OVERLAY (sink), allocation.x * scale, allocation.y * scale, allocation.width * scale, allocation.height * scale); return G_SOURCE_CONTINUE; }
/* This function is called when the GUI toolkit creates the physical window that will hold the video. * At this point we can retrieve its handler (which has a different meaning depending on the windowing system) * and pass it to GStreamer through the XOverlay interface. */ static void realize_cb (GtkWidget *widget, CustomData *data) { GdkWindow *window = gtk_widget_get_window (widget); guintptr window_handle; if (!gdk_window_ensure_native (window)) g_error ("Couldn't create native window needed for GstXOverlay!"); /* Retrieve window handler from GDK */ #if defined (GDK_WINDOWING_WIN32) window_handle = (guintptr)GDK_WINDOW_HWND (window); #elif defined (GDK_WINDOWING_QUARTZ) window_handle = gdk_quartz_window_get_nsview (window); #elif defined (GDK_WINDOWING_X11) window_handle = GDK_WINDOW_XID (window); #endif /* Pass it to playbin, which implements XOverlay and will forward it to the video sink */ gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (data->playbin), window_handle); }
static GstBusSyncReply bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data) { GtkWidget *ui_drawing; if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) return GST_BUS_PASS; if (!gst_message_has_name (message, "prepare-window-handle")) return GST_BUS_PASS; /* FIXME: make sure to get XID in main thread */ ui_drawing = GTK_WIDGET (gtk_builder_get_object (builder, "viewfinderArea")); gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (message->src), GDK_WINDOW_XID (gtk_widget_get_window (ui_drawing))); gst_message_unref (message); return GST_BUS_DROP; }