5.2.1 基本功能介绍
相机功能组件是M300上PSDK端口功能,也就是开发的负载设备功能。当我们开发的负载是一个相机,或者需要将第三方(非DJI无人机负载相机)集成到DJI无人机上时,就需要使用到功能组件。
从宏观功能上来说,此部分使得负载的相机与DJI无人机以及控制端集成融合于一体,控制端包括遥控器相机按键,APP相机控件,OSDK相机管理功能。从功能实现上来说,此功能组件将DJI无人机系统支持的相机基本功能抽象成PSDK接口,负载按照已经定义好的接口将负载硬件或相机物理功能联动起来。
相机功能组件包含的基本功能接口,包括相机模式,拍照,录像,变焦控制,相机状态,相机照片存储SD卡管理等;除此之前,DJI无人机系统(包括飞行器和遥控APP)还支持视频流,照片等媒体流功能,PSDK 相机功能组件也将此部分接口预留出来,用于负载相机自行设计并选择使用。
通过此部分sample,我们需要提炼出PSDK相机功能组件预留了什么接口,具体接口对应的是什么功能?然后再结合负载功能选择功能模块和开发。
5.2.2 主要代码文件
camera_emu/
├── dji_media_file_manage
│ ├── dji_media_file_core.c
│ ├── dji_media_file_core.h
│ ├── dji_media_file_jpg.c
│ ├── dji_media_file_jpg.h
│ ├── dji_media_file_mp4.c
│ └── dji_media_file_mp4.h
├── media_file
│ ├── out.h264
│ ├── PSDK_0001_ORG.jpg
│ ├── PSDK_0002_ORG.jpg
│ ├── PSDK_0003_ORG.jpg
│ ├── PSDK_0004_ORG.mp4
│ └── PSDK_0005.h264
├── test_payload_cam_emu_base.c
├── test_payload_cam_emu_base.h
├── test_payload_cam_emu_media.c
└── test_payload_cam_emu_media.h
PSDK lib头文件
dji_payload_camera.h
说明:
- 代码文件中将基本相机功能与媒体流部分分开,预留的接口不是必须使用,提供的功能可以根据实际需求选择开发。
- dji_media_file_manage,是对媒体文件部分的管理,APP端操作相册时与此部分媒体文件有关。
- media_file是sample中用于测试的媒体源文件,仅做sample模拟。
- test_payload_cam_emu_base,是基本相机功能代码部分
- test_payload_cam_emu_media,媒体处理部分代码,包括向飞机端推送相机实时视频流。
5.2.3 sample代码实现
相机组件功能基本是采用回调注册的方式,其基本原理与widget功能,云台功能组件部分等部分基本一致,可以先参考PSDK中回调注册基本原理。
待补充PSDK sample 运行详解
功能代码入口函数
sample中相机的基本功能和媒体功能通过两个宏定义来选择使用,两部分同时使用,也可以选择使用。
base:
CONFIG_MODULE_SAMPLE_CAMERA_EMU_ON
returnCode = DjiTest_CameraEmuBaseStartService();
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_ERROR("camera emu common init error");
}
media:
CONFIG_MODULE_SAMPLE_CAMERA_MEDIA_ON
returnCode = DjiTest_CameraEmuMediaStartService();
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_ERROR("camera emu media init error");
}
初始化
/**
* @brief Initialize the payload camera module.
* @note The interface is the total initialization interface of the camera module. The following interfaces are optional
* functions and can be freely selected according to the actual load device condition of the user. Before registering
* the optional interface, the interface must be initialized before the system can work normally. Interface initialization
* needs to be after djiCore_Init.
* @return Execution result.
*/
T_DjiReturnCode DjiPayloadCamera_Init(void);
API简介
-
初始化相机负载功能组件模块。
注册相机通用功能回调
/**
* @brief Register the handler for payload camera common function interfaces.
* @note This interface registers the camera's basic function interface, including camera camera, video, mode settings,
* SD card operation, camera status interface. Registration of this interface needs to be after DjiPayloadCamera_Init.
* @param cameraCommonHandler: pointer to the handler for payload camera common functions.
* @return Execution result.
*/
T_DjiReturnCode DjiPayloadCamera_RegCommonHandler(const T_DjiCameraCommonHandler *cameraCommonHandler);
API简介
-
注册相机基本功能的回调,包括相机、视频模式操作,SD卡管理操作,相机状态等。
参数说明
-
相机操作的回调函数句柄。
typedef struct {
//获取相机设备状态
T_DjiReturnCode (*GetSystemState)(T_DjiCameraSystemState *systemState);
//设置相机模式
T_DjiReturnCode (*SetMode)(E_DjiCameraMode mode);
//获取相机模式
T_DjiReturnCode (*GetMode)(E_DjiCameraMode *mode);
//开始录像
T_DjiReturnCode (*StartRecordVideo)(void);
//停止录像
T_DjiReturnCode (*StopRecordVideo)(void);
//开始拍照
T_DjiReturnCode (*StartShootPhoto)(void);
//停止拍照
T_DjiReturnCode (*StopShootPhoto)(void);
//设置拍照模式,single,burst,interval
T_DjiReturnCode (*SetShootPhotoMode)(E_DjiCameraShootPhotoMode mode);
//获取拍照模式,single,burst,interval
T_DjiReturnCode (*GetShootPhotoMode)(E_DjiCameraShootPhotoMode *mode);
//设置连拍数量
T_DjiReturnCode (*SetPhotoBurstCount)(E_DjiCameraBurstCount burstCount);
//获取连拍数量
T_DjiReturnCode (*GetPhotoBurstCount)(E_DjiCameraBurstCount *burstCount);
//设置间隔拍照参数
T_DjiReturnCode (*SetPhotoTimeIntervalSettings)(T_DjiCameraPhotoTimeIntervalSettings settings);
//获取间隔拍照参数
T_DjiReturnCode (*GetPhotoTimeIntervalSettings)(T_DjiCameraPhotoTimeIntervalSettings *settings);
//读取SD卡状态
T_DjiReturnCode (*GetSDCardState)(T_DjiCameraSDCardState *sdCardState);
//操作格式化SD卡
T_DjiReturnCode (*FormatSDCard)(void);
} T_DjiCameraCommonHandler;注:具体的回调原型和参数不具体贴出解释,具体可以参考源代码,主要了解PSDK预留的接口和功能。
注册相机测光模式回调
/**
* @brief Register the handler for payload camera exposure and metering function interfaces.
* @note This interface registers the spot metering and exposure interface of the camera. It currently includes
* setting and acquiring the metering mode and metering area. Special attention must be paid to the limitations
* of the interface parameters. Registration of this interface needs to be after DjiPayloadCamera_Init.
* @param cameraExposureMeteringHandler: pointer to the handler for payload camera exposure and metering functions.
* @return Execution result.
*/
T_DjiReturnCode DjiPayloadCamera_RegExposureMeteringHandler(const T_DjiCameraExposureMeteringHandler
*cameraExposureMeteringHandler);
API简介
-
注册相机测光模式功能回调。包括测光模式的设置/读取,设置、读取/设置点测光模式下点坐标。
参数
-
cameraExposureMeteringHandler,测光模式回调句柄。
/**
* @brief Camera metering mode.
*/
typedef enum {
DJI_CAMERA_METERING_MODE_CENTER = 0, /*!< Center metering mode. */
DJI_CAMERA_METERING_MODE_AVERAGE = 1, /*!< Average metering mode. */
DJI_CAMERA_METERING_MODE_SPOT = 2, /*!< Spot metering mode. */
} E_DjiCameraMeteringMode;
/**
* @brief Camera metering feature handler.
* @warning User can not execute blocking style operations or functions in callback function, because that will block dji
* root thread, causing problems such as slow system response, payload disconnection or infinite loop.
*/
typedef struct {
//设置测光模式
T_DjiReturnCode (*SetMeteringMode)(E_DjiCameraMeteringMode mode);
//获取测光模式
T_DjiReturnCode (*GetMeteringMode)(E_DjiCameraMeteringMode *mode);
//设置点坐标(行列坐标,列参数范围0 ~ 11,行参数范围:0 ~ 7)
T_DjiReturnCode (*SetSpotMeteringTarget)(T_DjiCameraSpotMeteringTarget target);
//获取点坐标
T_DjiReturnCode (*GetSpotMeteringTarget)(T_DjiCameraSpotMeteringTarget *target);
} T_DjiCameraExposureMeteringHandler;
注册相机对焦功能回调
/**
* @brief Register the handler for payload camera focus function interfaces.
* @note This interface registers the camera's focus interface, which includes setting and acquiring the focus mode,
* focus area, and focus settings. Special attention must be paid to the interface parameters. Registration of
* this interface needs to be after DjiPayloadCamera_Init.
* @param cameraFocusHandler: pointer to the handler for payload camera focus functions.
* @return Execution result.
*/
T_DjiReturnCode DjiPayloadCamera_RegFocusHandler(const T_DjiCameraFocusHandler *cameraFocusHandler);
API简介
-
注册对焦功能回调,包括:设置/获取对焦模式,设置/获取对焦目标点,设置/获取对焦助手设置,设置/获取对焦环值。
参数
-
cameraFocusHandler,相机对焦功能回调句柄。
/**
* @brief Camera focus feature handler.
* @warning User can not execute blocking style operations or functions in callback function, because that will block dji
* root thread, causing problems such as slow system response, payload disconnection or infinite loop.
*/
typedef struct {
//设置对焦模式
T_DjiReturnCode (*SetFocusMode)(E_DjiCameraFocusMode mode);
//获取对焦模式
T_DjiReturnCode (*GetFocusMode)(E_DjiCameraFocusMode *mode);
//设置对焦目标点
T_DjiReturnCode (*SetFocusTarget)(T_DjiCameraPointInScreen target);
//获取对焦目标点
T_DjiReturnCode (*GetFocusTarget)(T_DjiCameraPointInScreen *target);
//设置对焦助手设置
T_DjiReturnCode (*SetFocusAssistantSettings)(T_DjiCameraFocusAssistantSettings settings);
//获取对焦助手设置
T_DjiReturnCode (*GetFocusAssistantSettings)(T_DjiCameraFocusAssistantSettings *settings);
//设置对焦环值
T_DjiReturnCode (*SetFocusRingValue)(uint32_t value);
//获取对焦环值
T_DjiReturnCode (*GetFocusRingValue)(uint32_t *value);
//获取对焦环最大值
T_DjiReturnCode (*GetFocusRingValueUpperBound)(uint32_t *value);
} T_DjiCameraFocusHandler;
说明:
-
对焦环最大值是相机性能参数,不能设置,只能从相机端获取。
注册数码变焦功能回调
/**
* @brief Register the handler for payload camera digital zoom function interfaces.
* @note This interface registers the camera's digital zoom interface, which includes setting and obtaining the digital
* zoom zoom factor. Registering the load on this interface requires digital zoom. Registration of this interface
* needs to be after DjiPayloadCamera_Init.
* @param cameraDigitalZoomHandler: pointer to the handler for payload camera digital zoom functions.
* @return Execution result.
*/
T_DjiReturnCode DjiPayloadCamera_RegDigitalZoomHandler(const T_DjiCameraDigitalZoomHandler
*cameraDigitalZoomHandler);
API简介
-
支持数码变焦功能的相机负载通过此句柄注册数码变焦相关回调。包括:设置/读取变焦参数。
参数
-
cameraDigitalZoomHandler,数码变焦句柄。
/**
* @brief Camera digital zoom feature handler.
* @warning User can not execute blocking style operations or functions in callback function, because that will block dji
* root thread, causing problems such as slow system response, payload disconnection or infinite loop.
*/
typedef struct {
//设置数码变焦参数
T_DjiReturnCode (*SetDigitalZoomFactor)(dji_f32_t factor);
//获取数码变焦参数
T_DjiReturnCode (*GetDigitalZoomFactor)(dji_f32_t *factor);
} T_DjiCameraDigitalZoomHandler;
注册光学变焦功能回调
/**
* @brief Register the handler for payload camera optical zoom function interfaces.
* @note This interface registers the camera's optical zoom interface, which includes setting and acquiring optical zoom
* parameters, and a continuous zoom interface. Registering the load on this interface requires support for optical
* zoom. Registration of this interface needs to be after DjiPayloadCamera_Init.
* @param cameraOpticalZoomHandler: pointer to the handler for payload camera optical zoom functions.
* @return Execution result.
*/
T_DjiReturnCode DjiPayloadCamera_RegOpticalZoomHandler(const T_DjiCameraOpticalZoomHandler
*cameraOpticalZoomHandler);
API简介
-
支持光学变焦功能的负载相机通过此接口注册相关回调。包括:设置/获取光学变焦焦距值,获取光学变焦倍数,获取相机光学变焦参数(最大、最小变焦焦距值,以及变焦步长),开始/停止连续变焦。
参数
-
cameraOpticalZoomHandler,相机光学变焦功能回调句柄。
/**
* @brief Camera optical zoom feature handler.
* @warning User can not execute blocking style operations or functions in callback function, because that will block dji
* root thread, causing problems such as slow system response, payload disconnection or infinite loop.
*/
typedef struct {
//设置光学变焦焦距值
T_DjiReturnCode (*SetOpticalZoomFocalLength)(uint32_t focalLength);
//获取光学变焦焦距值
T_DjiReturnCode (*GetOpticalZoomFocalLength)(uint32_t *focalLength);
//获取光学变焦倍数
T_DjiReturnCode (*GetOpticalZoomFactor)(dji_f32_t *factor);
//获取相机光学变焦参数(最大、最小变焦焦距值,以及变焦步长)
T_DjiReturnCode (*GetOpticalZoomSpec)(T_DjiCameraOpticalZoomSpec *spec);
//开始连续变焦
T_DjiReturnCode (*StartContinuousOpticalZoom)(E_DjiCameraZoomDirection direction, E_DjiCameraZoomSpeed speed);
//停止连续变焦
T_DjiReturnCode (*StopContinuousOpticalZoom)(void);
} T_DjiCameraOpticalZoomHandler;-
说明
-
光学变焦倍数:factor 是当前焦距值/最小焦距值。
-
此回调仅支持设置焦距值,不能设置焦距倍数。提供接口获取当前的焦距倍数。
-
获取相机光学变焦参数是相机的性能参数,仅可获取不能设置。
-
-
注册指点变焦功能回调
/**
* @brief Register handler functions for tap zoom function.
* @details Registration specifies dji application support tap zoom function.
* @param cameraTapZoomHandler: pointer to structure of handler functions for tap zoom function.
* @return Execution result.
*/
T_DjiReturnCode DjiPayloadCamera_RegTapZoomHandler(const T_DjiCameraTapZoomHandler *cameraTapZoomHandler);
API简介
-
支持指点变焦功能的负载相机通过此API注册功能回调。包括:设置/获取指点变焦状态,获取指点变焦功能使能状态,设置/获取指点变焦倍率,指点触发点回调。
参数
-
cameraTapZoomHandler,指点变焦功能回调函数句柄。
/**
* @brief Prototype of handler functions for tap zooming.
* @note User can not execute blocking style operations or functions in callback function, like djiXPort_RotateSync()
* function, because that will block dji root thread, causing problems such as slow system response, payload
* disconnection or infinite loop.
*/
typedef struct {
//获取指点变焦状态
T_DjiReturnCode (*GetTapZoomState)(T_DjiCameraTapZoomState *state);
//设置指点变焦状态
T_DjiReturnCode (*SetTapZoomEnabled)(bool enabledFlag);
//获取负载相机是否使能指点变焦
T_DjiReturnCode (*GetTapZoomEnabled)(bool *enabledFlag);
//设置指定变焦倍率
T_DjiReturnCode (*SetTapZoomMultiplier)(uint8_t multiplier);
//获取指点变焦倍率
T_DjiReturnCode (*GetTapZoomMultiplier)(uint8_t *multiplier);
//指点变焦触发点
T_DjiReturnCode (*TapZoomAtTarget)(T_DjiCameraPointInScreen target);
} T_DjiCameraTapZoomHandler;.
创建camera_emu任务
前面部分都是基于负载相机具体的功能注册回调,可以看做是负载相机功能的初始化部分,只要完成初始化部分就可以在Pilot APP 上看到一个负载相机界面。如果同时挂载多个负载,因为Pilot同时只有一个大窗口和一个小窗口两个相机显示界面,可以通过小窗口上的设置控件任选两个相机进行呈现。到这里PSDK端与APP端相机功能就已经成功连接,我们也注意到初始化部分注册了很多与APP端交互的回调,设备端还需要结合负载相机硬件特性将其支持的功能联动起来。sample没有具体的硬件功能,主要提供了两个常见任务,一个是基本任务,主要通过一些全局变量来代替设备的功能状态,然后通过回调将这些状态与APP通信呈现出来。另一个是相机的媒体功能,包括相册媒体功能以及实时的视频流推流功能。
-
基本相机功能
这里将创建线程部分代码贴出来,任务中的代码较长就不具体贴出解释,大致解释一下其中有关功能的处理。
/* Create the camera emu taskHandle */
if (osalHandler->TaskCreate("user_camera_task", UserCamera_Task,
PAYLOAD_CAMERA_EMU_TASK_STACK_SIZE, NULL, &s_userCameraThread)
!= DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_ERROR("user camera taskHandle create error");
return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
}任务功能梳理:
-
任务中是一个死循环,可以看做是一个持续工作中的相机设备。
-
功能实现原理大致一样,以拍照和存储功能为例,当APP触发拍照指令后,PSDK中注册的拍照回调函数就会被调用,函数中设置相机拍照的全局变量,然后此循环中因为状态机的变更会进入实际的拍照处理,相机设备完成拍照会生成图片存储,通过API将新生成的图片推送至APP端,同时SD卡的存储状态要对应变更。注册的SD卡状态读取的回调被触发时就会将此变更的状态回传给APP端,APP端就完成了一次拍照过程。
-
TAP_ZOOM中还会涉及云台的转动,需要支持云台功能组件。
-
-
相机媒体功能
一旦注册相机基本功能,APP上就会有一个实时画面窗口,对应的是PSDK相机实时视频流回传显示。APP上还有相册预览,媒体下载以及回放等功能,也需要PSDK端将相机的媒体信息回传然后在APP上呈现。
PSDK sample中另外开了一个宏定义:CONFIG_MODULE_SAMPLE_CAMERA_MEDIA_ON 用来打开camera media模拟功能,代码文件为:
test_payload_cam_emu_media.c test_payload_cam_emu_media.h
这部分实现方式与基本功能部分也基本一样,通过回调函数与APP端建立连接。
注册API:
/**
* @brief Register the handler for payload camera media download and playback function interfaces.
* @note Registering the camera playback and downloading related interfaces, mainly able to operate the media files of
* the user storage device online through the playback interface of the pilot. It can playback and download files
* of pictures and videos`. Currently, only media files in MP4 and JPG formats are supported.
* @param cameraMediaHandler: pointer to the handler for payload camera media download and playback functions.
* @return Execution result.
*/
T_DjiReturnCode DjiPayloadCamera_RegMediaDownloadPlaybackHandler(const T_DjiCameraMediaDownloadPlaybackHandler
*cameraMediaHandler);API简介:
-
注册相机媒体功能回调。对应的是APP端比如DJI Pilot相册管理功能,可以查看预览图片,下载图片以及媒体回放等功能。需要注意,当前仅支持JPG、MP4格式文件。
参数说明
-
cameraMediaHandler,相机媒体功能回调句柄。
typedef struct {
//获取媒体文件存放路径,表示的是PSDK设备上相机媒体文件存放路径
T_DjiReturnCode (*GetMediaFileDir)(char *dirPath);
//获取媒体文件原始信息,文件类型、格式等信息
T_DjiReturnCode (*GetMediaFileOriginInfo)(const char *filePath, T_DjiCameraMediaFileInfo *fileInfo);
//获取媒体文件数据,区别与file info,文件数据是实际的媒体数据比如图片数据或MP4音视频
T_DjiReturnCode (*GetMediaFileOriginData)(const char *filePath, uint32_t offset, uint32_t length, uint8_t *data);
//创建缩略图,sample尺寸:scale=100:-1
T_DjiReturnCode (*CreateMediaFileThumbNail)(const char *filePath);
//获取缩略图文件信息
T_DjiReturnCode (*GetMediaFileThumbNailInfo)(const char *filePath, T_DjiCameraMediaFileInfo *fileInfo);
//获取缩略图文件数据,区别与文件信息(格式,大小等)
T_DjiReturnCode (*GetMediaFileThumbNailData)(const char *filePath, uint32_t offset, uint32_t length,
uint8_t *data);
//销毁缩略图,释放内存资源
T_DjiReturnCode (*DestroyMediaFileThumbNail)(const char *filePath);
//创建屏显缩略图,比例为适配屏幕放大,sample尺寸:scale=600:-1,所以这个与缩略图的区别在于这个是放大版的缩略图
T_DjiReturnCode (*CreateMediaFileScreenNail)(const char *filePath);
//获取缩略图文件数据
T_DjiReturnCode (*GetMediaFileScreenNailData)(const char *filePath, uint32_t offset, uint32_t length,
uint8_t *data);
//获取缩略图文件信息
T_DjiReturnCode (*GetMediaFileScreenNailInfo)(const char *filePath, T_DjiCameraMediaFileInfo *fileInfo);
//销毁缩略图,释放内存资源
T_DjiReturnCode (*DestroyMediaFileScreenNail)(const char *filePath);
//开始下载通知回调,开始下载时会触发此函数,通常用于调整数据通道带宽比
T_DjiReturnCode (*StartDownloadNotification)(void);
//停止下载通知,停止下载时触发,可用于恢复数据通道带宽比
T_DjiReturnCode (*StopDownloadNotification)(void);
//删除指定媒体文件
T_DjiReturnCode (*DeleteMediaFile)(char *filePath);
//获取媒体回放状态
T_DjiReturnCode (*GetMediaPlaybackStatus)(T_DjiCameraPlaybackStatus *status);
//设置需要回放的媒体文件
T_DjiReturnCode (*SetMediaPlaybackFile)(const char *filePath);
//开始回放
T_DjiReturnCode (*StartMediaPlayback)(void);
//停止回放
T_DjiReturnCode (*StopMediaPlayback)(void);
//暂停回放
T_DjiReturnCode (*PauseMediaPlayback)(void);
//设置回放进度位置
T_DjiReturnCode (*SeekMediaPlayback)(uint32_t playbackPosition);
} T_DjiCameraMediaDownloadPlaybackHandler;
注册好与APP端交互的回调后,也要开启一个任务实时给APP端推送视频流,sample没有相机设备采集视频流,使用一个H264裸流文件读取H264帧向APP端发送。
returnCode = osalHandler->TaskCreate("user_camera_media_task", UserCameraMedia_SendVideoTask, 2048,
NULL, &s_userSendVideoThread);
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
USER_LOG_ERROR("user send video task create error.");
return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
}具体代码不展开了,这部分实际使用过程中应该是需要调整代码的,实际使用中一般不需要保存成H264文件再推送,直接从采集端编码成的H264帧通过发送API发送即可。
-
5.2.4 开发注意事项
-
camera emu是PSDK的一个基本模块功能,Pilot APP上相机和云台是一体的,如果注册使用camera emu模块,Pilot相机界面无法选定PSDK负载,如果同时挂载多个相机负载时,就无法切换到PSDK负载上,遥控器也就无法选定和控制PSDK负载,但是自定义控件是可用的。实际负载也是可控的(通过MSDK,OSDK指定负载的位置控制),但是APP上无法选定到PSDK界面来。
-
回调函数中要避免阻塞,否则可能会导致PSDK主线程卡住影响与APP端的通信连接。
-
sample代码中的回调实现都是通用功能的demo,可以根据实际应用来调整或修改。但是回调的定义个参数格式不可更改。
-
实时视频流需结合相机视频采集按帧向飞机端发送,H264格式需要满足官方指定标准。注意码率大小和帧率控制。
-
创建缩略图部分需要注意正确释放资源,否则可能会导致内存泄露,无特殊需求可直接使用sample案例。
-
评论
0 条评论
请登录写评论。