2016-07-14 44 views
1

我正在嘗試編寫一個非常簡單的GTK +程序,它允許我使用Gstreamer播放視頻。以下是代碼:無法在GTK +窗口中嵌入Gstreamer視頻

#include <gtk/gtk.h> 
#include <gst/gst.h> 
#include <gst/video/videooverlay.h> 
#include <gdk/gdkwin32.h> 

static GstElement *playbin; 
static guintptr window_handle = 0; 

static void report_error(GstBus *playbin_bus, GstMessage *error_message, gpointer user_data) { 
    GError *error; 
    gchar *debug_info; 
    gst_message_parse_error(error_message, &error, &debug_info); 
    g_printerr("Error received from element %s: %s\n", GST_OBJECT_NAME(error_message->src), error->message); 
    g_printerr("Debugging information: %s\n", debug_info ? debug_info : "none"); 
    g_clear_error(&error); 
    g_free(debug_info); 
} 

static GstBusSyncReply prepare_window_handle(GstBus *bus, GstMessage *message, GstPipeline * pipeline) { 
    if (!gst_is_video_overlay_prepare_window_handle_message(message)) { 
     return GST_BUS_PASS; 
    } 
    g_assert(window_handle != 0); 
    gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(playbin), window_handle); 
    gst_message_unref(message); 
    return GST_BUS_DROP; 
} 

static void realize_video_drawing_area(GtkWidget *video_drawing_area, gpointer user_data) { 
    GdkWindow *video_window = gtk_widget_get_window(video_drawing_area); 
    if (!gdk_window_ensure_native(video_window)) { 
     g_error("Couldn't create native window needed for GstVideoOverlay!"); 
    } 
    window_handle = (guintptr) GDK_WINDOW_HWND(video_window); 
} 

static void play(GtkButton *play_button, gpointer user_data) { 
    gst_element_set_state(playbin, GST_STATE_PLAYING); 
} 

static void activate(GtkApplication *app, gpointer user_data) { 

    GtkWidget *window = gtk_application_window_new(app); 

    GtkWidget *root_pane = gtk_overlay_new(); 
    gtk_container_add(GTK_CONTAINER(window), root_pane); 

    GtkWidget *video_drawing_area = gtk_drawing_area_new(); 
    gtk_container_add(GTK_CONTAINER(root_pane), video_drawing_area); 
    gtk_widget_set_size_request(video_drawing_area, 800, 600); 
    gtk_widget_set_double_buffered(video_drawing_area, FALSE); 
    g_signal_connect(video_drawing_area, "realize", G_CALLBACK(realize_video_drawing_area), NULL); 

    GtkWidget *play_button = gtk_button_new_with_label("Play"); 
    gtk_overlay_add_overlay(GTK_OVERLAY(root_pane), play_button); 
    gtk_widget_set_halign(play_button, GTK_ALIGN_END); 
    gtk_widget_set_valign(play_button, GTK_ALIGN_END); 
    gtk_widget_set_margin_end(play_button, 20); 
    gtk_widget_set_margin_bottom(play_button, 20); 
    g_signal_connect(G_OBJECT(play_button), "clicked", G_CALLBACK(play), NULL); 

    gtk_widget_show_all(window); 

} 

int main(int argc, char **argv) { 

    gst_init(&argc, &argv); 
    playbin = gst_element_factory_make("playbin", NULL); 
    g_object_set(playbin, "uri", "http://techslides.com/demos/sample-videos/small.ogv", NULL); 
    GstBus *playbin_bus = gst_element_get_bus(playbin); 
    gst_bus_enable_sync_message_emission(playbin_bus); 
    gst_bus_set_sync_handler(playbin_bus, (GstBusSyncHandler) prepare_window_handle, NULL, NULL); 
    gst_bus_add_signal_watch(playbin_bus); 
    g_signal_connect(playbin_bus, "message::error", G_CALLBACK(report_error), NULL); 
    gst_object_unref(playbin_bus); 

    GtkApplication *app = gtk_application_new("com.techn.videotest", G_APPLICATION_FLAGS_NONE); 
    g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); 
    return g_application_run(G_APPLICATION(app), argc, argv); 

} 

每當我按「播放」,音頻播放開始,但我沒有看到視頻。如果我註釋掉該行

gst_bus_set_sync_handler(playbin_bus, (GstBusSyncHandler) prepare_window_handle, NULL, NULL); 

該視頻在單獨的D3D窗口中啓動並且沒有問題地播放。我沒有看到相關的錯誤信息在控制檯,除非以下罪狀:

(video_test.exe:5172): GStreamer-WARNING **: Failed to load plugin 'C:\msys64\mingw32\lib\gstreamer-1.0\libgstchromaprint.dll': 'C:\msys64\mingw32\lib\gstreamer-1.0\libgstchromaprint.dll': The specified module could not be found. 

(video_test.exe:5172): GStreamer-WARNING **: Failed to load plugin 'C:\msys64\mingw32\lib\gstreamer-1.0\libgstfragmented.dll': 'C:\msys64\mingw32\lib\gstreamer-1.0\libgstfragmented.dll': The specified module could not be found. 

