作者 ookk303

紫燕sdk更新

要显示太多修改。

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

@@ -145,7 +145,8 @@ @@ -145,7 +145,8 @@
145 "jzsdk_expansion.h": "c", 145 "jzsdk_expansion.h": "c",
146 "jzsdk_expansionapi.h": "c", 146 "jzsdk_expansionapi.h": "c",
147 "test_widget_speaker.h": "c", 147 "test_widget_speaker.h": "c",
148 - "dji_expansion.h": "c" 148 + "dji_expansion.h": "c",
  149 + "test_widget.h": "c"
149 }, 150 },
150 "Codegeex.GenerationPreference": "automatic", 151 "Codegeex.GenerationPreference": "automatic",
151 "C_Cpp.dimInactiveRegions": false, 152 "C_Cpp.dimInactiveRegions": false,
1 # 编译链的配置 1 # 编译链的配置
2 2
3 #1、编译链与设备类型的选择 3 #1、编译链与设备类型的选择
4 -set(DEVICE_NAME JZ_H1E) 4 +set(DEVICE_NAME JZ_H150G)
5 #上一行为禁止修改行 5 #上一行为禁止修改行
6 6
7 message("**************************JZSDK构建编译开始***************************\n") 7 message("**************************JZSDK构建编译开始***************************\n")
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 #define VERSION_CHOOSE_H 7 #define VERSION_CHOOSE_H
8 #include "JZsdk_Base/JZsdk_Code/JZsdk_DeviceCode.h" 8 #include "JZsdk_Base/JZsdk_Code/JZsdk_DeviceCode.h"
9 //1~10行 除了D可以修改版本选择 禁止动任何东西 9 //1~10行 除了D可以修改版本选择 禁止动任何东西
10 -#define DEVICE_VERSION JZ_H1E 10 +#define DEVICE_VERSION JZ_H150G
11 11
12 //禁止修改行 选择是串口程序 还是 psdk程序 12 //禁止修改行 选择是串口程序 还是 psdk程序
13 #define APP_VERSION APP_PSDK 13 #define APP_VERSION APP_PSDK
@@ -23,7 +23,7 @@ @@ -23,7 +23,7 @@
23 #define MODIFY_VERSION_TEN_POSITION 1 23 #define MODIFY_VERSION_TEN_POSITION 1
24 #define MODIFY_VERSION_ONE_POSITION 1 24 #define MODIFY_VERSION_ONE_POSITION 1
25 #define DEBUG_VERSION_TEN_POSITION 0 25 #define DEBUG_VERSION_TEN_POSITION 0
26 -#define DEBUG_VERSION_ONE_POSITION 5 26 +#define DEBUG_VERSION_ONE_POSITION 3
27 27
28 28
29 29
@@ -66,7 +66,6 @@ int num_flag=0;//版本号信息 @@ -66,7 +66,6 @@ int num_flag=0;//版本号信息
66 extern int height_Volume_lock; 66 extern int height_Volume_lock;
67 67
68 extern int SpeakerWidgetUseLock; 68 extern int SpeakerWidgetUseLock;
69 -extern char Jz_SerialNumber[128]; //设备序列号  
70 extern float g_height_value; 69 extern float g_height_value;
71 extern int Widget_RealTimeOpusFlag; //用于标志ui里的实时语音开关 70 extern int Widget_RealTimeOpusFlag; //用于标志ui里的实时语音开关
72 71
1 -# Prerequisites  
2 -*.d  
3 -  
4 -# Compiled Object files  
5 -*.slo  
6 -*.lo  
7 -*.o  
8 -*.obj  
9 -  
10 -# Precompiled Headers  
11 -*.gch  
12 -*.pch  
13 -  
14 -# Compiled Dynamic libraries  
15 -*.so  
16 -*.dylib  
17 -*.dll  
18 -  
19 -# Fortran module files  
20 -*.mod  
21 -*.smod  
22 -  
23 -# Compiled Static libraries  
24 -*.lai  
25 -*.la  
26 -.a  
27 -.lib  
28 -  
29 -# Executables  
30 -*.exe  
31 -*.out  
32 -*.app  
1 -# Ziyan Payload SDK (PSDK)  
2 -  
3 -  
4 -  
5 -## What is the Ziyan Payload SDK?  
6 -  
7 -The ziyan Payload SDK(PSDK), is a development kit provided by ziyan to support developers to develop payload that can be mounted on ziyan aircraft. developers can obtain the information or other resource from the aircraft. According to the software logic and algorithm framework designed by the developer, users could develop payload that can be mounted on ziyan aircraft, to perform actions they need, such as Automated Flight Controller, Payload Controller, Video Image Analysis Platform, Mapping Camera, Megaphone And Searchlight, etc.  
8 -  
9 -  
10 -  
11 -## Latest Release  
12 -  
13 -The latest release version of PSDK is 1.0.0.0 This version of Payload SDK mainly first release. Please refer to the release notes for detailed changes list.  
14 -  
15 -## License  
16 -  
17 -Payload SDK codebase is MIT-licensed. Please refer to the LICENSE file for detailed information.  
18 -  
19 -# Ziyan Payload SDK (PSDK)  
20 -  
21 -## 什么是Ziyan Payload SDK?  
22 -  
23 -Ziyan Payload SDK(PSDK)是由Ziyan提供的一套开发工具包,支持开发者开发可以安装在Ziyan无人机上的有效载荷。开发者可以从无人机获取信息或其他资源。根据开发者设计的软件逻辑和算法框架,用户可以开发出可以安装在Ziyan无人机上的有效载荷,以执行他们需要的操作,例如自动飞行控制器、有效载荷控制器、视频图像分析平台、测绘相机、扩音器和探照灯等。  
24 -  
25 -## 最新版本  
26 -  
27 -PSDK的最新版本是1.0.0.0。这个版本的Payload SDK主要是首次发布。请参考发布说明以获取详细的变更列表。  
28 -  
29 -## 许可证  
30 -  
31 -Payload SDK的代码库采用MIT许可证。请参考LICENSE文件以获取详细信息。  
1 -# Ziyan Payload SDK Release Log  
2 -  
3 -  
4 -  
5 -## V1.0.0.2-20250401-Release  
6 -  
7 -**[Note]**:  
8 -To support more camera expansion features, Add new camera API. Fixed some known issues.  
9 -  
10 -**[Added]**:  
11 -* Add API which used to get obtain camera calculation position.  
12 -* Add API which used to control the camera tracker integrated into the payload camera.  
13 -  
14 -**[Fixed]**:  
15 -* Fix the issue that the camera status is not updated when the camera has connected.  
16 -* Fix occasional screen distortion in camera videos  
17 ----  
18 -  
19 -  
20 -  
21 -  
22 -  
23 -## V1.0.0.1-20250310-Release  
24 -**[Note]**:  
25 -To support more camera expansion features, Add new camera API. Fixed some known issues.  
26 -  
27 -**[Added]**:  
28 -* Add API which used to control the range finder integrated into the payload camera.  
29 ----  
30 -  
31 -  
32 -  
33 -  
34 -  
35 -## V1.0.0.0-20250306-Release  
36 -**[Note]**:  
37 -This version of Payload SDK mainly first release. Please refer to the release notes for detailed changes list.  
38 -  
39 -**[Added]**:  
40 -* Added support for gimbal functionality  
41 -* Added support for basic camera functionality  
42 -* Added support for widget functionality  
43 -* Added support for subscription functionality  
44 ----  
45 -  
46 -  
47 -# Ziyan Payload SDK 发布日志  
48 -  
49 -## V1.0.0.2-20250401-发布  
50 -  
51 -**[注意]**:  
52 -为了支持更多的相机扩展功能,添加了新的相机API。修复了一些已知问题。  
53 -  
54 -**[新增]**:  
55 -* 添加用于获取相机计算位置的API。  
56 -* 添加用于控制集成在有效载荷相机中的相机跟踪器的API。  
57 -  
58 -**[修复]**:  
59 -* 修复了相机连接时相机状态未更新的问题。  
60 -* 修复了相机视频中偶尔出现的屏幕扭曲问题  
61 ----  
62 -  
63 -  
64 -  
65 -  
66 -## V1.0.0.1-20250310-发布  
67 -**[注意]**:  
68 -为了支持更多的相机扩展功能,添加了新的相机API。修复了一些已知问题。  
69 -  
70 -**[新增]**:  
71 -* 添加用于控制集成在有效载荷相机中的测距仪的API。  
72 ----  
73 -  
74 -  
75 -  
76 -  
77 -  
78 -## V1.0.0.0-20250306-发布  
79 -**[注意]**:  
80 -这个版本的Payload SDK主要是首次发布。请参考发布说明以获取详细的变更列表。  
81 -  
82 -**[新增]**:  
83 -* 增加了支持云台功能  
84 -* 增加了支持基本相机功能  
85 -* 增加了支持小部件功能  
86 -* 增加了支持订阅功能  
87 ----  
88 -  
89 -  
1 /** 1 /**
2 ******************************************************************** 2 ********************************************************************
3 - * @file dji_aircraft_info.h  
4 - * @brief This is the header file for "dji_aircraft_info.c", defining the structure and 3 + * @file ziyan_aircraft_info.h
  4 + * @brief This is the header file for "ziyan_aircraft_info.c", defining the structure and
5 * (exported) function prototypes. 5 * (exported) function prototypes.
6 * 6 *
7 * @copyright (c) 2021 ZIYAN. All rights reserved. 7 * @copyright (c) 2021 ZIYAN. All rights reserved.
@@ -43,7 +43,7 @@ typedef enum { @@ -43,7 +43,7 @@ typedef enum {
43 * @note This transfer type only support linux platform and use network port. Users need to deploy FTP service on 43 * @note This transfer type only support linux platform and use network port. Users need to deploy FTP service on
44 * payload. The ftp user info used to transfer upgrade firmware is : 44 * payload. The ftp user info used to transfer upgrade firmware is :
45 * username:ziyan_payload_ftp 45 * username:ziyan_payload_ftp
46 - * password:DJi_#$31 46 + * password:Ziyan_#$31
47 * You can get guide about FTP service deployment on https://developer.ziyan.com/payload-sdk/documentation 47 * You can get guide about FTP service deployment on https://developer.ziyan.com/payload-sdk/documentation
48 */ 48 */
49 ZIYAN_FIRMWARE_TRANSFER_TYPE_FTP = 0, 49 ZIYAN_FIRMWARE_TRANSFER_TYPE_FTP = 0,
@@ -36,7 +36,7 @@ extern "C" { @@ -36,7 +36,7 @@ extern "C" {
36 #define ZIYAN_SDK_VERSION_MAJOR 1 /*!< ZIYAN SDK major version num, when have incompatible API changes. Range from 0 to 99. */ 36 #define ZIYAN_SDK_VERSION_MAJOR 1 /*!< ZIYAN SDK major version num, when have incompatible API changes. Range from 0 to 99. */
37 #define ZIYAN_SDK_VERSION_MINOR 0 /*!< ZIYAN SDK minor version num, when add functionality in a backwards compatible manner changes. Range from 0 to 99. */ 37 #define ZIYAN_SDK_VERSION_MINOR 0 /*!< ZIYAN SDK minor version num, when add functionality in a backwards compatible manner changes. Range from 0 to 99. */
38 #define ZIYAN_SDK_VERSION_MODIFY 0 /*!< ZIYAN SDK modify version num, when have backwards compatible bug fixes changes. Range from 0 to 99. */ 38 #define ZIYAN_SDK_VERSION_MODIFY 0 /*!< ZIYAN SDK modify version num, when have backwards compatible bug fixes changes. Range from 0 to 99. */
39 -#define ZIYAN_SDK_VERSION_DEBUG 2 /*!< ZIYAN SDK version beta info, release version will be 0, when beta version release changes. Range from 0 to 255. */ 39 +#define ZIYAN_SDK_VERSION_DEBUG 4 /*!< ZIYAN SDK version beta info, release version will be 0, when beta version release changes. Range from 0 to 255. */
40 #define ZIYAN_SDK_VERSION_BUILD 1 /*!< ZIYAN SDK version build info, when jenkins trigger build changes. Range from 0 to 65535. */ 40 #define ZIYAN_SDK_VERSION_BUILD 1 /*!< ZIYAN SDK version build info, when jenkins trigger build changes. Range from 0 to 65535. */
41 41
42 /* Exported types ------------------------------------------------------------*/ 42 /* Exported types ------------------------------------------------------------*/
@@ -763,13 +763,13 @@ static T_ZiyanReturnCode GetMediaFileDir(char *dirPath) @@ -763,13 +763,13 @@ static T_ZiyanReturnCode GetMediaFileDir(char *dirPath)
763 char curFileDirPath[ZIYAN_FILE_PATH_SIZE_MAX]; 763 char curFileDirPath[ZIYAN_FILE_PATH_SIZE_MAX];
764 char tempPath[ZIYAN_FILE_PATH_SIZE_MAX]; 764 char tempPath[ZIYAN_FILE_PATH_SIZE_MAX];
765 765
766 - returnCode = ZiyanUserUtil_GetCurrentFileDirPath(__FILE__, ZIYAN_FILE_PATH_SIZE_MAX, curFileDirPath); 766 + returnCode = ZiyanUserUtil_GetCurrentFileDirPath(__FILE__, sizeof(curFileDirPath), curFileDirPath);
767 if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) { 767 if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
768 USER_LOG_ERROR("Get file current path error, stat = 0x%08llX", returnCode); 768 USER_LOG_ERROR("Get file current path error, stat = 0x%08llX", returnCode);
769 return returnCode; 769 return returnCode;
770 } 770 }
771 771
772 - snprintf(dirPath, ZIYAN_FILE_PATH_SIZE_MAX, "%smedia_file", curFileDirPath); 772 + snprintf(dirPath, ZIYAN_FILE_PATH_SIZE_MAX + 32, "%smedia_file", curFileDirPath);
773 773
774 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS; 774 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
775 } 775 }
  1 +/**
  2 + ********************************************************************
  3 + * @file test_payload_cam_emu_media.c
  4 + * @brief
  5 + *
  6 + * @copyright (c) 2021 ZIYAN. All rights reserved.
  7 + *
  8 + * All information contained herein is, and remains, the property of ZIYAN.
  9 + * The intellectual and technical concepts contained herein are proprietary
  10 + * to ZIYAN and may be covered by U.S. and foreign patents, patents in process,
  11 + * and protected by trade secret or copyright law. Dissemination of this
  12 + * information, including but not limited to data and other proprietary
  13 + * material(s) incorporated within the information, in any form, is strictly
  14 + * prohibited without the express written consent of ZIYAN.
  15 + *
  16 + * If you receive this source code without ZIYAN’s authorization, you may not
  17 + * further disseminate the information, and you must immediately remove the
  18 + * source code and notify ZIYAN of its removal. ZIYAN reserves the right to pursue
  19 + * legal actions against you for any loss(es) or damage(s) caused by your
  20 + * failure to do so.
  21 + *
  22 + *********************************************************************
  23 + */
  24 +
  25 +/* Includes ------------------------------------------------------------------*/
  26 +#include <fcntl.h>
  27 +#include <stdlib.h>
  28 +#include "ziyan_logger.h"
  29 +#include "utils/util_misc.h"
  30 +#include "utils/util_time.h"
  31 +#include "utils/util_file.h"
  32 +#include "utils/util_buffer.h"
  33 +#include "test_payload_cam_emu_media.h"
  34 +#include "test_payload_cam_emu_base.h"
  35 +#include "camera_emu/ziyan_media_file_manage/ziyan_media_file_core.h"
  36 +#include "ziyan_high_speed_data_channel.h"
  37 +#include "ziyan_aircraft_info.h"
  38 +
  39 +/* Private constants ---------------------------------------------------------*/
  40 +#define FFMPEG_CMD_BUF_SIZE (256 + 256)
  41 +#define SEND_VIDEO_TASK_FREQ 120
  42 +#define VIDEO_FRAME_MAX_COUNT 18000 // max video duration 10 minutes
  43 +#define VIDEO_FRAME_AUD_LEN 6
  44 +#define DATA_SEND_FROM_VIDEO_STREAM_MAX_LEN 60000
  45 +
  46 +/* Private types -------------------------------------------------------------*/
  47 +typedef enum {
  48 + TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_STOP = 0,
  49 + TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_PAUSE = 1,
  50 + TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_START = 2,
  51 +} E_TestPayloadCameraPlaybackCommand;
  52 +
  53 +typedef struct {
  54 + uint8_t isInPlayProcess;
  55 + uint16_t videoIndex;
  56 + char filePath[ZIYAN_FILE_PATH_SIZE_MAX];
  57 + uint32_t videoLengthMs;
  58 + uint64_t startPlayTimestampsUs;
  59 + uint64_t playPosMs;
  60 +} T_ZiyanPlaybackInfo;
  61 +
  62 +typedef struct {
  63 + E_TestPayloadCameraPlaybackCommand command;
  64 + uint32_t timeMs;
  65 + char path[ZIYAN_FILE_PATH_SIZE_MAX];
  66 +} T_TestPayloadCameraPlaybackCommand;
  67 +
  68 +typedef struct {
  69 + float durationS;
  70 + uint32_t positionInFile;
  71 + uint32_t size;
  72 +} T_TestPayloadCameraVideoFrameInfo;
  73 +
  74 +/* Private functions declaration ---------------------------------------------*/
  75 +static T_ZiyanReturnCode ZiyanPlayback_StopPlay(T_ZiyanPlaybackInfo *playbackInfo);
  76 +static T_ZiyanReturnCode ZiyanPlayback_PausePlay(T_ZiyanPlaybackInfo *playbackInfo);
  77 +static T_ZiyanReturnCode ZiyanPlayback_SetPlayFile(T_ZiyanPlaybackInfo *playbackInfo, const char *filePath,
  78 + uint16_t index);
  79 +static T_ZiyanReturnCode ZiyanPlayback_SeekPlay(T_ZiyanPlaybackInfo *playbackInfo, uint32_t seekPos);
  80 +static T_ZiyanReturnCode ZiyanPlayback_StartPlay(T_ZiyanPlaybackInfo *playbackInfo);
  81 +static T_ZiyanReturnCode ZiyanPlayback_GetPlaybackStatus(T_ZiyanPlaybackInfo *playbackInfo,
  82 + T_ZiyanCameraPlaybackStatus *playbackStatus);
  83 +static T_ZiyanReturnCode ZiyanPlayback_GetVideoLengthMs(const char *filePath, uint32_t *videoLengthMs);
  84 +static T_ZiyanReturnCode ZiyanPlayback_StartPlayProcess(const char *filePath, uint32_t playPosMs);
  85 +static T_ZiyanReturnCode ZiyanPlayback_StopPlayProcess(void);
  86 +static T_ZiyanReturnCode
  87 +ZiyanPlayback_VideoFileTranscode(const char *inPath, const char *outFormat, char *outPath, uint16_t outPathBufferSize);
  88 +static T_ZiyanReturnCode
  89 +ZiyanPlayback_GetFrameInfoOfVideoFile(const char *path, T_TestPayloadCameraVideoFrameInfo *frameInfo,
  90 + uint32_t frameInfoBufferCount, uint32_t *frameCount);
  91 +static T_ZiyanReturnCode ZiyanPlayback_GetFrameRateOfVideoFile(const char *path, float *frameRate);
  92 +static T_ZiyanReturnCode
  93 +ZiyanPlayback_GetFrameNumberByTime(T_TestPayloadCameraVideoFrameInfo *frameInfo, uint32_t frameCount,
  94 + uint32_t *frameNumber, uint32_t timeMs);
  95 +static T_ZiyanReturnCode GetMediaFileDir(char *dirPath);
  96 +static T_ZiyanReturnCode GetMediaFileOriginData(const char *filePath, uint32_t offset, uint32_t length,
  97 + uint8_t *data);
  98 +
  99 +static T_ZiyanReturnCode CreateMediaFileThumbNail(const char *filePath);
  100 +static T_ZiyanReturnCode GetMediaFileThumbNailInfo(const char *filePath, T_ZiyanCameraMediaFileInfo *fileInfo);
  101 +static T_ZiyanReturnCode GetMediaFileThumbNailData(const char *filePath, uint32_t offset, uint32_t length,
  102 + uint8_t *data);
  103 +static T_ZiyanReturnCode DestroyMediaFileThumbNail(const char *filePath);
  104 +
  105 +static T_ZiyanReturnCode CreateMediaFileScreenNail(const char *filePath);
  106 +static T_ZiyanReturnCode GetMediaFileScreenNailInfo(const char *filePath, T_ZiyanCameraMediaFileInfo *fileInfo);
  107 +static T_ZiyanReturnCode GetMediaFileScreenNailData(const char *filePath, uint32_t offset, uint32_t length,
  108 + uint8_t *data);
  109 +static T_ZiyanReturnCode DestroyMediaFileScreenNail(const char *filePath);
  110 +
  111 +static T_ZiyanReturnCode DeleteMediaFile(char *filePath);
  112 +static T_ZiyanReturnCode SetMediaPlaybackFile(const char *filePath);
  113 +static T_ZiyanReturnCode StartMediaPlayback(void);
  114 +static T_ZiyanReturnCode StopMediaPlayback(void);
  115 +static T_ZiyanReturnCode PauseMediaPlayback(void);
  116 +static T_ZiyanReturnCode SeekMediaPlayback(uint32_t playbackPosition);
  117 +static T_ZiyanReturnCode GetMediaPlaybackStatus(T_ZiyanCameraPlaybackStatus *status);
  118 +
  119 +static T_ZiyanReturnCode StartDownloadNotification(void);
  120 +static T_ZiyanReturnCode StopDownloadNotification(void);
  121 +
  122 +_Noreturn static void *UserCameraMedia_SendVideoTask(void *arg);
  123 +
  124 +/* Private variables -------------------------------------------------------------*/
  125 +static T_ZiyanCameraMediaDownloadPlaybackHandler s_psdkCameraMedia = {0};
  126 +static T_ZiyanPlaybackInfo s_playbackInfo = {0};
  127 +static T_ZiyanTaskHandle s_userSendVideoThread;
  128 +static T_UtilBuffer s_mediaPlayCommandBufferHandler = {0};
  129 +static T_ZiyanMutexHandle s_mediaPlayCommandBufferMutex = {0};
  130 +static T_ZiyanSemaHandle s_mediaPlayWorkSem = NULL;
  131 +static uint8_t s_mediaPlayCommandBuffer[sizeof(T_TestPayloadCameraPlaybackCommand) * 32] = {0};
  132 +static const char *s_frameKeyChar = "[PACKET]";
  133 +static const char *s_frameDurationTimeKeyChar = "duration_time";
  134 +static const char *s_framePositionKeyChar = "pos";
  135 +static const char *s_frameSizeKeyChar = "size";
  136 +static T_ZiyanMediaFileHandle s_mediaFileThumbNailHandle;
  137 +static T_ZiyanMediaFileHandle s_mediaFileScreenNailHandle;
  138 +static const uint8_t s_frameAudInfo[VIDEO_FRAME_AUD_LEN] = {0x00, 0x00, 0x00, 0x01, 0x09, 0x10};
  139 +static char s_mediaFileDirPath[ZIYAN_FILE_PATH_SIZE_MAX] = {0};
  140 +static bool s_isMediaFileDirPathConfigured = false;
  141 +
  142 +/* Exported functions definition ---------------------------------------------*/
  143 +T_ZiyanReturnCode ZiyanTest_CameraEmuMediaStartService(void)
  144 +{
  145 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  146 + T_ZiyanReturnCode returnCode;
  147 + const T_ZiyanDataChannelBandwidthProportionOfHighspeedChannel bandwidthProportionOfHighspeedChannel =
  148 + {10, 60, 30};
  149 + T_ZiyanAircraftInfoBaseInfo aircraftInfoBaseInfo = {0};
  150 +
  151 + if (ZiyanAircraftInfo_GetBaseInfo(&aircraftInfoBaseInfo) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  152 + USER_LOG_ERROR("get aircraft information error.");
  153 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  154 + }
  155 +
  156 + s_psdkCameraMedia.GetMediaFileDir = GetMediaFileDir;
  157 + s_psdkCameraMedia.GetMediaFileOriginInfo = ZiyanTest_CameraMediaGetFileInfo;
  158 + s_psdkCameraMedia.GetMediaFileOriginData = GetMediaFileOriginData;
  159 +
  160 + s_psdkCameraMedia.CreateMediaFileThumbNail = CreateMediaFileThumbNail;
  161 + s_psdkCameraMedia.GetMediaFileThumbNailInfo = GetMediaFileThumbNailInfo;
  162 + s_psdkCameraMedia.GetMediaFileThumbNailData = GetMediaFileThumbNailData;
  163 + s_psdkCameraMedia.DestroyMediaFileThumbNail = DestroyMediaFileThumbNail;
  164 +
  165 + s_psdkCameraMedia.CreateMediaFileScreenNail = CreateMediaFileScreenNail;
  166 + s_psdkCameraMedia.GetMediaFileScreenNailInfo = GetMediaFileScreenNailInfo;
  167 + s_psdkCameraMedia.GetMediaFileScreenNailData = GetMediaFileScreenNailData;
  168 + s_psdkCameraMedia.DestroyMediaFileScreenNail = DestroyMediaFileScreenNail;
  169 +
  170 + s_psdkCameraMedia.DeleteMediaFile = DeleteMediaFile;
  171 +
  172 + s_psdkCameraMedia.SetMediaPlaybackFile = SetMediaPlaybackFile;
  173 +
  174 + s_psdkCameraMedia.StartMediaPlayback = StartMediaPlayback;
  175 + s_psdkCameraMedia.StopMediaPlayback = StopMediaPlayback;
  176 + s_psdkCameraMedia.PauseMediaPlayback = PauseMediaPlayback;
  177 + s_psdkCameraMedia.SeekMediaPlayback = SeekMediaPlayback;
  178 + s_psdkCameraMedia.GetMediaPlaybackStatus = GetMediaPlaybackStatus;
  179 +
  180 + s_psdkCameraMedia.StartDownloadNotification = StartDownloadNotification;
  181 + s_psdkCameraMedia.StopDownloadNotification = StopDownloadNotification;
  182 +
  183 + if (ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS != osalHandler->SemaphoreCreate(0, &s_mediaPlayWorkSem)) {
  184 + USER_LOG_ERROR("SemaphoreCreate(\"%s\") error.", "s_mediaPlayWorkSem");
  185 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  186 + }
  187 +
  188 + if (osalHandler->MutexCreate(&s_mediaPlayCommandBufferMutex) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  189 + USER_LOG_ERROR("mutex create error");
  190 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  191 + }
  192 +
  193 + UtilBuffer_Init(&s_mediaPlayCommandBufferHandler, s_mediaPlayCommandBuffer, sizeof(s_mediaPlayCommandBuffer));
  194 +
  195 + if (aircraftInfoBaseInfo.aircraftType == ZIYAN_AIRCRAFT_TYPE_SHADOW_PLUS ||
  196 + aircraftInfoBaseInfo.aircraftType == ZIYAN_AIRCRAFT_TYPE_SHADOW_MAX) {
  197 + returnCode = ZiyanPayloadCamera_RegMediaDownloadPlaybackHandler(&s_psdkCameraMedia);
  198 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  199 + USER_LOG_ERROR("psdk camera media function init error.");
  200 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  201 + }
  202 + }
  203 +
  204 + returnCode = ZiyanHighSpeedDataChannel_SetBandwidthProportion(bandwidthProportionOfHighspeedChannel);
  205 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  206 + USER_LOG_ERROR("Set data channel bandwidth width proportion error.");
  207 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  208 + }
  209 +
  210 + if (ZiyanPlatform_GetHalNetworkHandler() != NULL || ZiyanPlatform_GetHalUsbBulkHandler() != NULL) {
  211 + returnCode = osalHandler->TaskCreate("user_camera_media_task", UserCameraMedia_SendVideoTask, 2048,
  212 + NULL, &s_userSendVideoThread);
  213 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  214 + USER_LOG_ERROR("user send video task create error.");
  215 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  216 + }
  217 + }
  218 +
  219 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  220 +}
  221 +
  222 +T_ZiyanReturnCode ZiyanTest_CameraEmuSetMediaFilePath(const char *path)
  223 +{
  224 + memset(s_mediaFileDirPath, 0, sizeof(s_mediaFileDirPath));
  225 + memcpy(s_mediaFileDirPath, path, USER_UTIL_MIN(strlen(path), sizeof(s_mediaFileDirPath) - 1));
  226 + s_isMediaFileDirPathConfigured = true;
  227 +
  228 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  229 +}
  230 +
  231 +T_ZiyanReturnCode ZiyanTest_CameraMediaGetFileInfo(const char *filePath, T_ZiyanCameraMediaFileInfo *fileInfo)
  232 +{
  233 + T_ZiyanReturnCode returnCode;
  234 + T_ZiyanMediaFileHandle mediaFileHandle;
  235 +
  236 + returnCode = ZiyanMediaFile_CreateHandle(filePath, &mediaFileHandle);
  237 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  238 + USER_LOG_ERROR("Media file create handle error stat:0x%08llX", returnCode);
  239 + return returnCode;
  240 + }
  241 +
  242 + returnCode = ZiyanMediaFile_GetMediaFileType(mediaFileHandle, &fileInfo->type);
  243 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  244 + USER_LOG_ERROR("Media file get type error stat:0x%08llX", returnCode);
  245 + goto out;
  246 + }
  247 +
  248 + returnCode = ZiyanMediaFile_GetMediaFileAttr(mediaFileHandle, &fileInfo->mediaFileAttr);
  249 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  250 + USER_LOG_ERROR("Media file get attr error stat:0x%08llX", returnCode);
  251 + goto out;
  252 + }
  253 +
  254 + returnCode = ZiyanMediaFile_GetFileSizeOrg(mediaFileHandle, &fileInfo->fileSize);
  255 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  256 + USER_LOG_ERROR("Media file get size error stat:0x%08llX", returnCode);
  257 + goto out;
  258 + }
  259 +
  260 +out:
  261 + returnCode = ZiyanMediaFile_DestroyHandle(mediaFileHandle);
  262 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  263 + USER_LOG_ERROR("Media file destroy handle error stat:0x%08llX", returnCode);
  264 + return returnCode;
  265 + }
  266 +
  267 + return returnCode;
  268 +}
  269 +
  270 +/* Private functions definition-----------------------------------------------*/
  271 +static T_ZiyanReturnCode ZiyanPlayback_StopPlay(T_ZiyanPlaybackInfo *playbackInfo)
  272 +{
  273 + T_ZiyanReturnCode returnCode;
  274 +
  275 + returnCode = ZiyanPlayback_StopPlayProcess();
  276 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  277 + USER_LOG_ERROR("stop play error ");
  278 + }
  279 +
  280 + playbackInfo->isInPlayProcess = 0;
  281 + playbackInfo->playPosMs = 0;
  282 +
  283 + return returnCode;
  284 +}
  285 +
  286 +static T_ZiyanReturnCode ZiyanPlayback_PausePlay(T_ZiyanPlaybackInfo *playbackInfo)
  287 +{
  288 + T_ZiyanReturnCode returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  289 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  290 +
  291 + T_TestPayloadCameraPlaybackCommand playbackCommand = {0};
  292 + if (playbackInfo->isInPlayProcess) {
  293 + playbackCommand.command = TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_PAUSE;
  294 +
  295 + if (osalHandler->MutexLock(s_mediaPlayCommandBufferMutex) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  296 + USER_LOG_ERROR("mutex lock error");
  297 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  298 + }
  299 +
  300 + if (UtilBuffer_GetUnusedSize(&s_mediaPlayCommandBufferHandler) >= sizeof(T_TestPayloadCameraPlaybackCommand)) {
  301 + UtilBuffer_Put(&s_mediaPlayCommandBufferHandler, (const uint8_t *) &playbackCommand,
  302 + sizeof(T_TestPayloadCameraPlaybackCommand));
  303 + } else {
  304 + USER_LOG_ERROR("Media playback command buffer is full.");
  305 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_OUT_OF_RANGE;
  306 + }
  307 +
  308 + if (osalHandler->MutexUnlock(s_mediaPlayCommandBufferMutex) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  309 + USER_LOG_ERROR("mutex unlock error");
  310 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  311 + }
  312 + osalHandler->SemaphorePost(s_mediaPlayWorkSem);
  313 + }
  314 +
  315 + playbackInfo->isInPlayProcess = 0;
  316 +
  317 + return returnCode;
  318 +}
  319 +
  320 +static T_ZiyanReturnCode ZiyanPlayback_SetPlayFile(T_ZiyanPlaybackInfo *playbackInfo, const char *filePath, uint16_t index)
  321 +{
  322 + T_ZiyanReturnCode returnCode;
  323 +
  324 + if (strlen(filePath) > ZIYAN_FILE_PATH_SIZE_MAX) {
  325 + USER_LOG_ERROR("Ziyan playback file path out of length range error\n");
  326 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  327 + }
  328 +
  329 + strcpy(playbackInfo->filePath, filePath);
  330 + playbackInfo->videoIndex = index;
  331 +
  332 + returnCode = ZiyanPlayback_GetVideoLengthMs(filePath, &playbackInfo->videoLengthMs);
  333 +
  334 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  335 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  336 + }
  337 +
  338 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  339 +}
  340 +
  341 +static T_ZiyanReturnCode ZiyanPlayback_SeekPlay(T_ZiyanPlaybackInfo *playbackInfo, uint32_t seekPos)
  342 +{
  343 + T_ZiyanRunTimeStamps ti;
  344 + T_ZiyanReturnCode returnCode;
  345 +
  346 + returnCode = ZiyanPlayback_PausePlay(playbackInfo);
  347 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  348 + USER_LOG_ERROR("pause play error \n");
  349 + return returnCode;
  350 + }
  351 +
  352 + playbackInfo->playPosMs = seekPos;
  353 + returnCode = ZiyanPlayback_StartPlayProcess(playbackInfo->filePath, playbackInfo->playPosMs);
  354 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  355 + USER_LOG_ERROR("start playback process error \n");
  356 + return returnCode;
  357 + }
  358 +
  359 + playbackInfo->isInPlayProcess = 1;
  360 + ti = ZiyanUtilTime_GetRunTimeStamps();
  361 + playbackInfo->startPlayTimestampsUs = ti.realUsec - playbackInfo->playPosMs * 1000;
  362 +
  363 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  364 +}
  365 +
  366 +static T_ZiyanReturnCode ZiyanPlayback_StartPlay(T_ZiyanPlaybackInfo *playbackInfo)
  367 +{
  368 + T_ZiyanRunTimeStamps ti;
  369 + T_ZiyanReturnCode returnCode;
  370 +
  371 + if (playbackInfo->isInPlayProcess == 1) {
  372 + //already in playing, return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS
  373 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  374 + }
  375 +
  376 + returnCode = ZiyanPlayback_StartPlayProcess(playbackInfo->filePath, playbackInfo->playPosMs);
  377 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  378 + USER_LOG_ERROR("start play process error \n");
  379 + return returnCode;
  380 + }
  381 +
  382 + playbackInfo->isInPlayProcess = 1;
  383 +
  384 + ti = ZiyanUtilTime_GetRunTimeStamps();
  385 + playbackInfo->startPlayTimestampsUs = ti.realUsec - playbackInfo->playPosMs * 1000;
  386 +
  387 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  388 +}
  389 +
  390 +static T_ZiyanReturnCode ZiyanPlayback_GetPlaybackStatus(T_ZiyanPlaybackInfo *playbackInfo,
  391 + T_ZiyanCameraPlaybackStatus *playbackStatus)
  392 +{
  393 + T_ZiyanRunTimeStamps timeStamps;
  394 +
  395 + memset(playbackStatus, 0, sizeof(T_ZiyanCameraPlaybackStatus));
  396 +
  397 + //update playback pos info
  398 + if (playbackInfo->isInPlayProcess) {
  399 + timeStamps = ZiyanUtilTime_GetRunTimeStamps();
  400 + playbackInfo->playPosMs = (timeStamps.realUsec - playbackInfo->startPlayTimestampsUs) / 1000;
  401 +
  402 + if (playbackInfo->playPosMs >= playbackInfo->videoLengthMs) {
  403 + if (ZiyanPlayback_PausePlay(playbackInfo) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  404 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  405 + }
  406 + }
  407 + }
  408 +
  409 + //set playback status
  410 + if (playbackInfo->isInPlayProcess == 0 && playbackInfo->playPosMs != 0) {
  411 + playbackStatus->playbackMode = ZIYAN_CAMERA_PLAYBACK_MODE_PAUSE;
  412 + } else if (playbackInfo->isInPlayProcess) {
  413 + playbackStatus->playbackMode = ZIYAN_CAMERA_PLAYBACK_MODE_PLAY;
  414 + } else {
  415 + playbackStatus->playbackMode = ZIYAN_CAMERA_PLAYBACK_MODE_STOP;
  416 + }
  417 +
  418 + playbackStatus->playPosMs = playbackInfo->playPosMs;
  419 + playbackStatus->videoLengthMs = playbackInfo->videoLengthMs;
  420 +
  421 + if (playbackInfo->videoLengthMs != 0) {
  422 + playbackStatus->videoPlayProcess =
  423 + (playbackInfo->videoLengthMs - playbackInfo->playPosMs) / playbackInfo->videoLengthMs;
  424 + } else {
  425 + playbackStatus->videoPlayProcess = 0;
  426 + }
  427 +
  428 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  429 +}
  430 +
  431 +static T_ZiyanReturnCode ZiyanPlayback_GetVideoLengthMs(const char *filePath, uint32_t *videoLengthMs)
  432 +{
  433 + FILE *fp;
  434 + T_ZiyanReturnCode returnCode;
  435 + char ffmpegCmdStr[FFMPEG_CMD_BUF_SIZE];
  436 + float hour, minute, second;
  437 + char tempTailStr[128];
  438 + int ret;
  439 +
  440 + snprintf(ffmpegCmdStr, FFMPEG_CMD_BUF_SIZE, "ffmpeg -i \"%s\" 2>&1 | grep \"Duration\"", filePath);
  441 + fp = popen(ffmpegCmdStr, "r");
  442 +
  443 + if (fp == NULL) {
  444 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  445 + }
  446 +
  447 + ret = fscanf(fp, " Duration: %f:%f:%f,%127s", &hour, &minute, &second, tempTailStr);
  448 + if (ret <= 0) {
  449 + USER_LOG_ERROR("MP4 File Get Duration Error\n");
  450 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  451 + goto out;
  452 + }
  453 +
  454 + *videoLengthMs = (uint32_t) ((hour * 3600 + minute * 60 + second) * 1000);
  455 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  456 +
  457 +out:
  458 + pclose(fp);
  459 +
  460 + return returnCode;
  461 +}
  462 +
  463 +static T_ZiyanReturnCode ZiyanPlayback_StartPlayProcess(const char *filePath, uint32_t playPosMs)
  464 +{
  465 + T_ZiyanReturnCode returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  466 + T_TestPayloadCameraPlaybackCommand mediaPlayCommand = {0};
  467 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  468 +
  469 + mediaPlayCommand.command = TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_START;
  470 + mediaPlayCommand.timeMs = playPosMs;
  471 +
  472 + if (strlen(filePath) >= sizeof(mediaPlayCommand.path)) {
  473 + USER_LOG_ERROR("File path is too long.");
  474 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_OUT_OF_RANGE;
  475 + }
  476 + memcpy(mediaPlayCommand.path, filePath, strlen(filePath));
  477 +
  478 + if (osalHandler->MutexLock(s_mediaPlayCommandBufferMutex) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  479 + USER_LOG_ERROR("mutex lock error");
  480 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  481 + }
  482 +
  483 + if (UtilBuffer_GetUnusedSize(&s_mediaPlayCommandBufferHandler) >= sizeof(T_TestPayloadCameraPlaybackCommand)) {
  484 + UtilBuffer_Put(&s_mediaPlayCommandBufferHandler, (const uint8_t *) &mediaPlayCommand,
  485 + sizeof(T_TestPayloadCameraPlaybackCommand));
  486 + } else {
  487 + USER_LOG_ERROR("Media playback command buffer is full.");
  488 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_OUT_OF_RANGE;
  489 + }
  490 +
  491 + if (osalHandler->MutexUnlock(s_mediaPlayCommandBufferMutex) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  492 + USER_LOG_ERROR("mutex unlock error");
  493 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  494 + }
  495 + osalHandler->SemaphorePost(s_mediaPlayWorkSem);
  496 + return returnCode;
  497 +}
  498 +
  499 +static T_ZiyanReturnCode ZiyanPlayback_StopPlayProcess(void)
  500 +{
  501 + T_ZiyanReturnCode returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  502 + T_TestPayloadCameraPlaybackCommand playbackCommand = {0};
  503 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  504 +
  505 + playbackCommand.command = TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_STOP;
  506 +
  507 + if (osalHandler->MutexLock(s_mediaPlayCommandBufferMutex) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  508 + USER_LOG_ERROR("mutex lock error");
  509 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  510 + }
  511 +
  512 + if (UtilBuffer_GetUnusedSize(&s_mediaPlayCommandBufferHandler) >= sizeof(T_TestPayloadCameraPlaybackCommand)) {
  513 + UtilBuffer_Put(&s_mediaPlayCommandBufferHandler, (const uint8_t *) &playbackCommand,
  514 + sizeof(T_TestPayloadCameraPlaybackCommand));
  515 + } else {
  516 + USER_LOG_ERROR("Media playback command buffer is full.");
  517 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_OUT_OF_RANGE;
  518 + }
  519 +
  520 + if (osalHandler->MutexUnlock(s_mediaPlayCommandBufferMutex) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  521 + USER_LOG_ERROR("mutex unlock error");
  522 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  523 + }
  524 + osalHandler->SemaphorePost(s_mediaPlayWorkSem);
  525 + return returnCode;
  526 +}
  527 +
  528 +static T_ZiyanReturnCode ZiyanPlayback_VideoFileTranscode(const char *inPath, const char *outFormat, char *outPath,
  529 + uint16_t outPathBufferSize)
  530 +{
  531 + T_ZiyanReturnCode returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  532 + T_ZiyanReturnCode ziyanStatus = ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  533 + FILE *fpCommand = NULL;
  534 + char ffmpegCmdStr[FFMPEG_CMD_BUF_SIZE];
  535 + char *directory = NULL;
  536 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  537 +
  538 + directory = osalHandler->Malloc(ZIYAN_FILE_PATH_SIZE_MAX);
  539 + if (directory == NULL) {
  540 + USER_LOG_ERROR("malloc memory for directory fail.");
  541 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_MEMORY_ALLOC_FAILED;
  542 + }
  543 +
  544 + ziyanStatus = ZiyanUserUtil_GetCurrentFileDirPath(inPath, ZIYAN_FILE_PATH_SIZE_MAX, directory);
  545 + if (ziyanStatus != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  546 + USER_LOG_ERROR("get directory of file error: 0x%08llX.", ziyanStatus);
  547 + returnCode = ziyanStatus;
  548 + goto out;
  549 + }
  550 +
  551 + snprintf(outPath, outPathBufferSize, "%sout.%s", directory, outFormat);
  552 + snprintf(ffmpegCmdStr, FFMPEG_CMD_BUF_SIZE,
  553 + "echo \"y\" | ffmpeg -i \"%s\" -codec copy -f \"%s\" \"%s\" 1>/dev/null 2>&1", inPath,
  554 + outFormat, outPath);
  555 + fpCommand = popen(ffmpegCmdStr, "r");
  556 + if (fpCommand == NULL) {
  557 + USER_LOG_ERROR("execute transcode command fail.");
  558 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  559 + goto out;
  560 + }
  561 +
  562 + pclose(fpCommand);
  563 +
  564 +out:
  565 + osalHandler->Free(directory);
  566 +
  567 + return returnCode;
  568 +}
  569 +
  570 +static T_ZiyanReturnCode
  571 +ZiyanPlayback_GetFrameInfoOfVideoFile(const char *path, T_TestPayloadCameraVideoFrameInfo *frameInfo,
  572 + uint32_t frameInfoBufferCount, uint32_t *frameCount)
  573 +{
  574 + long ret;
  575 + T_ZiyanReturnCode returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  576 + FILE *fpCommand = NULL;
  577 + char ffmpegCmdStr[FFMPEG_CMD_BUF_SIZE];
  578 + char *frameInfoString = NULL;
  579 + char *frameLocation = NULL;
  580 + char frameParameterFormat[50] = {0};
  581 + char *frameDurationTimeLocation = NULL;
  582 + float frameDurationTimeS = 0;
  583 + uint32_t frameNumber = 0;
  584 + char *framePositionLocation = NULL;
  585 + uint32_t framePosition = 0;
  586 + char *frameSizeLocation = NULL;
  587 + uint32_t frameSize = 0;
  588 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  589 +
  590 + frameInfoString = osalHandler->Malloc(VIDEO_FRAME_MAX_COUNT * 1024);
  591 + if (frameInfoString == NULL) {
  592 + USER_LOG_ERROR("malloc memory for frame info fail.");
  593 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_MEMORY_ALLOC_FAILED;
  594 + }
  595 + memset(frameInfoString, 0, VIDEO_FRAME_MAX_COUNT * 1024);
  596 +
  597 + snprintf(ffmpegCmdStr, FFMPEG_CMD_BUF_SIZE, "ffprobe -show_packets \"%s\" 2>/dev/null", path);
  598 + fpCommand = popen(ffmpegCmdStr, "r");
  599 + if (fpCommand == NULL) {
  600 + USER_LOG_ERROR("execute show frames commands fail.");
  601 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  602 + goto out2;
  603 + }
  604 +
  605 + ret = (long) fread(frameInfoString, 1, VIDEO_FRAME_MAX_COUNT * 1024, fpCommand);
  606 + if (ret < 0) {
  607 + USER_LOG_ERROR("read show frames commands result error.");
  608 + goto out1;
  609 + }
  610 + frameInfoString[ret] = '\0';
  611 +
  612 + frameLocation = frameInfoString;
  613 + *frameCount = 0;
  614 + while (1) {
  615 + // find frame
  616 + frameLocation = strstr(frameLocation, s_frameKeyChar);
  617 + if (frameLocation == NULL) {
  618 + USER_LOG_DEBUG("reach file tail.");
  619 + break;
  620 + }
  621 +
  622 + // find frame duration
  623 + frameDurationTimeLocation = strstr(frameLocation, s_frameDurationTimeKeyChar);
  624 + if (frameDurationTimeLocation == NULL) {
  625 + USER_LOG_ERROR("can not find pkt_duration_time.");
  626 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  627 + goto out1;
  628 + }
  629 +
  630 + ret = snprintf(frameParameterFormat, sizeof(frameParameterFormat), "%s=%%f", s_frameDurationTimeKeyChar);
  631 + if (ret < 0) {
  632 + USER_LOG_ERROR("snprintf frameParameterFormat fail.");
  633 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  634 + goto out1;
  635 + }
  636 +
  637 + ret = sscanf(frameDurationTimeLocation, frameParameterFormat, &frameDurationTimeS);
  638 + if (ret <= 0) {
  639 + USER_LOG_ERROR("can not find pkt_duration_time.");
  640 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  641 + goto out1;
  642 + }
  643 + frameInfo[frameNumber].durationS = frameDurationTimeS;
  644 +
  645 + // find frame position
  646 + framePositionLocation = strstr(frameLocation, s_framePositionKeyChar);
  647 + if (framePositionLocation == NULL) {
  648 + USER_LOG_ERROR("can not found pkt_pos.");
  649 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  650 + goto out1;
  651 + }
  652 +
  653 + ret = snprintf(frameParameterFormat, sizeof(frameParameterFormat), "%s=%%d", s_framePositionKeyChar);
  654 + if (ret < 0) {
  655 + USER_LOG_ERROR("snprintf frameParameterFormat fail.");
  656 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  657 + goto out1;
  658 + }
  659 +
  660 + ret = sscanf(framePositionLocation, frameParameterFormat, &framePosition);
  661 + if (ret <= 0) {
  662 + USER_LOG_ERROR("can not found pkt_pos.");
  663 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  664 + goto out1;
  665 + }
  666 + frameInfo[frameNumber].positionInFile = framePosition;
  667 +
  668 + // find frame size
  669 + frameSizeLocation = strstr(frameLocation, s_frameSizeKeyChar);
  670 + if (frameSizeLocation == NULL) {
  671 + USER_LOG_ERROR("can not found pkt_size.");
  672 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  673 + goto out1;
  674 + }
  675 +
  676 + ret = snprintf(frameParameterFormat, sizeof(frameParameterFormat), "%s=%%d", s_frameSizeKeyChar);
  677 + if (ret < 0) {
  678 + USER_LOG_ERROR("snprintf frameParameterFormat fail.");
  679 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  680 + goto out1;
  681 + }
  682 +
  683 + ret = sscanf(frameSizeLocation, frameParameterFormat, &frameSize);
  684 + if (ret <= 0) {
  685 + USER_LOG_ERROR("can not find pkt_size.");
  686 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  687 + goto out1;
  688 + }
  689 + frameInfo[frameNumber].size = frameSize;
  690 +
  691 + frameLocation += strlen(s_frameKeyChar);
  692 + frameNumber++;
  693 + (*frameCount)++;
  694 +
  695 + if (frameNumber >= frameInfoBufferCount) {
  696 + USER_LOG_ERROR("frame buffer is full.");
  697 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_OUT_OF_RANGE;
  698 + goto out1;
  699 + }
  700 + }
  701 +
  702 +out1:
  703 + pclose(fpCommand);
  704 +
  705 +out2:
  706 + osalHandler->Free(frameInfoString);
  707 +
  708 + return returnCode;
  709 +}
  710 +
  711 +static T_ZiyanReturnCode ZiyanPlayback_GetFrameRateOfVideoFile(const char *path, float *frameRate)
  712 +{
  713 + int ret;
  714 + T_ZiyanReturnCode returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  715 + FILE *fpCommand = NULL;
  716 + char ffmpegCmdStr[FFMPEG_CMD_BUF_SIZE] = {0};
  717 + int frameRateMolecule = 0;
  718 + int frameRateDenominator = 0;
  719 +
  720 + snprintf(ffmpegCmdStr, FFMPEG_CMD_BUF_SIZE, "ffprobe -show_streams \"%s\" 2>/dev/null | grep r_frame_rate", path);
  721 + fpCommand = popen(ffmpegCmdStr, "r");
  722 + if (fpCommand == NULL) {
  723 + USER_LOG_ERROR("execute show frame rate command fail.");
  724 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  725 + }
  726 +
  727 + ret = fscanf(fpCommand, "r_frame_rate=%d/%d", &frameRateMolecule, &frameRateDenominator);
  728 + if (ret <= 0) {
  729 + USER_LOG_ERROR("can not find frame rate.");
  730 + returnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  731 + goto out;
  732 + }
  733 + *frameRate = (float) frameRateMolecule / (float) frameRateDenominator;
  734 +
  735 +out:
  736 + pclose(fpCommand);
  737 +
  738 + return returnCode;
  739 +}
  740 +
  741 +static T_ZiyanReturnCode ZiyanPlayback_GetFrameNumberByTime(T_TestPayloadCameraVideoFrameInfo *frameInfo,
  742 + uint32_t frameCount, uint32_t *frameNumber, uint32_t timeMs)
  743 +{
  744 + uint32_t i = 0;
  745 + double camulativeTimeS = 0;
  746 + double timeS = (double) timeMs / 1000.0;
  747 +
  748 + for (i = 0; i < frameCount; ++i) {
  749 + camulativeTimeS += frameInfo[i].durationS;
  750 +
  751 + if (camulativeTimeS >= timeS) {
  752 + *frameNumber = i;
  753 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  754 + }
  755 + }
  756 +
  757 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  758 +}
  759 +
  760 +static T_ZiyanReturnCode GetMediaFileDir(char *dirPath)
  761 +{
  762 + T_ZiyanReturnCode returnCode;
  763 + char curFileDirPath[ZIYAN_FILE_PATH_SIZE_MAX];
  764 + char tempPath[ZIYAN_FILE_PATH_SIZE_MAX];
  765 +
  766 + returnCode = ZiyanUserUtil_GetCurrentFileDirPath(__FILE__, ZIYAN_FILE_PATH_SIZE_MAX, curFileDirPath);
  767 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  768 + USER_LOG_ERROR("Get file current path error, stat = 0x%08llX", returnCode);
  769 + return returnCode;
  770 + }
  771 +
  772 + snprintf(dirPath, ZIYAN_FILE_PATH_SIZE_MAX, "%smedia_file", curFileDirPath);
  773 +
  774 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  775 +}
  776 +
  777 +static T_ZiyanReturnCode GetMediaFileOriginData(const char *filePath, uint32_t offset, uint32_t length, uint8_t *data)
  778 +{
  779 + T_ZiyanReturnCode returnCode;
  780 + uint32_t realLen = 0;
  781 + T_ZiyanMediaFileHandle mediaFileHandle;
  782 +
  783 + returnCode = ZiyanMediaFile_CreateHandle(filePath, &mediaFileHandle);
  784 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  785 + USER_LOG_ERROR("Media file create handle error stat:0x%08llX", returnCode);
  786 + return returnCode;
  787 + }
  788 +
  789 + returnCode = ZiyanMediaFile_GetDataOrg(mediaFileHandle, offset, length, data, &realLen);
  790 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  791 + USER_LOG_ERROR("Media file get data error stat:0x%08llX", returnCode);
  792 + return returnCode;
  793 + }
  794 +
  795 + returnCode = ZiyanMediaFile_DestroyHandle(mediaFileHandle);
  796 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  797 + USER_LOG_ERROR("Media file destroy handle error stat:0x%08llX", returnCode);
  798 + return returnCode;
  799 + }
  800 +
  801 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  802 +}
  803 +
  804 +static T_ZiyanReturnCode CreateMediaFileThumbNail(const char *filePath)
  805 +{
  806 + T_ZiyanReturnCode returnCode;
  807 +
  808 + returnCode = ZiyanMediaFile_CreateHandle(filePath, &s_mediaFileThumbNailHandle);
  809 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  810 + USER_LOG_ERROR("Media file create handle error stat:0x%08llX", returnCode);
  811 + return returnCode;
  812 + }
  813 +
  814 + returnCode = ZiyanMediaFile_CreateThm(s_mediaFileThumbNailHandle);
  815 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  816 + USER_LOG_ERROR("Media file create thumb nail error stat:0x%08llX", returnCode);
  817 + return returnCode;
  818 + }
  819 +
  820 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  821 +}
  822 +
  823 +static T_ZiyanReturnCode GetMediaFileThumbNailInfo(const char *filePath, T_ZiyanCameraMediaFileInfo *fileInfo)
  824 +{
  825 + T_ZiyanReturnCode returnCode;
  826 +
  827 + USER_UTIL_UNUSED(filePath);
  828 +
  829 + if (s_mediaFileThumbNailHandle == NULL) {
  830 + USER_LOG_ERROR("Media file thumb nail handle null error");
  831 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  832 + }
  833 +
  834 + returnCode = ZiyanMediaFile_GetMediaFileType(s_mediaFileThumbNailHandle, &fileInfo->type);
  835 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  836 + USER_LOG_ERROR("Media file get type error stat:0x%08llX", returnCode);
  837 + return returnCode;
  838 + }
  839 +
  840 + returnCode = ZiyanMediaFile_GetMediaFileAttr(s_mediaFileThumbNailHandle, &fileInfo->mediaFileAttr);
  841 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  842 + USER_LOG_ERROR("Media file get attr error stat:0x%08llX", returnCode);
  843 + return returnCode;
  844 + }
  845 +
  846 + returnCode = ZiyanMediaFile_GetFileSizeThm(s_mediaFileThumbNailHandle, &fileInfo->fileSize);
  847 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  848 + USER_LOG_ERROR("Media file get size error stat:0x%08llX", returnCode);
  849 + return returnCode;
  850 + }
  851 +
  852 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  853 +}
  854 +
  855 +static T_ZiyanReturnCode GetMediaFileThumbNailData(const char *filePath, uint32_t offset, uint32_t length, uint8_t *data)
  856 +{
  857 + T_ZiyanReturnCode returnCode;
  858 + uint16_t realLen = 0;
  859 +
  860 + USER_UTIL_UNUSED(filePath);
  861 +
  862 + if (s_mediaFileThumbNailHandle == NULL) {
  863 + USER_LOG_ERROR("Media file thumb nail handle null error");
  864 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  865 + }
  866 +
  867 + returnCode = ZiyanMediaFile_GetDataThm(s_mediaFileThumbNailHandle, offset, length, data, &realLen);
  868 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  869 + USER_LOG_ERROR("Media file get data error stat:0x%08llX", returnCode);
  870 + return returnCode;
  871 + }
  872 +
  873 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  874 +}
  875 +
  876 +static T_ZiyanReturnCode DestroyMediaFileThumbNail(const char *filePath)
  877 +{
  878 + T_ZiyanReturnCode returnCode;
  879 +
  880 + USER_UTIL_UNUSED(filePath);
  881 +
  882 + if (s_mediaFileThumbNailHandle == NULL) {
  883 + USER_LOG_ERROR("Media file thumb nail handle null error");
  884 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  885 + }
  886 +
  887 + returnCode = ZiyanMediaFile_DestoryThm(s_mediaFileThumbNailHandle);
  888 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  889 + USER_LOG_ERROR("Media file destroy thumb nail error stat:0x%08llX", returnCode);
  890 + return returnCode;
  891 + }
  892 +
  893 + returnCode = ZiyanMediaFile_DestroyHandle(s_mediaFileThumbNailHandle);
  894 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  895 + USER_LOG_ERROR("Media file destroy handle error stat:0x%08llX", returnCode);
  896 + return returnCode;
  897 + }
  898 +
  899 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  900 +}
  901 +
  902 +static T_ZiyanReturnCode CreateMediaFileScreenNail(const char *filePath)
  903 +{
  904 + T_ZiyanReturnCode returnCode;
  905 +
  906 + returnCode = ZiyanMediaFile_CreateHandle(filePath, &s_mediaFileScreenNailHandle);
  907 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  908 + USER_LOG_ERROR("Media file create handle error stat:0x%08llX", returnCode);
  909 + return returnCode;
  910 + }
  911 +
  912 + returnCode = ZiyanMediaFile_CreateScr(s_mediaFileScreenNailHandle);
  913 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  914 + USER_LOG_ERROR("Media file create screen nail error stat:0x%08llX", returnCode);
  915 + return returnCode;
  916 + }
  917 +
  918 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  919 +}
  920 +
  921 +static T_ZiyanReturnCode GetMediaFileScreenNailInfo(const char *filePath, T_ZiyanCameraMediaFileInfo *fileInfo)
  922 +{
  923 + T_ZiyanReturnCode returnCode;
  924 +
  925 + USER_UTIL_UNUSED(filePath);
  926 +
  927 + if (s_mediaFileScreenNailHandle == NULL) {
  928 + USER_LOG_ERROR("Media file screen nail handle null error");
  929 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  930 + }
  931 +
  932 + returnCode = ZiyanMediaFile_GetMediaFileType(s_mediaFileScreenNailHandle, &fileInfo->type);
  933 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  934 + USER_LOG_ERROR("Media file get type error stat:0x%08llX", returnCode);
  935 + return returnCode;
  936 + }
  937 +
  938 + returnCode = ZiyanMediaFile_GetMediaFileAttr(s_mediaFileScreenNailHandle, &fileInfo->mediaFileAttr);
  939 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  940 + USER_LOG_ERROR("Media file get attr error stat:0x%08llX", returnCode);
  941 + return returnCode;
  942 + }
  943 +
  944 + returnCode = ZiyanMediaFile_GetFileSizeScr(s_mediaFileScreenNailHandle, &fileInfo->fileSize);
  945 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  946 + USER_LOG_ERROR("Media file get size error stat:0x%08llX", returnCode);
  947 + return returnCode;
  948 + }
  949 +
  950 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  951 +}
  952 +
  953 +static T_ZiyanReturnCode GetMediaFileScreenNailData(const char *filePath, uint32_t offset, uint32_t length,
  954 + uint8_t *data)
  955 +{
  956 + T_ZiyanReturnCode returnCode;
  957 + uint16_t realLen = 0;
  958 +
  959 + USER_UTIL_UNUSED(filePath);
  960 +
  961 + if (s_mediaFileScreenNailHandle == NULL) {
  962 + USER_LOG_ERROR("Media file screen nail handle null error");
  963 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  964 + }
  965 +
  966 + returnCode = ZiyanMediaFile_GetDataScr(s_mediaFileScreenNailHandle, offset, length, data, &realLen);
  967 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  968 + USER_LOG_ERROR("Media file get size error stat:0x%08llX", returnCode);
  969 + return returnCode;
  970 + }
  971 +
  972 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  973 +}
  974 +
  975 +static T_ZiyanReturnCode DestroyMediaFileScreenNail(const char *filePath)
  976 +{
  977 + T_ZiyanReturnCode returnCode;
  978 +
  979 + USER_UTIL_UNUSED(filePath);
  980 +
  981 + if (s_mediaFileScreenNailHandle == NULL) {
  982 + USER_LOG_ERROR("Media file screen nail handle null error");
  983 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
  984 + }
  985 +
  986 + returnCode = ZiyanMediaFile_DestroyScr(s_mediaFileScreenNailHandle);
  987 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  988 + USER_LOG_ERROR("Media file destroy screen nail error stat:0x%08llX", returnCode);
  989 + return returnCode;
  990 + }
  991 +
  992 + returnCode = ZiyanMediaFile_DestroyHandle(s_mediaFileScreenNailHandle);
  993 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  994 + USER_LOG_ERROR("Media file destroy handle error stat:0x%08llX", returnCode);
  995 + return returnCode;
  996 + }
  997 +
  998 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  999 +}
  1000 +
  1001 +static T_ZiyanReturnCode DeleteMediaFile(char *filePath)
  1002 +{
  1003 + T_ZiyanReturnCode returnCode;
  1004 +
  1005 + USER_LOG_INFO("delete media file:%s", filePath);
  1006 + returnCode = UtilFile_Delete(filePath);
  1007 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1008 + USER_LOG_ERROR("Media file delete error stat:0x%08llX", returnCode);
  1009 + return returnCode;
  1010 + }
  1011 +
  1012 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1013 +}
  1014 +
  1015 +static T_ZiyanReturnCode SetMediaPlaybackFile(const char *filePath)
  1016 +{
  1017 + USER_LOG_INFO("set media playback file:%s", filePath);
  1018 + T_ZiyanReturnCode returnCode;
  1019 +
  1020 + returnCode = ZiyanPlayback_StopPlay(&s_playbackInfo);
  1021 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1022 + return returnCode;
  1023 + }
  1024 +
  1025 + returnCode = ZiyanPlayback_SetPlayFile(&s_playbackInfo, filePath, 0);
  1026 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1027 + return returnCode;
  1028 + }
  1029 +
  1030 + returnCode = ZiyanPlayback_StartPlay(&s_playbackInfo);
  1031 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1032 + return returnCode;
  1033 + }
  1034 +
  1035 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1036 +}
  1037 +
  1038 +static T_ZiyanReturnCode StartMediaPlayback(void)
  1039 +{
  1040 + T_ZiyanReturnCode returnCode;
  1041 +
  1042 + USER_LOG_INFO("start media playback");
  1043 + returnCode = ZiyanPlayback_StartPlay(&s_playbackInfo);
  1044 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1045 + USER_LOG_ERROR("start media playback status error, stat:0x%08llX", returnCode);
  1046 + return returnCode;
  1047 + }
  1048 +
  1049 + return returnCode;
  1050 +}
  1051 +
  1052 +static T_ZiyanReturnCode StopMediaPlayback(void)
  1053 +{
  1054 + T_ZiyanReturnCode returnCode;
  1055 +
  1056 + USER_LOG_INFO("stop media playback");
  1057 + returnCode = ZiyanPlayback_StopPlay(&s_playbackInfo);
  1058 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1059 + USER_LOG_ERROR("stop media playback error, stat:0x%08llX", returnCode);
  1060 + return returnCode;
  1061 + }
  1062 +
  1063 + return returnCode;
  1064 +}
  1065 +
  1066 +static T_ZiyanReturnCode PauseMediaPlayback(void)
  1067 +{
  1068 + T_ZiyanReturnCode returnCode;
  1069 +
  1070 + USER_LOG_INFO("pause media playback");
  1071 + returnCode = ZiyanPlayback_PausePlay(&s_playbackInfo);
  1072 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1073 + USER_LOG_ERROR("pause media playback error, stat:0x%08llX", returnCode);
  1074 + return returnCode;
  1075 + }
  1076 +
  1077 + return returnCode;
  1078 +}
  1079 +
  1080 +static T_ZiyanReturnCode SeekMediaPlayback(uint32_t playbackPosition)
  1081 +{
  1082 + T_ZiyanReturnCode returnCode;
  1083 +
  1084 + USER_LOG_INFO("seek media playback:%d", playbackPosition);
  1085 + returnCode = ZiyanPlayback_SeekPlay(&s_playbackInfo, playbackPosition);
  1086 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1087 + USER_LOG_ERROR("seek media playback error, stat:0x%08llX", returnCode);
  1088 + return returnCode;
  1089 + }
  1090 +
  1091 + return returnCode;
  1092 +}
  1093 +
  1094 +static T_ZiyanReturnCode GetMediaPlaybackStatus(T_ZiyanCameraPlaybackStatus *status)
  1095 +{
  1096 + T_ZiyanReturnCode returnCode;
  1097 +
  1098 + returnCode = ZiyanPlayback_GetPlaybackStatus(&s_playbackInfo, status);
  1099 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1100 + USER_LOG_ERROR("get playback status error, stat:0x%08llX", returnCode);
  1101 + return returnCode;
  1102 + }
  1103 +
  1104 + status->videoPlayProcess = (uint8_t) (((float) s_playbackInfo.playPosMs / (float) s_playbackInfo.videoLengthMs) *
  1105 + 100);
  1106 +
  1107 + USER_LOG_DEBUG("get media playback status %d %d %d %d", status->videoPlayProcess, status->playPosMs,
  1108 + status->videoLengthMs, status->playbackMode);
  1109 +
  1110 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1111 +}
  1112 +
  1113 +static T_ZiyanReturnCode StartDownloadNotification(void)
  1114 +{
  1115 + T_ZiyanReturnCode returnCode;
  1116 + T_ZiyanDataChannelBandwidthProportionOfHighspeedChannel bandwidthProportion = {0};
  1117 +
  1118 + USER_LOG_DEBUG("media download start notification.");
  1119 +
  1120 + bandwidthProportion.dataStream = 0;
  1121 + bandwidthProportion.videoStream = 0;
  1122 + bandwidthProportion.downloadStream = 100;
  1123 +
  1124 + returnCode = ZiyanHighSpeedDataChannel_SetBandwidthProportion(bandwidthProportion);
  1125 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1126 + USER_LOG_ERROR("Set bandwidth proportion for high speed channel error, stat:0x%08llX.", returnCode);
  1127 + return returnCode;
  1128 + }
  1129 +
  1130 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1131 +}
  1132 +
  1133 +static T_ZiyanReturnCode StopDownloadNotification(void)
  1134 +{
  1135 + T_ZiyanReturnCode returnCode;
  1136 + T_ZiyanDataChannelBandwidthProportionOfHighspeedChannel bandwidthProportion = {0};
  1137 +
  1138 + USER_LOG_DEBUG("media download stop notification.");
  1139 +
  1140 + bandwidthProportion.dataStream = 10;
  1141 + bandwidthProportion.videoStream = 60;
  1142 + bandwidthProportion.downloadStream = 30;
  1143 +
  1144 + returnCode = ZiyanHighSpeedDataChannel_SetBandwidthProportion(bandwidthProportion);
  1145 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1146 + USER_LOG_ERROR("Set bandwidth proportion for high speed channel error, stat:0x%08llX.", returnCode);
  1147 + return returnCode;
  1148 + }
  1149 +
  1150 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  1151 +}
  1152 +
  1153 +#ifndef __CC_ARM
  1154 +#pragma GCC diagnostic push
  1155 +#pragma GCC diagnostic ignored "-Wmissing-noreturn"
  1156 +#pragma GCC diagnostic ignored "-Wreturn-type"
  1157 +#endif
  1158 +
  1159 +static void *UserCameraMedia_SendVideoTask(void *arg)
  1160 +{
  1161 + int ret;
  1162 + T_ZiyanReturnCode returnCode;
  1163 + static uint32_t sendVideoStep = 0;
  1164 + FILE *fpFile = NULL;
  1165 + unsigned long dataLength = 0;
  1166 + uint16_t lengthOfDataToBeSent = 0;
  1167 + int lengthOfDataHaveBeenSent = 0;
  1168 + char *dataBuffer = NULL;
  1169 + T_TestPayloadCameraPlaybackCommand playbackCommand = {0};
  1170 + uint16_t bufferReadSize = 0;
  1171 + char *videoFilePath = NULL;
  1172 + char *transcodedFilePath = NULL;
  1173 + float frameRate = 1.0f;
  1174 + uint32_t waitDuration = 1000 / SEND_VIDEO_TASK_FREQ;
  1175 + uint32_t rightNow = 0;
  1176 + uint32_t sendExpect = 0;
  1177 + T_TestPayloadCameraVideoFrameInfo *frameInfo = NULL;
  1178 + uint32_t frameNumber = 0;
  1179 + uint32_t frameCount = 0;
  1180 + uint32_t startTimeMs = 0;
  1181 + bool sendVideoFlag = true;
  1182 + bool sendOneTimeFlag = false;
  1183 + T_ZiyanDataChannelState videoStreamState = {0};
  1184 + E_ZiyanCameraMode mode = ZIYAN_CAMERA_MODE_SHOOT_PHOTO;
  1185 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  1186 + uint32_t frameBufSize = 0;
  1187 + E_ZiyanCameraVideoStreamType videoStreamType;
  1188 + char curFileDirPath[ZIYAN_FILE_PATH_SIZE_MAX];
  1189 + char tempPath[ZIYAN_FILE_PATH_SIZE_MAX];
  1190 +
  1191 + USER_UTIL_UNUSED(arg);
  1192 +
  1193 + returnCode = ZiyanUserUtil_GetCurrentFileDirPath(__FILE__, ZIYAN_FILE_PATH_SIZE_MAX, curFileDirPath);
  1194 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1195 + USER_LOG_ERROR("Get file current path error, stat = 0x%08llX", returnCode);
  1196 + exit(1);
  1197 + }
  1198 + if (s_isMediaFileDirPathConfigured == true) {
  1199 + snprintf(tempPath, ZIYAN_FILE_PATH_SIZE_MAX, "%sPSDK_0005.h264", s_mediaFileDirPath);
  1200 + } else {
  1201 + snprintf(tempPath, ZIYAN_FILE_PATH_SIZE_MAX, "%smedia_file/PSDK_0005.h264", curFileDirPath);
  1202 + }
  1203 +
  1204 + videoFilePath = osalHandler->Malloc(ZIYAN_FILE_PATH_SIZE_MAX);
  1205 + if (videoFilePath == NULL) {
  1206 + USER_LOG_ERROR("malloc memory for video file path fail.");
  1207 + exit(1);
  1208 + }
  1209 +
  1210 + transcodedFilePath = osalHandler->Malloc(ZIYAN_FILE_PATH_SIZE_MAX);
  1211 + if (transcodedFilePath == NULL) {
  1212 + USER_LOG_ERROR("malloc memory for transcoded file path fail.");
  1213 + exit(1);
  1214 + }
  1215 +
  1216 + frameInfo = osalHandler->Malloc(VIDEO_FRAME_MAX_COUNT * sizeof(T_TestPayloadCameraVideoFrameInfo));
  1217 + if (frameInfo == NULL) {
  1218 + USER_LOG_ERROR("malloc memory for frame info fail.");
  1219 + exit(1);
  1220 + }
  1221 + memset(frameInfo, 0, VIDEO_FRAME_MAX_COUNT * sizeof(T_TestPayloadCameraVideoFrameInfo));
  1222 +
  1223 + returnCode = ZiyanPlayback_StopPlayProcess();
  1224 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1225 + USER_LOG_ERROR("stop playback and start liveview error: 0x%08llX.", returnCode);
  1226 + exit(1);
  1227 + }
  1228 +
  1229 + (void)osalHandler->GetTimeMs(&rightNow);
  1230 + sendExpect = rightNow + waitDuration;
  1231 + while (1) {
  1232 + (void)osalHandler->GetTimeMs(&rightNow);
  1233 + if (sendExpect > rightNow) {
  1234 + waitDuration = sendExpect - rightNow;
  1235 + } else {
  1236 + waitDuration = 1000 / SEND_VIDEO_TASK_FREQ;
  1237 + }
  1238 + (void)osalHandler->SemaphoreTimedWait(s_mediaPlayWorkSem, waitDuration);
  1239 +
  1240 + // response playback command
  1241 + if (osalHandler->MutexLock(s_mediaPlayCommandBufferMutex) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1242 + USER_LOG_ERROR("mutex lock error");
  1243 + continue;
  1244 + }
  1245 +
  1246 + bufferReadSize = UtilBuffer_Get(&s_mediaPlayCommandBufferHandler, (uint8_t *) &playbackCommand,
  1247 + sizeof(T_TestPayloadCameraPlaybackCommand));
  1248 +
  1249 + if (osalHandler->MutexUnlock(s_mediaPlayCommandBufferMutex) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1250 + USER_LOG_ERROR("mutex unlock error");
  1251 + continue;
  1252 + }
  1253 +
  1254 + if (bufferReadSize != sizeof(T_TestPayloadCameraPlaybackCommand))
  1255 + goto send;
  1256 +
  1257 + switch (playbackCommand.command) {
  1258 + case TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_STOP:
  1259 + snprintf(videoFilePath, ZIYAN_FILE_PATH_SIZE_MAX, "%s", tempPath);
  1260 + startTimeMs = 0;
  1261 + sendVideoFlag = true;
  1262 + sendOneTimeFlag = false;
  1263 + break;
  1264 + case TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_PAUSE:
  1265 + sendVideoFlag = false;
  1266 + goto send;
  1267 + case TEST_PAYLOAD_CAMERA_MEDIA_PLAY_COMMAND_START:
  1268 + snprintf(videoFilePath, ZIYAN_FILE_PATH_SIZE_MAX, "%s", playbackCommand.path);
  1269 + startTimeMs = playbackCommand.timeMs;
  1270 + sendVideoFlag = true;
  1271 + sendOneTimeFlag = true;
  1272 + break;
  1273 + default:
  1274 + USER_LOG_ERROR("playback command invalid: %d.", playbackCommand.command);
  1275 + sendVideoFlag = false;
  1276 + goto send;
  1277 + }
  1278 +
  1279 + // video send preprocess
  1280 + returnCode = ZiyanPlayback_VideoFileTranscode(videoFilePath, "h264", transcodedFilePath,
  1281 + ZIYAN_FILE_PATH_SIZE_MAX);
  1282 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1283 + USER_LOG_ERROR("transcode video file error: 0x%08llX.", returnCode);
  1284 + continue;
  1285 + }
  1286 +
  1287 + returnCode = ZiyanPlayback_GetFrameRateOfVideoFile(transcodedFilePath, &frameRate);
  1288 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1289 + USER_LOG_ERROR("get frame rate of video error: 0x%08llX.", returnCode);
  1290 + continue;
  1291 + }
  1292 +
  1293 + returnCode = ZiyanPlayback_GetFrameInfoOfVideoFile(transcodedFilePath, frameInfo, VIDEO_FRAME_MAX_COUNT,
  1294 + &frameCount);
  1295 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1296 + USER_LOG_ERROR("get frame info of video error: 0x%08llX.", returnCode);
  1297 + continue;
  1298 + }
  1299 +
  1300 + returnCode = ZiyanPlayback_GetFrameNumberByTime(frameInfo, frameCount, &frameNumber,
  1301 + startTimeMs);
  1302 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1303 + USER_LOG_ERROR("get start frame number error: 0x%08llX.", returnCode);
  1304 + continue;
  1305 + }
  1306 +
  1307 + if (fpFile != NULL)
  1308 + fclose(fpFile);
  1309 +
  1310 + fpFile = fopen(transcodedFilePath, "rb+");
  1311 + if (fpFile == NULL) {
  1312 + USER_LOG_ERROR("open video file fail.");
  1313 + continue;
  1314 + }
  1315 +
  1316 + send:
  1317 + if (fpFile == NULL) {
  1318 + USER_LOG_ERROR("open video file fail.");
  1319 + continue;
  1320 + }
  1321 +
  1322 + if (sendVideoFlag != true)
  1323 + continue;
  1324 +
  1325 + returnCode = ZiyanTest_CameraGetMode(&mode);
  1326 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1327 + continue;
  1328 + }
  1329 +
  1330 + returnCode = ZiyanTest_CameraGetVideoStreamType(&videoStreamType);
  1331 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1332 + continue;
  1333 + }
  1334 +
  1335 + if (mode == ZIYAN_CAMERA_MODE_PLAYBACK && s_playbackInfo.isInPlayProcess == false) {
  1336 + continue;
  1337 + }
  1338 +
  1339 + frameBufSize = frameInfo[frameNumber].size;
  1340 + if (videoStreamType == ZIYAN_CAMERA_VIDEO_STREAM_TYPE_H264_ZIYAN_FORMAT) {
  1341 + frameBufSize = frameBufSize + VIDEO_FRAME_AUD_LEN;
  1342 + }
  1343 +
  1344 + dataBuffer = calloc(frameBufSize, 1);
  1345 + if (dataBuffer == NULL) {
  1346 + USER_LOG_ERROR("malloc fail.");
  1347 + goto free;
  1348 + }
  1349 +
  1350 + ret = fseek(fpFile, frameInfo[frameNumber].positionInFile, SEEK_SET);
  1351 + if (ret != 0) {
  1352 + USER_LOG_ERROR("fseek fail.");
  1353 + goto free;
  1354 + }
  1355 +
  1356 + dataLength = fread(dataBuffer, 1, frameInfo[frameNumber].size, fpFile);
  1357 + if (dataLength != frameInfo[frameNumber].size) {
  1358 + USER_LOG_ERROR("read data from video file error.");
  1359 + } else {
  1360 + USER_LOG_DEBUG("read data from video file success, len = %d B\r\n", dataLength);
  1361 + }
  1362 +
  1363 + if (videoStreamType == ZIYAN_CAMERA_VIDEO_STREAM_TYPE_H264_ZIYAN_FORMAT) {
  1364 + memcpy(&dataBuffer[frameInfo[frameNumber].size], s_frameAudInfo, VIDEO_FRAME_AUD_LEN);
  1365 + dataLength = dataLength + VIDEO_FRAME_AUD_LEN;
  1366 + }
  1367 +
  1368 + lengthOfDataHaveBeenSent = 0;
  1369 + while (dataLength - lengthOfDataHaveBeenSent) {
  1370 + lengthOfDataToBeSent = USER_UTIL_MIN(DATA_SEND_FROM_VIDEO_STREAM_MAX_LEN,
  1371 + dataLength - lengthOfDataHaveBeenSent);
  1372 + printf("send video stream, len = %d B\r\n", lengthOfDataToBeSent);
  1373 + returnCode = ZiyanPayloadCamera_SendVideoStream((const uint8_t *) dataBuffer + lengthOfDataHaveBeenSent,
  1374 + lengthOfDataToBeSent);
  1375 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1376 + USER_LOG_ERROR("send video stream error: 0x%08llX.", returnCode);
  1377 + }
  1378 + lengthOfDataHaveBeenSent += lengthOfDataToBeSent;
  1379 + }
  1380 +
  1381 + (void)osalHandler->GetTimeMs(&sendExpect);
  1382 + sendExpect += (1000 / frameRate);
  1383 +
  1384 + if ((frameNumber++) >= frameCount) {
  1385 + USER_LOG_DEBUG("reach file tail.");
  1386 + frameNumber = 0;
  1387 +
  1388 + if (sendOneTimeFlag == true)
  1389 + sendVideoFlag = false;
  1390 + }
  1391 +
  1392 + returnCode = ZiyanPayloadCamera_GetVideoStreamState(&videoStreamState);
  1393 + if (returnCode == ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  1394 + USER_LOG_DEBUG(
  1395 + "video stream state: realtimeBandwidthLimit: %d, realtimeBandwidthBeforeFlowController: %d, realtimeBandwidthAfterFlowController:%d busyState: %d.",
  1396 + videoStreamState.realtimeBandwidthLimit, videoStreamState.realtimeBandwidthBeforeFlowController,
  1397 + videoStreamState.realtimeBandwidthAfterFlowController,
  1398 + videoStreamState.busyState);
  1399 + } else {
  1400 + USER_LOG_ERROR("get video stream state error.");
  1401 + }
  1402 +
  1403 + free:
  1404 + free(dataBuffer);
  1405 + }
  1406 +}
  1407 +
  1408 +#ifndef __CC_ARM
  1409 +#pragma GCC diagnostic pop
  1410 +#endif
  1411 +
  1412 +//#endif
  1413 +
  1414 +/****************** (C) COPYRIGHT ZIYAN Innovations *****END OF FILE****/
