音视频ringbuffer

该文件定义了一个TuyaRingBuffer的数据结构和一系列函数,用于处理视频和音频帧的存储、获取以及用户状态管理。RingBuffer支持多个用户独立的状态,并能处理不同类型的帧(如I帧、P帧),同时提供了检查延迟和设置最大缓冲时间的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*

* 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_ */

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值