作者 ookk303

更新

正在显示 18 个修改的文件 包含 4858 行增加3 行删除

要显示太多修改。

为保证性能只显示 18 of 18+ 个文件。

@@ -8,8 +8,20 @@ ModuleLib @@ -8,8 +8,20 @@ ModuleLib
8 project_build/AUTEL_道通PSDK 8 project_build/AUTEL_道通PSDK
9 project_build/GDU_普宙PSDK 9 project_build/GDU_普宙PSDK
10 10
11 -project_build/Only_Serial/build  
12 -project_build/Only_Serial/Upgrade_Package 11 +project_build/Only_Serial/*
  12 +!project_build/Only_Serial/application
  13 +!project_build/Only_Serial/CMakeLists.txt
13 14
14 -project_build/DJI_大疆PSDK 15 +
  16 +project_build/DJI_大疆PSDK/*
15 !project_build/DJI_大疆PSDK/samples 17 !project_build/DJI_大疆PSDK/samples
  18 +project_build/DJI_大疆PSDK/samples/sample_c++
  19 +
  20 +project_build/DJI_大疆PSDK/samples/sample_c/platform/*
  21 +!project_build/DJI_大疆PSDK/samples/sample_c/platform/linux
  22 +
  23 +
  24 +project_build/DJI_大疆PSDK/samples/sample_c/platform/linux/all/*
  25 +!project_build/DJI_大疆PSDK/samples/sample_c/platform/linux/all/application
  26 +!project_build/DJI_大疆PSDK/samples/sample_c/platform/linux/all/hal
  27 +!project_build/DJI_大疆PSDK/samples/sample_c/platform/linux/all/CMakeLists.txt
  1 +/**
  2 + ********************************************************************
  3 + * @file dji_media_file_core.c
  4 + * @brief
  5 + *
  6 + * @copyright (c) 2021 DJI. All rights reserved.
  7 + *
  8 + * All information contained herein is, and remains, the property of DJI.
  9 + * The intellectual and technical concepts contained herein are proprietary
  10 + * to DJI and may be covered by U.S. and foreign patents, patents in process,
  11 + * and protected by trade secret or copyright law. Dissemination of this
  12 + * information, including but not limited to data and other proprietary
  13 + * material(s) incorporated within the information, in any form, is strictly
  14 + * prohibited without the express written consent of DJI.
  15 + *
  16 + * If you receive this source code without DJI’s authorization, you may not
  17 + * further disseminate the information, and you must immediately remove the
  18 + * source code and notify DJI of its removal. DJI reserves the right to pursue
  19 + * legal actions against you for any loss(es) or damage(s) caused by your
  20 + * failure to do so.
  21 + *
  22 + *********************************************************************
  23 + */
  24 +
  25 +/* Includes ------------------------------------------------------------------*/
  26 +#include <string.h>
  27 +#include <dji_logger.h>
  28 +
  29 +#include "dji_media_file_core.h"
  30 +#include "dji_media_file_jpg.h"
  31 +#include "dji_media_file_mp4.h"
  32 +#include "dji_platform.h"
  33 +
  34 +/* Private constants ---------------------------------------------------------*/
  35 +
  36 +/* Private types -------------------------------------------------------------*/
  37 +
  38 +/* Private functions declaration ---------------------------------------------*/
  39 +
  40 +/* Private values ------------------------------------------------------------*/
  41 +//@formatter:off
  42 +static const T_DjiMediaFileOptItem s_mediaFileOpt[] =
  43 +{
  44 + //JPEG File Operation Item
  45 + {
  46 + DJI_CAMERA_FILE_TYPE_JPEG ,
  47 + DjiMediaFile_IsSupported_JPG,
  48 + DjiMediaFile_GetAttrFunc_JPG,
  49 + DjiMediaFile_GetDataOrigin_JPG,
  50 + DjiMediaFile_GetFileSizeOrigin_JPG,
  51 + DjiMediaFile_CreateThumbNail_JPG,
  52 + DjiMediaFile_GetFileSizeThumbNail_JPG,
  53 + DjiMediaFile_GetDataThumbNail_JPG,
  54 + DjiMediaFile_DestroyThumbNail_JPG,
  55 + DjiMediaFile_CreateScreenNail_JPG,
  56 + DjiMediaFile_GetFileSizeScreenNail_JPG,
  57 + DjiMediaFile_GetDataScreenNail_JPG,
  58 + DjiMediaFile_DestroyScreenNail_JPG,
  59 + },
  60 + //MP4 File Operation Item
  61 + {
  62 + DJI_CAMERA_FILE_TYPE_MP4 ,
  63 + DjiMediaFile_IsSupported_MP4,
  64 + DjiMediaFile_GetAttrFunc_MP4,
  65 + DjiMediaFile_GetDataOrigin_MP4,
  66 + DjiMediaFile_GetFileSizeOrigin_MP4,
  67 + DjiMediaFile_CreateThumbNail_MP4,
  68 + DjiMediaFile_GetFileSizeThumbNail_MP4,
  69 + DjiMediaFile_GetDataThumbNail_MP4,
  70 + DjiMediaFile_DestroyThumbNail_MP4,
  71 + DjiMediaFile_CreateScreenNail_MP4,
  72 + DjiMediaFile_GetFileSizeScreenNail_MP4,
  73 + DjiMediaFile_GetDataScreenNail_MP4,
  74 + DjiMediaFile_DestroyScreenNail_MP4,
  75 + },
  76 +};
  77 +static const uint32_t s_mediaFileOptCount = sizeof (s_mediaFileOpt) / sizeof(T_DjiMediaFileOptItem);
  78 +//@formatter:on
  79 +
  80 +/* Exported functions definition ---------------------------------------------*/
  81 +bool DjiMediaFile_IsSupported(const char *filePath)
  82 +{
  83 + int i;
  84 +
  85 + for (i = 0; i < s_mediaFileOptCount; i++) {
  86 + if (s_mediaFileOpt[i].isSupportedFunc(filePath) == true) {
  87 + return true;
  88 + }
  89 + }
  90 +
  91 + return false;
  92 +}
  93 +
  94 +T_DjiReturnCode DjiMediaFile_CreateHandle(const char *filePath, T_DjiMediaFileHandle *pMediaFileHandle)
  95 +{
  96 + int optIndex;
  97 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  98 +
  99 + for (optIndex = 0; optIndex < s_mediaFileOptCount; optIndex++) {
  100 + if (s_mediaFileOpt[optIndex].isSupportedFunc(filePath) == true) {
  101 + break;
  102 + }
  103 + }
  104 +
  105 + if (optIndex == s_mediaFileOptCount) {
  106 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  107 + }
  108 +
  109 + *pMediaFileHandle = osalHandler->Malloc(sizeof(T_DjiMediaFile));
  110 + if (*pMediaFileHandle == NULL) {
  111 + return DJI_ERROR_SYSTEM_MODULE_CODE_MEMORY_ALLOC_FAILED;
  112 + }
  113 +
  114 + (*pMediaFileHandle)->filePath = osalHandler->Malloc(strlen(filePath) + 1);
  115 + if ((*pMediaFileHandle)->filePath == NULL) {
  116 + return DJI_ERROR_SYSTEM_MODULE_CODE_MEMORY_ALLOC_FAILED;
  117 + }
  118 +
  119 + (*pMediaFileHandle)->mediaFileOptItem = s_mediaFileOpt[optIndex];
  120 + (*pMediaFileHandle)->mediaFileThm.privThm = NULL;
  121 + (*pMediaFileHandle)->mediaFileScr.privScr = NULL;
  122 +
  123 + strcpy((*pMediaFileHandle)->filePath, filePath);
  124 +
  125 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  126 +}
  127 +
  128 +T_DjiReturnCode DjiMediaFile_DestroyHandle(T_DjiMediaFileHandle mediaFileHandle)
  129 +{
  130 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  131 +
  132 + osalHandler->Free(mediaFileHandle->filePath);
  133 + osalHandler->Free(mediaFileHandle);
  134 +
  135 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  136 +}
  137 +
  138 +T_DjiReturnCode DjiMediaFile_GetMediaFileType(T_DjiMediaFileHandle mediaFileHandle,
  139 + E_DjiCameraMediaFileType *mediaFileType)
  140 +{
  141 + *mediaFileType = mediaFileHandle->mediaFileOptItem.mediaFileType;
  142 +
  143 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  144 +}
  145 +
  146 +T_DjiReturnCode DjiMediaFile_GetMediaFileAttr(T_DjiMediaFileHandle mediaFileHandle,
  147 + T_DjiCameraMediaFileAttr *mediaFileAttr)
  148 +{
  149 + if (mediaFileHandle->mediaFileOptItem.getAttrFunc == NULL) {
  150 + USER_LOG_ERROR("Media file handle getAttrFunc null error");
  151 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  152 + }
  153 +
  154 + return mediaFileHandle->mediaFileOptItem.getAttrFunc(mediaFileHandle, mediaFileAttr);
  155 +}
  156 +
  157 +T_DjiReturnCode DjiMediaFile_GetDataOrg(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  158 + uint8_t *data, uint32_t *realLen)
  159 +{
  160 + if (mediaFileHandle->mediaFileOptItem.getDataOrgFunc == NULL) {
  161 + USER_LOG_ERROR("Media file handle getDataOrgFunc null error");
  162 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  163 + }
  164 +
  165 + return mediaFileHandle->mediaFileOptItem.getDataOrgFunc(mediaFileHandle, offset, len, data, realLen);
  166 +}
  167 +
  168 +T_DjiReturnCode DjiMediaFile_GetFileSizeOrg(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize)
  169 +{
  170 + if (mediaFileHandle->mediaFileOptItem.getFileSizeOrgFunc == NULL) {
  171 + USER_LOG_ERROR("Media file handle getFileSizeOrgFunc null error");
  172 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  173 + }
  174 +
  175 + return mediaFileHandle->mediaFileOptItem.getFileSizeOrgFunc(mediaFileHandle, fileSize);
  176 +}
  177 +
  178 +T_DjiReturnCode DjiMediaFile_CreateThm(T_DjiMediaFileHandle mediaFileHandle)
  179 +{
  180 + if (mediaFileHandle->mediaFileOptItem.createThmFunc == NULL) {
  181 + USER_LOG_ERROR("Media file handle createThmFunc null error");
  182 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  183 + }
  184 +
  185 + return mediaFileHandle->mediaFileOptItem.createThmFunc(mediaFileHandle);
  186 +}
  187 +
  188 +T_DjiReturnCode DjiMediaFile_GetFileSizeThm(T_DjiMediaFileHandle mediaFileHandle, uint32_t *fileSize)
  189 +{
  190 + if (mediaFileHandle->mediaFileOptItem.getFileSizeThmFunc == NULL) {
  191 + USER_LOG_ERROR("Media file handle getFileSizeThmFunc null error");
  192 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  193 + }
  194 +
  195 + return mediaFileHandle->mediaFileOptItem.getFileSizeThmFunc(mediaFileHandle, fileSize);
  196 +}
  197 +
  198 +T_DjiReturnCode DjiMediaFile_GetDataThm(T_DjiMediaFileHandle mediaFileHandle, uint32_t offset, uint16_t len,
  199 + uint8_t *data, uint16_t *realLen)
  200 +{
  201 + if (mediaFileHandle->mediaFileOptItem.getDataThmFunc == NULL) {
  202 + USER_LOG_ERROR("Media file handle getDataThmFunc null error");
  203 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  204 + }
  205 +
  206 + return mediaFileHandle->mediaFileOptItem.getDataThmFunc(mediaFileHandle, offset, len, data, realLen);
  207 +}
  208 +
  209 +T_DjiReturnCode DjiMediaFile_DestoryThm(T_DjiMediaFileHandle mediaFileHandle)
  210 +{
  211 + if (mediaFileHandle->mediaFileOptItem.destroyThmFunc == NULL) {
  212 + USER_LOG_ERROR("Media file handle destroyThmFunc null error");
  213 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  214 + }
  215 +
  216 + return mediaFileHandle->mediaFileOptItem.destroyThmFunc(mediaFileHandle);
  217 +}
  218 +
  219 +T_DjiReturnCode DjiMediaFile_CreateScr(T_DjiMediaFileHandle mediaFileHandle)
  220 +{
  221 + if (mediaFileHandle->mediaFileOptItem.creatScrFunc == NULL) {
  222 + USER_LOG_ERROR("Media file handle creatScrFunc null error");
  223 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  224 + }
  225 +
  226 + return mediaFileHandle->mediaFileOptItem.creatScrFunc(mediaFileHandle);
  227 +}
  228 +
  229 +T_DjiReturnCode DjiMediaFile_GetFileSizeScr(T_DjiMediaFileHandle mediaFileHandle, uint32_t *fileSize)
  230 +{
  231 + if (mediaFileHandle->mediaFileOptItem.getFileSizeScrFunc == NULL) {
  232 + USER_LOG_ERROR("Media file handle getFileSizeScrFunc null error");
  233 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  234 + }
  235 +
  236 + return mediaFileHandle->mediaFileOptItem.getFileSizeScrFunc(mediaFileHandle, fileSize);
  237 +}
  238 +
  239 +T_DjiReturnCode DjiMediaFile_GetDataScr(T_DjiMediaFileHandle mediaFileHandle, uint32_t offset, uint16_t len,
  240 + uint8_t *data, uint16_t *realLen)
  241 +{
  242 + if (mediaFileHandle->mediaFileOptItem.getDataScrFunc == NULL) {
  243 + USER_LOG_ERROR("Media file handle getDataScrFunc null error");
  244 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  245 + }
  246 +
  247 + return mediaFileHandle->mediaFileOptItem.getDataScrFunc(mediaFileHandle, offset, len, data, realLen);
  248 +}
  249 +
  250 +T_DjiReturnCode DjiMediaFile_DestroyScr(T_DjiMediaFileHandle mediaFileHandle)
  251 +{
  252 + if (mediaFileHandle->mediaFileOptItem.destroyScrFunc == NULL) {
  253 + USER_LOG_ERROR("Media file handle destroyScrFunc null error");
  254 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  255 + }
  256 +
  257 + return mediaFileHandle->mediaFileOptItem.destroyScrFunc(mediaFileHandle);
  258 +}
  259 +
  260 +/* Private functions definition-----------------------------------------------*/
  261 +
  262 +/****************** (C) COPYRIGHT DJI Innovations *****END OF FILE****/
  1 +/**
  2 + ********************************************************************
  3 + * @file dji_media_file_core.h
  4 + * @brief This is the header file for "dji_media_file_core.c", defining the structure and
  5 + * (exported) function prototypes.
  6 + *
  7 + * @copyright (c) 2021 DJI. All rights reserved.
  8 + *
  9 + * All information contained herein is, and remains, the property of DJI.
  10 + * The intellectual and technical concepts contained herein are proprietary
  11 + * to DJI and may be covered by U.S. and foreign patents, patents in process,
  12 + * and protected by trade secret or copyright law. Dissemination of this
  13 + * information, including but not limited to data and other proprietary
  14 + * material(s) incorporated within the information, in any form, is strictly
  15 + * prohibited without the express written consent of DJI.
  16 + *
  17 + * If you receive this source code without DJI’s authorization, you may not
  18 + * further disseminate the information, and you must immediately remove the
  19 + * source code and notify DJI of its removal. DJI reserves the right to pursue
  20 + * legal actions against you for any loss(es) or damage(s) caused by your
  21 + * failure to do so.
  22 + *
  23 + *********************************************************************
  24 + */
  25 +
  26 +/* Define to prevent recursive inclusion -------------------------------------*/
  27 +#ifndef PSDK_MEDIA_FILE_CORE_H
  28 +#define PSDK_MEDIA_FILE_CORE_H
  29 +
  30 +#ifdef __cplusplus
  31 +extern "C" {
  32 +#endif
  33 +
  34 +/* Includes ------------------------------------------------------------------*/
  35 +#include <dji_typedef.h>
  36 +#include <dji_payload_camera.h>
  37 +
  38 +/* Exported constants --------------------------------------------------------*/
  39 +#define PSDK_MEDIA_FILE_PATH_LEN_MAX 512 /*max file path len */
  40 +#define PSDK_MEDIA_DIR_PATH_LEN_MAX 256 /*max dir path len */
  41 +
  42 +/* Exported types ------------------------------------------------------------*/
  43 +typedef struct {
  44 + void *privThm;
  45 +} T_DjiMediaFileThm;
  46 +
  47 +typedef struct {
  48 + void *privScr;
  49 +} T_DjiMediaFileScr;
  50 +
  51 +struct _DjiMediaFile;
  52 +
  53 +typedef struct {
  54 + E_DjiCameraMediaFileType mediaFileType;
  55 + bool (*isSupportedFunc)(const char *filePath);
  56 +
  57 + T_DjiReturnCode (*getAttrFunc)(struct _DjiMediaFile *mediaFileHandle, T_DjiCameraMediaFileAttr *mediaFileAttr);
  58 +
  59 + T_DjiReturnCode (*getDataOrgFunc)(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  60 + uint8_t *data, uint32_t *realLen);
  61 + T_DjiReturnCode (*getFileSizeOrgFunc)(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize);
  62 +
  63 + T_DjiReturnCode (*createThmFunc)(struct _DjiMediaFile *mediaFileHandle);
  64 + T_DjiReturnCode (*getFileSizeThmFunc)(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize);
  65 + T_DjiReturnCode (*getDataThmFunc)(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  66 + uint8_t *data, uint16_t *realLen);
  67 + T_DjiReturnCode (*destroyThmFunc)(struct _DjiMediaFile *mediaFileHandle);
  68 +
  69 + T_DjiReturnCode (*creatScrFunc)(struct _DjiMediaFile *mediaFileHandle);
  70 + T_DjiReturnCode (*getFileSizeScrFunc)(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize);
  71 + T_DjiReturnCode (*getDataScrFunc)(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  72 + uint8_t *data, uint16_t *realLen);
  73 + T_DjiReturnCode (*destroyScrFunc)(struct _DjiMediaFile *mediaFileHandle);
  74 +} T_DjiMediaFileOptItem;
  75 +
  76 +typedef struct _DjiMediaFile {
  77 + char *filePath;
  78 + T_DjiMediaFileOptItem mediaFileOptItem;
  79 + T_DjiMediaFileThm mediaFileThm;
  80 + T_DjiMediaFileScr mediaFileScr;
  81 +} T_DjiMediaFile, *T_DjiMediaFileHandle;
  82 +
  83 +/* Exported functions --------------------------------------------------------*/
  84 +bool DjiMediaFile_IsSupported(const char *filePath);
  85 +T_DjiReturnCode DjiMediaFile_CreateHandle(const char *filePath, T_DjiMediaFileHandle *pMediaFileHandle);
  86 +T_DjiReturnCode DjiMediaFile_DestroyHandle(T_DjiMediaFileHandle mediaFileHandle);
  87 +
  88 +T_DjiReturnCode DjiMediaFile_GetMediaFileType(T_DjiMediaFileHandle mediaFileHandle,
  89 + E_DjiCameraMediaFileType *mediaFileType);
  90 +T_DjiReturnCode DjiMediaFile_GetMediaFileAttr(T_DjiMediaFileHandle mediaFileHandle,
  91 + T_DjiCameraMediaFileAttr *mediaFileAttr);
  92 +
  93 +T_DjiReturnCode DjiMediaFile_GetDataOrg(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  94 + uint8_t *data, uint32_t *realLen);
  95 +T_DjiReturnCode DjiMediaFile_GetFileSizeOrg(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize);
  96 +
  97 +T_DjiReturnCode DjiMediaFile_CreateThm(T_DjiMediaFileHandle mediaFileHandle);
  98 +T_DjiReturnCode DjiMediaFile_GetFileSizeThm(T_DjiMediaFileHandle mediaFileHandle, uint32_t *fileSize);
  99 +T_DjiReturnCode DjiMediaFile_GetDataThm(T_DjiMediaFileHandle mediaFileHandle, uint32_t offset, uint16_t len,
  100 + uint8_t *data, uint16_t *realLen);
  101 +T_DjiReturnCode DjiMediaFile_DestoryThm(T_DjiMediaFileHandle mediaFileHandle);
  102 +
  103 +T_DjiReturnCode DjiMediaFile_CreateScr(T_DjiMediaFileHandle mediaFileHandle);
  104 +T_DjiReturnCode DjiMediaFile_GetFileSizeScr(T_DjiMediaFileHandle mediaFileHandle, uint32_t *fileSize);
  105 +T_DjiReturnCode DjiMediaFile_GetDataScr(T_DjiMediaFileHandle mediaFileHandle, uint32_t offset, uint16_t len,
  106 + uint8_t *data, uint16_t *realLen);
  107 +T_DjiReturnCode DjiMediaFile_DestroyScr(T_DjiMediaFileHandle mediaFileHandle);
  108 +
  109 +#ifdef __cplusplus
  110 +}
  111 +#endif
  112 +
  113 +#endif // PSDK_MEDIA_FILE_CORE_H
  114 +
  115 +/************************ (C) COPYRIGHT DJI Innovations *******END OF FILE******/
  1 +/**
  2 + ********************************************************************
  3 + * @file dji_media_file_jpg.c
  4 + * @brief
  5 + *
  6 + * @copyright (c) 2021 DJI. All rights reserved.
  7 + *
  8 + * All information contained herein is, and remains, the property of DJI.
  9 + * The intellectual and technical concepts contained herein are proprietary
  10 + * to DJI and may be covered by U.S. and foreign patents, patents in process,
  11 + * and protected by trade secret or copyright law. Dissemination of this
  12 + * information, including but not limited to data and other proprietary
  13 + * material(s) incorporated within the information, in any form, is strictly
  14 + * prohibited without the express written consent of DJI.
  15 + *
  16 + * If you receive this source code without DJI’s authorization, you may not
  17 + * further disseminate the information, and you must immediately remove the
  18 + * source code and notify DJI of its removal. DJI reserves the right to pursue
  19 + * legal actions against you for any loss(es) or damage(s) caused by your
  20 + * failure to do so.
  21 + *
  22 + *********************************************************************
  23 + */
  24 +
  25 +
  26 +/* Includes ------------------------------------------------------------------*/
  27 +#include "dji_media_file_jpg.h"
  28 +#include "dji_media_file_core.h"
  29 +#include <stdio.h>
  30 +#include <string.h>
  31 +#include <stdlib.h>
  32 +#include <unistd.h>
  33 +#include <dji_logger.h>
  34 +#include <utils/util_misc.h>
  35 +#include "dji_platform.h"
  36 +#include "utils/util_time.h"
  37 +#include "utils/util_file.h"
  38 +
  39 +/* Private constants ---------------------------------------------------------*/
  40 +#define JPG_FILE_SUFFIX ".jpg"
  41 +#define JPG_TEMP_FILE_TEMPLATE_STR "JPG_TEMP_XXXXXX.jpg"
  42 +#define JPG_TEMP_FILE_PATH_MAX_LEN 50
  43 +#define FFMPEG_CMD_BUF_SIZE 1024
  44 +
  45 +#define JPG_THM_SCALE_CFG_STR "scale=100:-1"
  46 +#define JPG_SCR_SCALE_CFG_STR "scale=600:-1"
  47 +
  48 +/* Private types -------------------------------------------------------------*/
  49 +typedef struct {
  50 + FILE *tempFile;
  51 + char tempfilePath[JPG_TEMP_FILE_PATH_MAX_LEN];
  52 +} T_DjiJPGTempFilePriv;
  53 +
  54 +/* Private functions declaration ---------------------------------------------*/
  55 +static T_DjiReturnCode DjiMediaFile_CreateTempFilePriv_JPG(const char *srcFilePath, const char *scaleCfgStr,
  56 + T_DjiJPGTempFilePriv **pTempFilePrivHandle);
  57 +static T_DjiReturnCode DjiMediaFile_DestroyTempFilePriv_JPG(T_DjiJPGTempFilePriv *tempFilePrivHandle);
  58 +
  59 +/* Exported functions definition ---------------------------------------------*/
  60 +bool DjiMediaFile_IsSupported_JPG(const char *filePath)
  61 +{
  62 + if (filePath == NULL) {
  63 + USER_LOG_ERROR("input parameter is null error");
  64 + return false;
  65 + }
  66 +
  67 + if (strcmp(&filePath[strlen(filePath) - 4], JPG_FILE_SUFFIX) == 0) {
  68 + return true;
  69 + }
  70 +
  71 + return false;
  72 +}
  73 +
  74 +T_DjiReturnCode DjiMediaFile_GetAttrFunc_JPG(struct _DjiMediaFile *mediaFileHandle,
  75 + T_DjiCameraMediaFileAttr *mediaFileAttr)
  76 +{
  77 + USER_UTIL_UNUSED(mediaFileHandle);
  78 +
  79 + mediaFileAttr->attrVideoDuration = 0;
  80 +
  81 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  82 +}
  83 +
  84 +T_DjiReturnCode DjiMediaFile_GetDataOrigin_JPG(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  85 + uint8_t *data, uint32_t *realLen)
  86 +{
  87 + return UtilFile_GetFileDataByPath(mediaFileHandle->filePath, offset, len, data, realLen);
  88 +}
  89 +
  90 +T_DjiReturnCode DjiMediaFile_GetFileSizeOrigin_JPG(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize)
  91 +{
  92 + return UtilFile_GetFileSizeByPath(mediaFileHandle->filePath, fileSize);
  93 +}
  94 +
  95 +T_DjiReturnCode DjiMediaFile_CreateThumbNail_JPG(struct _DjiMediaFile *mediaFileHandle)
  96 +{
  97 + return DjiMediaFile_CreateTempFilePriv_JPG(mediaFileHandle->filePath, JPG_THM_SCALE_CFG_STR,
  98 + (T_DjiJPGTempFilePriv **) &mediaFileHandle->mediaFileThm.privThm);
  99 +}
  100 +
  101 +T_DjiReturnCode DjiMediaFile_GetFileSizeThumbNail_JPG(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize)
  102 +{
  103 + T_DjiJPGTempFilePriv *jpgFileThmPriv = (T_DjiJPGTempFilePriv *) mediaFileHandle->mediaFileThm.privThm;
  104 +
  105 + return UtilFile_GetFileSize(jpgFileThmPriv->tempFile, fileSize);
  106 +}
  107 +
  108 +T_DjiReturnCode
  109 +DjiMediaFile_GetDataThumbNail_JPG(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  110 + uint8_t *data, uint16_t *realLen)
  111 +{
  112 + T_DjiJPGTempFilePriv *jpgFileThmPriv = (T_DjiJPGTempFilePriv *) mediaFileHandle->mediaFileThm.privThm;
  113 +
  114 + return UtilFile_GetFileData(jpgFileThmPriv->tempFile, offset, len, data, realLen);
  115 +}
  116 +
  117 +T_DjiReturnCode DjiMediaFile_DestroyThumbNail_JPG(struct _DjiMediaFile *mediaFileHandle)
  118 +{
  119 + return DjiMediaFile_DestroyTempFilePriv_JPG(mediaFileHandle->mediaFileThm.privThm);
  120 +}
  121 +
  122 +T_DjiReturnCode DjiMediaFile_CreateScreenNail_JPG(struct _DjiMediaFile *mediaFileHandle)
  123 +{
  124 + return DjiMediaFile_CreateTempFilePriv_JPG(mediaFileHandle->filePath, JPG_SCR_SCALE_CFG_STR,
  125 + (T_DjiJPGTempFilePriv **) &mediaFileHandle->mediaFileScr.privScr);
  126 +}
  127 +
  128 +T_DjiReturnCode DjiMediaFile_GetFileSizeScreenNail_JPG(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize)
  129 +{
  130 + T_DjiJPGTempFilePriv *jpgFileScrPriv = (T_DjiJPGTempFilePriv *) mediaFileHandle->mediaFileScr.privScr;
  131 +
  132 + return UtilFile_GetFileSize(jpgFileScrPriv->tempFile, fileSize);
  133 +}
  134 +
  135 +T_DjiReturnCode
  136 +DjiMediaFile_GetDataScreenNail_JPG(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  137 + uint8_t *data, uint16_t *realLen)
  138 +{
  139 + T_DjiJPGTempFilePriv *jpgFileScrPriv = (T_DjiJPGTempFilePriv *) mediaFileHandle->mediaFileScr.privScr;
  140 +
  141 + return UtilFile_GetFileData(jpgFileScrPriv->tempFile, offset, len, data, realLen);
  142 +}
  143 +
  144 +T_DjiReturnCode DjiMediaFile_DestroyScreenNail_JPG(struct _DjiMediaFile *mediaFileHandle)
  145 +{
  146 + return DjiMediaFile_DestroyTempFilePriv_JPG(mediaFileHandle->mediaFileScr.privScr);
  147 +}
  148 +
  149 +/* Private functions definition-----------------------------------------------*/
  150 +static T_DjiReturnCode DjiMediaFile_CreateTempFilePriv_JPG(const char *srcFilePath, const char *scaleCfgStr,
  151 + T_DjiJPGTempFilePriv **pTempFilePrivHandle)
  152 +{
  153 + char ffmpeg_cmd[FFMPEG_CMD_BUF_SIZE];
  154 + int cmdRet;
  155 + T_DjiRunTimeStamps tiStart, tiEnd;
  156 + T_DjiJPGTempFilePriv *jpgTempFilePriv;
  157 + T_DjiReturnCode psdkStat;
  158 + int tempFd;
  159 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  160 +
  161 + tiStart = DjiUtilTime_GetRunTimeStamps();
  162 +
  163 + *pTempFilePrivHandle = osalHandler->Malloc(sizeof(T_DjiJPGTempFilePriv));
  164 + if (*pTempFilePrivHandle == NULL) {
  165 + return DJI_ERROR_SYSTEM_MODULE_CODE_MEMORY_ALLOC_FAILED;
  166 + }
  167 +
  168 + jpgTempFilePriv = *pTempFilePrivHandle;
  169 +
  170 + //get temp file name
  171 + strcpy(jpgTempFilePriv->tempfilePath, JPG_TEMP_FILE_TEMPLATE_STR);
  172 + tempFd = mkstemps(jpgTempFilePriv->tempfilePath, strlen(JPG_FILE_SUFFIX));
  173 + if (tempFd < 0) {
  174 + USER_LOG_ERROR("JPG Create Temp File Error, tempFd = %d\n", tempFd);
  175 + psdkStat = DJI_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  176 + goto err_create_temp;
  177 + }
  178 + close(tempFd);
  179 + unlink(jpgTempFilePriv->tempfilePath);
  180 +
  181 + //ffmpeg cmd send
  182 + snprintf(ffmpeg_cmd, FFMPEG_CMD_BUF_SIZE, "ffmpeg -i \"%s\" -vf %s %s 1>/dev/null 2>&1",
  183 + srcFilePath, scaleCfgStr, jpgTempFilePriv->tempfilePath);
  184 +
  185 + cmdRet = system(ffmpeg_cmd);
  186 +
  187 + tiEnd = DjiUtilTime_GetRunTimeStamps();
  188 +
  189 + USER_LOG_DEBUG("JPG Create TempFile, RealTime = %ld us\n", tiEnd.realUsec - tiStart.realUsec);
  190 +
  191 + if (cmdRet != 0) {
  192 + USER_LOG_ERROR("JPG ffmpeg cmd call error, ret = %d\n", cmdRet);
  193 + psdkStat = DJI_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  194 + goto err_system_cmd;
  195 + }
  196 +
  197 + //open temp file
  198 + jpgTempFilePriv->tempFile = fopen(jpgTempFilePriv->tempfilePath, "rb+");
  199 + if (jpgTempFilePriv->tempFile == NULL) {
  200 + psdkStat = DJI_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  201 + goto err_file_open;
  202 + }
  203 +
  204 + //unlink temp file
  205 + unlink(jpgTempFilePriv->tempfilePath);
  206 +
  207 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  208 +
  209 +err_file_open:
  210 + unlink(jpgTempFilePriv->tempfilePath);
  211 +err_system_cmd:
  212 +err_create_temp:
  213 + osalHandler->Free(*pTempFilePrivHandle);
  214 +
  215 + return psdkStat;
  216 +}
  217 +
  218 +static T_DjiReturnCode DjiMediaFile_DestroyTempFilePriv_JPG(T_DjiJPGTempFilePriv *tempFilePrivHandle)
  219 +{
  220 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  221 +
  222 + fclose(tempFilePrivHandle->tempFile);
  223 + osalHandler->Free(tempFilePrivHandle);
  224 +
  225 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  226 +}
  227 +
  228 +/****************** (C) COPYRIGHT DJI Innovations *****END OF FILE****/
  1 +/**
  2 + ********************************************************************
  3 + * @file dji_media_file_jpg.h
  4 + * @brief This is the header file for "dji_media_file_jpg.c", defining the structure and
  5 + * (exported) function prototypes.
  6 + *
  7 + * @copyright (c) 2021 DJI. All rights reserved.
  8 + *
  9 + * All information contained herein is, and remains, the property of DJI.
  10 + * The intellectual and technical concepts contained herein are proprietary
  11 + * to DJI and may be covered by U.S. and foreign patents, patents in process,
  12 + * and protected by trade secret or copyright law. Dissemination of this
  13 + * information, including but not limited to data and other proprietary
  14 + * material(s) incorporated within the information, in any form, is strictly
  15 + * prohibited without the express written consent of DJI.
  16 + *
  17 + * If you receive this source code without DJI’s authorization, you may not
  18 + * further disseminate the information, and you must immediately remove the
  19 + * source code and notify DJI of its removal. DJI reserves the right to pursue
  20 + * legal actions against you for any loss(es) or damage(s) caused by your
  21 + * failure to do so.
  22 + *
  23 + *********************************************************************
  24 + */
  25 +
  26 +/* Define to prevent recursive inclusion -------------------------------------*/
  27 +#ifndef PSDK_MEDIA_FILE_JPG_H
  28 +#define PSDK_MEDIA_FILE_JPG_H
  29 +
  30 +#ifdef __cplusplus
  31 +extern "C" {
  32 +#endif
  33 +
  34 +/* Includes ------------------------------------------------------------------*/
  35 +#include <dji_payload_camera.h>
  36 +#include <dji_typedef.h>
  37 +#include "dji_media_file_core.h"
  38 +
  39 +/* Exported constants --------------------------------------------------------*/
  40 +
  41 +
  42 +/* Exported types ------------------------------------------------------------*/
  43 +
  44 +
  45 +/* Exported functions --------------------------------------------------------*/
  46 +bool DjiMediaFile_IsSupported_JPG(const char *filePath);
  47 +
  48 +T_DjiReturnCode DjiMediaFile_GetAttrFunc_JPG(struct _DjiMediaFile *mediaFileHandle,
  49 + T_DjiCameraMediaFileAttr *mediaFileAttr);
  50 +
  51 +T_DjiReturnCode DjiMediaFile_GetDataOrigin_JPG(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  52 + uint8_t *data, uint32_t *realLen);
  53 +T_DjiReturnCode DjiMediaFile_GetFileSizeOrigin_JPG(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize);
  54 +
  55 +T_DjiReturnCode DjiMediaFile_CreateThumbNail_JPG(struct _DjiMediaFile *mediaFileHandle);
  56 +T_DjiReturnCode DjiMediaFile_GetFileSizeThumbNail_JPG(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize);
  57 +T_DjiReturnCode
  58 +DjiMediaFile_GetDataThumbNail_JPG(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  59 + uint8_t *data, uint16_t *realLen);
  60 +T_DjiReturnCode DjiMediaFile_DestroyThumbNail_JPG(struct _DjiMediaFile *mediaFileHandle);
  61 +
  62 +T_DjiReturnCode DjiMediaFile_CreateScreenNail_JPG(struct _DjiMediaFile *mediaFileHandle);
  63 +T_DjiReturnCode DjiMediaFile_GetFileSizeScreenNail_JPG(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize);
  64 +T_DjiReturnCode
  65 +DjiMediaFile_GetDataScreenNail_JPG(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  66 + uint8_t *data, uint16_t *realLen);
  67 +T_DjiReturnCode DjiMediaFile_DestroyScreenNail_JPG(struct _DjiMediaFile *mediaFileHandle);
  68 +
  69 +#ifdef __cplusplus
  70 +}
  71 +#endif
  72 +
  73 +#endif // PSDK_MEIDA_FILE_JPG_H
  74 +
  75 +/************************ (C) COPYRIGHT DJI Innovations *******END OF FILE******/
  1 +/**
  2 + ********************************************************************
  3 + * @file dji_media_file_mp4.c
  4 + * @brief
  5 + *
  6 + * @copyright (c) 2021 DJI. All rights reserved.
  7 + *
  8 + * All information contained herein is, and remains, the property of DJI.
  9 + * The intellectual and technical concepts contained herein are proprietary
  10 + * to DJI and may be covered by U.S. and foreign patents, patents in process,
  11 + * and protected by trade secret or copyright law. Dissemination of this
  12 + * information, including but not limited to data and other proprietary
  13 + * material(s) incorporated within the information, in any form, is strictly
  14 + * prohibited without the express written consent of DJI.
  15 + *
  16 + * If you receive this source code without DJI’s authorization, you may not
  17 + * further disseminate the information, and you must immediately remove the
  18 + * source code and notify DJI of its removal. DJI reserves the right to pursue
  19 + * legal actions against you for any loss(es) or damage(s) caused by your
  20 + * failure to do so.
  21 + *
  22 + *********************************************************************
  23 + */
  24 +
  25 +
  26 +/* Includes ------------------------------------------------------------------*/
  27 +#include "dji_media_file_mp4.h"
  28 +#include "dji_media_file_core.h"
  29 +#include <string.h>
  30 +#include <unistd.h>
  31 +#include <stdio.h>
  32 +#include <dji_logger.h>
  33 +#include <stdlib.h>
  34 +#include "dji_platform.h"
  35 +#include "utils/util_time.h"
  36 +#include "utils/util_file.h"
  37 +
  38 +/* Private constants ---------------------------------------------------------*/
  39 +
  40 +#define MP4_FILE_SUFFIX ".mp4"
  41 +#define MP4_TEMP_FILE_TEMPLATE_STR "MP4_TEMP_XXXXXX.jpg"
  42 +#define MP4_TEMP_FILE_PATH_MAX_LEN 50
  43 +#define FFMPEG_CMD_BUF_SIZE (256 + 256)
  44 +
  45 +#define MP4_THM_SCALE_CFG_STR "scale=100:-1"
  46 +#define MP4_SCR_SCALE_CFG_STR "scale=600:-1"
  47 +
  48 +/* Private types -------------------------------------------------------------*/
  49 +typedef struct {
  50 + FILE *tempFile;
  51 + char tempfilePath[MP4_TEMP_FILE_PATH_MAX_LEN];
  52 +} T_DjiMP4TempPicPriv;
  53 +
  54 +/* Private functions declaration ---------------------------------------------*/
  55 +static T_DjiReturnCode DjiMediaFile_CreateTempPicPriv_MP4(const char *srcFilePath, const char *scaleCfgStr,
  56 + T_DjiMP4TempPicPriv **pTempPicPrivHandle);
  57 +static T_DjiReturnCode DjiMediaFile_DestroyTempPicPriv_MP4(T_DjiMP4TempPicPriv *tempPicPrivHandle);
  58 +
  59 +/* Private values ------------------------------------------------------------*/
  60 +
  61 +/* Exported functions definition ---------------------------------------------*/
  62 +bool DjiMediaFile_IsSupported_MP4(const char *filePath)
  63 +{
  64 + if (filePath == NULL) {
  65 + USER_LOG_ERROR("input parameter is null error");
  66 + return false;
  67 + }
  68 +
  69 + if (strcmp(&filePath[strlen(filePath) - 4], MP4_FILE_SUFFIX) == 0) {
  70 + return true;
  71 + }
  72 +
  73 + return false;
  74 +}
  75 +
  76 +T_DjiReturnCode DjiMediaFile_GetAttrFunc_MP4(struct _DjiMediaFile *mediaFileHandle,
  77 + T_DjiCameraMediaFileAttr *mediaFileAttr)
  78 +{
  79 + FILE *fp;
  80 + char ffmpegCmdStr[FFMPEG_CMD_BUF_SIZE];
  81 + float hour, minute, second;
  82 + char tempTailStr[128];
  83 + int ret;
  84 + T_DjiReturnCode psdkStat;
  85 +
  86 + snprintf(ffmpegCmdStr, FFMPEG_CMD_BUF_SIZE, "ffmpeg -i \"%s\" 2>&1 | grep \"Duration\"", mediaFileHandle->filePath);
  87 + fp = popen(ffmpegCmdStr, "r");
  88 +
  89 + if (fp == NULL) {
  90 + return DJI_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  91 + }
  92 +
  93 + ret = fscanf(fp, " Duration: %f:%f:%f,%127s", &hour, &minute, &second, tempTailStr);
  94 + if (ret <= 0) {
  95 + USER_LOG_ERROR("MP4 File Get Duration Error\n");
  96 + psdkStat = DJI_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  97 + goto out;
  98 + }
  99 +
  100 + mediaFileAttr->attrVideoDuration = (uint32_t) (hour * 3600 + minute * 60 + second + 0.5);
  101 +
  102 + /*! The user needs to obtain the frame rate and resolution of the video file by ffmpeg tools.
  103 + * Also the frame rate and resolution of video need convert to enum E_DjiCameraVideoFrameRate or
  104 + * E_DjiCameraVideoResolution.
  105 + */
  106 + mediaFileAttr->attrVideoFrameRate = DJI_CAMERA_VIDEO_FRAME_RATE_30_FPS;
  107 + mediaFileAttr->attrVideoResolution = DJI_CAMERA_VIDEO_RESOLUTION_1920x1080;
  108 +
  109 + psdkStat = DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  110 +
  111 +out:
  112 + pclose(fp);
  113 +
  114 + return psdkStat;
  115 +}
  116 +
  117 +T_DjiReturnCode DjiMediaFile_GetDataOrigin_MP4(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  118 + uint8_t *data, uint32_t *realLen)
  119 +{
  120 + return UtilFile_GetFileDataByPath(mediaFileHandle->filePath, offset, len, data, realLen);
  121 +}
  122 +
  123 +T_DjiReturnCode DjiMediaFile_GetFileSizeOrigin_MP4(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize)
  124 +{
  125 + return UtilFile_GetFileSizeByPath(mediaFileHandle->filePath, fileSize);
  126 +}
  127 +
  128 +T_DjiReturnCode DjiMediaFile_CreateThumbNail_MP4(struct _DjiMediaFile *mediaFileHandle)
  129 +{
  130 +
  131 + return DjiMediaFile_CreateTempPicPriv_MP4(mediaFileHandle->filePath, MP4_THM_SCALE_CFG_STR,
  132 + (T_DjiMP4TempPicPriv **) &mediaFileHandle->mediaFileThm.privThm);
  133 +}
  134 +
  135 +T_DjiReturnCode DjiMediaFile_GetFileSizeThumbNail_MP4(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize)
  136 +{
  137 + T_DjiMP4TempPicPriv *jpgFileThmPriv = (T_DjiMP4TempPicPriv *) mediaFileHandle->mediaFileThm.privThm;
  138 +
  139 + return UtilFile_GetFileSize(jpgFileThmPriv->tempFile, fileSize);
  140 +}
  141 +
  142 +T_DjiReturnCode
  143 +DjiMediaFile_GetDataThumbNail_MP4(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  144 + uint8_t *data, uint16_t *realLen)
  145 +{
  146 + T_DjiMP4TempPicPriv *jpgFileThmPriv = (T_DjiMP4TempPicPriv *) mediaFileHandle->mediaFileThm.privThm;
  147 +
  148 + return UtilFile_GetFileData(jpgFileThmPriv->tempFile, offset, len, data, realLen);
  149 +}
  150 +
  151 +T_DjiReturnCode DjiMediaFile_DestroyThumbNail_MP4(struct _DjiMediaFile *MediaFileHandle)
  152 +{
  153 + return DjiMediaFile_DestroyTempPicPriv_MP4(MediaFileHandle->mediaFileThm.privThm);
  154 +}
  155 +
  156 +T_DjiReturnCode DjiMediaFile_CreateScreenNail_MP4(struct _DjiMediaFile *mediaFileHandle)
  157 +{
  158 + return DjiMediaFile_CreateTempPicPriv_MP4(mediaFileHandle->filePath, MP4_SCR_SCALE_CFG_STR,
  159 + (T_DjiMP4TempPicPriv **) &mediaFileHandle->mediaFileScr.privScr);
  160 +}
  161 +
  162 +T_DjiReturnCode DjiMediaFile_GetFileSizeScreenNail_MP4(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize)
  163 +{
  164 + T_DjiMP4TempPicPriv *jpgFileScrPriv = (T_DjiMP4TempPicPriv *) mediaFileHandle->mediaFileScr.privScr;
  165 +
  166 + return UtilFile_GetFileSize(jpgFileScrPriv->tempFile, fileSize);
  167 +}
  168 +
  169 +T_DjiReturnCode
  170 +DjiMediaFile_GetDataScreenNail_MP4(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  171 + uint8_t *data, uint16_t *realLen)
  172 +{
  173 + T_DjiMP4TempPicPriv *jpgFileScrPriv = (T_DjiMP4TempPicPriv *) mediaFileHandle->mediaFileScr.privScr;
  174 +
  175 + return UtilFile_GetFileData(jpgFileScrPriv->tempFile, offset, len, data, realLen);
  176 +}
  177 +
  178 +T_DjiReturnCode DjiMediaFile_DestroyScreenNail_MP4(struct _DjiMediaFile *mediaFileHandle)
  179 +{
  180 + return DjiMediaFile_DestroyTempPicPriv_MP4(mediaFileHandle->mediaFileScr.privScr);
  181 +}
  182 +
  183 +/* Private functions definition-----------------------------------------------*/
  184 +static T_DjiReturnCode DjiMediaFile_CreateTempPicPriv_MP4(const char *srcFilePath, const char *scaleCfgStr,
  185 + T_DjiMP4TempPicPriv **pTempPicPrivHandle)
  186 +{
  187 + char ffmpeg_cmd[FFMPEG_CMD_BUF_SIZE];
  188 + int cmdRet;
  189 + T_DjiRunTimeStamps tiStart, tiEnd;
  190 + T_DjiMP4TempPicPriv *mp4TempPicFile;
  191 + T_DjiReturnCode psdkStat;
  192 + int tempFd;
  193 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  194 +
  195 + tiStart = DjiUtilTime_GetRunTimeStamps();
  196 +
  197 + *pTempPicPrivHandle = osalHandler->Malloc(sizeof(T_DjiMP4TempPicPriv));
  198 + if (*pTempPicPrivHandle == NULL) {
  199 + return DJI_ERROR_SYSTEM_MODULE_CODE_MEMORY_ALLOC_FAILED;
  200 + }
  201 +
  202 + mp4TempPicFile = *pTempPicPrivHandle;
  203 +
  204 + //get temp file name
  205 + strcpy(mp4TempPicFile->tempfilePath, MP4_TEMP_FILE_TEMPLATE_STR);
  206 + tempFd = mkstemps(mp4TempPicFile->tempfilePath, strlen(MP4_FILE_SUFFIX));
  207 + if (tempFd < 0) {
  208 + USER_LOG_ERROR("JPG Create Temp File Error, tempFd = %d\n", tempFd);
  209 + psdkStat = DJI_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  210 + goto err_create_temp;
  211 + }
  212 + close(tempFd);
  213 + unlink(mp4TempPicFile->tempfilePath);
  214 +
  215 + //ffmpeg cmd send
  216 + snprintf(ffmpeg_cmd, FFMPEG_CMD_BUF_SIZE, "ffmpeg -i \"%s\" -vf %s -ss 00:00:00 -vframes 1 %s 1>/dev/null 2>&1",
  217 + srcFilePath, scaleCfgStr, mp4TempPicFile->tempfilePath);
  218 +
  219 + cmdRet = system(ffmpeg_cmd);
  220 +
  221 + tiEnd = DjiUtilTime_GetRunTimeStamps();
  222 +
  223 + USER_LOG_DEBUG("JPG Create TempFile, RealTime = %ld us\n", tiEnd.realUsec - tiStart.realUsec);
  224 +
  225 + if (cmdRet != 0) {
  226 + USER_LOG_ERROR("JPG ffmpeg cmd call error, ret = %d\n", cmdRet);
  227 + psdkStat = DJI_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  228 + goto err_system_cmd;
  229 + }
  230 +
  231 + //open temp file
  232 + mp4TempPicFile->tempFile = fopen(mp4TempPicFile->tempfilePath, "rb+");
  233 + if (mp4TempPicFile->tempFile == NULL) {
  234 + psdkStat = DJI_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  235 + goto err_file_open;
  236 + }
  237 +
  238 + //unlink temp file
  239 + unlink(mp4TempPicFile->tempfilePath);
  240 +
  241 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  242 +
  243 +err_file_open:
  244 + unlink(mp4TempPicFile->tempfilePath);
  245 +err_system_cmd:
  246 +err_create_temp:
  247 + osalHandler->Free(*pTempPicPrivHandle);
  248 +
  249 + return psdkStat;
  250 +}
  251 +
  252 +static T_DjiReturnCode DjiMediaFile_DestroyTempPicPriv_MP4(T_DjiMP4TempPicPriv *tempPicPrivHandle)
  253 +{
  254 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  255 +
  256 + fclose(tempPicPrivHandle->tempFile);
  257 + osalHandler->Free(tempPicPrivHandle);
  258 +
  259 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  260 +}
  261 +
  262 +/****************** (C) COPYRIGHT DJI Innovations *****END OF FILE****/
  1 +/**
  2 + ********************************************************************
  3 + * @file dji_media_file_mp4.h
  4 + * @brief This is the header file for "dji_media_file_mp4.c", defining the structure and
  5 + * (exported) function prototypes.
  6 + *
  7 + * @copyright (c) 2021 DJI. All rights reserved.
  8 + *
  9 + * All information contained herein is, and remains, the property of DJI.
  10 + * The intellectual and technical concepts contained herein are proprietary
  11 + * to DJI and may be covered by U.S. and foreign patents, patents in process,
  12 + * and protected by trade secret or copyright law. Dissemination of this
  13 + * information, including but not limited to data and other proprietary
  14 + * material(s) incorporated within the information, in any form, is strictly
  15 + * prohibited without the express written consent of DJI.
  16 + *
  17 + * If you receive this source code without DJI’s authorization, you may not
  18 + * further disseminate the information, and you must immediately remove the
  19 + * source code and notify DJI of its removal. DJI reserves the right to pursue
  20 + * legal actions against you for any loss(es) or damage(s) caused by your
  21 + * failure to do so.
  22 + *
  23 + *********************************************************************
  24 + */
  25 +
  26 +/* Define to prevent recursive inclusion -------------------------------------*/
  27 +#ifndef PSDK_MEDIA_FILE_MP4_H
  28 +#define PSDK_MEDIA_FILE_MP4_H
  29 +
  30 +#ifdef __cplusplus
  31 +extern "C" {
  32 +#endif
  33 +
  34 +/* Includes ------------------------------------------------------------------*/
  35 +#include <dji_payload_camera.h>
  36 +#include <dji_typedef.h>
  37 +#include "dji_media_file_core.h"
  38 +
  39 +/* Exported constants --------------------------------------------------------*/
  40 +
  41 +
  42 +/* Exported types ------------------------------------------------------------*/
  43 +
  44 +
  45 +/* Exported functions --------------------------------------------------------*/
  46 +bool DjiMediaFile_IsSupported_MP4(const char *filePath);
  47 +
  48 +T_DjiReturnCode DjiMediaFile_GetAttrFunc_MP4(struct _DjiMediaFile *mediaFileHandle,
  49 + T_DjiCameraMediaFileAttr *mediaFileAttr);
  50 +
  51 +T_DjiReturnCode DjiMediaFile_GetDataOrigin_MP4(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  52 + uint8_t *data, uint32_t *realLen);
  53 +T_DjiReturnCode DjiMediaFile_GetFileSizeOrigin_MP4(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize);
  54 +
  55 +T_DjiReturnCode DjiMediaFile_CreateThumbNail_MP4(struct _DjiMediaFile *mediaFileHandle);
  56 +T_DjiReturnCode DjiMediaFile_GetFileSizeThumbNail_MP4(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize);
  57 +T_DjiReturnCode
  58 +DjiMediaFile_GetDataThumbNail_MP4(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  59 + uint8_t *data, uint16_t *realLen);
  60 +T_DjiReturnCode DjiMediaFile_DestroyThumbNail_MP4(struct _DjiMediaFile *MediaFileHandle);
  61 +
  62 +T_DjiReturnCode DjiMediaFile_CreateScreenNail_MP4(struct _DjiMediaFile *mediaFileHandle);
  63 +T_DjiReturnCode DjiMediaFile_GetFileSizeScreenNail_MP4(struct _DjiMediaFile *mediaFileHandle, uint32_t *fileSize);
  64 +T_DjiReturnCode
  65 +DjiMediaFile_GetDataScreenNail_MP4(struct _DjiMediaFile *mediaFileHandle, uint32_t offset, uint16_t len,
  66 + uint8_t *data, uint16_t *realLen);
  67 +T_DjiReturnCode DjiMediaFile_DestroyScreenNail_MP4(struct _DjiMediaFile *mediaFileHandle);
  68 +
  69 +#ifdef __cplusplus
  70 +}
  71 +#endif
  72 +
  73 +#endif // PSDK_MEDIA_FILE_MP4_H
  74 +
  75 +/************************ (C) COPYRIGHT DJI Innovations *******END OF FILE******/
  1 +/**
  2 + ********************************************************************
  3 + * @file test_payload_cam_emu_common.c
  4 + * @brief
  5 + *
  6 + * @copyright (c) 2021 DJI. All rights reserved.
  7 + *
  8 + * All information contained herein is, and remains, the property of DJI.
  9 + * The intellectual and technical concepts contained herein are proprietary
  10 + * to DJI and may be covered by U.S. and foreign patents, patents in process,
  11 + * and protected by trade secret or copyright law. Dissemination of this
  12 + * information, including but not limited to data and other proprietary
  13 + * material(s) incorporated within the information, in any form, is strictly
  14 + * prohibited without the express written consent of DJI.
  15 + *
  16 + * If you receive this source code without DJI’s authorization, you may not
  17 + * further disseminate the information, and you must immediately remove the
  18 + * source code and notify DJI of its removal. DJI reserves the right to pursue
  19 + * legal actions against you for any loss(es) or damage(s) caused by your
  20 + * failure to do so.
  21 + *
  22 + *********************************************************************
  23 + */
  24 +
  25 +/* Includes ------------------------------------------------------------------*/
  26 +#include "math.h"
  27 +#include "test_payload_cam_emu_base.h"
  28 +#include "utils/util_misc.h"
  29 +#include "dji_logger.h"
  30 +#include "dji_platform.h"
  31 +#include "dji_payload_camera.h"
  32 +#include "dji_aircraft_info.h"
  33 +#include "dji_gimbal.h"
  34 +#include "dji_xport.h"
  35 +#include "gimbal_emu/test_payload_gimbal_emu.h"
  36 +
  37 +#include "Psdk_UI_io.h"
  38 +
  39 +
  40 +/* Private constants ---------------------------------------------------------*/
  41 +#define PAYLOAD_CAMERA_EMU_TASK_FREQ (100)
  42 +#define PAYLOAD_CAMERA_EMU_TASK_STACK_SIZE (2048)
  43 +#define SDCARD_TOTAL_SPACE_IN_MB (32 * 1024)
  44 +#define SDCARD_PER_PHOTO_SPACE_IN_MB (4)
  45 +#define SDCARD_PER_SECONDS_RECORD_SPACE_IN_MB (2)
  46 +#define ZOOM_OPTICAL_FOCAL_MAX_LENGTH (300)
  47 +#define ZOOM_OPTICAL_FOCAL_MIN_LENGTH (10)
  48 +#define ZOOM_OPTICAL_FOCAL_LENGTH_STEP (10)
  49 +#define ZOOM_OPTICAL_FOCAL_LENGTH_CTRL_STEP (5)
  50 +#define ZOOM_DIGITAL_BASE_FACTOR (1.0)
  51 +#define ZOOM_DIGITAL_STEP_FACTOR (0.1)
  52 +#define ZOOM_DIGITAL_MAX_FACTOR (6.0)
  53 +#define FOCUS_MAX_RINGVALUE (1000)
  54 +#define FOCUS_MID_RINGVALUE (500)
  55 +#define IMAGE_SENSOR_X_SIZE (88.0f) // unit: 0.1mm
  56 +#define IMAGE_SENSOR_Y_SIZE (66.0f) // unit: 0.1mm
  57 +#define CENTER_POINT_IN_SCREEN_X_VALUE (0.5f)
  58 +#define CENTER_POINT_IN_SCREEN_Y_VALUE (0.5f)
  59 +#define TAP_ZOOM_DURATION (2000) // unit: ms
  60 +#define INTERVAL_PHOTOGRAPH_ALWAYS_COUNT (255)
  61 +#define INTERVAL_PHOTOGRAPH_INTERVAL_INIT_VALUE (1) // unit: s
  62 +#define TAKING_PHOTO_SPENT_TIME_MS_EMU (500)
  63 +#define PHOTO_FILE_PATH "../../../../../api_sample/camera_media_emu/media_file/DJI_0001_ORG.jpg"
  64 +
  65 +// Attention: you can select which camera function you want to run, default: all on.
  66 +#define USER_CAMERA_EMU_METERING_ON 1
  67 +#define USER_CAMERA_EMU_FOCUS_ON 1
  68 +#define USER_CAMERA_EMU_HYBRID_ZOOM_ON 1
  69 +#define USER_CAMERA_EMU_TAP_ZOOM_ON 1
  70 +
  71 +/* Private types -------------------------------------------------------------*/
  72 +typedef struct {
  73 + E_DjiGimbalRotationMode rotationMode;
  74 + T_DjiGimbalRotationProperty rotationProperty;
  75 + T_DjiAttitude3d rotationValue;
  76 +} T_TestCameraGimbalRotationArgument;
  77 +
  78 +/* Private variables ---------------------------------------------------------*/
  79 +static bool s_isCamInited = false;
  80 +
  81 +static T_DjiCameraCommonHandler s_commonHandler;
  82 +static T_DjiCameraExposureMeteringHandler s_exposureMeteringHandler;
  83 +static T_DjiCameraFocusHandler s_focusHandler;
  84 +static T_DjiCameraDigitalZoomHandler s_digitalZoomHandler;
  85 +static T_DjiCameraOpticalZoomHandler s_opticalZoomHandler;
  86 +static T_DjiCameraTapZoomHandler s_tapZoomHandler;
  87 +
  88 +static T_DjiTaskHandle s_userCameraThread;
  89 +
  90 +static T_DjiCameraSystemState s_cameraState = {0};
  91 +static E_DjiCameraShootPhotoMode s_cameraShootPhotoMode = DJI_CAMERA_SHOOT_PHOTO_MODE_SINGLE;
  92 +static E_DjiCameraBurstCount s_cameraBurstCount = DJI_CAMERA_BURST_COUNT_2;
  93 +static T_DjiCameraPhotoTimeIntervalSettings s_cameraPhotoTimeIntervalSettings = {INTERVAL_PHOTOGRAPH_ALWAYS_COUNT,
  94 + INTERVAL_PHOTOGRAPH_INTERVAL_INIT_VALUE};
  95 +static T_DjiCameraSDCardState s_cameraSDCardState = {0};
  96 +static T_DjiMutexHandle s_commonMutex = {0};
  97 +
  98 +static E_DjiCameraMeteringMode s_cameraMeteringMode = DJI_CAMERA_METERING_MODE_CENTER;
  99 +static T_DjiCameraSpotMeteringTarget s_cameraSpotMeteringTarget = {0};
  100 +
  101 +static E_DjiCameraFocusMode s_cameraFocusMode = DJI_CAMERA_FOCUS_MODE_AUTO;
  102 +static T_DjiCameraPointInScreen s_cameraFocusTarget = {0};
  103 +static uint32_t s_cameraFocusRingValue = FOCUS_MID_RINGVALUE;
  104 +static T_DjiCameraFocusAssistantSettings s_cameraFocusAssistantSettings = {0};
  105 +
  106 +static E_DjiCameraZoomDirection s_cameraZoomDirection = DJI_CAMERA_ZOOM_DIRECTION_OUT;
  107 +static E_DjiCameraZoomSpeed s_cameraZoomSpeed = DJI_CAMERA_ZOOM_SPEED_NORMAL;
  108 +static uint32_t s_cameraOpticalZoomFocalLength = ZOOM_OPTICAL_FOCAL_MIN_LENGTH;
  109 +static dji_f32_t s_cameraDigitalZoomFactor = ZOOM_DIGITAL_BASE_FACTOR;
  110 +static bool s_isStartContinuousOpticalZoom = false;
  111 +static bool s_isOpticalZoomReachLimit = false;
  112 +static T_DjiMutexHandle s_zoomMutex = {0};
  113 +
  114 +static bool s_isTapZoomEnabled = false;
  115 +static T_DjiCameraTapZoomState s_cameraTapZoomState = {0};
  116 +static uint8_t s_tapZoomMultiplier = 1;
  117 +static uint32_t s_tapZoomStartTime = 0;
  118 +static bool s_isStartTapZoom = false;
  119 +static bool s_isTapZooming = false;
  120 +static T_TestCameraGimbalRotationArgument s_tapZoomNewestGimbalRotationArgument = {0};
  121 +static uint32_t s_tapZoomNewestTargetHybridFocalLength = 0; // unit: 0.1mm
  122 +static T_DjiMutexHandle s_tapZoomMutex = NULL;
  123 +static E_DjiCameraVideoStreamType s_cameraVideoStreamType;
  124 +
  125 +/* Private functions declaration ---------------------------------------------*/
  126 +static T_DjiReturnCode GetSystemState(T_DjiCameraSystemState *systemState);
  127 +static T_DjiReturnCode SetMode(E_DjiCameraMode mode);
  128 +static T_DjiReturnCode StartRecordVideo(void);
  129 +static T_DjiReturnCode StopRecordVideo(void);
  130 +static T_DjiReturnCode StartShootPhoto(void);
  131 +static T_DjiReturnCode StopShootPhoto(void);
  132 +static T_DjiReturnCode SetShootPhotoMode(E_DjiCameraShootPhotoMode mode);
  133 +static T_DjiReturnCode GetShootPhotoMode(E_DjiCameraShootPhotoMode *mode);
  134 +static T_DjiReturnCode SetPhotoBurstCount(E_DjiCameraBurstCount burstCount);
  135 +static T_DjiReturnCode GetPhotoBurstCount(E_DjiCameraBurstCount *burstCount);
  136 +static T_DjiReturnCode SetPhotoTimeIntervalSettings(T_DjiCameraPhotoTimeIntervalSettings settings);
  137 +static T_DjiReturnCode GetPhotoTimeIntervalSettings(T_DjiCameraPhotoTimeIntervalSettings *settings);
  138 +static T_DjiReturnCode GetSDCardState(T_DjiCameraSDCardState *sdCardState);
  139 +static T_DjiReturnCode FormatSDCard(void);
  140 +
  141 +static T_DjiReturnCode SetMeteringMode(E_DjiCameraMeteringMode mode);
  142 +static T_DjiReturnCode GetMeteringMode(E_DjiCameraMeteringMode *mode);
  143 +static T_DjiReturnCode SetSpotMeteringTarget(T_DjiCameraSpotMeteringTarget target);
  144 +static T_DjiReturnCode GetSpotMeteringTarget(T_DjiCameraSpotMeteringTarget *target);
  145 +
  146 +static T_DjiReturnCode SetFocusMode(E_DjiCameraFocusMode mode);
  147 +static T_DjiReturnCode GetFocusMode(E_DjiCameraFocusMode *mode);
  148 +static T_DjiReturnCode SetFocusTarget(T_DjiCameraPointInScreen target);
  149 +static T_DjiReturnCode GetFocusTarget(T_DjiCameraPointInScreen *target);
  150 +static T_DjiReturnCode SetFocusAssistantSettings(T_DjiCameraFocusAssistantSettings settings);
  151 +static T_DjiReturnCode GetFocusAssistantSettings(T_DjiCameraFocusAssistantSettings *settings);
  152 +static T_DjiReturnCode SetFocusRingValue(uint32_t value);
  153 +static T_DjiReturnCode GetFocusRingValue(uint32_t *value);
  154 +static T_DjiReturnCode GetFocusRingValueUpperBound(uint32_t *value);
  155 +
  156 +static T_DjiReturnCode SetDigitalZoomFactor(dji_f32_t factor);
  157 +static T_DjiReturnCode SetOpticalZoomFocalLength(uint32_t focalLength);
  158 +static T_DjiReturnCode GetOpticalZoomFocalLength(uint32_t *focalLength);
  159 +static T_DjiReturnCode GetOpticalZoomSpec(T_DjiCameraOpticalZoomSpec *spec);
  160 +static T_DjiReturnCode StartContinuousOpticalZoom(E_DjiCameraZoomDirection direction, E_DjiCameraZoomSpeed speed);
  161 +static T_DjiReturnCode StopContinuousOpticalZoom(void);
  162 +static T_DjiReturnCode GetTapZoomState(T_DjiCameraTapZoomState *state);
  163 +static T_DjiReturnCode SetTapZoomEnabled(bool enabledFlag);
  164 +static T_DjiReturnCode GetTapZoomEnabled(bool *enabledFlag);
  165 +static T_DjiReturnCode SetTapZoomMultiplier(uint8_t multiplier);
  166 +static T_DjiReturnCode GetTapZoomMultiplier(uint8_t *multiplier);
  167 +static T_DjiReturnCode TapZoomAtTarget(T_DjiCameraPointInScreen target);
  168 +static T_DjiReturnCode DjiTest_CameraHybridZoom(uint32_t focalLength);
  169 +static T_DjiReturnCode DjiTest_CameraRotationGimbal(T_TestCameraGimbalRotationArgument gimbalRotationArgument);
  170 +
  171 +static void *UserCamera_Task(void *arg);
  172 +
  173 +/* Exported functions definition ---------------------------------------------*/
  174 +
  175 +/* Private functions definition-----------------------------------------------*/
  176 +static T_DjiReturnCode GetSystemState(T_DjiCameraSystemState *systemState)
  177 +{
  178 + T_DjiReturnCode returnCode;
  179 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  180 +
  181 + returnCode = osalHandler->MutexLock(s_commonMutex);
  182 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  183 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  184 + return returnCode;
  185 + }
  186 +
  187 + *systemState = s_cameraState;
  188 +
  189 + returnCode = osalHandler->MutexUnlock(s_commonMutex);
  190 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  191 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  192 + return returnCode;
  193 + }
  194 +
  195 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  196 +}
  197 +
  198 +//设置模式
  199 +static T_DjiReturnCode SetMode(E_DjiCameraMode mode)
  200 +{
  201 + T_DjiReturnCode returnCode;
  202 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  203 +
  204 + returnCode = osalHandler->MutexLock(s_commonMutex);
  205 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  206 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  207 + return returnCode;
  208 + }
  209 +
  210 + s_cameraState.cameraMode = mode;
  211 + USER_LOG_INFO("set camera mode:%d", mode);
  212 +
  213 + returnCode = osalHandler->MutexUnlock(s_commonMutex);
  214 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  215 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  216 + return returnCode;
  217 + }
  218 +
  219 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  220 +}
  221 +
  222 +
  223 +// 开始录像
  224 +static T_DjiReturnCode StartRecordVideo(void)
  225 +{
  226 + T_DjiReturnCode djiStat;
  227 + T_DjiReturnCode returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  228 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  229 +
  230 + djiStat = osalHandler->MutexLock(s_commonMutex);
  231 + if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  232 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", djiStat);
  233 + return djiStat;
  234 + }
  235 +
  236 + if (s_cameraState.isRecording != false) {
  237 + USER_LOG_ERROR("camera is already in recording state");
  238 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_NONSUPPORT_IN_CURRENT_STATE;
  239 + goto out;
  240 + }
  241 +
  242 + s_cameraState.isRecording = true;
  243 + USER_LOG_INFO("start record video");
  244 + //录像通知函数
  245 + if(JZsdk_Psdk_UI_io_VideoRecord(1) != 0)
  246 + {
  247 + //录像开启失败
  248 + s_cameraState.isRecording = false;
  249 + }
  250 +
  251 +out:
  252 + djiStat = osalHandler->MutexUnlock(s_commonMutex);
  253 + if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  254 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", djiStat);
  255 + return djiStat;
  256 + }
  257 +
  258 + return returnCode;
  259 +}
  260 +
  261 +//结束录像
  262 +static T_DjiReturnCode StopRecordVideo(void)
  263 +{
  264 + T_DjiReturnCode djiStat;
  265 + T_DjiReturnCode returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  266 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  267 +
  268 + djiStat = osalHandler->MutexLock(s_commonMutex);
  269 + if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  270 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", djiStat);
  271 + return djiStat;
  272 + }
  273 +
  274 + if (s_cameraState.isRecording != true) {
  275 + USER_LOG_ERROR("camera is not in recording state");
  276 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_NONSUPPORT_IN_CURRENT_STATE;
  277 + goto out;
  278 + }
  279 +
  280 + s_cameraState.isRecording = false;
  281 + s_cameraState.isStoring = true;
  282 + s_cameraState.currentVideoRecordingTimeInSeconds = 0;
  283 +
  284 + USER_LOG_INFO("stop record video");
  285 + //录像通知函数
  286 + if(JZsdk_Psdk_UI_io_VideoRecord(0) != 0)
  287 + {
  288 + //关闭失败
  289 + s_cameraState.isRecording = true;
  290 + s_cameraState.isStoring = false;
  291 + }
  292 +
  293 +out:
  294 + djiStat = osalHandler->MutexUnlock(s_commonMutex);
  295 + if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  296 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", djiStat);
  297 + return djiStat;
  298 + }
  299 +
  300 + return returnCode;
  301 +}
  302 +
  303 +//拍照功能
  304 +static T_DjiReturnCode StartShootPhoto(void)
  305 +{
  306 + T_DjiReturnCode returnCode;
  307 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  308 +
  309 + returnCode = osalHandler->MutexLock(s_commonMutex);
  310 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  311 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  312 + return returnCode;
  313 + }
  314 +
  315 + USER_LOG_INFO("start shoot photo");
  316 + s_cameraState.isStoring = true;
  317 +
  318 + // 拍照模式的判定
  319 + if (s_cameraShootPhotoMode == DJI_CAMERA_SHOOT_PHOTO_MODE_SINGLE) {
  320 + s_cameraState.shootingState = DJI_CAMERA_SHOOTING_SINGLE_PHOTO;
  321 + // 这里接过去推流那边 以获取拍照内容
  322 + JZsdk_Psdk_UI_io_ShootPhoto();
  323 +
  324 + } else if (s_cameraShootPhotoMode == DJI_CAMERA_SHOOT_PHOTO_MODE_BURST) {
  325 + s_cameraState.shootingState = DJI_CAMERA_SHOOTING_BURST_PHOTO;
  326 + //暂时不做连拍
  327 + //JZsdk_Psdk_UI_io_BurstShootPhoto(s_cameraBurstCount);
  328 +
  329 + } else if (s_cameraShootPhotoMode == DJI_CAMERA_SHOOT_PHOTO_MODE_INTERVAL) {
  330 + s_cameraState.shootingState = DJI_CAMERA_SHOOTING_INTERVAL_PHOTO;
  331 + s_cameraState.isShootingIntervalStart = true;
  332 + s_cameraState.currentPhotoShootingIntervalTimeInSeconds = s_cameraPhotoTimeIntervalSettings.timeIntervalSeconds;
  333 + }
  334 +
  335 + returnCode = osalHandler->MutexUnlock(s_commonMutex);
  336 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  337 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  338 + return returnCode;
  339 + }
  340 +
  341 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  342 +}
  343 +
  344 +//停止拍照
  345 +static T_DjiReturnCode StopShootPhoto(void)
  346 +{
  347 + T_DjiReturnCode returnCode;
  348 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  349 +
  350 + returnCode = osalHandler->MutexLock(s_commonMutex);
  351 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  352 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  353 + return returnCode;
  354 + }
  355 +
  356 + USER_LOG_INFO("stop shoot photo");
  357 + s_cameraState.shootingState = DJI_CAMERA_SHOOTING_PHOTO_IDLE;
  358 +
  359 + //改成转码后再取消锁定
  360 + //s_cameraState.isStoring = false;
  361 + s_cameraState.isShootingIntervalStart = false;
  362 +
  363 + returnCode = osalHandler->MutexUnlock(s_commonMutex);
  364 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  365 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  366 + return returnCode;
  367 + }
  368 +
  369 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  370 +}
  371 +
  372 +
  373 +//设置拍摄模式
  374 +static T_DjiReturnCode SetShootPhotoMode(E_DjiCameraShootPhotoMode mode)
  375 +{
  376 + T_DjiReturnCode returnCode;
  377 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  378 +
  379 + returnCode = osalHandler->MutexLock(s_commonMutex);
  380 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  381 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  382 + return returnCode;
  383 + }
  384 +
  385 + s_cameraShootPhotoMode = mode;
  386 + USER_LOG_INFO("set shoot photo mode:%d", mode);
  387 +
  388 + returnCode = osalHandler->MutexUnlock(s_commonMutex);
  389 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  390 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  391 + return returnCode;
  392 + }
  393 +
  394 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  395 +}
  396 +
  397 +static T_DjiReturnCode GetShootPhotoMode(E_DjiCameraShootPhotoMode *mode)
  398 +{
  399 + T_DjiReturnCode returnCode;
  400 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  401 +
  402 + returnCode = osalHandler->MutexLock(s_commonMutex);
  403 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  404 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  405 + return returnCode;
  406 + }
  407 +
  408 + *mode = s_cameraShootPhotoMode;
  409 +
  410 + returnCode = osalHandler->MutexUnlock(s_commonMutex);
  411 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  412 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);\
  413 + return returnCode;
  414 + }
  415 +
  416 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  417 +}
  418 +
  419 +//加载相机的连拍数量
  420 +static T_DjiReturnCode SetPhotoBurstCount(E_DjiCameraBurstCount burstCount)
  421 +{
  422 + T_DjiReturnCode returnCode;
  423 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  424 +
  425 + returnCode = osalHandler->MutexLock(s_commonMutex);
  426 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  427 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  428 + return returnCode;
  429 + }
  430 +
  431 + s_cameraBurstCount = burstCount;
  432 + USER_LOG_INFO("set photo burst count:%d", burstCount);
  433 +
  434 + returnCode = osalHandler->MutexUnlock(s_commonMutex);
  435 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  436 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  437 + return returnCode;
  438 + }
  439 +
  440 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  441 +}
  442 +
  443 +
  444 +//得到相机设定的连拍数量
  445 +static T_DjiReturnCode GetPhotoBurstCount(E_DjiCameraBurstCount *burstCount)
  446 +{
  447 + T_DjiReturnCode returnCode;
  448 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  449 +
  450 + returnCode = osalHandler->MutexLock(s_commonMutex);
  451 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  452 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  453 + return returnCode;
  454 + }
  455 +
  456 + *burstCount = s_cameraBurstCount;
  457 +
  458 + returnCode = osalHandler->MutexUnlock(s_commonMutex);
  459 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  460 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  461 + return returnCode;
  462 + }
  463 +
  464 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  465 +}
  466 +
  467 +//设置定时拍摄的时间
  468 +static T_DjiReturnCode SetPhotoTimeIntervalSettings(T_DjiCameraPhotoTimeIntervalSettings settings)
  469 +{
  470 + T_DjiReturnCode returnCode;
  471 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  472 +
  473 + returnCode = osalHandler->MutexLock(s_commonMutex);
  474 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  475 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  476 + return returnCode;
  477 + }
  478 +
  479 + s_cameraPhotoTimeIntervalSettings.captureCount = settings.captureCount;
  480 + s_cameraPhotoTimeIntervalSettings.timeIntervalSeconds = settings.timeIntervalSeconds;
  481 + USER_LOG_INFO("set photo interval settings count:%d seconds:%d", settings.captureCount,
  482 + settings.timeIntervalSeconds);
  483 + s_cameraState.currentPhotoShootingIntervalCount = settings.captureCount;
  484 +
  485 + returnCode = osalHandler->MutexUnlock(s_commonMutex);
  486 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  487 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  488 + return returnCode;
  489 + }
  490 +
  491 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  492 +}
  493 +
  494 +//得到定时拍摄的时间
  495 +static T_DjiReturnCode GetPhotoTimeIntervalSettings(T_DjiCameraPhotoTimeIntervalSettings *settings)
  496 +{
  497 + T_DjiReturnCode returnCode;
  498 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  499 +
  500 + returnCode = osalHandler->MutexLock(s_commonMutex);
  501 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  502 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  503 + return returnCode;
  504 + }
  505 +
  506 + memcpy(settings, &s_cameraPhotoTimeIntervalSettings, sizeof(T_DjiCameraPhotoTimeIntervalSettings));
  507 +
  508 + returnCode = osalHandler->MutexUnlock(s_commonMutex);
  509 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  510 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  511 + return returnCode;
  512 + }
  513 +
  514 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  515 +}
  516 +
  517 +//得到sd佧的状态
  518 +static T_DjiReturnCode GetSDCardState(T_DjiCameraSDCardState *sdCardState)
  519 +{
  520 + T_DjiReturnCode returnCode;
  521 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  522 +
  523 + returnCode = osalHandler->MutexLock(s_commonMutex);
  524 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  525 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  526 + return returnCode;
  527 + }
  528 +
  529 + memcpy(sdCardState, &s_cameraSDCardState, sizeof(T_DjiCameraSDCardState));
  530 +
  531 + returnCode = osalHandler->MutexUnlock(s_commonMutex);
  532 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  533 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  534 + return returnCode;
  535 + }
  536 +
  537 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  538 +}
  539 +
  540 +// 格式化sd佧
  541 +static T_DjiReturnCode FormatSDCard(void)
  542 +{
  543 + T_DjiReturnCode returnCode;
  544 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  545 +
  546 + returnCode = osalHandler->MutexLock(s_commonMutex);
  547 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  548 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  549 + return returnCode;
  550 + }
  551 +
  552 + USER_LOG_INFO("format sdcard");
  553 +
  554 + memset(&s_cameraSDCardState, 0, sizeof(T_DjiCameraSDCardState));
  555 + s_cameraSDCardState.isInserted = true;
  556 + s_cameraSDCardState.isVerified = true;
  557 + s_cameraSDCardState.totalSpaceInMB = SDCARD_TOTAL_SPACE_IN_MB;
  558 + s_cameraSDCardState.remainSpaceInMB = SDCARD_TOTAL_SPACE_IN_MB;
  559 + s_cameraSDCardState.availableCaptureCount = SDCARD_TOTAL_SPACE_IN_MB / SDCARD_PER_PHOTO_SPACE_IN_MB;
  560 + s_cameraSDCardState.availableRecordingTimeInSeconds =
  561 + SDCARD_TOTAL_SPACE_IN_MB / SDCARD_PER_SECONDS_RECORD_SPACE_IN_MB;
  562 +
  563 + returnCode = osalHandler->MutexUnlock(s_commonMutex);
  564 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  565 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  566 + return returnCode;
  567 + }
  568 +
  569 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  570 +}
  571 +
  572 +
  573 +//设置测量模式
  574 +static T_DjiReturnCode SetMeteringMode(E_DjiCameraMeteringMode mode)
  575 +{
  576 + USER_LOG_INFO("set metering mode:%d", mode);
  577 + s_cameraMeteringMode = mode;
  578 +
  579 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  580 +}
  581 +
  582 +static T_DjiReturnCode GetMeteringMode(E_DjiCameraMeteringMode *mode)
  583 +{
  584 + *mode = s_cameraMeteringMode;
  585 +
  586 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  587 +}
  588 +
  589 +static T_DjiReturnCode SetSpotMeteringTarget(T_DjiCameraSpotMeteringTarget target)
  590 +{
  591 + USER_LOG_INFO("set spot metering area col:%d row:%d", target.col, target.row);
  592 + memcpy(&s_cameraSpotMeteringTarget, &target, sizeof(T_DjiCameraSpotMeteringTarget));
  593 +
  594 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  595 +}
  596 +
  597 +static T_DjiReturnCode GetSpotMeteringTarget(T_DjiCameraSpotMeteringTarget *target)
  598 +{
  599 + memcpy(target, &s_cameraSpotMeteringTarget, sizeof(T_DjiCameraSpotMeteringTarget));
  600 +
  601 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  602 +}
  603 +
  604 +static T_DjiReturnCode SetFocusMode(E_DjiCameraFocusMode mode)
  605 +{
  606 + USER_LOG_INFO("set focus mode:%d", mode);
  607 + s_cameraFocusMode = mode;
  608 +
  609 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  610 +}
  611 +
  612 +static T_DjiReturnCode GetFocusMode(E_DjiCameraFocusMode *mode)
  613 +{
  614 + *mode = s_cameraFocusMode;
  615 +
  616 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  617 +}
  618 +
  619 +static T_DjiReturnCode SetFocusTarget(T_DjiCameraPointInScreen target)
  620 +{
  621 + USER_LOG_INFO("set focus target x:%.2f y:%.2f", target.focusX, target.focusY);
  622 + memcpy(&s_cameraFocusTarget, &target, sizeof(T_DjiCameraPointInScreen));
  623 +
  624 + int PointX = (int)(target.focusX *100);
  625 + int PointY = (int)(target.focusY *100);
  626 +
  627 + //发送到对焦点
  628 + //USER_LOG_INFO("Px:%d Py:%d",PointX,PointY);
  629 + JZsdK_SetFocusTarget(PointX, PointY);
  630 +
  631 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  632 +}
  633 +
  634 +static T_DjiReturnCode GetFocusTarget(T_DjiCameraPointInScreen *target)
  635 +{
  636 + memcpy(target, &s_cameraFocusTarget, sizeof(T_DjiCameraPointInScreen));
  637 +
  638 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  639 +}
  640 +
  641 +static T_DjiReturnCode SetFocusAssistantSettings(T_DjiCameraFocusAssistantSettings settings)
  642 +{
  643 + USER_LOG_INFO("set focus assistant setting MF:%d AF:%d", settings.isEnabledMF, settings.isEnabledAF);
  644 + memcpy(&s_cameraFocusAssistantSettings, &settings, sizeof(T_DjiCameraFocusAssistantSettings));
  645 +
  646 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  647 +}
  648 +
  649 +static T_DjiReturnCode GetFocusAssistantSettings(T_DjiCameraFocusAssistantSettings *settings)
  650 +{
  651 + memcpy(settings, &s_cameraFocusAssistantSettings, sizeof(T_DjiCameraFocusAssistantSettings));
  652 +
  653 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  654 +}
  655 +
  656 +static T_DjiReturnCode SetFocusRingValue(uint32_t value)
  657 +{
  658 + USER_LOG_INFO("set focus ring value:%d", value);
  659 + s_cameraFocusRingValue = value;
  660 +
  661 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  662 +}
  663 +
  664 +static T_DjiReturnCode GetFocusRingValue(uint32_t *value)
  665 +{
  666 + *value = s_cameraFocusRingValue;
  667 +
  668 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  669 +}
  670 +
  671 +static T_DjiReturnCode GetFocusRingValueUpperBound(uint32_t *value)
  672 +{
  673 + *value = FOCUS_MAX_RINGVALUE;
  674 +
  675 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  676 +}
  677 +
  678 +static T_DjiReturnCode SetDigitalZoomFactor(dji_f32_t factor)
  679 +{
  680 + T_DjiReturnCode returnCode;
  681 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  682 +
  683 + returnCode = osalHandler->MutexLock(s_zoomMutex);
  684 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  685 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  686 + return returnCode;
  687 + }
  688 +
  689 + USER_LOG_INFO("set digital zoom factor:%.2f", factor);
  690 + s_cameraDigitalZoomFactor = factor;
  691 +
  692 + returnCode = osalHandler->MutexUnlock(s_zoomMutex);
  693 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  694 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  695 + return returnCode;
  696 + }
  697 +
  698 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  699 +}
  700 +
  701 +static T_DjiReturnCode SetOpticalZoomFocalLength(uint32_t focalLength)
  702 +{
  703 + T_DjiReturnCode returnCode;
  704 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  705 +
  706 + returnCode = osalHandler->MutexLock(s_zoomMutex);
  707 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  708 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  709 + return returnCode;
  710 + }
  711 +
  712 + USER_LOG_INFO("set optical zoom focal length:%d", focalLength);
  713 + s_isOpticalZoomReachLimit = false;
  714 + s_cameraDigitalZoomFactor = ZOOM_DIGITAL_BASE_FACTOR;
  715 + s_cameraOpticalZoomFocalLength = ZOOM_OPTICAL_FOCAL_MIN_LENGTH;
  716 +
  717 + returnCode = osalHandler->MutexUnlock(s_zoomMutex);
  718 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  719 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  720 + return returnCode;
  721 + }
  722 +
  723 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  724 +}
  725 +
  726 +static T_DjiReturnCode GetOpticalZoomFocalLength(uint32_t *focalLength)
  727 +{
  728 + T_DjiReturnCode returnCode;
  729 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  730 +
  731 + returnCode = osalHandler->MutexLock(s_zoomMutex);
  732 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  733 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  734 + return returnCode;
  735 + }
  736 +
  737 + *focalLength = s_cameraOpticalZoomFocalLength;
  738 +
  739 + returnCode = osalHandler->MutexUnlock(s_zoomMutex);
  740 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  741 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  742 + return returnCode;
  743 + }
  744 +
  745 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  746 +}
  747 +
  748 +static T_DjiReturnCode GetOpticalZoomSpec(T_DjiCameraOpticalZoomSpec *spec)
  749 +{
  750 + spec->maxFocalLength = ZOOM_OPTICAL_FOCAL_MAX_LENGTH;
  751 + spec->minFocalLength = ZOOM_OPTICAL_FOCAL_MIN_LENGTH;
  752 + spec->focalLengthStep = ZOOM_OPTICAL_FOCAL_LENGTH_STEP;
  753 +
  754 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  755 +}
  756 +
  757 +static T_DjiReturnCode StartContinuousOpticalZoom(E_DjiCameraZoomDirection direction, E_DjiCameraZoomSpeed speed)
  758 +{
  759 + T_DjiReturnCode returnCode;
  760 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  761 +
  762 + returnCode = osalHandler->MutexLock(s_zoomMutex);
  763 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  764 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  765 + return returnCode;
  766 + }
  767 +
  768 + USER_LOG_INFO("start continuous optical zoom direction:%d speed:%d", direction, speed);
  769 + s_isStartContinuousOpticalZoom = true;
  770 + s_cameraZoomDirection = direction;
  771 + s_cameraZoomSpeed = speed;
  772 +
  773 + returnCode = osalHandler->MutexUnlock(s_zoomMutex);
  774 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  775 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  776 + return returnCode;
  777 + }
  778 +
  779 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  780 +}
  781 +
  782 +static T_DjiReturnCode StopContinuousOpticalZoom(void)
  783 +{
  784 + T_DjiReturnCode returnCode;
  785 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  786 +
  787 + returnCode = osalHandler->MutexLock(s_zoomMutex);
  788 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  789 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  790 + return returnCode;
  791 + }
  792 +
  793 + USER_LOG_INFO("stop continuous optical zoom");
  794 + s_isStartContinuousOpticalZoom = false;
  795 + s_cameraZoomDirection = DJI_CAMERA_ZOOM_DIRECTION_OUT;
  796 + s_cameraZoomSpeed = DJI_CAMERA_ZOOM_SPEED_NORMAL;
  797 +
  798 + returnCode = osalHandler->MutexUnlock(s_zoomMutex);
  799 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  800 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  801 + return returnCode;
  802 + }
  803 +
  804 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  805 +}
  806 +
  807 +static T_DjiReturnCode GetTapZoomState(T_DjiCameraTapZoomState *state)
  808 +{
  809 + T_DjiReturnCode returnCode;
  810 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  811 +
  812 + returnCode = osalHandler->MutexLock(s_tapZoomMutex);
  813 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  814 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  815 + return returnCode;
  816 + }
  817 +
  818 + memcpy(state, &s_cameraTapZoomState, sizeof(T_DjiCameraTapZoomState));
  819 +
  820 + returnCode = osalHandler->MutexUnlock(s_tapZoomMutex);
  821 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  822 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  823 + return returnCode;
  824 + }
  825 +
  826 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  827 +}
  828 +
  829 +static T_DjiReturnCode SetTapZoomEnabled(bool enabledFlag)
  830 +{
  831 + USER_LOG_INFO("set tap zoom enabled flag: %d.", enabledFlag);
  832 + s_isTapZoomEnabled = enabledFlag;
  833 +
  834 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  835 +}
  836 +
  837 +static T_DjiReturnCode GetTapZoomEnabled(bool *enabledFlag)
  838 +{
  839 + *enabledFlag = s_isTapZoomEnabled;
  840 +
  841 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  842 +}
  843 +
  844 +static T_DjiReturnCode SetTapZoomMultiplier(uint8_t multiplier)
  845 +{
  846 + USER_LOG_INFO("set tap zoom multiplier: %d.", multiplier);
  847 + s_tapZoomMultiplier = multiplier;
  848 +
  849 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  850 +}
  851 +
  852 +static T_DjiReturnCode GetTapZoomMultiplier(uint8_t *multiplier)
  853 +{
  854 + *multiplier = s_tapZoomMultiplier;
  855 +
  856 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  857 +}
  858 +
  859 +static T_DjiReturnCode TapZoomAtTarget(T_DjiCameraPointInScreen target)
  860 +{
  861 + T_DjiReturnCode returnCode;
  862 + E_DjiGimbalRotationMode rotationMode;
  863 + T_DjiGimbalRotationProperty rotationProperty = {0};
  864 + T_DjiAttitude3d rotationValue = {0};
  865 + float hybridFocalLength = 0; // unit: 0.1mm
  866 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  867 +
  868 + USER_LOG_INFO("tap zoom at target: x %f, y %f.", target.focusX, target.focusY);
  869 +
  870 + if (s_isTapZoomEnabled != true) {
  871 + USER_LOG_WARN("tap zoom is not enabled.");
  872 + return DJI_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  873 + }
  874 +
  875 + if (s_isTapZooming || s_isStartTapZoom) {
  876 + USER_LOG_WARN("The last tap zoom process is not over.");
  877 + return DJI_ERROR_SYSTEM_MODULE_CODE_NONSUPPORT_IN_CURRENT_STATE;
  878 + }
  879 +
  880 + rotationMode = DJI_GIMBAL_ROTATION_MODE_RELATIVE_ANGLE;
  881 + rotationProperty.relativeAngleRotation.actionTime = TAP_ZOOM_DURATION / 10;
  882 +
  883 + returnCode = osalHandler->MutexLock(s_zoomMutex);
  884 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  885 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  886 + return returnCode;
  887 + }
  888 +
  889 + /* Calculation formula: rotation angle = arctan((coordinate of target in sensor - coordinate of center point in
  890 + * sensor) / hybrid focal length). Here, suppose that images of all pixels of sensor are displayed in screen,
  891 + * and that center of the image sensor coincides with center of rotation of the gimbal, and that optical axis of
  892 + * camera coincides with x-axis of gimbal. */
  893 + hybridFocalLength = (dji_f32_t) s_cameraOpticalZoomFocalLength * s_cameraDigitalZoomFactor;
  894 +
  895 + returnCode = osalHandler->MutexUnlock(s_zoomMutex);
  896 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  897 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  898 + return returnCode;
  899 + }
  900 +
  901 + rotationValue.pitch = (int32_t) (
  902 + atan2f((target.focusY - CENTER_POINT_IN_SCREEN_Y_VALUE) * IMAGE_SENSOR_Y_SIZE, hybridFocalLength) * 1800 /
  903 + DJI_PI);
  904 + rotationValue.yaw = (int32_t) (
  905 + atan2f((target.focusX - CENTER_POINT_IN_SCREEN_X_VALUE) * IMAGE_SENSOR_X_SIZE, hybridFocalLength) * 1800 /
  906 + DJI_PI);
  907 +
  908 + returnCode = osalHandler->MutexLock(s_tapZoomMutex);
  909 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  910 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  911 + return returnCode;
  912 + }
  913 +
  914 + s_tapZoomNewestGimbalRotationArgument.rotationMode = rotationMode;
  915 + s_tapZoomNewestGimbalRotationArgument.rotationProperty = rotationProperty;
  916 + s_tapZoomNewestGimbalRotationArgument.rotationValue = rotationValue;
  917 + s_tapZoomNewestTargetHybridFocalLength = (uint32_t) (hybridFocalLength * (float) s_tapZoomMultiplier);
  918 +
  919 + returnCode = osalHandler->MutexUnlock(s_tapZoomMutex);
  920 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  921 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  922 + return returnCode;
  923 + }
  924 +
  925 + s_isStartTapZoom = true;
  926 +
  927 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  928 +}
  929 +
  930 +static T_DjiReturnCode DjiTest_CameraHybridZoom(uint32_t focalLength)
  931 +{
  932 + if (focalLength >= ZOOM_OPTICAL_FOCAL_MIN_LENGTH && focalLength <= ZOOM_OPTICAL_FOCAL_MAX_LENGTH) {
  933 + s_cameraOpticalZoomFocalLength = focalLength;
  934 + s_cameraDigitalZoomFactor = ZOOM_DIGITAL_BASE_FACTOR;
  935 + } else if (focalLength < ZOOM_OPTICAL_FOCAL_MIN_LENGTH) {
  936 + s_cameraOpticalZoomFocalLength = ZOOM_OPTICAL_FOCAL_MIN_LENGTH;
  937 + s_cameraDigitalZoomFactor = ZOOM_DIGITAL_BASE_FACTOR;
  938 +
  939 + USER_LOG_ERROR("focal length %d is smaller than min optical focal length %d.", focalLength,
  940 + ZOOM_OPTICAL_FOCAL_MIN_LENGTH);
  941 + return DJI_ERROR_SYSTEM_MODULE_CODE_OUT_OF_RANGE;
  942 + } else {
  943 + s_cameraOpticalZoomFocalLength = ZOOM_OPTICAL_FOCAL_MAX_LENGTH;
  944 + s_cameraDigitalZoomFactor = (float) focalLength / ZOOM_OPTICAL_FOCAL_MAX_LENGTH;
  945 + }
  946 +
  947 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  948 +}
  949 +
  950 +static T_DjiReturnCode DjiTest_CameraRotationGimbal(T_TestCameraGimbalRotationArgument gimbalRotationArgument)
  951 +{
  952 + T_DjiReturnCode returnCode;
  953 + T_DjiAircraftInfoBaseInfo aircraftBaseInfo = {0};
  954 +
  955 + returnCode = DjiAircraftInfo_GetBaseInfo(&aircraftBaseInfo);
  956 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  957 + USER_LOG_ERROR("get aircraft information error: 0x%08llX.", returnCode);
  958 + return returnCode;
  959 + }
  960 +
  961 + if (aircraftBaseInfo.djiAdapterType == DJI_SDK_ADAPTER_TYPE_SKYPORT_V2 ||
  962 + aircraftBaseInfo.djiAdapterType == DJI_SDK_ADAPTER_TYPE_NONE) {
  963 + returnCode = DjiTest_GimbalRotate(gimbalRotationArgument.rotationMode, gimbalRotationArgument.rotationProperty,
  964 + gimbalRotationArgument.rotationValue);
  965 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  966 + USER_LOG_ERROR("rotate gimbal error: 0x%08llX.", returnCode);
  967 + return returnCode;
  968 + }
  969 + } else if (aircraftBaseInfo.djiAdapterType == DJI_SDK_ADAPTER_TYPE_XPORT) {
  970 + returnCode = DjiXPort_RotateSync(gimbalRotationArgument.rotationMode, gimbalRotationArgument.rotationProperty,
  971 + gimbalRotationArgument.rotationValue);
  972 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  973 + USER_LOG_ERROR("rotate XPort error: 0x%08llX.", returnCode);
  974 + return returnCode;
  975 + }
  976 + } else {
  977 + USER_LOG_ERROR("PSDK adapter type is invalid: %d.", aircraftBaseInfo.djiAdapterType);
  978 + return DJI_ERROR_SYSTEM_MODULE_CODE_NONSUPPORT;
  979 + }
  980 +
  981 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  982 +}
  983 +
  984 +#ifndef __CC_ARM
  985 +#pragma GCC diagnostic push
  986 +#pragma GCC diagnostic ignored "-Wmissing-noreturn"
  987 +#pragma GCC diagnostic ignored "-Wreturn-type"
  988 +#endif
  989 +
  990 +static void *UserCamera_Task(void *arg)
  991 +{
  992 + static uint32_t photoCnt = 0;
  993 + static uint32_t step = 0;
  994 + T_DjiReturnCode returnCode;
  995 + int32_t tempFocalLength = 0;
  996 + dji_f32_t tempDigitalFactor = 0.0f;
  997 + uint32_t currentTime = 0;
  998 + bool isStartIntervalPhotoAction = false;
  999 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  1000 +
  1001 + USER_UTIL_UNUSED(arg);
  1002 +
  1003 + while (1) {
  1004 + osalHandler->TaskSleepMs(1000 / PAYLOAD_CAMERA_EMU_TASK_FREQ);
  1005 + step++;
  1006 +
  1007 + returnCode = osalHandler->MutexLock(s_commonMutex);
  1008 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1009 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  1010 + continue;
  1011 + }
  1012 +
  1013 + s_cameraSDCardState.availableRecordingTimeInSeconds =
  1014 + s_cameraSDCardState.remainSpaceInMB / SDCARD_PER_SECONDS_RECORD_SPACE_IN_MB;
  1015 + s_cameraSDCardState.availableCaptureCount = s_cameraSDCardState.remainSpaceInMB / SDCARD_PER_PHOTO_SPACE_IN_MB;
  1016 +
  1017 +//l理解你的照片 短和逻辑存储
  1018 + //realize your photo shoot and storage logic here
  1019 + if (s_cameraState.shootingState != DJI_CAMERA_SHOOTING_PHOTO_IDLE &&
  1020 + photoCnt++ > TAKING_PHOTO_SPENT_TIME_MS_EMU / (1000 / PAYLOAD_CAMERA_EMU_TASK_FREQ)) {
  1021 + photoCnt = 0;
  1022 +
  1023 +//在拍摄结束后 把照片放入仓库
  1024 + //store the photo after shooting finished
  1025 + if (s_cameraShootPhotoMode == DJI_CAMERA_SHOOT_PHOTO_MODE_SINGLE) {
  1026 + s_cameraSDCardState.remainSpaceInMB =
  1027 + s_cameraSDCardState.remainSpaceInMB - SDCARD_PER_PHOTO_SPACE_IN_MB;
  1028 + s_cameraState.isStoring = false;
  1029 + s_cameraState.shootingState = DJI_CAMERA_SHOOTING_PHOTO_IDLE;
  1030 + } else if (s_cameraShootPhotoMode == DJI_CAMERA_SHOOT_PHOTO_MODE_BURST) {
  1031 + s_cameraSDCardState.remainSpaceInMB =
  1032 + s_cameraSDCardState.remainSpaceInMB - SDCARD_PER_PHOTO_SPACE_IN_MB * s_cameraBurstCount;
  1033 + s_cameraState.isStoring = false;
  1034 + s_cameraState.shootingState = DJI_CAMERA_SHOOTING_PHOTO_IDLE;
  1035 + } else if (s_cameraShootPhotoMode == DJI_CAMERA_SHOOT_PHOTO_MODE_INTERVAL) {
  1036 + if (isStartIntervalPhotoAction == true) {
  1037 + s_cameraState.isStoring = false;
  1038 + s_cameraState.shootingState = DJI_CAMERA_SHOOTING_PHOTO_IDLE;
  1039 + s_cameraSDCardState.remainSpaceInMB =
  1040 + s_cameraSDCardState.remainSpaceInMB - SDCARD_PER_PHOTO_SPACE_IN_MB;
  1041 + }
  1042 + }
  1043 +
  1044 +// 检查 sd卡 的 保留空间
  1045 + //check the remain space of sdcard
  1046 + if (s_cameraSDCardState.remainSpaceInMB > SDCARD_TOTAL_SPACE_IN_MB) {
  1047 + s_cameraSDCardState.remainSpaceInMB = 0;
  1048 + s_cameraSDCardState.isFull = true;
  1049 + }
  1050 +
  1051 +#if dji_ARCH_SYS_LINUX
  1052 + T_DjiCameraMediaFileInfo mediaFileInfo = {0};
  1053 +
  1054 +// 退入 媒体文件信息
  1055 + // push added media file information
  1056 + if (s_cameraShootPhotoMode == dji_CAMERA_SHOOT_PHOTO_MODE_SINGLE) {
  1057 + if (UtilFile_IsFileExist(PHOTO_FILE_PATH) == true) {
  1058 + psdkStat = PsdkTest_CameraMediaGetFileInfo(PHOTO_FILE_PATH, &mediaFileInfo);
  1059 + if (psdkStat != dji_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1060 + PsdkLogger_UserLogError("Get media file info error 0x%08llX", psdkStat);
  1061 + }
  1062 +
  1063 + psdkStat = PsdkPayloadCamera_PushAddedMediaFileInfo(PHOTO_FILE_PATH, mediaFileInfo);
  1064 + if (psdkStat != dji_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1065 + PsdkLogger_UserLogError("Push added media file info error 0x%08llX", psdkStat);
  1066 + }
  1067 + } else {
  1068 + PsdkLogger_UserLogWarn("Can't found the media file by path. "
  1069 + "Probably because media file has not existed. "
  1070 + "Please check media file if exists. ");
  1071 + }
  1072 + }
  1073 +#endif
  1074 + }
  1075 +
  1076 + returnCode = osalHandler->MutexUnlock(s_commonMutex);
  1077 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1078 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  1079 + continue;
  1080 + }
  1081 +
  1082 + // 10Hz
  1083 + if (USER_UTIL_IS_WORK_TURN(step, 10, PAYLOAD_CAMERA_EMU_TASK_FREQ)) {
  1084 + returnCode = osalHandler->MutexLock(s_zoomMutex);
  1085 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1086 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  1087 + continue;
  1088 + }
  1089 +
  1090 +#ifdef USER_CAMERA_EMU_HYBRID_ZOOM_ON
  1091 + //Add logic here for zoom camera
  1092 + if (s_isStartContinuousOpticalZoom == true) {
  1093 + tempDigitalFactor = s_cameraDigitalZoomFactor;
  1094 + tempFocalLength = (int32_t) s_cameraOpticalZoomFocalLength;
  1095 + if (s_isOpticalZoomReachLimit == false) {
  1096 + if (s_cameraZoomDirection == DJI_CAMERA_ZOOM_DIRECTION_IN) {
  1097 + tempFocalLength += ((int) s_cameraZoomSpeed - DJI_CAMERA_ZOOM_SPEED_SLOWEST + 1) *
  1098 + ZOOM_OPTICAL_FOCAL_LENGTH_CTRL_STEP;
  1099 + } else if (s_cameraZoomDirection == DJI_CAMERA_ZOOM_DIRECTION_OUT) {
  1100 + tempFocalLength -= ((int) s_cameraZoomSpeed - DJI_CAMERA_ZOOM_SPEED_SLOWEST + 1) *
  1101 + ZOOM_OPTICAL_FOCAL_LENGTH_CTRL_STEP;
  1102 + }
  1103 +
  1104 + if (tempFocalLength > ZOOM_OPTICAL_FOCAL_MAX_LENGTH) {
  1105 + s_isOpticalZoomReachLimit = true;
  1106 + tempFocalLength = ZOOM_OPTICAL_FOCAL_MAX_LENGTH;
  1107 + }
  1108 +
  1109 + if (tempFocalLength < ZOOM_OPTICAL_FOCAL_MIN_LENGTH) {
  1110 + tempFocalLength = ZOOM_OPTICAL_FOCAL_MIN_LENGTH;
  1111 + }
  1112 + } else {
  1113 + if (s_cameraZoomDirection == DJI_CAMERA_ZOOM_DIRECTION_IN) {
  1114 + tempDigitalFactor += (dji_f32_t) ZOOM_DIGITAL_STEP_FACTOR;
  1115 + } else if (s_cameraZoomDirection == DJI_CAMERA_ZOOM_DIRECTION_OUT) {
  1116 + tempDigitalFactor -= (dji_f32_t) ZOOM_DIGITAL_STEP_FACTOR;
  1117 + }
  1118 +
  1119 + if (tempDigitalFactor > (dji_f32_t) ZOOM_DIGITAL_MAX_FACTOR) {
  1120 + tempDigitalFactor = (dji_f32_t) ZOOM_DIGITAL_MAX_FACTOR;
  1121 + }
  1122 +
  1123 + if (tempDigitalFactor < (dji_f32_t) ZOOM_DIGITAL_BASE_FACTOR) {
  1124 + s_isOpticalZoomReachLimit = false;
  1125 + tempDigitalFactor = ZOOM_DIGITAL_BASE_FACTOR;
  1126 + }
  1127 + }
  1128 + s_cameraOpticalZoomFocalLength = (uint16_t) tempFocalLength;
  1129 + s_cameraDigitalZoomFactor = tempDigitalFactor;
  1130 + }
  1131 +#endif
  1132 +
  1133 +#if USER_CAMERA_EMU_TAP_ZOOM_ON
  1134 + returnCode = osalHandler->MutexLock(s_tapZoomMutex);
  1135 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1136 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  1137 + goto out;
  1138 + }
  1139 +
  1140 + if (s_isStartTapZoom) {
  1141 + s_isStartTapZoom = false;
  1142 + s_isTapZooming = true;
  1143 +
  1144 + returnCode = osalHandler->GetTimeMs(&s_tapZoomStartTime);
  1145 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1146 + USER_LOG_ERROR("get start time error: 0x%08llX.", returnCode);
  1147 + }
  1148 +
  1149 + returnCode = DjiTest_CameraRotationGimbal(s_tapZoomNewestGimbalRotationArgument);
  1150 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
  1151 + USER_LOG_ERROR("rotate gimbal error: 0x%08llX.", returnCode);
  1152 + else
  1153 + s_cameraTapZoomState.isGimbalMoving = true;
  1154 +
  1155 + returnCode = DjiTest_CameraHybridZoom(s_tapZoomNewestTargetHybridFocalLength);
  1156 + if (returnCode == DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1157 + s_cameraTapZoomState.zoomState = (dji_f32_t) s_tapZoomNewestTargetHybridFocalLength >
  1158 + ((dji_f32_t) s_cameraOpticalZoomFocalLength *
  1159 + s_cameraDigitalZoomFactor)
  1160 + ? DJI_CAMERA_TAP_ZOOM_STATE_ZOOM_IN
  1161 + : DJI_CAMERA_TAP_ZOOM_STATE_ZOOM_OUT;
  1162 + } else if (returnCode == DJI_ERROR_SYSTEM_MODULE_CODE_OUT_OF_RANGE) {
  1163 + USER_LOG_ERROR("hybrid zoom focal length beyond limit.");
  1164 + s_cameraTapZoomState.zoomState = DJI_CAMERA_TAP_ZOOM_STATE_ZOOM_LIMITED;
  1165 + } else {
  1166 + USER_LOG_ERROR("hybrid zoom error: 0x%08llX.", returnCode);
  1167 + }
  1168 + } else if (s_isTapZooming) {
  1169 + returnCode = osalHandler->GetTimeMs(&currentTime);
  1170 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1171 + USER_LOG_ERROR("get start time error: 0x%08llX.", returnCode);
  1172 + }
  1173 +
  1174 + if ((currentTime - s_tapZoomStartTime) >= TAP_ZOOM_DURATION) {
  1175 + s_cameraTapZoomState.zoomState = DJI_CAMERA_TAP_ZOOM_STATE_IDLE;
  1176 + s_cameraTapZoomState.isGimbalMoving = false;
  1177 + s_isTapZooming = false;
  1178 + }
  1179 + }
  1180 +
  1181 + returnCode = osalHandler->MutexUnlock(s_tapZoomMutex);
  1182 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1183 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  1184 + goto out;
  1185 + }
  1186 +#endif
  1187 +
  1188 +out:
  1189 + returnCode = osalHandler->MutexUnlock(s_zoomMutex);
  1190 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1191 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  1192 + continue;
  1193 + }
  1194 + }
  1195 +
  1196 + // 1Hz
  1197 + if (USER_UTIL_IS_WORK_TURN(step, 1, PAYLOAD_CAMERA_EMU_TASK_FREQ)) {
  1198 + returnCode = osalHandler->MutexLock(s_commonMutex);
  1199 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1200 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  1201 + continue;
  1202 + }
  1203 +
  1204 + if (s_cameraState.isRecording) {
  1205 + s_cameraState.currentVideoRecordingTimeInSeconds++;
  1206 + s_cameraSDCardState.remainSpaceInMB =
  1207 + s_cameraSDCardState.remainSpaceInMB - SDCARD_PER_SECONDS_RECORD_SPACE_IN_MB;
  1208 + if (s_cameraSDCardState.remainSpaceInMB > SDCARD_TOTAL_SPACE_IN_MB) {
  1209 + s_cameraSDCardState.remainSpaceInMB = 0;
  1210 + s_cameraSDCardState.isFull = true;
  1211 + }
  1212 + }
  1213 +
  1214 + if (s_cameraState.isShootingIntervalStart == false) {
  1215 + isStartIntervalPhotoAction = false;
  1216 + }
  1217 +
  1218 + if (s_cameraShootPhotoMode == DJI_CAMERA_SHOOT_PHOTO_MODE_INTERVAL
  1219 + && s_cameraState.isShootingIntervalStart == true && s_cameraPhotoTimeIntervalSettings.captureCount > 0
  1220 + && s_cameraPhotoTimeIntervalSettings.timeIntervalSeconds > 0) {
  1221 + s_cameraState.currentPhotoShootingIntervalTimeInSeconds--;
  1222 +
  1223 + if ((s_cameraState.currentPhotoShootingIntervalTimeInSeconds == 0 &&
  1224 + s_cameraState.currentPhotoShootingIntervalCount > 0) ||
  1225 + (s_cameraState.isShootingIntervalStart == true && isStartIntervalPhotoAction == false)) {
  1226 +
  1227 + isStartIntervalPhotoAction = true;
  1228 +
  1229 + s_cameraState.shootingState = DJI_CAMERA_SHOOTING_INTERVAL_PHOTO;
  1230 + s_cameraState.isStoring = true;
  1231 + s_cameraState.currentPhotoShootingIntervalTimeInSeconds
  1232 + = s_cameraPhotoTimeIntervalSettings.timeIntervalSeconds;
  1233 + if (s_cameraState.currentPhotoShootingIntervalCount < INTERVAL_PHOTOGRAPH_ALWAYS_COUNT) {
  1234 + USER_LOG_INFO("interval taking photograph count:%d interval_time:%ds",
  1235 + (s_cameraPhotoTimeIntervalSettings.captureCount -
  1236 + s_cameraState.currentPhotoShootingIntervalCount + 1),
  1237 + s_cameraPhotoTimeIntervalSettings.timeIntervalSeconds);
  1238 + JZsdk_Psdk_UI_io_ShootPhoto();
  1239 + s_cameraState.currentPhotoShootingIntervalCount--;
  1240 + if (s_cameraState.currentPhotoShootingIntervalCount == 0) {
  1241 + s_cameraState.shootingState = DJI_CAMERA_SHOOTING_PHOTO_IDLE;
  1242 + s_cameraState.isStoring = false;
  1243 + s_cameraState.isShootingIntervalStart = false;
  1244 + }
  1245 + } else {
  1246 + USER_LOG_INFO("interval taking photograph always, interval_time:%ds",
  1247 + s_cameraPhotoTimeIntervalSettings.timeIntervalSeconds);
  1248 + JZsdk_Psdk_UI_io_ShootPhoto();
  1249 +
  1250 + s_cameraState.currentPhotoShootingIntervalCount--;
  1251 + }
  1252 + }
  1253 + }
  1254 +
  1255 + returnCode = osalHandler->MutexUnlock(s_commonMutex);
  1256 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1257 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  1258 + continue;
  1259 + }
  1260 + }
  1261 + }
  1262 +}
  1263 +
  1264 +#ifndef __CC_ARM
  1265 +#pragma GCC diagnostic pop
  1266 +#endif
  1267 +
  1268 +/* Private functions definition-----------------------------------------------*/
  1269 +// 照相机 菜单 基础 开始 服务
  1270 +T_DjiReturnCode DjiTest_CameraEmuBaseStartService(void)
  1271 +{
  1272 + T_DjiReturnCode returnCode;
  1273 + char ipAddr[DJI_IP_ADDR_STR_SIZE_MAX] = {0};
  1274 + uint16_t port = 0;
  1275 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  1276 + T_DjiAircraftInfoBaseInfo aircraftInfoBaseInfo = {0};
  1277 +
  1278 + returnCode = osalHandler->MutexCreate(&s_commonMutex);
  1279 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1280 + USER_LOG_ERROR("create mutex used to lock tap zoom arguments error: 0x%08llX", returnCode);
  1281 + return returnCode;
  1282 + }
  1283 +
  1284 + returnCode = osalHandler->MutexCreate(&s_zoomMutex);
  1285 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1286 + USER_LOG_ERROR("create mutex used to lock tap zoom arguments error: 0x%08llX", returnCode);
  1287 + return returnCode;
  1288 + }
  1289 +
  1290 + returnCode = osalHandler->MutexCreate(&s_tapZoomMutex);
  1291 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1292 + USER_LOG_ERROR("create mutex used to lock tap zoom arguments error: 0x%08llX", returnCode);
  1293 + return returnCode;
  1294 + }
  1295 +
  1296 + returnCode = DjiPayloadCamera_Init();
  1297 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1298 + USER_LOG_ERROR("init payload camera error:0x%08llX", returnCode);
  1299 + return returnCode;
  1300 + }
  1301 +
  1302 +// 初始化 sd卡的环境
  1303 + /* Init the SDcard parameters */
  1304 + s_cameraSDCardState.isInserted = true;
  1305 + s_cameraSDCardState.isVerified = true;
  1306 + s_cameraSDCardState.totalSpaceInMB = SDCARD_TOTAL_SPACE_IN_MB;
  1307 + s_cameraSDCardState.remainSpaceInMB = SDCARD_TOTAL_SPACE_IN_MB;
  1308 + s_cameraSDCardState.availableCaptureCount = SDCARD_TOTAL_SPACE_IN_MB / SDCARD_PER_PHOTO_SPACE_IN_MB;
  1309 + s_cameraSDCardState.availableRecordingTimeInSeconds =
  1310 + SDCARD_TOTAL_SPACE_IN_MB / SDCARD_PER_SECONDS_RECORD_SPACE_IN_MB;
  1311 +
  1312 +// 注册相机 指令 的 权柄
  1313 + /* Register the camera common handler */
  1314 + s_commonHandler.GetSystemState = GetSystemState;
  1315 + s_commonHandler.SetMode = SetMode;
  1316 + s_commonHandler.GetMode = DjiTest_CameraGetMode;
  1317 + s_commonHandler.StartRecordVideo = StartRecordVideo;
  1318 + s_commonHandler.StopRecordVideo = StopRecordVideo;
  1319 + s_commonHandler.StartShootPhoto = StartShootPhoto;
  1320 + s_commonHandler.StopShootPhoto = StopShootPhoto;
  1321 + s_commonHandler.SetShootPhotoMode = SetShootPhotoMode;
  1322 + s_commonHandler.GetShootPhotoMode = GetShootPhotoMode;
  1323 + s_commonHandler.SetPhotoBurstCount = SetPhotoBurstCount;
  1324 + s_commonHandler.GetPhotoBurstCount = GetPhotoBurstCount;
  1325 + s_commonHandler.SetPhotoTimeIntervalSettings = SetPhotoTimeIntervalSettings;
  1326 + s_commonHandler.GetPhotoTimeIntervalSettings = GetPhotoTimeIntervalSettings;
  1327 + s_commonHandler.GetSDCardState = GetSDCardState;
  1328 + s_commonHandler.FormatSDCard = FormatSDCard;
  1329 +
  1330 + returnCode = DjiPayloadCamera_RegCommonHandler(&s_commonHandler);
  1331 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1332 + USER_LOG_ERROR("camera register common handler error:0x%08llX", returnCode);
  1333 + }
  1334 +
  1335 + /* Register the camera metering handler */
  1336 +#if USER_CAMERA_EMU_METERING_ON
  1337 + s_exposureMeteringHandler.SetMeteringMode = SetMeteringMode;
  1338 + s_exposureMeteringHandler.GetMeteringMode = GetMeteringMode;
  1339 + s_exposureMeteringHandler.SetSpotMeteringTarget = SetSpotMeteringTarget;
  1340 + s_exposureMeteringHandler.GetSpotMeteringTarget = GetSpotMeteringTarget;
  1341 +
  1342 + returnCode = DjiPayloadCamera_RegExposureMeteringHandler(&s_exposureMeteringHandler);
  1343 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1344 + USER_LOG_ERROR("camera register exposure metering handler error:0x%08llX", returnCode);
  1345 + return returnCode;
  1346 + }
  1347 +#endif
  1348 +
  1349 +// 注册 相机 焦点 句柄
  1350 + /* Register the camera focus handler */
  1351 +#if USER_CAMERA_EMU_FOCUS_ON
  1352 + s_focusHandler.SetFocusMode = SetFocusMode;
  1353 + s_focusHandler.GetFocusMode = GetFocusMode;
  1354 + s_focusHandler.SetFocusTarget = SetFocusTarget;
  1355 + s_focusHandler.GetFocusTarget = GetFocusTarget;
  1356 + s_focusHandler.SetFocusAssistantSettings = SetFocusAssistantSettings;
  1357 + s_focusHandler.GetFocusAssistantSettings = GetFocusAssistantSettings;
  1358 + s_focusHandler.SetFocusRingValue = SetFocusRingValue;
  1359 + s_focusHandler.GetFocusRingValue = GetFocusRingValue;
  1360 + s_focusHandler.GetFocusRingValueUpperBound = GetFocusRingValueUpperBound;
  1361 +
  1362 + returnCode = DjiPayloadCamera_RegFocusHandler(&s_focusHandler);
  1363 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1364 + USER_LOG_ERROR("camera register adjustable focal point handler error:0x%08llX", returnCode);
  1365 + return returnCode;
  1366 + }
  1367 +#endif
  1368 +
  1369 +// 注册 相机 数码变焦 的句柄
  1370 + /* Register the camera digital zoom handler */
  1371 +#if USER_CAMERA_EMU_HYBRID_ZOOM_ON
  1372 + s_digitalZoomHandler.SetDigitalZoomFactor = SetDigitalZoomFactor;
  1373 + s_digitalZoomHandler.GetDigitalZoomFactor = DjiTest_CameraGetDigitalZoomFactor;
  1374 +
  1375 + returnCode = DjiPayloadCamera_RegDigitalZoomHandler(&s_digitalZoomHandler);
  1376 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1377 + USER_LOG_ERROR("camera register digital zoom handler error:0x%08llX", returnCode);
  1378 + return returnCode;
  1379 + }
  1380 +
  1381 +// 注册 相机 光学 变焦
  1382 + /* Register the camera optical zoom handler */
  1383 + s_opticalZoomHandler.SetOpticalZoomFocalLength = SetOpticalZoomFocalLength;
  1384 + s_opticalZoomHandler.GetOpticalZoomFocalLength = GetOpticalZoomFocalLength;
  1385 + s_opticalZoomHandler.GetOpticalZoomFactor = DjiTest_CameraGetOpticalZoomFactor;
  1386 + s_opticalZoomHandler.GetOpticalZoomSpec = GetOpticalZoomSpec;
  1387 + s_opticalZoomHandler.StartContinuousOpticalZoom = StartContinuousOpticalZoom;
  1388 + s_opticalZoomHandler.StopContinuousOpticalZoom = StopContinuousOpticalZoom;
  1389 +
  1390 + returnCode = DjiPayloadCamera_RegOpticalZoomHandler(&s_opticalZoomHandler);
  1391 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1392 + USER_LOG_ERROR("camera register optical zoom handler error:0x%08llX", returnCode);
  1393 + return returnCode;
  1394 + }
  1395 +#endif
  1396 +
  1397 +// 注册 利用变焦
  1398 + /* Register the camera tap zoom handler */
  1399 +#if USER_CAMERA_EMU_TAP_ZOOM_ON
  1400 + s_tapZoomHandler.GetTapZoomState = GetTapZoomState;
  1401 + s_tapZoomHandler.SetTapZoomEnabled = SetTapZoomEnabled;
  1402 + s_tapZoomHandler.GetTapZoomEnabled = GetTapZoomEnabled;
  1403 + s_tapZoomHandler.SetTapZoomMultiplier = SetTapZoomMultiplier;
  1404 + s_tapZoomHandler.GetTapZoomMultiplier = GetTapZoomMultiplier;
  1405 + s_tapZoomHandler.TapZoomAtTarget = TapZoomAtTarget;
  1406 +
  1407 + returnCode = DjiPayloadCamera_RegTapZoomHandler(&s_tapZoomHandler);
  1408 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1409 + USER_LOG_ERROR("camera register tap zoom handler error:0x%08llX", returnCode);
  1410 + return returnCode;
  1411 + }
  1412 +#endif
  1413 +
  1414 +// 注册 相机的 菜单 任务
  1415 + /* Create the camera emu taskHandle */
  1416 + if (osalHandler->TaskCreate("user_camera_task", UserCamera_Task,
  1417 + PAYLOAD_CAMERA_EMU_TASK_STACK_SIZE, NULL, &s_userCameraThread)
  1418 + != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1419 + USER_LOG_ERROR("user camera taskHandle create error");
  1420 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  1421 + }
  1422 +
  1423 +// 得到 相机 的 基础 信息
  1424 + if (DjiAircraftInfo_GetBaseInfo(&aircraftInfoBaseInfo) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1425 + USER_LOG_ERROR("get aircraft information error.");
  1426 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  1427 + }
  1428 +
  1429 +// 设置 视频 流 的 类型
  1430 + returnCode = DjiPayloadCamera_SetVideoStreamType(DJI_CAMERA_VIDEO_STREAM_TYPE_H264_DJI_FORMAT);
  1431 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1432 + USER_LOG_ERROR("DJI camera set video stream error.");
  1433 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  1434 + }
  1435 +
  1436 + //设置传输视频的类型
  1437 + s_cameraVideoStreamType = DJI_CAMERA_VIDEO_STREAM_TYPE_H264_DJI_FORMAT;
  1438 +
  1439 +// 获取视频流远程地址 飞机云台的地址
  1440 + returnCode = DjiPayloadCamera_GetVideoStreamRemoteAddress(ipAddr, &port);
  1441 + if (returnCode == DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1442 + USER_LOG_DEBUG("Get video stream remote address: %s, port: %d", ipAddr, port);
  1443 + } else {
  1444 + USER_LOG_ERROR("get video stream remote address error.");
  1445 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  1446 + }
  1447 +
  1448 + s_isCamInited = true;
  1449 +
  1450 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1451 +}
  1452 +
  1453 +T_DjiReturnCode DjiTest_CameraGetDigitalZoomFactor(dji_f32_t *factor)
  1454 +{
  1455 + T_DjiReturnCode returnCode;
  1456 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  1457 +
  1458 + returnCode = osalHandler->MutexLock(s_zoomMutex);
  1459 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1460 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  1461 + return returnCode;
  1462 + }
  1463 +
  1464 + *factor = s_cameraDigitalZoomFactor;
  1465 +
  1466 + returnCode = osalHandler->MutexUnlock(s_zoomMutex);
  1467 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1468 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  1469 + return returnCode;
  1470 + }
  1471 +
  1472 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1473 +}
  1474 +
  1475 +T_DjiReturnCode DjiTest_CameraGetOpticalZoomFactor(dji_f32_t *factor)
  1476 +{
  1477 + T_DjiReturnCode returnCode;
  1478 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  1479 +
  1480 + returnCode = osalHandler->MutexLock(s_zoomMutex);
  1481 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1482 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  1483 + return returnCode;
  1484 + }
  1485 +
  1486 + //Formula:factor = currentFocalLength / minFocalLength
  1487 + *factor = (dji_f32_t) s_cameraOpticalZoomFocalLength / ZOOM_OPTICAL_FOCAL_MIN_LENGTH;
  1488 +
  1489 + returnCode = osalHandler->MutexUnlock(s_zoomMutex);
  1490 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1491 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  1492 + return returnCode;
  1493 + }
  1494 +
  1495 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1496 +}
  1497 +
  1498 +T_DjiReturnCode DjiTest_CameraGetMode(E_DjiCameraMode *mode)
  1499 +{
  1500 + T_DjiReturnCode returnCode;
  1501 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  1502 +
  1503 + returnCode = osalHandler->MutexLock(s_commonMutex);
  1504 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1505 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  1506 + return returnCode;
  1507 + }
  1508 +
  1509 + *mode = s_cameraState.cameraMode;
  1510 +
  1511 + returnCode = osalHandler->MutexUnlock(s_commonMutex);
  1512 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1513 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  1514 + return returnCode;
  1515 + }
  1516 +
  1517 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1518 +}
  1519 +
  1520 +T_DjiReturnCode DjiTest_CameraGetVideoStreamType(E_DjiCameraVideoStreamType *type)
  1521 +{
  1522 + if (s_isCamInited == false) {
  1523 + return DJI_ERROR_SYSTEM_MODULE_CODE_NONSUPPORT_IN_CURRENT_STATE;
  1524 + }
  1525 +
  1526 + *type = s_cameraVideoStreamType;
  1527 +
  1528 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1529 +}
  1530 +
  1531 +bool DjiTest_CameraIsInited(void)
  1532 +{
  1533 + return s_isCamInited;
  1534 +}
  1535 +
  1536 +/****************** (C) COPYRIGHT DJI Innovations *****END OF FILE****/
  1537 +
  1538 +
  1539 +
  1540 +//手动添加 by ookk303
  1541 +// 0空闲中 1录像中 2单拍中 3连拍中 4转码中
  1542 +void DJI_CamEmu_base_CameraTransLock(int flag)
  1543 +{
  1544 + switch (flag)
  1545 + {
  1546 + case 0:
  1547 + {
  1548 + s_cameraState.isRecording = 0;
  1549 + s_cameraState.isStoring = 0;
  1550 + break;
  1551 + }
  1552 +
  1553 + case 1:
  1554 + {
  1555 + s_cameraState.isRecording = 1;
  1556 + s_cameraState.isStoring = 0;
  1557 + break;
  1558 + }
  1559 +
  1560 + case 2:
  1561 + {
  1562 + s_cameraState.isRecording = 0;
  1563 + s_cameraState.isStoring = 1;
  1564 + break;
  1565 + }
  1566 +
  1567 + case 3:
  1568 + {
  1569 + s_cameraState.isRecording = 0;
  1570 + s_cameraState.isStoring = 1;
  1571 + break;
  1572 + }
  1573 +
  1574 + case 4:
  1575 + {
  1576 + s_cameraState.isRecording = 0;
  1577 + s_cameraState.isStoring = 1;
  1578 + break;
  1579 + }
  1580 +
  1581 + default:
  1582 + break;
  1583 + }
  1584 +}
  1 +/**
  2 + ********************************************************************
  3 + * @file test_payload_cam_emu_common.h
  4 + * @brief This is the header file for "test_payload_cam_emu.c", defining the structure and
  5 + * (exported) function prototypes.
  6 + *
  7 + * @copyright (c) 2021 DJI. All rights reserved.
  8 + *
  9 + * All information contained herein is, and remains, the property of DJI.
  10 + * The intellectual and technical concepts contained herein are proprietary
  11 + * to DJI and may be covered by U.S. and foreign patents, patents in process,
  12 + * and protected by trade secret or copyright law. Dissemination of this
  13 + * information, including but not limited to data and other proprietary
  14 + * material(s) incorporated within the information, in any form, is strictly
  15 + * prohibited without the express written consent of DJI.
  16 + *
  17 + * If you receive this source code without DJI’s authorization, you may not
  18 + * further disseminate the information, and you must immediately remove the
  19 + * source code and notify DJI of its removal. DJI reserves the right to pursue
  20 + * legal actions against you for any loss(es) or damage(s) caused by your
  21 + * failure to do so.
  22 + *
  23 + *********************************************************************
  24 + */
  25 +
  26 +/* Define to prevent recursive inclusion -------------------------------------*/
  27 +#ifndef TEST_PAYLOAD_CAM_EMU_BASE_H
  28 +#define TEST_PAYLOAD_CAM_EMU_BASE_H
  29 +
  30 +/* Includes ------------------------------------------------------------------*/
  31 +#include "dji_typedef.h"
  32 +#include "dji_payload_camera.h"
  33 +
  34 +#ifdef __cplusplus
  35 +extern "C" {
  36 +#endif
  37 +
  38 +/* Exported constants --------------------------------------------------------*/
  39 +
  40 +/* Exported types ------------------------------------------------------------*/
  41 +
  42 +/* Exported functions --------------------------------------------------------*/
  43 +T_DjiReturnCode DjiTest_CameraEmuBaseStartService(void);
  44 +T_DjiReturnCode DjiTest_CameraGetDigitalZoomFactor(dji_f32_t *factor);
  45 +T_DjiReturnCode DjiTest_CameraGetOpticalZoomFactor(dji_f32_t *factor);
  46 +T_DjiReturnCode DjiTest_CameraGetMode(E_DjiCameraMode *mode);
  47 +T_DjiReturnCode DjiTest_CameraGetVideoStreamType(E_DjiCameraVideoStreamType *type);
  48 +bool DjiTest_CameraIsInited(void);
  49 +void DJI_CamEmu_base_CameraTransLock(int flag);
  50 +
  51 +#ifdef __cplusplus
  52 +}
  53 +#endif
  54 +
  55 +#endif // TEST_PAYLOAD_CAM_EMU_BASE_H
  56 +/************************ (C) COPYRIGHT DJI Innovations *******END OF FILE******/
  1 +/**
  2 + ********************************************************************
  3 + * @file test_payload_cam_emu_media.c
  4 + * @brief
  5 + *
  6 + * @copyright (c) 2021 DJI. All rights reserved.
  7 + *
  8 + * All information contained herein is, and remains, the property of DJI.
  9 + * The intellectual and technical concepts contained herein are proprietary
  10 + * to DJI and may be covered by U.S. and foreign patents, patents in process,
  11 + * and protected by trade secret or copyright law. Dissemination of this
  12 + * information, including but not limited to data and other proprietary
  13 + * material(s) incorporated within the information, in any form, is strictly
  14 + * prohibited without the express written consent of DJI.
  15 + *
  16 + * If you receive this source code without DJI’s authorization, you may not
  17 + * further disseminate the information, and you must immediately remove the
  18 + * source code and notify DJI of its removal. DJI reserves the right to pursue
  19 + * legal actions against you for any loss(es) or damage(s) caused by your
  20 + * failure to do so.
  21 + *
  22 + *********************************************************************
  23 + */
  24 +
  25 +/* Includes ------------------------------------------------------------------*/
  26 +#include <fcntl.h>
  27 +#include <stdlib.h>
  28 +#include "dji_logger.h"
  29 +#include "utils/util_misc.h"
  30 +#include "utils/util_time.h"
  31 +#include "utils/util_file.h"
  32 +#include "utils/util_buffer.h"
  33 +#include "test_payload_cam_emu_media.h"
  34 +#include "test_payload_cam_emu_base.h"
  35 +#include "camera_emu/dji_media_file_manage/dji_media_file_core.h"
  36 +#include "dji_high_speed_data_channel.h"
  37 +#include "dji_aircraft_info.h"
  38 +
  39 +#include "Dji_Control/DJI_VideoDeal.h"
  40 +#include <pthread.h>
  41 +
  42 +/* Private constants ---------------------------------------------------------*/
  43 +#define FFMPEG_CMD_BUF_SIZE (256 + 256)
  44 +#define SEND_VIDEO_TASK_FREQ 120
  45 +#define VIDEO_FRAME_MAX_COUNT 18000 // max video duration 10 minutes
  46 +#define VIDEO_FRAME_AUD_LEN 6
  47 +#define DATA_SEND_FROM_VIDEO_STREAM_MAX_LEN 60000
  48 +
  49 +//飞机传输通道值占比
  50 +#define TRANS_RATIO_DATA (10)
  51 +#define TRANS_RATIO_VIDEO (85)
  52 +#define TRANS_RATIO_DOWNLOAD (5)
  53 +
  54 +/* Private types -------------------------------------------------------------*/
  55 +typedef enum {
  56 + TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_STOP = 0,
  57 + TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_PAUSE = 1,
  58 + TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_START = 2,
  59 +} E_TestPayloadCameraPlaybackCommand;
  60 +
  61 +typedef struct {
  62 + uint8_t isInPlayProcess;
  63 + uint16_t videoIndex;
  64 + char filePath[DJI_FILE_PATH_SIZE_MAX];
  65 + uint32_t videoLengthMs;
  66 + uint64_t startPlayTimestampsUs;
  67 + uint64_t playPosMs;
  68 +} T_DjiPlaybackInfo;
  69 +
  70 +typedef struct {
  71 + E_TestPayloadCameraPlaybackCommand command;
  72 + uint32_t timeMs;
  73 + char path[DJI_FILE_PATH_SIZE_MAX];
  74 +} T_TestPayloadCameraPlaybackCommand;
  75 +
  76 +typedef struct {
  77 + float durationS;
  78 + uint32_t positionInFile;
  79 + uint32_t size;
  80 +} T_TestPayloadCameraVideoFrameInfo;
  81 +
  82 +/* Private functions declaration ---------------------------------------------*/
  83 +static T_DjiReturnCode DjiPlayback_StopPlay(T_DjiPlaybackInfo *playbackInfo);
  84 +static T_DjiReturnCode DjiPlayback_PausePlay(T_DjiPlaybackInfo *playbackInfo);
  85 +static T_DjiReturnCode DjiPlayback_SetPlayFile(T_DjiPlaybackInfo *playbackInfo, const char *filePath,
  86 + uint16_t index);
  87 +static T_DjiReturnCode DjiPlayback_SeekPlay(T_DjiPlaybackInfo *playbackInfo, uint32_t seekPos);
  88 +static T_DjiReturnCode DjiPlayback_StartPlay(T_DjiPlaybackInfo *playbackInfo);
  89 +static T_DjiReturnCode DjiPlayback_GetPlaybackStatus(T_DjiPlaybackInfo *playbackInfo,
  90 + T_DjiCameraPlaybackStatus *playbackStatus);
  91 +static T_DjiReturnCode DjiPlayback_GetVideoLengthMs(const char *filePath, uint32_t *videoLengthMs);
  92 +static T_DjiReturnCode DjiPlayback_StartPlayProcess(const char *filePath, uint32_t playPosMs);
  93 +static T_DjiReturnCode DjiPlayback_StopPlayProcess(void);
  94 +static T_DjiReturnCode
  95 +DjiPlayback_VideoFileTranscode(const char *inPath, const char *outFormat, char *outPath, uint16_t outPathBufferSize);
  96 +static T_DjiReturnCode
  97 +DjiPlayback_GetFrameInfoOfVideoFile(const char *path, T_TestPayloadCameraVideoFrameInfo *frameInfo,
  98 + uint32_t frameInfoBufferCount, uint32_t *frameCount);
  99 +static T_DjiReturnCode DjiPlayback_GetFrameRateOfVideoFile(const char *path, float *frameRate);
  100 +static T_DjiReturnCode
  101 +DjiPlayback_GetFrameNumberByTime(T_TestPayloadCameraVideoFrameInfo *frameInfo, uint32_t frameCount,
  102 + uint32_t *frameNumber, uint32_t timeMs);
  103 +static T_DjiReturnCode GetMediaFileDir(char *dirPath);
  104 +static T_DjiReturnCode GetMediaFileOriginData(const char *filePath, uint32_t offset, uint32_t length,
  105 + uint8_t *data);
  106 +
  107 +static T_DjiReturnCode CreateMediaFileThumbNail(const char *filePath);
  108 +static T_DjiReturnCode GetMediaFileThumbNailInfo(const char *filePath, T_DjiCameraMediaFileInfo *fileInfo);
  109 +static T_DjiReturnCode GetMediaFileThumbNailData(const char *filePath, uint32_t offset, uint32_t length,
  110 + uint8_t *data);
  111 +static T_DjiReturnCode DestroyMediaFileThumbNail(const char *filePath);
  112 +
  113 +static T_DjiReturnCode CreateMediaFileScreenNail(const char *filePath);
  114 +static T_DjiReturnCode GetMediaFileScreenNailInfo(const char *filePath, T_DjiCameraMediaFileInfo *fileInfo);
  115 +static T_DjiReturnCode GetMediaFileScreenNailData(const char *filePath, uint32_t offset, uint32_t length,
  116 + uint8_t *data);
  117 +static T_DjiReturnCode DestroyMediaFileScreenNail(const char *filePath);
  118 +
  119 +static T_DjiReturnCode DeleteMediaFile(char *filePath);
  120 +static T_DjiReturnCode SetMediaPlaybackFile(const char *filePath);
  121 +static T_DjiReturnCode StartMediaPlayback(void);
  122 +static T_DjiReturnCode StopMediaPlayback(void);
  123 +static T_DjiReturnCode PauseMediaPlayback(void);
  124 +static T_DjiReturnCode SeekMediaPlayback(uint32_t playbackPosition);
  125 +static T_DjiReturnCode GetMediaPlaybackStatus(T_DjiCameraPlaybackStatus *status);
  126 +
  127 +static T_DjiReturnCode StartDownloadNotification(void);
  128 +static T_DjiReturnCode StopDownloadNotification(void);
  129 +
  130 +_Noreturn static void *UserCameraMedia_SendVideoTask(void *arg);
  131 +_Noreturn static void *TestCameraMedia_SendVideoTask(void *arg);
  132 +
  133 +/* Private variables -------------------------------------------------------------*/
  134 +static T_DjiCameraMediaDownloadPlaybackHandler s_psdkCameraMedia = {0};
  135 +static T_DjiPlaybackInfo s_playbackInfo = {0};
  136 +static T_DjiTaskHandle s_userSendVideoThread;
  137 +static T_UtilBuffer s_mediaPlayCommandBufferHandler = {0};
  138 +static T_DjiMutexHandle s_mediaPlayCommandBufferMutex = {0};
  139 +static T_DjiSemaHandle s_mediaPlayWorkSem = NULL;
  140 +static uint8_t s_mediaPlayCommandBuffer[sizeof(T_TestPayloadCameraPlaybackCommand) * 32] = {0};
  141 +static const char *s_frameKeyChar = "[PACKET]";
  142 +static const char *s_frameDurationTimeKeyChar = "duration_time";
  143 +static const char *s_framePositionKeyChar = "pos";
  144 +static const char *s_frameSizeKeyChar = "size";
  145 +static T_DjiMediaFileHandle s_mediaFileThumbNailHandle;
  146 +static T_DjiMediaFileHandle s_mediaFileScreenNailHandle;
  147 +static const uint8_t s_frameAudInfo[VIDEO_FRAME_AUD_LEN] = {0x00, 0x00, 0x00, 0x01, 0x09, 0x10};
  148 +static char s_mediaFileDirPath[DJI_FILE_PATH_SIZE_MAX] = {0};
  149 +static bool s_isMediaFileDirPathConfigured = false;
  150 +
  151 +/* Exported functions definition ---------------------------------------------*/
  152 +// 接口函数定义
  153 +// 照相机 菜单 媒体 开始 服务
  154 +
  155 +T_DjiReturnCode DjiTest_CameraEmuMediaStartService(int mode)
  156 +{
  157 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  158 + T_DjiReturnCode returnCode;
  159 + const T_DjiDataChannelBandwidthProportionOfHighspeedChannel bandwidthProportionOfHighspeedChannel =
  160 + {TRANS_RATIO_DATA, TRANS_RATIO_VIDEO, TRANS_RATIO_DOWNLOAD};
  161 +
  162 + T_DjiAircraftInfoBaseInfo aircraftInfoBaseInfo = {0};
  163 +
  164 + if (DjiAircraftInfo_GetBaseInfo(&aircraftInfoBaseInfo) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  165 + USER_LOG_ERROR("get aircraft information error.");
  166 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  167 + }
  168 +
  169 + s_psdkCameraMedia.GetMediaFileDir = GetMediaFileDir;
  170 + s_psdkCameraMedia.GetMediaFileOriginInfo = DjiTest_CameraMediaGetFileInfo;
  171 + s_psdkCameraMedia.GetMediaFileOriginData = GetMediaFileOriginData;
  172 +
  173 + s_psdkCameraMedia.CreateMediaFileThumbNail = CreateMediaFileThumbNail;
  174 + s_psdkCameraMedia.GetMediaFileThumbNailInfo = GetMediaFileThumbNailInfo;
  175 + s_psdkCameraMedia.GetMediaFileThumbNailData = GetMediaFileThumbNailData;
  176 + s_psdkCameraMedia.DestroyMediaFileThumbNail = DestroyMediaFileThumbNail;
  177 +
  178 + s_psdkCameraMedia.CreateMediaFileScreenNail = CreateMediaFileScreenNail;
  179 + s_psdkCameraMedia.GetMediaFileScreenNailInfo = GetMediaFileScreenNailInfo;
  180 + s_psdkCameraMedia.GetMediaFileScreenNailData = GetMediaFileScreenNailData;
  181 + s_psdkCameraMedia.DestroyMediaFileScreenNail = DestroyMediaFileScreenNail;
  182 +
  183 + s_psdkCameraMedia.DeleteMediaFile = DeleteMediaFile;
  184 +
  185 + s_psdkCameraMedia.SetMediaPlaybackFile = SetMediaPlaybackFile;
  186 +
  187 + s_psdkCameraMedia.StartMediaPlayback = StartMediaPlayback;
  188 + s_psdkCameraMedia.StopMediaPlayback = StopMediaPlayback;
  189 + s_psdkCameraMedia.PauseMediaPlayback = PauseMediaPlayback;
  190 + s_psdkCameraMedia.SeekMediaPlayback = SeekMediaPlayback;
  191 + s_psdkCameraMedia.GetMediaPlaybackStatus = GetMediaPlaybackStatus;
  192 +
  193 + s_psdkCameraMedia.StartDownloadNotification = StartDownloadNotification;
  194 + s_psdkCameraMedia.StopDownloadNotification = StopDownloadNotification;
  195 +
  196 + if (DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS != osalHandler->SemaphoreCreate(0, &s_mediaPlayWorkSem)) {
  197 + USER_LOG_ERROR("SemaphoreCreate(\"%s\") error.", "s_mediaPlayWorkSem");
  198 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  199 + }
  200 +
  201 + if (osalHandler->MutexCreate(&s_mediaPlayCommandBufferMutex) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  202 + USER_LOG_ERROR("mutex create error");
  203 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  204 + }
  205 +
  206 + UtilBuffer_Init(&s_mediaPlayCommandBufferHandler, s_mediaPlayCommandBuffer, sizeof(s_mediaPlayCommandBuffer));
  207 +
  208 + if (aircraftInfoBaseInfo.aircraftType == DJI_AIRCRAFT_TYPE_M300_RTK ||
  209 + aircraftInfoBaseInfo.aircraftType == DJI_AIRCRAFT_TYPE_M350_RTK) {
  210 + returnCode = DjiPayloadCamera_RegMediaDownloadPlaybackHandler(&s_psdkCameraMedia);
  211 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  212 + USER_LOG_ERROR("psdk camera media function init error.");
  213 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  214 + }
  215 + }
  216 +
  217 + returnCode = DjiHighSpeedDataChannel_SetBandwidthProportion(bandwidthProportionOfHighspeedChannel);
  218 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  219 + USER_LOG_ERROR("Set data channel bandwidth width proportion error.");
  220 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  221 + }
  222 +
  223 + if (mode == 0)
  224 + {
  225 + // 大疆平台 获得 套接字 权柄
  226 + if (DjiPlatform_GetHalNetworkHandler() != NULL || DjiPlatform_GetHalUsbBulkHandler() != NULL) {
  227 + // 创建相机媒体任务,使用者相机媒体任务,
  228 + returnCode = osalHandler->TaskCreate("user_camera_media_task", UserCameraMedia_SendVideoTask, 2048,
  229 + NULL, &s_userSendVideoThread);
  230 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  231 + USER_LOG_ERROR("user send video task create error.");
  232 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  233 + }
  234 + }
  235 + }
  236 + else if (mode == 1)
  237 + {
  238 + if (DjiPlatform_GetHalNetworkHandler() != NULL || DjiPlatform_GetHalUsbBulkHandler() != NULL) {
  239 + // 创建测试图传线程
  240 + returnCode = osalHandler->TaskCreate("user_camera_media_task", TestCameraMedia_SendVideoTask, 2048,
  241 + NULL, &s_userSendVideoThread);
  242 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  243 + USER_LOG_ERROR("user send video task create error.");
  244 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  245 + }
  246 + }
  247 + }
  248 +
  249 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  250 +}
  251 +
  252 +T_DjiReturnCode DjiTest_CameraEmuSetMediaFilePath(const char *path)
  253 +{
  254 + memset(s_mediaFileDirPath, 0, sizeof(s_mediaFileDirPath));
  255 + memcpy(s_mediaFileDirPath, path, USER_UTIL_MIN(strlen(path), sizeof(s_mediaFileDirPath) - 1));
  256 + s_isMediaFileDirPathConfigured = true;
  257 +
  258 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  259 +}
  260 +
  261 +T_DjiReturnCode DjiTest_CameraMediaGetFileInfo(const char *filePath, T_DjiCameraMediaFileInfo *fileInfo)
  262 +{
  263 + T_DjiReturnCode returnCode;
  264 + T_DjiMediaFileHandle mediaFileHandle;
  265 +
  266 + returnCode = DjiMediaFile_CreateHandle(filePath, &mediaFileHandle);
  267 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  268 + USER_LOG_ERROR("Media file create handle error stat:0x%08llX", returnCode);
  269 + return returnCode;
  270 + }
  271 +
  272 + returnCode = DjiMediaFile_GetMediaFileType(mediaFileHandle, &fileInfo->type);
  273 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  274 + USER_LOG_ERROR("Media file get type error stat:0x%08llX", returnCode);
  275 + goto out;
  276 + }
  277 +
  278 + returnCode = DjiMediaFile_GetMediaFileAttr(mediaFileHandle, &fileInfo->mediaFileAttr);
  279 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  280 + USER_LOG_ERROR("Media file get attr error stat:0x%08llX", returnCode);
  281 + goto out;
  282 + }
  283 +
  284 + returnCode = DjiMediaFile_GetFileSizeOrg(mediaFileHandle, &fileInfo->fileSize);
  285 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  286 + USER_LOG_ERROR("Media file get size error stat:0x%08llX", returnCode);
  287 + goto out;
  288 + }
  289 +
  290 +out:
  291 + returnCode = DjiMediaFile_DestroyHandle(mediaFileHandle);
  292 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  293 + USER_LOG_ERROR("Media file destroy handle error stat:0x%08llX", returnCode);
  294 + return returnCode;
  295 + }
  296 +
  297 + return returnCode;
  298 +}
  299 +
  300 +/* Private functions definition-----------------------------------------------*/
  301 +static T_DjiReturnCode DjiPlayback_StopPlay(T_DjiPlaybackInfo *playbackInfo)
  302 +{
  303 + T_DjiReturnCode returnCode;
  304 +
  305 + returnCode = DjiPlayback_StopPlayProcess();
  306 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  307 + USER_LOG_ERROR("stop play error ");
  308 + }
  309 +
  310 + playbackInfo->isInPlayProcess = 0;
  311 + playbackInfo->playPosMs = 0;
  312 +
  313 + return returnCode;
  314 +}
  315 +
  316 +static T_DjiReturnCode DjiPlayback_PausePlay(T_DjiPlaybackInfo *playbackInfo)
  317 +{
  318 + T_DjiReturnCode returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  319 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  320 +
  321 + T_TestPayloadCameraPlaybackCommand playbackCommand = {0};
  322 + if (playbackInfo->isInPlayProcess) {
  323 + playbackCommand.command = TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_PAUSE;
  324 +
  325 + if (osalHandler->MutexLock(s_mediaPlayCommandBufferMutex) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  326 + USER_LOG_ERROR("mutex lock error");
  327 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  328 + }
  329 +
  330 + if (UtilBuffer_GetUnusedSize(&s_mediaPlayCommandBufferHandler) >= sizeof(T_TestPayloadCameraPlaybackCommand)) {
  331 + UtilBuffer_Put(&s_mediaPlayCommandBufferHandler, (const uint8_t *) &playbackCommand,
  332 + sizeof(T_TestPayloadCameraPlaybackCommand));
  333 + } else {
  334 + USER_LOG_ERROR("Media playback command buffer is full.");
  335 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_OUT_OF_RANGE;
  336 + }
  337 +
  338 + if (osalHandler->MutexUnlock(s_mediaPlayCommandBufferMutex) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  339 + USER_LOG_ERROR("mutex unlock error");
  340 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  341 + }
  342 + osalHandler->SemaphorePost(s_mediaPlayWorkSem);
  343 + }
  344 +
  345 + playbackInfo->isInPlayProcess = 0;
  346 +
  347 + return returnCode;
  348 +}
  349 +
  350 +static T_DjiReturnCode DjiPlayback_SetPlayFile(T_DjiPlaybackInfo *playbackInfo, const char *filePath, uint16_t index)
  351 +{
  352 + T_DjiReturnCode returnCode;
  353 +
  354 + if (strlen(filePath) > DJI_FILE_PATH_SIZE_MAX) {
  355 + USER_LOG_ERROR("Dji playback file path out of length range error\n");
  356 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  357 + }
  358 +
  359 + strcpy(playbackInfo->filePath, filePath);
  360 + playbackInfo->videoIndex = index;
  361 +
  362 + returnCode = DjiPlayback_GetVideoLengthMs(filePath, &playbackInfo->videoLengthMs);
  363 +
  364 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  365 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  366 + }
  367 +
  368 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  369 +}
  370 +
  371 +static T_DjiReturnCode DjiPlayback_SeekPlay(T_DjiPlaybackInfo *playbackInfo, uint32_t seekPos)
  372 +{
  373 + T_DjiRunTimeStamps ti;
  374 + T_DjiReturnCode returnCode;
  375 +
  376 + returnCode = DjiPlayback_PausePlay(playbackInfo);
  377 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  378 + USER_LOG_ERROR("pause play error \n");
  379 + return returnCode;
  380 + }
  381 +
  382 + playbackInfo->playPosMs = seekPos;
  383 + returnCode = DjiPlayback_StartPlayProcess(playbackInfo->filePath, playbackInfo->playPosMs);
  384 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  385 + USER_LOG_ERROR("start playback process error \n");
  386 + return returnCode;
  387 + }
  388 +
  389 + playbackInfo->isInPlayProcess = 1;
  390 + ti = DjiUtilTime_GetRunTimeStamps();
  391 + playbackInfo->startPlayTimestampsUs = ti.realUsec - playbackInfo->playPosMs * 1000;
  392 +
  393 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  394 +}
  395 +
  396 +static T_DjiReturnCode DjiPlayback_StartPlay(T_DjiPlaybackInfo *playbackInfo)
  397 +{
  398 + T_DjiRunTimeStamps ti;
  399 + T_DjiReturnCode returnCode;
  400 +
  401 + if (playbackInfo->isInPlayProcess == 1) {
  402 + //already in playing, return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS
  403 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  404 + }
  405 +
  406 + returnCode = DjiPlayback_StartPlayProcess(playbackInfo->filePath, playbackInfo->playPosMs);
  407 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  408 + USER_LOG_ERROR("start play process error \n");
  409 + return returnCode;
  410 + }
  411 +
  412 + playbackInfo->isInPlayProcess = 1;
  413 +
  414 + ti = DjiUtilTime_GetRunTimeStamps();
  415 + playbackInfo->startPlayTimestampsUs = ti.realUsec - playbackInfo->playPosMs * 1000;
  416 +
  417 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  418 +}
  419 +
  420 +static T_DjiReturnCode DjiPlayback_GetPlaybackStatus(T_DjiPlaybackInfo *playbackInfo,
  421 + T_DjiCameraPlaybackStatus *playbackStatus)
  422 +{
  423 + T_DjiRunTimeStamps timeStamps;
  424 +
  425 + memset(playbackStatus, 0, sizeof(T_DjiCameraPlaybackStatus));
  426 +
  427 + //update playback pos info
  428 + if (playbackInfo->isInPlayProcess) {
  429 + timeStamps = DjiUtilTime_GetRunTimeStamps();
  430 + playbackInfo->playPosMs = (timeStamps.realUsec - playbackInfo->startPlayTimestampsUs) / 1000;
  431 +
  432 + if (playbackInfo->playPosMs >= playbackInfo->videoLengthMs) {
  433 + if (DjiPlayback_PausePlay(playbackInfo) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  434 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  435 + }
  436 + }
  437 + }
  438 +
  439 + //set playback status
  440 + if (playbackInfo->isInPlayProcess == 0 && playbackInfo->playPosMs != 0) {
  441 + playbackStatus->playbackMode = DJI_CAMERA_PLAYBACK_MODE_PAUSE;
  442 + } else if (playbackInfo->isInPlayProcess) {
  443 + playbackStatus->playbackMode = DJI_CAMERA_PLAYBACK_MODE_PLAY;
  444 + } else {
  445 + playbackStatus->playbackMode = DJI_CAMERA_PLAYBACK_MODE_STOP;
  446 + }
  447 +
  448 + playbackStatus->playPosMs = playbackInfo->playPosMs;
  449 + playbackStatus->videoLengthMs = playbackInfo->videoLengthMs;
  450 +
  451 + if (playbackInfo->videoLengthMs != 0) {
  452 + playbackStatus->videoPlayProcess =
  453 + (playbackInfo->videoLengthMs - playbackInfo->playPosMs) / playbackInfo->videoLengthMs;
  454 + } else {
  455 + playbackStatus->videoPlayProcess = 0;
  456 + }
  457 +
  458 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  459 +}
  460 +
  461 +// 获取视频长度
  462 +static T_DjiReturnCode DjiPlayback_GetVideoLengthMs(const char *filePath, uint32_t *videoLengthMs)
  463 +{
  464 + FILE *fp;
  465 + T_DjiReturnCode returnCode;
  466 + char ffmpegCmdStr[FFMPEG_CMD_BUF_SIZE];
  467 + float hour, minute, second;
  468 + char tempTailStr[128];
  469 + int ret;
  470 +
  471 + snprintf(ffmpegCmdStr, FFMPEG_CMD_BUF_SIZE, "ffmpeg -i \"%s\" 2>&1 | grep \"Duration\"", filePath);
  472 + fp = popen(ffmpegCmdStr, "r");
  473 +
  474 + if (fp == NULL) {
  475 + return DJI_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  476 + }
  477 +
  478 + ret = fscanf(fp, " Duration: %f:%f:%f,%127s", &hour, &minute, &second, tempTailStr);
  479 + if (ret <= 0) {
  480 + USER_LOG_ERROR("MP4 File Get Duration Error\n");
  481 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  482 + goto out;
  483 + }
  484 +
  485 + *videoLengthMs = (uint32_t) ((hour * 3600 + minute * 60 + second) * 1000);
  486 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  487 +
  488 +out:
  489 + pclose(fp);
  490 +
  491 + return returnCode;
  492 +}
  493 +
  494 +
  495 +// 开始播放进程
  496 +static T_DjiReturnCode DjiPlayback_StartPlayProcess(const char *filePath, uint32_t playPosMs)
  497 +{
  498 + T_DjiReturnCode returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  499 + T_TestPayloadCameraPlaybackCommand mediaPlayCommand = {0};
  500 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  501 +
  502 + mediaPlayCommand.command = TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_START;
  503 + mediaPlayCommand.timeMs = playPosMs;
  504 +
  505 + if (strlen(filePath) >= sizeof(mediaPlayCommand.path)) {
  506 + USER_LOG_ERROR("File path is too long.");
  507 + return DJI_ERROR_SYSTEM_MODULE_CODE_OUT_OF_RANGE;
  508 + }
  509 + memcpy(mediaPlayCommand.path, filePath, strlen(filePath));
  510 +
  511 + if (osalHandler->MutexLock(s_mediaPlayCommandBufferMutex) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  512 + USER_LOG_ERROR("mutex lock error");
  513 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  514 + }
  515 +
  516 + if (UtilBuffer_GetUnusedSize(&s_mediaPlayCommandBufferHandler) >= sizeof(T_TestPayloadCameraPlaybackCommand)) {
  517 + UtilBuffer_Put(&s_mediaPlayCommandBufferHandler, (const uint8_t *) &mediaPlayCommand,
  518 + sizeof(T_TestPayloadCameraPlaybackCommand));
  519 + } else {
  520 + USER_LOG_ERROR("Media playback command buffer is full.");
  521 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_OUT_OF_RANGE;
  522 + }
  523 +
  524 + if (osalHandler->MutexUnlock(s_mediaPlayCommandBufferMutex) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  525 + USER_LOG_ERROR("mutex unlock error");
  526 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  527 + }
  528 + osalHandler->SemaphorePost(s_mediaPlayWorkSem);
  529 + return returnCode;
  530 +}
  531 +
  532 +static T_DjiReturnCode DjiPlayback_StopPlayProcess(void)
  533 +{
  534 + T_DjiReturnCode returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  535 + T_TestPayloadCameraPlaybackCommand playbackCommand = {0};
  536 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  537 +
  538 + playbackCommand.command = TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_STOP;
  539 +
  540 + if (osalHandler->MutexLock(s_mediaPlayCommandBufferMutex) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  541 + USER_LOG_ERROR("mutex lock error");
  542 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  543 + }
  544 +
  545 + if (UtilBuffer_GetUnusedSize(&s_mediaPlayCommandBufferHandler) >= sizeof(T_TestPayloadCameraPlaybackCommand)) {
  546 + UtilBuffer_Put(&s_mediaPlayCommandBufferHandler, (const uint8_t *) &playbackCommand,
  547 + sizeof(T_TestPayloadCameraPlaybackCommand));
  548 + } else {
  549 + USER_LOG_ERROR("Media playback command buffer is full.");
  550 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_OUT_OF_RANGE;
  551 + }
  552 +
  553 + if (osalHandler->MutexUnlock(s_mediaPlayCommandBufferMutex) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  554 + USER_LOG_ERROR("mutex unlock error");
  555 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  556 + }
  557 + osalHandler->SemaphorePost(s_mediaPlayWorkSem);
  558 + return returnCode;
  559 +}
  560 +
  561 +static T_DjiReturnCode DjiPlayback_VideoFileTranscode(const char *inPath, const char *outFormat, char *outPath,
  562 + uint16_t outPathBufferSize)
  563 +{
  564 + T_DjiReturnCode returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  565 + T_DjiReturnCode djiStatus = DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  566 + FILE *fpCommand = NULL;
  567 + char ffmpegCmdStr[FFMPEG_CMD_BUF_SIZE];
  568 + char *directory = NULL;
  569 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  570 +
  571 + directory = osalHandler->Malloc(DJI_FILE_PATH_SIZE_MAX);
  572 + if (directory == NULL) {
  573 + USER_LOG_ERROR("malloc memory for directory fail.");
  574 + return DJI_ERROR_SYSTEM_MODULE_CODE_MEMORY_ALLOC_FAILED;
  575 + }
  576 +
  577 + // USER_LOG_INFO("inPath%s",inPath);
  578 +
  579 + djiStatus = DjiUserUtil_GetCurrentFileDirPath(inPath, DJI_FILE_PATH_SIZE_MAX, directory);
  580 + if (djiStatus != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  581 + USER_LOG_ERROR("get directory of file error: 0x%08llX.", djiStatus);
  582 + returnCode = djiStatus;
  583 + goto out;
  584 + }
  585 +
  586 + // USER_LOG_INFO("inPath%s",inPath);
  587 +
  588 + snprintf(outPath, outPathBufferSize, "%sout.%s", directory, outFormat);
  589 + // 结果为 /root/sdcard/media_file/out.h264
  590 + USER_LOG_INFO("%sout.%s ", directory, outFormat);
  591 + snprintf(ffmpegCmdStr, FFMPEG_CMD_BUF_SIZE,
  592 + "echo \"y\" | ffmpeg -i \"%s\" -codec copy -f \"%s\" \"%s\" 1>/dev/null 2>&1", inPath,
  593 + outFormat, outPath);
  594 + // 结果为 echo "y" | ffmpeg -i "/root/sdcard/media_file/PSDK_0005.h264" -codec copy -f "h264" "/root/sdcard/media_file/out.h264" 1>/dev/null 2>&1
  595 + USER_LOG_INFO("ffmpegCmdStr:%s",ffmpegCmdStr);
  596 + fpCommand = popen(ffmpegCmdStr, "r");
  597 + if (fpCommand == NULL) {
  598 + USER_LOG_ERROR("execute transcode command fail.");
  599 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  600 + goto out;
  601 + }
  602 +
  603 + pclose(fpCommand);
  604 +
  605 +out:
  606 + osalHandler->Free(directory);
  607 +
  608 + return returnCode;
  609 +}
  610 +
  611 +
  612 +// 获得视频的帧信息
  613 +static T_DjiReturnCode
  614 +DjiPlayback_GetFrameInfoOfVideoFile(const char *path, T_TestPayloadCameraVideoFrameInfo *frameInfo,
  615 + uint32_t frameInfoBufferCount, uint32_t *frameCount)
  616 +{
  617 + long ret;
  618 + T_DjiReturnCode returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  619 + FILE *fpCommand = NULL;
  620 + char ffmpegCmdStr[FFMPEG_CMD_BUF_SIZE];
  621 + char *frameInfoString = NULL;
  622 + char *frameLocation = NULL;
  623 + char frameParameterFormat[50] = {0};
  624 + char *frameDurationTimeLocation = NULL;
  625 + float frameDurationTimeS = 0;
  626 + uint32_t frameNumber = 0;
  627 + char *framePositionLocation = NULL;
  628 + uint32_t framePosition = 0;
  629 + char *frameSizeLocation = NULL;
  630 + uint32_t frameSize = 0;
  631 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  632 +
  633 + frameInfoString = osalHandler->Malloc(VIDEO_FRAME_MAX_COUNT * 1024);
  634 + if (frameInfoString == NULL) {
  635 + USER_LOG_ERROR("malloc memory for frame info fail.");
  636 + return DJI_ERROR_SYSTEM_MODULE_CODE_MEMORY_ALLOC_FAILED;
  637 + }
  638 + memset(frameInfoString, 0, VIDEO_FRAME_MAX_COUNT * 1024);
  639 +
  640 + snprintf(ffmpegCmdStr, FFMPEG_CMD_BUF_SIZE, "ffprobe -show_packets \"%s\" 2>/dev/null", path);
  641 + fpCommand = popen(ffmpegCmdStr, "r");
  642 + if (fpCommand == NULL) {
  643 + USER_LOG_ERROR("execute show frames commands fail.");
  644 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  645 + goto out2;
  646 + }
  647 +
  648 + ret = (long) fread(frameInfoString, 1, VIDEO_FRAME_MAX_COUNT * 1024, fpCommand);
  649 + if (ret < 0) {
  650 + USER_LOG_ERROR("read show frames commands result error.");
  651 + goto out1;
  652 + }
  653 + frameInfoString[ret] = '\0';
  654 +
  655 + frameLocation = frameInfoString;
  656 + *frameCount = 0;
  657 + while (1) {
  658 + // find frame
  659 + frameLocation = strstr(frameLocation, s_frameKeyChar);
  660 + if (frameLocation == NULL) {
  661 + USER_LOG_DEBUG("reach file tail.");
  662 + break;
  663 + }
  664 +
  665 + // find frame duration
  666 + frameDurationTimeLocation = strstr(frameLocation, s_frameDurationTimeKeyChar);
  667 + if (frameDurationTimeLocation == NULL) {
  668 + USER_LOG_ERROR("can not find pkt_duration_time.");
  669 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  670 + goto out1;
  671 + }
  672 +
  673 + ret = snprintf(frameParameterFormat, sizeof(frameParameterFormat), "%s=%%f", s_frameDurationTimeKeyChar);
  674 + if (ret < 0) {
  675 + USER_LOG_ERROR("snprintf frameParameterFormat fail.");
  676 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  677 + goto out1;
  678 + }
  679 +
  680 + ret = sscanf(frameDurationTimeLocation, frameParameterFormat, &frameDurationTimeS);
  681 + if (ret <= 0) {
  682 + USER_LOG_ERROR("can not find pkt_duration_time.");
  683 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  684 + goto out1;
  685 + }
  686 + frameInfo[frameNumber].durationS = frameDurationTimeS;
  687 +
  688 + // find frame position
  689 + framePositionLocation = strstr(frameLocation, s_framePositionKeyChar);
  690 + if (framePositionLocation == NULL) {
  691 + USER_LOG_ERROR("can not found pkt_pos.");
  692 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  693 + goto out1;
  694 + }
  695 +
  696 + ret = snprintf(frameParameterFormat, sizeof(frameParameterFormat), "%s=%%d", s_framePositionKeyChar);
  697 + if (ret < 0) {
  698 + USER_LOG_ERROR("snprintf frameParameterFormat fail.");
  699 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  700 + goto out1;
  701 + }
  702 +
  703 + ret = sscanf(framePositionLocation, frameParameterFormat, &framePosition);
  704 + if (ret <= 0) {
  705 + USER_LOG_ERROR("can not found pkt_pos.");
  706 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  707 + goto out1;
  708 + }
  709 + frameInfo[frameNumber].positionInFile = framePosition;
  710 +
  711 + // find frame size
  712 + //frameSizeLocation 由 frameLocation s_frameSizeKeyChar 拼接而成
  713 +
  714 + frameSizeLocation = strstr(frameLocation, s_frameSizeKeyChar);
  715 + if (frameSizeLocation == NULL) {
  716 + USER_LOG_ERROR("can not found pkt_size.");
  717 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  718 + goto out1;
  719 + }
  720 +
  721 + ret = snprintf(frameParameterFormat, sizeof(frameParameterFormat), "%s=%%d", s_frameSizeKeyChar);
  722 + if (ret < 0) {
  723 + USER_LOG_ERROR("snprintf frameParameterFormat fail.");
  724 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  725 + goto out1;
  726 + }
  727 +
  728 +
  729 + // 从frameSizeLocation 读取数据流 到 frameSize
  730 + ret = sscanf(frameSizeLocation, frameParameterFormat, &frameSize);
  731 + if (ret <= 0) {
  732 + USER_LOG_ERROR("can not find pkt_size.");
  733 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  734 + goto out1;
  735 + }
  736 + frameInfo[frameNumber].size = frameSize;
  737 +
  738 + frameLocation += strlen(s_frameKeyChar);
  739 + frameNumber++;
  740 + (*frameCount)++;
  741 +
  742 + if (frameNumber >= frameInfoBufferCount) {
  743 + USER_LOG_ERROR("frame buffer is full.");
  744 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_OUT_OF_RANGE;
  745 + goto out1;
  746 + }
  747 + }
  748 +
  749 +out1:
  750 + pclose(fpCommand);
  751 +
  752 +out2:
  753 + osalHandler->Free(frameInfoString);
  754 +
  755 + return returnCode;
  756 +}
  757 +
  758 +
  759 +//获取视频的帧速率
  760 +static T_DjiReturnCode DjiPlayback_GetFrameRateOfVideoFile(const char *path, float *frameRate)
  761 +{
  762 + int ret;
  763 + T_DjiReturnCode returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  764 + FILE *fpCommand = NULL;
  765 + char ffmpegCmdStr[FFMPEG_CMD_BUF_SIZE] = {0};
  766 + int frameRateMolecule = 0;
  767 + int frameRateDenominator = 0;
  768 +
  769 +
  770 + //改动 手动获取
  771 + //path = "/root/sdcard/media_file/PSDK_0005.h264";
  772 +
  773 + //查看文件流信息指令 ffprobe -show_frames filename
  774 + //ffprobe -show_streams "/root/sdcard/media_file/PSDK_0005.h264" 2>/dev/null | grep r_frame_rate
  775 +
  776 + snprintf(ffmpegCmdStr, FFMPEG_CMD_BUF_SIZE, "ffprobe -show_streams \"%s\" 2>/dev/null | grep r_frame_rate", path);
  777 + fpCommand = popen(ffmpegCmdStr, "r");
  778 + if (fpCommand == NULL) {
  779 + USER_LOG_ERROR("execute show frame rate command fail.");
  780 + return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  781 + }
  782 +
  783 + USER_LOG_INFO("ffmpegCmdStr:%s", ffmpegCmdStr);
  784 +
  785 + //此处报错
  786 + // 从fpcommand中读取数据 %d %d 放入到frameRateMolecule frameRateDenominator
  787 + // 失败返还-1f
  788 +
  789 + ret = fscanf(fpCommand, "r_frame_rate=%d/%d", &frameRateMolecule, &frameRateDenominator);
  790 + if (ret <= 0) {
  791 + USER_LOG_ERROR("can not find frame rate.");
  792 + returnCode = DJI_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  793 + goto out;
  794 + }
  795 + *frameRate = (float) frameRateMolecule / (float) frameRateDenominator;
  796 +
  797 +out:
  798 + pclose(fpCommand);
  799 +
  800 + return returnCode;
  801 +}
  802 +
  803 +//获取视频帧数
  804 +static T_DjiReturnCode DjiPlayback_GetFrameNumberByTime(T_TestPayloadCameraVideoFrameInfo *frameInfo,
  805 + uint32_t frameCount, uint32_t *frameNumber, uint32_t timeMs)
  806 +{
  807 + uint32_t i = 0;
  808 + double camulativeTimeS = 0;
  809 + double timeS = (double) timeMs / 1000.0;
  810 +
  811 + for (i = 0; i < frameCount; ++i) {
  812 + camulativeTimeS += frameInfo[i].durationS;
  813 +
  814 + if (camulativeTimeS >= timeS) {
  815 + *frameNumber = i;
  816 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  817 + }
  818 + }
  819 +
  820 + return DJI_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  821 +}
  822 +
  823 +static T_DjiReturnCode GetMediaFileDir(char *dirPath)
  824 +{
  825 + T_DjiReturnCode returnCode;
  826 + char curFileDirPath[DJI_FILE_PATH_SIZE_MAX];
  827 + char tempPath[DJI_FILE_PATH_SIZE_MAX];
  828 +
  829 + USER_LOG_INFO("自动获取相册地址");
  830 + // returnCode = DjiUserUtil_GetCurrentFileDirPath("/root/sdcard/DCIM", DJI_FILE_PATH_SIZE_MAX, curFileDirPath);
  831 + // if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  832 + // USER_LOG_ERROR("Get file current path error, stat = 0x%08llX", returnCode);
  833 + // return returnCode;
  834 + // }
  835 +
  836 + snprintf(curFileDirPath,DJI_FILE_PATH_SIZE_MAX,"/root/sdcard/DCIM");
  837 + snprintf(dirPath, DJI_FILE_PATH_SIZE_MAX, "%s", curFileDirPath);
  838 +
  839 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  840 +}
  841 +
  842 +static T_DjiReturnCode GetMediaFileOriginData(const char *filePath, uint32_t offset, uint32_t length, uint8_t *data)
  843 +{
  844 + T_DjiReturnCode returnCode;
  845 + uint32_t realLen = 0;
  846 + T_DjiMediaFileHandle mediaFileHandle;
  847 +
  848 + returnCode = DjiMediaFile_CreateHandle(filePath, &mediaFileHandle);
  849 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  850 + USER_LOG_ERROR("Media file create handle error stat:0x%08llX", returnCode);
  851 + return returnCode;
  852 + }
  853 +
  854 + returnCode = DjiMediaFile_GetDataOrg(mediaFileHandle, offset, length, data, &realLen);
  855 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  856 + USER_LOG_ERROR("Media file get data error stat:0x%08llX", returnCode);
  857 + return returnCode;
  858 + }
  859 +
  860 + returnCode = DjiMediaFile_DestroyHandle(mediaFileHandle);
  861 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  862 + USER_LOG_ERROR("Media file destroy handle error stat:0x%08llX", returnCode);
  863 + return returnCode;
  864 + }
  865 +
  866 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  867 +}
  868 +
  869 +static T_DjiReturnCode CreateMediaFileThumbNail(const char *filePath)
  870 +{
  871 + T_DjiReturnCode returnCode;
  872 +
  873 + returnCode = DjiMediaFile_CreateHandle(filePath, &s_mediaFileThumbNailHandle);
  874 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  875 + USER_LOG_ERROR("Media file create handle error stat:0x%08llX", returnCode);
  876 + return returnCode;
  877 + }
  878 +
  879 + returnCode = DjiMediaFile_CreateThm(s_mediaFileThumbNailHandle);
  880 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  881 + USER_LOG_ERROR("Media file create thumb nail error stat:0x%08llX", returnCode);
  882 + return returnCode;
  883 + }
  884 +
  885 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  886 +}
  887 +
  888 +static T_DjiReturnCode GetMediaFileThumbNailInfo(const char *filePath, T_DjiCameraMediaFileInfo *fileInfo)
  889 +{
  890 + T_DjiReturnCode returnCode;
  891 +
  892 + USER_UTIL_UNUSED(filePath);
  893 +
  894 + if (s_mediaFileThumbNailHandle == NULL) {
  895 + USER_LOG_ERROR("Media file thumb nail handle null error");
  896 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  897 + }
  898 +
  899 + returnCode = DjiMediaFile_GetMediaFileType(s_mediaFileThumbNailHandle, &fileInfo->type);
  900 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  901 + USER_LOG_ERROR("Media file get type error stat:0x%08llX", returnCode);
  902 + return returnCode;
  903 + }
  904 +
  905 + returnCode = DjiMediaFile_GetMediaFileAttr(s_mediaFileThumbNailHandle, &fileInfo->mediaFileAttr);
  906 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  907 + USER_LOG_ERROR("Media file get attr error stat:0x%08llX", returnCode);
  908 + return returnCode;
  909 + }
  910 +
  911 + returnCode = DjiMediaFile_GetFileSizeThm(s_mediaFileThumbNailHandle, &fileInfo->fileSize);
  912 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  913 + USER_LOG_ERROR("Media file get size error stat:0x%08llX", returnCode);
  914 + return returnCode;
  915 + }
  916 +
  917 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  918 +}
  919 +
  920 +static T_DjiReturnCode GetMediaFileThumbNailData(const char *filePath, uint32_t offset, uint32_t length, uint8_t *data)
  921 +{
  922 + T_DjiReturnCode returnCode;
  923 + uint16_t realLen = 0;
  924 +
  925 + USER_UTIL_UNUSED(filePath);
  926 +
  927 + if (s_mediaFileThumbNailHandle == NULL) {
  928 + USER_LOG_ERROR("Media file thumb nail handle null error");
  929 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  930 + }
  931 +
  932 + returnCode = DjiMediaFile_GetDataThm(s_mediaFileThumbNailHandle, offset, length, data, &realLen);
  933 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  934 + USER_LOG_ERROR("Media file get data error stat:0x%08llX", returnCode);
  935 + return returnCode;
  936 + }
  937 +
  938 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  939 +}
  940 +
  941 +static T_DjiReturnCode DestroyMediaFileThumbNail(const char *filePath)
  942 +{
  943 + T_DjiReturnCode returnCode;
  944 +
  945 + USER_UTIL_UNUSED(filePath);
  946 +
  947 + if (s_mediaFileThumbNailHandle == NULL) {
  948 + USER_LOG_ERROR("Media file thumb nail handle null error");
  949 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  950 + }
  951 +
  952 + returnCode = DjiMediaFile_DestoryThm(s_mediaFileThumbNailHandle);
  953 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  954 + USER_LOG_ERROR("Media file destroy thumb nail error stat:0x%08llX", returnCode);
  955 + return returnCode;
  956 + }
  957 +
  958 + returnCode = DjiMediaFile_DestroyHandle(s_mediaFileThumbNailHandle);
  959 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  960 + USER_LOG_ERROR("Media file destroy handle error stat:0x%08llX", returnCode);
  961 + return returnCode;
  962 + }
  963 +
  964 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  965 +}
  966 +
  967 +static T_DjiReturnCode CreateMediaFileScreenNail(const char *filePath)
  968 +{
  969 + T_DjiReturnCode returnCode;
  970 +
  971 + returnCode = DjiMediaFile_CreateHandle(filePath, &s_mediaFileScreenNailHandle);
  972 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  973 + USER_LOG_ERROR("Media file create handle error stat:0x%08llX", returnCode);
  974 + return returnCode;
  975 + }
  976 +
  977 + returnCode = DjiMediaFile_CreateScr(s_mediaFileScreenNailHandle);
  978 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  979 + USER_LOG_ERROR("Media file create screen nail error stat:0x%08llX", returnCode);
  980 + return returnCode;
  981 + }
  982 +
  983 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  984 +}
  985 +
  986 +static T_DjiReturnCode GetMediaFileScreenNailInfo(const char *filePath, T_DjiCameraMediaFileInfo *fileInfo)
  987 +{
  988 + T_DjiReturnCode returnCode;
  989 +
  990 + USER_UTIL_UNUSED(filePath);
  991 +
  992 + if (s_mediaFileScreenNailHandle == NULL) {
  993 + USER_LOG_ERROR("Media file screen nail handle null error");
  994 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  995 + }
  996 +
  997 + returnCode = DjiMediaFile_GetMediaFileType(s_mediaFileScreenNailHandle, &fileInfo->type);
  998 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  999 + USER_LOG_ERROR("Media file get type error stat:0x%08llX", returnCode);
  1000 + return returnCode;
  1001 + }
  1002 +
  1003 + returnCode = DjiMediaFile_GetMediaFileAttr(s_mediaFileScreenNailHandle, &fileInfo->mediaFileAttr);
  1004 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1005 + USER_LOG_ERROR("Media file get attr error stat:0x%08llX", returnCode);
  1006 + return returnCode;
  1007 + }
  1008 +
  1009 + returnCode = DjiMediaFile_GetFileSizeScr(s_mediaFileScreenNailHandle, &fileInfo->fileSize);
  1010 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1011 + USER_LOG_ERROR("Media file get size error stat:0x%08llX", returnCode);
  1012 + return returnCode;
  1013 + }
  1014 +
  1015 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1016 +}
  1017 +
  1018 +static T_DjiReturnCode GetMediaFileScreenNailData(const char *filePath, uint32_t offset, uint32_t length,
  1019 + uint8_t *data)
  1020 +{
  1021 + T_DjiReturnCode returnCode;
  1022 + uint16_t realLen = 0;
  1023 +
  1024 + USER_UTIL_UNUSED(filePath);
  1025 +
  1026 + if (s_mediaFileScreenNailHandle == NULL) {
  1027 + USER_LOG_ERROR("Media file screen nail handle null error");
  1028 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  1029 + }
  1030 +
  1031 + returnCode = DjiMediaFile_GetDataScr(s_mediaFileScreenNailHandle, offset, length, data, &realLen);
  1032 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1033 + USER_LOG_ERROR("Media file get size error stat:0x%08llX", returnCode);
  1034 + return returnCode;
  1035 + }
  1036 +
  1037 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1038 +}
  1039 +
  1040 +static T_DjiReturnCode DestroyMediaFileScreenNail(const char *filePath)
  1041 +{
  1042 + T_DjiReturnCode returnCode;
  1043 +
  1044 + USER_UTIL_UNUSED(filePath);
  1045 +
  1046 + if (s_mediaFileScreenNailHandle == NULL) {
  1047 + USER_LOG_ERROR("Media file screen nail handle null error");
  1048 + return DJI_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  1049 + }
  1050 +
  1051 + returnCode = DjiMediaFile_DestroyScr(s_mediaFileScreenNailHandle);
  1052 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1053 + USER_LOG_ERROR("Media file destroy screen nail error stat:0x%08llX", returnCode);
  1054 + return returnCode;
  1055 + }
  1056 +
  1057 + returnCode = DjiMediaFile_DestroyHandle(s_mediaFileScreenNailHandle);
  1058 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1059 + USER_LOG_ERROR("Media file destroy handle error stat:0x%08llX", returnCode);
  1060 + return returnCode;
  1061 + }
  1062 +
  1063 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1064 +}
  1065 +
  1066 +static T_DjiReturnCode DeleteMediaFile(char *filePath)
  1067 +{
  1068 + T_DjiReturnCode returnCode;
  1069 +
  1070 + USER_LOG_INFO("delete media file:%s", filePath);
  1071 + returnCode = DjiFile_Delete(filePath);
  1072 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1073 + USER_LOG_ERROR("Media file delete error stat:0x%08llX", returnCode);
  1074 + return returnCode;
  1075 + }
  1076 +
  1077 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1078 +}
  1079 +
  1080 +static T_DjiReturnCode SetMediaPlaybackFile(const char *filePath)
  1081 +{
  1082 + USER_LOG_INFO("set media playback file:%s", filePath);
  1083 + T_DjiReturnCode returnCode;
  1084 +
  1085 + returnCode = DjiPlayback_StopPlay(&s_playbackInfo);
  1086 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1087 + return returnCode;
  1088 + }
  1089 +
  1090 + returnCode = DjiPlayback_SetPlayFile(&s_playbackInfo, filePath, 0);
  1091 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1092 + return returnCode;
  1093 + }
  1094 +
  1095 + returnCode = DjiPlayback_StartPlay(&s_playbackInfo);
  1096 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1097 + return returnCode;
  1098 + }
  1099 +
  1100 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1101 +}
  1102 +
  1103 +static T_DjiReturnCode StartMediaPlayback(void)
  1104 +{
  1105 + T_DjiReturnCode returnCode;
  1106 +
  1107 + USER_LOG_INFO("start media playback");
  1108 + returnCode = DjiPlayback_StartPlay(&s_playbackInfo);
  1109 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1110 + USER_LOG_ERROR("start media playback status error, stat:0x%08llX", returnCode);
  1111 + return returnCode;
  1112 + }
  1113 +
  1114 + return returnCode;
  1115 +}
  1116 +
  1117 +static T_DjiReturnCode StopMediaPlayback(void)
  1118 +{
  1119 + T_DjiReturnCode returnCode;
  1120 +
  1121 + USER_LOG_INFO("stop media playback");
  1122 + returnCode = DjiPlayback_StopPlay(&s_playbackInfo);
  1123 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1124 + USER_LOG_ERROR("stop media playback error, stat:0x%08llX", returnCode);
  1125 + return returnCode;
  1126 + }
  1127 +
  1128 + return returnCode;
  1129 +}
  1130 +
  1131 +static T_DjiReturnCode PauseMediaPlayback(void)
  1132 +{
  1133 + T_DjiReturnCode returnCode;
  1134 +
  1135 + USER_LOG_INFO("pause media playback");
  1136 + returnCode = DjiPlayback_PausePlay(&s_playbackInfo);
  1137 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1138 + USER_LOG_ERROR("pause media playback error, stat:0x%08llX", returnCode);
  1139 + return returnCode;
  1140 + }
  1141 +
  1142 + return returnCode;
  1143 +}
  1144 +
  1145 +static T_DjiReturnCode SeekMediaPlayback(uint32_t playbackPosition)
  1146 +{
  1147 + T_DjiReturnCode returnCode;
  1148 +
  1149 + USER_LOG_INFO("seek media playback:%d", playbackPosition);
  1150 + returnCode = DjiPlayback_SeekPlay(&s_playbackInfo, playbackPosition);
  1151 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1152 + USER_LOG_ERROR("seek media playback error, stat:0x%08llX", returnCode);
  1153 + return returnCode;
  1154 + }
  1155 +
  1156 + return returnCode;
  1157 +}
  1158 +
  1159 +static T_DjiReturnCode GetMediaPlaybackStatus(T_DjiCameraPlaybackStatus *status)
  1160 +{
  1161 + T_DjiReturnCode returnCode;
  1162 +
  1163 + returnCode = DjiPlayback_GetPlaybackStatus(&s_playbackInfo, status);
  1164 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1165 + USER_LOG_ERROR("get playback status error, stat:0x%08llX", returnCode);
  1166 + return returnCode;
  1167 + }
  1168 +
  1169 + status->videoPlayProcess = (uint8_t) (((float) s_playbackInfo.playPosMs / (float) s_playbackInfo.videoLengthMs) *
  1170 + 100);
  1171 +
  1172 + USER_LOG_DEBUG("get media playback status %d %d %d %d", status->videoPlayProcess, status->playPosMs,
  1173 + status->videoLengthMs, status->playbackMode);
  1174 +
  1175 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1176 +}
  1177 +
  1178 +static T_DjiReturnCode StartDownloadNotification(void)
  1179 +{
  1180 + T_DjiReturnCode returnCode;
  1181 + T_DjiDataChannelBandwidthProportionOfHighspeedChannel bandwidthProportion = {0};
  1182 +
  1183 + USER_LOG_DEBUG("media download start notification.");
  1184 +
  1185 + bandwidthProportion.dataStream = 0;
  1186 + bandwidthProportion.videoStream = 0;
  1187 + bandwidthProportion.downloadStream = 100;
  1188 +
  1189 + returnCode = DjiHighSpeedDataChannel_SetBandwidthProportion(bandwidthProportion);
  1190 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1191 + USER_LOG_ERROR("Set bandwidth proportion for high speed channel error, stat:0x%08llX.", returnCode);
  1192 + return returnCode;
  1193 + }
  1194 +
  1195 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1196 +}
  1197 +
  1198 +static T_DjiReturnCode StopDownloadNotification(void)
  1199 +{
  1200 + T_DjiReturnCode returnCode;
  1201 + T_DjiDataChannelBandwidthProportionOfHighspeedChannel bandwidthProportion = {0};
  1202 +
  1203 + USER_LOG_DEBUG("media download stop notification.");
  1204 +
  1205 + bandwidthProportion.dataStream = TRANS_RATIO_DATA;
  1206 + bandwidthProportion.videoStream = TRANS_RATIO_VIDEO;
  1207 + bandwidthProportion.downloadStream = TRANS_RATIO_DOWNLOAD;
  1208 +
  1209 + returnCode = DjiHighSpeedDataChannel_SetBandwidthProportion(bandwidthProportion);
  1210 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1211 + USER_LOG_ERROR("Set bandwidth proportion for high speed channel error, stat:0x%08llX.", returnCode);
  1212 + return returnCode;
  1213 + }
  1214 +
  1215 + return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1216 +}
  1217 +
  1218 +#ifndef __CC_ARM
  1219 +#pragma GCC diagnostic push
  1220 +#pragma GCC diagnostic ignored "-Wmissing-noreturn"
  1221 +#pragma GCC diagnostic ignored "-Wreturn-type"
  1222 +#endif
  1223 +
  1224 +
  1225 +
  1226 +// 任务
  1227 +static void *UserCameraMedia_SendVideoTask(void *arg)
  1228 +{
  1229 + int ret;
  1230 + // 回调错误
  1231 + T_DjiReturnCode returnCode;
  1232 + //发送视频的阶数
  1233 + static uint32_t sendVideoStep = 0;
  1234 + // 传输的视频文件
  1235 + FILE *fpFile = NULL;
  1236 + //传输数据长度 一帧不能超过65kb 超过需要分割
  1237 + unsigned long dataLength = 0;
  1238 + // 将要发送的产度
  1239 + uint16_t lengthOfDataToBeSent = 0;
  1240 + // 上次已发送的长度
  1241 + int lengthOfDataHaveBeenSent = 0;
  1242 + // 视频数据队列
  1243 + char *dataBuffer = NULL;
  1244 + // 回放指令
  1245 + T_TestPayloadCameraPlaybackCommand playbackCommand = {0};
  1246 + //
  1247 + uint16_t bufferReadSize = 0;
  1248 + // 视频文件的地址
  1249 + char *videoFilePath = NULL;
  1250 + // 转码文件的地址
  1251 + char *transcodedFilePath = NULL;
  1252 + float frameRate = 1.0f;
  1253 + uint32_t waitDuration = 1000 / SEND_VIDEO_TASK_FREQ;
  1254 + uint32_t rightNow = 0;
  1255 + uint32_t sendExpect = 0;
  1256 + // 帧信息
  1257 + T_TestPayloadCameraVideoFrameInfo *frameInfo = NULL;
  1258 + // 帧数
  1259 + uint32_t frameNumber = 0;
  1260 + // 总帧
  1261 + uint32_t frameCount = 0;
  1262 + // 开始时间的 延迟
  1263 + uint32_t startTimeMs = 0;
  1264 + // 发送文件的标识
  1265 + bool sendVideoFlag = true;
  1266 + // 发送 一次 的 时间 标示
  1267 + bool sendOneTimeFlag = false;
  1268 + // 视频流状态
  1269 + T_DjiDataChannelState videoStreamState = {0};
  1270 + // 拍照模式
  1271 + E_DjiCameraMode mode = DJI_CAMERA_MODE_SHOOT_PHOTO;
  1272 + // ousl硬件层 句柄
  1273 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  1274 + uint32_t frameBufSize = 0;
  1275 + // 视频流类型
  1276 + E_DjiCameraVideoStreamType videoStreamType;
  1277 + // 通用 文件路径
  1278 + char curFileDirPath[DJI_FILE_PATH_SIZE_MAX];
  1279 + // 临时路径
  1280 + char tempPath[DJI_FILE_PATH_SIZE_MAX];
  1281 +
  1282 + USER_UTIL_UNUSED(arg);
  1283 +
  1284 +
  1285 + // 获取视频流文件信息
  1286 + // 获取 通用地址 的错误
  1287 + returnCode = DjiUserUtil_GetCurrentFileDirPath("/root/sdcard/DCIM", DJI_FILE_PATH_SIZE_MAX, curFileDirPath);
  1288 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1289 + USER_LOG_ERROR("Get file current path error, stat = 0x%08llX", returnCode);
  1290 + pthread_exit(NULL);
  1291 + }
  1292 +
  1293 + USER_LOG_INFO("curFileDirPath:%s",curFileDirPath);
  1294 +
  1295 + if (s_isMediaFileDirPathConfigured == true) {
  1296 + snprintf(tempPath, DJI_FILE_PATH_SIZE_MAX, "%sPSDK_0005.h264", s_mediaFileDirPath);
  1297 + } else {
  1298 + snprintf(tempPath, DJI_FILE_PATH_SIZE_MAX, "%smedia_file/PSDK_0005.h264", curFileDirPath);
  1299 + }
  1300 +
  1301 + // 写入用于推送文件的临时地址
  1302 + // USER_LOG_INFO("tempPath:%s",tempPath);
  1303 +
  1304 + // 视频流处理线程初始化
  1305 + // 为视频文件申请
  1306 + videoFilePath = osalHandler->Malloc(DJI_FILE_PATH_SIZE_MAX);
  1307 + if (videoFilePath == NULL) {
  1308 + USER_LOG_ERROR("malloc memory for video file path fail.");
  1309 + pthread_exit(NULL);
  1310 + }
  1311 +
  1312 + // 转码文件的地址
  1313 + transcodedFilePath = osalHandler->Malloc(DJI_FILE_PATH_SIZE_MAX);
  1314 + if (transcodedFilePath == NULL) {
  1315 + USER_LOG_ERROR("malloc memory for transcoded file path fail.");
  1316 + pthread_exit(NULL);
  1317 + }
  1318 +
  1319 + // 帧信息
  1320 + frameInfo = osalHandler->Malloc(VIDEO_FRAME_MAX_COUNT * sizeof(T_TestPayloadCameraVideoFrameInfo));
  1321 + if (frameInfo == NULL) {
  1322 + USER_LOG_ERROR("malloc memory for frame info fail.");
  1323 + pthread_exit(NULL);
  1324 + }
  1325 + memset(frameInfo, 0, VIDEO_FRAME_MAX_COUNT * sizeof(T_TestPayloadCameraVideoFrameInfo));
  1326 +
  1327 +
  1328 + //停止 回放播放程序
  1329 + returnCode = DjiPlayback_StopPlayProcess();
  1330 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1331 + USER_LOG_ERROR("stop playback and start liveview error: 0x%08llX.", returnCode);
  1332 + pthread_exit(NULL);
  1333 + }
  1334 +
  1335 + (void)osalHandler->GetTimeMs(&rightNow);
  1336 + sendExpect = rightNow + waitDuration;
  1337 + while (1) {
  1338 + // (void)osalHandler->GetTimeMs(&rightNow);
  1339 + // if (sendExpect > rightNow) {
  1340 + // waitDuration = sendExpect - rightNow;
  1341 + // } else {
  1342 + // waitDuration = 1000 / SEND_VIDEO_TASK_FREQ;
  1343 + // }
  1344 + // (void)osalHandler->SemaphoreTimedWait(s_mediaPlayWorkSem, waitDuration);
  1345 + osalHandler->TaskSleepMs(40);
  1346 +
  1347 + // response playback command
  1348 + // 响应播放命令
  1349 + if (osalHandler->MutexLock(s_mediaPlayCommandBufferMutex) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1350 + USER_LOG_ERROR("mutex lock error");
  1351 + continue;
  1352 + }
  1353 +
  1354 + bufferReadSize = UtilBuffer_Get(&s_mediaPlayCommandBufferHandler, (uint8_t *) &playbackCommand,
  1355 + sizeof(T_TestPayloadCameraPlaybackCommand));
  1356 +
  1357 + if (osalHandler->MutexUnlock(s_mediaPlayCommandBufferMutex) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1358 + USER_LOG_ERROR("mutex unlock error"); //互斥锁 解锁 失败
  1359 + continue;
  1360 + }
  1361 +
  1362 + //&& playbackCommand.command != TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_STOP
  1363 + // if (bufferReadSize != sizeof(T_TestPayloadCameraPlaybackCommand) && playbackCommand.command != TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_STOP)
  1364 + // {
  1365 + // goto send;
  1366 + // }
  1367 +
  1368 + returnCode = DjiTest_CameraGetVideoStreamType(&videoStreamType);
  1369 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1370 + continue;
  1371 + }
  1372 +
  1373 + //printf("视频流类型videoStreamType%d\n",videoStreamType);
  1374 +
  1375 +// 根据 输入的指令 选择功能
  1376 + switch (playbackCommand.command) {
  1377 + case TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_STOP:
  1378 + //snprintf(videoFilePath, DJI_FILE_PATH_SIZE_MAX, "%s", tempPath);
  1379 + startTimeMs = 0;
  1380 + //sendVideoFlag = true;
  1381 + //sendOneTimeFlag = false;
  1382 +
  1383 + //录像回放函数
  1384 + DJI_VideoReplay_input(playbackCommand.command, 0, NULL);
  1385 + goto Push_end;
  1386 +
  1387 + break;
  1388 +
  1389 + // 暂停视频播放
  1390 + case TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_PAUSE:
  1391 + //sendVideoFlag = false;
  1392 + //goto send;
  1393 + //录像回放函数
  1394 + DJI_VideoReplay_input(playbackCommand.command, 0, NULL);
  1395 +
  1396 + goto Push_end;
  1397 + break;
  1398 +
  1399 + // 开始视频播放
  1400 + case TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_START:
  1401 + //snprintf(videoFilePath, DJI_FILE_PATH_SIZE_MAX, "%s", playbackCommand.path);
  1402 + startTimeMs = playbackCommand.timeMs;
  1403 + // sendVideoFlag = true;
  1404 + // sendOneTimeFlag = true;
  1405 +
  1406 + //录像回放函数
  1407 + DJI_VideoReplay_input(playbackCommand.command, playbackCommand.timeMs, playbackCommand.path);
  1408 +
  1409 + goto Push_end;
  1410 + break;
  1411 + // 其余输入 负载的指令无效
  1412 + default:
  1413 + USER_LOG_ERROR("playback command invalid: %d.", playbackCommand.command);
  1414 + sendVideoFlag = false;
  1415 + goto send;
  1416 + }
  1417 +
  1418 + // video send preprocess 视频发送预处理
  1419 + //转码函数
  1420 + returnCode = DjiPlayback_VideoFileTranscode(videoFilePath, "h264", transcodedFilePath,
  1421 + DJI_FILE_PATH_SIZE_MAX);
  1422 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1423 + USER_LOG_ERROR("transcode video file error: 0x%08llX.", returnCode);
  1424 + continue;
  1425 + }
  1426 +
  1427 + // 获取视频文件中的帧速率
  1428 + returnCode = DjiPlayback_GetFrameRateOfVideoFile(transcodedFilePath, &frameRate);
  1429 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1430 + USER_LOG_ERROR("get frame rate of video error: 0x%08llX.", returnCode);
  1431 + continue;
  1432 + }
  1433 +
  1434 + // 获取视频文件中的 帧信息
  1435 + returnCode = DjiPlayback_GetFrameInfoOfVideoFile(transcodedFilePath, frameInfo, VIDEO_FRAME_MAX_COUNT,
  1436 + &frameCount);
  1437 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1438 + USER_LOG_ERROR("get frame info of video error: 0x%08llX.", returnCode);
  1439 + continue;
  1440 + }
  1441 +
  1442 + // 根据时间获取 帧数
  1443 + returnCode = DjiPlayback_GetFrameNumberByTime(frameInfo, frameCount, &frameNumber,
  1444 + startTimeMs);
  1445 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1446 + USER_LOG_ERROR("get start frame number error: 0x%08llX.", returnCode);
  1447 + continue;
  1448 + }
  1449 +
  1450 + if (fpFile != NULL)
  1451 + fclose(fpFile);
  1452 +
  1453 +// fpfile 为转码文件
  1454 + fpFile = fopen(transcodedFilePath, "rb+");
  1455 + if (fpFile == NULL) {
  1456 + USER_LOG_ERROR("open video file fail.");
  1457 + continue;
  1458 + }
  1459 +
  1460 +send:
  1461 + if (fpFile == NULL) {
  1462 + USER_LOG_ERROR("open video file fail.");
  1463 + continue;
  1464 + }
  1465 +
  1466 + if (sendVideoFlag != true)
  1467 + continue;
  1468 +
  1469 + returnCode = DjiTest_CameraGetMode(&mode);
  1470 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1471 + continue;
  1472 + }
  1473 +
  1474 + returnCode = DjiTest_CameraGetVideoStreamType(&videoStreamType);
  1475 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1476 + continue;
  1477 + }
  1478 +
  1479 + if (mode == DJI_CAMERA_MODE_PLAYBACK && s_playbackInfo.isInPlayProcess == false) {
  1480 + continue;
  1481 + }
  1482 +
  1483 + if (!USER_UTIL_IS_WORK_TURN(sendVideoStep++, frameRate, SEND_VIDEO_TASK_FREQ))
  1484 + continue;
  1485 +
  1486 + frameBufSize = frameInfo[frameNumber].size;
  1487 + if (videoStreamType == DJI_CAMERA_VIDEO_STREAM_TYPE_H264_DJI_FORMAT) {
  1488 + frameBufSize = frameBufSize + VIDEO_FRAME_AUD_LEN;
  1489 + }
  1490 +
  1491 + // 视频流解析
  1492 + // 视频内容的长度 分配 帧的内容长度数量 个 1字节
  1493 + dataBuffer = calloc(frameBufSize, 1);
  1494 + if (dataBuffer == NULL) {
  1495 + USER_LOG_ERROR("malloc fail.");
  1496 + goto free;
  1497 + }
  1498 +
  1499 + ret = fseek(fpFile, frameInfo[frameNumber].positionInFile, SEEK_SET);
  1500 + if (ret != 0) {
  1501 + USER_LOG_ERROR("fseek fail.");
  1502 + goto free;
  1503 + }
  1504 +
  1505 +// 读取内容长度
  1506 + dataLength = fread(dataBuffer, 1, frameInfo[frameNumber].size, fpFile);
  1507 + if (dataLength != frameInfo[frameNumber].size) {
  1508 + USER_LOG_ERROR("read data from video file error.");
  1509 + } else {
  1510 + USER_LOG_DEBUG("read data from video file success, len = %d B\r\n", dataLength);
  1511 + }
  1512 +
  1513 + // 如果 视频流类型 为 大疆H264 类型
  1514 + if (videoStreamType == DJI_CAMERA_VIDEO_STREAM_TYPE_H264_DJI_FORMAT) {
  1515 + // 将 审核的帧信息 复制到 数据内容 的 帧信息【帧数】大小 长度为 视频帧审核长度
  1516 + //USER_LOG_INFO("播放类型为大疆h264型");
  1517 + memcpy(&dataBuffer[frameInfo[frameNumber].size], s_frameAudInfo, VIDEO_FRAME_AUD_LEN);
  1518 + dataLength = dataLength + VIDEO_FRAME_AUD_LEN;
  1519 + }
  1520 +
  1521 + lengthOfDataHaveBeenSent = 0;
  1522 + while (dataLength - lengthOfDataHaveBeenSent) {
  1523 + lengthOfDataToBeSent = USER_UTIL_MIN(DATA_SEND_FROM_VIDEO_STREAM_MAX_LEN,
  1524 + dataLength - lengthOfDataHaveBeenSent);
  1525 +
  1526 + // 推送(发送) 视频流 (databuffer序列 (存储的一帧图片数据+ 已经发送的数据长度 , 将要发送的数据长度 )
  1527 + // 用于返还 视频流通道的状态
  1528 + returnCode = DjiPayloadCamera_SendVideoStream((const uint8_t *) dataBuffer + lengthOfDataHaveBeenSent,
  1529 + lengthOfDataToBeSent);
  1530 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1531 + USER_LOG_ERROR("send video stream error: 0x%08llX.", returnCode);
  1532 + }
  1533 + lengthOfDataHaveBeenSent += lengthOfDataToBeSent;
  1534 + }
  1535 +
  1536 + (void)osalHandler->GetTimeMs(&sendExpect);
  1537 + sendExpect += (1000 / frameRate);
  1538 +
  1539 + if ((frameNumber++) >= frameCount) {
  1540 + USER_LOG_DEBUG("reach file tail.");
  1541 + frameNumber = 0;
  1542 +
  1543 + if (sendOneTimeFlag == true)
  1544 + sendVideoFlag = false;
  1545 + }
  1546 +
  1547 + // 调整帧速率
  1548 + returnCode = DjiPayloadCamera_GetVideoStreamState(&videoStreamState);
  1549 + if (returnCode == DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1550 + USER_LOG_DEBUG(
  1551 + "video stream state: realtimeBandwidthLimit: %d, realtimeBandwidthBeforeFlowController: %d, realtimeBandwidthAfterFlowController:%d busyState: %d.",
  1552 + videoStreamState.realtimeBandwidthLimit, videoStreamState.realtimeBandwidthBeforeFlowController,
  1553 + videoStreamState.realtimeBandwidthAfterFlowController,
  1554 + videoStreamState.busyState);
  1555 + } else {
  1556 + USER_LOG_ERROR("get video stream state error.");
  1557 + }
  1558 +
  1559 +free:
  1560 + free(dataBuffer);
  1561 +
  1562 +Push_end:
  1563 + continue;
  1564 + }
  1565 +
  1566 +VideoSend_end:
  1567 + if(ret < 0)
  1568 + USER_LOG_ERROR("推流模块加载失败");
  1569 +}
  1570 +
  1571 +
  1572 +
  1573 +//录像播放测试函数,用于研发新产品时,图传播放录像使用
  1574 +static void *TestCameraMedia_SendVideoTask(void *arg)
  1575 +{
  1576 + int ret;
  1577 + // 回调错误
  1578 + T_DjiReturnCode returnCode;
  1579 + //发送视频的阶数
  1580 + static uint32_t sendVideoStep = 0;
  1581 + // 传输的视频文件
  1582 + FILE *fpFile = NULL;
  1583 + //传输数据长度 一帧不能超过65kb 超过需要分割
  1584 + unsigned long dataLength = 0;
  1585 + // 将要发送的产度
  1586 + uint16_t lengthOfDataToBeSent = 0;
  1587 + // 上次已发送的长度
  1588 + int lengthOfDataHaveBeenSent = 0;
  1589 + // 视频数据队列
  1590 + char *dataBuffer = NULL;
  1591 + // 回放指令
  1592 + T_TestPayloadCameraPlaybackCommand playbackCommand = {0};
  1593 + //
  1594 + uint16_t bufferReadSize = 0;
  1595 + // 视频文件的地址
  1596 + char *videoFilePath = NULL;
  1597 + // 转码文件的地址
  1598 + char *transcodedFilePath = NULL;
  1599 + float frameRate = 1.0f;
  1600 + // 帧信息
  1601 + T_TestPayloadCameraVideoFrameInfo *frameInfo = NULL;
  1602 + // 帧数
  1603 + uint32_t frameNumber = 0;
  1604 + // 总帧
  1605 + uint32_t frameCount = 0;
  1606 + // 开始时间的 延迟
  1607 + uint32_t startTimeMs = 0;
  1608 + // 发送文件的标识
  1609 + bool sendVideoFlag = true;
  1610 + // 发送 一次 的 时间 标示
  1611 + bool sendOneTimeFlag = false;
  1612 + // 视频流状态
  1613 + T_DjiDataChannelState videoStreamState = {0};
  1614 + // 拍照模式
  1615 + E_DjiCameraMode mode = DJI_CAMERA_MODE_SHOOT_PHOTO;
  1616 + // ousl硬件层 句柄
  1617 + T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
  1618 + uint32_t frameBufSize = 0;
  1619 + // 视频流类型
  1620 + E_DjiCameraVideoStreamType videoStreamType;
  1621 + // 通用 文件路径
  1622 + char curFileDirPath[DJI_FILE_PATH_SIZE_MAX];
  1623 + // 临时路径
  1624 + char tempPath[DJI_FILE_PATH_SIZE_MAX];
  1625 +
  1626 + USER_UTIL_UNUSED(arg);
  1627 +
  1628 +
  1629 + // 获取视频流文件信息
  1630 + // 获取 通用地址 的错误
  1631 + returnCode = DjiUserUtil_GetCurrentFileDirPath("/root/sdcard/DCIM", DJI_FILE_PATH_SIZE_MAX, curFileDirPath);
  1632 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1633 + USER_LOG_ERROR("Get file current path error, stat = 0x%08llX", returnCode);
  1634 + exit(1);
  1635 + }
  1636 +
  1637 + USER_LOG_INFO("curFileDirPath:%s",curFileDirPath);
  1638 +
  1639 + // if (s_isMediaFileDirPathConfigured == true) {
  1640 + // snprintf(tempPath, DJI_FILE_PATH_SIZE_MAX, "%sPSDK_0005.h264", s_mediaFileDirPath);
  1641 + // } else {
  1642 + // snprintf(tempPath, DJI_FILE_PATH_SIZE_MAX, "%smedia_file/PSDK_0005.h264", curFileDirPath);
  1643 + // }
  1644 + snprintf(tempPath, DJI_FILE_PATH_SIZE_MAX, "/root/sdcard/media_file/PSDK_0005.h264", curFileDirPath);
  1645 +
  1646 + // 写入用于推送文件的临时地址
  1647 + // USER_LOG_INFO("tempPath:%s",tempPath);
  1648 +
  1649 + // 视频流处理线程初始化
  1650 + // 为视频文件申请
  1651 + videoFilePath = osalHandler->Malloc(DJI_FILE_PATH_SIZE_MAX);
  1652 + if (videoFilePath == NULL) {
  1653 + USER_LOG_ERROR("malloc memory for video file path fail.");
  1654 + exit(1);
  1655 + }
  1656 +
  1657 + // 转码文件的地址
  1658 + transcodedFilePath = osalHandler->Malloc(DJI_FILE_PATH_SIZE_MAX);
  1659 + if (transcodedFilePath == NULL) {
  1660 + USER_LOG_ERROR("malloc memory for transcoded file path fail.");
  1661 + exit(1);
  1662 + }
  1663 +
  1664 + // 帧信息
  1665 + frameInfo = osalHandler->Malloc(VIDEO_FRAME_MAX_COUNT * sizeof(T_TestPayloadCameraVideoFrameInfo));
  1666 + if (frameInfo == NULL) {
  1667 + USER_LOG_ERROR("malloc memory for frame info fail.");
  1668 + exit(1);
  1669 + }
  1670 + memset(frameInfo, 0, VIDEO_FRAME_MAX_COUNT * sizeof(T_TestPayloadCameraVideoFrameInfo));
  1671 +
  1672 +
  1673 + //停止 回放播放程序
  1674 + returnCode = DjiPlayback_StopPlayProcess();
  1675 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1676 + USER_LOG_ERROR("stop playback and start liveview error: 0x%08llX.", returnCode);
  1677 + exit(1);
  1678 + }
  1679 +
  1680 + while (1) {
  1681 + osalHandler->TaskSleepMs(1000 / SEND_VIDEO_TASK_FREQ);
  1682 +
  1683 + // response playback command
  1684 + if (osalHandler->MutexLock(s_mediaPlayCommandBufferMutex) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1685 + USER_LOG_ERROR("mutex lock error");
  1686 + continue;
  1687 + }
  1688 +
  1689 + bufferReadSize = UtilBuffer_Get(&s_mediaPlayCommandBufferHandler, (uint8_t *) &playbackCommand,
  1690 + sizeof(T_TestPayloadCameraPlaybackCommand));
  1691 +
  1692 + if (osalHandler->MutexUnlock(s_mediaPlayCommandBufferMutex) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1693 + USER_LOG_ERROR("mutex unlock error");
  1694 + continue;
  1695 + }
  1696 +
  1697 + if (bufferReadSize != sizeof(T_TestPayloadCameraPlaybackCommand))
  1698 + goto send;
  1699 +
  1700 + switch (playbackCommand.command) {
  1701 + case TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_STOP:
  1702 + snprintf(videoFilePath, DJI_FILE_PATH_SIZE_MAX, "%s", tempPath);
  1703 + startTimeMs = 0;
  1704 + sendVideoFlag = true;
  1705 + sendOneTimeFlag = false;
  1706 + break;
  1707 + case TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_PAUSE:
  1708 + sendVideoFlag = false;
  1709 + goto send;
  1710 + case TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_START:
  1711 + snprintf(videoFilePath, DJI_FILE_PATH_SIZE_MAX, "%s", playbackCommand.path);
  1712 + startTimeMs = playbackCommand.timeMs;
  1713 + sendVideoFlag = true;
  1714 + sendOneTimeFlag = true;
  1715 + break;
  1716 + default:
  1717 + USER_LOG_ERROR("playback command invalid: %d.", playbackCommand.command);
  1718 + sendVideoFlag = false;
  1719 + goto send;
  1720 + }
  1721 +
  1722 + // video send preprocess
  1723 + returnCode = DjiPlayback_VideoFileTranscode(videoFilePath, "h264", transcodedFilePath,
  1724 + DJI_FILE_PATH_SIZE_MAX);
  1725 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1726 + USER_LOG_ERROR("transcode video file error: 0x%08llX.", returnCode);
  1727 + continue;
  1728 + }
  1729 +
  1730 + returnCode = DjiPlayback_GetFrameRateOfVideoFile(transcodedFilePath, &frameRate);
  1731 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1732 + USER_LOG_ERROR("get frame rate of video error: 0x%08llX.", returnCode);
  1733 + continue;
  1734 + }
  1735 +
  1736 + returnCode = DjiPlayback_GetFrameInfoOfVideoFile(transcodedFilePath, frameInfo, VIDEO_FRAME_MAX_COUNT,
  1737 + &frameCount);
  1738 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1739 + USER_LOG_ERROR("get frame info of video error: 0x%08llX.", returnCode);
  1740 + continue;
  1741 + }
  1742 +
  1743 + returnCode = DjiPlayback_GetFrameNumberByTime(frameInfo, frameCount, &frameNumber,
  1744 + startTimeMs);
  1745 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1746 + USER_LOG_ERROR("get start frame number error: 0x%08llX.", returnCode);
  1747 + continue;
  1748 + }
  1749 +
  1750 + if (fpFile != NULL)
  1751 + fclose(fpFile);
  1752 +
  1753 + fpFile = fopen(transcodedFilePath, "rb+");
  1754 + if (fpFile == NULL) {
  1755 + USER_LOG_ERROR("open video file fail.");
  1756 + continue;
  1757 + }
  1758 +
  1759 +send:
  1760 + if (fpFile == NULL) {
  1761 + USER_LOG_ERROR("open video file fail.");
  1762 + continue;
  1763 + }
  1764 +
  1765 + if (sendVideoFlag != true)
  1766 + continue;
  1767 +
  1768 + returnCode = DjiTest_CameraGetMode(&mode);
  1769 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1770 + continue;
  1771 + }
  1772 +
  1773 + returnCode = DjiTest_CameraGetVideoStreamType(&videoStreamType);
  1774 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1775 + continue;
  1776 + }
  1777 +
  1778 + if (mode == DJI_CAMERA_MODE_PLAYBACK && s_playbackInfo.isInPlayProcess == false) {
  1779 + continue;
  1780 + }
  1781 +
  1782 + if (!USER_UTIL_IS_WORK_TURN(sendVideoStep++, frameRate, SEND_VIDEO_TASK_FREQ))
  1783 + continue;
  1784 +
  1785 + frameBufSize = frameInfo[frameNumber].size;
  1786 + if (videoStreamType == DJI_CAMERA_VIDEO_STREAM_TYPE_H264_DJI_FORMAT) {
  1787 + frameBufSize = frameBufSize + VIDEO_FRAME_AUD_LEN;
  1788 + }
  1789 +
  1790 + dataBuffer = calloc(frameBufSize, 1);
  1791 + if (dataBuffer == NULL) {
  1792 + USER_LOG_ERROR("malloc fail.");
  1793 + goto free;
  1794 + }
  1795 +
  1796 + ret = fseek(fpFile, frameInfo[frameNumber].positionInFile, SEEK_SET);
  1797 + if (ret != 0) {
  1798 + USER_LOG_ERROR("fseek fail.");
  1799 + goto free;
  1800 + }
  1801 +
  1802 + dataLength = fread(dataBuffer, 1, frameInfo[frameNumber].size, fpFile);
  1803 + if (dataLength != frameInfo[frameNumber].size) {
  1804 + USER_LOG_ERROR("read data from video file error.");
  1805 + } else {
  1806 + USER_LOG_DEBUG("read data from video file success, len = %d B\r\n", dataLength);
  1807 + }
  1808 +
  1809 + if (videoStreamType == DJI_CAMERA_VIDEO_STREAM_TYPE_H264_DJI_FORMAT) {
  1810 + memcpy(&dataBuffer[frameInfo[frameNumber].size], s_frameAudInfo, VIDEO_FRAME_AUD_LEN);
  1811 + dataLength = dataLength + VIDEO_FRAME_AUD_LEN;
  1812 + }
  1813 +
  1814 + lengthOfDataHaveBeenSent = 0;
  1815 + while (dataLength - lengthOfDataHaveBeenSent) {
  1816 + lengthOfDataToBeSent = USER_UTIL_MIN(DATA_SEND_FROM_VIDEO_STREAM_MAX_LEN,
  1817 + dataLength - lengthOfDataHaveBeenSent);
  1818 + returnCode = DjiPayloadCamera_SendVideoStream((const uint8_t *) dataBuffer + lengthOfDataHaveBeenSent,
  1819 + lengthOfDataToBeSent);
  1820 + if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1821 + USER_LOG_ERROR("send video stream error: 0x%08llX.", returnCode);
  1822 + }
  1823 + lengthOfDataHaveBeenSent += lengthOfDataToBeSent;
  1824 + }
  1825 +
  1826 + if ((frameNumber++) >= frameCount) {
  1827 + USER_LOG_DEBUG("reach file tail.");
  1828 + frameNumber = 0;
  1829 +
  1830 + if (sendOneTimeFlag == true)
  1831 + sendVideoFlag = false;
  1832 + }
  1833 +
  1834 + returnCode = DjiPayloadCamera_GetVideoStreamState(&videoStreamState);
  1835 + if (returnCode == DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1836 + USER_LOG_DEBUG(
  1837 + "video stream state: realtimeBandwidthLimit: %d, realtimeBandwidthBeforeFlowController: %d, realtimeBandwidthAfterFlowController:%d busyState: %d.",
  1838 + videoStreamState.realtimeBandwidthLimit, videoStreamState.realtimeBandwidthBeforeFlowController,
  1839 + videoStreamState.realtimeBandwidthAfterFlowController,
  1840 + videoStreamState.busyState);
  1841 + } else {
  1842 + USER_LOG_ERROR("get video stream state error.");
  1843 + }
  1844 +
  1845 +free:
  1846 + free(dataBuffer);
  1847 + }
  1848 +
  1849 +VideoSend_end:
  1850 + if(ret < 0)
  1851 + USER_LOG_ERROR("推流模块加载失败");
  1852 +}
  1853 +
  1854 +#ifndef __CC_ARM
  1855 +#pragma GCC diagnostic pop
  1856 +#endif
  1857 +
  1858 +//#endif
  1859 +
  1860 +/****************** (C) COPYRIGHT DJI Innovations *****END OF FILE****/
  1 +/**
  2 + ********************************************************************
  3 + * @file test_payload_cam_emu_media.h
  4 + * @brief This is the header file for "test_payload_cam_media.c", defining the structure and
  5 + * (exported) function prototypes.
  6 + *
  7 + * @copyright (c) 2021 DJI. All rights reserved.
  8 + *
  9 + * All information contained herein is, and remains, the property of DJI.
  10 + * The intellectual and technical concepts contained herein are proprietary
  11 + * to DJI and may be covered by U.S. and foreign patents, patents in process,
  12 + * and protected by trade secret or copyright law. Dissemination of this
  13 + * information, including but not limited to data and other proprietary
  14 + * material(s) incorporated within the information, in any form, is strictly
  15 + * prohibited without the express written consent of DJI.
  16 + *
  17 + * If you receive this source code without DJI’s authorization, you may not
  18 + * further disseminate the information, and you must immediately remove the
  19 + * source code and notify DJI of its removal. DJI reserves the right to pursue
  20 + * legal actions against you for any loss(es) or damage(s) caused by your
  21 + * failure to do so.
  22 + *
  23 + *********************************************************************
  24 + */
  25 +
  26 +/* Define to prevent recursive inclusion -------------------------------------*/
  27 +#ifndef TEST_PAYLOAD_CAM_EMU_MEDIA_H
  28 +#define TEST_PAYLOAD_CAM_EMU_MEDIA_H
  29 +
  30 +/* Includes ------------------------------------------------------------------*/
  31 +#include "dji_typedef.h"
  32 +#include "dji_payload_camera.h"
  33 +
  34 +#ifdef __cplusplus
  35 +extern "C" {
  36 +#endif
  37 +
  38 +/* Exported constants --------------------------------------------------------*/
  39 +
  40 +/* Exported types ------------------------------------------------------------*/
  41 +
  42 +/* Exported functions --------------------------------------------------------*/
  43 +T_DjiReturnCode DjiTest_CameraEmuMediaStartService(int mode);
  44 +T_DjiReturnCode DjiTest_CameraEmuSetMediaFilePath(const char *path);
  45 +T_DjiReturnCode DjiTest_CameraMediaGetFileInfo(const char *filePath, T_DjiCameraMediaFileInfo *fileInfo);
  46 +
  47 +#ifdef __cplusplus
  48 +}
  49 +#endif
  50 +
  51 +#endif // TEST_PAYLOAD_CAM_EMU_MEDIA_H
  52 +/************************ (C) COPYRIGHT DJI Innovations *******END OF FILE******/
  1 +/**
  2 + ********************************************************************
  3 + * @file test_camera_manager.h
  4 + * @brief This is the header file for "test_camera_manager.c", defining the structure and
  5 + * (exported) function prototypes.
  6 + *
  7 + * @copyright (c) 2021 DJI. All rights reserved.
  8 + *
  9 + * All information contained herein is, and remains, the property of DJI.
  10 + * The intellectual and technical concepts contained herein are proprietary
  11 + * to DJI and may be covered by U.S. and foreign patents, patents in process,
  12 + * and protected by trade secret or copyright law. Dissemination of this
  13 + * information, including but not limited to data and other proprietary
  14 + * material(s) incorporated within the information, in any form, is strictly
  15 + * prohibited without the express written consent of DJI.
  16 + *
  17 + * If you receive this source code without DJI’s authorization, you may not
  18 + * further disseminate the information, and you must immediately remove the
  19 + * source code and notify DJI of its removal. DJI reserves the right to pursue
  20 + * legal actions against you for any loss(es) or damage(s) caused by your
  21 + * failure to do so.
  22 + *
  23 + *********************************************************************
  24 + */
  25 +
  26 +/* Define to prevent recursive inclusion -------------------------------------*/
  27 +#ifndef TEST_CAMERA_MANAGER_H
  28 +#define TEST_CAMERA_MANAGER_H
  29 +
  30 +/* Includes ------------------------------------------------------------------*/
  31 +#include "dji_typedef.h"
  32 +#include "dji_camera_manager.h"
  33 +
  34 +#ifdef __cplusplus
  35 +extern "C" {
  36 +#endif
  37 +
  38 +/* Exported constants --------------------------------------------------------*/
  39 +
  40 +/* Exported types ------------------------------------------------------------*/
  41 +typedef enum {
  42 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_CAMERA_SHUTTER_SPEED,
  43 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_CAMERA_APERTURE,
  44 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_CAMERA_EV,
  45 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_CAMERA_ISO,
  46 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_CAMERA_FOCUS_POINT,
  47 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_CAMERA_TAP_ZOOM_POINT,
  48 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_CAMERA_ZOOM_PARAM,
  49 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SHOOT_SINGLE_PHOTO,
  50 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SHOOT_BURST_PHOTO,
  51 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SHOOT_INTERVAL_PHOTO,
  52 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_RECORD_VIDEO,
  53 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_DOWNLOAD_AND_DELETE_MEDIA_FILE,
  54 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_DOWNLOAD_FILE_LIST_BY_SLICES,
  55 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_THERMOMETRY,
  56 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_GET_LIDAR_RANGING_INFO,
  57 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_IR_CAMERA_ZOOM_PARAM,
  58 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_NIGHT_SCENE_MODE,
  59 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_CAPTURE_RECORDING_STREAMS,
  60 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SHOW_STORAGE_INFO,
  61 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_FORMAT_SD_CARD,
  62 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_LINK_ZOOM,
  63 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_USER_CUSTOM_DIR_FILE_NAME,
  64 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_RESET_CAMERA_SETTINGS,
  65 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_AE_LOCK_MODE,
  66 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_FOCUS_RING_VALUE,
  67 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_CONNECT_STATUS_TEST,
  68 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_GET_PHOTO_VIDEO_PARAM,
  69 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_METERING_MODE,
  70 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_METERING_POINT,
  71 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_FFC_MODE_AND_TRRIGER,
  72 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SET_GAIN_MODE,
  73 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_GET_CAMERA_STATUS,
  74 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_SUBSCRIBE_POINT_CLOUD,
  75 + E_DJI_TEST_CAMERA_MANAGER_SAMPLE_SELECT_INDEX_MAX
  76 +} E_DjiTestCameraManagerSampleSelect;
  77 +/* Exported functions --------------------------------------------------------*/
  78 +
  79 +/*! @brief Sample to set exposure compensation value for camera, using async
  80 + * api
  81 + *
  82 + * @note In this interface, exposure compensation value will be got then be
  83 + * set.
  84 + * @param index payload node index, input limit see enum
  85 + * DJI::OSDK::PayloadIndexType
  86 + * @param dataTarget the target exposure compensation value
  87 + * @return T_DjiReturnCode error code
  88 + */
  89 +T_DjiReturnCode DjiTest_CameraManagerSetEV(E_DjiMountPosition position,
  90 + E_DjiCameraManagerExposureCompensation exposureCompensation);
  91 +
  92 +/*! @brief Sample to set exposure mode for camera, using async api
  93 + *
  94 + * @note In this interface, exposure will be got then be set.
  95 + * @param index payload node index, input limit see enum
  96 + * DJI::OSDK::PayloadIndexType
  97 + * @param dataTarget the target exposure mode
  98 + * @return T_DjiReturnCode error code
  99 + */
  100 +T_DjiReturnCode DjiTest_CameraManagerSetExposureMode(E_DjiMountPosition position,
  101 + E_DjiCameraManagerExposureMode exposureMode);
  102 +
  103 +/*! @brief Sample to set ISO value for camera, using async api
  104 + *
  105 + * @note In this interface, ISO will be got then be set.
  106 + * @param index payload node index, input limit see enum
  107 + * DJI::OSDK::PayloadIndexType
  108 + * @param dataTarget the target ISO value
  109 + * @return T_DjiReturnCode error code
  110 + */
  111 +T_DjiReturnCode DjiTest_CameraManagerSetISO(E_DjiMountPosition position,
  112 + E_DjiCameraManagerISO isoData);
  113 +/*! @brief Sample to set shutter speed for camera, using async api
  114 + *
  115 + * @note In this interface, shutter speed will be got then be set.
  116 + * @param index payload node index, input limit see enum
  117 + * DJI::OSDK::PayloadIndexType
  118 + * @param dataTarget the target shutter speed
  119 + * @return T_DjiReturnCode error code
  120 + */
  121 +T_DjiReturnCode DjiTest_CameraManagerSetShutterSpeed(E_DjiMountPosition position,
  122 + E_DjiCameraManagerShutterSpeed shutterSpeed);
  123 +
  124 +/*! @brief Sample to set shutter aperture value for camera, using async api
  125 + *
  126 + * @note In this interface, aperture value will be got then be set.
  127 + * @param index payload node index, input limit see enum
  128 + * DJI::OSDK::PayloadIndexType
  129 + * @param dataTarget the target aperture value
  130 + * @return T_DjiReturnCode error code
  131 + */
  132 +T_DjiReturnCode DjiTest_CameraManagerSetAperture(E_DjiMountPosition position,
  133 + E_DjiCameraManagerAperture aperture);
  134 +
  135 +/*! @brief Sample to set focus point for camera, using async api
  136 + *
  137 + * @note In this interface, focus mode will be set to be AUTO. Then the
  138 + * focus point will be set to be (x, y)
  139 + * @param index payload node index, input limit see enum
  140 + * DJI::OSDK::PayloadIndexType
  141 + * @param x the x value of target focus point, 0~1
  142 + * @param y the y value of target focus point, 0~1
  143 + * @return T_DjiReturnCode error code
  144 + */
  145 +T_DjiReturnCode DjiTest_CameraManagerSetFocusPoint(E_DjiMountPosition position,
  146 + T_DjiCameraManagerFocusPosData tapFocusPos);
  147 +
  148 +/*! @brief Sample to set tap-zoom point for camera, using async api
  149 + *
  150 + * @note In this interface, tap-zoom function will be enable and the
  151 + * multiplier will be set. Then the tap-zoom function will start with the
  152 + * target tap-zoom point (x, y)
  153 + * @param index payload node index, input limit see enum
  154 + * DJI::OSDK::PayloadIndexType
  155 + * @param multiplier the zoom multiplier of each tap zoom
  156 + * @param x the x value of target tap-zoom point, 0~1
  157 + * @param y the y value of target tap-zoom point, 0~1
  158 + * @return T_DjiReturnCode error code
  159 + */
  160 +T_DjiReturnCode DjiTest_CameraManagerSetTapZoomPoint(E_DjiMountPosition position, uint8_t multiplier,
  161 + T_DjiCameraManagerTapZoomPosData tapZoomPosData);
  162 +/*! @brief Sample to execute continuous zoom on camera, using sync api
  163 + *
  164 + * @note It is only supported by X5, X5R and X5S camera on Osmo with lens
  165 + * Olympus M.Zuiko ED 14-42mm f/3.5-5.6 EZ, Z3 camera, Z30 camera.
  166 + * @note In this interface, the zoom will start with the designated direction
  167 + * and speed, and will stop after zoomTimeInSecond second(s).
  168 + * @param index payload node index, input limit see enum
  169 + * DJI::OSDK::PayloadIndexType
  170 + * @param direction the choice of zoom out or zoom in
  171 + * @param speed zooming speed
  172 + * @return T_DjiReturnCode error code
  173 + */
  174 +T_DjiReturnCode DjiTest_CameraManagerStartContinuousZoom(E_DjiMountPosition position,
  175 + E_DjiCameraZoomDirection zoomDirection,
  176 + E_DjiCameraZoomSpeed zoomSpeed);
  177 +
  178 +/*! @brief Sample to execute position zoom on camera, using sync api
  179 + *
  180 + * @note It is only supported by X5, X5R and X5S camera on Osmo with lens
  181 + * Olympus M.Zuiko ED 14-42mm f/3.5-5.6 EZ, Z3 camera, Z30 camera.
  182 + * @note In this interface, the zoom will set the zoom factor as the your
  183 + * target value.
  184 + * @param index payload node index, input limit see enum
  185 + * DJI::OSDK::PayloadIndexType
  186 + * @param factor target zoom factor
  187 + * @return T_DjiReturnCode error code
  188 + */
  189 +T_DjiReturnCode DjiTest_CameraManagerOpticalZoom(E_DjiMountPosition position,
  190 + E_DjiCameraZoomDirection zoomDirection,
  191 + dji_f32_t factor);
  192 +
  193 +/*! @brief Sample to stop continuous zoom on camera, using async api
  194 + *
  195 + * @note It is only supported by X5, X5R and X5S camera on Osmo with lens
  196 + * Olympus M.Zuiko ED 14-42mm f/3.5-5.6 EZ, Z3 camera, Z30 camera.
  197 + * @param index payload node index, input limit see enum
  198 + * DJI::OSDK::PayloadIndexType
  199 + * @return T_DjiReturnCode error code
  200 + */
  201 +T_DjiReturnCode DjiTest_CameraManagerStopContinuousZoom(E_DjiMountPosition position);
  202 +
  203 +/*! @brief Sample to shoot single photo, using async api
  204 + *
  205 + * @note In this interface, camera will be set to be the SHOOT_PHOTO mode
  206 + * then start to shoot a single photo.
  207 + * @param index payload node index, input limit see enum
  208 + * DJI::OSDK::PayloadIndexType
  209 + * @return T_DjiReturnCode error code
  210 + */
  211 +T_DjiReturnCode DjiTest_CameraManagerStartShootSinglePhoto(E_DjiMountPosition position);
  212 +
  213 +/*! @brief Sample to shoot burst photo, using async api
  214 + *
  215 + * @note In this interface, camera will be set to be the SHOOT_PHOTO mode
  216 + * then start to shoot a burst photo.
  217 + * @param index payload node index, input limit see enum
  218 + * DJI::OSDK::PayloadIndexType
  219 + * @param count The number of pictures in each burst shooting
  220 + * @return T_DjiReturnCode error code
  221 + */
  222 +T_DjiReturnCode DjiTest_CameraManagerStartShootBurstPhoto(E_DjiMountPosition position,
  223 + E_DjiCameraBurstCount burstCount);
  224 +
  225 +/*! @brief Sample to start shooting interval photo, using async api
  226 + *
  227 + * @note In this interface, camera will be set to be the SHOOT_PHOTO mode
  228 + * then start to shoot a interval photo.
  229 + * @param index payload node index, input limit see enum
  230 + * DJI::OSDK::PayloadIndexType
  231 + * @param intervalData the parameter of interval shooting
  232 + * @return T_DjiReturnCode error code
  233 + */
  234 +T_DjiReturnCode DjiTest_CameraManagerStartShootIntervalPhoto(E_DjiMountPosition position,
  235 + T_DjiCameraPhotoTimeIntervalSettings intervalData);
  236 +
  237 +/*! @brief Sample to stop shooting, using async api
  238 + *
  239 + * @note In this interface, camera will stop all the shooting action
  240 + * @param index payload node index, input limit see enum
  241 + * DJI::OSDK::PayloadIndexType
  242 + * @return T_DjiReturnCode error code
  243 + */
  244 +T_DjiReturnCode DjiTest_CameraManagerStopShootPhoto(E_DjiMountPosition position);
  245 +
  246 +/*! @brief Sample to start record video, using async api
  247 + *
  248 + * @note In this interface, camera will be set to be the RECORD_VIDEO mode
  249 + * then start to record video.
  250 + * @param index payload node index, input limit see enum
  251 + * DJI::OSDK::PayloadIndexType
  252 + * @return T_DjiReturnCode error code
  253 + */
  254 +T_DjiReturnCode DjiTest_CameraManagerStartRecordVideo(E_DjiMountPosition position);
  255 +
  256 +/*! @brief Sample to stop record video, using async api
  257 + *
  258 + * @note In this interface, camera will be set to be the RECORD_VIDEO mode
  259 + * then stop recording video.
  260 + * @param index payload node index, input limit see enum
  261 + * DJI::OSDK::PayloadIndexType
  262 + * @return T_DjiReturnCode error code
  263 + */
  264 +T_DjiReturnCode DjiTest_CameraManagerStopRecordVideo(E_DjiMountPosition position);
  265 +
  266 +T_DjiReturnCode DjiTest_CameraManagerRunSample(E_DjiMountPosition mountPosition,
  267 + E_DjiTestCameraManagerSampleSelect cameraManagerSampleSelect);
  268 +
  269 +#ifdef __cplusplus
  270 +}
  271 +#endif
  272 +
  273 +#endif // TEST_CAMERA_MANAGER_H
  274 +/************************ (C) COPYRIGHT DJI Innovations *******END OF FILE******/