Compare commits
7 Commits
3.5
...
5938550032
| Author | SHA1 | Date | |
|---|---|---|---|
| 5938550032 | |||
| bf32d053a6 | |||
| 6688d23e13 | |||
| 916a8d8fc9 | |||
| 8c834c4884 | |||
| 59b71864e4 | |||
| 758f1f3979 |
83
.gitignore
vendored
Normal file
83
.gitignore
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
# tc
|
||||
/.idea/*
|
||||
/build/*
|
||||
|
||||
|
||||
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# AWS User-specific
|
||||
.idea/**/aws.xml
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/artifacts
|
||||
# .idea/compiler.xml
|
||||
# .idea/jarRepositories.xml
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
# *.iml
|
||||
# *.ipr
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# SonarLint plugin
|
||||
.idea/sonarlint/
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
@ -37,7 +37,7 @@ extern "C" {
|
||||
#define DJI_VERSION_MINOR 5 /*!< DJI SDK minor version num, when add functionality in a backwards compatible manner changes. Range from 0 to 99. */
|
||||
#define DJI_VERSION_MODIFY 0 /*!< DJI SDK modify version num, when have backwards compatible bug fixes changes. Range from 0 to 99. */
|
||||
#define DJI_VERSION_BETA 0 /*!< DJI SDK version beta info, release version will be 0, when beta version release changes. Range from 0 to 255. */
|
||||
#define DJI_VERSION_BUILD 1764 /*!< DJI SDK version build info, when jenkins trigger build changes. Range from 0 to 65535. */
|
||||
#define DJI_VERSION_BUILD 1765 /*!< DJI SDK version build info, when jenkins trigger build changes. Range from 0 to 65535. */
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
|
||||
Binary file not shown.
BIN
psdk_lib/lib/aarch64-linux-android-gcc/libpayloadsdk.a
Normal file
BIN
psdk_lib/lib/aarch64-linux-android-gcc/libpayloadsdk.a
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
psdk_lib/lib/arm-linux-androideabi-gcc/libpayloadsdk.a
Normal file
BIN
psdk_lib/lib/arm-linux-androideabi-gcc/libpayloadsdk.a
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
176
samples/sample_c/module_sample/camera_emu/ffmpeg_tc.c
Normal file
176
samples/sample_c/module_sample/camera_emu/ffmpeg_tc.c
Normal file
@ -0,0 +1,176 @@
|
||||
//
|
||||
// Created by tangchao on 2021/11/16.
|
||||
//
|
||||
|
||||
|
||||
#include "ffmpeg_tc.h"
|
||||
|
||||
char *getsystemtime()
|
||||
{
|
||||
//获取系统时间
|
||||
time_t timer;//time_t就是long int 类型
|
||||
struct tm *tblock;
|
||||
timer = time(NULL);//返回秒数(精度为秒),从1970-1-1,00:00:00 可以当成整型输出或用于其它函数
|
||||
tblock = localtime(&timer);
|
||||
//printf("Local time is: %s\n", asctime(tblock));
|
||||
|
||||
//格式化时间为需要的格式
|
||||
char fileNameTmp[256] = { 0 };
|
||||
char dirNameTmp[256] = { 0 };
|
||||
strftime(fileNameTmp, sizeof(fileNameTmp), "%Y%m%d_%H%M%S", tblock);
|
||||
return fileNameTmp;
|
||||
}
|
||||
|
||||
AVFrame *get_video_frame(IntputDev* input)//tc改动
|
||||
{
|
||||
clock_t start,finish;
|
||||
start = clock(); // 设置开始clock
|
||||
|
||||
int ret;
|
||||
AVFrame * ret_frame=NULL;
|
||||
|
||||
if(av_read_frame(input->v_ifmtCtx, input->in_packet)>=0)
|
||||
{
|
||||
if(input->in_packet->stream_index==input->videoindex)
|
||||
{
|
||||
ret = avcodec_send_packet(input->pCodecCtx, input->in_packet);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error sending a packet for decoding\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = avcodec_receive_frame(input->pCodecCtx, input->pFrame);
|
||||
if(ret<0)
|
||||
{
|
||||
printf("Decode Error.\n");
|
||||
av_packet_unref(input->in_packet);
|
||||
return NULL;
|
||||
}
|
||||
sws_scale(input->img_convert_ctx, (const unsigned char* const*)input->pFrame->data, input->pFrame->linesize, 0, input->pCodecCtx->height, input->pFrameYUV->data, input->pFrameYUV->linesize);
|
||||
input->pFrameYUV->pts=input->next_pts++;
|
||||
ret_frame= input->pFrameYUV;
|
||||
}
|
||||
av_packet_unref(input->in_packet);
|
||||
}
|
||||
|
||||
finish = clock();// 设置结束clock
|
||||
double duration = (double)(finish - start) / CLOCKS_PER_SEC;//转换浮点型
|
||||
// printf( "采集视频帧时间:%lf seconds\n", duration );
|
||||
|
||||
return ret_frame;
|
||||
}
|
||||
//
|
||||
//static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt)
|
||||
//{
|
||||
// int ret;
|
||||
//
|
||||
// /* send the frame to the encoder */
|
||||
// if (frame)
|
||||
// printf("Send frame %3"PRId64"\n", frame->pts);
|
||||
//
|
||||
// ret = avcodec_send_frame(enc_ctx, frame);//返回-21?????????????????????????????????????????????
|
||||
// if (ret < 0) {
|
||||
// fprintf(stderr, "Error sending a frame for encoding\n");
|
||||
// exit(1);
|
||||
// }
|
||||
//
|
||||
// while (ret >= 0) {
|
||||
// ret = avcodec_receive_packet(enc_ctx, pkt);
|
||||
// if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
|
||||
// return;
|
||||
// else if (ret < 0) {
|
||||
// fprintf(stderr, "Error during encoding\n");
|
||||
// exit(1);
|
||||
// }
|
||||
//
|
||||
//// printf("Write packet %3"PRId64" (size=%5d)\n", pkt->pts, pkt->size);
|
||||
//// fwrite(pkt->data, 1, pkt->size, outfile);
|
||||
// av_packet_unref(pkt);
|
||||
// }
|
||||
//}
|
||||
|
||||
void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt, char **data, int *datasize)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* send the frame to the encoder */
|
||||
// if (frame)
|
||||
// printf("Send frame %3"PRId64"\n", frame->pts);
|
||||
|
||||
ret = avcodec_send_frame(enc_ctx, frame);//返回-21?????????????????????????????????????????????
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error sending a frame for encoding\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (ret >= 0) {
|
||||
ret = avcodec_receive_packet(enc_ctx, pkt);
|
||||
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
|
||||
{
|
||||
printf("11111111111111111111\n");
|
||||
return;
|
||||
}
|
||||
else if (ret < 0) {
|
||||
fprintf(stderr, "Error during encoding\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// printf("Write packet %3"PRId64" (size=%5d)\n", pkt->pts, pkt->size);
|
||||
// fwrite(pkt->data, 1, pkt->size, outfile);
|
||||
|
||||
//tc
|
||||
char *dataBuffer = calloc(pkt->size, 1);
|
||||
memcpy(dataBuffer,pkt->data,pkt->size);
|
||||
|
||||
*data = dataBuffer;
|
||||
*datasize = pkt->size;
|
||||
|
||||
av_packet_unref(pkt);
|
||||
}
|
||||
printf("22222222222222222\n");
|
||||
}
|
||||
|
||||
char * encode2(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt, int *datasize)
|
||||
{
|
||||
clock_t start,finish;
|
||||
start = clock(); // 设置开始clock
|
||||
|
||||
int ret;
|
||||
char *dataBuffer;
|
||||
|
||||
ret = avcodec_send_frame(enc_ctx, frame);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error sending a frame for encoding\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
while (ret >= 0) {
|
||||
ret = avcodec_receive_packet(enc_ctx, pkt);
|
||||
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
|
||||
{
|
||||
printf("11111111111111111111\n");
|
||||
return NULL;
|
||||
}
|
||||
else if (ret < 0) {
|
||||
fprintf(stderr, "Error during encoding\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// printf("Write packet %3"PRId64" (size=%5d)\n", pkt->pts, pkt->size);
|
||||
// fwrite(pkt->data, 1, pkt->size, outfile);
|
||||
|
||||
//tc
|
||||
dataBuffer = calloc(pkt->size, 1);
|
||||
memcpy(dataBuffer,pkt->data,pkt->size);
|
||||
|
||||
*datasize = pkt->size;
|
||||
|
||||
av_packet_unref(pkt);
|
||||
|
||||
finish = clock();// 设置结束clock
|
||||
double duration = (double)(finish - start) / CLOCKS_PER_SEC;//转换浮点型
|
||||
// printf( "编码视频帧时间:%lf seconds\n", duration );
|
||||
|
||||
return dataBuffer;
|
||||
}
|
||||
}
|
||||
63
samples/sample_c/module_sample/camera_emu/ffmpeg_tc.h
Normal file
63
samples/sample_c/module_sample/camera_emu/ffmpeg_tc.h
Normal file
@ -0,0 +1,63 @@
|
||||
//
|
||||
// Created by tangchao on 2021/11/16.
|
||||
//
|
||||
|
||||
#ifndef PSDK_DEMO_FFMPEG_TC_H
|
||||
#define PSDK_DEMO_FFMPEG_TC_H
|
||||
|
||||
|
||||
//tc开始
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <libavutil/avassert.h>
|
||||
#include <libavutil/channel_layout.h>
|
||||
#include <libavutil/opt.h>
|
||||
#include <libavutil/mathematics.h>
|
||||
#include <libavutil/timestamp.h>
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libswscale/swscale.h>
|
||||
#include <libswresample/swresample.h>
|
||||
#include "libavdevice/avdevice.h"
|
||||
|
||||
#include <libavutil/imgutils.h>
|
||||
|
||||
#include <unistd.h>//usleep
|
||||
|
||||
|
||||
#define STREAM_DURATION 50.0 /*录制视频的持续时间 秒*/
|
||||
#define STREAM_FRAME_RATE 15 /* images/s 这里可以根据摄像头的采集速度来设置帧率 */
|
||||
#define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */
|
||||
#define SCALE_FLAGS SWS_BICUBIC
|
||||
//tc结束
|
||||
|
||||
|
||||
//存放视频的宽度和高度
|
||||
int video_width;
|
||||
int video_height;
|
||||
|
||||
|
||||
typedef struct IntputDev
|
||||
{
|
||||
AVCodecContext *pCodecCtx;
|
||||
AVCodec *pCodec;
|
||||
AVFormatContext *v_ifmtCtx;
|
||||
int videoindex;
|
||||
struct SwsContext *img_convert_ctx;
|
||||
AVPacket *in_packet;
|
||||
AVFrame *pFrame,*pFrameYUV;
|
||||
|
||||
/*下一帧的点数*/
|
||||
int64_t next_pts;
|
||||
}IntputDev;
|
||||
|
||||
char *getsystemtime();
|
||||
AVFrame *get_video_frame(IntputDev* input);
|
||||
//static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt);
|
||||
void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt, char **data, int *datasize);
|
||||
char * encode2(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt, int *datasize);
|
||||
|
||||
#endif //PSDK_DEMO_FFMPEG_TC_H
|
||||
@ -92,6 +92,8 @@ static T_DjiReturnCode DjiPlayback_GetFrameRateOfVideoFile(const char *path, flo
|
||||
static T_DjiReturnCode
|
||||
DjiPlayback_GetFrameNumberByTime(T_TestPayloadCameraVideoFrameInfo *frameInfo, uint32_t frameCount,
|
||||
uint32_t *frameNumber, uint32_t timeMs);
|
||||
|
||||
//用于s_psdkCameraMedia中的回调函数:相机类负载设备的下载回放功能
|
||||
static T_DjiReturnCode GetMediaFileDir(char *dirPath);
|
||||
static T_DjiReturnCode GetMediaFileOriginData(const char *filePath, uint32_t offset, uint32_t length,
|
||||
uint8_t *data);
|
||||
@ -120,12 +122,13 @@ static T_DjiReturnCode StartDownloadNotification(void);
|
||||
static T_DjiReturnCode StopDownloadNotification(void);
|
||||
|
||||
_Noreturn static void *UserCameraMedia_SendVideoTask(void *arg);
|
||||
static void *UserCameraMedia_SendVideoTask_tc(void *arg);
|
||||
|
||||
/* Private variables -------------------------------------------------------------*/
|
||||
static T_DjiCameraMediaDownloadPlaybackHandler s_psdkCameraMedia = {0};
|
||||
static T_DjiPlaybackInfo s_playbackInfo = {0};
|
||||
static T_DjiCameraMediaDownloadPlaybackHandler s_psdkCameraMedia = {0};//控制相机类负载设备执行媒体文件下载回放功能
|
||||
static T_DjiPlaybackInfo s_playbackInfo = {0};//非常重要的变量!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
||||
static T_DjiTaskHandle s_userSendVideoThread;
|
||||
static T_UtilBuffer s_mediaPlayCommandBufferHandler = {0};
|
||||
static T_UtilBuffer s_mediaPlayCommandBufferHandler = {0};//非常重要的变量,用户自定义功能读取此变量中的命令执行相应的操作!!!!!!!!!!!!!!!!!!!
|
||||
static T_DjiMutexHandle s_mediaPlayCommandBufferMutex = {0};
|
||||
static uint8_t s_mediaPlayCommandBuffer[sizeof(T_TestPayloadCameraPlaybackCommand) * 32] = {0};
|
||||
static const char *s_frameKeyChar = "[PACKET]";
|
||||
@ -152,30 +155,36 @@ T_DjiReturnCode DjiTest_CameraEmuMediaStartService(void)
|
||||
return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
|
||||
}
|
||||
|
||||
// 实现获取媒体文件信息的功能
|
||||
s_psdkCameraMedia.GetMediaFileDir = GetMediaFileDir;
|
||||
s_psdkCameraMedia.GetMediaFileOriginInfo = DjiTest_CameraMediaGetFileInfo;
|
||||
s_psdkCameraMedia.GetMediaFileOriginData = GetMediaFileOriginData;
|
||||
s_psdkCameraMedia.GetMediaFileOriginInfo = DjiTest_CameraMediaGetFileInfo;//非常重要!!!!!获取视频文件信息(类型、帧率、分辨率等)
|
||||
s_psdkCameraMedia.GetMediaFileOriginData = GetMediaFileOriginData;//获取视频文件数据
|
||||
|
||||
// 实现获取媒体文件缩略图的功能
|
||||
s_psdkCameraMedia.CreateMediaFileThumbNail = CreateMediaFileThumbNail;
|
||||
s_psdkCameraMedia.GetMediaFileThumbNailInfo = GetMediaFileThumbNailInfo;
|
||||
s_psdkCameraMedia.GetMediaFileThumbNailData = GetMediaFileThumbNailData;
|
||||
s_psdkCameraMedia.DestroyMediaFileThumbNail = DestroyMediaFileThumbNail;
|
||||
|
||||
// 实现获取媒体文件截屏图的功能
|
||||
s_psdkCameraMedia.CreateMediaFileScreenNail = CreateMediaFileScreenNail;
|
||||
s_psdkCameraMedia.GetMediaFileScreenNailInfo = GetMediaFileScreenNailInfo;
|
||||
s_psdkCameraMedia.GetMediaFileScreenNailData = GetMediaFileScreenNailData;
|
||||
s_psdkCameraMedia.DestroyMediaFileScreenNail = DestroyMediaFileScreenNail;
|
||||
|
||||
// 实现删除媒体文件的功能
|
||||
s_psdkCameraMedia.DeleteMediaFile = DeleteMediaFile;
|
||||
|
||||
// 实现控制媒体文件回放的功能
|
||||
s_psdkCameraMedia.SetMediaPlaybackFile = SetMediaPlaybackFile;
|
||||
|
||||
s_psdkCameraMedia.StartMediaPlayback = StartMediaPlayback;
|
||||
s_psdkCameraMedia.StopMediaPlayback = StopMediaPlayback;
|
||||
s_psdkCameraMedia.PauseMediaPlayback = PauseMediaPlayback;
|
||||
s_psdkCameraMedia.StartMediaPlayback = StartMediaPlayback;//主要作用是将命令写入到s_mediaPlayCommandBufferHandler
|
||||
s_psdkCameraMedia.StopMediaPlayback = StopMediaPlayback;//主要作用是将命令写入到s_mediaPlayCommandBufferHandler
|
||||
s_psdkCameraMedia.PauseMediaPlayback = PauseMediaPlayback;//主要作用是将命令写入到s_mediaPlayCommandBufferHandler
|
||||
s_psdkCameraMedia.SeekMediaPlayback = SeekMediaPlayback;
|
||||
s_psdkCameraMedia.GetMediaPlaybackStatus = GetMediaPlaybackStatus;
|
||||
|
||||
// 实现下载媒体文件的功能
|
||||
s_psdkCameraMedia.StartDownloadNotification = StartDownloadNotification;
|
||||
s_psdkCameraMedia.StopDownloadNotification = StopDownloadNotification;
|
||||
|
||||
@ -186,6 +195,7 @@ T_DjiReturnCode DjiTest_CameraEmuMediaStartService(void)
|
||||
|
||||
UtilBuffer_Init(&s_mediaPlayCommandBufferHandler, s_mediaPlayCommandBuffer, sizeof(s_mediaPlayCommandBuffer));
|
||||
|
||||
// 注册相机类负载设备的下载回放功能
|
||||
if (aircraftInfoBaseInfo.aircraftType == DJI_AIRCRAFT_TYPE_M300_RTK ||
|
||||
aircraftInfoBaseInfo.aircraftType == DJI_AIRCRAFT_TYPE_M350_RTK) {
|
||||
returnCode = DjiPayloadCamera_RegMediaDownloadPlaybackHandler(&s_psdkCameraMedia);
|
||||
@ -201,14 +211,15 @@ T_DjiReturnCode DjiTest_CameraEmuMediaStartService(void)
|
||||
return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
|
||||
}
|
||||
|
||||
if (DjiPlatform_GetHalNetworkHandler() != NULL || DjiPlatform_GetHalUsbBulkHandler() != NULL) {
|
||||
returnCode = osalHandler->TaskCreate("user_camera_media_task", UserCameraMedia_SendVideoTask, 2048,
|
||||
NULL, &s_userSendVideoThread);
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("user send video task create error.");
|
||||
return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
||||
}
|
||||
}
|
||||
// 创建线程执行用户自定义函数
|
||||
// if (DjiPlatform_GetHalNetworkHandler() != NULL || DjiPlatform_GetHalUsbBulkHandler() != NULL) {
|
||||
// returnCode = osalHandler->TaskCreate("user_camera_media_task", UserCameraMedia_SendVideoTask_tc, 2048,
|
||||
// NULL, &s_userSendVideoThread);
|
||||
// if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
// USER_LOG_ERROR("user send video task create error.");
|
||||
// return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
||||
// }
|
||||
// }
|
||||
|
||||
return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
||||
}
|
||||
@ -227,7 +238,7 @@ T_DjiReturnCode DjiTest_CameraMediaGetFileInfo(const char *filePath, T_DjiCamera
|
||||
T_DjiReturnCode returnCode;
|
||||
T_DjiMediaFileHandle mediaFileHandle;
|
||||
|
||||
returnCode = DjiMediaFile_CreateHandle(filePath, &mediaFileHandle);
|
||||
returnCode = DjiMediaFile_CreateHandle(filePath, &mediaFileHandle);//mediaFileHandle是重点!!!!其中注册了很多处理媒体文件的函数
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("Media file create handle error stat:0x%08llX", returnCode);
|
||||
return returnCode;
|
||||
@ -252,7 +263,7 @@ T_DjiReturnCode DjiTest_CameraMediaGetFileInfo(const char *filePath, T_DjiCamera
|
||||
}
|
||||
|
||||
out:
|
||||
returnCode = DjiMediaFile_DestroyHandle(mediaFileHandle);
|
||||
returnCode = DjiMediaFile_DestroyHandle(mediaFileHandle);//释放内存空间
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("Media file destroy handle error stat:0x%08llX", returnCode);
|
||||
return returnCode;
|
||||
@ -291,6 +302,7 @@ static T_DjiReturnCode DjiPlayback_PausePlay(T_DjiPlaybackInfo *playbackInfo)
|
||||
return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
|
||||
}
|
||||
|
||||
//内存空间>=一个命令???????????????????????????????????????????????????????????????????????????
|
||||
if (UtilBuffer_GetUnusedSize(&s_mediaPlayCommandBufferHandler) >= sizeof(T_TestPayloadCameraPlaybackCommand)) {
|
||||
UtilBuffer_Put(&s_mediaPlayCommandBufferHandler, (const uint8_t *) &playbackCommand,
|
||||
sizeof(T_TestPayloadCameraPlaybackCommand));
|
||||
@ -336,12 +348,14 @@ static T_DjiReturnCode DjiPlayback_SeekPlay(T_DjiPlaybackInfo *playbackInfo, uin
|
||||
T_DjiRunTimeStamps ti;
|
||||
T_DjiReturnCode returnCode;
|
||||
|
||||
//先暂停播放
|
||||
returnCode = DjiPlayback_PausePlay(playbackInfo);
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("pause play error \n");
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
//将需要播放的位置写入到变量playbackInfo中
|
||||
playbackInfo->playPosMs = seekPos;
|
||||
returnCode = DjiPlayback_StartPlayProcess(playbackInfo->filePath, playbackInfo->playPosMs);
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
@ -545,6 +559,7 @@ static T_DjiReturnCode DjiPlayback_VideoFileTranscode(const char *inPath, const
|
||||
snprintf(ffmpegCmdStr, FFMPEG_CMD_BUF_SIZE,
|
||||
"echo \"y\" | ffmpeg -i \"%s\" -codec copy -f \"%s\" \"%s\" 1>/dev/null 2>&1", inPath,
|
||||
outFormat, outPath);
|
||||
// printf(ffmpegCmdStr);
|
||||
fpCommand = popen(ffmpegCmdStr, "r");
|
||||
if (fpCommand == NULL) {
|
||||
USER_LOG_ERROR("execute transcode command fail.");
|
||||
@ -620,6 +635,7 @@ DjiPlayback_GetFrameInfoOfVideoFile(const char *path, T_TestPayloadCameraVideoFr
|
||||
goto out1;
|
||||
}
|
||||
|
||||
//%%表示这里就是一个“%”符,让程序不要理解成格式符
|
||||
ret = snprintf(frameParameterFormat, sizeof(frameParameterFormat), "%s=%%f", s_frameDurationTimeKeyChar);
|
||||
if (ret < 0) {
|
||||
USER_LOG_ERROR("snprintf frameParameterFormat fail.");
|
||||
@ -627,6 +643,7 @@ DjiPlayback_GetFrameInfoOfVideoFile(const char *path, T_TestPayloadCameraVideoFr
|
||||
goto out1;
|
||||
}
|
||||
|
||||
//将DurationTime从frameDurationTimeLocation读入到frameDurationTimeS
|
||||
ret = sscanf(frameDurationTimeLocation, frameParameterFormat, &frameDurationTimeS);
|
||||
if (ret <= 0) {
|
||||
USER_LOG_ERROR("can not find pkt_duration_time.");
|
||||
@ -681,7 +698,7 @@ DjiPlayback_GetFrameInfoOfVideoFile(const char *path, T_TestPayloadCameraVideoFr
|
||||
}
|
||||
frameInfo[frameNumber].size = frameSize;
|
||||
|
||||
frameLocation += strlen(s_frameKeyChar);
|
||||
frameLocation += strlen(s_frameKeyChar);//排除已经找到的帧
|
||||
frameNumber++;
|
||||
(*frameCount)++;
|
||||
|
||||
@ -1020,6 +1037,7 @@ static T_DjiReturnCode SetMediaPlaybackFile(const char *filePath)
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
//设置完成回放文件后,就开始回放(播放回放文件)
|
||||
returnCode = DjiPlayback_StartPlay(&s_playbackInfo);
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
return returnCode;
|
||||
@ -1033,7 +1051,7 @@ static T_DjiReturnCode StartMediaPlayback(void)
|
||||
T_DjiReturnCode returnCode;
|
||||
|
||||
USER_LOG_INFO("start media playback");
|
||||
returnCode = DjiPlayback_StartPlay(&s_playbackInfo);
|
||||
returnCode = DjiPlayback_StartPlay(&s_playbackInfo);//s_playbackInfo是哪里设置的????????????????????
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("start media playback status error, stat:0x%08llX", returnCode);
|
||||
return returnCode;
|
||||
@ -1149,6 +1167,7 @@ static T_DjiReturnCode StopDownloadNotification(void)
|
||||
#pragma GCC diagnostic ignored "-Wreturn-type"
|
||||
#endif
|
||||
|
||||
//https://developer.dji.com/doc/payload-sdk-tutorial/cn/function-set/advanced-function/camera-video-stream-transmission.html
|
||||
static void *UserCameraMedia_SendVideoTask(void *arg)
|
||||
{
|
||||
int ret;
|
||||
@ -1159,12 +1178,12 @@ static void *UserCameraMedia_SendVideoTask(void *arg)
|
||||
uint16_t lengthOfDataToBeSent = 0;
|
||||
int lengthOfDataHaveBeenSent = 0;
|
||||
char *dataBuffer = NULL;
|
||||
T_TestPayloadCameraPlaybackCommand playbackCommand = {0};
|
||||
T_TestPayloadCameraPlaybackCommand playbackCommand = {0};//??????????????????????
|
||||
uint16_t bufferReadSize = 0;
|
||||
char *videoFilePath = NULL;
|
||||
char *transcodedFilePath = NULL;
|
||||
char *transcodedFilePath = NULL;//转换视频编码后的文件路径
|
||||
float frameRate = 1.0f;
|
||||
T_TestPayloadCameraVideoFrameInfo *frameInfo = NULL;
|
||||
T_TestPayloadCameraVideoFrameInfo *frameInfo = NULL;//时长,大小,此帧在文件中的位置
|
||||
uint32_t frameNumber = 0;
|
||||
uint32_t frameCount = 0;
|
||||
uint32_t startTimeMs = 0;
|
||||
@ -1180,6 +1199,7 @@ static void *UserCameraMedia_SendVideoTask(void *arg)
|
||||
|
||||
USER_UTIL_UNUSED(arg);
|
||||
|
||||
//获取视频流文件信息(1)
|
||||
returnCode = DjiUserUtil_GetCurrentFileDirPath(__FILE__, DJI_FILE_PATH_SIZE_MAX, curFileDirPath);
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("Get file current path error, stat = 0x%08llX", returnCode);
|
||||
@ -1191,6 +1211,7 @@ static void *UserCameraMedia_SendVideoTask(void *arg)
|
||||
snprintf(tempPath, DJI_FILE_PATH_SIZE_MAX, "%smedia_file/PSDK_0005.h264", curFileDirPath);
|
||||
}
|
||||
|
||||
//使用PSDK 开发的相机类负载设备在创建视频流处理线程后,需要先初始化线程状态并向相机类负载设备申请用于缓存视频流文件的内存空间。
|
||||
videoFilePath = osalHandler->Malloc(DJI_FILE_PATH_SIZE_MAX);
|
||||
if (videoFilePath == NULL) {
|
||||
USER_LOG_ERROR("malloc memory for video file path fail.");
|
||||
@ -1210,6 +1231,7 @@ static void *UserCameraMedia_SendVideoTask(void *arg)
|
||||
}
|
||||
memset(frameInfo, 0, VIDEO_FRAME_MAX_COUNT * sizeof(T_TestPayloadCameraVideoFrameInfo));
|
||||
|
||||
//???????????????????????????????????????????????????????????????
|
||||
returnCode = DjiPlayback_StopPlayProcess();
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("stop playback and start liveview error: 0x%08llX.", returnCode);
|
||||
@ -1225,6 +1247,7 @@ static void *UserCameraMedia_SendVideoTask(void *arg)
|
||||
continue;
|
||||
}
|
||||
|
||||
//将参数从s_mediaPlayCommandBufferHandler拷贝到playbackCommand
|
||||
bufferReadSize = UtilBuffer_Get(&s_mediaPlayCommandBufferHandler, (uint8_t *) &playbackCommand,
|
||||
sizeof(T_TestPayloadCameraPlaybackCommand));
|
||||
|
||||
@ -1233,10 +1256,10 @@ static void *UserCameraMedia_SendVideoTask(void *arg)
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bufferReadSize != sizeof(T_TestPayloadCameraPlaybackCommand))
|
||||
if (bufferReadSize != sizeof(T_TestPayloadCameraPlaybackCommand))//?????????????????????????????
|
||||
goto send;
|
||||
|
||||
switch (playbackCommand.command) {
|
||||
switch (playbackCommand.command) {//测试开机后不做任何操作的情况下,这个command是什么类型
|
||||
case TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_STOP:
|
||||
snprintf(videoFilePath, DJI_FILE_PATH_SIZE_MAX, "%s", tempPath);
|
||||
startTimeMs = 0;
|
||||
@ -1259,6 +1282,9 @@ static void *UserCameraMedia_SendVideoTask(void *arg)
|
||||
}
|
||||
|
||||
// video send preprocess
|
||||
//获取视频流文件信息(2)
|
||||
//获取H.264 文件的信息
|
||||
//???????????????????????????????????????????????????????
|
||||
returnCode = DjiPlayback_VideoFileTranscode(videoFilePath, "h264", transcodedFilePath,
|
||||
DJI_FILE_PATH_SIZE_MAX);
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
@ -1272,6 +1298,7 @@ static void *UserCameraMedia_SendVideoTask(void *arg)
|
||||
continue;
|
||||
}
|
||||
|
||||
//????????????????????????????????????????????????????????????????????
|
||||
returnCode = DjiPlayback_GetFrameInfoOfVideoFile(transcodedFilePath, frameInfo, VIDEO_FRAME_MAX_COUNT,
|
||||
&frameCount);
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
@ -1280,7 +1307,7 @@ static void *UserCameraMedia_SendVideoTask(void *arg)
|
||||
}
|
||||
|
||||
returnCode = DjiPlayback_GetFrameNumberByTime(frameInfo, frameCount, &frameNumber,
|
||||
startTimeMs);
|
||||
startTimeMs);//获取指定时间所在帧的位置(帧号)
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("get start frame number error: 0x%08llX.", returnCode);
|
||||
continue;
|
||||
@ -1289,15 +1316,15 @@ static void *UserCameraMedia_SendVideoTask(void *arg)
|
||||
if (fpFile != NULL)
|
||||
fclose(fpFile);
|
||||
|
||||
fpFile = fopen(transcodedFilePath, "rb+");
|
||||
fpFile = fopen(transcodedFilePath, "rb+");//打开编码后的文件
|
||||
if (fpFile == NULL) {
|
||||
USER_LOG_ERROR("open video file fail.");
|
||||
USER_LOG_ERROR("open video file fail.111111111111111111111111");
|
||||
continue;
|
||||
}
|
||||
|
||||
send:
|
||||
if (fpFile == NULL) {
|
||||
USER_LOG_ERROR("open video file fail.");
|
||||
USER_LOG_ERROR("open video file fail.222222222222222222222222222");
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -1314,14 +1341,19 @@ send:
|
||||
continue;
|
||||
}
|
||||
|
||||
//????????????????????????????????
|
||||
if (mode == DJI_CAMERA_MODE_PLAYBACK && s_playbackInfo.isInPlayProcess == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//????????????????????????????????
|
||||
if (!USER_UTIL_IS_WORK_TURN(sendVideoStep++, frameRate, SEND_VIDEO_TASK_FREQ))
|
||||
continue;
|
||||
|
||||
frameBufSize = frameInfo[frameNumber].size;
|
||||
|
||||
//3. 解析视频流文件
|
||||
//基于PSDK 开发的相机类负载设备获取视频流文件的信息后,将解析视频流文件的内容,识别视频流文件的帧头。
|
||||
frameBufSize = frameInfo[frameNumber].size;//这行几行代码的意思:每一帧的大小不一样
|
||||
if (videoStreamType == DJI_CAMERA_VIDEO_STREAM_TYPE_H264_DJI_FORMAT) {
|
||||
frameBufSize = frameBufSize + VIDEO_FRAME_AUD_LEN;
|
||||
}
|
||||
@ -1345,11 +1377,21 @@ send:
|
||||
USER_LOG_DEBUG("read data from video file success, len = %d B\r\n", dataLength);
|
||||
}
|
||||
|
||||
//4. 发送视频流数据
|
||||
//基于PSDK 开发的相机类负载设备在解析视频流文件并识别视频流文件的帧头后,调用视频流发送接口PsdkPayloadCamera_SendVideoStream,
|
||||
//以逐帧的方式发送视频流数据。若视频流格式为DJI H264格式,需要在每一帧的最后增加AUD信息,用于标识一帧的结束。
|
||||
if (videoStreamType == DJI_CAMERA_VIDEO_STREAM_TYPE_H264_DJI_FORMAT) {
|
||||
memcpy(&dataBuffer[frameInfo[frameNumber].size], s_frameAudInfo, VIDEO_FRAME_AUD_LEN);
|
||||
dataLength = dataLength + VIDEO_FRAME_AUD_LEN;
|
||||
}
|
||||
|
||||
// for(int i=0;i<dataLength - VIDEO_FRAME_AUD_LEN;i++)
|
||||
// {
|
||||
//// printf("%c",data[i]);
|
||||
// printf("%02X ",dataBuffer[i]);
|
||||
// }
|
||||
// printf("\n");
|
||||
|
||||
lengthOfDataHaveBeenSent = 0;
|
||||
while (dataLength - lengthOfDataHaveBeenSent) {
|
||||
lengthOfDataToBeSent = USER_UTIL_MIN(DATA_SEND_FROM_VIDEO_STREAM_MAX_LEN,
|
||||
@ -1370,6 +1412,8 @@ send:
|
||||
sendVideoFlag = false;
|
||||
}
|
||||
|
||||
//5. 获取视频流状态
|
||||
//使用PSDK 开发的相机类负载设备能够获取视频流发送的实时状态,方便用户调整视频流的码率,确保图传画面的稳定显示。
|
||||
returnCode = DjiPayloadCamera_GetVideoStreamState(&videoStreamState);
|
||||
if (returnCode == DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_DEBUG(
|
||||
@ -1386,6 +1430,457 @@ free:
|
||||
}
|
||||
}
|
||||
|
||||
static void *UserCameraMedia_SendVideoTask_tc(void *arg)
|
||||
{
|
||||
int ret;
|
||||
T_DjiReturnCode returnCode;
|
||||
static uint32_t sendVideoStep = 0;
|
||||
FILE *fpFile = NULL;
|
||||
unsigned long dataLength = 0;
|
||||
uint16_t lengthOfDataToBeSent = 0;
|
||||
int lengthOfDataHaveBeenSent = 0;
|
||||
char *dataBuffer = NULL;
|
||||
T_TestPayloadCameraPlaybackCommand playbackCommand = {0};//??????????????????????
|
||||
uint16_t bufferReadSize = 0;
|
||||
char *videoFilePath = NULL;
|
||||
char *transcodedFilePath = NULL;//转换视频编码后的文件路径
|
||||
float frameRate = 1.0f;
|
||||
T_TestPayloadCameraVideoFrameInfo *frameInfo = NULL;//时长,大小,此帧在文件中的位置
|
||||
uint32_t frameNumber = 0;
|
||||
uint32_t frameCount = 0;
|
||||
uint32_t startTimeMs = 0;
|
||||
bool sendVideoFlag = true;
|
||||
bool sendOneTimeFlag = false;
|
||||
T_DjiDataChannelState videoStreamState = {0};
|
||||
E_DjiCameraMode mode = DJI_CAMERA_MODE_SHOOT_PHOTO;
|
||||
T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
|
||||
uint32_t frameBufSize = 0;
|
||||
E_DjiCameraVideoStreamType videoStreamType;
|
||||
char curFileDirPath[DJI_FILE_PATH_SIZE_MAX];
|
||||
char tempPath[DJI_FILE_PATH_SIZE_MAX];
|
||||
|
||||
USER_UTIL_UNUSED(arg);
|
||||
|
||||
//获取视频流文件信息(1)
|
||||
returnCode = DjiUserUtil_GetCurrentFileDirPath(__FILE__, DJI_FILE_PATH_SIZE_MAX, curFileDirPath);
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("Get file current path error, stat = 0x%08llX", returnCode);
|
||||
exit(1);
|
||||
}
|
||||
if (s_isMediaFileDirPathConfigured == true) {
|
||||
snprintf(tempPath, DJI_FILE_PATH_SIZE_MAX, "%sPSDK_0005.h264", s_mediaFileDirPath);
|
||||
} else {
|
||||
snprintf(tempPath, DJI_FILE_PATH_SIZE_MAX, "%smedia_file/PSDK_0005.h264", curFileDirPath);
|
||||
}
|
||||
|
||||
//使用PSDK 开发的相机类负载设备在创建视频流处理线程后,需要先初始化线程状态并向相机类负载设备申请用于缓存视频流文件的内存空间。
|
||||
videoFilePath = osalHandler->Malloc(DJI_FILE_PATH_SIZE_MAX);
|
||||
if (videoFilePath == NULL) {
|
||||
USER_LOG_ERROR("malloc memory for video file path fail.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
transcodedFilePath = osalHandler->Malloc(DJI_FILE_PATH_SIZE_MAX);
|
||||
if (transcodedFilePath == NULL) {
|
||||
USER_LOG_ERROR("malloc memory for transcoded file path fail.");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
frameInfo = osalHandler->Malloc(VIDEO_FRAME_MAX_COUNT * sizeof(T_TestPayloadCameraVideoFrameInfo));
|
||||
if (frameInfo == NULL) {
|
||||
USER_LOG_ERROR("malloc memory for frame info fail.");
|
||||
exit(1);
|
||||
}
|
||||
memset(frameInfo, 0, VIDEO_FRAME_MAX_COUNT * sizeof(T_TestPayloadCameraVideoFrameInfo));
|
||||
|
||||
//???????????????????????????????????????????????????????????????
|
||||
returnCode = DjiPlayback_StopPlayProcess();
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("stop playback and start liveview error: 0x%08llX.", returnCode);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*tc111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111*/
|
||||
// int ret;
|
||||
int have_video = 0, have_audio = 0;
|
||||
int encode_video = 0, encode_audio = 0;
|
||||
AVDictionary *opt = NULL;
|
||||
int i;
|
||||
|
||||
/*添加摄像头******************************************************************************************************************************/
|
||||
|
||||
char *dev_name = "/dev/video10";
|
||||
|
||||
//输入文件格式
|
||||
AVFormatContext *v_ifmtCtx;
|
||||
v_ifmtCtx = avformat_alloc_context();
|
||||
|
||||
AVInputFormat *ifmt=av_find_input_format("video4linux2");
|
||||
|
||||
avdevice_register_all();
|
||||
|
||||
ret = avformat_open_input(&v_ifmtCtx, dev_name, ifmt, NULL);//根据摄像头名字(dev_name)和格式(ifmt) 打开流(摄像头,v_ifmtCtx)
|
||||
if(ret!=0)
|
||||
{
|
||||
printf("无法打开摄像头输入流:%d\n",ret);
|
||||
return -1;
|
||||
}
|
||||
// printf("摄像头输入流的封装格式为:%s\n",ifmt->name);//因为ifmt=null,所以此行代码出现段错误
|
||||
|
||||
//input video initialize
|
||||
if(avformat_find_stream_info(v_ifmtCtx,NULL)<0)//获取流(摄像头)的信息
|
||||
{
|
||||
printf("找不到流信息.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int videoindex = -1;
|
||||
for (i = 0; i < v_ifmtCtx->nb_streams; i++)
|
||||
{
|
||||
if (v_ifmtCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
|
||||
{
|
||||
videoindex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(videoindex==-1)
|
||||
{
|
||||
printf("找不到视频流。\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//获取帧率信息
|
||||
int aa = v_ifmtCtx->streams[videoindex]->r_frame_rate.num;
|
||||
int bb = v_ifmtCtx->streams[videoindex]->r_frame_rate.den;
|
||||
double dInputFps = v_ifmtCtx->streams[videoindex]->r_frame_rate.num*1.0 / v_ifmtCtx->streams[videoindex]->r_frame_rate.den;
|
||||
printf("摄像头的帧率%d\n",(int)dInputFps);
|
||||
|
||||
|
||||
//视频流的编解码器
|
||||
AVCodecContext *pCodecCtx;
|
||||
AVCodec *pCodec;
|
||||
|
||||
pCodec=avcodec_find_decoder(v_ifmtCtx->streams[videoindex]->codecpar->codec_id);
|
||||
printf("编码器名字:%%s\n",pCodec->name);
|
||||
|
||||
if(pCodec==NULL)
|
||||
{
|
||||
printf("找不到编解码器。\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// pCodecCtx=v_ifmtCtx->streams[videoindex]->codecpar;//老版api方式,新版放弃
|
||||
// pCodecCtx=avcodec_alloc_context3(NULL);
|
||||
pCodecCtx=avcodec_alloc_context3(pCodec);//tc
|
||||
if (pCodecCtx == NULL)
|
||||
{
|
||||
printf("Could not allocate AVCodecContext\n");
|
||||
return -1;
|
||||
}
|
||||
avcodec_parameters_to_context(pCodecCtx, v_ifmtCtx->streams[videoindex]->codecpar);
|
||||
|
||||
if(avcodec_open2(pCodecCtx, pCodec,NULL)<0)
|
||||
{
|
||||
printf("无法打开编解码器。\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
AVFrame *pFrame,*pFrameYUV;
|
||||
pFrame=av_frame_alloc();
|
||||
pFrameYUV=av_frame_alloc();
|
||||
|
||||
|
||||
|
||||
unsigned char *out_buffer=(unsigned char *)av_malloc(av_image_get_buffer_size(AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height,16));
|
||||
// av_image_fill_arrays((AVPicture *)pFrameYUV->data,(AVPicture *)pFrameYUV->linesize, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height,16);
|
||||
av_image_fill_arrays(pFrameYUV->data,pFrameYUV->linesize, out_buffer, AV_PIX_FMT_YUV420P, pCodecCtx->width, pCodecCtx->height,16);
|
||||
|
||||
video_width=pCodecCtx->width;
|
||||
video_height=pCodecCtx->height;
|
||||
printf("摄像头尺寸(WxH): %d x %d \n",pCodecCtx->width, pCodecCtx->height);
|
||||
|
||||
//tc:
|
||||
pFrameYUV->format = AV_PIX_FMT_YUV420P;
|
||||
pFrameYUV->width = video_width;
|
||||
pFrameYUV->height = video_height;
|
||||
|
||||
struct SwsContext *img_convert_ctx;
|
||||
img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);
|
||||
|
||||
IntputDev video_input={0};
|
||||
|
||||
AVPacket *in_packet=(AVPacket *)av_malloc(sizeof(AVPacket));
|
||||
video_input.img_convert_ctx=img_convert_ctx;
|
||||
video_input.in_packet=in_packet;
|
||||
video_input.pCodecCtx=pCodecCtx;
|
||||
video_input.pCodec=pCodec;
|
||||
video_input.v_ifmtCtx=v_ifmtCtx;
|
||||
video_input.videoindex=videoindex;
|
||||
video_input.pFrame=pFrame;
|
||||
video_input.pFrameYUV=pFrameYUV;
|
||||
|
||||
/*添加摄像头结束*******************************************************************************************************************************************/
|
||||
|
||||
/*添加输出信息*******************************************************************************************************************************************/
|
||||
// if (argc <= 2) {
|
||||
// fprintf(stderr, "Usage: %s <output file> <codec name>\n", argv[0]);//libx264
|
||||
// exit(0);
|
||||
// }
|
||||
const char *filename, *codec_name;
|
||||
const AVCodec *codec;
|
||||
AVCodecContext *c= NULL;
|
||||
// int i, ret, x, y;
|
||||
FILE *f;
|
||||
AVFrame *frame;
|
||||
AVPacket *pkt;
|
||||
|
||||
// filename = argv[1];
|
||||
// codec_name = argv[2];
|
||||
|
||||
filename = "delete.h264";
|
||||
codec_name = "libx264";
|
||||
|
||||
|
||||
|
||||
/* find the mpeg1video encoder */
|
||||
codec = avcodec_find_encoder_by_name(codec_name);
|
||||
if (!codec) {
|
||||
fprintf(stderr, "Codec '%s' not found\n", codec_name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
c = avcodec_alloc_context3(codec);
|
||||
if (!c) {
|
||||
fprintf(stderr, "Could not allocate video codec context\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pkt = av_packet_alloc();
|
||||
if (!pkt)
|
||||
exit(1);
|
||||
|
||||
c->codec_id = codec->id;
|
||||
c->bit_rate = 400000; //平均比特率,例子代码默认值是400000
|
||||
/* 分辨率必须是2的倍数。*/
|
||||
c->width=video_width;
|
||||
c->height=video_height;
|
||||
|
||||
|
||||
/*时基:这是基本的时间单位(以秒为单位)
|
||||
*表示其中的帧时间戳。 对于固定fps内容,
|
||||
*时基应为1 /framerate,时间戳增量应为
|
||||
*等于1。*/
|
||||
c->time_base = (AVRational){1, 15};
|
||||
c->framerate = (AVRational){15, 1};
|
||||
c->gop_size = 15; /* emit one intra frame every twelve frames at most */
|
||||
c->pix_fmt = AV_PIX_FMT_YUV420P;
|
||||
|
||||
c->max_b_frames = 0;
|
||||
av_opt_set(c->priv_data, "tune", "zerolatency", 0);//解决编码延时
|
||||
av_opt_set(c->priv_data, "preset", "superfast", 0);
|
||||
|
||||
|
||||
if(c->codec_id == AV_CODEC_ID_MPEG2VIDEO)
|
||||
{
|
||||
/* 只是为了测试,我们还添加了B帧 */
|
||||
c->max_b_frames = 2;
|
||||
}
|
||||
if(c->codec_id == AV_CODEC_ID_MPEG1VIDEO)
|
||||
{
|
||||
/*需要避免使用其中一些系数溢出的宏块。
|
||||
*普通视频不会发生这种情况,因为
|
||||
*色度平面的运动与亮度平面不匹配。 */
|
||||
c->mb_decision = 2;
|
||||
}
|
||||
|
||||
/* open it */
|
||||
ret = avcodec_open2(c, codec, NULL);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
AVFrame *frame_tmp;
|
||||
char *data;
|
||||
int datasize;
|
||||
clock_t start,finish;
|
||||
/*tc222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222*/
|
||||
|
||||
while (1) {
|
||||
// response playback command
|
||||
if (osalHandler->MutexLock(s_mediaPlayCommandBufferMutex) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("mutex lock error");
|
||||
continue;
|
||||
}
|
||||
|
||||
//将参数从s_mediaPlayCommandBufferHandler拷贝到playbackCommand
|
||||
bufferReadSize = UtilBuffer_Get(&s_mediaPlayCommandBufferHandler, (uint8_t *) &playbackCommand,
|
||||
sizeof(T_TestPayloadCameraPlaybackCommand));
|
||||
|
||||
if (osalHandler->MutexUnlock(s_mediaPlayCommandBufferMutex) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("mutex unlock error");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (bufferReadSize != sizeof(T_TestPayloadCameraPlaybackCommand))//?????????????????????????????
|
||||
goto send;
|
||||
|
||||
//(1)测试开机后不做任何操作的情况下,这个command是什么类型;(2)这个switch有啥用?
|
||||
switch (playbackCommand.command) {
|
||||
case TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_STOP:
|
||||
snprintf(videoFilePath, DJI_FILE_PATH_SIZE_MAX, "%s", tempPath);
|
||||
startTimeMs = 0;
|
||||
sendVideoFlag = true;
|
||||
sendOneTimeFlag = false;
|
||||
break;
|
||||
case TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_PAUSE:
|
||||
sendVideoFlag = false;
|
||||
goto send;
|
||||
case TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_START:
|
||||
snprintf(videoFilePath, DJI_FILE_PATH_SIZE_MAX, "%s", playbackCommand.path);
|
||||
startTimeMs = playbackCommand.timeMs;
|
||||
sendVideoFlag = true;
|
||||
sendOneTimeFlag = true;
|
||||
break;
|
||||
default:
|
||||
USER_LOG_ERROR("playback command invalid: %d.", playbackCommand.command);
|
||||
sendVideoFlag = false;
|
||||
goto send;
|
||||
}
|
||||
|
||||
// video send preprocess
|
||||
//获取视频流文件信息(2)
|
||||
//获取H.264 文件的信息
|
||||
//将输入视频文件(videoFilePath)编码为h264,并写到视频文件中(transcodedFilePath)
|
||||
returnCode = DjiPlayback_VideoFileTranscode(videoFilePath, "h264", transcodedFilePath,
|
||||
DJI_FILE_PATH_SIZE_MAX);
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("transcode video file error: 0x%08llX.", returnCode);
|
||||
continue;
|
||||
}
|
||||
|
||||
returnCode = DjiPlayback_GetFrameRateOfVideoFile(transcodedFilePath, &frameRate);
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("get frame rate of video error: 0x%08llX.", returnCode);
|
||||
continue;
|
||||
}
|
||||
|
||||
//获取每一帧的信息并存入frameInfo,frameCount代表此文件共有多少帧
|
||||
returnCode = DjiPlayback_GetFrameInfoOfVideoFile(transcodedFilePath, frameInfo, VIDEO_FRAME_MAX_COUNT,
|
||||
&frameCount);
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("get frame info of video error: 0x%08llX.", returnCode);
|
||||
continue;
|
||||
}
|
||||
|
||||
//获取指定时间所在帧的位置(帧号)
|
||||
returnCode = DjiPlayback_GetFrameNumberByTime(frameInfo, frameCount, &frameNumber,
|
||||
startTimeMs);
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("get start frame number error: 0x%08llX.", returnCode);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (fpFile != NULL)
|
||||
fclose(fpFile);
|
||||
|
||||
fpFile = fopen(transcodedFilePath, "rb+");//打开编码后的文件
|
||||
if (fpFile == NULL) {
|
||||
USER_LOG_ERROR("open video file fail.111111111111111111111111");
|
||||
continue;
|
||||
}
|
||||
|
||||
send:
|
||||
frame_tmp=get_video_frame(&video_input);
|
||||
|
||||
// encode(c, frame_tmp, pkt, &data, &datasize);
|
||||
data = encode2(c, frame_tmp, pkt, &datasize);
|
||||
|
||||
if(data == NULL)
|
||||
{
|
||||
// printf("编码后数据为空!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
//3. 解析视频流文件
|
||||
//基于PSDK 开发的相机类负载设备获取视频流文件的信息后,将解析视频流文件的内容,识别视频流文件的帧头。
|
||||
frameBufSize = datasize;
|
||||
if (videoStreamType == DJI_CAMERA_VIDEO_STREAM_TYPE_H264_DJI_FORMAT) {
|
||||
frameBufSize = frameBufSize + VIDEO_FRAME_AUD_LEN;
|
||||
}
|
||||
|
||||
dataBuffer = calloc(frameBufSize, 1);
|
||||
if (dataBuffer == NULL) {
|
||||
USER_LOG_ERROR("malloc fail.");
|
||||
goto free;
|
||||
}
|
||||
|
||||
memcpy(dataBuffer,data,datasize);
|
||||
dataLength = datasize;
|
||||
|
||||
|
||||
|
||||
//4. 发送视频流数据
|
||||
//基于PSDK 开发的相机类负载设备在解析视频流文件并识别视频流文件的帧头后,调用视频流发送接口PsdkPayloadCamera_SendVideoStream,
|
||||
//以逐帧的方式发送视频流数据。若视频流格式为DJI H264格式,需要在每一帧的最后增加AUD信息,用于标识一帧的结束。
|
||||
if (videoStreamType == DJI_CAMERA_VIDEO_STREAM_TYPE_H264_DJI_FORMAT) {
|
||||
memcpy(&dataBuffer[datasize], s_frameAudInfo, VIDEO_FRAME_AUD_LEN);
|
||||
dataLength = dataLength + VIDEO_FRAME_AUD_LEN;
|
||||
}
|
||||
|
||||
//tc:将视频帧打印出来
|
||||
// char *deletestr = calloc(dataLength+5,1);
|
||||
// memcpy(deletestr, data, datasize);
|
||||
// printf("正在显示的视频帧:%s\n", deletestr);
|
||||
// free(deletestr);
|
||||
//
|
||||
// for(i=0;i<datasize;i++)
|
||||
// {
|
||||
//// printf("%c",data[i]);
|
||||
// printf("%02X ",data[i]);
|
||||
// }
|
||||
// printf("\n");
|
||||
|
||||
start = clock(); // 设置开始clock
|
||||
|
||||
lengthOfDataHaveBeenSent = 0;
|
||||
while (dataLength - lengthOfDataHaveBeenSent) {
|
||||
lengthOfDataToBeSent = USER_UTIL_MIN(DATA_SEND_FROM_VIDEO_STREAM_MAX_LEN,
|
||||
dataLength - lengthOfDataHaveBeenSent);
|
||||
returnCode = DjiPayloadCamera_SendVideoStream((const uint8_t *) dataBuffer + lengthOfDataHaveBeenSent,
|
||||
lengthOfDataToBeSent);
|
||||
if (returnCode != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("send video stream error: 0x%08llX.", returnCode);
|
||||
}
|
||||
lengthOfDataHaveBeenSent += lengthOfDataToBeSent;
|
||||
}
|
||||
|
||||
finish = clock();// 设置结束clock
|
||||
double duration = (double)(finish - start) / CLOCKS_PER_SEC;//转换浮点型
|
||||
// printf( "发送视频帧时间:%lf seconds\n", duration );
|
||||
|
||||
//5. 获取视频流状态
|
||||
//使用PSDK 开发的相机类负载设备能够获取视频流发送的实时状态,方便用户调整视频流的码率,确保图传画面的稳定显示。
|
||||
returnCode = DjiPayloadCamera_GetVideoStreamState(&videoStreamState);
|
||||
if (returnCode == DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_DEBUG(
|
||||
"video stream state: realtimeBandwidthLimit: %d, realtimeBandwidthBeforeFlowController: %d, realtimeBandwidthAfterFlowController:%d busyState: %d.",
|
||||
videoStreamState.realtimeBandwidthLimit, videoStreamState.realtimeBandwidthBeforeFlowController,
|
||||
videoStreamState.realtimeBandwidthAfterFlowController,
|
||||
videoStreamState.busyState);
|
||||
} else {
|
||||
USER_LOG_ERROR("get video stream state error.");
|
||||
}
|
||||
|
||||
free:
|
||||
free(dataBuffer);
|
||||
free(data);
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __CC_ARM
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
@ -31,6 +31,8 @@
|
||||
#include "dji_typedef.h"
|
||||
#include "dji_payload_camera.h"
|
||||
|
||||
#include "ffmpeg_tc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@ -41,6 +41,9 @@ static void *UserFcSubscription_Task(void *arg);
|
||||
static T_DjiReturnCode DjiTest_FcSubscriptionReceiveQuaternionCallback(const uint8_t *data, uint16_t dataSize,
|
||||
const T_DjiDataTimestamp *timestamp);
|
||||
|
||||
static char* uitoa(unsigned int n, char *s);
|
||||
static int GMT_toLocalTime(unsigned long gmt_time,unsigned int* year,unsigned int* month,unsigned int* day,unsigned int* hour,unsigned int* minute,unsigned int* sec);
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
static T_DjiTaskHandle s_userFcSubscriptionThread;
|
||||
static bool s_userFcSubscriptionDataShow = false;
|
||||
@ -48,6 +51,7 @@ static uint8_t s_totalSatelliteNumberUsed = 0;
|
||||
static uint32_t s_userFcSubscriptionDataCnt = 0;
|
||||
|
||||
/* Exported functions definition ---------------------------------------------*/
|
||||
//要先订阅消息(DjiFcSubscription_SubscribeTopic),才能获取消息(DjiFcSubscription_GetLatestValueOfTopic)
|
||||
T_DjiReturnCode DjiTest_FcSubscriptionStartService(void)
|
||||
{
|
||||
T_DjiReturnCode djiStat;
|
||||
@ -60,6 +64,7 @@ T_DjiReturnCode DjiTest_FcSubscriptionStartService(void)
|
||||
return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
|
||||
}
|
||||
|
||||
//订阅姿态四元数
|
||||
djiStat = DjiFcSubscription_SubscribeTopic(DJI_FC_SUBSCRIPTION_TOPIC_QUATERNION, DJI_DATA_SUBSCRIPTION_TOPIC_50_HZ,
|
||||
DjiTest_FcSubscriptionReceiveQuaternionCallback);
|
||||
if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
@ -69,6 +74,7 @@ T_DjiReturnCode DjiTest_FcSubscriptionStartService(void)
|
||||
USER_LOG_DEBUG("Subscribe topic quaternion success.");
|
||||
}
|
||||
|
||||
//订阅无人机速度
|
||||
djiStat = DjiFcSubscription_SubscribeTopic(DJI_FC_SUBSCRIPTION_TOPIC_VELOCITY, DJI_DATA_SUBSCRIPTION_TOPIC_1_HZ,
|
||||
NULL);
|
||||
if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
@ -96,6 +102,21 @@ T_DjiReturnCode DjiTest_FcSubscriptionStartService(void)
|
||||
USER_LOG_DEBUG("Subscribe topic gps details success.");
|
||||
}
|
||||
|
||||
//订阅gps日期
|
||||
djiStat = DjiFcSubscription_SubscribeTopic(DJI_FC_SUBSCRIPTION_TOPIC_GPS_DATE, 1,NULL);
|
||||
if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("Subscribe topic QUATERNION error.");
|
||||
return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
|
||||
}
|
||||
|
||||
//订阅gps时间
|
||||
djiStat = DjiFcSubscription_SubscribeTopic(DJI_FC_SUBSCRIPTION_TOPIC_GPS_TIME, 1,NULL);
|
||||
if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("Subscribe topic QUATERNION error.");
|
||||
return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
|
||||
}
|
||||
|
||||
//创建用户任务
|
||||
if (osalHandler->TaskCreate("user_subscription_task", UserFcSubscription_Task,
|
||||
FC_SUBSCRIPTION_TASK_STACK_SIZE, NULL, &s_userFcSubscriptionThread) !=
|
||||
DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
@ -248,9 +269,14 @@ static void *UserFcSubscription_Task(void *arg)
|
||||
T_DjiFcSubscriptionGpsDetails gpsDetails = {0};
|
||||
T_DjiOsalHandler *osalHandler = NULL;
|
||||
|
||||
T_DjiFcSubscriptionGpsDate gpsDate={0};
|
||||
T_DjiFcSubscriptionGpsTime gpsTime={0};
|
||||
|
||||
USER_UTIL_UNUSED(arg);
|
||||
osalHandler = DjiPlatform_GetOsalHandler();
|
||||
|
||||
int counter = 0;
|
||||
bool isGetGpsDate_time = true;
|
||||
while (1) {
|
||||
osalHandler->TaskSleepMs(1000 / FC_SUBSCRIPTION_TASK_FREQ);
|
||||
|
||||
@ -295,9 +321,191 @@ static void *UserFcSubscription_Task(void *arg)
|
||||
s_totalSatelliteNumberUsed = gpsDetails.totalSatelliteNumberUsed;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
djiStat = DjiFcSubscription_GetLatestValueOfTopic(DJI_FC_SUBSCRIPTION_TOPIC_GPS_DATE,
|
||||
(uint8_t *) &gpsDate,
|
||||
sizeof(T_DjiFcSubscriptionGpsDate),
|
||||
×tamp);
|
||||
if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("get value of topic gps DATE error.");
|
||||
isGetGpsDate_time = false;
|
||||
} else {
|
||||
USER_LOG_DEBUG("timestamp: millisecond %u microsecond %u.", timestamp.millisecond,
|
||||
timestamp.microsecond);
|
||||
USER_LOG_DEBUG("gps DATE: %d.", gpsDate);
|
||||
}//PsdkLogger_UserLogInfo
|
||||
|
||||
djiStat = DjiFcSubscription_GetLatestValueOfTopic(DJI_FC_SUBSCRIPTION_TOPIC_GPS_TIME,
|
||||
(uint8_t *) &gpsTime,
|
||||
sizeof(T_DjiFcSubscriptionGpsTime),
|
||||
×tamp);
|
||||
if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("get value of topic gps TIME error.");
|
||||
isGetGpsDate_time = false;
|
||||
} else {
|
||||
USER_LOG_DEBUG("gps TIME: %d.", gpsTime);
|
||||
}//PsdkLogger_UserLogInfo
|
||||
|
||||
if(counter>1 &&counter<10 && isGetGpsDate_time)//避免dji的bug:第一次获取的gpsDate和gpsTime都为0
|
||||
{
|
||||
printf("开始设置时间\n");
|
||||
system('date');
|
||||
|
||||
char *gpsDate_str = (char *)malloc(sizeof(char)*50);
|
||||
char *gpsTime_str = (char *)malloc(sizeof(char)*20);
|
||||
|
||||
|
||||
uitoa(gpsDate,gpsDate_str);
|
||||
uitoa(gpsTime,gpsTime_str);
|
||||
strcat(gpsDate_str, gpsTime_str);
|
||||
// printf("pingjie----------------------------------------------:%s\n",gpsDate_str);
|
||||
|
||||
|
||||
char *year = (char *)malloc(sizeof(char)*10);
|
||||
char *mon = (char *)malloc(sizeof(char)*10);
|
||||
char *mday = (char *)malloc(sizeof(char)*10);
|
||||
char *hour = (char *)malloc(sizeof(char)*10);
|
||||
char *min = (char *)malloc(sizeof(char)*10);
|
||||
char *sec = (char *)malloc(sizeof(char)*10);
|
||||
|
||||
strncpy(year, gpsDate_str, 4);
|
||||
strncpy(mon, gpsDate_str+4, 2);
|
||||
strncpy(mday, gpsDate_str+6, 2);
|
||||
if(gpsTime >= 100000)//dji时间格式为hhmmss,但是当时间小于上午10点时,小时位(hh)只有1位:21923(2:19:23);
|
||||
{
|
||||
strncpy(hour, gpsTime_str, 2);
|
||||
strncpy(min, gpsTime_str+2, 2);
|
||||
strncpy(sec, gpsTime_str+4, 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
strncpy(hour, gpsTime_str, 1);
|
||||
strncpy(min, gpsTime_str+1, 2);
|
||||
strncpy(sec, gpsTime_str+3, 2);
|
||||
}
|
||||
|
||||
|
||||
// printf("year:%s\n",year);
|
||||
// printf("mon:%s\n",mon);
|
||||
// printf("mday:%s\n",mday);
|
||||
// printf("hour:%s\n",hour);
|
||||
// printf("min:%s\n",min);
|
||||
// printf("sec:%s\n",sec);
|
||||
|
||||
struct tm info;
|
||||
info.tm_year = atoi(year) - 1900;;
|
||||
info.tm_mon = atoi(mon) - 1;
|
||||
info.tm_mday = atoi(mday);
|
||||
info.tm_hour = atoi(hour) + 8;
|
||||
info.tm_min = atoi(min);
|
||||
info.tm_sec = atoi(sec);
|
||||
info.tm_isdst = -1;
|
||||
|
||||
int gmt_time = mktime(&info);
|
||||
|
||||
LocalTimeInfo LocalTime;
|
||||
|
||||
GMT_toLocalTime(gmt_time,&LocalTime.year,&LocalTime.month,&LocalTime.day,&LocalTime.hour,&LocalTime.minute,&LocalTime.second);
|
||||
// printf("MyLocalTime=%d-%d-%d %d:%d:%d\n",LocalTime.year,LocalTime.month,LocalTime.day,LocalTime.hour,LocalTime.minute,LocalTime.second);
|
||||
|
||||
char *timeParam = (char *)malloc(sizeof(char)*500);
|
||||
sprintf(timeParam,"%d-%d-%d %d:%d:%d",LocalTime.year,LocalTime.month,LocalTime.day,LocalTime.hour,LocalTime.minute,LocalTime.second);
|
||||
// printf("----------: %s",timeParam);
|
||||
|
||||
char *command = (char *)malloc(sizeof(char)*100);
|
||||
|
||||
strcat(command, "date -s \"");
|
||||
strcat(command, timeParam);
|
||||
strcat(command, "\"");
|
||||
|
||||
// printf("command---:%s\n",command);
|
||||
system(command);
|
||||
}
|
||||
counter++;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
char* uitoa(unsigned int n, char *s)
|
||||
{
|
||||
int i, j;
|
||||
i = 0;
|
||||
char buf[20];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
do{
|
||||
buf[i++] = n % 10 + '0';//取下一个数字
|
||||
} while ((n /= 10)>0);//删除该数字
|
||||
i -= 1;
|
||||
for (j = 0; i >= 0; j++, i--)//生成的数字是逆序的,所以要逆序输出
|
||||
s[j] = buf[i];
|
||||
s[j] = '\0';
|
||||
return s;
|
||||
}
|
||||
|
||||
/*格林威治时间就是1970年01月01日00时00分00秒起至现在的总秒数*/
|
||||
/*通过格林威治时间,计算本地时间*/
|
||||
int GMT_toLocalTime(unsigned long gmt_time,unsigned int* year,unsigned int* month,unsigned int* day,unsigned int* hour,unsigned int* minute,unsigned int* sec)
|
||||
{
|
||||
int TIME_ZONE = 8;
|
||||
unsigned long gmtTime = gmt_time + TIME_ZONE * 60 * 60;
|
||||
int leap_years = 0;
|
||||
int month_days[] = {31, 28, 31,30,31, 30,31,31, 30,31,30,31};
|
||||
int i =0;
|
||||
int days;
|
||||
|
||||
*sec = (int)(gmtTime%60);//秒钟数
|
||||
gmtTime = gmtTime/60;//总共有多少分钟
|
||||
|
||||
*minute = (int)(gmtTime%60);
|
||||
gmtTime = gmtTime/60;//总共有多少小时
|
||||
|
||||
*hour = (int)(gmtTime%24);
|
||||
gmtTime = gmtTime/24;//总共有多少天
|
||||
|
||||
//去掉小时分钟秒钟后,转换成从公元元年开始到现在的天数
|
||||
//不包括今天
|
||||
gmtTime += 719162;
|
||||
// 首先不考虑闰年计算年份和天数
|
||||
// 计算年份
|
||||
*year = (int)(gmtTime/365);
|
||||
// days = (从公元元年开始到year的闰年个数 + 当前年份已经度过的天数)除以365后的余数
|
||||
days = (int)(gmtTime%365);
|
||||
while(1)
|
||||
{
|
||||
//总共有多少个闰年,天数要相应的减去这些天数
|
||||
leap_years = (*year)/4 - (*year)/100; //计算普通闰年
|
||||
leap_years += (*year)/400; //加上世纪闰年
|
||||
if(days < leap_years)
|
||||
{
|
||||
days+=365;
|
||||
(*year)--;
|
||||
}else break;
|
||||
}
|
||||
days -= leap_years;
|
||||
(*year)++;
|
||||
days++;
|
||||
//计算今年总共度过了多少秒
|
||||
if(((*year)%4 == 0 && (*year) % 100!=0) || (*year)%400==0) month_days[1] = 29;//今年是闰年,修改二月份为29天
|
||||
*month = 1;
|
||||
for(i=0;i<12;i++)
|
||||
{
|
||||
if(days <= month_days[i])
|
||||
{
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
days -=month_days[i];
|
||||
(*month)++;
|
||||
}
|
||||
}
|
||||
*day =days;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifndef __CC_ARM
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
@ -31,6 +31,20 @@
|
||||
#include "dji_typedef.h"
|
||||
#include "dji_fc_subscription.h"
|
||||
|
||||
#include <malloc.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
typedef struct LocalTimeInformation
|
||||
{
|
||||
unsigned int year;
|
||||
unsigned int month;
|
||||
unsigned int day;
|
||||
unsigned int hour;
|
||||
unsigned int minute;
|
||||
unsigned int second;
|
||||
}LocalTimeInfo;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@ -32,6 +32,10 @@
|
||||
#include "dji_sdk_config.h"
|
||||
#include "file_binary_array_list_en.h"
|
||||
|
||||
//sbg
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
#define WIDGET_DIR_PATH_LEN_MAX (256)
|
||||
#define WIDGET_TASK_STACK_SIZE (2048)
|
||||
@ -45,21 +49,65 @@ static T_DjiReturnCode DjiTestWidget_SetWidgetValue(E_DjiWidgetType widgetType,
|
||||
static T_DjiReturnCode DjiTestWidget_GetWidgetValue(E_DjiWidgetType widgetType, uint32_t index, int32_t *value,
|
||||
void *userData);
|
||||
|
||||
static T_DjiReturnCode PsdkTestWidget_SetWidgetValue_StartRecord(E_DjiWidgetType widgetType, uint32_t index, int32_t value,
|
||||
void *userData);
|
||||
|
||||
static void *PsdkTest_IrisRecordSystemChanged(void *arg);
|
||||
|
||||
/* Private values ------------------------------------------------------------*/
|
||||
static T_DjiTaskHandle s_widgetTestThread;
|
||||
static bool s_isWidgetFileDirPathConfigured = false;
|
||||
static char s_widgetFileDirPath[DJI_FILE_PATH_SIZE_MAX] = {0};
|
||||
|
||||
|
||||
static T_DjiTaskHandle s_widgetSbgThread;
|
||||
static T_DjiTaskHandle s_widgetXimeaThread;
|
||||
|
||||
|
||||
|
||||
int SbgRecordCondition=0;
|
||||
|
||||
static int s_sbgMagState=0;
|
||||
static int s_stateOfXimea=100;
|
||||
static int s_stateOfSbg=0;
|
||||
static int s_stateOfFile=0;
|
||||
|
||||
//0:ximeaAirborneSystem系统未就绪,不可启动;1:ximeaAirborneSystem系统就绪,可以启动;
|
||||
//2:ximeaAirborneSystem系统正在启动;3:ximeaAirborneSystem系统启动成功;4:系统已经关闭,并且不能再次启动;
|
||||
int systemON_Control = 0;
|
||||
|
||||
char s_strUIMessage[100]=" ";
|
||||
static char * s_strStateOfSbg="None";
|
||||
static char * s_strSbgSatelliteCounter="None";
|
||||
static char * s_strSbgAccuracy="None";
|
||||
char XimeaFramerate[100]=" ";
|
||||
char XimeaExposeTime[100]=" ";
|
||||
char XimeaExposeMaxValue[100]=" ";
|
||||
char spectralBin[100]="None";
|
||||
static char * s_strSbgSolutionMode="None";
|
||||
static char * s_strStateOfXimea="None";
|
||||
|
||||
char * s_strPitch="None";
|
||||
char * s_strRoll="None";
|
||||
char * s_strYaw="None";
|
||||
|
||||
static int s_sockfd;
|
||||
static struct sockaddr_in s_server;
|
||||
|
||||
|
||||
static const T_DjiWidgetHandlerListItem s_widgetHandlerList[] = {
|
||||
{0, DJI_WIDGET_TYPE_BUTTON, DjiTestWidget_SetWidgetValue, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{1, DJI_WIDGET_TYPE_LIST, DjiTestWidget_SetWidgetValue, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{2, DJI_WIDGET_TYPE_SWITCH, DjiTestWidget_SetWidgetValue, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{3, DJI_WIDGET_TYPE_SCALE, DjiTestWidget_SetWidgetValue, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{4, DJI_WIDGET_TYPE_BUTTON, DjiTestWidget_SetWidgetValue, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{5, DJI_WIDGET_TYPE_SCALE, DjiTestWidget_SetWidgetValue, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{6, DJI_WIDGET_TYPE_INT_INPUT_BOX, DjiTestWidget_SetWidgetValue, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{7, DJI_WIDGET_TYPE_SWITCH, DjiTestWidget_SetWidgetValue, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{8, DJI_WIDGET_TYPE_LIST, DjiTestWidget_SetWidgetValue, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{0, DJI_WIDGET_TYPE_BUTTON, DjiTestWidget_SetWidgetValue, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{1, DJI_WIDGET_TYPE_LIST, DjiTestWidget_SetWidgetValue, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{2, DJI_WIDGET_TYPE_SWITCH, DjiTestWidget_SetWidgetValue, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{3, DJI_WIDGET_TYPE_SCALE, DjiTestWidget_SetWidgetValue, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{4, DJI_WIDGET_TYPE_BUTTON, DjiTestWidget_SetWidgetValue, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{5, DJI_WIDGET_TYPE_SWITCH, PsdkTestWidget_SetWidgetValue_StartRecord, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{6, DJI_WIDGET_TYPE_INT_INPUT_BOX, PsdkTestWidget_SetWidgetValue_StartRecord, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{7, DJI_WIDGET_TYPE_BUTTON, PsdkTestWidget_SetWidgetValue_StartRecord, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{8, DJI_WIDGET_TYPE_INT_INPUT_BOX, PsdkTestWidget_SetWidgetValue_StartRecord, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{9, DJI_WIDGET_TYPE_SWITCH, PsdkTestWidget_SetWidgetValue_StartRecord, DjiTestWidget_GetWidgetValue, NULL},
|
||||
{10, DJI_WIDGET_TYPE_LIST, PsdkTestWidget_SetWidgetValue_StartRecord, DjiTestWidget_GetWidgetValue, NULL},//PsdkTestWidget_SetWidgetValue
|
||||
{11, DJI_WIDGET_TYPE_LIST, PsdkTestWidget_SetWidgetValue_StartRecord, DjiTestWidget_GetWidgetValue, NULL},
|
||||
};
|
||||
|
||||
static const char *s_widgetTypeNameArray[] = {
|
||||
@ -89,6 +137,9 @@ T_DjiReturnCode DjiTest_WidgetStartService(void)
|
||||
|
||||
#ifdef SYSTEM_ARCH_LINUX
|
||||
//Step 2 : Set UI Config (Linux environment)
|
||||
//获取控件图像和UI配置文件所在文件夹
|
||||
USER_LOG_INFO("验证是否定义了宏PSDK_ARCH_SYS_LINUX:是!--------------------------------------------------------------------------------------------------------------------------");
|
||||
|
||||
char curFileDirPath[WIDGET_DIR_PATH_LEN_MAX];
|
||||
char tempPath[WIDGET_DIR_PATH_LEN_MAX];
|
||||
djiStat = DjiUserUtil_GetCurrentFileDirPath(__FILE__, WIDGET_DIR_PATH_LEN_MAX, curFileDirPath);
|
||||
@ -111,6 +162,7 @@ T_DjiReturnCode DjiTest_WidgetStartService(void)
|
||||
}
|
||||
|
||||
//set ui config for English language
|
||||
//设置系统语言为英文时控件配置文件的路径
|
||||
djiStat = DjiWidget_RegUiConfigByDirPath(DJI_MOBILE_APP_LANGUAGE_ENGLISH,
|
||||
DJI_MOBILE_APP_SCREEN_TYPE_BIG_SCREEN,
|
||||
tempPath);
|
||||
@ -161,6 +213,27 @@ T_DjiReturnCode DjiTest_WidgetStartService(void)
|
||||
return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
|
||||
}
|
||||
|
||||
|
||||
//Step 5 : Run ximea task
|
||||
if (osalHandler->TaskCreate("ximea", PsdkTest_IrisRecordSystemChanged, WIDGET_TASK_STACK_SIZE, NULL,
|
||||
&s_widgetXimeaThread) != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("Psdk widget test task(ximea) create error.");
|
||||
return DJI_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
|
||||
}
|
||||
|
||||
/* tc-----------------------------------------------*/
|
||||
struct hostent *he;
|
||||
he=gethostbyname("127.0.0.1");
|
||||
|
||||
s_sockfd=socket(AF_INET, SOCK_DGRAM,0);
|
||||
|
||||
|
||||
bzero(&s_server,sizeof(s_server));
|
||||
s_server.sin_family = AF_INET;
|
||||
s_server.sin_port = htons(PORT);
|
||||
s_server.sin_addr= *((struct in_addr *)he->h_addr);
|
||||
/* tc-----------------------------------------------*/
|
||||
|
||||
return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
@ -186,6 +259,13 @@ __attribute__((weak)) void DjiTest_WidgetLogAppend(const char *fmt, ...)
|
||||
#endif
|
||||
|
||||
/* Private functions definition-----------------------------------------------*/
|
||||
//在DJI pilot的浮窗上显示系统时间
|
||||
int messageTimeCounter = 0;
|
||||
int messageTimespan = 10;
|
||||
|
||||
int XimeaAirborneSystemSurvival_Counter = 1;
|
||||
int ximeaAirborneSystemSurvivalTime = 0;
|
||||
int ximeaAirborneSystemSurvivalTime_Temp = 0;
|
||||
static void *DjiTest_WidgetTask(void *arg)
|
||||
{
|
||||
char message[DJI_WIDGET_FLOATING_WINDOW_MSG_MAX_LEN];
|
||||
@ -202,7 +282,8 @@ static void *DjiTest_WidgetTask(void *arg)
|
||||
}
|
||||
|
||||
#ifndef USER_FIRMWARE_MAJOR_VERSION
|
||||
snprintf(message, DJI_WIDGET_FLOATING_WINDOW_MSG_MAX_LEN, "System time : %u ms", sysTimeMs);
|
||||
snprintf(message, DJI_WIDGET_FLOATING_WINDOW_MSG_MAX_LEN, "%s\n相机: %s; 惯导: %s;\n卫星: %s; 精度: %s;\n帧率: %s;曝光: %s;max: %s;\nP: %s; R: %s; Y: %s;\n光谱bin: %s;\n",
|
||||
s_strUIMessage, s_strStateOfXimea, s_strStateOfSbg, s_strSbgSatelliteCounter, s_strSbgAccuracy, XimeaFramerate, XimeaExposeTime, XimeaExposeMaxValue, s_strPitch, s_strRoll, s_strYaw, spectralBin);
|
||||
#else
|
||||
snprintf(message, DJI_WIDGET_FLOATING_WINDOW_MSG_MAX_LEN,
|
||||
"System time : %u ms\r\nVersion: v%02d.%02d.%02d.%02d\r\nBuild time: %s %s", sysTimeMs,
|
||||
@ -217,10 +298,279 @@ static void *DjiTest_WidgetTask(void *arg)
|
||||
USER_LOG_ERROR("Floating window show message error, stat = 0x%08llX", djiStat);
|
||||
}
|
||||
|
||||
|
||||
messageTimeCounter++;
|
||||
|
||||
if (messageTimeCounter % messageTimespan == 0)
|
||||
{
|
||||
strcpy(s_strUIMessage," ");
|
||||
}
|
||||
|
||||
//判断ximeaAirborneSystem系统是否存活
|
||||
// if(ximeaAirborneSystemSurvivalTime > 10)
|
||||
// {
|
||||
// if (XimeaAirborneSystemSurvival_Counter % 10 ==0)
|
||||
// {
|
||||
// if (ximeaAirborneSystemSurvivalTime - ximeaAirborneSystemSurvivalTime_Temp == 0)
|
||||
// {
|
||||
// strcpy(s_strUIMessage,"采集系统无响应,请重启!");
|
||||
// messageTimeCounter = 0;
|
||||
// messageTimespan = 10;
|
||||
// }
|
||||
//
|
||||
// XimeaAirborneSystemSurvival_Counter = 1;
|
||||
// ximeaAirborneSystemSurvivalTime_Temp = ximeaAirborneSystemSurvivalTime;
|
||||
// }
|
||||
//
|
||||
// XimeaAirborneSystemSurvival_Counter++;
|
||||
// }
|
||||
|
||||
|
||||
osalHandler->TaskSleepMs(1000);
|
||||
}
|
||||
}
|
||||
|
||||
static void *PsdkTest_IrisRecordSystemChanged(void *arg)//
|
||||
{
|
||||
// FILE * fp;
|
||||
// char buffer[80];
|
||||
// fp = popen("/home/iris-xport/cpp_qtcreator/ximeaImageRecorder-Release/ximeaImageRecorder", "r");ss
|
||||
// fgets(buffer, sizeof(buffer), fp);
|
||||
// printf("%s", buffer);
|
||||
// pclose(fp);
|
||||
|
||||
|
||||
int sockfd;
|
||||
struct sockaddr_in server;
|
||||
struct sockaddr_in client;
|
||||
socklen_t addrlen;
|
||||
int num;
|
||||
char buf[MAXDATASIZE];
|
||||
|
||||
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
|
||||
{
|
||||
perror("Creatingsocket failed.");
|
||||
}
|
||||
|
||||
bzero(&server,sizeof(server));
|
||||
server.sin_family=AF_INET;
|
||||
server.sin_port=htons(PORT+1);
|
||||
server.sin_addr.s_addr= htonl(INADDR_ANY);
|
||||
if(bind(sockfd, (struct sockaddr *)&server, sizeof(server)) == -1)
|
||||
{
|
||||
perror("Bind()error.");
|
||||
}
|
||||
|
||||
addrlen=sizeof(client);
|
||||
while (1)
|
||||
{
|
||||
//printf("PsdkTest_IrisRecordSystemChanged: record system status change! 8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888888\n");
|
||||
|
||||
num =recvfrom(sockfd,buf,MAXDATASIZE,0,(struct sockaddr*)&client,&addrlen);
|
||||
|
||||
if (num < 0)
|
||||
{
|
||||
perror("recvfrom() error\n");
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
buf[num] = '\0';
|
||||
|
||||
printf("You got a message (%s) from client.\n",buf);
|
||||
//printf("You got a message (%s%) from client.\nIt's ip is%s, port is %d.\n",buf,inet_ntoa(client.sin_addr),htons(client.sin_port));
|
||||
|
||||
|
||||
char * result[3];
|
||||
result[0] = strtok( buf, "," );
|
||||
result[1] = strtok( NULL, "," );
|
||||
result[2] = strtok( NULL, "," );
|
||||
|
||||
// printf("result[0]: %s\n", result[0]);
|
||||
// printf("result[1]: %s\n\n", result[1]);
|
||||
// printf("result[2]: %s\n\n", result[2]);
|
||||
|
||||
|
||||
if (strcmp(result[0],"sbg") == 0)
|
||||
{
|
||||
s_stateOfSbg = atoi(result[1]);
|
||||
printf("sbg的状态为: %d\n\n", atoi(result[1]));
|
||||
|
||||
switch (s_stateOfSbg)
|
||||
{
|
||||
case 0:
|
||||
s_strStateOfSbg="未打开";
|
||||
|
||||
if (systemON_Control == 0)
|
||||
{
|
||||
strcpy(s_strUIMessage,"系统已就绪!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 1000;
|
||||
|
||||
systemON_Control = 1;//ximeaAirborneSystem系统一启动就会发送此信息 → 代表采集系统就绪;
|
||||
}
|
||||
|
||||
if (systemON_Control == 3)
|
||||
{
|
||||
strcpy(s_strUIMessage,"数据量过大,采集系统已经停止,请重新上电!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 1000;
|
||||
}
|
||||
|
||||
break;
|
||||
case 1:
|
||||
s_strStateOfSbg="波特率设置失败";
|
||||
break;
|
||||
case 2:
|
||||
s_strStateOfSbg="打开成功";
|
||||
break;
|
||||
case 3:
|
||||
s_strStateOfSbg="采集中";
|
||||
systemON_Control = 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (strcmp(result[0],"Accuracy") == 0)
|
||||
{
|
||||
// printf("惯导定位精度为: %s\n\n", result[1]);
|
||||
|
||||
s_strSbgAccuracy=result[1];
|
||||
s_strSbgSatelliteCounter=result[2];
|
||||
|
||||
ximeaAirborneSystemSurvivalTime++;
|
||||
|
||||
|
||||
// s_sbgMagState = atoi(result[1]);
|
||||
|
||||
// switch (s_sbgMagState)
|
||||
// {
|
||||
// case 0:
|
||||
// s_strSbgAccuracy="false";
|
||||
// break;
|
||||
// case 1:
|
||||
// s_strSbgAccuracy="true";
|
||||
// break;
|
||||
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
else if (strcmp(result[0],"SolutionMode") == 0)
|
||||
{
|
||||
// s_sbgMagState = atoi(result[1]);
|
||||
//
|
||||
// switch (s_sbgMagState)
|
||||
// {
|
||||
// case 0:
|
||||
// s_strSbgSolutionMode="UNINITIALIZED";
|
||||
// break;
|
||||
// case 1:
|
||||
// s_strSbgSolutionMode="VERTICAL_GYRO";
|
||||
// break;
|
||||
// case 2:
|
||||
// s_strSbgSolutionMode="AHRS";
|
||||
// break;
|
||||
// case 3:
|
||||
// s_strSbgSolutionMode="NAV_VELOCITY";
|
||||
// break;
|
||||
// case 4:
|
||||
// s_strSbgSolutionMode="NAV_POSITION";
|
||||
// break;
|
||||
//
|
||||
// default:
|
||||
// break;
|
||||
// }
|
||||
}
|
||||
else if (strcmp(result[0],"ximea") == 0)
|
||||
{
|
||||
s_stateOfXimea = atoi(result[1]);
|
||||
printf("ximea的状态为: %d\n\n", atoi(result[1]));
|
||||
|
||||
switch (s_stateOfXimea)//0-61:ximea官方错误代码;99:发生的ximea官方错误代码,没有处理;100:未打开;101:打开;102:设置帧率;103:自动曝光;104:正在采集;
|
||||
{
|
||||
case 10:
|
||||
s_strStateOfXimea="10";
|
||||
|
||||
strcpy(s_strUIMessage,"相机timeout,请重启!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 200;
|
||||
break;
|
||||
case 11:
|
||||
s_strStateOfXimea="11";
|
||||
|
||||
strcpy(s_strUIMessage,"相机:Invalid arguments supplied!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 200;
|
||||
break;
|
||||
case 57:
|
||||
s_strStateOfXimea="57";
|
||||
|
||||
strcpy(s_strUIMessage,"相机被占用!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 200;
|
||||
break;
|
||||
case 99:
|
||||
s_strStateOfXimea="99";
|
||||
|
||||
strcpy(s_strUIMessage,"相机异常,错误码见日志!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 200;
|
||||
break;
|
||||
case 100:
|
||||
s_strStateOfXimea="未打开";
|
||||
break;
|
||||
case 101:
|
||||
s_strStateOfXimea="打开成功";
|
||||
|
||||
strcpy(s_strUIMessage,"系统启动成功!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 20;
|
||||
|
||||
break;
|
||||
case 102:
|
||||
s_strStateOfXimea="帧率已设置";
|
||||
break;
|
||||
case 103:
|
||||
s_strStateOfXimea="曝光完成";
|
||||
break;
|
||||
case 104:
|
||||
s_strStateOfXimea="正在采集";
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (strcmp(result[0],"XimeaAutoExpose") == 0)
|
||||
{
|
||||
strcpy(XimeaExposeMaxValue, result[1]);
|
||||
strcpy(XimeaExposeTime, result[2]);
|
||||
|
||||
strcpy(s_strUIMessage,"曝光时间设置成功!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10;
|
||||
}
|
||||
else if (strcmp(result[0],"XimeaFrameRate") == 0)
|
||||
{
|
||||
int tmp = atoi(result[1]);
|
||||
sprintf(XimeaFramerate,"%d",tmp);
|
||||
// strcpy(XimeaFramerate,result[1]);
|
||||
|
||||
strcpy(s_strUIMessage,"帧率设置成功!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10;
|
||||
}
|
||||
else if (strcmp(result[0],"bin") == 0)
|
||||
{
|
||||
int spectralBin_tm = atoi(result[2]);
|
||||
sprintf(spectralBin,"%d",spectralBin_tm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __CC_ARM
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
@ -248,4 +598,298 @@ static T_DjiReturnCode DjiTestWidget_GetWidgetValue(E_DjiWidgetType widgetType,
|
||||
return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int frameRateGlobel = 0;
|
||||
static T_DjiReturnCode PsdkTestWidget_SetWidgetValue_StartRecord(E_DjiWidgetType widgetType, uint32_t index, int32_t value,
|
||||
void *userData)
|
||||
{
|
||||
USER_UTIL_UNUSED(userData);
|
||||
|
||||
USER_LOG_INFO("Set widget value, widgetType = %s, widgetIndex = %d ,widgetValue = %d",
|
||||
s_widgetTypeNameArray[widgetType], index, value);
|
||||
s_widgetValueList[index] = value;
|
||||
|
||||
switch (index)
|
||||
{
|
||||
case 5://系统启动关闭
|
||||
if (value==0)//系统关闭
|
||||
{
|
||||
if (systemON_Control == 3)
|
||||
{
|
||||
strcpy(s_strUIMessage,"系统已经关闭!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 1000;
|
||||
|
||||
char* command = "2";
|
||||
sendto(s_sockfd, command,strlen(command),0,(struct sockaddr *)&s_server,sizeof(s_server));
|
||||
|
||||
systemON_Control = 4;
|
||||
}
|
||||
}
|
||||
else if (value==1)//系统启动
|
||||
{
|
||||
if (systemON_Control == 0)
|
||||
{
|
||||
strcpy(s_strUIMessage,"请等待系统初始化!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 1000;
|
||||
}
|
||||
else if (systemON_Control == 1)
|
||||
{
|
||||
strcpy(s_strUIMessage,"系统启动中,请等待!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 1000;
|
||||
|
||||
char* command = "1";
|
||||
sendto(s_sockfd, command,strlen(command),0,(struct sockaddr *)&s_server,sizeof(s_server));
|
||||
|
||||
systemON_Control = 2;
|
||||
}
|
||||
else if (systemON_Control == 2)
|
||||
{
|
||||
strcpy(s_strUIMessage,"系统启动中,请等待!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 1000;
|
||||
}
|
||||
else if (systemON_Control == 3)
|
||||
{
|
||||
strcpy(s_strUIMessage,"系统已经启动!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 1000;
|
||||
}
|
||||
else if (systemON_Control == 4)
|
||||
{
|
||||
strcpy(s_strUIMessage,"相机占用,请重新上电!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 1000;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 6://设置帧率
|
||||
{
|
||||
if (s_stateOfXimea < 101)
|
||||
{
|
||||
strcpy(s_strUIMessage,"请先启动系统!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10;
|
||||
|
||||
break;
|
||||
}
|
||||
else if (s_stateOfXimea > 103)
|
||||
{
|
||||
strcpy(s_strUIMessage,"相机采集中,此操作无效!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// 控制帧率范围
|
||||
if(value > 150)
|
||||
{
|
||||
strcpy(s_strUIMessage,"帧率不可超过150!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10;
|
||||
|
||||
break;
|
||||
}
|
||||
else if(value == 0)
|
||||
{
|
||||
strcpy(s_strUIMessage,"帧率无效!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
frameRateGlobel = value;
|
||||
|
||||
char command[50] = "5,";
|
||||
char framerate[20];
|
||||
sprintf(framerate,"%d",value);
|
||||
strcat(command,framerate);
|
||||
sendto(s_sockfd, command,strlen(command),0,(struct sockaddr *)&s_server,sizeof(s_server));
|
||||
break;
|
||||
}
|
||||
case 7://自动曝光
|
||||
if (value==0)
|
||||
{
|
||||
;
|
||||
}
|
||||
else if (value==1)
|
||||
{
|
||||
if (s_stateOfXimea < 101)
|
||||
{
|
||||
strcpy(s_strUIMessage,"请先启动系统!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10;
|
||||
|
||||
break;
|
||||
}
|
||||
else if (s_stateOfXimea > 103)
|
||||
{
|
||||
strcpy(s_strUIMessage,"相机采集中,此操作无效!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(s_strUIMessage,"正在自动曝光,请稍等!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 1000;
|
||||
|
||||
char* command = "6";
|
||||
sendto(s_sockfd, command,strlen(command),0,(struct sockaddr *)&s_server,sizeof(s_server));
|
||||
}
|
||||
break;
|
||||
case 8://手动设置曝光时间
|
||||
{
|
||||
if (s_stateOfXimea < 101)
|
||||
{
|
||||
strcpy(s_strUIMessage,"请先启动系统!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10;
|
||||
|
||||
break;
|
||||
}
|
||||
else if (s_stateOfXimea > 103)
|
||||
{
|
||||
strcpy(s_strUIMessage,"相机采集中,此操作无效!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//曝光时间有效性判断
|
||||
if(frameRateGlobel == 0)
|
||||
{
|
||||
strcpy(s_strUIMessage,"请先设置帧率!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
float maxExposureTime = 1 / (float)frameRateGlobel * 1000;//单位是ms
|
||||
|
||||
if(value > maxExposureTime)
|
||||
{
|
||||
strcpy(s_strUIMessage,"曝光时间超过上限,无效!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10;
|
||||
|
||||
break;
|
||||
}
|
||||
else if(value == 0)
|
||||
{
|
||||
strcpy(s_strUIMessage,"曝光时间无效!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
char command[50] = "7,";
|
||||
char exposureTime[20];
|
||||
sprintf(exposureTime,"%d",(value));
|
||||
strcat(command,exposureTime);
|
||||
sendto(s_sockfd, command,strlen(command),0,(struct sockaddr *)&s_server,sizeof(s_server));
|
||||
|
||||
break;
|
||||
}
|
||||
case 9:
|
||||
if (value==0)//停止采集
|
||||
{
|
||||
char* command = "4";
|
||||
sendto(s_sockfd, command,strlen(command),0,(struct sockaddr *)&s_server,sizeof(s_server));
|
||||
}
|
||||
else if (value==1)//开始采集
|
||||
{
|
||||
if (s_stateOfXimea < 101)
|
||||
{
|
||||
strcpy(s_strUIMessage,"请先启动系统!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10;
|
||||
|
||||
break;
|
||||
}
|
||||
else if (s_stateOfXimea == 101)
|
||||
{
|
||||
strcpy(s_strUIMessage,"请先设置帧率!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10;
|
||||
|
||||
break;
|
||||
}
|
||||
else if (s_stateOfXimea == 102)
|
||||
{
|
||||
strcpy(s_strUIMessage,"请先设置曝光时间!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
char* command = "3";
|
||||
sendto(s_sockfd, command,strlen(command),0,(struct sockaddr *)&s_server,sizeof(s_server));
|
||||
}
|
||||
break;
|
||||
case 10:
|
||||
if (value==0)//等待指令
|
||||
{
|
||||
}
|
||||
if (value==1)
|
||||
{
|
||||
system("reboot");
|
||||
}
|
||||
else if (value==2)
|
||||
{
|
||||
system("shutdown now");
|
||||
}
|
||||
else if (value==3)
|
||||
{
|
||||
system("/home/300tc/projects/udpClient/udpClient 127.0.0.1 9,1");
|
||||
}
|
||||
else if (value==4)
|
||||
{
|
||||
system("/home/300tc/projects/udpClient/udpClient 127.0.0.1 9,0");
|
||||
}
|
||||
else if (value==5)
|
||||
{
|
||||
strcpy(s_strUIMessage,"系统正在更新,稍后会自动重启!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10000;
|
||||
|
||||
system("/home/pi/tc_ShellScripts/update0.sh &> /media/nvme/300TC/update/log");
|
||||
}
|
||||
break;
|
||||
case 11:
|
||||
if (value==0)//等待指令
|
||||
{
|
||||
}
|
||||
if (value==1)
|
||||
{
|
||||
system("sudo sed -i 's/spectralBin =.*/spectralBin = 1;/g' /media/nvme/300TC/config/ximea.cfg");
|
||||
}
|
||||
else if (value==2)
|
||||
{
|
||||
system("sudo sed -i 's/spectralBin =.*/spectralBin = 2;/g' /media/nvme/300TC/config/ximea.cfg");
|
||||
}
|
||||
|
||||
strcpy(s_strUIMessage,"请重新上电!");
|
||||
messageTimeCounter = 0;
|
||||
messageTimespan = 10000;
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
/****************** (C) COPYRIGHT DJI Innovations *****END OF FILE****/
|
||||
|
||||
@ -34,6 +34,21 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
|
||||
#define PORT 45454
|
||||
#define MAXDATASIZE 100
|
||||
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
},
|
||||
"speaker": {
|
||||
"is_enable_tts": true,
|
||||
"is_enable_voice": true
|
||||
"is_enable_voice": false
|
||||
},
|
||||
"widget_list": [
|
||||
{
|
||||
@ -76,6 +76,19 @@
|
||||
"mapping_config_display_order": 3,
|
||||
"button_value_step_length": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"widget_index": 4,
|
||||
"widget_type": "button",
|
||||
"widget_name": "按钮",
|
||||
"icon_file_set": {
|
||||
"icon_file_name_selected": "icon_button1.png",
|
||||
"icon_file_name_unselected": "icon_button1.png"
|
||||
},
|
||||
"customize_rc_buttons_config": {
|
||||
"is_enable": true,
|
||||
"mapping_config_display_order": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -86,62 +99,73 @@
|
||||
"is_enable": true
|
||||
},
|
||||
"widget_list": [
|
||||
{
|
||||
"widget_index": 4,
|
||||
"widget_type": "button",
|
||||
"widget_name": "按钮 4",
|
||||
"customize_rc_buttons_config": {
|
||||
"is_enable": true,
|
||||
"mapping_config_display_order": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"widget_index": 5,
|
||||
"widget_type": "scale",
|
||||
"widget_name": "范围条 5",
|
||||
"customize_rc_buttons_config": {
|
||||
"is_enable": true,
|
||||
"mapping_config_display_order": 5,
|
||||
"button_value_step_length": 5
|
||||
}
|
||||
"widget_type": "switch",
|
||||
"widget_name": "系统启动"
|
||||
},
|
||||
{
|
||||
"widget_index": 6,
|
||||
"widget_type": "int_input_box",
|
||||
"widget_name": "整形值输入框 6",
|
||||
"int_input_box_hint": "unit:s"
|
||||
"widget_name": "帧率",
|
||||
"int_input_box_hint": "unit:hz"
|
||||
},
|
||||
{
|
||||
"widget_index": 7,
|
||||
"widget_type": "switch",
|
||||
"widget_name": "开关 7",
|
||||
"customize_rc_buttons_config": {
|
||||
"is_enable": true,
|
||||
"mapping_config_display_order": 7
|
||||
}
|
||||
"widget_type": "button",
|
||||
"widget_name": "自动曝光"
|
||||
},
|
||||
{
|
||||
"widget_index": 8,
|
||||
"widget_type": "int_input_box",
|
||||
"widget_name": "曝光时间",
|
||||
"int_input_box_hint": "unit:ms"
|
||||
},
|
||||
{
|
||||
"widget_index": 9,
|
||||
"widget_type": "switch",
|
||||
"widget_name": "开始采集"
|
||||
},
|
||||
{
|
||||
"widget_index": 10,
|
||||
"widget_type": "list",
|
||||
"widget_name": "列表 8",
|
||||
"widget_name": "系统指令",
|
||||
"list_item": [
|
||||
{
|
||||
"item_name": "选项 1"
|
||||
"item_name": "等待指令"
|
||||
},
|
||||
{
|
||||
"item_name": "选项 2"
|
||||
"item_name": "重启电脑"
|
||||
},
|
||||
{
|
||||
"item_name": "选项 3"
|
||||
"item_name": "关机"
|
||||
},
|
||||
{
|
||||
"item_name": "选项 4"
|
||||
"item_name": "测试采集"
|
||||
},
|
||||
{
|
||||
"item_name": "停止采集"
|
||||
},
|
||||
{
|
||||
"item_name": "更新"
|
||||
}
|
||||
],
|
||||
"customize_rc_buttons_config": {
|
||||
"is_enable": true,
|
||||
"mapping_config_display_order": 8
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"widget_index": 11,
|
||||
"widget_type": "list",
|
||||
"widget_name": "bin",
|
||||
"list_item": [
|
||||
{
|
||||
"item_name": "等待指令"
|
||||
},
|
||||
{
|
||||
"item_name": "光谱1"
|
||||
},
|
||||
{
|
||||
"item_name": "光谱2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
},
|
||||
"speaker": {
|
||||
"is_enable_tts": true,
|
||||
"is_enable_voice": true
|
||||
"is_enable_voice": false
|
||||
},
|
||||
"widget_list": [
|
||||
{
|
||||
@ -76,6 +76,19 @@
|
||||
"mapping_config_display_order": 3,
|
||||
"button_value_step_length": 5
|
||||
}
|
||||
},
|
||||
{
|
||||
"widget_index": 4,
|
||||
"widget_type": "button",
|
||||
"widget_name": "Button",
|
||||
"icon_file_set": {
|
||||
"icon_file_name_selected": "icon_button1.png",
|
||||
"icon_file_name_unselected": "icon_button1.png"
|
||||
},
|
||||
"customize_rc_buttons_config": {
|
||||
"is_enable": true,
|
||||
"mapping_config_display_order": 0
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
@ -86,62 +99,73 @@
|
||||
"is_enable": true
|
||||
},
|
||||
"widget_list": [
|
||||
{
|
||||
"widget_index": 4,
|
||||
"widget_type": "button",
|
||||
"widget_name": "Button 4",
|
||||
"customize_rc_buttons_config": {
|
||||
"is_enable": true,
|
||||
"mapping_config_display_order": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"widget_index": 5,
|
||||
"widget_type": "scale",
|
||||
"widget_name": "Scale 5",
|
||||
"customize_rc_buttons_config": {
|
||||
"is_enable": true,
|
||||
"mapping_config_display_order": 5,
|
||||
"button_value_step_length": 5
|
||||
}
|
||||
"widget_type": "switch",
|
||||
"widget_name": "系统启动"
|
||||
},
|
||||
{
|
||||
"widget_index": 6,
|
||||
"widget_type": "int_input_box",
|
||||
"widget_name": "Integer Input Box 6",
|
||||
"int_input_box_hint": "unit:s"
|
||||
"widget_name": "帧率",
|
||||
"int_input_box_hint": "unit:hz"
|
||||
},
|
||||
{
|
||||
"widget_index": 7,
|
||||
"widget_type": "switch",
|
||||
"widget_name": "Switch 7",
|
||||
"customize_rc_buttons_config": {
|
||||
"is_enable": true,
|
||||
"mapping_config_display_order": 7
|
||||
}
|
||||
"widget_type": "button",
|
||||
"widget_name": "自动曝光"
|
||||
},
|
||||
{
|
||||
"widget_index": 8,
|
||||
"widget_type": "int_input_box",
|
||||
"widget_name": "曝光时间",
|
||||
"int_input_box_hint": "unit:ms"
|
||||
},
|
||||
{
|
||||
"widget_index": 9,
|
||||
"widget_type": "switch",
|
||||
"widget_name": "开始采集"
|
||||
},
|
||||
{
|
||||
"widget_index": 10,
|
||||
"widget_type": "list",
|
||||
"widget_name": "List 8",
|
||||
"widget_name": "系统指令",
|
||||
"list_item": [
|
||||
{
|
||||
"item_name": "Item 1"
|
||||
"item_name": "等待指令"
|
||||
},
|
||||
{
|
||||
"item_name": "Item 2"
|
||||
"item_name": "重启电脑"
|
||||
},
|
||||
{
|
||||
"item_name": "Item 3"
|
||||
"item_name": "关机"
|
||||
},
|
||||
{
|
||||
"item_name": "Item 4"
|
||||
"item_name": "测试采集"
|
||||
},
|
||||
{
|
||||
"item_name": "停止采集"
|
||||
},
|
||||
{
|
||||
"item_name": "更新"
|
||||
}
|
||||
],
|
||||
"customize_rc_buttons_config": {
|
||||
"is_enable": true,
|
||||
"mapping_config_display_order": 8
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"widget_index": 11,
|
||||
"widget_type": "list",
|
||||
"widget_name": "bin",
|
||||
"list_item": [
|
||||
{
|
||||
"item_name": "等待指令"
|
||||
},
|
||||
{
|
||||
"item_name": "光谱1"
|
||||
},
|
||||
{
|
||||
"item_name": "光谱2"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -40,9 +40,9 @@
|
||||
|
||||
|
||||
/* Private functions declaration ---------------------------------------------*/
|
||||
static void *UserXPort_Task(void *arg);
|
||||
static T_DjiReturnCode ReceiveXPortSystemState(T_DjiGimbalSystemState systemState);
|
||||
static T_DjiReturnCode ReceiveXPortAttitudeInformation(T_DjiGimbalAttitudeInformation attitudeInformation);
|
||||
static void *UserXPort_Task(void *arg);//用户自定义xport任务
|
||||
static T_DjiReturnCode ReceiveXPortSystemState(T_DjiGimbalSystemState systemState);//通过构造回调函数接受xport的状态信息
|
||||
static T_DjiReturnCode ReceiveXPortAttitudeInformation(T_DjiGimbalAttitudeInformation attitudeInformation);//构造回调函数获取X-Port 的姿态,在回调函数中打印X-Port 的姿态信息。
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
static T_DjiTaskHandle s_userXPortThread;
|
||||
@ -51,6 +51,10 @@ static T_DjiGimbalSystemState s_userXPortSystemState = {0};
|
||||
static bool s_isUserXPortInited = false;
|
||||
static bool s_isUserXPortSystemStateVaild = false;
|
||||
|
||||
extern char * s_strPitch;
|
||||
extern char * s_strRoll;
|
||||
extern char * s_strYaw;
|
||||
|
||||
/* Exported functions definition ---------------------------------------------*/
|
||||
T_DjiReturnCode DjiTest_XPortStartService(void)
|
||||
{
|
||||
@ -59,6 +63,7 @@ T_DjiReturnCode DjiTest_XPortStartService(void)
|
||||
T_DjiAircraftInfoBaseInfo aircraftInfoBaseInfo = {0};
|
||||
T_DjiOsalHandler *osalHandler = DjiPlatform_GetOsalHandler();
|
||||
|
||||
//X-Port 功能模块初始化
|
||||
djiStat = DjiXPort_Init();
|
||||
if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("XPort init error: 0x%08llX.", djiStat);
|
||||
@ -73,12 +78,14 @@ T_DjiReturnCode DjiTest_XPortStartService(void)
|
||||
return djiStat;
|
||||
}
|
||||
|
||||
//通过注册回调函数接收X-Port 的状态信息。注册后,回调函数将会被自动调用,调用频率为
|
||||
djiStat = DjiXPort_RegReceiveSystemStateCallback(ReceiveXPortSystemState);
|
||||
if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("register receive XPort system state callback function error: 0x%08llX.", djiStat);
|
||||
return djiStat;
|
||||
}
|
||||
|
||||
//通过注册回调函数获取X-Port 的姿态信息.注册后,回调函数将会被自动调用,调用频率为
|
||||
djiStat = DjiXPort_RegReceiveAttitudeInformationCallback(ReceiveXPortAttitudeInformation);
|
||||
if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("register receive XPort attitude information callback function error: 0x%08llX.",
|
||||
@ -86,22 +93,28 @@ T_DjiReturnCode DjiTest_XPortStartService(void)
|
||||
return djiStat;
|
||||
}
|
||||
|
||||
//配置xport信息;开始------------------------------------------------------------------------------------------------------
|
||||
//下述代码中X-Port 的角度单位为0.1度
|
||||
|
||||
//设置俯仰轴关节角(PITCH_JOINT_ANGLE)限位
|
||||
limitAngle.upperLimit = 300;
|
||||
limitAngle.lowerLimit = -1000;
|
||||
limitAngle.lowerLimit = -1200;
|
||||
djiStat = DjiXPort_SetLimitAngleSync(DJI_XPORT_LIMIT_ANGLE_CATEGORY_PITCH_JOINT_ANGLE, limitAngle);
|
||||
if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("set pitch joint angle limit angle for XPort error: 0x%08llX.", djiStat);
|
||||
return djiStat;
|
||||
}
|
||||
|
||||
//设置俯仰轴欧拉角(PITCH_EULER_ANGLE)限位
|
||||
limitAngle.upperLimit = 300;
|
||||
limitAngle.lowerLimit = -800;
|
||||
limitAngle.lowerLimit = -1200;
|
||||
djiStat = DjiXPort_SetLimitAngleSync(DJI_XPORT_LIMIT_ANGLE_CATEGORY_PITCH_EULER_ANGLE, limitAngle);
|
||||
if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("set pitch euler angle limit angle for XPort error: 0x%08llX.", djiStat);
|
||||
return djiStat;
|
||||
}
|
||||
|
||||
//设置扩展俯仰轴欧拉角(PITCH_EULER_ANGLE_EXTENSION)限位
|
||||
limitAngle.upperLimit = 300;
|
||||
limitAngle.lowerLimit = -1000;
|
||||
djiStat = DjiXPort_SetLimitAngleSync(DJI_XPORT_LIMIT_ANGLE_CATEGORY_PITCH_EULER_ANGLE_EXTENSION, limitAngle);
|
||||
@ -110,6 +123,7 @@ T_DjiReturnCode DjiTest_XPortStartService(void)
|
||||
return djiStat;
|
||||
}
|
||||
|
||||
//设置航向轴关节角(YAW_JOINT_ANGLE)限位1、获取飞机信息 → 判断云台在飞机上的挂载点
|
||||
djiStat = DjiAircraftInfo_GetBaseInfo(&aircraftInfoBaseInfo);
|
||||
if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("get aircraft base information error: 0x%08llX.", djiStat);
|
||||
@ -130,24 +144,28 @@ T_DjiReturnCode DjiTest_XPortStartService(void)
|
||||
return DJI_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
|
||||
}
|
||||
|
||||
//设置航向轴关节角(YAW_JOINT_ANGLE)限位2、
|
||||
djiStat = DjiXPort_SetLimitAngleSync(DJI_XPORT_LIMIT_ANGLE_CATEGORY_YAW_JOINT_ANGLE, limitAngle);
|
||||
if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("set yaw joint angle limit angle for XPort error: 0x%08llX.", djiStat);
|
||||
return djiStat;
|
||||
}
|
||||
|
||||
djiStat = DjiXPort_SetGimbalModeSync(DJI_GIMBAL_MODE_FREE);
|
||||
//设置X-Port 工作模式
|
||||
djiStat = DjiXPort_SetGimbalModeSync(DJI_GIMBAL_MODE_YAW_FOLLOW);
|
||||
if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("set XPort gimbal mode error: 0x%08llX.", djiStat);
|
||||
return djiStat;
|
||||
}
|
||||
|
||||
//使用X-Port 复位功能
|
||||
djiStat = DjiXPort_ResetSync(DJI_GIMBAL_RESET_MODE_PITCH_AND_YAW);
|
||||
if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("reset XPort gimbal error: 0x%08llX.", djiStat);
|
||||
return djiStat;
|
||||
}
|
||||
|
||||
//用户自定义xport功能
|
||||
if (osalHandler->TaskCreate("user_xport_task", UserXPort_Task, XPORT_TASK_STACK_SIZE, NULL, &s_userXPortThread) !=
|
||||
DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
USER_LOG_ERROR("user XPort task create error.");
|
||||
@ -219,6 +237,7 @@ T_DjiReturnCode DjiTest_XPortGetSystemState(T_DjiGimbalSystemState *systemState)
|
||||
#pragma GCC diagnostic ignored "-Wreturn-type"
|
||||
#endif
|
||||
|
||||
//用户自定义xport功能函数实现
|
||||
static void *UserXPort_Task(void *arg)
|
||||
{
|
||||
T_DjiReturnCode djiStat;
|
||||
@ -234,6 +253,7 @@ static void *UserXPort_Task(void *arg)
|
||||
osalHandler->TaskSleepMs(1000 / XPORT_TASK_FREQ);
|
||||
step++;
|
||||
|
||||
//XPORT_TASK_FREQ(10)的整数才执行if后面的代码:获取xport限位角并打印出来
|
||||
if (USER_UTIL_IS_WORK_TURN(step, 1, XPORT_TASK_FREQ)) {
|
||||
djiStat = DjiXPort_GetLimitAngleSync(DJI_XPORT_LIMIT_ANGLE_CATEGORY_ROLL_JOINT_ANGLE, &limitAngle);
|
||||
if (djiStat != DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
|
||||
@ -283,6 +303,7 @@ static void *UserXPort_Task(void *arg)
|
||||
limitAngle.upperLimit, limitAngle.lowerLimit);
|
||||
}
|
||||
|
||||
//XPORT_TASK_FREQ(1)的整数才执行if后面的代码:设置xport速度转换系数
|
||||
if (USER_UTIL_IS_WORK_TURN(step, 10, XPORT_TASK_FREQ)) {
|
||||
if (DjiTest_CameraIsInited()) {
|
||||
djiStat = DjiTest_CameraGetOpticalZoomFactor(&opticalZoomFactor);
|
||||
@ -340,12 +361,22 @@ static T_DjiReturnCode ReceiveXPortSystemState(T_DjiGimbalSystemState systemStat
|
||||
return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
char * pitchTmp[10];
|
||||
char * rollTmp[10];
|
||||
char * yawTmp[10];
|
||||
static T_DjiReturnCode ReceiveXPortAttitudeInformation(T_DjiGimbalAttitudeInformation attitudeInformation)
|
||||
{
|
||||
USER_LOG_DEBUG("receive XPort attitude information:");
|
||||
USER_LOG_DEBUG("XPort attitude: pitch %d, roll %d, yaw %d.", attitudeInformation.attitude.pitch,
|
||||
attitudeInformation.attitude.roll, attitudeInformation.attitude.yaw);
|
||||
|
||||
sprintf(pitchTmp, "%d", attitudeInformation.attitude.pitch);
|
||||
sprintf(rollTmp, "%d", attitudeInformation.attitude.roll);
|
||||
sprintf(yawTmp, "%d", attitudeInformation.attitude.yaw);
|
||||
s_strPitch = pitchTmp;
|
||||
s_strRoll = rollTmp;
|
||||
s_strYaw = yawTmp;
|
||||
|
||||
return DJI_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
@ -40,10 +40,12 @@ file(GLOB_RECURSE MODULE_SAMPLE_SRC ../../../module_sample/*.c)
|
||||
include_directories(../../../module_sample)
|
||||
include_directories(../common)
|
||||
include_directories(../manifold2/application)
|
||||
include_directories(/home/300tc/library/ffmpeg_build/include)
|
||||
|
||||
include_directories(../../../../../psdk_lib/include)
|
||||
link_directories(../../../../../psdk_lib/lib/${TOOLCHAIN_NAME})
|
||||
link_libraries(${CMAKE_CURRENT_LIST_DIR}/../../../../../psdk_lib/lib/${TOOLCHAIN_NAME}/lib${PACKAGE_NAME}.a)
|
||||
link_directories(/home/300tc/library/ffmpeg_build/lib)
|
||||
|
||||
if (NOT EXECUTABLE_OUTPUT_PATH)
|
||||
set(EXECUTABLE_OUTPUT_PATH ${CMAKE_BINARY_DIR}/bin)
|
||||
@ -80,7 +82,20 @@ else ()
|
||||
message(STATUS "Cannot Find LIBUSB")
|
||||
endif (LIBUSB_FOUND)
|
||||
|
||||
target_link_libraries(${PROJECT_NAME} m)
|
||||
target_link_libraries(${PROJECT_NAME}
|
||||
avformat
|
||||
avfilter
|
||||
avcodec
|
||||
swscale
|
||||
avutil
|
||||
swresample
|
||||
avdevice
|
||||
avutil
|
||||
postproc
|
||||
z
|
||||
m
|
||||
pthread
|
||||
)
|
||||
|
||||
add_custom_command(TARGET ${PROJECT_NAME}
|
||||
PRE_LINK COMMAND cmake ..
|
||||
|
||||
@ -35,12 +35,12 @@ extern "C" {
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
// ATTENTION: User must goto https://developer.dji.com/user/apps/#all to create your own dji sdk application, get dji sdk application
|
||||
// information then fill in the application information here.
|
||||
#define USER_APP_NAME "your_app_name"
|
||||
#define USER_APP_ID "your_app_id"
|
||||
#define USER_APP_KEY "your_app_key"
|
||||
#define USER_APP_LICENSE "your_app_license"
|
||||
#define USER_DEVELOPER_ACCOUNT "your_developer_account"
|
||||
#define USER_BAUD_RATE "460800"
|
||||
#define USER_APP_NAME "imager"
|
||||
#define USER_APP_ID "90210"
|
||||
#define USER_APP_KEY "2c309ca22fb1e67cc166ccc9dc261f4"
|
||||
#define USER_APP_LICENSE "JYdEUQRW5lsZANuJnMr9qGsD/1I3KyJL+es97f0qkC4QuCITbCjTIzQNkjk63nuShBtjtC4cCf9PdlLfGCGQWQ5rJDBURg9JbotJEXejpXJgTV/1Jq3ZAp9Jp7ajOhvClcKDzfOllPj/216BtYrC7G92CED39p4iUec5p4cG/ClHYAEKys+1cyHWufcV3COgqqCdxlveY0LlWXP44Q1e4vcFMfo4AqN4LghOO7fMdqsN6CLWNN0WEZu8GnU1TWzXAUE9uLjzqxH8WJLDJChBQvXdsxm/RTuER2mCu8NflMNDhnl+sWASiqTXJyZwN8gdu2fuDkU8umlhxQP+1Gk8ig=="
|
||||
#define USER_DEVELOPER_ACCOUNT "735056338@qq.com"
|
||||
#define USER_BAUD_RATE "115200"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
|
||||
@ -42,7 +42,7 @@ extern "C" {
|
||||
#ifdef PLATFORM_ARCH_x86_64
|
||||
#define LINUX_NETWORK_DEV "enxf8e43b7bbc2c"
|
||||
#else
|
||||
#define LINUX_NETWORK_DEV "l4tbr0"
|
||||
#define LINUX_NETWORK_DEV "eth1"
|
||||
#endif
|
||||
/**
|
||||
* @attention
|
||||
|
||||
@ -45,7 +45,7 @@ extern "C" {
|
||||
|
||||
/* Exported constants --------------------------------------------------------*/
|
||||
//User can config dev based on there environmental conditions
|
||||
#define LINUX_UART_DEV1 "/dev/ttyUSB0"
|
||||
#define LINUX_UART_DEV1 "/dev/ttyUSB1"
|
||||
#define LINUX_UART_DEV2 "/dev/ttyACM0"
|
||||
|
||||
/* Exported types ------------------------------------------------------------*/
|
||||
|
||||
Reference in New Issue
Block a user