Инициализация QCamera вызывает критические ошибки gstreamer - PullRequest
1 голос
/ 06 марта 2020

Я пытаюсь использовать функциональность QCamera QT для сканирования штрих-кодов. Мое устройство - устройство без головы, которое использует Wayland. Я использую QT 5.9.1 и gstreamer 1.0 - v1.14. На моем устройстве есть плагин camerabin2, и я могу использовать gstreamer для записи видео / фотографий в одиночку. Ранее я делал снимок с помощью отдельного конвейера gstreamer, собирал файл и передавал изображение в QZXing для обработки, но это было довольно медленно. Я хотел посмотреть, смогу ли я повысить производительность от использования QCamera напрямую с QZXing, но, к сожалению, я сталкиваюсь с некоторыми ошибками gstreamer.
Вот мой код:

#include <QFile>
#include <QZXing.h>
#include <QCamera>
#include <QCameraInfo>
#include <QCameraImageCapture>
#include <QCameraViewfinder>
#include <QRegularExpressionMatch>
#include "wirelesscontrollermain.hpp"
#include "barcodereader.hpp"
#include "calibrationhandler.hpp"
#include "jsonhelper.hpp"
namespace
{
    const int BARCODE_TIMEOUT_15S = 15000;

    QZXing* mDecoder;
    QCamera* mCamera;
    QCameraImageCapture* mImageCapture;
    QCameraViewfinder* mViewFinder;
}

BarcodeReader::BarcodeReader(WirelessControllerMain &parent)
: mParent(parent)
, mIsScanningActive(false)
, mTimeoutExpired(false)
, mScanningTimeout(this)
{
    mScanningTimeout.setInterval(BARCODE_TIMEOUT_15S);
    mScanningTimeout.setSingleShot(true);

    QObject::connect(&mScanningTimeout, SIGNAL(timeout()), this, SLOT(onBarcodeFailureTimeout()));
}

BarcodeReader::~BarcodeReader()
{
    delete mDecoder;
    mDecoder = NULL;
    delete mCamera;
    mCamera = NULL;
    delete mImageCapture;
    mImageCapture = NULL;
}

void BarcodeReader::init()
{
    if(QCameraInfo::availableCameras().count() > 0)
    {
        qWarning() << "we have cameras";
        const QList<QCameraInfo> cameras = QCameraInfo::availableCameras();
        for (const QCameraInfo &cameraInfo : cameras)
        {
            qCritical() << cameraInfo.deviceName();
        }
    }

    mCamera = new QCamera(QCameraInfo::defaultCamera());
    mImageCapture = new QCameraImageCapture(mCamera);

    QObject::connect(mImageCapture, SIGNAL(imageCaptured(int,QImage)), this, SLOT(pictureReady(int,QImage)));
    QObject::connect(mImageCapture, SIGNAL(imageAvailable(int,QVideoFrame)), this, SLOT(pictureReady(int,QVideoFrame)));
    QObject::connect(mImageCapture, SIGNAL(error(int,QCameraImageCapture::Error,QString)), this, SLOT(onImgCapError(int, QCameraImageCapture::Error, QString)));
    QObject::connect(mImageCapture, SIGNAL(readyForCaptureChanged(bool)), this, SLOT(onReadyForCapture(bool)));
    QObject::connect(mCamera, SIGNAL(lockStatusChanged(QCamera::LockStatus,QCamera::LockChangeReason)), this, SLOT(onLockStatusChange(QCamera::LockStatus, QCamera::LockChangeReason)));

    mCamera->setCaptureMode(QCamera::CaptureStillImage);
    mCamera->start();
    mViewFinder = new QCameraViewfinder();
    mViewFinder->show();
    mCamera->setViewfinder(mViewFinder);
}

void BarcodeReader::onReadyForCapture(bool isReadyForCapture)
{
    if(isReadyForCapture)
    {
        qCritical() << "ready for capture";
    }
    else
    {
        qCritical() << "not ready for capture";
    }
}

