Local Storage

Last Updated on : 2024-12-05 09:25:52download

Local storage, a basic feature of an IP camera (IPC), manages the SD card. It stores audio, videos, and images to the SD card in the specified directory and file structure, supporting video search, playback, download, and deletion.

Feature description

Local storage can record live streams to the SD card, allowing for event recording or continuous recording. When the local storage is full, new videos will overwrite the oldest ones. Playback by time allows search for recordings by time.

Development guide

Runtime environment

  • Development framework

    The general features provided by the IPC Development Framework

  • Components

    svc_local_storage

SD card management

Hot swap detection, formatting, and status updates are available. To ensure excellent read/write performance, it is recommended to select a Class 10 SD card from reputable brands.

  • Hot swap detection:

    • Identify and mount the file system for data read/write when an SD card is inserted.
    • Stop recording and playback and unmount the file system when an SD card is removed.
  • SD card status: not detected, normal, and anomaly.

    An anomaly can be caused by no file system, incompatible file system, and file system or SD card damage.

  • SD card formatting: The user initiates formatting on the mobile app to erase the SD card for normal usage. How SD card formatting works:

    DPSDKSD cardSD Cardpb_stop_all, set mode none toSDKFormattingGet status errorStop writingGet status errorGet status error periodicallyFormatting is completed, making the SD card status normalGet normal statusWhen status is normal, the SDK will get mode from cfgStart writingDPSDKSD cardSD Card

Directory and file structure

The local storage uses a general file system to store audio, video, and index in a proprietary format and images in JPG format. Files are organized with a multilevel directory and file naming convention for fast retrieval.

Directories are broken down into two independent categories: recordings and local albums, as shown below.

DCIM                                       // The storage directory, located in the top level directory in the SD card file system.
    ├── CHAN0                              // The recording storage directory of the first channel for 1-channel or multichannel IPCs.
    │   └── 2022
    │       └── 10
    │           └── 14
    │               ├── 1665732067_0014    // The event folder, containing 14-second footage in UTC.
    │               │   ├── 0000.media     // The audio and video file in Tuya's proprietary format, starting at 0 seconds.
    │               │   ├── 0010.media     // Start at 10 seconds.
    │               │   ├── 1665732067.jpg // The thumbnail of an event video.
    │               │   └── .info          // Information about the video format and event type.
    │               └── day_idx.bin        // The index of the .info file.
    ├── CHAN1
    │           ...                        // The recording storage directory of the second channel for multichannel IPCs, with the same structure as that of the first channel.

Recordings

Recording

  • There are three recording modes:

    • Not recording (at any time)

    • Continuous recording (24/7)

    • Event recording (Recording is triggered by events. Pre-recording is supported.)

      Pre-recording enables storing the footage N seconds before the event. The maximum value of N is limited by ringBuff. For example, if ringBuff is 10 seconds, the upper limit of N is 9 seconds.

  • When the available space on the SD card is less than 500 MB, the program will automatically delete the oldest recordings to make room for new recordings. Only one event folder is deleted at a time.

Search

  • Search by month: Check for the available footage in a month.
  • Search by timeline: Check for the available footage on a specified day.

Playback

Read audio and video from the SD card and selectively send the data to the client at a specific rate.

  • The user can control playback, adjust the speed, and jump to a specified position on the timeline.
  • Playback control supports start, pause, resume, and end.
  • Speed up or slow down the playback by 0.5x, 2x, 4x, or 8x.

Download

Read audio and video from the SD card and send the data to the client as fast as possible.

Delete

Delete the recording on a specific day after the user initiates the deletion on the mobile app.

Video format

Store in a proprietary format

When storage is enabled and continuous recording or event recording is selected, the audio and video streams are automatically recorded to the SD card in Tuya’s proprietary format by default. Therefore, the video files saved in the SD card cannot be opened and played by conventional players. Users can only view playback on the Tuya-enabled app, which meets security requirements.

Storage encryption

To meet higher security requirements, the stored data is encrypted based on the proprietary format. Invoke the specified API to turn the encryption feature on or off. After the encryption feature is turned on, the stream data will be encrypted and written to the SD card.
The encrypted video can only be played back on the device used when recording. If the SD card is inserted into other devices, the encrypted video cannot be played back properly. For example, the encrypted video recorded in device A cannot be played back properly in device B.

  • The encryption process will take up additional CPU and memory resources. The computing power of different chip platforms varies, so it is impossible to give a unified CPU usage. Before use, it is necessary to test and evaluate the specific impact.
  • The encryption key is managed by the cloud and needs to be obtained from the cloud. Therefore, encryption can only be run as expected after the devices are paired.
  • If the encryption key goes wrong, it will be replaced and the encrypted video recorded before the key replacement cannot be played back properly.

Data structure

Initial parameters

