首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Qt和Raspberry Pi在qtgstreamer中的应用

Qt和Raspberry Pi在qtgstreamer中的应用
EN

Stack Overflow用户
提问于 2017-09-28 11:23:54
回答 2查看 954关注 0票数 0

我在解码从raspberry pi到带有Qt的笔记本电脑的视频流时遇到了问题。

我的pi管道是(使用adafruit raspberry pi摄像机):

代码语言:javascript
复制
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 

只需在笔记本上使用查看器和管道:

代码语言:javascript
复制
gst-launch-1.0 -v tcpclientsrc host=10.0.0.128 port=5000  ! gdpdepay !  rtph264depay ! avdec_h264 ! videoconvert ! autovideosink sync=false 

提供非常好的彩色视频,以一个相当不错的速度,虽然我没有测量的帧率。

当我在我的图形用户界面应用程序中使用qtgstreamer (有一个源width=640、height=480和我假设一个8位RGB映像)时,我在下面的代码中得到了460800的缓冲区大小,并且我希望它是921600。如果我使用QImage::Format_RGB888,程序会崩溃,因为图像缓冲区太小了。如果我使用QImage::Format_Index8,它将运行良好,显示视频在我的图形用户界面和一切,但是黑色和白色。有人有什么想法吗?这是我的相关代码:

代码语言:javascript
复制
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: " << gst_buffer_get_size(buffer);
    gst_buffer_map (buffer, &map, GST_MAP_READ);
    QImage img(map.data,width,height, QImage::Format_RGB888);
    img = img.copy();
    ((CameraStreamer*)obj)->emitNewImage(img);
    gst_buffer_unmap (buffer, &map);
    gst_sample_unref (sample);
    return GST_FLOW_OK;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2017-10-06 17:27:53

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

代码语言:javascript
复制
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);

我会发布更多的信息,我的申请git回购,但我认为这可能有助于其他人。

下面是链接:相机流光实例

票数 0
EN

Stack Overflow用户

发布于 2017-10-02 07:16:33

如果是I420,那么布局是:

代码语言:javascript
复制
460800 = 640 * 480 + 320 * 240 + 320 * 240

卢马平原Y为640 * 480,色度平原U和V均为320 * 240。所以UV平原的分辨率较小,在这些阵列上循环时要考虑到这一点。

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

代码语言:javascript
复制
R = Y + 1.140 * V
G = Y - 0.395 * U - 0.581 * V
B = Y + 2.032 * U
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46467934

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档