(video_test.exe:5172): GStreamer-WARNING **: Failed to load plugin 'C:\msys64\mingw32\lib\gstreamer-1.0\libgstx264.dll': 'C:\msys64\mingw32\lib\gstreamer-1.0\libgstx264.dll': The specified module could not be found. 

(video_test.exe:5172): GStreamer-WARNING **: Failed to load plugin 'C:\msys64\mingw32\lib\gstreamer-1.0\libgstx265.dll': 'C:\msys64\mingw32\lib\gstreamer-1.0\libgstx265.dll': The specified procedure could not be found. 

(video_test.exe:5172): GLib-GObject-WARNING **: attempt to override closure->va_marshal (63c488b0) with new marshal (66925ea8) 

我編譯程序使用以下命令行:

gcc video_test.c -o video_test `pkg-config --cflags --libs gtk+-3.0 gstreamer-1.0` -lgstvideo-1.0 -Wno-deprecated-declarations 

我使用的是Windows 10的機器上MSYS2環境和MinGW 32位編譯器。我有1.0版的Gstreamer和3.0版的GTK +庫。

+0

爲什麼不使用gstreamer-video-1.0 pkg config? – nayana

+0

感謝您的提示 - 我想我以前沒有找到圖書館的名稱。不過,它沒有任何區別。 – Martynas

回答

1

我上個月在使用msys2在windows 10上集成gstreamer和gtk + 3的問題相同。

Videooverlay不起作用!改用gtksink。

嘗試:

#include <gtk/gtk.h> 
#include <gst/gst.h> 

static GstElement *playbin, *sink; 

static void play(GtkButton *play_button, gpointer user_data) { 
    gst_element_set_state(playbin, GST_STATE_PLAYING); 
} 

static void activate(GtkApplication *app, gpointer user_data) { 

    GtkWidget *window = gtk_application_window_new(app); 

    GtkWidget *root_pane = gtk_overlay_new(); 
    gtk_container_add(GTK_CONTAINER(window), root_pane); 

    GtkWidget *video_drawing_area = gtk_drawing_area_new(); 

    g_object_get (sink, "widget", &video_drawing_area, NULL); 
    gtk_widget_set_size_request(video_drawing_area, 800, 600); 
    gtk_container_add(GTK_CONTAINER(root_pane), video_drawing_area); 

    GtkWidget *play_button = gtk_button_new_with_label("Play"); 
    gtk_overlay_add_overlay(GTK_OVERLAY(root_pane), play_button); 
    gtk_widget_set_halign(play_button, GTK_ALIGN_END); 
    gtk_widget_set_valign(play_button, GTK_ALIGN_END); 
    gtk_widget_set_margin_end(play_button, 20); 
    gtk_widget_set_margin_bottom(play_button, 20); 
    g_signal_connect(G_OBJECT(play_button), "clicked", G_CALLBACK(play), NULL); 

    gtk_widget_show_all(window); 

} 

int main(int argc, char **argv) { 

    gst_init(&argc, &argv); 
    playbin = gst_element_factory_make("playbin", NULL); 
    g_object_set(playbin, "uri", "http://techslides.com/demos/sample-videos/small.ogv", NULL); 

    sink = gst_element_factory_make ("gtksink", NULL); 
    g_object_set(playbin, "video-sink", sink, NULL); 


    GtkApplication *app = gtk_application_new("com.techn.videotest", G_APPLICATION_FLAGS_NONE); 
    g_signal_connect(app, "activate", G_CALLBACK(activate), NULL); 
    return g_application_run(G_APPLICATION(app), argc, argv); 

} 

並與編譯:

gcc videotest.c -o videotest `pkg-config --cflags --libs gtk+-3.0 gstreamer-video-1.0` 

或者試試:

#include <gtk/gtk.h> 
#include <gst/gst.h> 

GstElement *pipeline, *src, *sink; 

int main (int argc, char **argv) 
{ 
    gst_init (&argc, &argv); 
    gtk_init (&argc, &argv); 

    pipeline = gst_pipeline_new ("xvoverlay"); 
    src = gst_element_factory_make ("videotestsrc", NULL); 
    sink = gst_element_factory_make ("gtksink", NULL); 

    gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); 
    gst_element_link (src, sink); 

    GtkWidget *window = gtk_window_new (GTK_WINDOW_TOPLEVEL); 
    GtkWidget *area; 
    g_object_get (sink, "widget", &area, NULL); 
    gtk_container_add (GTK_CONTAINER (window), area); 

    gtk_widget_realize(area); 

    gtk_widget_show_all (window); 
    gst_element_set_state (pipeline, GST_STATE_PLAYING); 

    gtk_main(); 
    return 0; 
} 

這SO答案使我的解決方案: https://stackoverflow.com/a/32695253

1

我剛剛發現了這個問題。在我的情況下,使用gtksink並不適合。

我發現一切正常的情況下Windows Aero主題關閉。進一步的調查指出,這是因爲'分層的'W7窗口(WS_EX_LAYERED窗口屬性)。

所以,當它從GDK源代碼如下,有一個很好的解決方案規定:如果環境變量GDK_WIN32_LAYERED設置爲0

GDK完全不使用分層的窗口。它也可以通過編程完成:

#ifdef WIN32 
Glib::setenv ("GDK_WIN32_LAYERED", "0", false) ; 
#endif