机器人地面站-[QGroundControl源码解析]-[9]-[Camera]

2023-05-16

目录

前言

一.QGCCameraManager

二.QGCCameraIO

三.QGCCameraControl


前言

本篇介绍Camera文件夹下的内容,该文件夹下又三个类文件,分别是QGCCameraManager,QGCCameraIO,QGCCameraControl,按照命名可以理解这个三个类是对项目中的相机进行管理的,分别是QGCCameraManager管理camera实例,camera实例的逻辑在QGCCameraControl中编写,io功能在QGCCameraIO中编写。下面我们分别对这三个类的内容进行分析。

一.QGCCameraManager

该类主要用于管理相机设备实例,主要操作包含,控制相机的更换,手柄的更换,视频流的更换,相机信息的获取,心跳机制的管理,以及相机所有功能如截图,录像,存储等。

代码和注释如下

/*!
 * @file
 *   @brief Camera Controller
 *   @author Gus Grubba <gus@auterion.com>
 *
 */

/// @file
/// @brief  MAVLink Camera API. Camera Manager.
/// @author Gus Grubba <gus@auterion.com>

#pragma once

#include "QGCApplication.h"
#include <QLoggingCategory>
#include "QmlObjectListModel.h"
#include "QGCCameraControl.h"

#include <QObject>
#include <QTimer>

//为相机管理建立日志类
Q_DECLARE_LOGGING_CATEGORY(CameraManagerLog)

class Joystick;

//-----------------------------------------------------------------------------
/// Camera Manager
class QGCCameraManager : public QObject
{
    Q_OBJECT
public:
    QGCCameraManager(Vehicle* vehicle);
    virtual ~QGCCameraManager();

    //相机列表
    Q_PROPERTY(QmlObjectListModel*  cameras                 READ cameras                                        NOTIFY camerasChanged)
    //相机标签列表
    Q_PROPERTY(QStringList          cameraLabels            READ cameraLabels                                   NOTIFY cameraLabelsChanged)
    //当前相机实例
    Q_PROPERTY(QGCCameraControl*    currentCameraInstance   READ currentCameraInstance                          NOTIFY currentCameraChanged)
    //当前相机
    Q_PROPERTY(int                  currentCamera           READ currentCamera      WRITE  setCurrentCamera     NOTIFY currentCameraChanged)

    //-- Return a list of cameras provided by this vehicle 返回由该设备提供的摄像机列表
    virtual QmlObjectListModel* cameras             () { return &_cameras; }
    //-- Camera names to show the user (for selection) 显示给用户的相机名称(供选择)
    virtual QStringList         cameraLabels        () { return _cameraLabels; }
    //-- Current selected camera 当前选择的相机
    virtual int                 currentCamera       () { return _currentCamera; }
    virtual QGCCameraControl*   currentCameraInstance();
    //-- Set current camera
    virtual void                setCurrentCamera    (int sel);
    //-- Current stream 当前的流
    virtual QGCVideoStreamInfo* currentStreamInstance();
    //-- Current thermal stream
    virtual QGCVideoStreamInfo* thermalStreamInstance();

signals:
    void    camerasChanged          ();
    void    cameraLabelsChanged     ();
    void    currentCameraChanged    ();
    void    streamChanged           ();

protected slots:
    virtual void    _vehicleReady           (bool ready); //设备准备
    virtual void    _mavlinkMessageReceived (const mavlink_message_t& message); //mavlink消息收到
    virtual void    _activeJoystickChanged  (Joystick* joystick); //激活的手柄更改
    virtual void    _stepZoom               (int direction); //缩放步骤
    virtual void    _startZoom              (int direction); //开始缩放
    virtual void    _stopZoom               (); //结束缩放
    virtual void    _stepCamera             (int direction); //
    virtual void    _stepStream             (int direction);
    virtual void    _cameraTimeout          (); //相机超时
    virtual void    _triggerCamera          (); //触发相机
    virtual void    _startVideoRecording    (); //开始视频录制
    virtual void    _stopVideoRecording     (); //结束视频录制
    virtual void    _toggleVideoRecording   (); //

protected:
    virtual QGCCameraControl* _findCamera   (int id); //找到相机
    virtual void    _requestCameraInfo      (int compID); //请求相机信息
    virtual void    _handleHeartbeat        (const mavlink_message_t& message); //处理心跳
    virtual void    _handleCameraInfo       (const mavlink_message_t& message); //处理相机信息
    virtual void    _handleStorageInfo      (const mavlink_message_t& message); //处理存储信息
    virtual void    _handleCameraSettings   (const mavlink_message_t& message); //处理相机设置
    virtual void    _handleParamAck         (const mavlink_message_t& message); //处理参数应答
    virtual void    _handleParamValue       (const mavlink_message_t& message); //处理参数值
    virtual void    _handleCaptureStatus    (const mavlink_message_t& message); //处理截图状态
    virtual void    _handleVideoStreamInfo  (const mavlink_message_t& message); //处理视频流信息
    virtual void    _handleVideoStreamStatus(const mavlink_message_t& message); //处理视频流状态
    virtual void    _handleBatteryStatus    (const mavlink_message_t& message); //处理电池状态

protected:

    //内置类
    class CameraStruct : public QObject {
    public:
        CameraStruct(QObject* parent, uint8_t compID_);
        QElapsedTimer lastHeartbeat; //上一次心跳时间
        bool    infoReceived = false; //信息是否接收到
        bool    gaveUp       = false; //放弃
        int     tryCount     = 0; //尝试次数
        uint8_t compID       = 0; //comid
    };

    Vehicle*            _vehicle            = nullptr; //设备指针
    Joystick*           _activeJoystick     = nullptr; //手柄
    bool                _vehicleReadyState  = false; //设备准备状态
    int                 _currentTask        = 0; //当前任务
    QmlObjectListModel  _cameras; //相机列表
    QStringList         _cameraLabels; //相机名称列表
    int                 _currentCamera      = 0; //当前相机
    QElapsedTimer       _lastZoomChange;
    QElapsedTimer       _lastCameraChange;
    QTimer              _cameraTimer; //相机计时器
    QMap<QString, CameraStruct*> _cameraInfoRequest; //相机信息请求
};

cc文件如下

/*!
 * @file
 *   @brief Camera Controller
 *   @author Gus Grubba <gus@auterion.com>
 *
 */

#include "QGCApplication.h"
#include "QGCCameraManager.h"
#include "JoystickManager.h"

QGC_LOGGING_CATEGORY(CameraManagerLog, "CameraManagerLog")

