热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

使用qtgstreamer与Qt和RaspberryPi-UsingqtgstreamerwithQtandRaspberryPi

IamhavingaproblemwithdecodingavideostreamfrommyraspberrypitoalaptopwithaQtGUI.我

I am having a problem with decoding a video stream from my raspberry pi to a laptop with a Qt GUI.

我有一个问题,从我的覆盆子pi解码视频流到具有Qt GUI的笔记本电脑。

My pipeline for the pi is (using the adafruit raspberry pi camera):

我的pi管道是(使用adafruit覆盆子pi相机):

raspivid -t 999999 -h 480 -w 640 -fps 25 -hf -b 2000000 -o - | gst-launch-1.0 -v fdsrc ! h264parse !  rtph264pay config-interval=1 pt=96 ! gdppay ! tcpserversink host=10.0.0.128 port=5000 

Just using a viewer on the laptop with the pipeline:

只需在笔记本电脑上使用带有管道的查看器:

gst-launch-1.0 -v tcpclientsrc host=10.0.0.128 port=5000  ! gdpdepay !  rtph264depay ! avdec_h264 ! videoconvert ! autovideosink sync=false 

Gives very nice color video at a pretty decent rate, although I didn't measure the frame rate.

虽然我没有测量帧速率,但是以相当不错的速度提供了非常漂亮的彩色视频。

When I use qtgstreamer in my GUI application (with a source width=640,height=480 and I assume an 8-bit RGB image) I am getting the buffer size in the below code of 460800, and I expect it to be 921600. If I use the QImage::Format_RGB888 the program will crash because the image buffer is too small. If I use QImage::Format_Index8 it will run fine, show video in my GUI and all but is Black and White. Anyone have any ideas? Here is my relevant code:

当我在我的GUI应用程序中使用qtgstreamer时(源宽度= 640,高度= 480,我假设一个8位RGB图像)我在下面的代码460800中得到缓冲区大小,我希望它是921600。如果我使用QImage :: Format_RGB888,程序将崩溃,因为图像缓冲区太小。如果我使用QImage :: Format_Index8它将运行正常,在我的GUI中显示视频,但除了黑白之外。有人有主意吗?这是我的相关代码:

bool CameraStreamer::initStreamer()
{
    gst_init (NULL, NULL);
    //gst-launch-1.0 -v tcpclientsrc host=10.0.0.128 port=5000  ! gdpdepay !  rtph264depay ! avdec_h264 ! videoconvert ! autovideosink sync=false
    pipeline = gst_pipeline_new("Camera");
    source                  = gst_element_factory_make ("tcpclientsrc",           "cam-source");
    depay                   = gst_element_factory_make("gdpdepay",      "depay");
    rtpdepay                = gst_element_factory_make("rtph264depay","rtp-depay");
    decoder                 = gst_element_factory_make ("avdec_h264",          "videodecoder");
    videocOnvert= gst_element_factory_make("videoconvert","video-convert");
    sink                    = gst_element_factory_make ("appsink",          "video-output");
    if (!pipeline || !source  || !depay || !rtpdepay || !decoder || !videoconvert || !sink ) {
      qDebug() <<"One element could not be created. Exiting.\n";
      return false;
    }
    callbacks.eos = NULL;
    callbacks.new_sample = newBufferCallback;
    callbacks.new_preroll = NULL;
    gst_app_sink_set_callbacks((GstAppSink *) sink, &callbacks, this, NULL);
    g_object_set (G_OBJECT(source), "port", 5001, NULL);
    g_object_set (G_OBJECT(source),"host","10.0.0.128",NULL);
    gst_bin_add_many (GST_BIN (pipeline),
                      source, depay,rtpdepay,decoder, videoconvert,sink, NULL);
    if (!gst_element_link_many (source, depay,rtpdepay,decoder, videoconvert,sink, NULL))
        g_warning ("Main pipeline link Fail...");
    ret = gst_element_set_state (pipeline, GST_STATE_PLAYING);
    if (ret == GST_STATE_CHANGE_FAILURE)
    {
        g_printerr ("Unable to set the pipeline to the playing state.");
        gst_object_unref (pipeline);
        return false;
    }
    return true;
}

