Рабочий код qt / gstreamer на Debian, который не будет работать на rasbian - PullRequest
0 голосов
/ 27 октября 2018

У меня есть небольшая программа на qt / c ++, которая использует gstreamer. Он работает правильно на Debian 64bit и не будет работать на Raspberry Pi 3, работающем с Rasbian.

Программа отображает веб-камеру USB по адресу / dev / video0 и передает ее по указанному IP-адресу. (для тестирования я использую адрес обратной связи и имею программу RTP-приемника на том же компьютере для отображения потока)

У меня установлен qt creator на обеих машинах, а программы собраны на целевой машине. (без кросс-компиляции)

При запуске на Raspberry Pi "GstStateChangeReturn" возвращается как "GST_STATE_CHANGE_FAILURE"

Вот полный код:

gstreamer_stream_and_display_test.pro

#-------------------------------------------------
#
# Project created by QtCreator 2018-10-25T19:06:04
#
#-------------------------------------------------

QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = gstreamer_stream_and_display_test
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

CONFIG += c++11

SOURCES += \
        main.cpp \
        mainwindow.cpp

HEADERS += \
        mainwindow.h

FORMS += \
        mainwindow.ui

CONFIG += link_pkgconfig
PKGCONFIG += gstreamer-1.0 glib-2.0 gobject-2.0 gstreamer-video-1.0

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

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

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private:
    Ui::MainWindow *ui;
    GstElement *pipeline0;
    GstStateChangeReturn sret0;
};

#endif // MAINWINDOW_H

main.cpp

#include "mainwindow.h"
#include <QApplication>
#include <glib.h>
#include <gst/gst.h>
#include <gst/video/videooverlay.h>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    gst_init (&argc, &argv);
    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QApplication>
#include <QWidget>
#include <QDebug>
#include <glib.h>
#include <gst/gst.h>
#include <gst/video/videooverlay.h>

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setFixedSize(1280,720);
    setWindowTitle("Stream and Display Test");

    WId xwinid = winId();
    pipeline0 = gst_pipeline_new("myPipeline");
    GstElement *v4l2src = gst_element_factory_make("v4l2src", "v4l2src");
    GstElement *capsfilter = gst_element_factory_make("capsfilter", "capsfilter");
    GstElement *tee = gst_element_factory_make("tee", "tee");
    GstElement *encoder = gst_element_factory_make("jpegenc", "encoder");
    GstElement *videoConverter = gst_element_factory_make("videoconvert", "videoConverter");
    GstElement *rtp = gst_element_factory_make("rtpjpegpay", "rtp");
    GstElement *queueDisplay = gst_element_factory_make("queue", "queueDisplay");
    GstElement *queueStreamer = gst_element_factory_make("queue", "queueStreamer");
    GstElement *udpsink = gst_element_factory_make("udpsink", "udpsink");
    GstElement *videoSink = gst_element_factory_make("xvimagesink", "videoSink");

    //                               jpegenc -> rtpjpegpay -> udpsink
    //v4l2src -> capsfilter -> tee <
    //                               videoconvert -> queue -> xvimagesink

    g_object_set(udpsink, "port", 5200, NULL);
    g_object_set(udpsink, "host", "127.0.0.1", NULL);
    GstCaps *caps = gst_caps_from_string("video/x-raw, width=(int)1280, height=(int)720");
    g_object_set(capsfilter, "caps", caps, NULL);

    //add elements to bin
    gst_bin_add_many(GST_BIN(pipeline0), v4l2src, capsfilter, tee, encoder, queueDisplay, queueStreamer, videoConverter, rtp, udpsink, videoSink, NULL);

    //Link source elements
    if(!gst_element_link_many(v4l2src, capsfilter, tee, NULL))
    {
        qDebug()<<"Unable to link source elements";
    }
    //Link streaming elements
    if(!gst_element_link_many(queueStreamer, encoder, rtp, udpsink, NULL))
    {
        qDebug()<<"Unable to link streaming elements";
    }
    //Link display elements
    if(!gst_element_link_many(queueDisplay, videoConverter, videoSink, NULL))
    {
        qDebug()<<"Unable to link display elements";
    }

    //Create Tee Pads
    GstPad *teeStreamerPad = gst_element_get_request_pad(tee, "src_%u");
    GstPad *queueStreamerPad = gst_element_get_static_pad(queueStreamer, "sink");
    GstPad *teeDisplayPad = gst_element_get_request_pad(tee, "src_%u");
    GstPad *queueDisplayPad= gst_element_get_static_pad(queueDisplay, "sink");

    //Link Tee and Queue Pads
    if(gst_pad_link(teeStreamerPad, queueStreamerPad) != GST_PAD_LINK_OK)
    {
        qDebug()<<"Unable to link streamer pads";
    }
    if(gst_pad_link(teeDisplayPad, queueDisplayPad) != GST_PAD_LINK_OK)
    {
        qDebug()<<"Unable to link display pads";
    }

    gst_object_unref(queueStreamerPad);
    gst_object_unref(queueDisplayPad);

    //Setup Gui Display Area
    gint viewX = 0;
    gint viewY = 0;
    gint camResX = 1280;
    gint camResY = 720;
    gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY (videoSink), xwinid);
    gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY (videoSink), viewX, viewY, camResX, camResY);

    //start pipeline
    sret0 = gst_element_set_state(pipeline0, GST_STATE_PLAYING);
    if(sret0 == GST_STATE_CHANGE_FAILURE)
    {
        qDebug()<<"Error: GST_STATE_CHANGE_FAILURE";
        close();
    }
    else
    {
        qDebug()<<sret0;
    }
}

MainWindow::~MainWindow()
{
    gst_element_set_state (pipeline0, GST_STATE_NULL);
    gst_object_unref(pipeline0);
    delete ui;
    qDebug()<<"Closed correctly";
}

1 Ответ

0 голосов
/ 29 октября 2018

Я думаю, что вы все слишком усложнили, используя gstreamer напрямую.

Должно быть проще использовать класс Qt QCamera из мультимедийного модуля: он позволяет воспроизводить поток с веб-камеры (также: вы можете записывать, захватывать кадры, получить информацию о веб-камере и так далее).

Вы даже можете написать свой собственный QAbstractVideoSurface, который транслирует видео онлайн.

Этот пример , безусловно, хорошее начало.

...