//-----------------------------------------------------------------------------
// CameraStruct 构造
QGCCameraManager::CameraStruct::CameraStruct(QObject* parent, uint8_t compID_)
    : QObject(parent)
    , compID(compID_)
{
}

//-----------------------------------------------------------------------------
//QGCCameraManager构造
QGCCameraManager::QGCCameraManager(Vehicle *vehicle)
    : _vehicle(vehicle)
{
    QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
    qCDebug(CameraManagerLog) << "QGCCameraManager Created";
    //绑定槽函数
    connect(qgcApp()->toolbox()->multiVehicleManager(), &MultiVehicleManager::parameterReadyVehicleAvailableChanged, this, &QGCCameraManager::_vehicleReady);
    connect(_vehicle, &Vehicle::mavlinkMessageReceived, this, &QGCCameraManager::_mavlinkMessageReceived);
    //相机超时
    connect(&_cameraTimer, &QTimer::timeout, this, &QGCCameraManager::_cameraTimeout);
    _cameraTimer.setSingleShot(false);
    //计时器开启
    _lastZoomChange.start();
    _lastCameraChange.start();
    _cameraTimer.start(500);
}

//-----------------------------------------------------------------------------
QGCCameraManager::~QGCCameraManager()
{
}

//-----------------------------------------------------------------------------
// 更新当前相机
void
QGCCameraManager::setCurrentCamera(int sel)
{
    if(sel != _currentCamera && sel >= 0 && sel < _cameras.count()) {
        _currentCamera = sel;
        emit currentCameraChanged();
        emit streamChanged();
    }
}

//-----------------------------------------------------------------------------
//设备就绪
void
QGCCameraManager::_vehicleReady(bool ready)
{
    qCDebug(CameraManagerLog) << "_vehicleReady(" << ready << ")";
    if(ready) {
        if(qgcApp()->toolbox()->multiVehicleManager()->activeVehicle() == _vehicle) {
            _vehicleReadyState = true;
            //获取到手柄实例
            JoystickManager *pJoyMgr = qgcApp()->toolbox()->joystickManager();
            _activeJoystickChanged(pJoyMgr->activeJoystick());
            connect(pJoyMgr, &JoystickManager::activeJoystickChanged, this, &QGCCameraManager::_activeJoystickChanged);
        }
    }
}

//-----------------------------------------------------------------------------
void
QGCCameraManager::_mavlinkMessageReceived(const mavlink_message_t& message)
{
    //-- Only pay attention to camera components, as identified by their compId
    // 只注意相机组件,由它们的compId识别 组件id 对应typedef enum MAV_COMPONENT
    if(message.sysid == _vehicle->id() && (message.compid >= MAV_COMP_ID_CAMERA && message.compid <= MAV_COMP_ID_CAMERA6)) {
        //根据mavlink消息的不同状态执行指令
        switch (message.msgid) {
            case MAVLINK_MSG_ID_CAMERA_CAPTURE_STATUS:
                _handleCaptureStatus(message);
                break;
            case MAVLINK_MSG_ID_STORAGE_INFORMATION:
                _handleStorageInfo(message);
                break;
            case MAVLINK_MSG_ID_HEARTBEAT:
                _handleHeartbeat(message);
                break;
            case MAVLINK_MSG_ID_CAMERA_INFORMATION:
                _handleCameraInfo(message);
                break;
            case MAVLINK_MSG_ID_CAMERA_SETTINGS:
                _handleCameraSettings(message);
                break;
            case MAVLINK_MSG_ID_PARAM_EXT_ACK:
                _handleParamAck(message);
                break;
            case MAVLINK_MSG_ID_PARAM_EXT_VALUE:
                _handleParamValue(message);
                break;
            case MAVLINK_MSG_ID_VIDEO_STREAM_INFORMATION:
                _handleVideoStreamInfo(message);
                break;
            case MAVLINK_MSG_ID_VIDEO_STREAM_STATUS:
                _handleVideoStreamStatus(message);
                break;
            case MAVLINK_MSG_ID_BATTERY_STATUS:
                _handleBatteryStatus(message);
                break;
        }
    }
}

//-----------------------------------------------------------------------------
//处理心跳
void
QGCCameraManager::_handleHeartbeat(const mavlink_message_t &message)
{
    mavlink_heartbeat_t heartbeat;
    mavlink_msg_heartbeat_decode(&message, &heartbeat);
    //-- First time hearing from this one?  第一次收到这个camera的心跳
    QString sCompID = QString::number(message.compid);
    if(!_cameraInfoRequest.contains(sCompID)) {
        //不包含就添加
        qCDebug(CameraManagerLog) << "Hearbeat from " << message.compid;
        CameraStruct* pInfo = new CameraStruct(this, message.compid);
        pInfo->lastHeartbeat.start();
        _cameraInfoRequest[sCompID] = pInfo;
        //-- Request camera info 请求相机信息
        _requestCameraInfo(message.compid);
    } else {
        if(_cameraInfoRequest[sCompID]) {
            CameraStruct* pInfo = _cameraInfoRequest[sCompID];
            //-- Check if we have indeed received the camera info 检查我们是否确实收到了相机信息
            if(pInfo->infoReceived) {
                //-- We have it. Just update the heartbeat timeout 我们拥有它。只需更新心跳超时
                pInfo->lastHeartbeat.start();
            } else {
                //-- Try again. Maybe.
                if(pInfo->lastHeartbeat.elapsed() > 2000) {
                    //如果超时了并且次数超过3次了 就放弃这个相机了
                    if(pInfo->tryCount > 3) {
                        if(!pInfo->gaveUp) {
                            pInfo->gaveUp = true;
                            qWarning() << "Giving up requesting camera info from" << _vehicle->id() << message.compid;
                        }
                    } else {
                        pInfo->tryCount++;
                        //-- Request camera info again.
                        // 否则继续请求相机信息
                        _requestCameraInfo(message.compid);
                    }
                }
            }
        } else {
            qWarning() << "_cameraInfoRequest[" << sCompID << "] is null";
        }
    }
}

//-----------------------------------------------------------------------------
//获取当前相机实例
QGCCameraControl*
QGCCameraManager::currentCameraInstance()
{
    if(_currentCamera < _cameras.count() && _cameras.count()) {
        QGCCameraControl* pCamera = qobject_cast<QGCCameraControl*>(_cameras[_currentCamera]);
        return pCamera;
    }
    return nullptr;
}