@@ -31,6 +31,9 @@ @@ -31,6 +31,9 @@
31 #include <stdio.h> 31 #include <stdio.h>
32 #include "file_binary_array_list_en.h" 32 #include "file_binary_array_list_en.h"
33 33
  34 +#include <stdio.h>
  35 +#include <stdlib.h>
  36 +
34 37
35 #include "JZsdkLib.h" 38 #include "JZsdkLib.h"
36 #include "BaseConfig.h" 39 #include "BaseConfig.h"
@@ -45,6 +48,20 @@ @@ -45,6 +48,20 @@
45 #define WIDGET_DIR_PATH_LEN_MAX (256) 48 #define WIDGET_DIR_PATH_LEN_MAX (256)
46 #define WIDGET_TASK_STACK_SIZE (2048) 49 #define WIDGET_TASK_STACK_SIZE (2048)
47 50
  51 +#define ON JZ_FLAGCODE_ON
  52 +#define OFF JZ_FLAGCODE_OFF
  53 +#define PLAY_PAUSE 1
  54 +#define PLAY_CONTINUE 0
  55 +#define PLAY_SPEED_X1 1
  56 +#define WIDGET_FILE_DIR "/root/Configs/ZY_widget_file"
  57 +
  58 +int Opus_PlayMode=0;//0录音喊话 1实时喊话
  59 +
  60 +int num_flag=0;//版本号信息
  61 +// extern int SpeakerWidgetUseLock;
  62 +// extern float g_height_value;
  63 +// extern int Widget_RealTimeOpusFlag; //用于标志ui里的实时语音开关
  64 +
