更新时间:2024-08-14 09:07:42下载pdf
本地存储是智能摄像机 IPC 的基础功能。该功能负责管理 SD 卡,将音视频和图片等数据按特定目录和文件结构存储到 SD 卡上的通用文件系统,并支持数据的检索、回放、下载、删除等操作。
本地存储提供将实时流视频存储到本地 SD 卡的能力,可设置 事件录制模式 或 全时段录像模式。SD 卡储存空间达到上限后,采用循环覆盖的写入模式,并提供按时间索引的视频回放接口。
开发框架
IPC
开发框架的通用功能。
关联组件
svc_local_storage
SD 卡管理包括热插拔监测、格式化、状态维护等。为保证足够读写性能,建议选用主流品牌、class10 以上的 SD 卡。
热插拔监测:
SD 卡状态:包含卡不存在、卡正常工作、卡异常。
卡异常的主要导致原因有无文件系统、文件系统不支持、文件系统损坏、坏卡等。
SD 卡格式化:由用户在手机 App 上触发,会清空卡数据、使卡处于正常工作的状态。SD 卡格式化的流程图如下:
IPC 本地存储,采用通用文件系统,以私有格式文件存储音视频和索引、JPG 格式存储图片,按多级目录、特定文件名组织文件以加速检索。
目录分为录像、本地相册 2 大类,业务上彼此独立。具体如下:
DCIM // 涂鸦存储目录,位于 SD 卡的文件系统的顶层目录
├── CHAN0 // 单通道 IPC 或多通道 IPC 的第一个通道的录像存储目录
│ └── 2022
│ └── 10
│ └── 14
│ ├── 1665732067_0014 // 事件文件夹,记录 utc 时间开始的录像,时长 14 秒
│ │ ├── 0000.media // 音视频文件,采用涂鸦私有格式,从第 0 秒开始
│ │ ├── 0010.media // 从第 10 秒
│ │ ├── 1665732067.jpg // 事件封面图
│ │ └── .info // 录像括视频格式、事件类型
│ └── day_idx.bin // .info 文件的索引
├── CHAN1
│ ... //多通道 IPC 的第二个通道的录像存储目录,内部结构同
录像模式有 3 种:
不录像(任何时候不录像)
连续录像(7*24 小时持续录像)
事件录像(仅在有事件发生时录像,支持预录)
预录,是指事件发生前 N 秒的视频,也能存到 SD 卡。N 最大值受限于 ringBuff
时长,例如 ringBuff
有 10 秒,N 最大可为 9 秒。
循环覆盖,存储空间不足 500MB 时,程序自动删除时间最老的录像,为新录像留出存储空间。每次仅删除一个事件文件夹。
读取 SD 卡中的音视频数据,按照一定速率、有选择地传输给客户端做显示。
读取 SD 卡中的音视频数据,尽量快地传给 App 等客户端。
按天删除,由用户在 App 上触发,删除某一天的录像。
typedef struct {
CHAR_T base_path[SS_BASE_PATH_LEN]; /* 视频存储的根路径 */
UINT_T max_event_per_day; /* 每天的最大事件数,此限制应基于 Soc 能力,查询并在可接受的时间内返回播放信息 */
/* 如果事件数超过此限制,将拒绝查询消息 */
SS_SD_STATUS_CHANGED_CB sd_status_changed_cb; /* SD 卡状态变化通知回调 */
UINT_T skills; /* 0 表示支持所有能力,参考 TUYA_IPC_SKILL_BASIC | TUYA_IPC_SKILL_DOWNLOAD */
TUYA_IPC_ALBUM_INFO_T album_info; /* 相册信息 */
} TUYA_IPC_STORAGE_VAR_T;
SD 状态回调通知。
typedef OPERATE_RET (*SS_SD_STATUS_CHANGED_CB)(SD_STATUS_E status);
参数说明
typedef enum {
SD_STATUS_UNKNOWN = 0,
SD_STATUS_NORMAL,
SD_STATUS_ABNORMAL,
SD_STATUS_LACK_SPACE,
SD_STATUS_FORMATING,
SD_STATUS_NOT_EXIST,
SD_STATUS_MAX
} SD_STATUS_E;
初始化存储通道,该操作会执行缓存空间的创建和初始化,初始化成功会返回 OPRT_OK
。
/**
* @brief 初始化本地存储
*
* @param[in] p_storage_var: pointer
*
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*/
OPERATE_RET tuya_ipc_ss_init(IN TUYA_IPC_STORAGE_VAR_T *p_storage_var);
执行反初始化,释放缓存资源。
/**
* @brief uninit tuya stream storage, free used resource, memory e.g.
*
* @param VOID
*
* @return VOID
*/
VOID tuya_ipc_ss_uninit(VOID);
/**
* @brief if stream storage is inited
*
* @param VOID
*
* @return TRUE/FALSE
*/
BOOL_T tuya_ipc_ss_is_inited(VOID);
/**
* @brief set wtote mode of stream storage
*
* @param[in] write_mode
*
* @return OPERATE_RET
*/
OPERATE_RET tuya_ipc_ss_set_write_mode(IN CONST STREAM_STORAGE_WRITE_MODE_E write_mode);
/**
* @brief get current stream storage write mode
*
* @param VOID
*
* @return STREAM_STORAGE_WRITE_MODE_E
*/
STREAM_STORAGE_WRITE_MODE_E tuya_ipc_ss_get_write_mode(VOID);
/**
* @brief if stream storage write mode is enabled
*
* @param VOID
*
* @return TRUE/FALSE
*/
BOOL_T tuya_ipc_ss_write_mode_is_enabled(VOID);
/**
* @brief start event stream storage by channel
*
* @param[in] channel: which channel, 0 for ipc
*
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*/
OPERATE_RET tuya_ipc_ss_start_event(IN INT_T channel);
/**
* @brief stop event stream storage by channel
*
* @param[in] channel: which channel, 0 for ipc
*
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*/
OPERATE_RET tuya_ipc_ss_stop_event(IN INT_T channel);
/**
* @brief set pre-record time, invoke this API only if needed, or it is 2 seconds by default.
* Should be invoked once after init and before start.
*
* @param[in] pre_record_second: time in second
*
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*/
OPERATE_RET tuya_ipc_ss_set_pre_record_time(IN UINT_T pre_record_second);
/**
* @brief set max event duration, invoke this API only if needed, or it is 600 seconds by default.
* Should be invoked onece after init and before start.
*
* @param[in] max_event_duration: time in second
*
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*/
OPERATE_RET tuya_ipc_ss_set_max_event_duration(IN UINT_T max_event_duration);
该接口在 MEDIA_STREAM_PLAYBACK_START_TS
P2P 事件上启用,详细请参考 Demo 应用。
/**
* @brief start a new playback
*
* @param[in] pb_idx: playback/query index, for different client do query in the same time
* @param[in] event_cb: callback function of playback event
* @param[in] video_cb: callback function of getting playback video data
* @param[in] audio_cb: callback function of getting playback audio data
*
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*/
OPERATE_RET tuya_ipc_ss_pb_start(IN UINT_T pb_idx, IN SS_PB_EVENT_CB event_cb, IN SS_PB_GET_MEDIA_CB video_cb, IN SS_PB_GET_MEDIA_CB audio_cb);
回调参数
typedef VOID (*SS_PB_EVENT_CB)(IN UINT_T pb_idx, IN SS_PB_EVENT_E pb_event, IN PVOID_T args);
回放事件回调
typedef VOID (*SS_PB_GET_MEDIA_CB)(IN UINT_T pb_idx, IN CONST MEDIA_FRAME_T *p_frame);
音视频接收回调参数
参数 | 说明 |
---|---|
pb_idx |
回放和查询索引,针对不同的客户端在同一时间进行查询 |
event_cb |
回放事件回调 |
video_cb |
视频数据回调 |
audio_cb |
音频数据回调 |
停止指定通道的回放。
/**
* @brief stop an ongoing playback
*
* @param[in] pb_idx: playback/query index, for different client do query in the same time
*
* @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
*/
OPERATE_RET tuya_ipc_ss_pb_stop(IN UINT_T pb_idx);
在首次识别到正常的 SD 卡后,会申请录像缓存内存,在本存模组反初始化时释放。
内存大小:N 秒 *(1 秒视频主码流大小+1 秒音频主码流大小),N 为可配置,默认为 6。
对于多通道录像,每通道各一份内存。
音视频文件采用涂鸦私有格式存储音视频数据,以 .media
作为后缀,后续版本会新增对 MP4 格式的支持。
涂鸦提供了标准化的存储实现,如果开发者需要有自定义的存储逻辑,如不同的目录结构、不同的文件大小和格式、不同的文件读写方案等,可以选择不启用该模块,使用自有的存储方案程序。但是需要按照标准协议对接录像回放、下载等功能。
事件产生时调用 tuya_ipc_ss_start_event
后,不能立即调用 tuya_ipc_ss_stop_event
。
调用 tuya_ipc_ss_start_event
时,如果本地初始化未完成,内部会缓存事件标记,然后等初始化完成后,根据事件标记再开始录像。但是,如果在此期间调用了 tuya_ipc_ss_stop_event
, 标记会被清除,最终事件录像将不会产生。
调用 tuya_ipc_ss_start_event
或 tuya_ipc_ss_set_write_mode
后日志中出现 not init
报错,说明存储模块的目录初始化还没有完成。
此现象和上层 SD_STATUS_E tuya_ipc_sd_get_status(VOID)
的实现有关。SDK 内部会调用 tuya_ipc_sd_get_status
,在返回 SD_STATUS_NORMAL
后,存储目录初始化才能完成。
该内容对您有帮助吗?
是意见反馈该内容对您有帮助吗?
是意见反馈