//-----------------------------------------------------------------------------
//获取当前流实例
QGCVideoStreamInfo*
QGCCameraManager::currentStreamInstance()
{
    QGCCameraControl* pCamera = currentCameraInstance();
    if(pCamera) {
        QGCVideoStreamInfo* pInfo = pCamera->currentStreamInstance();
        return pInfo;
    }
    return nullptr;
}

//-----------------------------------------------------------------------------
QGCVideoStreamInfo*
QGCCameraManager::thermalStreamInstance()
{
    QGCCameraControl* pCamera = currentCameraInstance();
    if(pCamera) {
        QGCVideoStreamInfo* pInfo = pCamera->thermalStreamInstance();
        return pInfo;
    }
    return nullptr;
}

//-----------------------------------------------------------------------------
//查找相机
QGCCameraControl*
QGCCameraManager::_findCamera(int id)
{
    for(int i = 0; i < _cameras.count(); i++) {
        if(_cameras[i]) {
            QGCCameraControl* pCamera = qobject_cast<QGCCameraControl*>(_cameras[i]);
            if(pCamera) {
                if(pCamera->compID() == id) {
                    return pCamera;
                }
            } else {
                qCritical() << "Null QGCCameraControl instance";
            }
        }
    }
    //qWarning() << "Camera component id not found:" << id;
    return nullptr;
}

//-----------------------------------------------------------------------------
void
QGCCameraManager::_handleCameraInfo(const mavlink_message_t& message)
{
    //-- Have we requested it?
    //是否之前已经请求过相机信息
    QString sCompID = QString::number(message.compid);
    //如果还没有请求过
    if(_cameraInfoRequest.contains(sCompID) && !_cameraInfoRequest[sCompID]->infoReceived) {
        //-- Flag it as done 标识为true
        _cameraInfoRequest[sCompID]->infoReceived = true;
        //将mavlink数据解码成相机信息
        mavlink_camera_information_t info;
        mavlink_msg_camera_information_decode(&message, &info);
        qCDebug(CameraManagerLog) << "_handleCameraInfo:" << reinterpret_cast<const char*>(info.model_name) << reinterpret_cast<const char*>(info.vendor_name) << "Comp ID:" << message.compid;
        //创建相机实例
        QGCCameraControl* pCamera = _vehicle->firmwarePlugin()->createCameraControl(&info, _vehicle, message.compid, this);
        if(pCamera) {
            //指定pCamera对象所有权是c++
            QQmlEngine::setObjectOwnership(pCamera, QQmlEngine::CppOwnership);
            _cameras.append(pCamera);
            _cameraLabels << pCamera->modelName();
            //触发信号
            emit camerasChanged();
            emit cameraLabelsChanged();
        }
    }
}

//-----------------------------------------------------------------------------
//相机超时
void
QGCCameraManager::_cameraTimeout()
{
    //-- Iterate cameras
    foreach(QString sCompID, _cameraInfoRequest.keys()) {
        if(_cameraInfoRequest[sCompID]) {
            CameraStruct* pInfo = _cameraInfoRequest[sCompID];
            //-- Have we received a camera info message?
            if(pInfo->infoReceived) {
                //-- Has the camera stopped talking to us?
                //超时
                if(pInfo->lastHeartbeat.elapsed() > 5000) {
                    //-- Camera is gone. Remove it.
                    //清除
                    bool autoStream = false;
                    QGCCameraControl* pCamera = _findCamera(pInfo->compID);
                    if(pCamera) {
                        qWarning() << "Camera" << pCamera->modelName() << "stopped transmitting. Removing from list.";
                        int idx = _cameraLabels.indexOf(pCamera->modelName());
                        if(idx >= 0) {
                            _cameraLabels.removeAt(idx);
                        }
                        idx = _cameras.indexOf(pCamera);
                        if(idx >= 0) {
                            _cameras.removeAt(idx);
                        }
                        autoStream = pCamera->autoStream();
                        pCamera->deleteLater();
                        delete pInfo;
                    }
                    _cameraInfoRequest.remove(sCompID);
                    emit cameraLabelsChanged();
                    //-- If we have another camera, switch current camera.
                    if(_cameras.count()) {
                        setCurrentCamera(0);
                    } else {
                        //-- We're out of cameras
                        emit camerasChanged();
                        if(autoStream) {
                            emit streamChanged();
                        }
                    }
                    //-- Exit loop.
                    return;
                }
            }
        }
    }
}

//-----------------------------------------------------------------------------
//处理截屏事件
void
QGCCameraManager::_handleCaptureStatus(const mavlink_message_t &message)
{
    QGCCameraControl* pCamera = _findCamera(message.compid);
    if(pCamera) {
        mavlink_camera_capture_status_t cap;
        mavlink_msg_camera_capture_status_decode(&message, &cap);
        pCamera->handleCaptureStatus(cap);
    }
}

//-----------------------------------------------------------------------------
//处理存储信息
void
QGCCameraManager::_handleStorageInfo(const mavlink_message_t& message)
{
    QGCCameraControl* pCamera = _findCamera(message.compid);
    if(pCamera) {
        mavlink_storage_information_t st;
        mavlink_msg_storage_information_decode(&message, &st);
        pCamera->handleStorageInfo(st);
    }
}

//-----------------------------------------------------------------------------
//处理相机设置
void
QGCCameraManager::_handleCameraSettings(const mavlink_message_t& message)
{
    QGCCameraControl* pCamera = _findCamera(message.compid);
    if(pCamera) {
        mavlink_camera_settings_t settings;
        mavlink_msg_camera_settings_decode(&message, &settings);
        pCamera->handleSettings(settings);
    }
}

//-----------------------------------------------------------------------------
//处理相机参数应答
void
QGCCameraManager::_handleParamAck(const mavlink_message_t& message)
{
    QGCCameraControl* pCamera = _findCamera(message.compid);
    if(pCamera) {
        mavlink_param_ext_ack_t ack;
        mavlink_msg_param_ext_ack_decode(&message, &ack);
        pCamera->handleParamAck(ack);
    }
}

//-----------------------------------------------------------------------------
//处理相机参数值
void
QGCCameraManager::_handleParamValue(const mavlink_message_t& message)
{
    QGCCameraControl* pCamera = _findCamera(message.compid);
    if(pCamera) {
        mavlink_param_ext_value_t value;
        mavlink_msg_param_ext_value_decode(&message, &value);
        pCamera->handleParamValue(value);
    }
}