48 /* Private types -------------------------------------------------------------*/ 65 /* Private types -------------------------------------------------------------*/
49 66
50 /* Private functions declaration ---------------------------------------------*/ 67 /* Private functions declaration ---------------------------------------------*/
@@ -59,8 +76,18 @@ static T_ZiyanTaskHandle s_widgetTestThread; @@ -59,8 +76,18 @@ static T_ZiyanTaskHandle s_widgetTestThread;
59 static bool s_isWidgetFileDirPathConfigured = false; 76 static bool s_isWidgetFileDirPathConfigured = false;
60 static char s_widgetFileDirPath[ZIYAN_FILE_PATH_SIZE_MAX] = {0}; 77 static char s_widgetFileDirPath[ZIYAN_FILE_PATH_SIZE_MAX] = {0};
61 78
  79 +static const char *s_widgetTypeNameArray[] = {
  80 + "Unknown",
  81 + "Button",
  82 + "Switch",
  83 + "Scale",
  84 + "List",
  85 + "Int input box"
  86 +};
  87 +
  88 +#if 0
62 89
63 -#ifdef MEGAPHONE_CONFIG_STATUS_ON 90 +//#ifdef MEGAPHONE_CONFIG_STATUS_ON
64 91
65 static const T_ZiyanWidgetHandlerListItem s_widgetHandlerList[] = { 92 static const T_ZiyanWidgetHandlerListItem s_widgetHandlerList[] = {
66 //喊话器部分 93 //喊话器部分
@@ -101,8 +128,9 @@ static const T_ZiyanWidgetHandlerListItem s_widgetHandlerList[] = { @@ -101,8 +128,9 @@ static const T_ZiyanWidgetHandlerListItem s_widgetHandlerList[] = {
101 {28, ZIYAN_WIDGET_TYPE_LIST, ZiyanTestWidget_SetWidgetValue, ZiyanTestWidget_GetWidgetValue, NULL},//设置滤波输入值 128 {28, ZIYAN_WIDGET_TYPE_LIST, ZiyanTestWidget_SetWidgetValue, ZiyanTestWidget_GetWidgetValue, NULL},//设置滤波输入值
102 }; 129 };
103 130
104 -static const uint32_t s_widgetHandlerListCount = sizeof(s_widgetHandlerList) / sizeof(T_DjiWidgetHandlerListItem);  
105 -int32_t s_widgetValueList[29] = { OFF, OFF, PLAY_PAUSE, 30, 30, PLAY_SPEED_X1, 0, OFF,OFF,OFF, //喊话器部分 131 +static const uint32_t s_widgetHandlerListCount = sizeof(s_widgetHandlerList) / sizeof(T_ZiyanWidgetHandlerListItem);
  132 +static int32_t s_widgetValueList[sizeof(s_widgetHandlerList) / sizeof(T_ZiyanWidgetHandlerListItem)] = {
  133 + OFF, OFF, PLAY_PAUSE, 30, 30, PLAY_SPEED_X1, 0, OFF,OFF,OFF, //喊话器部分
106 OFF, OFF, OFF, OFF, 50, OFF, //探照灯部分 134 OFF, OFF, OFF, OFF, 50, OFF, //探照灯部分
107 0, 0, 2, //警灯部分 135 0, 0, 2, //警灯部分
108 100, 100 ,ON ,OFF,OFF, //云台部分 136 100, 100 ,ON ,OFF,OFF, //云台部分
@@ -123,21 +151,15 @@ static const T_ZiyanWidgetHandlerListItem s_widgetHandlerList[] = { @@ -123,21 +151,15 @@ static const T_ZiyanWidgetHandlerListItem s_widgetHandlerList[] = {
123 {8, ZIYAN_WIDGET_TYPE_LIST, ZiyanTestWidget_SetWidgetValue, ZiyanTestWidget_GetWidgetValue, NULL}, 151 {8, ZIYAN_WIDGET_TYPE_LIST, ZiyanTestWidget_SetWidgetValue, ZiyanTestWidget_GetWidgetValue, NULL},
124 }; 152 };
125 153
  154 +static const uint32_t s_widgetHandlerListCount = sizeof(s_widgetHandlerList) / sizeof(T_ZiyanWidgetHandlerListItem);
  155 +static int32_t s_widgetValueList[sizeof(s_widgetHandlerList) / sizeof(T_ZiyanWidgetHandlerListItem)] = {0};
  156 +
126 #endif 157 #endif
127 158
128 159
129 160
130 -static const char *s_widgetTypeNameArray[] = {  
131 - "Unknown",  
132 - "Button",  
133 - "Switch",  
134 - "Scale",  
135 - "List",  
136 - "Int input box"  
137 -};  
138 161
139 -static const uint32_t s_widgetHandlerListCount = sizeof(s_widgetHandlerList) / sizeof(T_ZiyanWidgetHandlerListItem);  
140 -static int32_t s_widgetValueList[sizeof(s_widgetHandlerList) / sizeof(T_ZiyanWidgetHandlerListItem)] = {0}; 162 +
141 163
142 /* Exported functions definition ---------------------------------------------*/ 164 /* Exported functions definition ---------------------------------------------*/
143 T_ZiyanReturnCode ZiyanTest_WidgetStartService(void) 165 T_ZiyanReturnCode ZiyanTest_WidgetStartService(void)
@@ -151,29 +173,80 @@ T_ZiyanReturnCode ZiyanTest_WidgetStartService(void) @@ -151,29 +173,80 @@ T_ZiyanReturnCode ZiyanTest_WidgetStartService(void)
151 USER_LOG_ERROR("Ziyan test widget init error, stat = 0x%08llX", ziyanStat); 173 USER_LOG_ERROR("Ziyan test widget init error, stat = 0x%08llX", ziyanStat);
152 return ziyanStat; 174 return ziyanStat;
153 } 175 }
  176 + USER_LOG_INFO("Ziyan test widget init success");
154 177
155 -#ifdef SYSTEM_ARCH_LINUX  
156 //Step 2 : Set UI Config (Linux environment) 178 //Step 2 : Set UI Config (Linux environment)
157 char curFileDirPath[WIDGET_DIR_PATH_LEN_MAX]; 179 char curFileDirPath[WIDGET_DIR_PATH_LEN_MAX];
158 char tempPath[WIDGET_DIR_PATH_LEN_MAX]; 180 char tempPath[WIDGET_DIR_PATH_LEN_MAX];
159 - ziyanStat = ZiyanUserUtil_GetCurrentFileDirPath(__FILE__, WIDGET_DIR_PATH_LEN_MAX, curFileDirPath);  
160 - if (ziyanStat != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {  
161 - USER_LOG_ERROR("Get file current path error, stat = 0x%08llX", ziyanStat);  
162 - return ziyanStat;  
163 - }  
164 181
165 - if (s_isWidgetFileDirPathConfigured == true) {  
166 - snprintf(tempPath, WIDGET_DIR_PATH_LEN_MAX, "%swidget_file/en_big_screen", s_widgetFileDirPath);  
167 - } else {  
168 - snprintf(tempPath, WIDGET_DIR_PATH_LEN_MAX, "%swidget_file/en_big_screen", curFileDirPath);  
169 - } 182 + // ziyanStat = ZiyanUserUtil_GetCurrentFileDirPath(__FILE__, WIDGET_DIR_PATH_LEN_MAX, curFileDirPath);
  183 + // if (ziyanStat != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  184 + // USER_LOG_ERROR("Get file current path error, stat = 0x%08llX", ziyanStat);
  185 + // return ziyanStat;
  186 + // }
170 187
171 - //set default ui config path  
172 - ziyanStat = ZiyanWidget_RegDefaultUiConfigByDirPath(tempPath);  
173 - if (ziyanStat != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {  
174 - USER_LOG_ERROR("Add default widget ui config error, stat = 0x%08llX", ziyanStat);  
175 - return ziyanStat;  
176 - } 188 + // if (s_isWidgetFileDirPathConfigured == true) {
  189 + // snprintf(tempPath, WIDGET_DIR_PATH_LEN_MAX, "%swidget_file/en_big_screen", s_widgetFileDirPath);
  190 + // } else {
  191 + // snprintf(tempPath, WIDGET_DIR_PATH_LEN_MAX, "%swidget_file/en_big_screen", curFileDirPath);
  192 + // }
  193 +
  194 + // //set default ui config path
  195 + // ziyanStat = ZiyanWidget_RegDefaultUiConfigByDirPath(tempPath);
  196 + // if (ziyanStat != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  197 + // USER_LOG_ERROR("Add default widget ui config error, stat = 0x%08llX", ziyanStat);
  198 + // return ziyanStat;
  199 + // }
  200 +
  201 + // //set ui config for English language
  202 + // ziyanStat = ZiyanWidget_RegUiConfigByDirPath(ZIYAN_MOBILE_APP_LANGUAGE_ENGLISH,
  203 + // ZIYAN_MOBILE_APP_SCREEN_TYPE_BIG_SCREEN,
  204 + // tempPath);
  205 + // if (ziyanStat != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  206 + // USER_LOG_ERROR("Add widget ui config error, stat = 0x%08llX", ziyanStat);
  207 + // return ziyanStat;
  208 + // }
  209 +
  210 + // //set ui config for Chinese language
  211 + // if (s_isWidgetFileDirPathConfigured == true) {
  212 + // snprintf(tempPath, WIDGET_DIR_PATH_LEN_MAX, "%swidget_file/cn_big_screen", s_widgetFileDirPath);
  213 + // } else {
  214 + // snprintf(tempPath, WIDGET_DIR_PATH_LEN_MAX, "%swidget_file/cn_big_screen", curFileDirPath);
  215 + // }
  216 +
  217 + // ziyanStat = ZiyanWidget_RegUiConfigByDirPath(ZIYAN_MOBILE_APP_LANGUAGE_CHINESE,
  218 + // ZIYAN_MOBILE_APP_SCREEN_TYPE_BIG_SCREEN,
  219 + // tempPath);
  220 + // if (ziyanStat != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  221 + // USER_LOG_ERROR("Add widget ui config error, stat = 0x%08llX", ziyanStat);
  222 + // return ziyanStat;
  223 + // }
  224 +
  225 + // //Step 2 : Set UI Config (RTOS environment)
  226 + // T_ZiyanWidgetBinaryArrayConfig enWidgetBinaryArrayConfig = {
  227 + // .binaryArrayCount = g_EnBinaryArrayCount,
  228 + // .fileBinaryArrayList = g_EnFileBinaryArrayList
  229 + // };
  230 +
  231 + // //set default ui config
  232 + // ziyanStat = ZiyanWidget_RegDefaultUiConfigByBinaryArray(&enWidgetBinaryArrayConfig);
  233 + // if (ziyanStat != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  234 + // USER_LOG_ERROR("Add default widget ui config error, stat = 0x%08llX", ziyanStat);
  235 + // return ziyanStat;
  236 + // }
  237 +
  238 +
  239 + //设置读取ui读取的文件路径
  240 + memset(curFileDirPath, 0, sizeof(curFileDirPath));
  241 + //暂时没有海外版语言的说法
  242 + snprintf(curFileDirPath, WIDGET_DIR_PATH_LEN_MAX, "%s/cn", WIDGET_FILE_DIR);
  243 +
  244 + /*********************************
  245 + * 加载英文控件
  246 + * *******************************/
  247 + memset(tempPath, 0, sizeof(tempPath));
  248 + snprintf(tempPath, WIDGET_DIR_PATH_LEN_MAX, "%swidget_file/en_big_screen", curFileDirPath);
  249 + USER_LOG_INFO("加载en控件%s\n",tempPath);
177 250
178 //set ui config for English language 251 //set ui config for English language
179 ziyanStat = ZiyanWidget_RegUiConfigByDirPath(ZIYAN_MOBILE_APP_LANGUAGE_ENGLISH, 252 ziyanStat = ZiyanWidget_RegUiConfigByDirPath(ZIYAN_MOBILE_APP_LANGUAGE_ENGLISH,
@@ -184,13 +257,15 @@ T_ZiyanReturnCode ZiyanTest_WidgetStartService(void) @@ -184,13 +257,15 @@ T_ZiyanReturnCode ZiyanTest_WidgetStartService(void)
184 return ziyanStat; 257 return ziyanStat;
185 } 258 }
186 259
187 - //set ui config for Chinese language  
188 - if (s_isWidgetFileDirPathConfigured == true) {  
189 - snprintf(tempPath, WIDGET_DIR_PATH_LEN_MAX, "%swidget_file/cn_big_screen", s_widgetFileDirPath);  
190 - } else { 260 +
  261 + /*********************************
  262 + * 加载中文控件
  263 + * *******************************/
  264 + memset(tempPath, 0, sizeof(tempPath));
191 snprintf(tempPath, WIDGET_DIR_PATH_LEN_MAX, "%swidget_file/cn_big_screen", curFileDirPath); 265 snprintf(tempPath, WIDGET_DIR_PATH_LEN_MAX, "%swidget_file/cn_big_screen", curFileDirPath);
192 - } 266 + USER_LOG_INFO("加载cn控件%s\n",tempPath);
193 267
  268 + //set ui config for Chinese language
194 ziyanStat = ZiyanWidget_RegUiConfigByDirPath(ZIYAN_MOBILE_APP_LANGUAGE_CHINESE, 269 ziyanStat = ZiyanWidget_RegUiConfigByDirPath(ZIYAN_MOBILE_APP_LANGUAGE_CHINESE,
195 ZIYAN_MOBILE_APP_SCREEN_TYPE_BIG_SCREEN, 270 ZIYAN_MOBILE_APP_SCREEN_TYPE_BIG_SCREEN,
196 tempPath); 271 tempPath);
@@ -198,26 +273,15 @@ T_ZiyanReturnCode ZiyanTest_WidgetStartService(void) @@ -198,26 +273,15 @@ T_ZiyanReturnCode ZiyanTest_WidgetStartService(void)
198 USER_LOG_ERROR("Add widget ui config error, stat = 0x%08llX", ziyanStat); 273 USER_LOG_ERROR("Add widget ui config error, stat = 0x%08llX", ziyanStat);
199 return ziyanStat; 274 return ziyanStat;
200 } 275 }
201 -#else  
202 - //Step 2 : Set UI Config (RTOS environment)  
203 - T_ZiyanWidgetBinaryArrayConfig enWidgetBinaryArrayConfig = {  
204 - .binaryArrayCount = g_EnBinaryArrayCount,  
205 - .fileBinaryArrayList = g_EnFileBinaryArrayList  
206 - };  
207 -  
208 - //set default ui config  
209 - ziyanStat = ZiyanWidget_RegDefaultUiConfigByBinaryArray(&enWidgetBinaryArrayConfig);  
210 - if (ziyanStat != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {  
211 - USER_LOG_ERROR("Add default widget ui config error, stat = 0x%08llX", ziyanStat);  
212 - return ziyanStat;  
213 - }  
214 -#endif 276 +
  277 +
215 //Step 3 : Set widget handler list 278 //Step 3 : Set widget handler list
216 ziyanStat = ZiyanWidget_RegHandlerList(s_widgetHandlerList, s_widgetHandlerListCount); 279 ziyanStat = ZiyanWidget_RegHandlerList(s_widgetHandlerList, s_widgetHandlerListCount);
217 if (ziyanStat != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) { 280 if (ziyanStat != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
218 USER_LOG_ERROR("Set widget handler list error, stat = 0x%08llX", ziyanStat); 281 USER_LOG_ERROR("Set widget handler list error, stat = 0x%08llX", ziyanStat);
219 return ziyanStat; 282 return ziyanStat;
220 } 283 }
  284 + USER_LOG_INFO("Step 3 : Set widget handler list");
221 285
222 //Step 4 : Run widget api sample task 286 //Step 4 : Run widget api sample task
223 if (osalHandler->TaskCreate("user_widget_task", ZiyanTest_WidgetTask, WIDGET_TASK_STACK_SIZE, NULL, 287 if (osalHandler->TaskCreate("user_widget_task", ZiyanTest_WidgetTask, WIDGET_TASK_STACK_SIZE, NULL,
@@ -225,6 +289,7 @@ T_ZiyanReturnCode ZiyanTest_WidgetStartService(void) @@ -225,6 +289,7 @@ T_ZiyanReturnCode ZiyanTest_WidgetStartService(void)
225 USER_LOG_ERROR("Ziyan widget test task create error."); 289 USER_LOG_ERROR("Ziyan widget test task create error.");
226 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN; 290 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
227 } 291 }
  292 + USER_LOG_INFO("Step 4 : Run widget api sample task");
228 293
229 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS; 294 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
230 } 295 }
@@ -266,16 +331,18 @@ static void *ZiyanTest_WidgetTask(void *arg) @@ -266,16 +331,18 @@ static void *ZiyanTest_WidgetTask(void *arg)
266 USER_LOG_ERROR("Get system time ms error, stat = 0x%08llX", ziyanStat); 331 USER_LOG_ERROR("Get system time ms error, stat = 0x%08llX", ziyanStat);
267 } 332 }
268 333
269 -#ifndef USER_FIRMWARE_MAJOR_VERSION 334 +// #ifndef USER_FIRMWARE_MAJOR_VERSION
  335 +// snprintf(message, ZIYAN_WIDGET_FLOATING_WINDOW_MSG_MAX_LEN, "System time : %u ms", sysTimeMs);
  336 +// #else
  337 +// snprintf(message, ZIYAN_WIDGET_FLOATING_WINDOW_MSG_MAX_LEN,
  338 +// "System time : %u ms\r\nVersion: v%02d.%02d.%02d.%02d\r\nBuild time: %s %s", sysTimeMs,
  339 +// USER_FIRMWARE_MAJOR_VERSION, USER_FIRMWARE_MINOR_VERSION,
  340 +// USER_FIRMWARE_MODIFY_VERSION, USER_FIRMWARE_DEBUG_VERSION,
  341 +// __DATE__, __TIME__);
  342 +// #endif
  343 +
  344 + //悬浮窗打印测试信息
270 snprintf(message, ZIYAN_WIDGET_FLOATING_WINDOW_MSG_MAX_LEN, "System time : %u ms", sysTimeMs); 345 snprintf(message, ZIYAN_WIDGET_FLOATING_WINDOW_MSG_MAX_LEN, "System time : %u ms", sysTimeMs);
271 -#else  
272 - snprintf(message, ZIYAN_WIDGET_FLOATING_WINDOW_MSG_MAX_LEN,  
273 - "System time : %u ms\r\nVersion: v%02d.%02d.%02d.%02d\r\nBuild time: %s %s", sysTimeMs,  
274 - USER_FIRMWARE_MAJOR_VERSION, USER_FIRMWARE_MINOR_VERSION,  
275 - USER_FIRMWARE_MODIFY_VERSION, USER_FIRMWARE_DEBUG_VERSION,  
276 - __DATE__, __TIME__);  
277 -#endif  
278 -  
279 346
280 ziyanStat = ZiyanWidgetFloatingWindow_ShowMessage(message); 347 ziyanStat = ZiyanWidgetFloatingWindow_ShowMessage(message);
281 if (ziyanStat != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) { 348 if (ziyanStat != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
@@ -290,8 +357,241 @@ static void *ZiyanTest_WidgetTask(void *arg) @@ -290,8 +357,241 @@ static void *ZiyanTest_WidgetTask(void *arg)
290 #pragma GCC diagnostic pop 357 #pragma GCC diagnostic pop
291 #endif 358 #endif
292 359
293 -#include <stdio.h>  
294 -#include <stdlib.h> 360 +static T_JZsdkReturnCode Megphone_Widget(unsigned int index, unsigned int value)
  361 +{
  362 +// #ifdef MEGAPHONE_CONFIG_STATUS_ON
  363 +// switch(index){
  364 +// //喊话器部分
  365 +// case 0://上一曲
  366 +// if(value==1)
  367 +// {
  368 +// //JZsdk_Psdk_UI_io_LastSong(1);
  369 +// JZSDK_WidgetMgMT_ConrtrolInputTask(JZSDK_WIDGET_LASTSONG, 0);
  370 +// }
  371 +// break;
  372 +// case 1://下一曲
  373 +// {
  374 +// if(value==1)
  375 +// {
  376 +
  377 +// //JZsdk_Psdk_UI_io_NextSong(1);
  378 +// JZSDK_WidgetMgMT_ConrtrolInputTask(JZSDK_WIDGET_NEXTSONG, 0);
  379 +// }
  380 +// break;
  381 +// }
  382 +// case 2: // 播放\暂停 value为1 是三角控件 暂停 所以要去取反
  383 +// {
  384 +// value = !value;
  385 +// JZSDK_WidgetMgMT_ConrtrolInputTask(JZSDK_WIDGET_PLAYANDSTOP, value);
  386 +
  387 +// break;
  388 +// }
  389 +
  390 +// case 3://内显示音量 scale
  391 +// {
  392 +// JZsdk_Psdk_UI_io_LumenAndVolume_PowerLimitation(1, value);
  393 +// JZsdk_Psdk_UI_io_SetVolume(1,value);
  394 +// break;
  395 +// }
  396 +// case 4://外显示音量 scale
  397 +// {
  398 +// JZsdk_Psdk_UI_io_LumenAndVolume_PowerLimitation(1, value);
  399 +// JZsdk_Psdk_UI_io_SetVolume(1,value);
  400 +// break;
  401 +// }
  402 +// case 5://TTS语速 list
  403 +// {
  404 +// int speed = JZsdk_Psdk_UI_io_GetTTSSpeed_ByValue(value);
  405 +// JZsdk_Psdk_UI_io_Set_TTS_speed(1,speed);
  406 +// break;
  407 +// }
  408 +// case 6://TTS音色 list
  409 +// {
  410 +// int tone = JZsdk_Psdk_UI_io_GetTTSTone_ByValue(value);
  411 +// JZsdk_Psdk_UI_io_Set_TTS_tone(1,tone);
  412 +// break;
  413 +// }
  414 +// case 7://TTS追加音色 list
  415 +// JZsdk_Psdk_UI_io_AppendTone(1,value);
  416 +// break;
  417 +// case 8: //switch 循环 循环是1
  418 +// JZsdk_Psdk_UI_io_SetAudioPlayLoop(1, value);
  419 +// break;
  420 +// case 9: //喊话模式切换
  421 +// {
  422 +// //切换前关闭所有实时喊话
  423 +// //Speaker_Set_SpeakerOFF();
  424 +
  425 +// //如果喊话器控件正在使用,禁止修改功能
  426 +// if (SpeakerWidgetUseLock == JZ_FLAGCODE_ON)
  427 +// {
  428 +// set_wideget_value(9,Opus_PlayMode);
  429 +// break;
  430 +// }
  431 +
  432 +// //切换前喊话器关闭所有语音功能
  433 +// JZsdk_Psdk_UI_io_StopPlayAudio();
  434 +
  435 +// switch(value){
  436 +// case 0:
  437 +// Widget_RealTimeOpusFlag = JZ_FLAGCODE_OFF;
  438 +// Opus_PlayMode = 0;
  439 +// break;
  440 +// case 1:
  441 +// Widget_RealTimeOpusFlag = JZ_FLAGCODE_ON;
  442 +// Opus_PlayMode = 1;
  443 +// break;
  444 +// default:
  445 +// Widget_RealTimeOpusFlag = JZ_FLAGCODE_OFF;
  446 +// Opus_PlayMode = 0;
  447 +// break;
  448 +// }
  449 +
  450 +// break;
  451 +// }
  452 +// //探照灯部分
  453 +// case 10://探照灯 内显示亮度
  454 +// {
  455 +// JZsdk_Psdk_UI_io_LumenAndVolume_PowerLimitation(0, value);
  456 +// JZsdk_Psdk_UI_io_Set_SearchLightLumen(1,value);
  457 +// break;
  458 +// }
  459 +// case 11://探照灯 外显示亮度
  460 +// {
  461 +// JZsdk_Psdk_UI_io_LumenAndVolume_PowerLimitation(0, value);
  462 +// JZsdk_Psdk_UI_io_Set_SearchLightLumen(1,value);
  463 +// break;
  464 +// }
  465 +// case 12: //探照灯模式
  466 +// {
  467 +// JZsdk_Psdk_UI_io_Set_SearchLightMode(1,value);
  468 +// break;
  469 +// }
  470 +
  471 +// case 13: //探照灯 爆闪开关 已合并至12
  472 +// {
  473 +// //JZsdk_Psdk_UI_io_Set_SearchLightBrustMode(1,value);
  474 +// break;
  475 +// }
  476 +// case 14://探照灯 爆闪频率
  477 +// {
  478 +// JZsdk_Psdk_UI_io_Set_SearchLightFrequency(1,value);
  479 +// break;
  480 +// }
  481 +// //侧面激光部分
  482 +// case 15://激光开关
  483 +// {
  484 +// JZSDK_WidgetMgMT_ConrtrolInputTask(JZSDK_WIDGET_SIDE_LASER_MODE, value);
  485 +// break;
  486 +// }
  487 +// //警灯部分
  488 +// case 16://警灯模式
  489 +// {
  490 +// JZsdk_Psdk_UI_io_Set_WarningLightMode(1,value);
  491 +// break;
  492 +// }
  493 +// case 17://警灯颜色1
  494 +// {
  495 +// JZsdk_Psdk_UI_io_Set_WarningLightFirstColor(1,(value+1));
  496 +// break;
  497 +// }
  498 +// case 18://警灯颜色2
  499 +// {
  500 +// JZsdk_Psdk_UI_io_Set_WarningLightSecondColor(1,(value+1));
  501 +// break;
  502 +// }
  503 +// //云台部分
  504 +// case 19://云台内部滑动条
  505 +// {
  506 +// if (Get_Gimbal_linkage() == JZ_FLAGCODE_OFF)
  507 +// {
  508 +// JZsdk_Psdk_Ui_io_Gimbal_PitchScaleMode(value);
  509 +// }
  510 +// break;
  511 +// }
  512 +// case 20://云台外部滑动条
  513 +// {
  514 +// if (Get_Gimbal_linkage() == JZ_FLAGCODE_OFF)
  515 +// {
  516 +// JZsdk_Psdk_Ui_io_Gimbal_PitchScaleMode(value);
  517 +// }
  518 +// break;
  519 +// }
  520 +// case 21://云台联动开关
  521 +// {
  522 +// Set_Gimbal_linkage(value);
  523 +// break;
  524 +// }
  525 +// case 22://云台向上微调
  526 +// {
  527 +// if(value == 1)
  528 +// {
  529 +// JZsdk_Psdk_UI_io_Set_AdjustmentGimbalPitchAngle(5);
  530 +// }
  531 +
  532 +// break;
  533 +// }
  534 +// case 23://云台向下微调
  535 +// {
  536 +// if(value == 1)
  537 +// {
  538 +// JZsdk_Psdk_UI_io_Set_AdjustmentGimbalPitchAngle(-5);
  539 +// }
  540 +// break;
  541 +// }
  542 +// //系统部分
  543 +// case 24://版本信息
  544 +// {
  545 +// if(value==1){
  546 +// num_flag+=1;
  547 +// if(num_flag<3)
  548 +// {
  549 +// break;
  550 +// }
  551 +// if(num_flag==3)
  552 +// {
  553 +// printf("打开调试界面");
  554 +// break;
  555 +// }
  556 +// if(num_flag>3){
  557 +// num_flag=0;//重新置零
  558 +// printf("关闭调试界面");
  559 +// break;
  560 +// }
  561 +// }
  562 +// break;
  563 +// }
  564 +// case 25://对外供电开关
  565 +// {
  566 +// JZsdk_Psdk_UI_io_Set_OutputPowerStatus(1 ,value);
  567 +// break;
  568 +// }
  569 +// //调试部分
  570 +// case 26://设置云台最大值
  571 +// {
  572 +// if(value==1 && num_flag == 3)
  573 +// {
  574 +// JZsdk_Psdk_UI_io_Set_MAXGimbalRangen();
  575 +// }
  576 +// break;
  577 +// }
  578 +// case 27://psdk云台最小值
  579 +// {
  580 +// if(value==1 && num_flag == 3)
  581 +// {
  582 +// JZsdk_Psdk_UI_io_Set_MINGimbalRangen();
  583 +// }
  584 +// break;
  585 +// }
  586 +// case 28://设置临时参数
  587 +// {
  588 +
  589 +// }
  590 +// default:
  591 +// break;
  592 +// }
  593 +// #endif
  594 +}
295 595
296 static T_ZiyanReturnCode ZiyanTestWidget_SetWidgetValue(E_ZiyanWidgetType widgetType, uint32_t index, int32_t value, 596 static T_ZiyanReturnCode ZiyanTestWidget_SetWidgetValue(E_ZiyanWidgetType widgetType, uint32_t index, int32_t value,
297 void *userData) 597 void *userData)
@@ -302,7 +602,8 @@ static T_ZiyanReturnCode ZiyanTestWidget_SetWidgetValue(E_ZiyanWidgetType widget @@ -302,7 +602,8 @@ static T_ZiyanReturnCode ZiyanTestWidget_SetWidgetValue(E_ZiyanWidgetType widget
302 s_widgetTypeNameArray[widgetType], index, value); 602 s_widgetTypeNameArray[widgetType], index, value);
303 s_widgetValueList[index] = value; 603 s_widgetValueList[index] = value;
304 604
305 - JZSDK_LOG_INFO("Set widget value, widgetType = %s, widgetIndex = %d ,widgetValue = %d"); 605 + //放入控件管理
  606 + Megphone_Widget(index, value);
306 607
307 // if(index == 0){ 608 // if(index == 0){
308 // uint8_t brightness = value; 609 // uint8_t brightness = value;
@@ -411,3 +712,16 @@ static T_ZiyanReturnCode ZiyanTestWidget_GetWidgetValue(E_ZiyanWidgetType widget @@ -411,3 +712,16 @@ static T_ZiyanReturnCode ZiyanTestWidget_GetWidgetValue(E_ZiyanWidgetType widget
411 } 712 }
412 713
413 /****************** (C) COPYRIGHT ZIYAN Innovations *****END OF FILE****/ 714 /****************** (C) COPYRIGHT ZIYAN Innovations *****END OF FILE****/
  715 +
  716 +T_JZsdkReturnCode set_wideget_value(int index,int value)
  717 +{
  718 + s_widgetValueList[index]=value;
  719 +
  720 + //printf("\n修改%d控件,%d\n\n",index,value);
  721 +}
  722 +
  723 + //获取播放模式 int Opus_PlayMode=0;//0录音喊话 1实时喊话
  724 +int Get_Opus_PlayMode()
  725 +{
  726 + return Opus_PlayMode;
  727 +}
@@ -29,6 +29,7 @@ @@ -29,6 +29,7 @@
29 29
30 /* Includes ------------------------------------------------------------------*/ 30 /* Includes ------------------------------------------------------------------*/
31 #include <ziyan_typedef.h> 31 #include <ziyan_typedef.h>
  32 +#include "JZsdk_Base/JZsdk_Code/JZsdk_Code.h"
32 33
33 #ifdef __cplusplus 34 #ifdef __cplusplus
34 extern "C" { 35 extern "C" {
@@ -43,6 +44,10 @@ T_ZiyanReturnCode ZiyanTest_WidgetStartService(void); @@ -43,6 +44,10 @@ T_ZiyanReturnCode ZiyanTest_WidgetStartService(void);
43 T_ZiyanReturnCode ZiyanTest_WidgetSetConfigFilePath(const char *path); 44 T_ZiyanReturnCode ZiyanTest_WidgetSetConfigFilePath(const char *path);
44 __attribute__((weak)) void ZiyanTest_WidgetLogAppend(const char *fmt, ...); 45 __attribute__((weak)) void ZiyanTest_WidgetLogAppend(const char *fmt, ...);
45 46
  47 +T_JZsdkReturnCode set_wideget_value(int index,int value);
  48 +int Get_Opus_PlayMode();
  49 +
  50 +
46 #ifdef __cplusplus 51 #ifdef __cplusplus
47 } 52 }
48 #endif 53 #endif
@@ -41,18 +41,11 @@ @@ -41,18 +41,11 @@
41 41
42 #endif 42 #endif
43 43
44 -#ifdef ALSA_INSTALLED  
45 -  
46 -#include <alsa/asoundlib.h>  
47 -  
48 -#endif  
49 -  
50 /* Private constants ---------------------------------------------------------*/ 44 /* Private constants ---------------------------------------------------------*/
51 #define WIDGET_SPEAKER_TASK_STACK_SIZE (2048) 45 #define WIDGET_SPEAKER_TASK_STACK_SIZE (2048)
52 46
53 /*! Attention: replace your audio device name here. */ 47 /*! Attention: replace your audio device name here. */
54 -// #define WIDGET_SPEAKER_USB_AUDIO_DEVICE_NAME "alsa_output.usb-C-Media_Electronics_Inc._USB_Audio_Device-00.analog-stereo"  
55 -#define WIDGET_SPEAKER_USB_AUDIO_DEVICE_NAME "alsa_card.usb-GeneralPlus_USB_Audio_Device-00" 48 +#define WIDGET_SPEAKER_USB_AUDIO_DEVICE_NAME "alsa_output.usb-C-Media_Electronics_Inc._USB_Audio_Device-00.analog-stereo"
56 49
57 #define WIDGET_SPEAKER_AUDIO_OPUS_FILE_NAME "test_audio.opus" 50 #define WIDGET_SPEAKER_AUDIO_OPUS_FILE_NAME "test_audio.opus"
58 #define WIDGET_SPEAKER_AUDIO_PCM_FILE_NAME "test_audio.pcm" 51 #define WIDGET_SPEAKER_AUDIO_PCM_FILE_NAME "test_audio.pcm"
@@ -87,12 +80,6 @@ static FILE *s_ttsFile = NULL; @@ -87,12 +80,6 @@ static FILE *s_ttsFile = NULL;
87 static bool s_isDecodeFinished = true; 80 static bool s_isDecodeFinished = true;
88 static uint16_t s_decodeBitrate = 0; 81 static uint16_t s_decodeBitrate = 0;
89 82
90 -#ifdef ALSA_INSTALLED  
91 - snd_pcm_t *pcm_handle = NULL;  
92 - snd_pcm_hw_params_t *hw_params = NULL;  
93 - snd_pcm_sw_params_t *sw_params = NULL;  
94 -#endif  
95 -  
96 /* Private functions declaration ---------------------------------------------*/ 83 /* Private functions declaration ---------------------------------------------*/
97 static void SetSpeakerState(E_ZiyanWidgetSpeakerState speakerState); 84 static void SetSpeakerState(E_ZiyanWidgetSpeakerState speakerState);
98 static T_ZiyanReturnCode GetSpeakerState(T_ZiyanWidgetSpeakerState *speakerState); 85 static T_ZiyanReturnCode GetSpeakerState(T_ZiyanWidgetSpeakerState *speakerState);
@@ -176,81 +163,6 @@ T_ZiyanReturnCode ZiyanTest_WidgetSpeakerStartService(void) @@ -176,81 +163,6 @@ T_ZiyanReturnCode ZiyanTest_WidgetSpeakerStartService(void)
176 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS; 163 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
177 } 164 }
178 165
179 -#ifdef ALSA_INSTALLED  
180 -T_ZiyanReturnCode ZiyanTest_AsoundInit()  
181 -{  
182 - // 打开默认音频设备  
183 - if (snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0) {  
184 - fprintf(stderr, "无法打开音频设备\n");  
185 - return 1;  
186 - }  
187 -  
188 - // 分配硬件参数结构体  
189 - snd_pcm_hw_params_alloca(&hw_params);  
190 - snd_pcm_hw_params_any(pcm_handle, hw_params);  
191 -  
192 - // 设置硬件参数  
193 - snd_pcm_hw_params_set_access(pcm_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);  
194 - snd_pcm_hw_params_set_format(pcm_handle, hw_params, SND_PCM_FORMAT_S16_LE); // 16-bit little-endian  
195 - snd_pcm_hw_params_set_rate(pcm_handle, hw_params, WIDGET_SPEAKER_AUDIO_OPUS_SAMPLE_RATE, 0); // 设置采样率为 16kHz  
196 - snd_pcm_hw_params_set_channels(pcm_handle, hw_params, WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS); // 设置单声道  
197 - snd_pcm_hw_params_set_buffer_size(pcm_handle, hw_params, 16000 * 8);  
198 - snd_pcm_hw_params_set_period_size(pcm_handle, hw_params, 1280, 0);  
199 -  
200 - // 应用硬件参数  
201 - if (snd_pcm_hw_params(pcm_handle, hw_params) < 0) {  
202 - fprintf(stderr, "无法设置硬件参数\n");  
203 - return 1;  
204 - }  
205 -  
206 - // 设置软件参数  
207 - snd_pcm_sw_params_alloca(&sw_params);  
208 - snd_pcm_sw_params_current(pcm_handle, sw_params);  
209 - snd_pcm_sw_params_set_avail_min(pcm_handle, sw_params, 1280);  
210 - snd_pcm_sw_params_set_start_threshold(pcm_handle, sw_params, 0);  
211 -  
212 - // 应用软件参数  
213 - if (snd_pcm_sw_params(pcm_handle, sw_params) < 0) {  
214 - fprintf(stderr, "无法设置软件参数\n");  
215 - return 1;  
216 - }  
217 -  
218 - // snd_pcm_prepare(pcm_handle);  
219 -  
220 - return 0;  
221 -}  
222 -#endif  
223 -  
224 -  
225 -T_ZiyanReturnCode ZiyanTest_PcmPlay(uint8_t* pcm_data, uint64_t size)  
226 -{  
227 -#ifdef ALSA_INSTALLED  
228 - if((pcm_handle != NULL)){  
229 - int err = snd_pcm_writei(pcm_handle, pcm_data, size);  
230 -  
231 - snd_pcm_sframes_t avail = snd_pcm_avail(pcm_handle);  
232 - if((16000 * 8 - avail) <= 16000){  
233 -  
234 - uint8_t pcm_empty[16000];  
235 - memset(pcm_empty, 0, sizeof(pcm_empty));  
236 - snd_pcm_writei(pcm_handle, pcm_empty, sizeof(pcm_empty));  
237 - }  
238 - // snd_pcm_sframes_t avail = 0;  
239 - printf("play pcm %d : %ld : %ld\n", err, size, avail);  
240 -  
241 - // 错误处理  
242 - if (err == -EPIPE) {  
243 - fprintf(stderr, "发生缓冲区溢出错误!\n");  
244 - snd_pcm_prepare(pcm_handle);  
245 - } else if (err < 0) {  
246 - fprintf(stderr, "播放失败: %s\n", snd_strerror(err));  
247 - } else if (err < 640) {  
248 - fprintf(stderr, "警告: 写入的帧数少于预期\n");  
249 - }  
250 - }  
251 -#endif  
252 -}  
253 -  
254 /* Private functions definition-----------------------------------------------*/ 166 /* Private functions definition-----------------------------------------------*/
255 #ifdef SYSTEM_ARCH_LINUX 167 #ifdef SYSTEM_ARCH_LINUX
256 168
@@ -322,7 +234,7 @@ static T_ZiyanReturnCode ZiyanTest_DecodeAudioData(void) @@ -322,7 +234,7 @@ static T_ZiyanReturnCode ZiyanTest_DecodeAudioData(void)
322 goto close_fin; 234 goto close_fin;
323 } 235 }
324 236
325 - fout = fopen(WIDGET_SPEAKER_AUDIO_PCM_FILE_NAME, "a+"); 237 + fout = fopen(WIDGET_SPEAKER_AUDIO_PCM_FILE_NAME, "w");
326 if (fout == NULL) { 238 if (fout == NULL) {
327 fprintf(stderr, "failed to open output file: %s\n", strerror(errno)); 239 fprintf(stderr, "failed to open output file: %s\n", strerror(errno));
328 goto close_fin; 240 goto close_fin;
@@ -330,12 +242,14 @@ static T_ZiyanReturnCode ZiyanTest_DecodeAudioData(void) @@ -330,12 +242,14 @@ static T_ZiyanReturnCode ZiyanTest_DecodeAudioData(void)
330 242
331 while (1) { 243 while (1) {
332 int i; 244 int i;
333 - unsigned char pcm_bytes[WIDGET_SPEAKER_AUDIO_OPUS_MAX_FRAME_SIZE * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS * 4] = {0}; 245 + unsigned char pcm_bytes[WIDGET_SPEAKER_AUDIO_OPUS_MAX_FRAME_SIZE * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS * 2];
334 int frame_size; 246 int frame_size;
335 247
336 /* Read a 16 bits/sample audio frame. */ 248 /* Read a 16 bits/sample audio frame. */
337 nbBytes = fread(cbits, 1, s_decodeBitrate / WIDGET_SPEAKER_AUDIO_OPUS_DECODE_BITRATE_8KBPS * 249 nbBytes = fread(cbits, 1, s_decodeBitrate / WIDGET_SPEAKER_AUDIO_OPUS_DECODE_BITRATE_8KBPS *
338 - WIDGET_SPEAKER_AUDIO_OPUS_DECODE_FRAME_SIZE_8KBPS * 8, fin); 250 + WIDGET_SPEAKER_AUDIO_OPUS_DECODE_FRAME_SIZE_8KBPS, fin);
  251 + if (feof(fin))
  252 + break;
339 253
340 /* Decode the data. In this example, frame_size will be constant because 254 /* Decode the data. In this example, frame_size will be constant because
341 the encoder is using a constant frame size. However, that may not 255 the encoder is using a constant frame size. However, that may not
@@ -347,6 +261,7 @@ static T_ZiyanReturnCode ZiyanTest_DecodeAudioData(void) @@ -347,6 +261,7 @@ static T_ZiyanReturnCode ZiyanTest_DecodeAudioData(void)
347 goto close_fout; 261 goto close_fout;
348 } 262 }
349 263
  264 + USER_LOG_DEBUG("decode data to file: %d\r\n", frame_size * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS);
350 /* Convert to little-endian ordering. */ 265 /* Convert to little-endian ordering. */
351 for (i = 0; i < WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS * frame_size; i++) { 266 for (i = 0; i < WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS * frame_size; i++) {
352 pcm_bytes[2 * i] = out[i] & 0xFF; 267 pcm_bytes[2 * i] = out[i] & 0xFF;
@@ -354,12 +269,6 @@ static T_ZiyanReturnCode ZiyanTest_DecodeAudioData(void) @@ -354,12 +269,6 @@ static T_ZiyanReturnCode ZiyanTest_DecodeAudioData(void)
354 } 269 }
355 /* Write the decoded audio to file. */ 270 /* Write the decoded audio to file. */
356 fwrite(pcm_bytes, sizeof(short), frame_size * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS, fout); 271 fwrite(pcm_bytes, sizeof(short), frame_size * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS, fout);
357 -#ifdef ALSA_INSTALLED  
358 - ZiyanTest_PcmPlay(pcm_bytes, frame_size * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS);  
359 -#endif  
360 -  
361 - if (feof(fin))  
362 - break;  
363 } 272 }
364 273
365 USER_LOG_INFO("Decode Finished..."); 274 USER_LOG_INFO("Decode Finished...");
@@ -583,6 +492,8 @@ static T_ZiyanReturnCode SetPlayMode(E_ZiyanWidgetSpeakerPlayMode playMode) @@ -583,6 +492,8 @@ static T_ZiyanReturnCode SetPlayMode(E_ZiyanWidgetSpeakerPlayMode playMode)
583 T_ZiyanReturnCode returnCode; 492 T_ZiyanReturnCode returnCode;
584 T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler(); 493 T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
585 494
  495 + printf("set play mode: %d.\n", playMode);
  496 +
586 returnCode = osalHandler->MutexLock(s_speakerMutex); 497 returnCode = osalHandler->MutexLock(s_speakerMutex);
587 if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) { 498 if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
588 USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode); 499 USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
@@ -708,7 +619,7 @@ static T_ZiyanReturnCode ReceiveTtsData(E_ZiyanWidgetTransmitDataEvent event, @@ -708,7 +619,7 @@ static T_ZiyanReturnCode ReceiveTtsData(E_ZiyanWidgetTransmitDataEvent event,
708 T_ZiyanReturnCode returnCode; 619 T_ZiyanReturnCode returnCode;
709 620
710 if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_START) { 621 if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_START) {
711 - USER_LOG_INFO("Create tts file."); 622 + USER_LOG_WARN("Create tts file.");
712 #ifdef SYSTEM_ARCH_LINUX 623 #ifdef SYSTEM_ARCH_LINUX
713 s_ttsFile = fopen(WIDGET_SPEAKER_TTS_FILE_NAME, "wb"); 624 s_ttsFile = fopen(WIDGET_SPEAKER_TTS_FILE_NAME, "wb");
714 if (s_ttsFile == NULL) { 625 if (s_ttsFile == NULL) {
@@ -719,7 +630,7 @@ static T_ZiyanReturnCode ReceiveTtsData(E_ZiyanWidgetTransmitDataEvent event, @@ -719,7 +630,7 @@ static T_ZiyanReturnCode ReceiveTtsData(E_ZiyanWidgetTransmitDataEvent event,
719 SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_TRANSMITTING); 630 SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_TRANSMITTING);
720 } 631 }
721 } else if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_TRANSMIT) { 632 } else if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_TRANSMIT) {
722 - USER_LOG_INFO("Transmit tts file, offset: %d, size: %d", offset, size); 633 + USER_LOG_WARN("Transmit tts file, offset: %d, size: %d", offset, size);
723 #ifdef SYSTEM_ARCH_LINUX 634 #ifdef SYSTEM_ARCH_LINUX
724 if (s_ttsFile != NULL) { 635 if (s_ttsFile != NULL) {
725 fseek(s_ttsFile, offset, SEEK_SET); 636 fseek(s_ttsFile, offset, SEEK_SET);
@@ -733,7 +644,7 @@ static T_ZiyanReturnCode ReceiveTtsData(E_ZiyanWidgetTransmitDataEvent event, @@ -733,7 +644,7 @@ static T_ZiyanReturnCode ReceiveTtsData(E_ZiyanWidgetTransmitDataEvent event,
733 SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_TRANSMITTING); 644 SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_TRANSMITTING);
734 } 645 }
735 } else if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_FINISH) { 646 } else if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_FINISH) {
736 - USER_LOG_INFO("Close tts file."); 647 + USER_LOG_WARN("Close tts file.");
737 #ifdef SYSTEM_ARCH_LINUX 648 #ifdef SYSTEM_ARCH_LINUX
738 if (s_ttsFile != NULL) { 649 if (s_ttsFile != NULL) {
739 fclose(s_ttsFile); 650 fclose(s_ttsFile);
@@ -760,6 +671,8 @@ static T_ZiyanReturnCode ReceiveAudioData(E_ZiyanWidgetTransmitDataEvent event, @@ -760,6 +671,8 @@ static T_ZiyanReturnCode ReceiveAudioData(E_ZiyanWidgetTransmitDataEvent event,
760 T_ZiyanReturnCode returnCode; 671 T_ZiyanReturnCode returnCode;
761 T_ZiyanWidgetTransDataContent transDataContent = {0}; 672 T_ZiyanWidgetTransDataContent transDataContent = {0};
762 673
  674 + USER_LOG_WARN("Vioce data %d: offset %d, size %d", event, offset, size);
  675 +
763 if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_START) { 676 if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_START) {
764 s_isDecodeFinished = false; 677 s_isDecodeFinished = false;
765 #ifdef SYSTEM_ARCH_LINUX 678 #ifdef SYSTEM_ARCH_LINUX
@@ -828,10 +741,6 @@ static void *ZiyanTest_WidgetSpeakerTask(void *arg) @@ -828,10 +741,6 @@ static void *ZiyanTest_WidgetSpeakerTask(void *arg)
828 T_ZiyanReturnCode ziyanReturnCode; 741 T_ZiyanReturnCode ziyanReturnCode;
829 T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler(); 742 T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
830 743
831 -#ifdef ALSA_INSTALLED  
832 - ZiyanTest_AsoundInit();  
833 -#endif  
834 -  
835 USER_UTIL_UNUSED(arg); 744 USER_UTIL_UNUSED(arg);
836 745
837 while (1) { 746 while (1) {
  1 +/**
  2 + ********************************************************************
  3 + * @file test_widget_speaker.c
  4 + * @brief
  5 + *
  6 + * @copyright (c) 2018 ZIYAN. All rights reserved.
  7 + *
  8 + * All information contained herein is, and remains, the property of ZIYAN.
  9 + * The intellectual and technical concepts contained herein are proprietary
  10 + * to ZIYAN and may be covered by U.S. and foreign patents, patents in process,
  11 + * and protected by trade secret or copyright law. Dissemination of this
  12 + * information, including but not limited to data and other proprietary
  13 + * material(s) incorporated within the information, in any form, is strictly
  14 + * prohibited without the express written consent of ZIYAN.
  15 + *
  16 + * If you receive this source code without ZIYAN’s authorization, you may not
  17 + * further disseminate the information, and you must immediately remove the
  18 + * source code and notify ZIYAN of its removal. ZIYAN reserves the right to pursue
  19 + * legal actions against you for any loss(es) or damage(s) caused by your
  20 + * failure to do so.
  21 + *
  22 + *********************************************************************
  23 + */
  24 +
  25 +/* Includes ------------------------------------------------------------------*/
  26 +#include "test_widget_speaker.h"
  27 +#include "ziyan_logger.h"
  28 +#include <stdlib.h>
  29 +#include <errno.h>
  30 +#include <string.h>
  31 +#include <stdio.h>
  32 +#include "utils/util_misc.h"
  33 +#include "utils/util_md5.h"
  34 +#include <ziyan_aircraft_info.h>
  35 +
  36 +#include "JZsdkLib.h"
  37 +
  38 +#ifdef OPUS_INSTALLED
  39 +
  40 +#include <opus/opus.h>
  41 +
  42 +#endif
  43 +
  44 +#ifdef ALSA_INSTALLED
  45 +
  46 +#include <alsa/asoundlib.h>
  47 +
  48 +#endif
  49 +
  50 +/* Private constants ---------------------------------------------------------*/
  51 +#define WIDGET_SPEAKER_TASK_STACK_SIZE (2048)
  52 +
  53 +/*! Attention: replace your audio device name here. */
  54 +// #define WIDGET_SPEAKER_USB_AUDIO_DEVICE_NAME "alsa_output.usb-C-Media_Electronics_Inc._USB_Audio_Device-00.analog-stereo"
  55 +#define WIDGET_SPEAKER_USB_AUDIO_DEVICE_NAME "alsa_card.usb-GeneralPlus_USB_Audio_Device-00"
  56 +
  57 +#define WIDGET_SPEAKER_AUDIO_OPUS_FILE_NAME "test_audio.opus"
  58 +#define WIDGET_SPEAKER_AUDIO_PCM_FILE_NAME "test_audio.pcm"
  59 +
  60 +#define WIDGET_SPEAKER_TTS_FILE_NAME "test_tts.txt"
  61 +#define WIDGET_SPEAKER_TTS_OUTPUT_FILE_NAME "tts_audio.wav"
  62 +#define WIDGET_SPEAKER_TTS_FILE_MAX_SIZE (3000)
  63 +
  64 +/* The frame size is hardcoded for this sample code but it doesn't have to be */
  65 +#define WIDGET_SPEAKER_AUDIO_OPUS_MAX_PACKET_SIZE (3 * 1276)
  66 +#define WIDGET_SPEAKER_AUDIO_OPUS_MAX_FRAME_SIZE (6 * 960)
  67 +#define WIDGET_SPEAKER_AUDIO_OPUS_SAMPLE_RATE (16000)
  68 +#define WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS (1)
  69 +
  70 +#define WIDGET_SPEAKER_AUDIO_OPUS_DECODE_FRAME_SIZE_8KBPS (40)
  71 +#define WIDGET_SPEAKER_AUDIO_OPUS_DECODE_BITRATE_8KBPS (8000)
  72 +
  73 +/* The speaker initialization parameters */
  74 +#define WIDGET_SPEAKER_DEFAULT_VOLUME (60)
  75 +#define EKHO_INSTALLED (1)
  76 +
  77 +/* Private types -------------------------------------------------------------*/
  78 +
  79 +/* Private values -------------------------------------------------------------*/
  80 +static T_ZiyanWidgetSpeakerHandler s_speakerHandler = {0};
  81 +static T_ZiyanMutexHandle s_speakerMutex = {0};
  82 +static T_ZiyanWidgetSpeakerState s_speakerState = {0};
  83 +static T_ZiyanTaskHandle s_widgetSpeakerTestThread;
  84 +
  85 +static FILE *s_audioFile = NULL;
  86 +static FILE *s_ttsFile = NULL;
  87 +static bool s_isDecodeFinished = true;
  88 +static uint16_t s_decodeBitrate = 0;
  89 +
  90 +#ifdef ALSA_INSTALLED
  91 + snd_pcm_t *pcm_handle = NULL;
  92 + snd_pcm_hw_params_t *hw_params = NULL;
  93 + snd_pcm_sw_params_t *sw_params = NULL;
  94 +#endif
  95 +
  96 +/* Private functions declaration ---------------------------------------------*/
  97 +static void SetSpeakerState(E_ZiyanWidgetSpeakerState speakerState);
  98 +static T_ZiyanReturnCode GetSpeakerState(T_ZiyanWidgetSpeakerState *speakerState);
  99 +static T_ZiyanReturnCode SetWorkMode(E_ZiyanWidgetSpeakerWorkMode workMode);
  100 +static T_ZiyanReturnCode SetPlayMode(E_ZiyanWidgetSpeakerPlayMode playMode);
  101 +static T_ZiyanReturnCode StartPlay(void);
  102 +static T_ZiyanReturnCode StopPlay(void);
  103 +static T_ZiyanReturnCode SetVolume(uint8_t volume);
  104 +static T_ZiyanReturnCode ReceiveTtsData(E_ZiyanWidgetTransmitDataEvent event,
  105 + uint32_t offset, uint8_t *buf, uint16_t size);
  106 +static T_ZiyanReturnCode ReceiveAudioData(E_ZiyanWidgetTransmitDataEvent event,
  107 + uint32_t offset, uint8_t *buf, uint16_t size);
  108 +#ifdef SYSTEM_ARCH_LINUX
  109 +static void *ZiyanTest_WidgetSpeakerTask(void *arg);
  110 +static uint32_t ZiyanTest_GetVoicePlayProcessId(void);
  111 +static uint32_t ZiyanTest_KillVoicePlayProcess(uint32_t pid);
  112 +static T_ZiyanReturnCode ZiyanTest_DecodeAudioData(void);
  113 +static T_ZiyanReturnCode ZiyanTest_PlayAudioData(void);
  114 +static T_ZiyanReturnCode ZiyanTest_PlayTtsData(void);
  115 +static T_ZiyanReturnCode ZiyanTest_CheckFileMd5Sum(const char *path, uint8_t *buf, uint16_t size);
  116 +#endif
  117 +
  118 +/* Exported functions definition ---------------------------------------------*/
  119 +T_ZiyanReturnCode ZiyanTest_WidgetSpeakerStartService(void)
  120 +{
  121 + T_ZiyanReturnCode returnCode;
  122 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  123 +
  124 + s_speakerHandler.GetSpeakerState = GetSpeakerState;
  125 + s_speakerHandler.SetWorkMode = SetWorkMode;
  126 + s_speakerHandler.StartPlay = StartPlay;
  127 + s_speakerHandler.StopPlay = StopPlay;
  128 + s_speakerHandler.SetPlayMode = SetPlayMode;
  129 + s_speakerHandler.SetVolume = SetVolume;
  130 + s_speakerHandler.ReceiveTtsData = ReceiveTtsData;
  131 + s_speakerHandler.ReceiveVoiceData = ReceiveAudioData;
  132 +
  133 + returnCode = osalHandler->MutexCreate(&s_speakerMutex);
  134 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  135 + USER_LOG_ERROR("Create speaker mutex error: 0x%08llX", returnCode);
  136 + return returnCode;
  137 + }
  138 +
  139 + returnCode = ZiyanWidget_RegSpeakerHandler(&s_speakerHandler);
  140 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  141 + USER_LOG_ERROR("Register speaker handler error: 0x%08llX", returnCode);
  142 + return returnCode;
  143 + }
  144 +
  145 + returnCode = osalHandler->MutexLock(s_speakerMutex);
  146 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  147 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  148 + return returnCode;
  149 + }
  150 +
  151 + s_speakerState.state = ZIYAN_WIDGET_SPEAKER_STATE_IDEL;
  152 + s_speakerState.workMode = ZIYAN_WIDGET_SPEAKER_WORK_MODE_VOICE;
  153 + s_speakerState.playMode = ZIYAN_WIDGET_SPEAKER_PLAY_MODE_SINGLE_PLAY;
  154 +
  155 + returnCode = osalHandler->MutexUnlock(s_speakerMutex);
  156 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  157 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  158 + return returnCode;
  159 + }
  160 +
  161 + returnCode = SetVolume(WIDGET_SPEAKER_DEFAULT_VOLUME);
  162 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  163 + USER_LOG_ERROR("Set speaker volume error: 0x%08llX", returnCode);
  164 + return returnCode;
  165 + }
  166 +
  167 +#ifdef SYSTEM_ARCH_LINUX
  168 + if (osalHandler->TaskCreate("user_widget_speaker_task", ZiyanTest_WidgetSpeakerTask, WIDGET_SPEAKER_TASK_STACK_SIZE,
  169 + NULL,
  170 + &s_widgetSpeakerTestThread) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  171 + USER_LOG_ERROR("Ziyan widget speaker test task create error.");
  172 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  173 + }
  174 +#endif
  175 +
  176 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  177 +}
  178 +
  179 +#ifdef ALSA_INSTALLED
  180 +T_ZiyanReturnCode ZiyanTest_AsoundInit()
  181 +{
  182 + // 打开默认音频设备
  183 + if (snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0) {
  184 + fprintf(stderr, "无法打开音频设备\n");
  185 + return 1;
  186 + }
  187 +
  188 + // 分配硬件参数结构体
  189 + snd_pcm_hw_params_alloca(&hw_params);
  190 + snd_pcm_hw_params_any(pcm_handle, hw_params);
  191 +
  192 + // 设置硬件参数
  193 + snd_pcm_hw_params_set_access(pcm_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
  194 + snd_pcm_hw_params_set_format(pcm_handle, hw_params, SND_PCM_FORMAT_S16_LE); // 16-bit little-endian
  195 + snd_pcm_hw_params_set_rate(pcm_handle, hw_params, WIDGET_SPEAKER_AUDIO_OPUS_SAMPLE_RATE, 0); // 设置采样率为 16kHz
  196 + snd_pcm_hw_params_set_channels(pcm_handle, hw_params, WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS); // 设置单声道
  197 + snd_pcm_hw_params_set_buffer_size(pcm_handle, hw_params, 16000 * 8);
  198 + snd_pcm_hw_params_set_period_size(pcm_handle, hw_params, 1280, 0);
  199 +
  200 + // 应用硬件参数
  201 + if (snd_pcm_hw_params(pcm_handle, hw_params) < 0) {
  202 + fprintf(stderr, "无法设置硬件参数\n");
  203 + return 1;
  204 + }
  205 +
  206 + // 设置软件参数
  207 + snd_pcm_sw_params_alloca(&sw_params);
  208 + snd_pcm_sw_params_current(pcm_handle, sw_params);
  209 + snd_pcm_sw_params_set_avail_min(pcm_handle, sw_params, 1280);
  210 + snd_pcm_sw_params_set_start_threshold(pcm_handle, sw_params, 0);
  211 +
  212 + // 应用软件参数
  213 + if (snd_pcm_sw_params(pcm_handle, sw_params) < 0) {
  214 + fprintf(stderr, "无法设置软件参数\n");
  215 + return 1;
  216 + }
  217 +
  218 + // snd_pcm_prepare(pcm_handle);
  219 +
  220 + return 0;
  221 +}
  222 +#endif
  223 +
  224 +
  225 +T_ZiyanReturnCode ZiyanTest_PcmPlay(uint8_t* pcm_data, uint64_t size)
  226 +{
  227 +#ifdef ALSA_INSTALLED
  228 + if((pcm_handle != NULL)){
  229 + int err = snd_pcm_writei(pcm_handle, pcm_data, size);
  230 +
  231 + snd_pcm_sframes_t avail = snd_pcm_avail(pcm_handle);
  232 + if((16000 * 8 - avail) <= 16000){
  233 +
  234 + uint8_t pcm_empty[16000];
  235 + memset(pcm_empty, 0, sizeof(pcm_empty));
  236 + snd_pcm_writei(pcm_handle, pcm_empty, sizeof(pcm_empty));
  237 + }
  238 + // snd_pcm_sframes_t avail = 0;
  239 + printf("play pcm %d : %ld : %ld\n", err, size, avail);
  240 +
  241 + // 错误处理
  242 + if (err == -EPIPE) {
  243 + fprintf(stderr, "发生缓冲区溢出错误!\n");
  244 + snd_pcm_prepare(pcm_handle);
  245 + } else if (err < 0) {
  246 + fprintf(stderr, "播放失败: %s\n", snd_strerror(err));
  247 + } else if (err < 640) {
  248 + fprintf(stderr, "警告: 写入的帧数少于预期\n");
  249 + }
  250 + }
  251 +#endif
  252 +}
  253 +
  254 +/* Private functions definition-----------------------------------------------*/
  255 +#ifdef SYSTEM_ARCH_LINUX
  256 +
  257 +static uint32_t ZiyanTest_GetVoicePlayProcessId(void)
  258 +{
  259 + FILE *fp;
  260 + char cmdStr[128];
  261 + uint32_t pid;
  262 + int ret;
  263 +
  264 + snprintf(cmdStr, 128, "pgrep ffplay");
  265 + fp = popen(cmdStr, "r");
  266 + if (fp == NULL) {
  267 + USER_LOG_ERROR("fp is null.");
  268 + return 0;
  269 + }
  270 +
  271 + ret = fscanf(fp, "%u", &pid);
  272 + if (ret <= 0) {
  273 + pid = 0;
  274 + goto out;
  275 + }
  276 +
  277 +out:
  278 + pclose(fp);
  279 +
  280 + return pid;
  281 +}
  282 +
  283 +static uint32_t ZiyanTest_KillVoicePlayProcess(uint32_t pid)
  284 +{
  285 + FILE *fp;
  286 + char cmdStr[128];
  287 +
  288 + snprintf(cmdStr, 128, "kill %d", pid);
  289 + fp = popen(cmdStr, "r");
  290 + if (fp == NULL) {
  291 + USER_LOG_ERROR("fp is null.");
  292 + return 0;
  293 + }
  294 +
  295 + pclose(fp);
  296 +
  297 + return pid;
  298 +}
  299 +
  300 +static T_ZiyanReturnCode ZiyanTest_DecodeAudioData(void)
  301 +{
  302 +#ifdef OPUS_INSTALLED
  303 + FILE *fin;
  304 + FILE *fout;
  305 + OpusDecoder *decoder;
  306 + opus_int16 out[WIDGET_SPEAKER_AUDIO_OPUS_MAX_FRAME_SIZE * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS];
  307 + uint8_t cbits[WIDGET_SPEAKER_AUDIO_OPUS_MAX_PACKET_SIZE];
  308 + int32_t nbBytes;
  309 + int32_t err;
  310 +
  311 + /*! Attention: you can use "ffmpeg -i xxx.mp3 -ar 16000 -ac 1 out.wav" and use opus-tools to generate opus file for test */
  312 + fin = fopen(WIDGET_SPEAKER_AUDIO_OPUS_FILE_NAME, "r");
  313 + if (fin == NULL) {
  314 + fprintf(stderr, "failed to open input file: %s\n", strerror(errno));
  315 + return EXIT_FAILURE;
  316 + }
  317 +
  318 + /* Create a new decoder state. */
  319 + decoder = opus_decoder_create(WIDGET_SPEAKER_AUDIO_OPUS_SAMPLE_RATE, WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS, &err);
  320 + if (err < 0) {
  321 + fprintf(stderr, "failed to create decoder: %s\n", opus_strerror(err));
  322 + goto close_fin;
  323 + }
  324 +
  325 + fout = fopen(WIDGET_SPEAKER_AUDIO_PCM_FILE_NAME, "a+");
  326 + if (fout == NULL) {
  327 + fprintf(stderr, "failed to open output file: %s\n", strerror(errno));
  328 + goto close_fin;
  329 + }
  330 +
  331 + while (1) {
  332 + int i;
  333 + unsigned char pcm_bytes[WIDGET_SPEAKER_AUDIO_OPUS_MAX_FRAME_SIZE * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS * 4] = {0};
  334 + int frame_size;
  335 +
  336 + /* Read a 16 bits/sample audio frame. */
  337 + nbBytes = fread(cbits, 1, s_decodeBitrate / WIDGET_SPEAKER_AUDIO_OPUS_DECODE_BITRATE_8KBPS *
  338 + WIDGET_SPEAKER_AUDIO_OPUS_DECODE_FRAME_SIZE_8KBPS * 8, fin);
  339 +
  340 + /* Decode the data. In this example, frame_size will be constant because
  341 + the encoder is using a constant frame size. However, that may not
  342 + be the case for all encoders, so the decoder must always check
  343 + the frame size returned. */
  344 + frame_size = opus_decode(decoder, cbits, nbBytes, out, WIDGET_SPEAKER_AUDIO_OPUS_MAX_FRAME_SIZE, 0);
  345 + if (frame_size < 0) {
  346 + fprintf(stderr, "decoder failed: %s\n", opus_strerror(frame_size));
  347 + goto close_fout;
  348 + }
  349 +
  350 + /* Convert to little-endian ordering. */
  351 + for (i = 0; i < WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS * frame_size; i++) {
  352 + pcm_bytes[2 * i] = out[i] & 0xFF;
  353 + pcm_bytes[2 * i + 1] = (out[i] >> 8) & 0xFF;
  354 + }
  355 + /* Write the decoded audio to file. */
  356 + fwrite(pcm_bytes, sizeof(short), frame_size * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS, fout);
  357 +#ifdef ALSA_INSTALLED
  358 + ZiyanTest_PcmPlay(pcm_bytes, frame_size * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS);
  359 +#endif
  360 +
  361 + if (feof(fin))
  362 + break;
  363 + }
  364 +
  365 + USER_LOG_INFO("Decode Finished...");
  366 + s_isDecodeFinished = true;
  367 +
  368 +decode_data_failed:
  369 + opus_decoder_destroy(decoder);
  370 +create_decoder_failed:
  371 + fclose(fout);
  372 +open_pcm_audio_failed:
  373 + fclose(fin);
  374 +#endif
  375 + return EXIT_SUCCESS;
  376 +
  377 +#ifdef OPUS_INSTALLED
  378 +close_fout:
  379 + fclose(fout);
  380 +
  381 +close_fin:
  382 + fclose(fin);
  383 +
  384 + return EXIT_FAILURE;
  385 +#endif
  386 +
  387 +}
  388 +
  389 +static T_ZiyanReturnCode ZiyanTest_PlayAudioData(void)
  390 +{
  391 + char cmdStr[128];
  392 +
  393 + memset(cmdStr, 0, sizeof(cmdStr));
  394 + USER_LOG_INFO("Start Playing...");
  395 +
  396 + snprintf(cmdStr, sizeof(cmdStr), "ffplay -nodisp -autoexit -ar 16000 -ac 1 -f s16le -i %s 2>/dev/null",
  397 + WIDGET_SPEAKER_AUDIO_PCM_FILE_NAME);
  398 +
  399 + return ZiyanUserUtil_RunSystemCmd(cmdStr);
  400 +}
  401 +
  402 +static T_ZiyanReturnCode ZiyanTest_PlayTtsData(void)
  403 +{
  404 + FILE *txtFile;
  405 + uint8_t data[WIDGET_SPEAKER_TTS_FILE_MAX_SIZE] = {0};
  406 + int32_t readLen;
  407 + char cmdStr[WIDGET_SPEAKER_TTS_FILE_MAX_SIZE + 128];
  408 + T_ZiyanAircraftInfoBaseInfo aircraftInfoBaseInfo;
  409 + T_ZiyanReturnCode returnCode;
  410 +
  411 + returnCode = ZiyanAircraftInfo_GetBaseInfo(&aircraftInfoBaseInfo);
  412 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  413 + USER_LOG_ERROR("get aircraft base info error");
  414 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  415 + }
  416 +
  417 + if (aircraftInfoBaseInfo.aircraftType == ZIYAN_AIRCRAFT_TYPE_SHADOW_PLUS ||
  418 + aircraftInfoBaseInfo.aircraftType == ZIYAN_AIRCRAFT_TYPE_SHADOW_MAX) {
  419 + return ZiyanTest_PlayAudioData();
  420 + } else {
  421 + txtFile = fopen(WIDGET_SPEAKER_TTS_FILE_NAME, "r");
  422 + if (txtFile == NULL) {
  423 + USER_LOG_ERROR("failed to open input file: %s\n", strerror(errno));
  424 + return EXIT_FAILURE;
  425 + }
  426 +
  427 + readLen = fread(data, 1, WIDGET_SPEAKER_TTS_FILE_MAX_SIZE - 1, txtFile);
  428 + if (readLen <= 0) {
  429 + USER_LOG_ERROR("Read tts file failed, error code: %d", readLen);
  430 + fclose(txtFile);
  431 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  432 + }
  433 +
  434 + data[readLen] = '\0';
  435 +
  436 + fclose(txtFile);
  437 +
  438 + USER_LOG_INFO("Read tts file success, len: %d", readLen);
  439 + USER_LOG_INFO("Content: %s", data);
  440 +
  441 + memset(cmdStr, 0, sizeof(cmdStr));
  442 +
  443 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_IN_TTS_CONVERSION);
  444 +
  445 +#if EKHO_INSTALLED
  446 + /*! Attention: you can use other tts opensource function to convert txt to speech, example used ekho v7.5 */
  447 + snprintf(cmdStr, sizeof(cmdStr), " ekho %s -s 20 -p 20 -a 100 -o %s", data,
  448 + WIDGET_SPEAKER_TTS_OUTPUT_FILE_NAME);
  449 +#else
  450 + USER_LOG_WARN(
  451 + "Ekho is not installed, please visit https://www.eguidedog.net/ekho.php to install it or use other TTS tools to convert audio");
  452 +#endif
  453 + ZiyanUserUtil_RunSystemCmd(cmdStr);
  454 +
  455 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_PLAYING);
  456 + USER_LOG_INFO("Start TTS Playing...");
  457 + memset(cmdStr, 0, sizeof(cmdStr));
  458 + snprintf(cmdStr, sizeof(cmdStr), "ffplay -nodisp -autoexit -ar 16000 -ac 1 -f s16le -i %s 2>/dev/null",
  459 + WIDGET_SPEAKER_TTS_OUTPUT_FILE_NAME);
  460 +
  461 + return ZiyanUserUtil_RunSystemCmd(cmdStr);
  462 + }
  463 +}
  464 +
  465 +static T_ZiyanReturnCode ZiyanTest_CheckFileMd5Sum(const char *path, uint8_t *buf, uint16_t size)
  466 +{
  467 + MD5_CTX md5Ctx;
  468 + uint32_t readFileTotalSize = 0;
  469 + uint16_t readLen;
  470 + T_ZiyanReturnCode returnCode;
  471 + uint8_t readBuf[1024] = {0};
  472 + uint8_t md5Sum[16] = {0};
  473 + FILE *file = NULL;;
  474 +
  475 + UtilMd5_Init(&md5Ctx);
  476 +
  477 + file = fopen(path, "rb");
  478 + if (file == NULL) {
  479 + USER_LOG_ERROR("Open tts file error.");
  480 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  481 + }
  482 +
  483 + while (1) {
  484 + returnCode = fseek(file, readFileTotalSize, SEEK_SET);
  485 + if (returnCode != 0) {
  486 + USER_LOG_INFO("fseek file error");
  487 + }
  488 +
  489 + readLen = fread(readBuf, 1, sizeof(readBuf), file);
  490 + if (readLen > 0) {
  491 + readFileTotalSize += readLen;
  492 + UtilMd5_Update(&md5Ctx, readBuf, readLen);
  493 + }
  494 +
  495 + if (feof(file))
  496 + break;
  497 + }
  498 +
  499 + UtilMd5_Final(&md5Ctx, md5Sum);
  500 + fclose(file);
  501 +
  502 + if (size == sizeof(md5Sum)) {
  503 + if (memcmp(md5Sum, buf, sizeof(md5Sum)) == 0) {
  504 + USER_LOG_INFO("MD5 sum check success");
  505 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  506 + } else {
  507 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  508 + }
  509 + } else {
  510 + USER_LOG_ERROR("MD5 sum length error");
  511 + }
  512 +
  513 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  514 +}
  515 +
  516 +#endif
  517 +
  518 +static void SetSpeakerState(E_ZiyanWidgetSpeakerState speakerState)
  519 +{
  520 + T_ZiyanReturnCode returnCode;
  521 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  522 +
  523 + returnCode = osalHandler->MutexLock(s_speakerMutex);
  524 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  525 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  526 + }
  527 +
  528 + s_speakerState.state = speakerState;
  529 +
  530 + returnCode = osalHandler->MutexUnlock(s_speakerMutex);
  531 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  532 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  533 + }
  534 +}
  535 +
  536 +static T_ZiyanReturnCode GetSpeakerState(T_ZiyanWidgetSpeakerState *speakerState)
  537 +{
  538 + T_ZiyanReturnCode returnCode;
  539 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  540 +
  541 + returnCode = osalHandler->MutexLock(s_speakerMutex);
  542 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  543 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  544 + return returnCode;
  545 + }
  546 +
  547 + *speakerState = s_speakerState;
  548 +
  549 + returnCode = osalHandler->MutexUnlock(s_speakerMutex);
  550 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  551 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  552 + return returnCode;
  553 + }
  554 +
  555 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  556 +}
  557 +
  558 +static T_ZiyanReturnCode SetWorkMode(E_ZiyanWidgetSpeakerWorkMode workMode)
  559 +{
  560 + T_ZiyanReturnCode returnCode;
  561 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  562 +
  563 + returnCode = osalHandler->MutexLock(s_speakerMutex);
  564 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  565 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  566 + return returnCode;
  567 + }
  568 +
  569 + USER_LOG_INFO("Set widget speaker work mode: %d", workMode);
  570 + s_speakerState.workMode = workMode;
  571 +
  572 + returnCode = osalHandler->MutexUnlock(s_speakerMutex);
  573 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  574 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  575 + return returnCode;
  576 + }
  577 +
  578 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  579 +}
  580 +
  581 +static T_ZiyanReturnCode SetPlayMode(E_ZiyanWidgetSpeakerPlayMode playMode)
  582 +{
  583 + T_ZiyanReturnCode returnCode;
  584 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  585 +
  586 + returnCode = osalHandler->MutexLock(s_speakerMutex);
  587 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  588 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  589 + return returnCode;
  590 + }
  591 +
  592 + USER_LOG_INFO("Set widget speaker play mode: %d", playMode);
  593 + s_speakerState.playMode = playMode;
  594 +
  595 + returnCode = osalHandler->MutexUnlock(s_speakerMutex);
  596 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  597 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  598 + return returnCode;
  599 + }
  600 +
  601 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  602 +}
  603 +
  604 +static T_ZiyanReturnCode StartPlay(void)
  605 +{
  606 + uint32_t pid;
  607 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  608 +
  609 +#ifdef SYSTEM_ARCH_LINUX
  610 + pid = ZiyanTest_GetVoicePlayProcessId();
  611 + if (pid != 0) {
  612 + ZiyanTest_KillVoicePlayProcess(pid);
  613 + }
  614 +#endif
  615 +
  616 + osalHandler->TaskSleepMs(5);
  617 + USER_LOG_INFO("Start widget speaker play");
  618 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_PLAYING);
  619 +
  620 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  621 +}
  622 +
  623 +static T_ZiyanReturnCode StopPlay(void)
  624 +{
  625 + T_ZiyanReturnCode returnCode;
  626 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  627 + uint32_t pid;
  628 +
  629 + returnCode = osalHandler->MutexLock(s_speakerMutex);
  630 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  631 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  632 + return returnCode;
  633 + }
  634 +
  635 + USER_LOG_INFO("Stop widget speaker play");
  636 + s_speakerState.state = ZIYAN_WIDGET_SPEAKER_STATE_IDEL;
  637 +
  638 +#ifdef SYSTEM_ARCH_LINUX
  639 + pid = ZiyanTest_GetVoicePlayProcessId();
  640 + if (pid != 0) {
  641 + ZiyanTest_KillVoicePlayProcess(pid);
  642 + }
  643 +#endif
  644 +
  645 + returnCode = osalHandler->MutexUnlock(s_speakerMutex);
  646 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  647 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  648 + return returnCode;
  649 + }
  650 +
  651 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  652 +}
  653 +
  654 +static T_ZiyanReturnCode SetVolume(uint8_t volume)
  655 +{
  656 + T_ZiyanReturnCode returnCode;
  657 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  658 + char cmdStr[128];
  659 + int32_t ret = 0;
  660 + float realVolume;
  661 +
  662 + returnCode = osalHandler->MutexLock(s_speakerMutex);
  663 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  664 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  665 + return returnCode;
  666 + }
  667 +
  668 + realVolume = 1.5f * (float) volume;
  669 + s_speakerState.volume = volume;
  670 +
  671 + USER_LOG_INFO("Set widget speaker volume: %d", volume);
  672 +
  673 + //将音量接口修改
  674 +
  675 +
  676 +// #ifdef PLATFORM_ARCH_x86_64
  677 +// snprintf(cmdStr, sizeof(cmdStr), "pactl list | grep %s -q", WIDGET_SPEAKER_USB_AUDIO_DEVICE_NAME);
  678 +// ret = system(cmdStr);
  679 +// if (ret == ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  680 +// memset(cmdStr, 0, sizeof(cmdStr));
  681 +// snprintf(cmdStr, sizeof(cmdStr), "pactl set-sink-volume %s %d%%", WIDGET_SPEAKER_USB_AUDIO_DEVICE_NAME,
  682 +// (int32_t) realVolume);
  683 +
  684 +// returnCode = ZiyanUserUtil_RunSystemCmd(cmdStr);
  685 +// if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  686 +// USER_LOG_ERROR("Set widget speaker volume error: %d", ret);
  687 +// }
  688 +// } else {
  689 +// USER_LOG_WARN("No audio device found, please add audio device and init speaker volume here.");
  690 +// }
  691 +// #else
  692 +// USER_LOG_WARN("No audio device found, please add audio device and init speaker volume here!!!");
  693 +// #endif
  694 +
  695 + returnCode = osalHandler->MutexUnlock(s_speakerMutex);
  696 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  697 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  698 + return returnCode;
  699 + }
  700 +
  701 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  702 +}
  703 +
  704 +static T_ZiyanReturnCode ReceiveTtsData(E_ZiyanWidgetTransmitDataEvent event,
  705 + uint32_t offset, uint8_t *buf, uint16_t size)
  706 +{
  707 + uint16_t writeLen;
  708 + T_ZiyanReturnCode returnCode;
  709 +
  710 + if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_START) {
  711 + USER_LOG_INFO("Create tts file.");
  712 +#ifdef SYSTEM_ARCH_LINUX
  713 + s_ttsFile = fopen(WIDGET_SPEAKER_TTS_FILE_NAME, "wb");
  714 + if (s_ttsFile == NULL) {
  715 + USER_LOG_ERROR("Open tts file error.");
  716 + }
  717 +#endif
  718 + if (s_speakerState.state != ZIYAN_WIDGET_SPEAKER_STATE_PLAYING) {
  719 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_TRANSMITTING);
  720 + }
  721 + } else if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_TRANSMIT) {
  722 + USER_LOG_INFO("Transmit tts file, offset: %d, size: %d", offset, size);
  723 +#ifdef SYSTEM_ARCH_LINUX
  724 + if (s_ttsFile != NULL) {
  725 + fseek(s_ttsFile, offset, SEEK_SET);
  726 + writeLen = fwrite(buf, 1, size, s_ttsFile);
  727 + if (writeLen != size) {
  728 + USER_LOG_ERROR("Write tts file error %d", writeLen);
  729 + }
  730 + }
  731 +#endif
  732 + if (s_speakerState.state != ZIYAN_WIDGET_SPEAKER_STATE_PLAYING) {
  733 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_TRANSMITTING);
  734 + }
  735 + } else if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_FINISH) {
  736 + USER_LOG_INFO("Close tts file.");
  737 +#ifdef SYSTEM_ARCH_LINUX
  738 + if (s_ttsFile != NULL) {
  739 + fclose(s_ttsFile);
  740 + s_ttsFile = NULL;
  741 + }
  742 +
  743 + returnCode = ZiyanTest_CheckFileMd5Sum(WIDGET_SPEAKER_TTS_FILE_NAME, buf, size);
  744 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  745 + USER_LOG_ERROR("File md5 sum check failed");
  746 + }
  747 +#endif
  748 + if (s_speakerState.state != ZIYAN_WIDGET_SPEAKER_STATE_PLAYING) {
  749 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_IDEL);
  750 + }
  751 + }
  752 +
  753 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  754 +}
  755 +
  756 +static T_ZiyanReturnCode ReceiveAudioData(E_ZiyanWidgetTransmitDataEvent event,
  757 + uint32_t offset, uint8_t *buf, uint16_t size)
  758 +{
  759 + uint16_t writeLen;
  760 + T_ZiyanReturnCode returnCode;
  761 + T_ZiyanWidgetTransDataContent transDataContent = {0};
  762 +
  763 + if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_START) {
  764 + s_isDecodeFinished = false;
  765 +#ifdef SYSTEM_ARCH_LINUX
  766 + USER_LOG_INFO("Create voice file.");
  767 + s_audioFile = fopen(WIDGET_SPEAKER_AUDIO_OPUS_FILE_NAME, "wb");
  768 + if (s_audioFile == NULL) {
  769 + USER_LOG_ERROR("Create tts file error.");
  770 + }
  771 + if (s_speakerState.state != ZIYAN_WIDGET_SPEAKER_STATE_PLAYING) {
  772 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_TRANSMITTING);
  773 + }
  774 +#endif
  775 +
  776 + memcpy(&transDataContent, buf, size);
  777 + s_decodeBitrate = transDataContent.transDataStartContent.fileDecodeBitrate;
  778 + USER_LOG_INFO("Create voice file: %s, decoder bitrate: %d.", transDataContent.transDataStartContent.fileName,
  779 + transDataContent.transDataStartContent.fileDecodeBitrate);
  780 + } else if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_TRANSMIT) {
  781 + USER_LOG_INFO("Transmit voice file, offset: %d, size: %d", offset, size);
  782 +#ifdef SYSTEM_ARCH_LINUX
  783 + if (s_audioFile != NULL) {
  784 + fseek(s_audioFile, offset, SEEK_SET);
  785 + writeLen = fwrite(buf, 1, size, s_audioFile);
  786 + if (writeLen != size) {
  787 + USER_LOG_ERROR("Write tts file error %d", writeLen);
  788 + }
  789 + }
  790 +#endif
  791 + if (s_speakerState.state != ZIYAN_WIDGET_SPEAKER_STATE_PLAYING) {
  792 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_TRANSMITTING);
  793 + }
  794 + } else if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_FINISH) {
  795 + USER_LOG_INFO("Close voice file.");
  796 + if (s_audioFile != NULL) {
  797 + fclose(s_audioFile);
  798 + s_audioFile = NULL;
  799 + }
  800 +
  801 +#ifdef SYSTEM_ARCH_LINUX
  802 + returnCode = ZiyanTest_CheckFileMd5Sum(WIDGET_SPEAKER_AUDIO_OPUS_FILE_NAME, buf, size);
  803 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  804 + USER_LOG_ERROR("File md5 sum check failed");
  805 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  806 + }
  807 +#endif
  808 + if (s_speakerState.state != ZIYAN_WIDGET_SPEAKER_STATE_PLAYING) {
  809 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_IDEL);
  810 + }
  811 +#ifdef SYSTEM_ARCH_LINUX
  812 + ZiyanTest_DecodeAudioData();
  813 +#endif
  814 + }
  815 +
  816 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  817 +}
  818 +
  819 +#ifdef SYSTEM_ARCH_LINUX
  820 +#ifndef __CC_ARM
  821 +#pragma GCC diagnostic push
  822 +#pragma GCC diagnostic ignored "-Wmissing-noreturn"
  823 +#pragma GCC diagnostic ignored "-Wreturn-type"
  824 +#endif
  825 +
  826 +static void *ZiyanTest_WidgetSpeakerTask(void *arg)
  827 +{
  828 + T_ZiyanReturnCode ziyanReturnCode;
  829 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  830 +
  831 +#ifdef ALSA_INSTALLED
  832 + ZiyanTest_AsoundInit();
  833 +#endif
  834 +
  835 + USER_UTIL_UNUSED(arg);
  836 +
  837 + while (1) {
  838 + osalHandler->TaskSleepMs(10);
  839 +
  840 + if (s_speakerState.state == ZIYAN_WIDGET_SPEAKER_STATE_PLAYING) {
  841 + if (s_speakerState.playMode == ZIYAN_WIDGET_SPEAKER_PLAY_MODE_LOOP_PLAYBACK) {
  842 + if (s_speakerState.workMode == ZIYAN_WIDGET_SPEAKER_WORK_MODE_VOICE) {
  843 + USER_LOG_DEBUG("Waiting opus decoder finished...");
  844 + while (s_isDecodeFinished == false) {
  845 + osalHandler->TaskSleepMs(1);
  846 + }
  847 + ziyanReturnCode = ZiyanTest_PlayAudioData();
  848 + if (ziyanReturnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  849 + USER_LOG_ERROR("Play audio data failed, error: 0x%08llX.", ziyanReturnCode);
  850 + }
  851 + } else {
  852 + ziyanReturnCode = ZiyanTest_PlayTtsData();
  853 + if (ziyanReturnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  854 + USER_LOG_ERROR("Play tts data failed, error: 0x%08llX.", ziyanReturnCode);
  855 + }
  856 + }
  857 + osalHandler->TaskSleepMs(1000);
  858 + } else {
  859 + if (s_speakerState.workMode == ZIYAN_WIDGET_SPEAKER_WORK_MODE_VOICE) {
  860 + USER_LOG_DEBUG("Waiting opus decoder finished...");
  861 + while (s_isDecodeFinished == false) {
  862 + osalHandler->TaskSleepMs(1);
  863 + }
  864 + ziyanReturnCode = ZiyanTest_PlayAudioData();
  865 + if (ziyanReturnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  866 + USER_LOG_ERROR("Play audio data failed, error: 0x%08llX.", ziyanReturnCode);
  867 + }
  868 + } else {
  869 + ziyanReturnCode = ZiyanTest_PlayTtsData();
  870 + if (ziyanReturnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  871 + USER_LOG_ERROR("Play tts data failed, error: 0x%08llX.", ziyanReturnCode);
  872 + }
  873 + }
  874 +
  875 + ziyanReturnCode = osalHandler->MutexLock(s_speakerMutex);
  876 + if (ziyanReturnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  877 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", ziyanReturnCode);
  878 + }
  879 +
  880 + if (s_speakerState.playMode == ZIYAN_WIDGET_SPEAKER_PLAY_MODE_SINGLE_PLAY) {
  881 + s_speakerState.state = ZIYAN_WIDGET_SPEAKER_STATE_IDEL;
  882 + }
  883 +
  884 + ziyanReturnCode = osalHandler->MutexUnlock(s_speakerMutex);
  885 + if (ziyanReturnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  886 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", ziyanReturnCode);
  887 + }
  888 + }
  889 + }
  890 + }
  891 +}
  892 +
  893 +#ifndef __CC_ARM
  894 +#pragma GCC diagnostic pop
  895 +#endif
  896 +#endif
  897 +
  898 +/****************** (C) COPYRIGHT ZIYAN Innovations *****END OF FILE****/
  1 +/**
  2 + ********************************************************************
  3 + * @file test_widget_speaker.c
  4 + * @brief
  5 + *
  6 + * @copyright (c) 2018 ZIYAN. All rights reserved.
  7 + *
  8 + * All information contained herein is, and remains, the property of ZIYAN.
  9 + * The intellectual and technical concepts contained herein are proprietary
  10 + * to ZIYAN and may be covered by U.S. and foreign patents, patents in process,
  11 + * and protected by trade secret or copyright law. Dissemination of this
  12 + * information, including but not limited to data and other proprietary
  13 + * material(s) incorporated within the information, in any form, is strictly
  14 + * prohibited without the express written consent of ZIYAN.
  15 + *
  16 + * If you receive this source code without ZIYAN’s authorization, you may not
  17 + * further disseminate the information, and you must immediately remove the
  18 + * source code and notify ZIYAN of its removal. ZIYAN reserves the right to pursue
  19 + * legal actions against you for any loss(es) or damage(s) caused by your
  20 + * failure to do so.
  21 + *
  22 + *********************************************************************
  23 + */
  24 +
  25 +/* Includes ------------------------------------------------------------------*/
  26 +#include "test_widget_speaker.h"
  27 +#include "ziyan_logger.h"
  28 +#include <stdlib.h>
  29 +#include <errno.h>
  30 +#include <string.h>
  31 +#include <stdio.h>
  32 +#include "utils/util_misc.h"
  33 +#include "utils/util_md5.h"
  34 +#include <ziyan_aircraft_info.h>
  35 +
  36 +#ifdef OPUS_INSTALLED
  37 +
  38 +#include <opus/opus.h>
  39 +
  40 +#endif
  41 +
  42 +#ifdef ALSA_INSTALLED
  43 +
  44 +#include <alsa/asoundlib.h>
  45 +
  46 +#endif
  47 +
  48 +/* Private constants ---------------------------------------------------------*/
  49 +#define WIDGET_SPEAKER_TASK_STACK_SIZE (2048)
  50 +
  51 +/*! Attention: replace your audio device name here. */
  52 +// #define WIDGET_SPEAKER_USB_AUDIO_DEVICE_NAME "alsa_output.usb-C-Media_Electronics_Inc._USB_Audio_Device-00.analog-stereo"
  53 +#define WIDGET_SPEAKER_USB_AUDIO_DEVICE_NAME "alsa_card.usb-GeneralPlus_USB_Audio_Device-00"
  54 +
  55 +#define WIDGET_SPEAKER_AUDIO_OPUS_FILE_NAME "test_audio.opus"
  56 +#define WIDGET_SPEAKER_AUDIO_PCM_FILE_NAME "test_audio.pcm"
  57 +
  58 +#define WIDGET_SPEAKER_TTS_FILE_NAME "test_tts.txt"
  59 +#define WIDGET_SPEAKER_TTS_OUTPUT_FILE_NAME "tts_audio.wav"
  60 +#define WIDGET_SPEAKER_TTS_FILE_MAX_SIZE (3000)
  61 +
  62 +/* The frame size is hardcoded for this sample code but it doesn't have to be */
  63 +#define WIDGET_SPEAKER_AUDIO_OPUS_MAX_PACKET_SIZE (3 * 1276)
  64 +#define WIDGET_SPEAKER_AUDIO_OPUS_MAX_FRAME_SIZE (6 * 960)
  65 +#define WIDGET_SPEAKER_AUDIO_OPUS_SAMPLE_RATE (16000)
  66 +#define WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS (1)
  67 +
  68 +#define WIDGET_SPEAKER_AUDIO_OPUS_DECODE_FRAME_SIZE_8KBPS (40)
  69 +#define WIDGET_SPEAKER_AUDIO_OPUS_DECODE_BITRATE_8KBPS (8000)
  70 +
  71 +/* The speaker initialization parameters */
  72 +#define WIDGET_SPEAKER_DEFAULT_VOLUME (60)
  73 +#define EKHO_INSTALLED (1)
  74 +
  75 +/* Private types -------------------------------------------------------------*/
  76 +
  77 +/* Private values -------------------------------------------------------------*/
  78 +static T_ZiyanWidgetSpeakerHandler s_speakerHandler = {0};
  79 +static T_ZiyanMutexHandle s_speakerMutex = {0};
  80 +static T_ZiyanWidgetSpeakerState s_speakerState = {0};
  81 +static T_ZiyanTaskHandle s_widgetSpeakerTestThread;
  82 +
  83 +static FILE *s_audioFile = NULL;
  84 +static FILE *s_ttsFile = NULL;
  85 +static bool s_isDecodeFinished = true;
  86 +static uint16_t s_decodeBitrate = 0;
  87 +
  88 +#ifdef ALSA_INSTALLED
  89 + snd_pcm_t *pcm_handle = NULL;
  90 + snd_pcm_hw_params_t *hw_params = NULL;
  91 + snd_pcm_sw_params_t *sw_params = NULL;
  92 +#endif
  93 +
  94 +/* Private functions declaration ---------------------------------------------*/
  95 +static void SetSpeakerState(E_ZiyanWidgetSpeakerState speakerState);
  96 +static T_ZiyanReturnCode GetSpeakerState(T_ZiyanWidgetSpeakerState *speakerState);
  97 +static T_ZiyanReturnCode SetWorkMode(E_ZiyanWidgetSpeakerWorkMode workMode);
  98 +static T_ZiyanReturnCode SetPlayMode(E_ZiyanWidgetSpeakerPlayMode playMode);
  99 +static T_ZiyanReturnCode StartPlay(void);
  100 +static T_ZiyanReturnCode StopPlay(void);
  101 +static T_ZiyanReturnCode SetVolume(uint8_t volume);
  102 +static T_ZiyanReturnCode ReceiveTtsData(E_ZiyanWidgetTransmitDataEvent event,
  103 + uint32_t offset, uint8_t *buf, uint16_t size);
  104 +static T_ZiyanReturnCode ReceiveAudioData(E_ZiyanWidgetTransmitDataEvent event,
  105 + uint32_t offset, uint8_t *buf, uint16_t size);
  106 +#ifdef SYSTEM_ARCH_LINUX
  107 +static void *ZiyanTest_WidgetSpeakerTask(void *arg);
  108 +static uint32_t ZiyanTest_GetVoicePlayProcessId(void);
  109 +static uint32_t ZiyanTest_KillVoicePlayProcess(uint32_t pid);
  110 +static T_ZiyanReturnCode ZiyanTest_DecodeAudioData(void);
  111 +static T_ZiyanReturnCode ZiyanTest_PlayAudioData(void);
  112 +static T_ZiyanReturnCode ZiyanTest_PlayTtsData(void);
  113 +static T_ZiyanReturnCode ZiyanTest_CheckFileMd5Sum(const char *path, uint8_t *buf, uint16_t size);
  114 +#endif
  115 +
  116 +/* Exported functions definition ---------------------------------------------*/
  117 +T_ZiyanReturnCode ZiyanTest_WidgetSpeakerStartService(void)
  118 +{
  119 + T_ZiyanReturnCode returnCode;
  120 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  121 +
  122 + s_speakerHandler.GetSpeakerState = GetSpeakerState;
  123 + s_speakerHandler.SetWorkMode = SetWorkMode;
  124 + s_speakerHandler.StartPlay = StartPlay;
  125 + s_speakerHandler.StopPlay = StopPlay;
  126 + s_speakerHandler.SetPlayMode = SetPlayMode;
  127 + s_speakerHandler.SetVolume = SetVolume;
  128 + s_speakerHandler.ReceiveTtsData = ReceiveTtsData;
  129 + s_speakerHandler.ReceiveVoiceData = ReceiveAudioData;
  130 +
  131 + returnCode = osalHandler->MutexCreate(&s_speakerMutex);
  132 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  133 + USER_LOG_ERROR("Create speaker mutex error: 0x%08llX", returnCode);
  134 + return returnCode;
  135 + }
  136 +
  137 + returnCode = ZiyanWidget_RegSpeakerHandler(&s_speakerHandler);
  138 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  139 + USER_LOG_ERROR("Register speaker handler error: 0x%08llX", returnCode);
  140 + return returnCode;
  141 + }
  142 +
  143 + returnCode = osalHandler->MutexLock(s_speakerMutex);
  144 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  145 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  146 + return returnCode;
  147 + }
  148 +
  149 + s_speakerState.state = ZIYAN_WIDGET_SPEAKER_STATE_IDEL;
  150 + s_speakerState.workMode = ZIYAN_WIDGET_SPEAKER_WORK_MODE_VOICE;
  151 + s_speakerState.playMode = ZIYAN_WIDGET_SPEAKER_PLAY_MODE_SINGLE_PLAY;
  152 +
  153 + returnCode = osalHandler->MutexUnlock(s_speakerMutex);
  154 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  155 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  156 + return returnCode;
  157 + }
  158 +
  159 + returnCode = SetVolume(WIDGET_SPEAKER_DEFAULT_VOLUME);
  160 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  161 + USER_LOG_ERROR("Set speaker volume error: 0x%08llX", returnCode);
  162 + return returnCode;
  163 + }
  164 +
  165 +#ifdef SYSTEM_ARCH_LINUX
  166 + if (osalHandler->TaskCreate("user_widget_speaker_task", ZiyanTest_WidgetSpeakerTask, WIDGET_SPEAKER_TASK_STACK_SIZE,
  167 + NULL,
  168 + &s_widgetSpeakerTestThread) != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  169 + USER_LOG_ERROR("Ziyan widget speaker test task create error.");
  170 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
  171 + }
  172 +#endif
  173 +
  174 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  175 +}
  176 +
  177 +#ifdef ALSA_INSTALLED
  178 +T_ZiyanReturnCode ZiyanTest_AsoundInit()
  179 +{
  180 + // 打开默认音频设备
  181 + if (snd_pcm_open(&pcm_handle, "default", SND_PCM_STREAM_PLAYBACK, 0) < 0) {
  182 + fprintf(stderr, "无法打开音频设备\n");
  183 + return 1;
  184 + }
  185 +
  186 + // 分配硬件参数结构体
  187 + snd_pcm_hw_params_alloca(&hw_params);
  188 + snd_pcm_hw_params_any(pcm_handle, hw_params);
  189 +
  190 + // 设置硬件参数
  191 + snd_pcm_hw_params_set_access(pcm_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED);
  192 + snd_pcm_hw_params_set_format(pcm_handle, hw_params, SND_PCM_FORMAT_S16_LE); // 16-bit little-endian
  193 + snd_pcm_hw_params_set_rate(pcm_handle, hw_params, WIDGET_SPEAKER_AUDIO_OPUS_SAMPLE_RATE, 0); // 设置采样率为 16kHz
  194 + snd_pcm_hw_params_set_channels(pcm_handle, hw_params, WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS); // 设置单声道
  195 + snd_pcm_hw_params_set_buffer_size(pcm_handle, hw_params, 16000 * 8);
  196 + snd_pcm_hw_params_set_period_size(pcm_handle, hw_params, 1280, 0);
  197 +
  198 + // 应用硬件参数
  199 + if (snd_pcm_hw_params(pcm_handle, hw_params) < 0) {
  200 + fprintf(stderr, "无法设置硬件参数\n");
  201 + return 1;
  202 + }
  203 +
  204 + // 设置软件参数
  205 + snd_pcm_sw_params_alloca(&sw_params);
  206 + snd_pcm_sw_params_current(pcm_handle, sw_params);
  207 + snd_pcm_sw_params_set_avail_min(pcm_handle, sw_params, 1280);
  208 + snd_pcm_sw_params_set_start_threshold(pcm_handle, sw_params, 0);
  209 +
  210 + // 应用软件参数
  211 + if (snd_pcm_sw_params(pcm_handle, sw_params) < 0) {
  212 + fprintf(stderr, "无法设置软件参数\n");
  213 + return 1;
  214 + }
  215 +
  216 + // snd_pcm_prepare(pcm_handle);
  217 +
  218 + return 0;
  219 +}
  220 +#endif
  221 +
  222 +
  223 +T_ZiyanReturnCode ZiyanTest_PcmPlay(uint8_t* pcm_data, uint64_t size)
  224 +{
  225 +#ifdef ALSA_INSTALLED
  226 + if((pcm_handle != NULL)){
  227 + int err = snd_pcm_writei(pcm_handle, pcm_data, size);
  228 +
  229 + snd_pcm_sframes_t avail = snd_pcm_avail(pcm_handle);
  230 + if((16000 * 8 - avail) <= 16000){
  231 +
  232 + uint8_t pcm_empty[16000];
  233 + memset(pcm_empty, 0, sizeof(pcm_empty));
  234 + snd_pcm_writei(pcm_handle, pcm_empty, sizeof(pcm_empty));
  235 + }
  236 + // snd_pcm_sframes_t avail = 0;
  237 + printf("play pcm %d : %ld : %ld\n", err, size, avail);
  238 +
  239 + // 错误处理
  240 + if (err == -EPIPE) {
  241 + fprintf(stderr, "发生缓冲区溢出错误!\n");
  242 + snd_pcm_prepare(pcm_handle);
  243 + } else if (err < 0) {
  244 + fprintf(stderr, "播放失败: %s\n", snd_strerror(err));
  245 + } else if (err < 640) {
  246 + fprintf(stderr, "警告: 写入的帧数少于预期\n");
  247 + }
  248 + }
  249 +#endif
  250 +}
  251 +
  252 +/* Private functions definition-----------------------------------------------*/
  253 +#ifdef SYSTEM_ARCH_LINUX
  254 +
  255 +static uint32_t ZiyanTest_GetVoicePlayProcessId(void)
  256 +{
  257 + FILE *fp;
  258 + char cmdStr[128];
  259 + uint32_t pid;
  260 + int ret;
  261 +
  262 + snprintf(cmdStr, 128, "pgrep ffplay");
  263 + fp = popen(cmdStr, "r");
  264 + if (fp == NULL) {
  265 + USER_LOG_ERROR("fp is null.");
  266 + return 0;
  267 + }
  268 +
  269 + ret = fscanf(fp, "%u", &pid);
  270 + if (ret <= 0) {
  271 + pid = 0;
  272 + goto out;
  273 + }
  274 +
  275 +out:
  276 + pclose(fp);
  277 +
  278 + return pid;
  279 +}
  280 +
  281 +static uint32_t ZiyanTest_KillVoicePlayProcess(uint32_t pid)
  282 +{
  283 + FILE *fp;
  284 + char cmdStr[128];
  285 +
  286 + snprintf(cmdStr, 128, "kill %d", pid);
  287 + fp = popen(cmdStr, "r");
  288 + if (fp == NULL) {
  289 + USER_LOG_ERROR("fp is null.");
  290 + return 0;
  291 + }
  292 +
  293 + pclose(fp);
  294 +
  295 + return pid;
  296 +}
  297 +
  298 +static T_ZiyanReturnCode ZiyanTest_DecodeAudioData(void)
  299 +{
  300 +#ifdef OPUS_INSTALLED
  301 + FILE *fin;
  302 + FILE *fout;
  303 + OpusDecoder *decoder;
  304 + opus_int16 out[WIDGET_SPEAKER_AUDIO_OPUS_MAX_FRAME_SIZE * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS];
  305 + uint8_t cbits[WIDGET_SPEAKER_AUDIO_OPUS_MAX_PACKET_SIZE];
  306 + int32_t nbBytes;
  307 + int32_t err;
  308 +
  309 + /*! Attention: you can use "ffmpeg -i xxx.mp3 -ar 16000 -ac 1 out.wav" and use opus-tools to generate opus file for test */
  310 + fin = fopen(WIDGET_SPEAKER_AUDIO_OPUS_FILE_NAME, "r");
  311 + if (fin == NULL) {
  312 + fprintf(stderr, "failed to open input file: %s\n", strerror(errno));
  313 + return EXIT_FAILURE;
  314 + }
  315 +
  316 + /* Create a new decoder state. */
  317 + decoder = opus_decoder_create(WIDGET_SPEAKER_AUDIO_OPUS_SAMPLE_RATE, WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS, &err);
  318 + if (err < 0) {
  319 + fprintf(stderr, "failed to create decoder: %s\n", opus_strerror(err));
  320 + goto close_fin;
  321 + }
  322 +
  323 + fout = fopen(WIDGET_SPEAKER_AUDIO_PCM_FILE_NAME, "a+");
  324 + if (fout == NULL) {
  325 + fprintf(stderr, "failed to open output file: %s\n", strerror(errno));
  326 + goto close_fin;
  327 + }
  328 +
  329 + while (1) {
  330 + int i;
  331 + unsigned char pcm_bytes[WIDGET_SPEAKER_AUDIO_OPUS_MAX_FRAME_SIZE * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS * 4] = {0};
  332 + int frame_size;
  333 +
  334 + /* Read a 16 bits/sample audio frame. */
  335 + nbBytes = fread(cbits, 1, s_decodeBitrate / WIDGET_SPEAKER_AUDIO_OPUS_DECODE_BITRATE_8KBPS *
  336 + WIDGET_SPEAKER_AUDIO_OPUS_DECODE_FRAME_SIZE_8KBPS * 8, fin);
  337 +
  338 + /* Decode the data. In this example, frame_size will be constant because
  339 + the encoder is using a constant frame size. However, that may not
  340 + be the case for all encoders, so the decoder must always check
  341 + the frame size returned. */
  342 + frame_size = opus_decode(decoder, cbits, nbBytes, out, WIDGET_SPEAKER_AUDIO_OPUS_MAX_FRAME_SIZE, 0);
  343 + if (frame_size < 0) {
  344 + fprintf(stderr, "decoder failed: %s\n", opus_strerror(frame_size));
  345 + goto close_fout;
  346 + }
  347 +
  348 + /* Convert to little-endian ordering. */
  349 + for (i = 0; i < WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS * frame_size; i++) {
  350 + pcm_bytes[2 * i] = out[i] & 0xFF;
  351 + pcm_bytes[2 * i + 1] = (out[i] >> 8) & 0xFF;
  352 + }
  353 + /* Write the decoded audio to file. */
  354 + fwrite(pcm_bytes, sizeof(short), frame_size * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS, fout);
  355 +#ifdef ALSA_INSTALLED
  356 + ZiyanTest_PcmPlay(pcm_bytes, frame_size * WIDGET_SPEAKER_AUDIO_OPUS_CHANNELS);
  357 +#endif
  358 +
  359 + if (feof(fin))
  360 + break;
  361 + }
  362 +
  363 + USER_LOG_INFO("Decode Finished...");
  364 + s_isDecodeFinished = true;
  365 +
  366 +decode_data_failed:
  367 + opus_decoder_destroy(decoder);
  368 +create_decoder_failed:
  369 + fclose(fout);
  370 +open_pcm_audio_failed:
  371 + fclose(fin);
  372 +#endif
  373 + return EXIT_SUCCESS;
  374 +
  375 +#ifdef OPUS_INSTALLED
  376 +close_fout:
  377 + fclose(fout);
  378 +
  379 +close_fin:
  380 + fclose(fin);
  381 +
  382 + return EXIT_FAILURE;
  383 +#endif
  384 +
  385 +}
  386 +
  387 +static T_ZiyanReturnCode ZiyanTest_PlayAudioData(void)
  388 +{
  389 + char cmdStr[128];
  390 +
  391 + memset(cmdStr, 0, sizeof(cmdStr));
  392 + USER_LOG_INFO("Start Playing...");
  393 +
  394 + snprintf(cmdStr, sizeof(cmdStr), "ffplay -nodisp -autoexit -ar 16000 -ac 1 -f s16le -i %s 2>/dev/null",
  395 + WIDGET_SPEAKER_AUDIO_PCM_FILE_NAME);
  396 +
  397 + return ZiyanUserUtil_RunSystemCmd(cmdStr);
  398 +}
  399 +
  400 +static T_ZiyanReturnCode ZiyanTest_PlayTtsData(void)
  401 +{
  402 + FILE *txtFile;
  403 + uint8_t data[WIDGET_SPEAKER_TTS_FILE_MAX_SIZE] = {0};
  404 + int32_t readLen;
  405 + char cmdStr[WIDGET_SPEAKER_TTS_FILE_MAX_SIZE + 128];
  406 + T_ZiyanAircraftInfoBaseInfo aircraftInfoBaseInfo;
  407 + T_ZiyanReturnCode returnCode;
  408 +
  409 + returnCode = ZiyanAircraftInfo_GetBaseInfo(&aircraftInfoBaseInfo);
  410 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  411 + USER_LOG_ERROR("get aircraft base info error");
  412 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  413 + }
  414 +
  415 + if (aircraftInfoBaseInfo.aircraftType == ZIYAN_AIRCRAFT_TYPE_SHADOW_PLUS ||
  416 + aircraftInfoBaseInfo.aircraftType == ZIYAN_AIRCRAFT_TYPE_SHADOW_MAX) {
  417 + return ZiyanTest_PlayAudioData();
  418 + } else {
  419 + txtFile = fopen(WIDGET_SPEAKER_TTS_FILE_NAME, "r");
  420 + if (txtFile == NULL) {
  421 + USER_LOG_ERROR("failed to open input file: %s\n", strerror(errno));
  422 + return EXIT_FAILURE;
  423 + }
  424 +
  425 + readLen = fread(data, 1, WIDGET_SPEAKER_TTS_FILE_MAX_SIZE - 1, txtFile);
  426 + if (readLen <= 0) {
  427 + USER_LOG_ERROR("Read tts file failed, error code: %d", readLen);
  428 + fclose(txtFile);
  429 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_NOT_FOUND;
  430 + }
  431 +
  432 + data[readLen] = '\0';
  433 +
  434 + fclose(txtFile);
  435 +
  436 + USER_LOG_INFO("Read tts file success, len: %d", readLen);
  437 + USER_LOG_INFO("Content: %s", data);
  438 +
  439 + memset(cmdStr, 0, sizeof(cmdStr));
  440 +
  441 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_IN_TTS_CONVERSION);
  442 +
  443 +#if EKHO_INSTALLED
  444 + /*! Attention: you can use other tts opensource function to convert txt to speech, example used ekho v7.5 */
  445 + snprintf(cmdStr, sizeof(cmdStr), " ekho %s -s 20 -p 20 -a 100 -o %s", data,
  446 + WIDGET_SPEAKER_TTS_OUTPUT_FILE_NAME);
  447 +#else
  448 + USER_LOG_WARN(
  449 + "Ekho is not installed, please visit https://www.eguidedog.net/ekho.php to install it or use other TTS tools to convert audio");
  450 +#endif
  451 + ZiyanUserUtil_RunSystemCmd(cmdStr);
  452 +
  453 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_PLAYING);
  454 + USER_LOG_INFO("Start TTS Playing...");
  455 + memset(cmdStr, 0, sizeof(cmdStr));
  456 + snprintf(cmdStr, sizeof(cmdStr), "ffplay -nodisp -autoexit -ar 16000 -ac 1 -f s16le -i %s 2>/dev/null",
  457 + WIDGET_SPEAKER_TTS_OUTPUT_FILE_NAME);
  458 +
  459 + return ZiyanUserUtil_RunSystemCmd(cmdStr);
  460 + }
  461 +}
  462 +
  463 +static T_ZiyanReturnCode ZiyanTest_CheckFileMd5Sum(const char *path, uint8_t *buf, uint16_t size)
  464 +{
  465 + MD5_CTX md5Ctx;
  466 + uint32_t readFileTotalSize = 0;
  467 + uint16_t readLen;
  468 + T_ZiyanReturnCode returnCode;
  469 + uint8_t readBuf[1024] = {0};
  470 + uint8_t md5Sum[16] = {0};
  471 + FILE *file = NULL;;
  472 +
  473 + UtilMd5_Init(&md5Ctx);
  474 +
  475 + file = fopen(path, "rb");
  476 + if (file == NULL) {
  477 + USER_LOG_ERROR("Open tts file error.");
  478 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  479 + }
  480 +
  481 + while (1) {
  482 + returnCode = fseek(file, readFileTotalSize, SEEK_SET);
  483 + if (returnCode != 0) {
  484 + USER_LOG_INFO("fseek file error");
  485 + }
  486 +
  487 + readLen = fread(readBuf, 1, sizeof(readBuf), file);
  488 + if (readLen > 0) {
  489 + readFileTotalSize += readLen;
  490 + UtilMd5_Update(&md5Ctx, readBuf, readLen);
  491 + }
  492 +
  493 + if (feof(file))
  494 + break;
  495 + }
  496 +
  497 + UtilMd5_Final(&md5Ctx, md5Sum);
  498 + fclose(file);
  499 +
  500 + if (size == sizeof(md5Sum)) {
  501 + if (memcmp(md5Sum, buf, sizeof(md5Sum)) == 0) {
  502 + USER_LOG_INFO("MD5 sum check success");
  503 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  504 + } else {
  505 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  506 + }
  507 + } else {
  508 + USER_LOG_ERROR("MD5 sum length error");
  509 + }
  510 +
  511 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  512 +}
  513 +
  514 +#endif
  515 +
  516 +static void SetSpeakerState(E_ZiyanWidgetSpeakerState speakerState)
  517 +{
  518 + T_ZiyanReturnCode returnCode;
  519 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  520 +
  521 + returnCode = osalHandler->MutexLock(s_speakerMutex);
  522 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  523 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  524 + }
  525 +
  526 + s_speakerState.state = speakerState;
  527 +
  528 + returnCode = osalHandler->MutexUnlock(s_speakerMutex);
  529 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  530 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  531 + }
  532 +}
  533 +
  534 +static T_ZiyanReturnCode GetSpeakerState(T_ZiyanWidgetSpeakerState *speakerState)
  535 +{
  536 + T_ZiyanReturnCode returnCode;
  537 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  538 +
  539 + returnCode = osalHandler->MutexLock(s_speakerMutex);
  540 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  541 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  542 + return returnCode;
  543 + }
  544 +
  545 + *speakerState = s_speakerState;
  546 +
  547 + returnCode = osalHandler->MutexUnlock(s_speakerMutex);
  548 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  549 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  550 + return returnCode;
  551 + }
  552 +
  553 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  554 +}
  555 +
  556 +static T_ZiyanReturnCode SetWorkMode(E_ZiyanWidgetSpeakerWorkMode workMode)
  557 +{
  558 + T_ZiyanReturnCode returnCode;
  559 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  560 +
  561 + returnCode = osalHandler->MutexLock(s_speakerMutex);
  562 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  563 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  564 + return returnCode;
  565 + }
  566 +
  567 + USER_LOG_INFO("Set widget speaker work mode: %d", workMode);
  568 + s_speakerState.workMode = workMode;
  569 +
  570 + returnCode = osalHandler->MutexUnlock(s_speakerMutex);
  571 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  572 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  573 + return returnCode;
  574 + }
  575 +
  576 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  577 +}
  578 +
  579 +static T_ZiyanReturnCode SetPlayMode(E_ZiyanWidgetSpeakerPlayMode playMode)
  580 +{
  581 + T_ZiyanReturnCode returnCode;
  582 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  583 +
  584 + returnCode = osalHandler->MutexLock(s_speakerMutex);
  585 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  586 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  587 + return returnCode;
  588 + }
  589 +
  590 + USER_LOG_INFO("Set widget speaker play mode: %d", playMode);
  591 + s_speakerState.playMode = playMode;
  592 +
  593 + returnCode = osalHandler->MutexUnlock(s_speakerMutex);
  594 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  595 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  596 + return returnCode;
  597 + }
  598 +
  599 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  600 +}
  601 +
  602 +static T_ZiyanReturnCode StartPlay(void)
  603 +{
  604 + uint32_t pid;
  605 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  606 +
  607 +#ifdef SYSTEM_ARCH_LINUX
  608 + pid = ZiyanTest_GetVoicePlayProcessId();
  609 + if (pid != 0) {
  610 + ZiyanTest_KillVoicePlayProcess(pid);
  611 + }
  612 +#endif
  613 +
  614 + osalHandler->TaskSleepMs(5);
  615 + USER_LOG_INFO("Start widget speaker play");
  616 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_PLAYING);
  617 +
  618 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  619 +}
  620 +
  621 +static T_ZiyanReturnCode StopPlay(void)
  622 +{
  623 + T_ZiyanReturnCode returnCode;
  624 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  625 + uint32_t pid;
  626 +
  627 + returnCode = osalHandler->MutexLock(s_speakerMutex);
  628 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  629 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  630 + return returnCode;
  631 + }
  632 +
  633 + USER_LOG_INFO("Stop widget speaker play");
  634 + s_speakerState.state = ZIYAN_WIDGET_SPEAKER_STATE_IDEL;
  635 +
  636 +#ifdef SYSTEM_ARCH_LINUX
  637 + pid = ZiyanTest_GetVoicePlayProcessId();
  638 + if (pid != 0) {
  639 + ZiyanTest_KillVoicePlayProcess(pid);
  640 + }
  641 +#endif
  642 +
  643 + returnCode = osalHandler->MutexUnlock(s_speakerMutex);
  644 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  645 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  646 + return returnCode;
  647 + }
  648 +
  649 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  650 +}
  651 +
  652 +static T_ZiyanReturnCode SetVolume(uint8_t volume)
  653 +{
  654 + T_ZiyanReturnCode returnCode;
  655 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  656 + char cmdStr[128];
  657 + int32_t ret = 0;
  658 + float realVolume;
  659 +
  660 + returnCode = osalHandler->MutexLock(s_speakerMutex);
  661 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  662 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", returnCode);
  663 + return returnCode;
  664 + }
  665 +
  666 + realVolume = 1.5f * (float) volume;
  667 + s_speakerState.volume = volume;
  668 +
  669 + USER_LOG_INFO("Set widget speaker volume: %d", volume);
  670 +
  671 +#ifdef PLATFORM_ARCH_x86_64
  672 + snprintf(cmdStr, sizeof(cmdStr), "pactl list | grep %s -q", WIDGET_SPEAKER_USB_AUDIO_DEVICE_NAME);
  673 + ret = system(cmdStr);
  674 + if (ret == ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  675 + memset(cmdStr, 0, sizeof(cmdStr));
  676 + snprintf(cmdStr, sizeof(cmdStr), "pactl set-sink-volume %s %d%%", WIDGET_SPEAKER_USB_AUDIO_DEVICE_NAME,
  677 + (int32_t) realVolume);
  678 +
  679 + returnCode = ZiyanUserUtil_RunSystemCmd(cmdStr);
  680 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  681 + USER_LOG_ERROR("Set widget speaker volume error: %d", ret);
  682 + }
  683 + } else {
  684 + USER_LOG_WARN("No audio device found, please add audio device and init speaker volume here.");
  685 + }
  686 +#else
  687 + USER_LOG_WARN("No audio device found, please add audio device and init speaker volume here!!!");
  688 +#endif
  689 +
  690 + returnCode = osalHandler->MutexUnlock(s_speakerMutex);
  691 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  692 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", returnCode);
  693 + return returnCode;
  694 + }
  695 +
  696 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  697 +}
  698 +
  699 +static T_ZiyanReturnCode ReceiveTtsData(E_ZiyanWidgetTransmitDataEvent event,
  700 + uint32_t offset, uint8_t *buf, uint16_t size)
  701 +{
  702 + uint16_t writeLen;
  703 + T_ZiyanReturnCode returnCode;
  704 +
  705 + if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_START) {
  706 + USER_LOG_INFO("Create tts file.");
  707 +#ifdef SYSTEM_ARCH_LINUX
  708 + s_ttsFile = fopen(WIDGET_SPEAKER_TTS_FILE_NAME, "wb");
  709 + if (s_ttsFile == NULL) {
  710 + USER_LOG_ERROR("Open tts file error.");
  711 + }
  712 +#endif
  713 + if (s_speakerState.state != ZIYAN_WIDGET_SPEAKER_STATE_PLAYING) {
  714 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_TRANSMITTING);
  715 + }
  716 + } else if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_TRANSMIT) {
  717 + USER_LOG_INFO("Transmit tts file, offset: %d, size: %d", offset, size);
  718 +#ifdef SYSTEM_ARCH_LINUX
  719 + if (s_ttsFile != NULL) {
  720 + fseek(s_ttsFile, offset, SEEK_SET);
  721 + writeLen = fwrite(buf, 1, size, s_ttsFile);
  722 + if (writeLen != size) {
  723 + USER_LOG_ERROR("Write tts file error %d", writeLen);
  724 + }
  725 + }
  726 +#endif
  727 + if (s_speakerState.state != ZIYAN_WIDGET_SPEAKER_STATE_PLAYING) {
  728 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_TRANSMITTING);
  729 + }
  730 + } else if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_FINISH) {
  731 + USER_LOG_INFO("Close tts file.");
  732 +#ifdef SYSTEM_ARCH_LINUX
  733 + if (s_ttsFile != NULL) {
  734 + fclose(s_ttsFile);
  735 + s_ttsFile = NULL;
  736 + }
  737 +
  738 + returnCode = ZiyanTest_CheckFileMd5Sum(WIDGET_SPEAKER_TTS_FILE_NAME, buf, size);
  739 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  740 + USER_LOG_ERROR("File md5 sum check failed");
  741 + }
  742 +#endif
  743 + if (s_speakerState.state != ZIYAN_WIDGET_SPEAKER_STATE_PLAYING) {
  744 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_IDEL);
  745 + }
  746 + }
  747 +
  748 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  749 +}
  750 +
  751 +static T_ZiyanReturnCode ReceiveAudioData(E_ZiyanWidgetTransmitDataEvent event,
  752 + uint32_t offset, uint8_t *buf, uint16_t size)
  753 +{
  754 + uint16_t writeLen;
  755 + T_ZiyanReturnCode returnCode;
  756 + T_ZiyanWidgetTransDataContent transDataContent = {0};
  757 +
  758 + if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_START) {
  759 + s_isDecodeFinished = false;
  760 +#ifdef SYSTEM_ARCH_LINUX
  761 + USER_LOG_INFO("Create voice file.");
  762 + s_audioFile = fopen(WIDGET_SPEAKER_AUDIO_OPUS_FILE_NAME, "wb");
  763 + if (s_audioFile == NULL) {
  764 + USER_LOG_ERROR("Create tts file error.");
  765 + }
  766 + if (s_speakerState.state != ZIYAN_WIDGET_SPEAKER_STATE_PLAYING) {
  767 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_TRANSMITTING);
  768 + }
  769 +#endif
  770 +
  771 + memcpy(&transDataContent, buf, size);
  772 + s_decodeBitrate = transDataContent.transDataStartContent.fileDecodeBitrate;
  773 + USER_LOG_INFO("Create voice file: %s, decoder bitrate: %d.", transDataContent.transDataStartContent.fileName,
  774 + transDataContent.transDataStartContent.fileDecodeBitrate);
  775 + } else if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_TRANSMIT) {
  776 + USER_LOG_INFO("Transmit voice file, offset: %d, size: %d", offset, size);
  777 +#ifdef SYSTEM_ARCH_LINUX
  778 + if (s_audioFile != NULL) {
  779 + fseek(s_audioFile, offset, SEEK_SET);
  780 + writeLen = fwrite(buf, 1, size, s_audioFile);
  781 + if (writeLen != size) {
  782 + USER_LOG_ERROR("Write tts file error %d", writeLen);
  783 + }
  784 + }
  785 +#endif
  786 + if (s_speakerState.state != ZIYAN_WIDGET_SPEAKER_STATE_PLAYING) {
  787 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_TRANSMITTING);
  788 + }
  789 + } else if (event == ZIYAN_WIDGET_TRANSMIT_DATA_EVENT_FINISH) {
  790 + USER_LOG_INFO("Close voice file.");
  791 + if (s_audioFile != NULL) {
  792 + fclose(s_audioFile);
  793 + s_audioFile = NULL;
  794 + }
  795 +
  796 +#ifdef SYSTEM_ARCH_LINUX
  797 + returnCode = ZiyanTest_CheckFileMd5Sum(WIDGET_SPEAKER_AUDIO_OPUS_FILE_NAME, buf, size);
  798 + if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  799 + USER_LOG_ERROR("File md5 sum check failed");
  800 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
  801 + }
  802 +#endif
  803 + if (s_speakerState.state != ZIYAN_WIDGET_SPEAKER_STATE_PLAYING) {
  804 + SetSpeakerState(ZIYAN_WIDGET_SPEAKER_STATE_IDEL);
  805 + }
  806 +#ifdef SYSTEM_ARCH_LINUX
  807 + ZiyanTest_DecodeAudioData();
  808 +#endif
  809 + }
  810 +
  811 + return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  812 +}
  813 +
  814 +#ifdef SYSTEM_ARCH_LINUX
  815 +#ifndef __CC_ARM
  816 +#pragma GCC diagnostic push
  817 +#pragma GCC diagnostic ignored "-Wmissing-noreturn"
  818 +#pragma GCC diagnostic ignored "-Wreturn-type"
  819 +#endif
  820 +
  821 +static void *ZiyanTest_WidgetSpeakerTask(void *arg)
  822 +{
  823 + T_ZiyanReturnCode ziyanReturnCode;
  824 + T_ZiyanOsalHandler *osalHandler = ZiyanPlatform_GetOsalHandler();
  825 +
  826 +#ifdef ALSA_INSTALLED
  827 + ZiyanTest_AsoundInit();
  828 +#endif
  829 +
  830 + USER_UTIL_UNUSED(arg);
  831 +
  832 + while (1) {
  833 + osalHandler->TaskSleepMs(10);
  834 +
  835 + if (s_speakerState.state == ZIYAN_WIDGET_SPEAKER_STATE_PLAYING) {
  836 + if (s_speakerState.playMode == ZIYAN_WIDGET_SPEAKER_PLAY_MODE_LOOP_PLAYBACK) {
  837 + if (s_speakerState.workMode == ZIYAN_WIDGET_SPEAKER_WORK_MODE_VOICE) {
  838 + USER_LOG_DEBUG("Waiting opus decoder finished...");
  839 + while (s_isDecodeFinished == false) {
  840 + osalHandler->TaskSleepMs(1);
  841 + }
  842 + ziyanReturnCode = ZiyanTest_PlayAudioData();
  843 + if (ziyanReturnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  844 + USER_LOG_ERROR("Play audio data failed, error: 0x%08llX.", ziyanReturnCode);
  845 + }
  846 + } else {
  847 + ziyanReturnCode = ZiyanTest_PlayTtsData();
  848 + if (ziyanReturnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  849 + USER_LOG_ERROR("Play tts data failed, error: 0x%08llX.", ziyanReturnCode);
  850 + }
  851 + }
  852 + osalHandler->TaskSleepMs(1000);
  853 + } else {
  854 + if (s_speakerState.workMode == ZIYAN_WIDGET_SPEAKER_WORK_MODE_VOICE) {
  855 + USER_LOG_DEBUG("Waiting opus decoder finished...");
  856 + while (s_isDecodeFinished == false) {
  857 + osalHandler->TaskSleepMs(1);
  858 + }
  859 + ziyanReturnCode = ZiyanTest_PlayAudioData();
  860 + if (ziyanReturnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  861 + USER_LOG_ERROR("Play audio data failed, error: 0x%08llX.", ziyanReturnCode);
  862 + }
  863 + } else {
  864 + ziyanReturnCode = ZiyanTest_PlayTtsData();
  865 + if (ziyanReturnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  866 + USER_LOG_ERROR("Play tts data failed, error: 0x%08llX.", ziyanReturnCode);
  867 + }
  868 + }
  869 +
  870 + ziyanReturnCode = osalHandler->MutexLock(s_speakerMutex);
  871 + if (ziyanReturnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  872 + USER_LOG_ERROR("lock mutex error: 0x%08llX.", ziyanReturnCode);
  873 + }
  874 +
  875 + if (s_speakerState.playMode == ZIYAN_WIDGET_SPEAKER_PLAY_MODE_SINGLE_PLAY) {
  876 + s_speakerState.state = ZIYAN_WIDGET_SPEAKER_STATE_IDEL;
  877 + }
  878 +
  879 + ziyanReturnCode = osalHandler->MutexUnlock(s_speakerMutex);
  880 + if (ziyanReturnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
  881 + USER_LOG_ERROR("unlock mutex error: 0x%08llX.", ziyanReturnCode);
  882 + }
  883 + }
  884 + }
  885 + }
  886 +}
  887 +
  888 +#ifndef __CC_ARM
  889 +#pragma GCC diagnostic pop
  890 +#endif
  891 +#endif
  892 +
  893 +/****************** (C) COPYRIGHT ZIYAN Innovations *****END OF FILE****/
  1 +/**
  2 + ********************************************************************
  3 + * @file test_widget_speaker.h
  4 + * @brief This is the header file for "test_widget_speaker.c", defining the structure and
  5 + * (exported) function prototypes.
  6 + *
  7 + * @copyright (c) 2018 ZIYAN. All rights reserved.
  8 + *
  9 + * All information contained herein is, and remains, the property of ZIYAN.
  10 + * The intellectual and technical concepts contained herein are proprietary
  11 + * to ZIYAN and may be covered by U.S. and foreign patents, patents in process,
  12 + * and protected by trade secret or copyright law. Dissemination of this
  13 + * information, including but not limited to data and other proprietary
  14 + * material(s) incorporated within the information, in any form, is strictly
  15 + * prohibited without the express written consent of ZIYAN.
  16 + *
  17 + * If you receive this source code without ZIYAN’s authorization, you may not
  18 + * further disseminate the information, and you must immediately remove the
  19 + * source code and notify ZIYAN of its removal. ZIYAN reserves the right to pursue
  20 + * legal actions against you for any loss(es) or damage(s) caused by your
  21 + * failure to do so.
  22 + *
  23 + *********************************************************************
  24 + */
  25 +
  26 +/* Define to prevent recursive inclusion -------------------------------------*/
  27 +#ifndef TEST_WIDGET_SPEAKER_H
  28 +#define TEST_WIDGET_SPEAKER_H
  29 +
  30 +/* Includes ------------------------------------------------------------------*/
  31 +#include "ziyan_widget.h"
  32 +
  33 +#ifdef __cplusplus
  34 +extern "C" {
  35 +#endif
  36 +
  37 +
  38 +/* Exported constants --------------------------------------------------------*/
  39 +T_ZiyanReturnCode ZiyanTest_WidgetSpeakerStartService(void);
  40 +
  41 +/* Exported types ------------------------------------------------------------*/
  42 +
  43 +/* Exported functions --------------------------------------------------------*/
  44 +
  45 +#ifdef __cplusplus
  46 +}
  47 +#endif
  48 +
  49 +#endif // TEST_WIDGET_SPEAKER_H
  50 +/************************ (C) COPYRIGHT ZIYAN Innovations *******END OF FILE******/
