机器人地面站-[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] 的相关文章

  • 正交相机旋转

    我可以使用此代码旋转相机 camera zoom 3 in constructor if camera zoom gt 1 camera zoom 0 01f camera rotate 15 this is done in render
  • 相机标定opencv

    你好 我正在做一个项目来进行图像 3D 重建 我正在校准相机的阶段 这需要很长时间才能完成 但是当我编译代码并在相机前显示棋盘时 它会直接进入未处理的异常错误 当图片不在框架中时 一旦进入框架就没有错误 出现未处理的错误我不知道为什么 我问
  • 在 iOS 中测量/计算距离

    我需要计算 iOS 中两点之间的距离 我可以保证至少有一部iPhone 4 所以相机的图像质量应该很好 这个想法是使用图片计算到某个点的距离 有一个名为 easyMeasure 的应用程序 它完全可以满足我的需要 我对毕达哥拉斯很满意 但这
  • 是否可以使用 flutter 相机插件流式传输视频?

    我一直在使用相机插件 我知道可以通过CameraController与功能start stopVideoRecording 这些函数将采用文件的路径作为输入 我希望能够在录制时将该视频流式传输到服务器 是否可以通过相机插件的当前功能以某种方
  • 将预览帧转换为位图

    我知道这个主题已经在黑板上出现过很多次了 但无论如何我都无法让它发挥作用 我想将预览中的视图帧保存为 jpeg 文件 它看起来或多或少 代码被简化 没有额外的逻辑 异常等 像这样 public void onPreviewFrame byt
  • 不确定如何使用 CICrop 裁剪图像

    我正在尝试使用 CICrop 裁剪图像 但是当我尝试裁剪时 它崩溃并显示以下错误消息 由于未捕获的异常 NSUnknownKeyException 而终止应用程序 原因 setValue forUndefinedKey 这个类 不符合键的键
  • 检测所有摄像头android

    我有一个使用 Camera2 API 来获取相机预览的应用程序 我想在手机的镜头之间进行选择 在我的代码中 我使用以下代码 CameraManager manager CameraManager activity getSystemServ
  • 在网络应用程序中从网络摄像头或移动摄像头拍照

    我正在开发一个网络应用程序 可以从本地浏览和拍照 而且我想通过相机捕获图像 我使用以下代码 我可以捕获设备相机
  • Windows Mobile:通过 C# 使用手机摄像头

    我想展示手机摄像头在 WinForm 中的控件的图像 我的想法是我的应用程序就像相机的程序一样工作 我想显示图像 就像用户要拍照一样 我怎样才能做到这一点 我可以这样做吗 如果您需要更多详细信息 请询问我 谢谢你 不太确定您需要什么 但您可
  • 访问 iOS 6 新 API 以获取相机曝光和快门速度

    在苹果的iOS 6 0 功能页面 https developer apple com technologies ios6 过去常说 利用内置摄像头的高级功能 新的 API 可让您控制焦点 曝光和感兴趣区域 您还可以使用人脸检测 API 访问
  • 如何使用鼠标改变OpenGL相机

    我正在尝试在 OpenGL 中设置一个相机来查看 3 维中的一些点 为了实现这一点 我不想使用旧的 固定的功能样式 glMatrixMode glTranslate 等 而是自己设置模型视图投影矩阵并在我的顶点着色器中使用它 正交投影就足够
  • 还有其他访问相机的替代方法吗?

    除了使用 ActionScript 3 之外 还有其他方法来访问相机吗 import flash media Camera videoInstance attachCamera cameraInstance 或者我应该使用任何 API 吗
  • 如何使用摄像头直播作为活动背景?

    我正在尝试制作一个应用程序 其中我需要使用相机实时馈送作为背景 我知道这是一件愚蠢的事情 但无能为力 这是客户的要求 我尝试过使用SurfaceView但到目前为止还没有成功 到目前为止 我在 Stack Overflow 上发现的更多内容
  • 如何更改Vuforia AR相机对焦模式?

    我在用Vuforia 6 2 AR SDK对于在Unity中 但是当我在 Android 手机中测试该应用程序时 相机看起来像blurry 我在 Vuforia 的开发者网站中搜索并找到了一些相机对焦模式 但我无法实现 因为该指南适用于较旧
  • 以编程方式截取屏幕截图不会捕获 surfaceVIew 的内容

    我有一个应用程序 我希望能够捕获屏幕截图 布局的背景是一个 SurfaceView 显示来自后置摄像头的视频 下面的代码可以截图 但是surfaceView的内容保存为黑色 这是代码 btn setOnClickListener new O
  • Android ACTION_IMAGE_CAPTURE 与内存中的 EXTRA_OUTPUT

    当我打电话时用相机拍照时 File file new File getFilesDir getAbsolutePath myImage jpg Uri outputFileUri Uri fromFile file cameraIntent
  • 是否可以使用 Google Glass 拍照而无需“点击接受”?

    我按照此处的代码使用 Google Glass 相机捕获图像 https developers google com glass develop gdk media camera camera capturing images or vid
  • 有机会通过 Android NDK 相机访问来减少快门时间吗?

    我编写了一个 Android 应用程序 可以从相机捕获实时预览 快门时间短很重要 至少应该是恒定的 目前我使用以下代码来实现低快门时间 Parameters params camera getParameters params setSce
  • iOS 相机视频实时预览与拍摄的照片有偏移

    我正在使用相机工作 相机以实时反馈的形式呈现给用户 当用户单击时 就会创建图像并将其传递给用户 问题是图像被设计为位于最顶部位置 该位置高于实时预览显示的位置 您知道如何调整相机的框架 使实时视频的顶部与他们要拍摄的照片的顶部相匹配吗 我以
  • Actionscript 3主类是根,但不允许动画虚拟相机

    我最近开始使用 Actionscript 3 学习 Animate CC 我正在尝试使用 Animate 的 虚拟相机 功能 为我提供一个可以平移 旋转和缩放游戏的相机 当根没有子类时 很容易实现 Camera 例如 您可以在屏幕上放置一个

随机推荐