//-----------------------------------------------------------------------------
//处理相机视频流
void
QGCCameraManager::_handleVideoStreamInfo(const mavlink_message_t& message)
{
    QGCCameraControl* pCamera = _findCamera(message.compid);
    if(pCamera) {
        mavlink_video_stream_information_t streamInfo;
        mavlink_msg_video_stream_information_decode(&message, &streamInfo);
        pCamera->handleVideoInfo(&streamInfo);
    }
}

//-----------------------------------------------------------------------------
//处理相机视频流状态
void
QGCCameraManager::_handleVideoStreamStatus(const mavlink_message_t& message)
{
    QGCCameraControl* pCamera = _findCamera(message.compid);
    if(pCamera) {
        mavlink_video_stream_status_t streamStatus;
        mavlink_msg_video_stream_status_decode(&message, &streamStatus);
        pCamera->handleVideoStatus(&streamStatus);
    }
}

//-----------------------------------------------------------------------------
//处理电池状态
void
QGCCameraManager::_handleBatteryStatus(const mavlink_message_t& message)
{
    QGCCameraControl* pCamera = _findCamera(message.compid);
    if(pCamera) {
        mavlink_battery_status_t batteryStatus;
        mavlink_msg_battery_status_decode(&message, &batteryStatus);
        pCamera->handleBatteryStatus(batteryStatus);
    }
}

//-----------------------------------------------------------------------------
//请求相机信息
void
QGCCameraManager::_requestCameraInfo(int compID)
{
    qCDebug(CameraManagerLog) << "_requestCameraInfo(" << compID << ")";
    if(_vehicle) {
        //发送mavlink请求
        _vehicle->sendMavCommand(
            compID,                                 // target component
            MAV_CMD_REQUEST_CAMERA_INFORMATION,     // command id
            false,                                  // showError
            1);                                     // Do Request
    }
}

//----------------------------------------------------------------------------------------
//激活手柄发生改变
void
QGCCameraManager::_activeJoystickChanged(Joystick* joystick)
{
    qCDebug(CameraManagerLog) << "Joystick changed";
    if(_activeJoystick) {
        disconnect(_activeJoystick, &Joystick::stepZoom,            this, &QGCCameraManager::_stepZoom);
        disconnect(_activeJoystick, &Joystick::startContinuousZoom, this, &QGCCameraManager::_startZoom);
        disconnect(_activeJoystick, &Joystick::stopContinuousZoom,  this, &QGCCameraManager::_stopZoom);
        disconnect(_activeJoystick, &Joystick::stepCamera,          this, &QGCCameraManager::_stepCamera);
        disconnect(_activeJoystick, &Joystick::stepStream,          this, &QGCCameraManager::_stepStream);
        disconnect(_activeJoystick, &Joystick::triggerCamera,       this, &QGCCameraManager::_triggerCamera);
        disconnect(_activeJoystick, &Joystick::startVideoRecord,    this, &QGCCameraManager::_startVideoRecording);
        disconnect(_activeJoystick, &Joystick::stopVideoRecord,     this, &QGCCameraManager::_stopVideoRecording);
        disconnect(_activeJoystick, &Joystick::toggleVideoRecord,   this, &QGCCameraManager::_toggleVideoRecording);
    }
    _activeJoystick = joystick;
    if(_activeJoystick) {
        connect(_activeJoystick, &Joystick::stepZoom,               this, &QGCCameraManager::_stepZoom);
        connect(_activeJoystick, &Joystick::startContinuousZoom,    this, &QGCCameraManager::_startZoom);
        connect(_activeJoystick, &Joystick::stopContinuousZoom,     this, &QGCCameraManager::_stopZoom);
        connect(_activeJoystick, &Joystick::stepCamera,             this, &QGCCameraManager::_stepCamera);
        connect(_activeJoystick, &Joystick::stepStream,             this, &QGCCameraManager::_stepStream);
        connect(_activeJoystick, &Joystick::triggerCamera,          this, &QGCCameraManager::_triggerCamera);
        connect(_activeJoystick, &Joystick::startVideoRecord,       this, &QGCCameraManager::_startVideoRecording);
        connect(_activeJoystick, &Joystick::stopVideoRecord,        this, &QGCCameraManager::_stopVideoRecording);
        connect(_activeJoystick, &Joystick::toggleVideoRecord,      this, &QGCCameraManager::_toggleVideoRecording);
    }
}

//-----------------------------------------------------------------------------
//触发相机拍照
void
QGCCameraManager::_triggerCamera()
{
    QGCCameraControl* pCamera = currentCameraInstance();
    if(pCamera) {
        pCamera->takePhoto();
    }
}

//-----------------------------------------------------------------------------
//开始视频录像
void
QGCCameraManager::_startVideoRecording()
{
    QGCCameraControl* pCamera = currentCameraInstance();
    if(pCamera) {
        pCamera->startVideo();
    }
}

//-----------------------------------------------------------------------------
void
QGCCameraManager::_stopVideoRecording()
{
    QGCCameraControl* pCamera = currentCameraInstance();
    if(pCamera) {
        pCamera->stopVideo();
    }
}

//-----------------------------------------------------------------------------
void
QGCCameraManager::_toggleVideoRecording()
{
    QGCCameraControl* pCamera = currentCameraInstance();
    if(pCamera) {
        pCamera->toggleVideo();
    }
}

//-----------------------------------------------------------------------------
//聚焦
void
QGCCameraManager::_stepZoom(int direction)
{
    if(_lastZoomChange.elapsed() > 40) {
        _lastZoomChange.start();
        qCDebug(CameraManagerLog) << "Step Camera Zoom" << direction;
        QGCCameraControl* pCamera = currentCameraInstance();
        if(pCamera) {
            pCamera->stepZoom(direction);
        }
    }
}

//-----------------------------------------------------------------------------
void
QGCCameraManager::_startZoom(int direction)
{
    qCDebug(CameraManagerLog) << "Start Camera Zoom" << direction;
    QGCCameraControl* pCamera = currentCameraInstance();
    if(pCamera) {
        pCamera->startZoom(direction);
    }
}

//-----------------------------------------------------------------------------
void
QGCCameraManager::_stopZoom()
{
    qCDebug(CameraManagerLog) << "Stop Camera Zoom";
    QGCCameraControl* pCamera = currentCameraInstance();
    if(pCamera) {
        pCamera->stopZoom();
    }
}

//-----------------------------------------------------------------------------
void
QGCCameraManager::_stepCamera(int direction)
{
    if(_lastCameraChange.elapsed() > 1000) {
        _lastCameraChange.start();
        qCDebug(CameraManagerLog) << "Step Camera" << direction;
        int c = _currentCamera + direction;
        if(c < 0) c = _cameras.count() - 1;
        if(c >= _cameras.count()) c = 0;
        setCurrentCamera(c);
    }
}

