如何在 Qt 无框窗口中显示 GStreamer 视频?

Posted

技术标签:

【中文标题】如何在 Qt 无框窗口中显示 GStreamer 视频?【英文标题】:How to show the GStreamer video in Qt frameless window ? 【发布时间】:2015-06-11 05:38:59 【问题描述】:

我正在尝试在 qt 无框窗口中显示 gstreamer 视频。 我正在为其创建代码的 gstreamer 管道是: gst-launch-1.0 -v rtspsrc location=rtsp://192.168.1.15:8554/test! rtpjitterbuffer! rtph264depay! avdec_h264 ! d3dvideosink sync=false 这是我的第一个问题,请回答我。我的代码如下 我的代码适用于 qt 窗口。它正在显示它正在接收的视频 来自 rtsp 链接,但我有两个主要问题:1.当我最小化此窗口时,它会丢失输出视频并开始显示空白屏幕。 2. 我想在无框窗口中打开这个视频,但如果我这样做了,它什么也不会显示。 我使用的是 Qt-4.8.12 和 gstreamer 1.4 版.5 适用于 Windows 7 64 位。非常感谢有关这两个问题的任何帮助。提前致谢。

#include <glib.h>
#include <gst/gst.h>
#include <gst/video/videooverlay.h>

#include <QApplication>
#include <QTimer>
#include <QWidget>
#include <stdio.h>
#include "qmainwindow.h"


static void on_pad_added (GstElement *element, GstPad *pad, gpointer data);
static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data);
int main(int argc, char *argv[])

  

  if (!g_thread_supported ())
    g_thread_init (NULL);

  /* Initialize GStreamer */


  gst_init (&argc, &argv);
  QApplication app(argc, argv);
  app.connect(&app, SIGNAL(lastWindowClosed()), &app, SLOT(quit ()));

  /* Creating Elements */

  //GstElement *pipeLine = gst_pipeline_new ("xvoverlay");

 QWidget window;
 // QMainWindow window;
  window.resize(1024,768);
  WId xwinid=window.winId();
  
  GMainLoop *loop;

  GstElement *pipeLine, *rtspSrc, *rtpJitterBuffer, *rtpH264Depay, *avDecH264, *videoSink;

  rtspSrc =  gst_element_factory_make("rtspsrc", NULL);

  rtpJitterBuffer =  gst_element_factory_make("rtpjitterbuffer", NULL);

  rtpH264Depay =  gst_element_factory_make("rtph264depay", NULL);

  avDecH264 = gst_element_factory_make("avdec_h264", NULL);

  videoSink =  gst_element_factory_make("d3dvideosink", NULL);

  loop = g_main_loop_new (NULL, FALSE); 

  if (!rtspSrc || !rtpJitterBuffer || !rtpH264Depay || !avDecH264 || !videoSink) 
  
        g_printerr ("Not all elements could be created.\n");
        return -1;
  
  

  /* Set element properties */

   g_object_set( rtspSrc, "location", "rtsp://192.168.1.16:8554/test" , NULL);
   g_object_set( videoSink, "sync", false, NULL);
  
   /*Initializing Pipeline*/

   pipeLine = gst_pipeline_new ("TestPipeLine");

   if (!pipeLine) 
   
	   g_printerr ("Pipeline could not be created.");
   

   /* we add a message handler */ 
  GstBus *bus = gst_pipeline_get_bus (GST_PIPELINE (pipeLine)); 
  gst_bus_add_watch (bus, bus_call, loop); 
  gst_object_unref (bus); 


   /*Adding Components to the pipeline */

   gst_bin_add_many (GST_BIN(pipeLine),
                        rtspSrc,
						rtpJitterBuffer,
                        rtpH264Depay,
                        avDecH264,
                        videoSink,
                        NULL);
/*   if (gst_element_link (rtspSrc, rtpJitterBuffer) != TRUE) 
   
        g_printerr ("rtspSrc & rtpJitterBuffer could not be linked.\n");
        gst_object_unref (pipeLine);
        return -1;
   
*/
   

   if (gst_element_link (rtpJitterBuffer, rtpH264Depay) != TRUE) 
   
        g_printerr ("rtpJitterBuffer and rtpH264Depay could not be linked.\n");
        gst_object_unref (pipeLine);
        return -1;
   
   
   if (gst_element_link (rtpH264Depay, avDecH264) != TRUE) 
   
        g_printerr ("rtpH264Depay and avDecH264 could not be linked.\n");
        gst_object_unref (pipeLine);
        return -1;
   
   if (gst_element_link (avDecH264, videoSink) != TRUE) 
   
        g_printerr ("avDecH264 and videoSink could not be linked.\n");
        gst_object_unref (pipeLine);
        return -1;
   

   g_signal_connect (rtspSrc, "pad-added", G_CALLBACK (on_pad_added), rtpJitterBuffer);
       window.setWindowFlags(Qt::FramelessWindowHint);
  // else
	//   g_printerr("Pipeline created");zz
   gst_video_overlay_set_window_handle (GST_VIDEO_OVERLAY(videoSink), guintptr(xwinid));

   window.show();
  
   /* Set the pipeline to "playing" state*/ 
  g_print ("Now playing: %s\n", argv[1]); 
  gst_element_set_state (pipeLine, GST_STATE_PLAYING); 
    app.exec();

  /* Iterate */ 
  g_print ("Running...\n"); 
  g_main_loop_run (loop); 
  

  /* Out of the main loop, clean up nicely */ 
  g_print ("Returned, stopping playback\n"); 
  gst_element_set_state (pipeLine, GST_STATE_NULL); 
  
  g_print ("Deleting pipeline\n"); 
  gst_object_unref (GST_OBJECT (pipeLine)); 

  return 0; 



static void on_pad_added (GstElement *element, GstPad *pad, gpointer data) 
 
  GstPad *sinkpad; 
  GstElement *decoder = (GstElement *) data; 

  /* We can now link this pad with the vorbis-decoder sink pad */ 
  g_print ("Dynamic pad created, linking demuxer/decoder\n"); 

  sinkpad = gst_element_get_static_pad (decoder, "sink"); 

  gst_pad_link (pad, sinkpad); 

  gst_object_unref (sinkpad); 
 

static gboolean bus_call (GstBus *bus, GstMessage *msg, gpointer data) 
 
  GMainLoop *loop = (GMainLoop *) data; 

  switch (GST_MESSAGE_TYPE (msg))  

    case GST_MESSAGE_EOS: 
      g_print ("End of stream\n"); 
      g_main_loop_quit (loop); 
      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); 

      g_main_loop_quit (loop); 
      break; 
     
    default: 
      break; 
   

  return TRUE; 
 

【问题讨论】:

【参考方案1】:

如果您切换回使用 QWindow,这将起作用:

window.setWindowFlags (Qt::FramelessWindowHint);

我不确定如何,但我认为 QWidget 可以使用类似的东西。

【讨论】:

以上是关于如何在 Qt 无框窗口中显示 GStreamer 视频?的主要内容,如果未能解决你的问题,请参考以下文章

Qt/win:无框窗口上的 showMaximized() 重叠任务栏

在 qml 中恢复最小化的无框窗口

无框窗口出现边框

无框 pyqt/qml 窗口

集成 Gstreamer Camera Output 窗口和 Qml 窗口

如何在不使用 -webkit-app-region 的情况下在 Electron 中移动无框窗口