@@ -6,8 +6,8 @@ @@ -6,8 +6,8 @@
6 #include "MediaProc/MediaProc.h" 6 #include "MediaProc/MediaProc.h"
7 7
8 // #include "camera_emu/test_payload_cam_emu_base.h" 8 // #include "camera_emu/test_payload_cam_emu_base.h"
9 -// #include "widget/test_widget.h"  
10 -// #include "widget/test_widget_speaker.h" 9 +#include "widget/test_widget.h"
  10 +#include "widget/test_widget_speaker.h"
11 // #include "data_transmission/test_data_transmission.h" 11 // #include "data_transmission/test_data_transmission.h"
12 12
13 #define VIDEO_FRAME_MAX_COUNT 18000 //视频最大帧数18000帧 13 #define VIDEO_FRAME_MAX_COUNT 18000 //视频最大帧数18000帧
@@ -436,24 +436,24 @@ unsigned int old_command_timeMS = 0; @@ -436,24 +436,24 @@ unsigned int old_command_timeMS = 0;
436 436
437 437
438 438
439 -// /*********************************************************************************************  
440 -// *  
441 -// * 拓展接口 : 控件相关  
442 -// *  
443 -// *************************************************************************************************/  
444 -// T_DjiReturnCode Get_RealTimeVoiceMode(int *mode)  
445 -// {  
446 -// if ( Get_Opus_PlayMode()==1 )//播放模式 为实时育英中  
447 -// {  
448 -// *mode = JZ_FLAGCODE_ON;  
449 -// }  
450 -// else  
451 -// {  
452 -// *mode = JZ_FLAGCODE_OFF;  
453 -// } 439 +/*********************************************************************************************
  440 + *
  441 + * 拓展接口 : 控件相关
  442 + *
  443 +*************************************************************************************************/
  444 +T_JZsdkReturnCode Get_RealTimeVoiceMode(int *mode)
  445 +{
  446 + if ( Get_Opus_PlayMode()==1 )//播放模式 为实时育英中
  447 + {
  448 + *mode = JZ_FLAGCODE_ON;
  449 + }
  450 + else
  451 + {
  452 + *mode = JZ_FLAGCODE_OFF;
  453 + }
454 454
455 -// return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;  
456 -// } 455 + return JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
  456 +}