GstFlowReturn CameraStreamer::newBufferCallback(GstAppSink *app_sink, void *obj)
{
    if(app_sink == NULL)
    {
        qDebug() <<"app_sink is NULL";
        return GST_FLOW_ERROR;
    }
    GstSample* sample = gst_app_sink_pull_sample(app_sink);
    if(!sample)
    {
        qDebug() <<"Error retreiving buffer...";
        return GST_FLOW_ERROR;
    }
    GstCaps* caps = gst_sample_get_caps (sample);
    if (!caps) {
        qDebug() <<"could not get snapshot format\n";
        exit (-1);
    }
    gint width, height;
    GstStructure* s = gst_caps_get_structure (caps, 0);
    int res = gst_structure_get_int (s, "width", &width)
        | gst_structure_get_int (s, "height", &height);
    if (!res) {
        qDebug() <<"could not get snapshot dimension\n";
        exit (-1);
    }
    GstMapInfo map;

    GstBuffer *buffer = gst_sample_get_buffer (sample);
    qDebug() <<"size: " <emitNewImage(img);
    gst_buffer_unmap (buffer, &map);
    gst_sample_unref (sample);
    return GST_FLOW_OK;
}

2 个解决方案

#1


0  

If that's I420, then the layout is:

如果那是I420,那么布局是:

460800 = 640 * 480 + 320 * 240 + 320 * 240

Luma plain Y is 640 * 480, chroma plains U and V are both 320 * 240. So the UV plains have a smaller resolution, take it into account when looping over these arrays.

Luma平原Y为640 * 480,色度平原U和V均为320 * 240.因此UV平面具有较小的分辨率,在环绕这些阵列时将其考虑在内。

Color conversion formula from the Wikipedia:

维基百科的颜色转换公式:

R = Y + 1.140 * V
G = Y - 0.395 * U - 0.581 * V
B = Y + 2.032 * U

#2


0  

So after a ridiculous amount of time and googling, I found the answer. I ended up using opencv to do the actual color conversion. Here is my method (continuing from above):

经过一段荒谬的时间和谷歌搜索后,我找到了答案。我最终使用opencv进行实际的颜色转换。这是我的方法(从上面继续):

GstBuffer *buffer = gst_sample_get_buffer (sample);
gst_buffer_map (buffer, &map, GST_MAP_READ);
cv::Mat temp_mat = cv::Mat(cv::Size(width, height+height/2), CV_8UC1, (char*)map.data);
cv::Mat result(height,width,3);
cv::cvtColor(temp_mat,result,CV_YUV2RGB_I420,3);
QImage rgb(result.size().width,result.size().height,QImage::Format_RGB888);
memcpy(rgb.scanLine(0), (unsigned char*)result.data, rgb.width() * rgb.height() * result.channels());
((CameraStreamer*)obj)->emitNewImage(rgb);
gst_buffer_unmap (buffer, &map);
gst_sample_unref (sample);

I will post more information on my application git repo, but I thought this may help other people.

我将在我的应用程序git repo上发布更多信息,但我认为这可能对其他人有所帮助。

Here's the link: camera streamer example

这是链接:相机流光示例