//-----------------------------------------------------------------------------
void
QGCCameraManager::_stepStream(int direction)
{
    if(_lastCameraChange.elapsed() > 1000) {
        _lastCameraChange.start();
        QGCCameraControl* pCamera = currentCameraInstance();
        if(pCamera) {
            qCDebug(CameraManagerLog) << "Step Camera Stream" << direction;
            int c = pCamera->currentStream() + direction;
            if(c < 0) c = pCamera->streams()->count() - 1;
            if(c >= pCamera->streams()->count()) c = 0;
            pCamera->setCurrentStream(c);
        }
    }
}


二.QGCCameraIO

该类主要处理相机的参数请求,参数应答,写参数,保存参数写入状态,和一些计时器用来设置写入重试和参数请求次数。

/*!
 * @file
 *   @brief Camera Controller
 *   @author Gus Grubba <gus@auterion.com>
 *
 */

/// @file
/// @brief  MAVLink Camera API. Camera parameter handler.
/// @author Gus Grubba <gus@auterion.com>

#pragma once

#include "QGCApplication.h"
#include <QLoggingCategory>

class QGCCameraControl;

Q_DECLARE_LOGGING_CATEGORY(CameraIOLog)
Q_DECLARE_LOGGING_CATEGORY(CameraIOLogVerbose)

//mavlink包
MAVPACKED(
typedef struct {
    union {
        float       param_float;
        double      param_double;
        int64_t     param_int64;
        uint64_t    param_uint64;
        int32_t     param_int32;
        uint32_t    param_uint32;
        int16_t     param_int16;
        uint16_t    param_uint16;
        int8_t      param_int8;
        uint8_t     param_uint8;
        uint8_t     bytes[MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_VALUE_LEN];
    };
    uint8_t type;
}) param_ext_union_t;

//-----------------------------------------------------------------------------
/// Camera parameter handler.
/// 相机参数处理器
class QGCCameraParamIO : public QObject
{
public:
    QGCCameraParamIO(QGCCameraControl* control, Fact* fact, Vehicle* vehicle);

    void        handleParamAck              (const mavlink_param_ext_ack_t& ack); //处理相机参数应答
    void        handleParamValue            (const mavlink_param_ext_value_t& value); //处理相机参数值
    void        setParamRequest             (); //设置参数请求
    bool        paramDone                   () const { return _done; }  //参数是否完成
    void        paramRequest                (bool reset = true); //参数请求
    void        sendParameter               (bool updateUI = false); //发送参数

    QStringList  optNames;   //选项名
    QVariantList optVariants;  //选项值

private slots:
    void        _paramWriteTimeout          (); //参数写入超时
    void        _paramRequestTimeout        (); //参数请求超时
    void        _factChanged                (QVariant value);
    void        _containerRawValueChanged   (const QVariant value);

private:
    void        _sendParameter              ();  //发送参数
    QVariant    _valueFromMessage           (const char* value, uint8_t param_type); //从消息中提取值

private:
    QGCCameraControl*   _control;
    Fact*               _fact;
    Vehicle*            _vehicle;
    int                 _sentRetries; //发送尝试次数
    int                 _requestRetries; //请求尝试次数
    bool                _paramRequestReceived; //参数请求是否收到
    QTimer              _paramWriteTimer; //写参数计时器
    QTimer              _paramRequestTimer; //请求参数计时器
    bool                _done; //完成状态
    bool                _updateOnSet;
    MAV_PARAM_EXT_TYPE  _mavParamType; //mavlink参数类型
    MAVLinkProtocol*    _pMavlink; //mavlink实例
    bool                _forceUIUpdate; //是否强制ui重绘
};

/*!
 * @file
 *   @brief Camera Controller
 *   @author Gus Grubba <gus@auterion.com>
 *
 */

#include "QGCCameraControl.h"
#include "QGCCameraIO.h"

QGC_LOGGING_CATEGORY(CameraIOLog, "CameraIOLog")
QGC_LOGGING_CATEGORY(CameraIOLogVerbose, "CameraIOLogVerbose")

//-----------------------------------------------------------------------------
//QGCCameraParamIO构造
QGCCameraParamIO::QGCCameraParamIO(QGCCameraControl *control, Fact* fact, Vehicle *vehicle)
    : QObject(control)
    , _control(control)
    , _fact(fact)
    , _vehicle(vehicle)
    , _sentRetries(0)
    , _requestRetries(0)
    , _done(false)
    , _updateOnSet(false)
    , _forceUIUpdate(false)
{
    //初始化变量
    //实例交给C++
    QQmlEngine::setObjectOwnership(this, QQmlEngine::CppOwnership);
    //设置定时器单次执行延时3s
    _paramWriteTimer.setSingleShot(true);
    _paramWriteTimer.setInterval(3000);
    _paramRequestTimer.setSingleShot(true);
    _paramRequestTimer.setInterval(3500);
    if(_fact->writeOnly()) {
        //-- Write mode is always "done" as it won't ever read
        _done = true;
    } else {
        connect(&_paramRequestTimer, &QTimer::timeout, this, &QGCCameraParamIO::_paramRequestTimeout);
    }
    //绑定函数
    connect(&_paramWriteTimer,   &QTimer::timeout, this, &QGCCameraParamIO::_paramWriteTimeout);
    connect(_fact, &Fact::rawValueChanged, this, &QGCCameraParamIO::_factChanged);
    connect(_fact, &Fact::_containerRawValueChanged, this, &QGCCameraParamIO::_containerRawValueChanged);
    _pMavlink = qgcApp()->toolbox()->mavlinkProtocol();
    //-- TODO: Even though we don't use anything larger than 32-bit, this should
    //   probably be updated.
    //尽管我们没有使用超过32位的数据,但这可能需要更新。
    switch (_fact->type()) {
        case FactMetaData::valueTypeUint8:
        case FactMetaData::valueTypeBool:
            _mavParamType = MAV_PARAM_EXT_TYPE_UINT8;
            break;
        case FactMetaData::valueTypeInt8:
            _mavParamType = MAV_PARAM_EXT_TYPE_INT8;
            break;
        case FactMetaData::valueTypeUint16:
            _mavParamType = MAV_PARAM_EXT_TYPE_UINT16;
            break;
        case FactMetaData::valueTypeInt16:
            _mavParamType = MAV_PARAM_EXT_TYPE_INT16;
            break;
        case FactMetaData::valueTypeUint32:
            _mavParamType = MAV_PARAM_EXT_TYPE_UINT32;
            break;
        case FactMetaData::valueTypeUint64:
            _mavParamType = MAV_PARAM_EXT_TYPE_UINT64;
            break;
        case FactMetaData::valueTypeInt64:
            _mavParamType = MAV_PARAM_EXT_TYPE_INT64;
            break;
        case FactMetaData::valueTypeFloat:
            _mavParamType = MAV_PARAM_EXT_TYPE_REAL32;
            break;
        case FactMetaData::valueTypeDouble:
            _mavParamType = MAV_PARAM_EXT_TYPE_REAL64;
            break;
            //-- String and custom are the same for now
        case FactMetaData::valueTypeString:
        case FactMetaData::valueTypeCustom:
            _mavParamType = MAV_PARAM_EXT_TYPE_CUSTOM;
            break;
        default:
            qWarning() << "Unsupported fact type" << _fact->type() << "for" << _fact->name();
        case FactMetaData::valueTypeInt32:
            _mavParamType = MAV_PARAM_EXT_TYPE_INT32;
            break;
    }
}