457 457
458 458
459 459
@@ -474,11 +474,11 @@ T_JZsdkReturnCode Zy_JZsdkToPsdk_ExpnasionInit() @@ -474,11 +474,11 @@ T_JZsdkReturnCode Zy_JZsdkToPsdk_ExpnasionInit()
474 T_JZsdkToPsdkHandler handler = { 474 T_JZsdkToPsdkHandler handler = {
475 .low_data_tran = NULL, 475 .low_data_tran = NULL,
476 .push_DJIH264Frame_to_plane = NULL, 476 .push_DJIH264Frame_to_plane = NULL,
477 - .Set_UI_Widget_Value = NULL, 477 + .Set_UI_Widget_Value = set_wideget_value,
478 .Set_UI_SpeakerWidget_PlayState = NULL, 478 .Set_UI_SpeakerWidget_PlayState = NULL,
479 .Set_UI_SpeakerWidget_LoopMode = NULL, 479 .Set_UI_SpeakerWidget_LoopMode = NULL,
480 .Set_UI_SpeakerWidget_Volume = NULL, 480 .Set_UI_SpeakerWidget_Volume = NULL,
481 - .Get_UI_SpeakerWidget_RealTimeVoiceMode = NULL, 481 + .Get_UI_SpeakerWidget_RealTimeVoiceMode = Get_RealTimeVoiceMode,
482 }; 482 };
483 483
484 if(ExpansionApi_JZsdkToPsdk_Init(handler) != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS) 484 if(ExpansionApi_JZsdkToPsdk_Init(handler) != JZ_ERROR_SYSTEM_MODULE_CODE_SUCCESS)
@@ -66,8 +66,8 @@ typedef struct { @@ -66,8 +66,8 @@ typedef struct {
66 } T_ThreadAttribute; 66 } T_ThreadAttribute;
67 67
68 /* Private values -------------------------------------------------------------*/ 68 /* Private values -------------------------------------------------------------*/
69 -static FILE *s_djiLogFile;  
70 -static FILE *s_djiLogFileCnt; 69 +static FILE *s_ziyanLogFile;
  70 +static FILE *s_ziyanLogFileCnt;
