• QT版本华睿相机的Demo程序实现


    此工程参照原先例子工程ShowImage。

    首先,QT创建一个Widget工程HuaRuiSDKDemo,

    图中多出的camerawidget是后来添加的qt设计师界面类CameraWidget

     

     2. 参照原先工程,把代码添加进去,再编译测试,完整代码如下,

    1)main.cpp

    #include "widget.h"
    #include <QApplication>
     
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        Widget w;
        w.show();
     
    
        return a.exec();
    }

    2.widget.h

    #ifndef WIDGET_H
    #define WIDGET_H
     
    
    #include <QWidget>
    #include <QTimer>
    #include "IMVAPI/IMVApi.h"
     
    
    namespace Ui {
    class Widget;
    }
     
    
    class Widget : public QWidget
    {
        Q_OBJECT
     
    
    public:
        explicit Widget(QWidget *parent = nullptr);
        ~Widget();
     
    
    private:
        void initUi();
     
    
    private slots:
        void on_pushButton_Open_clicked();
        void on_pushButton_Close_clicked();
        void on_pushButton_Start_clicked();
        void on_pushButton_Stop_clicked();
        void on_comboBox_currentIndexChanged(int index);
        void closeEvent(QCloseEvent * event);
        void onTimerStreamStatistic();// 定时刷新状态栏信息 | Refresh status bar information regularly
     
    
    private:
        Ui::Widget *ui;
     
    
        IMV_DeviceList m_deviceInfoList;	// 发现的相机列表 | List of cameras found
        QTimer m_staticTimer;				// 定时器,定时刷新状态栏信息 | Timer, refresh status bar information regularly
    };
     
    
    #endif // WIDGET_H

    3)widget.cpp

    #include "widget.h"
    #include "ui_widget.h"
     
    
    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
        connect(&m_staticTimer, &QTimer::timeout, this, &Widget::onTimerStreamStatistic);
     
    
        initUi();
    }
     
    
    Widget::~Widget()
    {
        delete ui;
    }
     
    
    void Widget::initUi()
    {
        int ret = IMV_OK;
     
    
        ui->label_Statistic->setText("");// 连接相机之前不显示状态栏 | Don't show status bar before connecting camera
     
    
        ret = IMV_EnumDevices(&m_deviceInfoList, interfaceTypeAll);
        if (IMV_OK != ret)
        {
            printf("Enumeration devices failed! ErrorCode[%d]\n", ret);
            return;
        }
        if (m_deviceInfoList.nDevNum < 1)
        {
            ui->comboBox->setEnabled(false);
            ui->pushButton_Open->setEnabled(false);
        }
        else
        {
            ui->comboBox->setEnabled(true);
            ui->pushButton_Open->setEnabled(true);
     
    
            for (unsigned int i = 0; i < m_deviceInfoList.nDevNum; i++)
            {
                ui->comboBox->addItem(m_deviceInfoList.pDevInfo[i].cameraKey);
            }
     
    
            ui->widget->SetCamera(m_deviceInfoList.pDevInfo[0].cameraKey);
        }
     
    
        ui->pushButton_Close->setEnabled(false);
        ui->pushButton_Start->setEnabled(false);
        ui->pushButton_Stop->setEnabled(false);
    }
     
    
    // 设置要连接的相机
    // set camera which need to connect
    void Widget::on_comboBox_currentIndexChanged(int nIndex)
    {
        ui->widget->SetCamera(m_deviceInfoList.pDevInfo[nIndex].cameraKey);
    }
     
    
    // 连接
    // connect
    void Widget::on_pushButton_Open_clicked()
    {
        if (!ui->widget->CameraOpen())
        {
            return;
        }
     
    
        ui->pushButton_Open->setEnabled(false);
        ui->pushButton_Close->setEnabled(true);
        ui->pushButton_Start->setEnabled(true);
        ui->pushButton_Stop->setEnabled(false);
        ui->comboBox->setEnabled(false);
     
    
        // 连接相机之后显示统计信息,所有值为0
        // Show statistics after connecting camera, all values are 0
        ui->widget->resetStatistic();
        QString strStatic = ui->widget->getStatistic();
        ui->label_Statistic->setText(strStatic);
    }
     
    
    // 断开
    // disconnect
    void Widget::on_pushButton_Close_clicked()
    {
        on_pushButton_Stop_clicked();
        ui->widget->CameraClose();
     
    
        ui->label_Statistic->setText("");// 断开相机以后不显示状态栏 | Do not display the status bar after disconnecting the camera
     
    
        ui->pushButton_Open->setEnabled(true);
        ui->pushButton_Close->setEnabled(false);
        ui->pushButton_Start->setEnabled(false);
        ui->pushButton_Stop->setEnabled(false);
        ui->comboBox->setEnabled(true);
    }
     
    
    // 开始
    // start
    void Widget::on_pushButton_Start_clicked()
    {
        // 设置连续拉流
        // set continue grabbing
        // ui->widget->CameraChangeTrig(CammerWidget::trigContinous);
     
    
        ui->widget->CameraStart();
     
    
        ui->pushButton_Start->setEnabled(false);
        ui->pushButton_Stop->setEnabled(true);
     
    
        ui->widget->resetStatistic();
        m_staticTimer.start(100);
    }
     
    
    // 停止
    // stop
    void Widget::on_pushButton_Stop_clicked()
    {
        m_staticTimer.stop();
     
    
        ui->widget->CameraStop();
     
    
        ui->pushButton_Start->setEnabled(true);
        ui->pushButton_Stop->setEnabled(false);
    }
     
    
    void Widget::onTimerStreamStatistic()
    {
        QString strStatic = ui->widget->getStatistic();
        ui->label_Statistic->setText(strStatic);
    }
     
    
    void Widget::closeEvent(QCloseEvent * event)
    {
        on_pushButton_Stop_clicked();
        ui->widget->CameraClose();
    }
    4)camerawidget.h
    #ifndef CAMERAWIDGET_H
    #define CAMERAWIDGET_H
     
    
    #include <windows.h>
    #include <process.h>
    #include <QWidget>
    #include "Media/VideoRender.h"
    #include "MessageQue.h"
    #include "IMVAPI/IMVApi.h"
    #include <QElapsedTimer>
    #include <QMutex>
    #include <QThread>
     
    
    // 状态栏统计信息
    // Status bar statistics
    struct FrameStatInfo
    {
        quint32     m_nFrameSize;       // 帧大小, 单位: 字节 | frame size ,length :byte
        qint64      m_nPassTime;         // 接收到该帧时经过的纳秒数 |  The number of nanoseconds passed when the frame was received
        FrameStatInfo(int nSize, qint64 nTime) : m_nFrameSize(nSize), m_nPassTime(nTime)
        {
        }
    };
     
    
    // 帧信息
    // frame imformation
    class CFrameInfo
    {
    public:
        CFrameInfo()
        {
            m_pImageBuf = NULL;
            m_nBufferSize = 0;
            m_nWidth = 0;
            m_nHeight = 0;
            m_ePixelType = gvspPixelMono8;
            m_nPaddingX = 0;
            m_nPaddingY = 0;
            m_nTimeStamp = 0;
        }
     
    
        ~CFrameInfo()
        {
        }
     
    
    public:
        unsigned char*	m_pImageBuf;
        int				m_nBufferSize;
        int				m_nWidth;
        int				m_nHeight;
        IMV_EPixelType	m_ePixelType;
        int				m_nPaddingX;
        int				m_nPaddingY;
        uint64_t		m_nTimeStamp;
    };
     
    
     
    
    namespace Ui {
    class CameraWidget;
    }
     
    
    class CameraWidget : public QWidget
    {
        Q_OBJECT
     
    
    public:
        explicit CameraWidget(QWidget *parent = nullptr);
        ~CameraWidget();
     
    
        // 枚举触发方式
        // Enumeration trigger mode
        enum ETrigType
        {
            trigContinous = 0,	// 连续拉流 | continue grabbing
            trigSoftware = 1,	// 软件触发 | software trigger
            trigLine = 2,		// 外部触发	| external trigger
        };
     
    
        // 打开相机
        // open cmaera
        bool CameraOpen(void);
        // 关闭相机
        // close camera
        bool CameraClose(void);
        // 开始采集
        // start grabbing
        bool CameraStart(void);
        // 停止采集
        // stop grabbing
        bool CameraStop(void);
        // 切换采集方式、触发方式 (连续采集、外部触发、软件触发)
        // Switch acquisition mode and triggering mode (continuous acquisition, external triggering and software triggering)
        bool CameraChangeTrig(ETrigType trigType = trigContinous);
        // 执行一次软触发
        // Execute a soft trigger
        bool ExecuteSoftTrig(void);
        // 设置曝光
        // set exposuse time
        bool SetExposeTime(double dExposureTime);
        // 设置增益
        // set gain
        bool SetAdjustPlus(double dGainRaw);
        // 设置当前相机
        // set current camera
        void SetCamera(const QString& strKey);
     
    
        // 状态栏统计信息
        // Status bar statistics
        void recvNewFrame(quint32 frameSize);
        void resetStatistic();
        QString getStatistic();
        void updateStatistic();
     
    
        void display();
     
    
    private:
     
    
        // 设置显示频率,默认一秒钟显示30帧
        // Set the display frequency to display 30 frames in one second by default
        void setDisplayFPS(int nFPS);
     
    
        // 计算该帧是否显示
        // Calculate whether the frame is displayed
        bool isTimeToDisplay();
     
    
        // 窗口关闭响应函数
        // Window close response function
        void closeEvent(QCloseEvent * event);
     
    
        // 显示一帧图像
        // display a frame image
        bool ShowImage(unsigned char* pRgbFrameBuf, int nWidth, int nHeight, IMV_EPixelType nPixelFormat);
     
    
        // VedioRender相关函数
        // VedioRender relative function
        bool openRender(int width, int height);
        bool closeRender();
     
    
    public:
        TMessageQue<CFrameInfo>				m_qDisplayFrameQueue;		// 显示队列      | diaplay queue
     
    
    private:
        Ui::CameraWidget *ui;
     
    
        QString								m_currentCameraKey;			// 当前相机key | current camera key
        IMV_HANDLE							m_devHandle;				// 相机句柄 | camera handle
     
    
        // 控制显示帧率   | Control display frame rate
        QMutex								m_mxTime;
        int									m_nDisplayInterval;         // 显示间隔 | diaplay time internal
        uint64_t							m_nFirstFrameTime;          // 第一帧的时间戳 | Time stamp of the first frame
        uint64_t							m_nLastFrameTime;           // 上一帧的时间戳 | Timestamp of previous frame
        QElapsedTimer						m_elapsedTimer;				// 用来计时,控制显示帧率 | Used to time and control the display frame rate
     
    
        // 状态栏统计信息
        // Status bar statistics
        typedef std::list<FrameStatInfo> FrameList;
        FrameList   m_listFrameStatInfo;
        QMutex      m_mxStatistic;
        quint64     m_nTotalFrameCount;		// 收到的总帧数 | recieve all frames
        QString     m_strStatistic;			// 统计信息, 不包括错误  | Statistics, excluding errors
        bool		m_bNeedUpdate;
     
    
        // VedioRender相关
        VR_HANDLE          m_handler;           // 绘图句柄 | draw inco handle
        VR_OPEN_PARAM_S    m_params;            // 显示参数 | display parmeters
        VR_HWND			m_hWnd;             // 显示窗口句柄 | display window handle
     
    
        bool			m_isExitDisplayThread;
        HANDLE			m_threadHandle;
    };
     
    
    #endif // CAMERAWIDGET_H
    5)camerawidget.cpp
    #include "camerawidget.h"
    #include "ui_camerawidget.h"
     
    
    #define DEFAULT_SHOW_RATE (30) // 默认显示帧率 | defult display frequency
    #define DEFAULT_ERROR_STRING ("N/A")
    #define MAX_FRAME_STAT_NUM (50)
    #define MIN_LEFT_LIST_NUM (2)
    #define MAX_STATISTIC_INTERVAL (5000000000) // List的更新时与最新一帧的时间最大间隔 |  The maximum time interval between the update of list and the latest frame
     
    
    // 取流回调函数
    // get frame callback function
    static void FrameCallback(IMV_Frame* pFrame, void* pUser)
    {
        CameraWidget* pCameraWidget = (CameraWidget*)pUser;
        if (!pCameraWidget)
        {
            printf("pCameraWidget is NULL!");
            return;
        }
     
    
        CFrameInfo frameInfo;
        frameInfo.m_nWidth = (int)pFrame->frameInfo.width;
        frameInfo.m_nHeight = (int)pFrame->frameInfo.height;
        frameInfo.m_nBufferSize = (int)pFrame->frameInfo.size;
        frameInfo.m_nPaddingX = (int)pFrame->frameInfo.paddingX;
        frameInfo.m_nPaddingY = (int)pFrame->frameInfo.paddingY;
        frameInfo.m_ePixelType = pFrame->frameInfo.pixelFormat;
        frameInfo.m_pImageBuf = (unsigned char *)malloc(sizeof(unsigned char) * frameInfo.m_nBufferSize);
        frameInfo.m_nTimeStamp = pFrame->frameInfo.timeStamp;
     
    
        // 内存申请失败,直接返回
        // memory application failed, return directly
        if (frameInfo.m_pImageBuf != NULL)
        {
            memcpy(frameInfo.m_pImageBuf, pFrame->pData, frameInfo.m_nBufferSize);
     
    
            if (pCameraWidget->m_qDisplayFrameQueue.size() > 16)
            {
                CFrameInfo frameOld;
                if (pCameraWidget->m_qDisplayFrameQueue.get(frameOld))
                {
                    free(frameOld.m_pImageBuf);
                    frameOld.m_pImageBuf = NULL;
                }
            }
     
    
            pCameraWidget->m_qDisplayFrameQueue.push_back(frameInfo);
        }
     
    
        pCameraWidget->recvNewFrame(pFrame->frameInfo.size);
    }
     
    
    // 显示线程
    // display thread
    static unsigned int __stdcall displayThread(void* pUser)
    {
        CameraWidget* pCameraWidget = (CameraWidget*)pUser;
        if (!pCameraWidget)
        {
            printf("pCameraWidget is NULL!");
            return -1;
        }
     
    
        pCameraWidget->display();
     
    
        return 0;
    }
     
    
     
    
    CameraWidget::CameraWidget(QWidget *parent) :
        QWidget(parent)
        , ui(new Ui::CameraWidget)
        , m_currentCameraKey("")
        , m_devHandle(NULL)
        , m_nDisplayInterval(0)
        , m_nFirstFrameTime(0)
        , m_nLastFrameTime(0)
        , m_handler(NULL)
        , m_bNeedUpdate(true)
        , m_nTotalFrameCount(0)
        , m_isExitDisplayThread(false)
        , m_threadHandle(NULL)
    {
        ui->setupUi(this);
     
    
     
    
        m_hWnd = (VR_HWND)this->winId();
     
    
        // 默认显示30帧
        // defult display 30 frames
        setDisplayFPS(DEFAULT_SHOW_RATE);
     
    
        m_elapsedTimer.start();
     
    
        // 启动显示线程
        // start display thread
        m_threadHandle = (HANDLE)_beginthreadex(NULL,
            0,
            displayThread,
            this,
            CREATE_SUSPENDED,
            NULL);
     
    
        if (!m_threadHandle)
        {
            printf("Failed to create display thread!\n");
        }
        else
        {
            ResumeThread(m_threadHandle);
     
    
            m_isExitDisplayThread = false;
        }
    }
     
    
    CameraWidget::~CameraWidget()
    {
        // 关闭显示线程
        // close display thread
        m_isExitDisplayThread = true;
        WaitForSingleObject(m_threadHandle, INFINITE);
        CloseHandle(m_threadHandle);
        m_threadHandle = NULL;
     
    
        delete ui;
    }
     
    
    // 设置曝光
    // set exposeTime
    bool CameraWidget::SetExposeTime(double dExposureTime)
    {
        int ret = IMV_OK;
     
    
        ret = IMV_SetDoubleFeatureValue(m_devHandle, "ExposureTime", dExposureTime);
        if (IMV_OK != ret)
        {
            printf("set ExposureTime value = %0.2f fail, ErrorCode[%d]\n", dExposureTime, ret);
            return false;
        }
     
    
        return true;
    }
     
    
    // 设置增益
    // set gain
    bool CameraWidget::SetAdjustPlus(double dGainRaw)
    {
        int ret = IMV_OK;
     
    
        ret = IMV_SetDoubleFeatureValue(m_devHandle, "GainRaw", dGainRaw);
        if (IMV_OK != ret)
        {
            printf("set GainRaw value = %0.2f fail, ErrorCode[%d]\n", dGainRaw, ret);
            return false;
        }
     
    
        return true;
    }
     
    
    // 打开相机
    // open camera
    bool CameraWidget::CameraOpen(void)
    {
        int ret = IMV_OK;
     
    
        if (m_currentCameraKey.length() == 0)
        {
            printf("open camera fail. No camera.\n");
            return false;
        }
     
    
        if (m_devHandle)
        {
            printf("m_devHandle is already been create!\n");
            return false;
        }
        QByteArray cameraKeyArray = m_currentCameraKey.toLocal8Bit();
        char* cameraKey = cameraKeyArray.data();
     
    
        ret = IMV_CreateHandle(&m_devHandle, modeByCameraKey, (void*)cameraKey);
        if (IMV_OK != ret)
        {
            printf("create devHandle failed! cameraKey[%s], ErrorCode[%d]\n", cameraKey, ret);
            return false;
        }
     
    
        // 打开相机
        // Open camera
        ret = IMV_Open(m_devHandle);
        if (IMV_OK != ret)
        {
            printf("open camera failed! ErrorCode[%d]\n", ret);
            return false;
        }
     
    
        return true;
    }
     
    
    // 关闭相机
    // close camera
    bool CameraWidget::CameraClose(void)
    {
        int ret = IMV_OK;
     
    
        if (!m_devHandle)
        {
            printf("close camera fail. No camera.\n");
            return false;
        }
     
    
        if (false == IMV_IsOpen(m_devHandle))
        {
            printf("camera is already close.\n");
            return false;
        }
     
    
        ret = IMV_Close(m_devHandle);
        if (IMV_OK != ret)
        {
            printf("close camera failed! ErrorCode[%d]\n", ret);
            return false;
        }
     
    
        ret = IMV_DestroyHandle(m_devHandle);
        if (IMV_OK != ret)
        {
            printf("destroy devHandle failed! ErrorCode[%d]\n", ret);
            return false;
        }
     
    
        m_devHandle = NULL;
     
    
        return true;
    }
     
    
    // 开始采集
    // start grabbing
    bool CameraWidget::CameraStart()
    {
        int ret = IMV_OK;
     
    
        if (IMV_IsGrabbing(m_devHandle))
        {
            printf("camera is already grebbing.\n");
            return false;
        }
     
    
     
    
        ret = IMV_AttachGrabbing(m_devHandle, FrameCallback, this);
        if (IMV_OK != ret)
        {
            printf("Attach grabbing failed! ErrorCode[%d]\n", ret);
            return false;
        }
     
    
        ret = IMV_StartGrabbing(m_devHandle);
        if (IMV_OK != ret)
        {
            printf("start grabbing failed! ErrorCode[%d]\n", ret);
            return false;
        }
     
    
        return true;
    }
     
    
    // 停止采集
    // stop grabbing
    bool CameraWidget::CameraStop()
    {
        int ret = IMV_OK;
        if (!IMV_IsGrabbing(m_devHandle))
        {
            printf("camera is already stop grebbing.\n");
            return false;
        }
     
    
        ret = IMV_StopGrabbing(m_devHandle);
        if (IMV_OK != ret)
        {
            printf("Stop grabbing failed! ErrorCode[%d]\n", ret);
            return false;
        }
     
    
        // 清空显示队列
        // clear display queue
        CFrameInfo frameOld;
        while (m_qDisplayFrameQueue.get(frameOld))
        {
            free(frameOld.m_pImageBuf);
            frameOld.m_pImageBuf = NULL;
        }
     
    
        m_qDisplayFrameQueue.clear();
     
    
        return true;
    }
     
    
    // 切换采集方式、触发方式 (连续采集、外部触发、软件触发)
    // Switch acquisition mode and triggering mode (continuous acquisition, external triggering and software triggering)
    bool CameraWidget::CameraChangeTrig(ETrigType trigType)
    {
        int ret = IMV_OK;
     
    
        if (trigContinous == trigType)
        {
            // 设置触发模式
            // set trigger mode
            ret = IMV_SetEnumFeatureSymbol(m_devHandle, "TriggerMode", "Off");
            if (IMV_OK != ret)
            {
                printf("set TriggerMode value = Off fail, ErrorCode[%d]\n", ret);
                return false;
            }
        }
        else if (trigSoftware == trigType)
        {
            // 设置触发器
            // set trigger
            ret = IMV_SetEnumFeatureSymbol(m_devHandle, "TriggerSelector", "FrameStart");
            if (IMV_OK != ret)
            {
                printf("set TriggerSelector value = FrameStart fail, ErrorCode[%d]\n", ret);
                return false;
            }
     
    
            // 设置触发模式
            // set trigger mode
            ret = IMV_SetEnumFeatureSymbol(m_devHandle, "TriggerMode", "On");
            if (IMV_OK != ret)
            {
                printf("set TriggerMode value = On fail, ErrorCode[%d]\n", ret);
                return false;
            }
     
    
            // 设置触发源为软触发
            // set triggerSource as software trigger
            ret = IMV_SetEnumFeatureSymbol(m_devHandle, "TriggerSource", "Software");
            if (IMV_OK != ret)
            {
                printf("set TriggerSource value = Software fail, ErrorCode[%d]\n", ret);
                return false;
            }
        }
        else if (trigLine == trigType)
        {
            // 设置触发器
            // set trigger
            ret = IMV_SetEnumFeatureSymbol(m_devHandle, "TriggerSelector", "FrameStart");
            if (IMV_OK != ret)
            {
                printf("set TriggerSelector value = FrameStart fail, ErrorCode[%d]\n", ret);
                return false;
            }
     
    
            // 设置触发模式
            // set trigger mode
            ret = IMV_SetEnumFeatureSymbol(m_devHandle, "TriggerMode", "On");
            if (IMV_OK != ret)
            {
                printf("set TriggerMode value = On fail, ErrorCode[%d]\n", ret);
                return false;
            }
     
    
            // 设置触发源为Line1触发
            // set trigggerSource as Line1 trigger
            ret = IMV_SetEnumFeatureSymbol(m_devHandle, "TriggerSource", "Line1");
            if (IMV_OK != ret)
            {
                printf("set TriggerSource value = Line1 fail, ErrorCode[%d]\n", ret);
                return false;
            }
        }
     
    
        return true;
    }
     
    
    // 执行一次软触发
    // execute one software trigger
    bool CameraWidget::ExecuteSoftTrig(void)
    {
        int ret = IMV_OK;
     
    
        ret = IMV_ExecuteCommandFeature(m_devHandle, "TriggerSoftware");
        if (IMV_OK != ret)
        {
            printf("ExecuteSoftTrig fail, ErrorCode[%d]\n", ret);
            return false;
        }
     
    
        printf("ExecuteSoftTrig success.\n");
        return true;
    }
     
    
    // 设置当前相机
    // set current camera
    void CameraWidget::SetCamera(const QString& strKey)
    {
        m_currentCameraKey = strKey;
    }
     
    
    // 显示
    // diaplay
    bool CameraWidget::ShowImage(unsigned char* pRgbFrameBuf, int nWidth, int nHeight, IMV_EPixelType nPixelFormat)
    {
        if (NULL == pRgbFrameBuf ||
            nWidth == 0 ||
            nHeight == 0)
        {
            printf("%s image is invalid.\n");
            return false;
        }
     
    
        if (NULL == m_handler)
        {
            openRender(nWidth, nHeight);
            if (NULL == m_handler)
            {
                return false;
            }
        }
     
    
        uint32_t width = (uint32_t)nWidth;
        uint32_t height = (uint32_t)nHeight;
        if (m_params.nWidth != width || m_params.nHeight != height)
        {
            closeRender();
            openRender(width, height);
        }
     
    
        VR_FRAME_S renderParam = { 0 };
        renderParam.data[0] = pRgbFrameBuf;
        renderParam.stride[0] = nWidth;
        renderParam.nWidth = nWidth;
        renderParam.nHeight = nHeight;
        if (nPixelFormat == gvspPixelMono8)
        {
            renderParam.format = VR_PIXEL_FMT_MONO8;
        }
        else
        {
            renderParam.format = VR_PIXEL_FMT_RGB24;
        }
     
    
        if (VR_SUCCESS == VR_RenderFrame(m_handler, &renderParam, NULL))
        {
            return true;
        }
        return false;
    }
     
    
    // 显示线程
    // display thread
    void CameraWidget::display()
    {
        while (!m_isExitDisplayThread)
        {
            CFrameInfo frameInfo;
     
    
            if (false == m_qDisplayFrameQueue.get(frameInfo))
            {
                Sleep(1);
                continue;
            }
     
    
            // 判断是否要显示。超过显示上限(30帧),就不做转码、显示处理
            // Judge whether to display. If the upper display limit (30 frames) is exceeded, transcoding and display processing will not be performed
            if (!isTimeToDisplay())
            {
                // 释放内存
                // release memory
                free(frameInfo.m_pImageBuf);
                continue;
            }
     
    
            // mono8格式可不做转码,直接显示,其他格式需要经过转码才能显示
            // mono8 format can be displayed directly without transcoding. Other formats can be displayed only after transcoding
            if (gvspPixelMono8 == frameInfo.m_ePixelType)
            {
                // 显示线程中发送显示信号,在主线程中显示图像
                // Send display signal in display thread and display image in main thread
                if (false == ShowImage(frameInfo.m_pImageBuf, (int)frameInfo.m_nWidth, (int)frameInfo.m_nHeight, frameInfo.m_ePixelType))
                {
                    printf("_render.display failed.\n");
                }
                // 释放内存
                // release memory
                free(frameInfo.m_pImageBuf);
            }
            else
            {
                // 转码
                unsigned char *pRGBbuffer = NULL;
                int nRgbBufferSize = 0;
                nRgbBufferSize = frameInfo.m_nWidth * frameInfo.m_nHeight * 3;
                pRGBbuffer = (unsigned char *)malloc(nRgbBufferSize);
                if (pRGBbuffer == NULL)
                {
                    // 释放内存
                    // release memory
                    free(frameInfo.m_pImageBuf);
                    printf("RGBbuffer malloc failed.\n");
                    continue;
                }
     
    
                IMV_PixelConvertParam stPixelConvertParam;
                stPixelConvertParam.nWidth = frameInfo.m_nWidth;
                stPixelConvertParam.nHeight = frameInfo.m_nHeight;
                stPixelConvertParam.ePixelFormat = frameInfo.m_ePixelType;
                stPixelConvertParam.pSrcData = frameInfo.m_pImageBuf;
                stPixelConvertParam.nSrcDataLen = frameInfo.m_nBufferSize;
                stPixelConvertParam.nPaddingX = frameInfo.m_nPaddingX;
                stPixelConvertParam.nPaddingY = frameInfo.m_nPaddingY;
                stPixelConvertParam.eBayerDemosaic = demosaicNearestNeighbor;
                stPixelConvertParam.eDstPixelFormat = gvspPixelBGR8;
                stPixelConvertParam.pDstBuf = pRGBbuffer;
                stPixelConvertParam.nDstBufSize = nRgbBufferSize;
     
    
                int ret = IMV_PixelConvert(m_devHandle, &stPixelConvertParam);
                if (IMV_OK != ret)
                {
                    // 释放内存
                    // release memory
                    printf("image convert to BGR failed! ErrorCode[%d]\n", ret);
                    free(frameInfo.m_pImageBuf);
                    free(pRGBbuffer);
                    continue;
                }
     
    
                // 释放内存
                // release memory
                free(frameInfo.m_pImageBuf);
     
    
                // 显示
                // display
                if (false == ShowImage(pRGBbuffer, stPixelConvertParam.nWidth, stPixelConvertParam.nHeight, stPixelConvertParam.eDstPixelFormat))
                {
                    printf("_render.display failed.");
                }
                free(pRGBbuffer);
            }
        }
    }
     
    
     
    
    bool CameraWidget::isTimeToDisplay()
    {
        m_mxTime.lock();
     
    
        // 不显示
        // don't display
        if (m_nDisplayInterval <= 0)
        {
            m_mxTime.unlock();
            return false;
        }
     
    
        // 第一帧必须显示
        // the frist frame must be displayed
        if (m_nFirstFrameTime == 0 || m_nLastFrameTime == 0)
        {
            m_nFirstFrameTime = m_elapsedTimer.nsecsElapsed();
            m_nLastFrameTime = m_nFirstFrameTime;
     
    
            m_mxTime.unlock();
            return true;
        }
     
    
        // 当前帧和上一帧的间隔如果大于显示间隔就显示
        // display if the interval between the current frame and the previous frame is greater than the display interval
        uint64_t nCurTimeTmp = m_elapsedTimer.nsecsElapsed();
        uint64_t nAcquisitionInterval = nCurTimeTmp - m_nLastFrameTime;
        if (nAcquisitionInterval > m_nDisplayInterval)
        {
            m_nLastFrameTime = nCurTimeTmp;
            m_mxTime.unlock();
            return true;
        }
     
    
        // 当前帧相对于第一帧的时间间隔
        // Time interval between the current frame and the first frame
        uint64_t nPre = (m_nLastFrameTime - m_nFirstFrameTime) % m_nDisplayInterval;
        if (nPre + nAcquisitionInterval > m_nDisplayInterval)
        {
            m_nLastFrameTime = nCurTimeTmp;
            m_mxTime.unlock();
            return true;
        }
     
    
        m_mxTime.unlock();
        return false;
    }
     
    
    // 设置显示频率
    // set display frequency
    void CameraWidget::setDisplayFPS(int nFPS)
    {
        m_mxTime.lock();
        if (nFPS > 0)
        {
            m_nDisplayInterval = 1000 * 1000 * 1000.0 / nFPS;
        }
        else
        {
            m_nDisplayInterval = 0;
        }
        m_mxTime.unlock();
    }
     
    
    // 窗口关闭响应函数
    // window close response function
    void CameraWidget::closeEvent(QCloseEvent * event)
    {
        IMV_DestroyHandle(m_devHandle);
        m_devHandle = NULL;
    }
     
    
    // 状态栏统计信息 开始
    // Status bar statistics begin
    void CameraWidget::resetStatistic()
    {
        QMutexLocker locker(&m_mxStatistic);
        m_nTotalFrameCount = 0;
        m_listFrameStatInfo.clear();
        m_bNeedUpdate = true;
    }
    QString CameraWidget::getStatistic()
    {
        if (m_mxStatistic.tryLock(30))
        {
            if (m_bNeedUpdate)
            {
                updateStatistic();
            }
     
    
            m_mxStatistic.unlock();
            return m_strStatistic;
        }
        return "";
    }
    void CameraWidget::updateStatistic()
    {
        size_t nFrameCount = m_listFrameStatInfo.size();
        QString strFPS = DEFAULT_ERROR_STRING;
        QString strSpeed = DEFAULT_ERROR_STRING;
     
    
        if (nFrameCount > 1)
        {
            quint64 nTotalSize = 0;
            FrameList::const_iterator it = m_listFrameStatInfo.begin();
     
    
            if (m_listFrameStatInfo.size() == 2)
            {
                nTotalSize = m_listFrameStatInfo.back().m_nFrameSize;
            }
            else
            {
                for (++it; it != m_listFrameStatInfo.end(); ++it)
                {
                    nTotalSize += it->m_nFrameSize;
                }
            }
     
    
            const FrameStatInfo& first = m_listFrameStatInfo.front();
            const FrameStatInfo& last = m_listFrameStatInfo.back();
     
    
            qint64 nsecs = last.m_nPassTime - first.m_nPassTime;
     
    
            if (nsecs > 0)
            {
                double dFPS = (nFrameCount - 1) * ((double)1000000000.0 / nsecs);
                double dSpeed = nTotalSize * ((double)1000000000.0 / nsecs) / (1000.0) / (1000.0) * (8.0);
                strFPS = QString::number(dFPS, 'f', 2);
                strSpeed = QString::number(dSpeed, 'f', 2);
            }
        }
     
    
        m_strStatistic = QString("Stream: %1 images   %2 FPS   %3 Mbps")
            .arg(m_nTotalFrameCount)
            .arg(strFPS)
            .arg(strSpeed);
        m_bNeedUpdate = false;
    }
    void CameraWidget::recvNewFrame(quint32 frameSize)
    {
        QMutexLocker locker(&m_mxStatistic);
        if (m_listFrameStatInfo.size() >= MAX_FRAME_STAT_NUM)
        {
            m_listFrameStatInfo.pop_front();
        }
        m_listFrameStatInfo.push_back(FrameStatInfo(frameSize, m_elapsedTimer.nsecsElapsed()));
        ++m_nTotalFrameCount;
     
    
        if (m_listFrameStatInfo.size() > MIN_LEFT_LIST_NUM)
        {
            FrameStatInfo infoFirst = m_listFrameStatInfo.front();
            FrameStatInfo infoLast = m_listFrameStatInfo.back();
            while (m_listFrameStatInfo.size() > MIN_LEFT_LIST_NUM && infoLast.m_nPassTime - infoFirst.m_nPassTime > MAX_STATISTIC_INTERVAL)
            {
                m_listFrameStatInfo.pop_front();
                infoFirst = m_listFrameStatInfo.front();
            }
        }
     
    
        m_bNeedUpdate = true;
    }
    // 状态栏统计信息 end
    // Status bar statistics ending
    // VedioRender显示相关 start
    // VedioRender releative display start
    bool CameraWidget::openRender(int width, int height)
    {
        if (NULL != m_handler ||
            0 == width ||
            0 == height)
        {
            return false;
        }
     
    
        memset(&m_params, 0, sizeof(m_params));
        m_params.eVideoRenderMode = VR_MODE_GDI;
        m_params.hWnd = m_hWnd;
        m_params.nWidth = width;
        m_params.nHeight = height;
     
    
        VR_ERR_E ret = VR_Open(&m_params, &m_handler);
        if (ret == VR_NOT_SUPPORT)
        {
            printf("%s cant't display YUV on this computer", __FUNCTION__);
            return false;
        }
     
    
        printf("%s open failed. error code[%d]", __FUNCTION__, ret);
        return false;
    }
     
    
    bool CameraWidget::closeRender()
    {
        if (m_handler != NULL)
        {
            VR_Close(m_handler);
            m_handler = NULL;
        }
        return true;
    }
    6) widget.ui

    7)camerawidget.ui

     

     

  • 相关阅读:
    1. HelmTemplate 3分钟将项目部署至k8s
    分布式搜索引擎es-3
    【2021集创赛】Arm杯三等奖:基于FPGA的人脸检测SoC设计
    嵌入式面试常见问题(三)
    【prometheus+grafana】快速入门搭建-服务监控各插件及企业微信告警
    笔试面试相关记录(4)
    SwiftUI调用相机拍照
    申请400开头电话的步骤及注意事项
    STM32实战总结:HAL之PWM蜂鸣器
    计算机毕业设计springboot+vue基本微信小程序的家装公司管理系统小程序
  • 原文地址:https://blog.csdn.net/zkmrobot/article/details/125562525