//-----------------------------------------------------------------------------
void
QGCCameraParamIO::setParamRequest()
{
    if(!_fact->writeOnly()) {
        _paramRequestReceived = false;
        _requestRetries = 0;
        _paramRequestTimer.start();
    }
}

//-----------------------------------------------------------------------------
void
QGCCameraParamIO::_factChanged(QVariant value)
{
    if(!_forceUIUpdate) {
        Q_UNUSED(value);
        qCDebug(CameraIOLog) << "UI Fact" << _fact->name() << "changed to" << value;
        _control->factChanged(_fact);
    }
}

//-----------------------------------------------------------------------------
void
QGCCameraParamIO::_containerRawValueChanged(const QVariant value)
{
    if(!_fact->readOnly()) {
        Q_UNUSED(value);
        qCDebug(CameraIOLog) << "Update Fact from camera" << _fact->name();
        _sentRetries = 0;
        _sendParameter();
    }
}

//-----------------------------------------------------------------------------
void
QGCCameraParamIO::sendParameter(bool updateUI)
{
    qCDebug(CameraIOLog) << "Send Fact" << _fact->name();
    _sentRetries = 0;
    _updateOnSet = updateUI;
    _sendParameter();
}

//-----------------------------------------------------------------------------
//发送参数
void
QGCCameraParamIO::_sendParameter()
{
    //获取mavlink实例
    WeakLinkInterfacePtr weakLink = _vehicle->vehicleLinkManager()->primaryLink();
    if (!weakLink.expired()) {
        //如果有效
        SharedLinkInterfacePtr sharedLink = weakLink.lock();
        //构造mavlink_param_ext_set_t
        mavlink_param_ext_set_t p;
        //初始化mavlink_param_ext_set_t
        memset(&p, 0, sizeof(mavlink_param_ext_set_t));
        //
        param_ext_union_t   union_value;
        mavlink_message_t   msg;
        //得到factType
        FactMetaData::ValueType_t factType = _fact->type();
        p.param_type = _mavParamType;
        //根据type进行不同type的赋值操作
        switch (factType) {
        case FactMetaData::valueTypeUint8:
        case FactMetaData::valueTypeBool:
            union_value.param_uint8 = static_cast<uint8_t>(_fact->rawValue().toUInt());
            break;
        case FactMetaData::valueTypeInt8:
            union_value.param_int8 = static_cast<int8_t>(_fact->rawValue().toInt());
            break;
        case FactMetaData::valueTypeUint16:
            union_value.param_uint16 = static_cast<uint16_t>(_fact->rawValue().toUInt());
            break;
        case FactMetaData::valueTypeInt16:
            union_value.param_int16 = static_cast<int16_t>(_fact->rawValue().toInt());
            break;
        case FactMetaData::valueTypeUint32:
            union_value.param_uint32 = static_cast<uint32_t>(_fact->rawValue().toUInt());
            break;
        case FactMetaData::valueTypeInt64:
            union_value.param_int64 = static_cast<int64_t>(_fact->rawValue().toLongLong());
            break;
        case FactMetaData::valueTypeUint64:
            union_value.param_uint64 = static_cast<uint64_t>(_fact->rawValue().toULongLong());
            break;
        case FactMetaData::valueTypeFloat:
            union_value.param_float = _fact->rawValue().toFloat();
            break;
        case FactMetaData::valueTypeDouble:
            union_value.param_double = _fact->rawValue().toDouble();
            break;
            //-- String and custom are the same for now
        case FactMetaData::valueTypeString:
        case FactMetaData::valueTypeCustom:
        {
            //如果是自定类型转为byte数组
            QByteArray custom = _fact->rawValue().toByteArray();
            memcpy(union_value.bytes, custom.data(), static_cast<size_t>(std::max(custom.size(), MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_VALUE_LEN)));
        }
            break;
        default:
            qCritical() << "Unsupported fact type" << factType << "for" << _fact->name();
        case FactMetaData::valueTypeInt32:
            union_value.param_int32 = static_cast<int32_t>(_fact->rawValue().toInt());
            break;
        }
        //将union_value的值复制到p.param_value
        memcpy(&p.param_value[0], &union_value.bytes[0], MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_VALUE_LEN);
        p.target_system     = static_cast<uint8_t>(_vehicle->id());
        p.target_component  = static_cast<uint8_t>(_control->compID());
        strncpy(p.param_id, _fact->name().toStdString().c_str(), MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_ID_LEN);
        //发送mavlink消息
        mavlink_msg_param_ext_set_encode_chan(
                    static_cast<uint8_t>(_pMavlink->getSystemId()),
                    static_cast<uint8_t>(_pMavlink->getComponentId()),
                    sharedLink->mavlinkChannel(),
                    &msg,
                    &p);
        _vehicle->sendMessageOnLinkThreadSafe(sharedLink.get(), msg);
    }
    _paramWriteTimer.start();
}

//-----------------------------------------------------------------------------
//写参数的定时器到时函数
void
QGCCameraParamIO::_paramWriteTimeout()
{
    if(++_sentRetries > 3) {
        qCWarning(CameraIOLog) << "No response for param set:" << _fact->name();
        _updateOnSet = false;
    } else {
        //-- Send it again
        qCDebug(CameraIOLog) << "Param set retry:" << _fact->name() << _sentRetries;
        _sendParameter();
        _paramWriteTimer.start();
    }
}