推荐阅读
  • 本文讨论了如何使用GStreamer来删除H264格式视频文件中的中间部分,而不需要进行重编码。作者提出了使用gst_element_seek(...)函数来实现这个目标的思路,并提到遇到了一个解决不了的BUG。文章还列举了8个解决方案,希望能够得到更好的思路。 ... [详细]
  • 如何自行分析定位SAP BSP错误
    The“BSPtag”Imentionedintheblogtitlemeansforexamplethetagchtmlb:configCelleratorbelowwhichi ... [详细]
  • 本文介绍了[从头学数学]中第101节关于比例的相关问题的研究和修炼过程。主要内容包括[机器小伟]和[工程师阿伟]一起研究比例的相关问题,并给出了一个求比例的函数scale的实现。 ... [详细]
  • 本文介绍了在Linux下安装Perl的步骤,并提供了一个简单的Perl程序示例。同时,还展示了运行该程序的结果。 ... [详细]
  • C语言常量与变量的深入理解及其影响
    本文深入讲解了C语言中常量与变量的概念及其深入实质,强调了对常量和变量的理解对于学习指针等后续内容的重要性。详细介绍了常量的分类和特点,以及变量的定义和分类。同时指出了常量和变量在程序中的作用及其对内存空间的影响,类似于const关键字的只读属性。此外,还提及了常量和变量在实际应用中可能出现的问题,如段错误和野指针。 ... [详细]
  • 本文介绍了解决java开源项目apache commons email简单使用报错的方法,包括使用正确的JAR包和正确的代码配置,以及相关参数的设置。详细介绍了如何使用apache commons email发送邮件。 ... [详细]
  • 本文介绍了关于Java异常的八大常见问题,包括异常管理的最佳做法、在try块中定义的变量不能用于catch或finally的原因以及为什么Double.parseDouble(null)和Integer.parseInt(null)会抛出不同的异常。同时指出这些问题是由于不同的开发人员开发所导致的,不值得过多思考。 ... [详细]
  • 使用freemaker生成Java代码的步骤及示例代码
    本文介绍了使用freemaker这个jar包生成Java代码的步骤,通过提前编辑好的模板,可以避免写重复代码。首先需要在springboot的pom.xml文件中加入freemaker的依赖包。然后编写模板,定义要生成的Java类的属性和方法。最后编写生成代码的类,通过加载模板文件和数据模型,生成Java代码文件。本文提供了示例代码,并展示了文件目录结构。 ... [详细]
  • 本文介绍了在实现了System.Collections.Generic.IDictionary接口的泛型字典类中如何使用foreach循环来枚举字典中的键值对。同时还讨论了非泛型字典类和泛型字典类在foreach循环中使用的不同类型,以及使用KeyValuePair类型在foreach循环中枚举泛型字典类的优势。阅读本文可以帮助您更好地理解泛型字典类的使用和性能优化。 ... [详细]
  • Matlab 中的一些小技巧(2)
    1.Ctrl+D打开子程序  在MATLAB的Editor中,将输入光标放到一个子程序名称中间,然后按Ctrl+D可以打开该子函数的m文件。当然这个子程序要在路径列表中(或在当前工作路径中)。实际上 ... [详细]
  • pytorch Dropout过拟合的操作
    这篇文章主要介绍了pytorchDropout过拟合的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完 ... [详细]
  • 【Vue基础】监听属性watch
    Vue监听属性是watch,我们可以通过watch来响应数据的变化。代码示例: ... [详细]
  • java多线程获取线程返回结果
    我们在使用java多线程编写相关业务代码时,往往有这样一种情况,某个线程依赖于其他线程执行结果。也就是说,我们需要在一个线程中获取另一个线程的信息。可以分为两种情况,一种是轮询,一 ... [详细]
  • [置顶]        C++类的构造函数与析构函数的调用顺序
    1构造函数的调用顺序[1]构造函数按此顺序执行工作:按声明顺序调用基类和成员构造函数。如果类派生自虚拟基类,则会将对象的虚拟基指针初始化。如果类具有或继承了虚函数,则会将对象的虚函数指针初始化。 ... [详细]
  • 数据结构-图详解(图基本概念、图的存储结构及C++实现)
    本文主要介绍关于数据结构,c++,图论的知识点,对【数据结构-图详解(图基本概念、图的存储结构及C++实现)】和【数据结构图的存储结构代码】有兴趣的朋友可以看下由【NUC_Dodamce】投稿的技术文 ... [详细]
author-avatar
lily0407520
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有