71 static pthread_t s_monitorThread = 0; 71 static pthread_t s_monitorThread = 0;
72 72
73 /* Private functions declaration ---------------------------------------------*/ 73 /* Private functions declaration ---------------------------------------------*/
@@ -231,7 +231,7 @@ int main(int argc, char **argv) @@ -231,7 +231,7 @@ int main(int argc, char **argv)
231 #endif 231 #endif
232 232
233 // #ifdef CONFIG_MODULE_SAMPLE_XPORT_ON 233 // #ifdef CONFIG_MODULE_SAMPLE_XPORT_ON
234 -// if (aircraftInfoBaseInfo.djiAdapterType == ZIYAN_SDK_ADAPTER_TYPE_XPORT) { 234 +// if (aircraftInfoBaseInfo.ziyanAdapterType == ZIYAN_SDK_ADAPTER_TYPE_XPORT) {
235 // if (ZiyanTest_XPortStartService() != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) { 235 // if (ZiyanTest_XPortStartService() != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
236 // USER_LOG_ERROR("psdk xport init error"); 236 // USER_LOG_ERROR("psdk xport init error");
237 // } 237 // }
@@ -315,7 +315,6 @@ int main(int argc, char **argv) @@ -315,7 +315,6 @@ int main(int argc, char **argv)
315 // #endif 315 // #endif
316 // } 316 // }
317 317
318 -  
319 // /*!< Step 5: Tell the ZIYAN Pilot you are ready. */ 318 // /*!< Step 5: Tell the ZIYAN Pilot you are ready. */
320 returnCode = ZiyanCore_ApplicationStart(); 319 returnCode = ZiyanCore_ApplicationStart();
321 if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) { 320 if (returnCode != ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS) {
@@ -516,7 +515,7 @@ static T_ZiyanReturnCode ZiyanUser_FillInUserInfo(T_ZiyanUserInfo *userInfo) @@ -516,7 +515,7 @@ static T_ZiyanReturnCode ZiyanUser_FillInUserInfo(T_ZiyanUserInfo *userInfo)
516 !strcmp(USER_DEVELOPER_ACCOUNT, "your_developer_account") || 515 !strcmp(USER_DEVELOPER_ACCOUNT, "your_developer_account") ||
517 !strcmp(USER_BAUD_RATE, "your_baud_rate")) { 516 !strcmp(USER_BAUD_RATE, "your_baud_rate")) {
518 USER_LOG_ERROR( 517 USER_LOG_ERROR(
519 - "Please fill in correct user information to 'samples/sample_c/platform/linux/manifold2/application/dji_sdk_app_info.h' file."); 518 + "Please fill in correct user information to 'samples/sample_c/platform/linux/manifold2/application/ziyan_sdk_app_info.h' file.");
520 sleep(1); 519 sleep(1);
521 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER; 520 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_INVALID_PARAMETER;
522 } 521 }
@@ -545,12 +544,12 @@ static T_ZiyanReturnCode ZiyanUser_LocalWrite(const uint8_t *data, uint16_t data @@ -545,12 +544,12 @@ static T_ZiyanReturnCode ZiyanUser_LocalWrite(const uint8_t *data, uint16_t data
545 { 544 {
546 uint32_t realLen; 545 uint32_t realLen;
547 546
548 - if (s_djiLogFile == NULL) { 547 + if (s_ziyanLogFile == NULL) {
549 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN; 548 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_UNKNOWN;
550 } 549 }
551 550
552 - realLen = fwrite(data, 1, dataLen, s_djiLogFile);  
553 - fflush(s_djiLogFile); 551 + realLen = fwrite(data, 1, dataLen, s_ziyanLogFile);
  552 + fflush(s_ziyanLogFile);
554 if (realLen == dataLen) { 553 if (realLen == dataLen) {
555 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS; 554 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
556 } else { 555 } else {
@@ -560,7 +559,7 @@ static T_ZiyanReturnCode ZiyanUser_LocalWrite(const uint8_t *data, uint16_t data @@ -560,7 +559,7 @@ static T_ZiyanReturnCode ZiyanUser_LocalWrite(const uint8_t *data, uint16_t data
560 559
561 static T_ZiyanReturnCode ZiyanUser_LocalWriteFsInit(const char *path) 560 static T_ZiyanReturnCode ZiyanUser_LocalWriteFsInit(const char *path)
562 { 561 {
563 - T_ZiyanReturnCode djiReturnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS; 562 + T_ZiyanReturnCode ziyanReturnCode = ZIYAN_ERROR_SYSTEM_MODULE_CODE_SUCCESS;
564 char filePath[ZIYAN_LOG_PATH_MAX_SIZE]; 563 char filePath[ZIYAN_LOG_PATH_MAX_SIZE];
565 char systemCmd[ZIYAN_SYSTEM_CMD_STR_MAX_SIZE]; 564 char systemCmd[ZIYAN_SYSTEM_CMD_STR_MAX_SIZE];
566 char folderName[ZIYAN_LOG_FOLDER_NAME_MAX_SIZE]; 565 char folderName[ZIYAN_LOG_FOLDER_NAME_MAX_SIZE];
@@ -583,20 +582,20 @@ static T_ZiyanReturnCode ZiyanUser_LocalWriteFsInit(const char *path) @@ -583,20 +582,20 @@ static T_ZiyanReturnCode ZiyanUser_LocalWriteFsInit(const char *path)
583 } 582 }
584 } 583 }
585 584
586 - s_djiLogFileCnt = fopen(ZIYAN_LOG_INDEX_FILE_NAME, "rb+");  
587 - if (s_djiLogFileCnt == NULL) {  
588 - s_djiLogFileCnt = fopen(ZIYAN_LOG_INDEX_FILE_NAME, "wb+");  
589 - if (s_djiLogFileCnt == NULL) { 585 + s_ziyanLogFileCnt = fopen(ZIYAN_LOG_INDEX_FILE_NAME, "rb+");
  586 + if (s_ziyanLogFileCnt == NULL) {
  587 + s_ziyanLogFileCnt = fopen(ZIYAN_LOG_INDEX_FILE_NAME, "wb+");
  588 + if (s_ziyanLogFileCnt == NULL) {
590 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR; 589 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
591 } 590 }
592 } else { 591 } else {
593 - ret = fseek(s_djiLogFileCnt, 0, SEEK_SET); 592 + ret = fseek(s_ziyanLogFileCnt, 0, SEEK_SET);
594 if (ret != 0) { 593 if (ret != 0) {
595 printf("Seek log count file error, ret: %d, errno: %d.\r\n", ret, errno); 594 printf("Seek log count file error, ret: %d, errno: %d.\r\n", ret, errno);
596 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR; 595 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
597 } 596 }
598 597
599 - ret = fread((uint16_t *) &logFileIndex, 1, sizeof(uint16_t), s_djiLogFileCnt); 598 + ret = fread((uint16_t *) &logFileIndex, 1, sizeof(uint16_t), s_ziyanLogFileCnt);
600 if (ret != sizeof(uint16_t)) { 599 if (ret != sizeof(uint16_t)) {
601 printf("Read log file index error.\r\n"); 600 printf("Read log file index error.\r\n");
602 } 601 }
@@ -605,27 +604,27 @@ static T_ZiyanReturnCode ZiyanUser_LocalWriteFsInit(const char *path) @@ -605,27 +604,27 @@ static T_ZiyanReturnCode ZiyanUser_LocalWriteFsInit(const char *path)
605 currentLogFileIndex = logFileIndex; 604 currentLogFileIndex = logFileIndex;
606 logFileIndex++; 605 logFileIndex++;
607 606
608 - ret = fseek(s_djiLogFileCnt, 0, SEEK_SET); 607 + ret = fseek(s_ziyanLogFileCnt, 0, SEEK_SET);
609 if (ret != 0) { 608 if (ret != 0) {
610 printf("Seek log file error, ret: %d, errno: %d.\r\n", ret, errno); 609 printf("Seek log file error, ret: %d, errno: %d.\r\n", ret, errno);
611 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR; 610 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
612 } 611 }
613 612
614 - ret = fwrite((uint16_t *) &logFileIndex, 1, sizeof(uint16_t), s_djiLogFileCnt); 613 + ret = fwrite((uint16_t *) &logFileIndex, 1, sizeof(uint16_t), s_ziyanLogFileCnt);
615 if (ret != sizeof(uint16_t)) { 614 if (ret != sizeof(uint16_t)) {
616 printf("Write log file index error.\r\n"); 615 printf("Write log file index error.\r\n");
617 - fclose(s_djiLogFileCnt); 616 + fclose(s_ziyanLogFileCnt);
618 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR; 617 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
619 } 618 }
620 619
621 - fclose(s_djiLogFileCnt); 620 + fclose(s_ziyanLogFileCnt);
622 621
623 sprintf(filePath, "%s_%04d_%04d%02d%02d_%02d-%02d-%02d.log", path, currentLogFileIndex, 622 sprintf(filePath, "%s_%04d_%04d%02d%02d_%02d-%02d-%02d.log", path, currentLogFileIndex,
624 localTime->tm_year + 1900, localTime->tm_mon + 1, localTime->tm_mday, 623 localTime->tm_year + 1900, localTime->tm_mon + 1, localTime->tm_mday,
625 localTime->tm_hour, localTime->tm_min, localTime->tm_sec); 624 localTime->tm_hour, localTime->tm_min, localTime->tm_sec);
626 625
627 - s_djiLogFile = fopen(filePath, "wb+");  
628 - if (s_djiLogFile == NULL) { 626 + s_ziyanLogFile = fopen(filePath, "wb+");
  627 + if (s_ziyanLogFile == NULL) {
629 USER_LOG_ERROR("Open filepath time error."); 628 USER_LOG_ERROR("Open filepath time error.");
630 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR; 629 return ZIYAN_ERROR_SYSTEM_MODULE_CODE_SYSTEM_ERROR;
631 } 630 }
@@ -639,7 +638,7 @@ static T_ZiyanReturnCode ZiyanUser_LocalWriteFsInit(const char *path) @@ -639,7 +638,7 @@ static T_ZiyanReturnCode ZiyanUser_LocalWriteFsInit(const char *path)
639 } 638 }
640 } 639 }
641 640
642 - return djiReturnCode; 641 + return ziyanReturnCode;
643 } 642 }
644 643
645 // #pragma GCC diagnostic push 644 // #pragma GCC diagnostic push