//-----------------------------------------------------------------------------
//处理参数响应
void
QGCCameraParamIO::handleParamAck(const mavlink_param_ext_ack_t& ack)
{
    //关闭写入参数定时器
    _paramWriteTimer.stop();
    //如果参数结果是sccept(接受)
    if(ack.param_result == PARAM_ACK_ACCEPTED) {
        //根绝type和value获取数据
        QVariant val = _valueFromMessage(ack.param_value, ack.param_type);
        //如果当前的fact的值与该值不等
        if(_fact->rawValue() != val) {
            //获取是否包含
            _fact->_containerSetRawValue(val);
            if(_updateOnSet) {
                _updateOnSet = false;
                _control->factChanged(_fact);
            }
        }
    } else if(ack.param_result == PARAM_ACK_IN_PROGRESS) {
        //-- Wait a bit longer for this one 正在处理中
        qCDebug(CameraIOLogVerbose) << "Param set in progress:" << _fact->name();
        _paramWriteTimer.start();
    } else {
        if(ack.param_result == PARAM_ACK_FAILED) {
            if(++_sentRetries < 3) {
                //-- Try again
                qCWarning(CameraIOLog) << "Param set failed:" << _fact->name() << _sentRetries;
                _paramWriteTimer.start();
            }
            return;
        } else if(ack.param_result == PARAM_ACK_VALUE_UNSUPPORTED) {
            //参数设置不支持
            qCWarning(CameraIOLog) << "Param set unsuported:" << _fact->name();
        }
        //-- If UI changed and value was not set, restore UI
        QVariant val = _valueFromMessage(ack.param_value, ack.param_type);
        if(_fact->rawValue() != val) {
            if(_control->validateParameter(_fact, val)) {
                _fact->_containerSetRawValue(val);
            }
        }
    }
}

//-----------------------------------------------------------------------------
//处理参数值
void
QGCCameraParamIO::handleParamValue(const mavlink_param_ext_value_t& value)
{
    //请求计时器停止
    _paramRequestTimer.stop();
    QVariant newValue = _valueFromMessage(value.param_value, value.param_type);
    if(_control->incomingParameter(_fact, newValue)) {
        _fact->_containerSetRawValue(newValue);
    }
    _paramRequestReceived = true;
    if(_forceUIUpdate) {
        emit _fact->rawValueChanged(_fact->rawValue());
        emit _fact->valueChanged(_fact->rawValue());
        _forceUIUpdate = false;
    }
    if(!_done) {
        _done = true;
        _control->_paramDone();
    }
    qCDebug(CameraIOLog) << QString("handleParamValue() %1 %2").arg(_fact->name()).arg(_fact->rawValueString());
}

//-----------------------------------------------------------------------------
QVariant
QGCCameraParamIO::_valueFromMessage(const char* value, uint8_t param_type)
{
    QVariant var;
    param_ext_union_t u;
    memcpy(u.bytes, value, MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_VALUE_LEN);
    switch (param_type) {
        case MAV_PARAM_EXT_TYPE_REAL32:
            var = QVariant(u.param_float);
            break;
        case MAV_PARAM_EXT_TYPE_UINT8:
            var = QVariant(u.param_uint8);
            break;
        case MAV_PARAM_EXT_TYPE_INT8:
            var = QVariant(u.param_int8);
            break;
        case MAV_PARAM_EXT_TYPE_UINT16:
            var = QVariant(u.param_uint16);
            break;
        case MAV_PARAM_EXT_TYPE_INT16:
            var = QVariant(u.param_int16);
            break;
        case MAV_PARAM_EXT_TYPE_UINT32:
            var = QVariant(u.param_uint32);
            break;
        case MAV_PARAM_EXT_TYPE_INT32:
            var = QVariant(u.param_int32);
            break;
        case MAV_PARAM_EXT_TYPE_UINT64:
            var = QVariant(static_cast<qulonglong>(u.param_uint64));
            break;
        case MAV_PARAM_EXT_TYPE_INT64:
            var = QVariant(static_cast<qulonglong>(u.param_int64));
            break;
        case MAV_PARAM_EXT_TYPE_CUSTOM:
            var = QVariant(QByteArray(value, MAVLINK_MSG_PARAM_EXT_SET_FIELD_PARAM_VALUE_LEN));
            break;
        default:
            var = QVariant(0);
            qCritical() << "Invalid param_type used for camera setting:" << param_type;
    }
    return var;
}

//-----------------------------------------------------------------------------
void
QGCCameraParamIO::_paramRequestTimeout()
{
    if(++_requestRetries > 3) {
        qCWarning(CameraIOLog) << "No response for param request:" << _fact->name();
        if(!_done) {
            _done = true;
            _control->_paramDone();
        }
    } else {
        //-- Request it again
        qCDebug(CameraIOLog) << "Param request retry:" << _fact->name();
        paramRequest(false);
        _paramRequestTimer.start();
    }
}

//-----------------------------------------------------------------------------
void
QGCCameraParamIO::paramRequest(bool reset)
{
    //-- If it's write only, we don't request it.
    if(_fact->writeOnly()) {
        if(!_done) {
            _done = true;
            _control->_paramDone();
        }
        return;
    }
    if(reset) {
        _requestRetries = 0;
        _forceUIUpdate  = true;
    }
    qCDebug(CameraIOLog) << "Request parameter:" << _fact->name();
    WeakLinkInterfacePtr weakLink = _vehicle->vehicleLinkManager()->primaryLink();
    if (!weakLink.expired()) {
        SharedLinkInterfacePtr sharedLink = weakLink.lock();

        char param_id[MAVLINK_MSG_PARAM_EXT_REQUEST_READ_FIELD_PARAM_ID_LEN + 1];
        memset(param_id, 0, sizeof(param_id));
        strncpy(param_id, _fact->name().toStdString().c_str(), MAVLINK_MSG_PARAM_EXT_REQUEST_READ_FIELD_PARAM_ID_LEN);
        mavlink_message_t msg;
        mavlink_msg_param_ext_request_read_pack_chan(
                    static_cast<uint8_t>(_pMavlink->getSystemId()),
                    static_cast<uint8_t>(_pMavlink->getComponentId()),
                    sharedLink->mavlinkChannel(),
                    &msg,
                    static_cast<uint8_t>(_vehicle->id()),
                    static_cast<uint8_t>(_control->compID()),
                    param_id,
                    -1);
        _vehicle->sendMessageOnLinkThreadSafe(sharedLink.get(), msg);
    }
    _paramRequestTimer.start();
}