typedef struct {
    CHAR_T base_path[SS_BASE_PATH_LEN]; /* The root directory of video storage. */
    UINT_T max_event_per_day;           /* The maximum number of events per day, which is based on the SoC capabilities. Query and get the playback information within the acceptable time period. */
                                        /* If the upper limit is exceeded, a query message will be rejected.*/
    SS_SD_STATUS_CHANGED_CB sd_status_changed_cb; /* The callback invoked when SD card status changes. */
    UINT_T skills;                     /* 0 means all the capabilities are supported. See  TUYA_IPC_SKILL_BASIC | TUYA_IPC_SKILL_DOWNLOAD for details. */
    TUYA_IPC_ALBUM_INFO_T album_info;   /* Album information. */
} TUYA_IPC_STORAGE_VAR_T;

Callback parameters

SD card status callback.

typedef OPERATE_RET (*SS_SD_STATUS_CHANGED_CB)(SD_STATUS_E status);

Parameter description

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;

API description

Initialize the channel

Initialize the storage channel, which will create and initialize a buffer. OPRT_OK is returned on success.

/**
 * @brief  Initialize local storage
 *
 * @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);

Deallocate local storage

Perform deinitialization to free the buffer memory.

/**
 * @brief uninit tuya stream storage, free used resource, memory e.g.
 *
 * @param VOID
 *
 * @return VOID
 */
VOID tuya_ipc_ss_uninit(VOID);

Determine if local storage is started

/**
 * @brief if stream storage is inited
 *
 * @param VOID
 *
 * @return TRUE/FALSE
 */
BOOL_T tuya_ipc_ss_is_inited(VOID);

Set local storage mode

/**
 * @brief Set write 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);

Get local storage 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);

Determine if write mode of local storage is enabled

/**
 * @brief if stream storage write mode is enabled
 *
 * @param VOID
 *
 * @return TRUE/FALSE
 */
BOOL_T tuya_ipc_ss_write_mode_is_enabled(VOID);

Start recording storage by channel

/**
 * @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);

Stop recording storage by 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);

Set pre-record time

/**
 * @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 seconds.
 *
 * @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);

Set the maximum event duration

/**
 * @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 seconds
 *
 * @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);

Start playback

This API is invoked based on the MEDIA_STREAM_PLAYBACK_START_TS P2P event. For more information, see the demo application.

/**
 * @brief start a new playback
 *
 * @param[in] pb_idx: the playback and search index, used for simultaneous search from different clients
 * @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);

Callback parameters

typedef VOID (*SS_PB_EVENT_CB)(IN UINT_T pb_idx, IN SS_PB_EVENT_E pb_event, IN PVOID_T args);

Playback event callback

typedef VOID (*SS_PB_GET_MEDIA_CB)(IN UINT_T pb_idx, IN CONST MEDIA_FRAME_T *p_frame);

Callback parameters of audio and video receiving

Parameter Description
pb_idx The playback and search index, used for simultaneous search from different clients.
event_cb Playback event callback
video_cb Video data callback
audio_cb Audio data callback

Stop playback

Stop playback on the specified channel.

/**
 * @brief stop an ongoing playback
 *
 * @param[in] pb_idx: the playback and search index, used for simultaneous search from different clients
 *
 * @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);

Storage encryption

  • When tuya_ipc_ss_init is invoked to initialize local storage, set the encryption enable parameter.
  • Dynamically turn encryption on or off. After the mode is changed, the original recording process will be stopped and a new recording will be started.
/**
 * @brief set the encryption mode
 *
 * @param[in] encrypt_enable: turn encryption on or off
 *
 * @return OPRT_OK on success. Others on error, please refer to tuya_error_code.h
 */
OPERATE_RET tuya_ipc_ss_set_encrypt_mode(IN CONST BOOL_T encrypt_enable)

Things to note

  • Recordings reside in a multilevel directory that is organized in year, month, day, and event folders as well as audio and video files.
  • An audio or video file can be up to 10 seconds long.
  • An event folder contains multiple audio and video files that are continuous and can last up to 600 seconds in total.
  • In event recording mode, an event folder contains all the recordings that are specific to an event.
  • In continuous mode, recordings in an event folder can last up to 600 seconds in total.

FAQs

When should I allocate and deallocate memory? How much memory is required?

The recording buffer memory is allocated when a normal SD card is detected and deallocated when local storage is deinitialized.
Memory size: N seconds × (the size of 1-second main video stream + the size of 1-second main audio stream). N is configurable, defaulting to 6.
For multichannel recording, each channel is allocated a buffer.

What video format is compatible with SD card storage?

Audio and video data is stored in Tuya’s proprietary format, with the suffix .media. MP4 format will be supported in later releases.

Does the local storage module support custom formats and logic?

If you prefer a custom storage logic instead of the standard implementation, you can choose not to enable local storage. Instead, use your own storage program for the customized directory structure, file size and format, and read/write solution. When integrating video playback, downloads, and other features, you must still follow the standard protocol.

