Рабочий код qt / gstreamer на debian, который не работает на rasbian

У меня есть небольшая программа qt / C++, которая использует gstreamer. Он правильно работает на 64-битной версии debian и не будет работать на Raspberry Pi 3, на котором запущен raspbian.

Программа отображает веб-камеру 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";
}

проблема не в Qt, а в gstreamer

eyllanesc 27.10.2018 01:32

Есть идеи, как это исправить?

M. P. 27.10.2018 01:58
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
2
268
1

Ответы 1

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

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

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

Этот пример - хорошее начало.

Другие вопросы по теме