我在寻找任何关于这个问题的提示:
我有一个运行嵌入式的i.MX6设备和一个运行在屏幕上的基于Qt5 Widget的应用程序。我还有一个定制的SDK,我不能更改它,它只限于QT5.5.1库,我需要在iMX上构建它。因为它是嵌入式的,所以我不能在上面使用'dpkg‘或'ldconfig’之类的命令。
目标:我的目标是在QT5.5应用程序中添加一个功能,在不同的小部件中显示来自多个摄像机的实时视频流(大约4到6个)。它需要硬件加速。
没有摄像头进行测试,我使用VLC来流3个视频(它们在本地运行),我的应用程序通过RTSP读取这些流。
我尝试了什么:,我一直在学习Qt和Gstreamer,以找到一个解决方案。我尝试了许多不同的东西,使用了所有已经安装在屏幕上的有前途的视频接收器,目前正在尝试基于的解决方案。
我制作了一个用于测试的简单Qt小部件应用程序,当我在我的x86系统(Ubuntu16.04)上运行它时,它运行得很好。正如您在这些截图中所看到的:
表1

表2

流很好地集成在单独的选项卡中,我可以通过单击选项卡在它们之间切换。然而,在目标设备上运行相同的应用程序(使用不同的接收器,例如imxipuvideosink)会显示“在”窗口上方和彼此之上的所有流。它们没有嵌入到Tab小部件中,可能是因为设备不能依赖X。
为了将流嵌入到小部件中,我尝试了许多不同的方法,下面是几种方法:
QGlib::connect(sink, "update", widget, &QWidget::update);,但是它抛出了一个“不匹配函数调用.”错误,并将更新槽标记为"<未解析的重载函数类型>“。:connect也是这样。我可能在这里做错了什么。rtspsrc location=rtsp://10.0.1.1:8554/stream ! videoparse width=400 height=300 format=i420 ! videoconvert ! qwidget5videosink我得到了一个输出,但是它在x86上被破坏了,并且目标设备没有安装视频插件。由于我一定要使用QWidget应用程序,所以使用QML的唯一方法是在基于小部件的应用程序中创建一个QQuickWidget。我将这个QQuickWidget的源代码设置为一个简单的.qml文件,并尝试如下:
gstreamer1.0-qt5中可用,所以我需要在嵌入式设备上安装它,这在技术上是可能的,但很困难,也很危险。我知道这是非常有限的,但由于这是嵌入式的,我想保持安装更多的软件包和库作为最后手段。而且,如果我必须安装一些东西,我应该按照什么顺序来尝试它们,从最有希望的到不太有希望的?任何建议或链接的例子是非常感谢的,我正在寻找一般的指导,看看我错过了什么,或知道我应该如何处理这个问题。
编辑: --我使用qwidgetvideosink搜索了更多内容,并找到了一种使其工作的方法。下面的管道是我发现的最好的结果:rtspsrc location=rtsp://10.0.1.1:8554/stream ! decodebin ! imxg2dvideotransform ! clockoverlay ! qwidget5videosink sync=false。不幸的是,这里的性能与使用MediaPlayer时一样糟糕,如果不是更糟的话。但是,至少通过这种方法,我可以定制管道。我尝试了几种不同的方法,但找不到更好的解决办法。我也想不出用更精确的插件代替解码的方法。在这方面的任何帮助也将受到感谢。
发布于 2021-07-09 13:32:04
我想分享一下我们在这个特殊问题上所寻求的解决方案,以防它能帮助任何有类似问题的人。
在失败了所有需要缺失librairies的解决方案(QtMultimedia、qmlgl接收器等)之后,或者只是由于未知的原因没有工作,我了解了帧缓冲器 --就我而言,它基本上只是GPU的层--以及如何在这种情况下使用它们。
事实证明,我一直在使用的linux嵌入式设备有3个帧缓冲区,它允许我们将应用程序分成一个用于视频流播放的“后台”帧缓冲区,以及一个用于覆盖显示的“前台”帧缓冲区。当我们希望背景中的视频变得可见时,覆盖层( Qt MainWindow)需要是透明的。为此,我们使用alpha混合和一个颜色键。
在测试了这个解决方案的各个部分之后,我们得到了一个启动两个管道的应用程序(因为我希望一次在屏幕上显示两个摄像头,每个摄像头都可以使用一个输入选择器切换到另一个流)。例如,管道结构如下所示:
input-selector name=selector ! decodebin ! textoverlay name=text0 ! queue !
imxg2dvideosink framebuffer=/dev/fb0 name=end0 force-aspect-ratio=false
window-x-coord=0 window-y-coord=0 window-width=512 window-height=473
rtspsrc location=rtsp://10.0.1.1:8554/stream name=src0 ! queue name=qs_0 ! selector.sink_0
rtspsrc location=rtsp://10.0.1.1:8556/stream name=src2 ! queue name=qs_2 ! selector.sink_1
rtspsrc location=rtsp://10.0.1.1:8558/stream name=src4 ! queue name=qs_4 ! selector.sink_2我们将framebuffer属性传递给接收器,以便它将视频发送到framebuffer 0,而应用程序本身则显示在显示在fb0顶部的framebuffer 1上。为了实现这一点,我们只需在调用应用程序可执行文件之前将QT_QPA_EGLFS_FB env变量设置为/dev/fb1,因为我们的设备使用插件运行。
对于alpha混合和颜色键控部分,我们必须在应用程序中这样做:
#include <fcntl.h>
#include <linux/mxcfb.h>
#include <sys/ioctl.h>
...
// Read overlay framebuffer fb1
int fb = 0;
fb = open("/dev/fb1", O_RDWR);
if (fb < 0)
qWarning() << "Error, framebuffer cannot be opened";
// Enable alpha
struct mxcfb_gbl_alpha alphaStruct;
alphaStruct.enable = 1;
alphaStruct.alpha = 255;
if (ioctl(fb, MXCFB_SET_GBL_ALPHA, &alphaStruct) < 0)
qWarning() << "Error, framebuffer alpha cannot be set";
// Set color key to pure blue
struct mxcfb_color_key colorKeyStruct;
guint32 colorKeyValue = g_ascii_strtoull("0x0000FF", NULL, 16);
colorKeyStruct.color_key = colorKeyValue;
colorKeyStruct.enable = 1;
if (ioctl(fb, MXCFB_SET_CLR_KEY, &colorKeyStruct) < 0)
qWarning() << "Error, framebuffer color key cannot be set";
...基本上,这将打开覆盖应用程序正在运行的框架缓冲区,在其上启用alpha,然后将一个颜色(蓝色)设置为透明颜色。因此,每个像素与这个确切的颜色值将显示的视频运行在背景中。
所以现在我们有了一个应用程序,它可以播放视频流和使用HW加速视频接收器的定制Gstreamer管道。
发布于 2021-06-23 20:04:02
你想要的是墨镜。这个人有一个预言家,可以传递一个窗口id。您可以基于:https://thiblahute.github.io/GStreamer-doc/gst-plugins-base-video-1.0/videooverlay.html?gi-language=c编写代码。
有关于gtk+和qt的例子。现在我看一下它,我在qt中使用了gtk+方式(与总线同步处理程序).我是用imxeglviv接收器在imx6上这样做的
https://stackoverflow.com/questions/67054782
复制相似问题