三.QGCCameraControl

这个类的中文件中还定义了其他几个类分别是视频流类,主要处理相机的mavlink的一些操作,代码太多,并且没有需要特别指出的地方所以,这里不贴出了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

机器人地面站-[QGroundControl源码解析]-[9]-[Camera] 的相关文章

  • 如何检测位图中的红色像素

    android中的getPixels 是上下左右读取像素 还是左右上下读取像素 基本上是按行或列读取 如果我想知道图片中的红色值较高的位置 我可以这样做吗 我假设它是按列读取的 Bitmap thumbnail Bitmap data ge
  • iOS:同时使用 WiFi 和移动数据

    Setup 我的项目涉及一个 WiFi 相机 它创建一个 WiFi 热点 为了在相机上流式传输视频预览 浏览媒体 用户需要连接到相机的热点 Problem 用户无法同时使用 3G 4G 上的蜂窝数据 因为 iOS 设备已通过 WiFi 连接
  • Android ACTION_IMAGE_CAPTURE 与内存中的 EXTRA_OUTPUT

    当我打电话时用相机拍照时 File file new File getFilesDir getAbsolutePath myImage jpg Uri outputFileUri Uri fromFile file cameraIntent
  • 禁止将拍摄的照片保存到 DCIM 文件夹中

    我在我的应用程序中通过 Intent 拍照 照片保存到 SD 上我指定的文件夹中 而且它们也保存到 DCIM 默认相机文件夹中 我不想两次 如何禁止将拍摄的照片保存到此默认相机目录中 先感谢您 这是我正在使用的 Intent intent
  • iPhone 相机访问权限?

    我想知道如何访问 iPhone 相机并实时使用它 例如 仅在相机视图上绘图 另一个相关问题 可以显示吗同时 4 个摄像机视图就像 Mac 上的 Photo Booth 一样 您可以使用 AVFoundation 来做到这一点 void in
  • Three.js 设置并读取相机外观向量

    而不是使用camera rotation或lookAt 函数旋转相机 我想将外观矢量直接传递给相机 是否可以直接设置相机外观矢量以及是否可以从相机读取外观矢量 相机没有 外观矢量 因此无法设置它 但是 您可以构造一个point通过将您的外观
  • DirectShow 虚拟摄像机不会出现在某些配置的列表中

    我使用 DirectShow 过滤器作为虚拟相机 CLSID VideoInputDeviceCategory 它运行良好 但某些应用程序 配置不将此提要显示为源 例如 在 win 8 1 上 我可以通过 webrtc 在 Chrome F
  • 如何将相机中的图像保存到 iPhone 图库中的特定文件夹?

    嘿 我是 iPhone 新手 最近我一直在尝试制作一个应用程序 基本上 我想要做的是 如果用户将从相机捕获任何图像 那么它应该保存在设备库中 我知道如何将照片保存在图库中 它对我有用 但我无法将所有捕获的图像保存到设备图库中的特定文件夹 例
  • 使用 iPhone 摄像头检测心率 [重复]

    这个问题在这里已经有答案了 可能的重复 使用摄像头检测心率 https stackoverflow com questions 9274027 detecting heart rate using the camera 我正在研究 iOS
  • 如何使用键盘和鼠标控制相机 - Three.js

    我在 WEB GL 中有一个带有 Three js 的 3D 环境 并且我曾经使用 Orbitcontrols js http codepen io nireno pen cAoGI http codepen io nireno pen c
  • 使用 OpenCV 进行相机校准 - 如何调整棋盘方块大小?

    我正在使用 OpenCV Python 示例开发相机校准程序 来自 OpenCV 教程 http opencv python tutroals readthedocs io en latest py tutorials py calib3d
  • PhoneGap 应用程序在 Android 上无响应

    我创建了一个简单的 PhoneGap 应用程序 现在只需在您点击按钮时拍摄一张照片 然后在同一页面上的图像中显示该照片 我已经构建了iOS和Android版本 iOS版本运行良好 另一方面 Android 版本突出显示该按钮 但从不切换到相
  • 如何用OpenCV解决图像处理相机IO延迟

    我有一个 OpenCV 程序 其工作原理如下 VideoCapture cap 0 Mat frame while true cap gt gt frame myprocess frame 问题是如果myprocess耗时较长 超过相机的I
  • HTC One M8 - 使用第二个后置摄像头

    我有一台 HTC One M8 设备 它有 2 个后置摄像头和一个额外的前置摄像头 我的问题是尝试访问第二个后置摄像头 我已经成功制作了一个应用程序 它同时运行 2 个摄像头 1 个前置摄像头和 1 个后置摄像头 但问题是我无法访问第二个后
  • 不调用 PreviewCallback 和带缓冲区的 PreviewCallback

    我对 Android 4 0 x 的预览回调有疑问 我设置了一个相机 创 建一个表面来显示相机图像on previewCallback 事件 一切正常 但对于 Android 4 0 x 则不然onPreviewCallback被称为 也不
  • Camera中添加Camera的Zoom控件

    我正在制作一个相机应用程序 其中我使用 Surface View 作为相机和所有其他东西 我从以下链接中获取了指南 http www brighthub com mobile google android articles 43414 as
  • VideoCapture 未检测到 uEye 摄像头

    我的 uEye 相机遇到了一个问题 使用我的笔记本电脑摄像头 id 0 或 USB 上的网络摄像头 id 1 此行完美运行 TheVideoCapturer open 1 TheVideoCapturer 属于 VideoCapture 类
  • Android webview 允许使用当前 Android Studio 访问相机

    我一直在尝试在我的网络视图上制作一个简单的输入按钮来访问相机和文件 我读过的解决方案各不相同 只有几行代码 没有解释它们到我在 Android Studio 中下载并打开的盲 github 项目链接 Os Fileup 等 的位置 并且它们
  • Camera.Parameters.FLASH_MODE_ON 在 Moto X 上不起作用

    我正在 moto x 上测试我的应用程序 即使打开闪光灯模式后 闪光灯也无法工作 应用程序在其他设备上运行良好 但在 Moto X 上运行不佳 这是一个代码片段 cameraInstance getCameraInstance camera
  • 如何在 Android 中保存相机的临时照片?

    在尝试从相机拍照并将其保存到应用程序的缓存文件夹中时 我没有得到任何可见的结果 应用程序不会崩溃 但在 LogCat 上 当我尝试将 ImageView src 字段设置为刚刚获取的文件的 URI 时 我收到此消息 09 17 14 03

随机推荐