void BarcodeReader::onImgCapError(int value, QCameraImageCapture::Error error, QString string)
{
    qWarning() << "integer: " <<value << "error:" << error << "string:" << string;
}

void BarcodeReader::onLockStatusChange(QCamera::LockStatus lockstatus, QCamera::LockChangeReason reason)
{
    qWarning() << "lock status: " << lockstatus << "reason: " << reason;
}

/*!
 * \brief BarcodeReader::startBarcodeScan
 * called when the barcode scan button has been pressed
 */
void BarcodeReader::startBarcodeScan()
{
    if(!mIsScanningActive)
    {
        qDebug() << "start barcode scan";
        qWarning() <<"is capture mode supported?" << mCamera->isCaptureModeSupported(QCamera::CaptureStillImage);

        if(mDecoder != NULL)
        {
            delete mDecoder;
            mDecoder = NULL;
        }
        mDecoder = new QZXing();
        QObject::connect(mDecoder, SIGNAL(error(QString)), this, SLOT(decodeError(QString)));
        mDecoder->setDecoder(QZXing::DecoderFormat_EAN_8 | QZXing::DecoderFormat_EAN_13 | QZXing::DecoderFormat_QR_CODE | QZXing::DecoderFormat_DATA_MATRIX);

        mIsScanningActive = true;
        mCurrentBarcodeValue.clear();

        mScanningTimeout.stop();
        mScanningTimeout.start();

        qCritical() << "camera state: " << mCamera->state();
        qCritical() << "camera availability" << mCamera->availability();
        if(mImageCapture->isReadyForCapture())
        {
            mImageCapture->capture();
        }
        else
        {
            qWarning() << "not ready for capture";
        }
    }
    else
    {
        qWarning() << "barcode scanning already active";
    }
}

void BarcodeReader::pictureReady(int id, const QVideoFrame &preview)
{
    qWarning() << "PICTURE READY - videoframe";
}

void BarcodeReader::pictureReady(int id, const QImage &preview)
{
    qWarning() << "PICTURE READY";
    QString result = mDecoder->decodeImage(preview);
    if(result.isEmpty())
    {
        if(mTimeoutExpired)
        {
            //if the timeout expired while we were waiting for a picture to be taken
            //process the last image and then call it quits
            endBarcodeScan();
        }
        else
        {
            qWarning() << "try another barcode pic";
            mCamera->start();
            //take a new picture and hope for the best
            if(mImageCapture->isReadyForCapture())
            {
                mImageCapture->capture();
                mCamera->unlock();
            }
            else
            {
                qWarning() << "not ready for capture";
            }
        }
    }
}

/*!
 * \brief BarcodeReader::decodeError
 * \param err - gets called when QZXing encounters a scan error
 */
void BarcodeReader::decodeError(QString err)
{
    qWarning() << "Decode Error: " << err;
}

/*!
 * \brief BarcodeReader::onBarcodeFailureTimeout
 * if weve been scanning for barcodes for X time and havent found anything,
 * this function gets called by the timer
 */
void BarcodeReader::onBarcodeFailureTimeout()
{
    qWarning() << "Could not find barcode: timeout expired";
    mTimeoutExpired = true;
}

и вот соответствующие выходные данные отладки приложения QT

BarcodeReader::init - we have cameras
BarcodeReader::init - "/dev/video0"
BarcodeReader::init - "/dev/video1"

(qWirelessController:29981): GStreamer-CRITICAL **: gst_element_link_pads_full: assertion 'GST_IS_ELEMENT (src)' failed

(qWirelessController:29981): GStreamer-CRITICAL **: gst_object_unref: assertion 'object != NULL' failed
 - CameraBin error: "GStreamer error: negotiation problem."
 - Unable to query the parameter info: "Invalid argument"
 - Unable to query the parameter info: "Invalid argument"
 - Unable to query the parameter info: "Invalid argument"
 - Unable to query the parameter info: "Invalid argument"
 - Unable to query the parameter info: "Invalid argument"
 - Unable to query the parameter info: "Invalid argument"
