Библиотека GStreamer C не работает должным образом в Xubuntu

#c #video-streaming #gtk3 #gstreamer-1.0

Вопрос:

Я пишу программу на языке Си, используя библиотеку gtk3. Я хочу, чтобы он мог получать видеопоток h264 с определенного IP-адреса (localhost) и ПОРТА UDP/RTP (5000).

Для этого я использую 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

Мне удалось отобразить видео в новом окне, используя следующий конвейер :

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 %sn", name, gst_element_get_name(element));
  g_free (name);

  g_print ("element %s will be linked to %sn",
           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 (amp;argc, amp;argv);
  gtk_init (amp;argc, amp;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-видео-1.0`

-> >Это работает точно так, как ожидалось на моей виртуальной машине Ubuntu (16.04)

-> >Это вообще не работает на моей виртуальной машине Xubuntu (18.04), и я не понимаю, почему !

Он компилируется, запускается без каких-либо ошибок, но окно исчезает, как только появляется !

Единственное изменение, которое я заметил во время отладки, заключается в следующем :

sret = gst_element_set_state (pipeline, GST_STATE_PLAYING);

-> возвращает 2 (GST_STATE_CHANGE_ASYNC) в Ubuntu

-> возвращает 0 (GST_STATE_CHANGE_FAILURE) в Xubuntu

Заранее благодарю вас за вашу помощь, я действительно застрял на этом и ничего не смог найти в Интернете ! Если вам нужна какая-либо другая информация, просто дайте мне знать, я буду на поляне, чтобы завершить свой пост.

Пока, опиДев.

Ответ №1:

Вот решение, которое я нашел :

Изменение xvimagesink на ximagesink :

sink = gst_element_factory_make ("xvimagesink", NULL); g_assert(sink);

становится

sink = gst_element_factory_make ("ximagesink", NULL); g_assert(sink);

Надеюсь, это поможет некоторым из вас, столкнувшимся с той же проблемой.