/*
* tuya_ring_buffer.h
*
* Created on: Feb 8, 2023
* Author: hi
*/
#ifndef TUYA_RING_BUFFER_H_
#define TUYA_RING_BUFFER_H_
typedef void (*FUNC_REQUEST_I_FRAME)(int channel);
typedef enum
{
E_CHANNEL_VIDEO_MAIN = 0,
E_CHANNEL_VIDEO_SUB,
E_CHANNEL_VIDEO_3RD,
E_CHANNEL_VIDEO_4TH,
E_CHANNEL_VIDEO_MAX = 8, //max video streams
E_CHANNEL_AUDIO,
E_CHANNEL_AUDIO_2RD,
E_CHANNEL_AUDIO_3RD,
E_CHANNEL_AUDIO_4TH,
E_CHANNEL_MAX = 16
}CHANNEL_E;
typedef enum
{
E_VIDEO_PB_FRAME = 0,
E_VIDEO_I_FRAME,
E_VIDEO_TS_FRAME,
E_AUDIO_FRAME,
E_CMD_FRAME,
E_VIDEO_KEY_FRAME,
E_MEDIA_FRAME_TYPE_MAX
}MEDIA_FRAME_TYPE_E;
typedef enum
{
E_USER_STREAM_STORAGE = 0,
E_USER_COULD_STORAGE = 1,
E_USER_ECHO_SHOW = 2,
E_USER_CHROMECAST = 3,
E_USER_DOORBELL = 4,
E_USER_P2P_USER = 5, //for multi P2P user, can be in format E_USER_P2P_USER+p2p_index
E_USER_RTSP = 10,
E_USER_TSTREAMER = 15,
E_USER_NUM_MAX = 16
}USER_INDEX_E;
typedef enum
{
E_SEND_READY_TO_START = 0,
E_SEND_NORMAL = 1,
E_SEND_PARTIAL = 2,
E_SEND_DELAY_TOO_MUCH = 3,
E_SEND_SYNC = 4,
E_KEY_FRAME_DELAY_RETRY = 5,
E_SEND_INVALID = 6
}Buffer_User_Status_E;
typedef struct
{
unsigned int index;
MEDIA_FRAME_TYPE_E type;
unsigned char *rawData;
unsigned int size;
unsigned long long int pts;
unsigned long long int timestamp;
unsigned int seqNo;
unsigned char *extraData;
unsigned int extraSize;
unsigned int syncSeq;
}Ring_Buffer_Node_S;
typedef struct
{
unsigned int nodeIndex;
unsigned int seqNo;
Buffer_User_Status_E status;
unsigned int dataOffset;
}Ring_Buffer_User_S;
typedef struct
{
unsigned char *addr;
unsigned int size;
unsigned int tailOffset;
}Buffer_Pool_S;
typedef struct
{
unsigned int isvalid;
Ring_Buffer_Node_S key_frame_node;
}KEY_FRAME_INFO_T;
typedef struct
{
unsigned int inited;
Ring_Buffer_Node_S *node;
unsigned int nodeNum;
unsigned int fps;
unsigned int bitrate;
unsigned int headIndex;
unsigned int latestIframeIndex;
unsigned int seqNo;
unsigned int maxBufferSec;
unsigned int maxFrameSize;
Buffer_Pool_S bufferPool;
FUNC_REQUEST_I_FRAME requestIframeCB;
Ring_Buffer_User_S user[E_USER_NUM_MAX];
unsigned int userIndex;
}Ring_Buffer_S;
int tuya_ipc_ring_buffer_init(CHANNEL_E channel, unsigned int bitrate, unsigned int fps, unsigned int max_buffer_seconds, FUNC_REQUEST_I_FRAME requestIframeCB);
/* append new frame into a ring buffer
*/
int tuya_ipc_ring_buffer_append_data(CHANNEL_E channel, unsigned char *addr, unsigned int size, MEDIA_FRAME_TYPE_E type, unsigned long long int pts);
int tuya_ipc_ring_buffer_append_data_with_timestamp(CHANNEL_E channel, unsigned char *addr, unsigned int size, MEDIA_FRAME_TYPE_E type, unsigned long long int pts, unsigned long long int timestamp);
/* get video/audio frame from ring buffer.
different user of the same stream channel can be independently mantain status with different userIndex,
and automaticlly get the next frame in the buffer if it's invoked continuously.
NULL will return if no more new frame exist inside ringbuffer.
API will jump to the newest I frame or audio frame is this GET is delayed too much time.
*/
Ring_Buffer_Node_S *tuya_ipc_ring_buffer_get_video_frame(CHANNEL_E channel, USER_INDEX_E userIndex, int isRetry);
Ring_Buffer_Node_S *tuya_ipc_ring_buffer_get_audio_frame(CHANNEL_E channel, USER_INDEX_E userIndex, int isRetry);
/* get video/audio frame from ring buffer.
the return node maybe video or audio, which can be recognized by type element
*/
Ring_Buffer_Node_S *tuya_ipc_ring_buffer_get_av_frame(CHANNEL_E v_channel, CHANNEL_E a_channel, USER_INDEX_E userIndex, int isRetry);
/* start with the newest frame, find previous frame by count frameNum.
for video stream(channel), it will keep find previous frame until it's I frame.
*/
Ring_Buffer_Node_S *tuya_ipc_ring_buffer_find_pre_video_by_frame(CHANNEL_E channel, unsigned int frameNum);
Ring_Buffer_Node_S *tuya_ipc_ring_buffer_find_pre_audio_by_frame(CHANNEL_E channel, unsigned int frameNum);
/* start with the newest frame, find previous frame by count frameNum, and update&anchor user(of userIndex) to this frame node.
for video stream(channel), it will keep find previous frame until it's I frame.
*/
Ring_Buffer_Node_S *tuya_ipc_ring_buffer_get_pre_video_frame(CHANNEL_E channel, USER_INDEX_E userIndex, unsigned int frameNum);
Ring_Buffer_Node_S *tuya_ipc_ring_buffer_get_pre_audio_frame(CHANNEL_E channel, USER_INDEX_E userIndex, unsigned int frameNum);
/* anchor user of userIndex to specified node.
normally this API is called after tuya_ipc_ring_buffer_find_pre_video_by_frame
*/
void tuya_ipc_ring_buffer_anchor_user_to_node(CHANNEL_E channel, USER_INDEX_E userIndex, Ring_Buffer_Node_S *node);
/* start from current frame node of user of userIndex, get the next target frame with right type, and it's sequence number is greater than or equal to seqNo
*/
Ring_Buffer_Node_S *tuya_ipc_ring_buffer_get_next_target_frame(CHANNEL_E channel, USER_INDEX_E userIndex, unsigned int seqNo, MEDIA_FRAME_TYPE_E type);
/* clean the state of user of userIndex, which means for next time tuya_ipc_ring_buffer_get_video_frame will start from the newest frame node
*/
void tuya_ipc_ring_buffer_clean_user_state(CHANNEL_E channel, USER_INDEX_E userIndex);
/* check if ring buffer user is delayed too much
*/
int tuya_ipc_ring_buffer_if_delay(CHANNEL_E channel, USER_INDEX_E userIndex);
/*
get ring buffer max buf seconds
*/
int tuya_ipc_ring_buffer_get_max_buf_secs();
/* set max frame size of channel
*/
int tuya_ipc_ring_buffer_set_max_frame_size(CHANNEL_E channel, unsigned int maxFrameSize);
/* get max frame size, return main stream size
*/
int tuya_ipc_ring_buffer_get_max_frame_size();
/*
set pre-record frame position, and then just get frame
must confirm return OPRT_OK
*/
int tuya_ipc_ring_buffer_anchor_user(CHANNEL_E channel,USER_INDEX_E userIndex, unsigned int frameNum, int checkOverlap);
/* clean the state of user of userIndex and data buffer, which means tuya_ipc_ring_buffer_get_pre_video_frame cann't get data earlier than the time this func called,
for next time tuya_ipc_ring_buffer_get_video_frame will start from the newest frame node
*/
void tuya_ipc_ring_buffer_clean_user_state_and_buffer(CHANNEL_E channel, USER_INDEX_E userIndex);
#endif /* TUYA_RING_BUFFER_H_ */