BarcodeReader::startBarcodeScan - start barcode scan
BarcodeReader::startBarcodeScan - is capture mode supported? true
BarcodeReader::startBarcodeScan - camera state:  QCamera::ActiveState
BarcodeReader::startBarcodeScan - camera availability 0
BarcodeReader::startBarcodeScan - not ready for capture
BarcodeReader::onBarcodeFailureTimeout - Could not find barcode: timeout expired

и вот небольшая часть вывода gst_debug = 4, где происходит ошибка

:00:28.200701097 19677  0x1722a00 INFO           viewfinderbin gstviewfinderbin.c:312:gst_viewfinder_bin_set_video_sink:<vf-bin> Setting video sink to <qgstvideorenderersink0>
0:00:28.218930847 19677  0x1722a00 INFO     wrappercamerabinsrc gstwrappercamerabinsrc.c:995:set_capsfilter_caps:<camera_source> new_caps:ANY
0:00:28.233847264 19677  0x1722a00 INFO     wrappercamerabinsrc gstwrappercamerabinsrc.c:884:gst_wrapper_camera_bin_src_set_zoom:<camera_source> setting zoom 1.000000
0:00:28.251089431 19677  0x1722a00 INFO     wrappercamerabinsrc gstwrappercamerabinsrc.c:890:gst_wrapper_camera_bin_src_set_zoom:<camera_source> zoom set using digitalzoom
0:00:28.268826264 19677  0x1722a00 INFO               GST_EVENT gstevent.c:1517:gst_event_new_reconfigure: creating reconfigure event
0:00:28.283702722 19677  0x1722a00 INFO               GST_EVENT gstevent.c:1517:gst_event_new_reconfigure: creating reconfigure event
0:00:28.298587347 19677  0x1722a00 INFO     wrappercamerabinsrc gstwrappercamerabinsrc.c:1003:set_capsfilter_caps:<camera_source> updated
0:00:28.313344514 19677  0x1722a00 INFO              GST_STATES gstbin.c:2089:gst_bin_get_state_func:<preview-pipeline> getting state
0:00:28.328236139 19677  0x1722a00 INFO        GST_ELEMENT_PADS gstpad.c:2134:gst_pad_unlink: unlinking preview-appsrc:src(0x18ced98) and preview-vscale:sink(0x18d2460)
0:00:28.346451306 19677  0x1722a00 INFO        GST_ELEMENT_PADS gstpad.c:2188:gst_pad_unlink: unlinked preview-appsrc:src and preview-vscale:sink
0:00:28.362642306 19677  0x1722a00 INFO        GST_ELEMENT_PADS gstutils.c:1774:gst_element_link_pads_full: trying to link element preview-appsrc:src to element preview-vscale:sink
0:00:28.381914181 19677  0x1722a00 INFO        GST_ELEMENT_PADS gstelement.c:920:gst_element_get_static_pad: found pad preview-appsrc:src
0:00:28.397408972 19677  0x1722a00 INFO        GST_ELEMENT_PADS gstelement.c:920:gst_element_get_static_pad: found pad preview-vscale:sink
0:00:28.412992139 19677  0x1722a00 INFO                GST_PADS gstutils.c:1588:prepare_link_maybe_ghosting: preview-appsrc and preview-vscale in same bin, no need for ghost pads
0:00:28.432092806 19677  0x1722a00 INFO                GST_PADS gstpad.c:2378:gst_pad_link_prepare: trying to link preview-appsrc:src and preview-vscale:sink
0:00:28.449303764 19677  0x1722a00 INFO                GST_PADS gstpad.c:2586:gst_pad_link_full: linked preview-appsrc:src and preview-vscale:sink, successful
0:00:28.466614764 19677  0x1722a00 INFO               GST_EVENT gstevent.c:1517:gst_event_new_reconfigure: creating reconfigure event
0:00:28.481535556 19677  0x1722a00 INFO               GST_EVENT gstpad.c:5808:gst_pad_send_event_unchecked:<preview-appsrc:src> Received event on flushing pad. Discarding
0:00:28.499853681 19677  0x1722a00 INFO              GST_STATES gstbin.c:2954:gst_bin_change_state_func:<camerabin> child 'imagebin-filesink' changed state to 2(READY) successfully
0:00:28.518643139 19677  0x1722a00 INFO              GST_STATES gstbin.c:2954:gst_bin_change_state_func:<camerabin> child 'videobin-filesink' changed state to 2(READY) successfully
0:00:28.537619556 19677  0x1722a00 INFO              GST_STATES gstbin.c:2506:gst_bin_element_set_state:<vf-bin> current NULL pending VOID_PENDING, desired next READY
0:00:28.555408306 19677  0x1722a00 INFO        GST_ELEMENT_PADS gstpad.c:2134:gst_pad_unlink: unlinking vfbin->videoscale:src(0x196f780) and fakesink0:sink(0x18d2868)
0:00:28.573421056 19677  0x1722a00 INFO        GST_ELEMENT_PADS gstpad.c:2188:gst_pad_unlink: unlinked vfbin->videoscale:src and fakesink0:sink
0:00:28.589460389 19677  0x1722a00 INFO           GST_PARENTAGE gstbin.c:1801:gst_bin_remove_func:<vf-bin> removed child "fakesink0"
0:00:28.604571931 19677  0x1722a00 INFO           GST_PARENTAGE gstbin.c:4468:gst_bin_get_by_name: [vf-bin]: looking up child element vfbin-videscale

