GStreamer C 库在 Xubuntu 上无法正常工作
GStreamer C library not working properly on Xubuntu
我正在使用 gtk3 库用 C 语言 编写程序。
我希望它能够从某个 IP 地址(本地主机)和 UDP/RTP 端口(5000)接收 h264 视频流。
为了做到这一点,我正在使用 gstreamer 来流式传输和接收视频。
我设法使用以下管道流式传输视频:
send.sh :
gst-launch-1.0 filesrc location=sample-mp4-file.mp4 ! decodebin ! x264enc ! 'video/x-h264, stream-format=(string)byte-stream' ! h264parse ! rtph264p
我设法使用以下管道在新 window 中显示视频:
receive.sh :
gst-launch-1.0 udpsrc port=5000 caps="application/x-rtp,encoding-name=H264" ! rtph264depay ! decodebin ! videoconvert ! autovideosink
至此,一切正常。
但现在我想接收流并将其显示在我的 C/GTK 程序中。我正在使用以下代码(在互联网上找到并经过修改以使其编译):
#include <stdlib.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include <gst/gst.h>
#include <glib.h>
#include <gdk/gdk.h>
#include <gst/video/videooverlay.h>
#include <gdk/gdkx.h>
static void destroy(GtkWidget *widget, gpointer data)
{
gtk_main_quit();
}
static void decodebin_pad_added(GstElement *element, GstPad *pad, gpointer data)
{
gchar *name;
GstElement *other = data;
name = gst_pad_get_name (pad);
g_print ("A new pad %s was created for %s\n", name, gst_element_get_name(element));
g_free (name);
g_print ("element %s will be linked to %s\n",
gst_element_get_name(element),
gst_element_get_name(other));
gst_element_link(element, other);
}
int main (int argc, char **argv)
{
GdkWindow *video_window_xwindow;
GtkWidget *window, *video_window;
gulong embed_xid;
GstStateChangeReturn sret;
gst_init (&argc, &argv);
gtk_init (&argc, &argv);
GstElement *pipeline, *udpsrc, *appxrtp, *depay, *decodebin, *videoconvert, *sink;
pipeline = gst_pipeline_new ("xvoverlay");
udpsrc = gst_element_factory_make ("udpsrc", NULL); g_assert(udpsrc);
//Set CAPS
g_object_set (G_OBJECT (udpsrc), "port", 5000, NULL);
GstCaps * xrtpcaps = gst_caps_from_string("application/x-rtp,encoding-name=H264");
g_object_set (udpsrc, "caps", xrtpcaps, NULL);
depay = gst_element_factory_make ("rtph264depay", NULL); g_assert(depay);
decodebin = gst_element_factory_make ("decodebin", NULL); g_assert(decodebin);
videoconvert = gst_element_factory_make ("videoconvert", NULL); g_assert(videoconvert);
sink = gst_element_factory_make ("xvimagesink", NULL); g_assert(sink);
//ADD
gst_bin_add_many (GST_BIN (pipeline), udpsrc, depay, decodebin, videoconvert, sink, NULL);
//LINK
g_assert(gst_element_link (udpsrc, depay));
g_assert(gst_element_link (depay, decodebin));
//g_assert(gst_element_link (decodebin, videoconvert));
g_signal_connect(decodebin, "pad-added", (GCallback)decodebin_pad_added, videoconvert);
g_assert(gst_element_link (videoconvert, sink));
/* prepare the ui */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (G_OBJECT (window), "delete-event", G_CALLBACK (destroy), (gpointer) pipeline);
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
gtk_window_set_title (GTK_WINDOW (window), "GstVideoOverlay Gtk+ demo");
video_window = gtk_drawing_area_new ();
gtk_container_add (GTK_CONTAINER (window), video_window);
gtk_container_set_border_width (GTK_CONTAINER (window), 2);
gtk_widget_show_all (window);
video_window_xwindow = gtk_widget_get_window (video_window);
embed_xid = GDK_WINDOW_XID (video_window_xwindow);
gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink), embed_xid);
/* run the pipeline */
sret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
if (sret == GST_STATE_CHANGE_FAILURE)
gst_element_set_state (pipeline, GST_STATE_NULL);
else
gtk_main ();
gst_object_unref (pipeline);
return 0;
}
使用以下命令编译:
gcc main.c -o main `pkg-config --cflags --libs gtk+-3.0 gstreamer-1.0 gstreamer-video-1.0`
-> 这在我的 Ubuntu (16.04) VM
上完全符合预期
-> 这在我的 Xubuntu (18.04) VM 上根本不起作用,我不明白为什么!
它编译,它 运行 没有任何错误,但是 window 一出现就消失了!
我在调试时注意到的唯一变化如下:
sret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
-> returns 2 (GST_STATE_CHANGE_ASYNC) 在 Ubuntu
-> Xubuntu
上的 returns 0 (GST_STATE_CHANGE_FAILURE)
提前感谢您的帮助,我真的被困在这个问题上,在互联网上找不到任何东西!
如果您需要任何其他信息,请告诉我,我很乐意完成我的 post。
再见,
opiDev.
这是我找到的解决方案:
更改 xvimagesink 由 ximagesink :
sink = gst_element_factory_make ("xvimagesink", NULL); g_assert(sink);
变成
sink = gst_element_factory_make ("ximagesink", NULL); g_assert(sink);
希望对遇到同样问题的你们有所帮助。
我正在使用 gtk3 库用 C 语言 编写程序。 我希望它能够从某个 IP 地址(本地主机)和 UDP/RTP 端口(5000)接收 h264 视频流。
为了做到这一点,我正在使用 gstreamer 来流式传输和接收视频。
我设法使用以下管道流式传输视频:
send.sh :
gst-launch-1.0 filesrc location=sample-mp4-file.mp4 ! decodebin ! x264enc ! 'video/x-h264, stream-format=(string)byte-stream' ! h264parse ! rtph264p
我设法使用以下管道在新 window 中显示视频:
receive.sh :
gst-launch-1.0 udpsrc port=5000 caps="application/x-rtp,encoding-name=H264" ! rtph264depay ! decodebin ! videoconvert ! autovideosink
至此,一切正常。 但现在我想接收流并将其显示在我的 C/GTK 程序中。我正在使用以下代码(在互联网上找到并经过修改以使其编译):
#include <stdlib.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include <gst/gst.h>
#include <glib.h>
#include <gdk/gdk.h>
#include <gst/video/videooverlay.h>
#include <gdk/gdkx.h>
static void destroy(GtkWidget *widget, gpointer data)
{
gtk_main_quit();
}
static void decodebin_pad_added(GstElement *element, GstPad *pad, gpointer data)
{
gchar *name;
GstElement *other = data;
name = gst_pad_get_name (pad);
g_print ("A new pad %s was created for %s\n", name, gst_element_get_name(element));
g_free (name);
g_print ("element %s will be linked to %s\n",
gst_element_get_name(element),
gst_element_get_name(other));
gst_element_link(element, other);
}
int main (int argc, char **argv)
{
GdkWindow *video_window_xwindow;
GtkWidget *window, *video_window;
gulong embed_xid;
GstStateChangeReturn sret;
gst_init (&argc, &argv);
gtk_init (&argc, &argv);
GstElement *pipeline, *udpsrc, *appxrtp, *depay, *decodebin, *videoconvert, *sink;
pipeline = gst_pipeline_new ("xvoverlay");
udpsrc = gst_element_factory_make ("udpsrc", NULL); g_assert(udpsrc);
//Set CAPS
g_object_set (G_OBJECT (udpsrc), "port", 5000, NULL);
GstCaps * xrtpcaps = gst_caps_from_string("application/x-rtp,encoding-name=H264");
g_object_set (udpsrc, "caps", xrtpcaps, NULL);
depay = gst_element_factory_make ("rtph264depay", NULL); g_assert(depay);
decodebin = gst_element_factory_make ("decodebin", NULL); g_assert(decodebin);
videoconvert = gst_element_factory_make ("videoconvert", NULL); g_assert(videoconvert);
sink = gst_element_factory_make ("xvimagesink", NULL); g_assert(sink);
//ADD
gst_bin_add_many (GST_BIN (pipeline), udpsrc, depay, decodebin, videoconvert, sink, NULL);
//LINK
g_assert(gst_element_link (udpsrc, depay));
g_assert(gst_element_link (depay, decodebin));
//g_assert(gst_element_link (decodebin, videoconvert));
g_signal_connect(decodebin, "pad-added", (GCallback)decodebin_pad_added, videoconvert);
g_assert(gst_element_link (videoconvert, sink));
/* prepare the ui */
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
g_signal_connect (G_OBJECT (window), "delete-event", G_CALLBACK (destroy), (gpointer) pipeline);
gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
gtk_window_set_title (GTK_WINDOW (window), "GstVideoOverlay Gtk+ demo");
video_window = gtk_drawing_area_new ();
gtk_container_add (GTK_CONTAINER (window), video_window);
gtk_container_set_border_width (GTK_CONTAINER (window), 2);
gtk_widget_show_all (window);
video_window_xwindow = gtk_widget_get_window (video_window);
embed_xid = GDK_WINDOW_XID (video_window_xwindow);
gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY (sink), embed_xid);
/* run the pipeline */
sret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
if (sret == GST_STATE_CHANGE_FAILURE)
gst_element_set_state (pipeline, GST_STATE_NULL);
else
gtk_main ();
gst_object_unref (pipeline);
return 0;
}
使用以下命令编译:
gcc main.c -o main `pkg-config --cflags --libs gtk+-3.0 gstreamer-1.0 gstreamer-video-1.0`
-> 这在我的 Ubuntu (16.04) VM
上完全符合预期-> 这在我的 Xubuntu (18.04) VM 上根本不起作用,我不明白为什么!
它编译,它 运行 没有任何错误,但是 window 一出现就消失了!
我在调试时注意到的唯一变化如下:
sret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
-> returns 2 (GST_STATE_CHANGE_ASYNC) 在 Ubuntu
-> Xubuntu
上的 returns 0 (GST_STATE_CHANGE_FAILURE)提前感谢您的帮助,我真的被困在这个问题上,在互联网上找不到任何东西! 如果您需要任何其他信息,请告诉我,我很乐意完成我的 post。
再见, opiDev.
这是我找到的解决方案:
更改 xvimagesink 由 ximagesink :
sink = gst_element_factory_make ("xvimagesink", NULL); g_assert(sink);
变成
sink = gst_element_factory_make ("ximagesink", NULL); g_assert(sink);
希望对遇到同样问题的你们有所帮助。