How can I fix frame skipping?

  • Check if the local time on the device remains consistent.
  • Check if the frame rate for audio and video is stable.
  • For low power products, the SD card mounting duration should fall within the pre-recording time.
  • The larger the capacity of the SD card, the longer it takes to create a folder for event recording after the first frame is captured. This can affect the continuity between the second and first frames, causing skipped frames.

Why is the device reporting an event without local video recording?

Do not call tuya_ipc_ss_stop_event immediately after tuya_ipc_ss_start_event is invoked when an event occurs.

When calling tuya_ipc_ss_start_event, if local initialization is not completed, the system will cache event flags and start recording based on these flags after initialization. However, if tuya_ipc_ss_stop_event is called during this period, the flag will be cleared, causing the event recording to fail.

Why does the local storage initialization fail?

After tuya_ipc_ss_start_event or tuya_ipc_ss_set_write_mode is called, a not init error appears in the log, indicating that the directory of the storage module has not been initialized.

This issue is mostly related to the implementation of the upper layer SD_STATUS_E tuya_ipc_sd_get_status(VOID). The SDK will call tuya_ipc_sd_get_status internally, and the storage directory initialization can only be completed after SD_STATUS_NORMAL is returned.

Why are there no download and delete buttons on the app’s playback interface?

You can enable the Download and Delete buttons on the playback interface only after uploading the specified capability flag through tuya_ipc_upload_skills. Each capability flag can be set one by one based on the input parameter skills of tuya_ipc_ss_init. You can find the value by searching for TUYA_IPC_SKILL_DOWNLOAD in tuya_ipc_stream_storage.h. Pay attention to the following points:

  • You need to perform tuya_ipc_ss_init before calling tuya_ipc_upload_skills. Otherwise, the stored capability flags cannot be uploaded.
  • You need to call tuya_ipc_upload_skills after connecting to the internet. Otherwise, the capability flags cannot be uploaded.

What are the considerations when I do not use the storage provided by the SDK?

Just do not call tuya_ipc_ss_init. If you want to enable features such as downloading and deleting playback, you need to upload the specified capability flags. Call tuya_ipc_skill_enable to set the capability flags individually, as shown below:

TUYA_IPC_SKILL_PARAM_U skill_param = { .value = TUYA_IPC_SKILL_BASIC | TUYA_IPC_SKILL_DOWNLOAD | TUYA_IPC_SKILL_DELETE_BY_DAY};
tuya_ipc_skill_enable(TUYA_IPC_SKILL_LOCALSTG, &skill_param);

How to implement playback for non-SDK storage?

If you have implemented features such as storage stream and need a playback feature, you can refer to the signaling processing flow in the demo. The following signaling is available for playback interaction:

  • Search by month: MEDIA_STREAM_PLAYBACK_QUERY_MONTH_SIMPLIFY. Refer to the demo for return values.
  • Search for a specific day: MEDIA_STREAM_PLAYBACK_QUERY_DAY_TS or MEDIA_STREAM_PLAYBACK_QUERY_DAY_TS_WITH_ENCRYPT. Refer to the demo for the types of return values.
  • Start playback: MEDIA_STREAM_PLAYBACK_START_TS. After receiving this signal, the device returns immediately and needs to locate the new playback time point and send audio and video files.
    • The sending operation needs to be executed in another thread. You need to implement thread creation, destruction, and resource management by yourself.
    • Send audio and video files frame by frame. For the playback sending interface, refer to the context of invoking tuya_ipc_media_playback_send_video_frame_with_encrypt and tuya_ipc_media_playback_send_audio_frame_with_encrypt in the demo.
    • You need to implement the playback time point feature and use it with the sending thread.
  • Pause the playback: MEDIA_STREAM_PLAYBACK_PAUSE
  • Resume the playback: MEDIA_STREAM_PLAYBACK_RESUME
  • Mute the playback: MEDIA_STREAM_PLAYBACK_MUTE
  • Unmute the playback: MEDIA_STREAM_PLAYBACK_UNMUTE
  • Set the playback speed: MEDIA_STREAM_PLAYBACK_SET_SPEED, used together with the sending thread. For playback speeds greater than 4 times, it is recommended to only send I-frames.
  • Stop the playback: MEDIA_STREAM_PLAYBACK_STOP
  • Start download: MEDIA_STREAM_DOWNLOAD_START
    • Refer to the signaling processing for starting playback and change the sending interface to tuya_imm_p2p_app_download_data.
    • After the download is sent, you need to call tuya_imm_p2p_app_download_status to set the sending completion tag.
    • Pay attention to download thread creation, destruction, and resource management.
  • Stop download: MEDIA_STREAM_DOWNLOAD_STOP
  • Pause download: MEDIA_STREAM_DOWNLOAD_PAUSE
  • Resume download: MEDIA_STREAM_DOWNLOAD_RESUME
  • Cancel download: MEDIA_STREAM_DOWNLOAD_CANCLE