(qWirelessController:19677): GStreamer-CRITICAL **: gst_element_link_pads_full: assertion 'GST_IS_ELEMENT (src)' failed
0:00:28.632689764 19677  0x1722a00 WARN           viewfinderbin gstviewfinderbin.c:237:gst_viewfinder_bin_create_elements:<vf-bin> error: linking videoscale and viewfindersink failed
0:00:28.651664431 19677  0x1722a00 INFO        GST_ERROR_SYSTEM gstelement.c:2145:gst_element_message_full_with_details:<vf-bin> posting message: GStreamer error: negotiation problem.
0:00:28.671232931 19677  0x1722a00 INFO        GST_ERROR_SYSTEM gstelement.c:2172:gst_element_message_full_with_details:<vf-bin> posted error message: GStreamer error: negotiation problem.

(qWirelessController:19677): GStreamer-CRITICAL **: gst_object_unref: assertion 'object != NULL' failed
0:00:28.701280723 19677  0x1722a00 INFO              GST_STATES gstbin.c:2506:gst_bin_element_set_state:<qgstvideorenderersink0> current NULL pending VOID_PENDING, desired next READY
0:00:28.720489598 19677  0x1722a00 INFO              GST_STATES gstelement.c:2676:gst_element_continue_state:<qgstvideorenderersink0> completed state change to READY
0:00:28.738063973 19677  0x1722a00 INFO              GST_STATES gstelement.c:2579:_priv_gst_element_state_changed:<qgstvideorenderersink0> notifying about state-changed NULL to READY (VOID_PENDING pending)

Кто-нибудь знает, что является причиной этой ошибки? Я могу предоставить полные журналы, если кто-то считает это полезным.

1 Ответ

0 голосов
/ 06 марта 2020

Да.

0:00:28.218930847 19677  0x1722a00 INFO     wrappercamerabinsrc gstwrappercamerabinsrc.c:995:set_capsfilter_caps:<camera_source> new_caps:ANY
0:00:28.233847264 19677  0x1722a00 INFO     wrappercamerabinsrc gstwrappercamerabinsrc.c:884:gst_wrapper_camera_bin_src_set_zoom:<camera_source> setting zoom 1.000000
0:00:28.251089431 19677  0x1722a00 INFO     wrappe

Вам необходимо удалить лишние обертки.

...