当前位置:网站首页>[Fuhan 6630 encodes and stores videos, and uses RTSP server and timestamp synchronization to realize VLC viewing videos]
[Fuhan 6630 encodes and stores videos, and uses RTSP server and timestamp synchronization to realize VLC viewing videos]
2022-07-03 02:46:00 【I&You】
Fuhan 6630 Encode and store video , use rtsp Server and timestamp synchronization vlc Watch the video
- Code logic mainly talks about several important functions
- Encoding threads _thread_venc_data( Save to the video file by frame )
- _dvr_handle_video_frame( Save to the video file by frame )
- read_stream( After the video file is saved )(vlc use url Request playback to start reading video file thread )
- write_stream( Add frame data to rtsp In line )
- RTSP Server logic has been mentioned in previous articles for reference
- Complete code download
Code logic mainly talks about several important functions
Encoding threads _thread_venc_data( Save to the video file by frame )
if(stStream.u32PackCount > 0)
{
s32Ret = FY_MPI_VENC_GetStream(i, &stStream, FY_TRUE);// Get a frame
}
if (FY_SUCCESS != s32Ret)
{
continue;
}
else
{
#if 1
if(i==4){
int len=0,off=0;
memset(&stVideoData, 0, sizeof(stVideoData));
stVideoData.buffer = malloc(200*1024);
// Unpack , Get valid stream data
for (k = 0; k < stStream.u32PackCount; k++)
{
len+=stStream.pstPack[k].u32Len-stStream.pstPack[k].u32Offset;
}
for (k = 0; k < stStream.u32PackCount; k++)
{
memcpy(stVideoData.buffer+off,stStream.pstPack[k].pu8Addr+stStream.pstPack[k].u32Offset,stStream.pstPack[k].u32Len-stStream.pstPack[k].u32Offset);
off+=stStream.pstPack[k].u32Len-stStream.pstPack[k].u32Offset;
}
stVideoData.len =len;
stVideoData.frametype = LXR_FRAME_TYPE_UNKNOWN; // It's useless
stVideoData.timestamp = stStream.pstPack[0].u64PTS*1000; // It's useless , The upper layer gets the assignment again
if(i < s32ChnTotal/2)
streamID = 0; //main stream
else
streamID = 1; //sub stream
conn = i%(s32ChnTotal/2); //conn, Channel number
_dvr_handle_video_frame(conn,streamID,&stVideoData, LXR_VIDEO_TYPE_H264);
}
_dvr_handle_video_frame( Save to the video file by frame )
void _dvr_handle_video_frame(int ch, int streamid, LXRFrame_t* m_frame, LXR_VIDEO_TYPE_E encType)
{
LXRFrame_t frame;
memcpy(&frame, m_frame, sizeof(LXRFrame_t));
// Analytic width and height
//JBOOL bIFrame = JFALSE; // whether I frame
FY_BOOL bNeedCmpareWH = FY_FALSE; // It needs to be wide and high
int frameW = 0, frameH = 0;
LXR_VIDEO_TYPE_E vencType = LXR_VIDEO_TYPE_H264;
unsigned long long timeStap =arch_getSystemStartupMs(); // Must be time stamped , Otherwise, it cannot be played back
frame.timestamp = timeStap;
if(encType == LXR_VIDEO_TYPE_H264)
{
vencType = LXR_VIDEO_TYPE_H264;
unsigned int NaluType = frame.buffer[4]&0x1f;
if((NaluType == 7) || (NaluType == 8) || (NaluType == 5))// Judge whether it is i frame
{
//bIFrame = JTRUE;
frame.frametype = LXR_FRAME_TYPE_I;
}
if(NaluType == 7)
{
// Test execution time .(3535)
// belt __compare_sps: 2us
// No : 7us
//struct timeval tmBegin,tmNow;
//gettimeofday(&tmBegin, 0);
// Check sps Do you need to parse
// analysis sps
#if 0
sps_data_t sps;
h264_parse_sps(frame.buffer+5, frame.len-5, &sps);
frameW = sps.width;
frameH = sps.height;
bNeedCmpareWH = FY_TRUE;
#endif
}
}
static FILE * fp=NULL;
static unsigned char first_iframe = 0;
if(fp==NULL){
fp = fopen("/mnt/h264_stream/lxr_test_record5.h264", "w");
}
if(fp == NULL){
perror("open_recordfile_fail");
}
if(!first_iframe&&frame.frametype==LXR_FRAME_TYPE_I){
first_iframe =1;
}
if(first_iframe){
// The first frame needs to be saved with keys , otherwise vlc It won't play
unsigned char sendBuf[200*1024];
unsigned char *p = (unsigned char*)sendBuf;
int size1,size2,size3,ret;
StramFrame_t grpc_frame={
0};// The frame structure saved to the video file
// assignment
grpc_frame.buffer=frame.buffer;
grpc_frame.ch=ch;
grpc_frame.frametype = frame.frametype;
grpc_frame.len=frame.len;
grpc_frame.stream_id = streamid;
grpc_frame.timestamp = frame.timestamp;
// Copy the data
size1 = sizeof(StramFrame_t);
size2 = grpc_frame.len;
size3 = size1+size2;
*((unsigned int*)p) = size1 + size2 ;
memcpy(p+sizeof(unsigned int), &grpc_frame, size1);
memcpy(p+sizeof(unsigned int)+size1, grpc_frame.buffer, size2);
if(size3>61440){
// Write once 60k, Write several times , You can define a write by yourself 64k Can also be
int i=0;
while(size3>61440){
ret =fwrite(p+i,61440,1,fp);
i+=61440;
size3-=61440;
}
ret =fwrite(p+i,size3,1,fp);
}else{
ret =fwrite(p,sizeof(unsigned int)+size1+size2,1,fp);
}
}
free(frame.buffer);
}
read_stream( After the video file is saved )(vlc use url Request playback to start reading video file thread )
void read_stream(void *arg){
int fd=0,ret;
unsigned char recBuf_init[200*1024];
unsigned char * recBuf=(unsigned char *)recBuf_init;
if(fd==0){
fd = open("/mnt/h264_stream/lxr_test_record5.h264", O_RDONLY);
}
if(fd <0 ){
perror("open_recordfile_fail");
}
while(1)
{
ret = read(fd,recBuf,61440);
if(ret==0){
// Leave after reading
return;
}
unsigned int lenTotal = *((unsigned int*)recBuf)+PACKET_HEAD;
if(ret>lenTotal){
// get entangled with sb.
unsigned int readlen=lenTotal,total=ret;
// Write data
write_stream(recBuf,lenTotal,fd);
unsigned char * recBuf_offset = recBuf;
while (readlen<ret)// Judge whether the unpacking is completed
{
// Offset to the first address of the next packet
recBuf_offset+=lenTotal;
lenTotal = *((unsigned int*)recBuf_offset)+PACKET_HEAD;
// Judge whether it is I Frame subcontracting
if(i_frame_flag(recBuf_offset)){
unsigned int iframe_read=ret-readlen;
while (iframe_read<lenTotal)// Note the package does not contain complete I The frame needs to get the packet
{
ret = read(fd,recBuf_offset+iframe_read,lenTotal-iframe_read);
iframe_read+=ret;
}
write_stream(recBuf_offset,lenTotal,fd);
readlen+=lenTotal;
}else{
//P Packet frame
if((readlen+lenTotal)>ret){
int tmps=lenTotal-(ret-readlen);// Used to store temporary variables
ret = read(fd,recBuf_offset+ret-readlen,tmps);
readlen = tmps;
write_stream(recBuf_offset,lenTotal,fd);
}else{
write_stream(recBuf_offset,lenTotal,fd);
readlen+=lenTotal;
}
}
}
}
else if(i_frame_flag(recBuf)){
// Judge whether it is i Packet frame
unsigned int iframe_read=ret;
while(iframe_read<lenTotal){
//I Frame subcontracting sending
ret = read(fd,recBuf+iframe_read,61440);
iframe_read+=ret;
}
if(lenTotal!=iframe_read){
// Sticky package appears
unsigned int not_readlen = iframe_read-lenTotal;
unsigned int readlen=0;
unsigned char * recBuf_offset=recBuf;
write_stream(recBuf,lenTotal,fd);// First complete I Frame write
while (not_readlen!=readlen)
{
// Offset to next P The first address of the frame
recBuf_offset+=lenTotal;
lenTotal = *((unsigned int*)recBuf_offset)+4;
write_stream(recBuf_offset,lenTotal,fd);
readlen+=lenTotal;
}
}else if(lenTotal==iframe_read){
// Single bag i frame
write_stream(recBuf,lenTotal,fd);
}
}else{
//P Packet frame
write_stream(recBuf,lenTotal,fd);
}
}
}
write_stream( Add frame data to rtsp In line )
void write_stream(unsigned char *recBuf,unsigned int lenTotal,int fd){
// Remove the head
unsigned char *head=(unsigned char *)recBuf+4;
StramFrame_t * recFrm=(StramFrame_t *)head;
if(recFrm)
{
recFrm->buffer = (unsigned char*)recFrm + sizeof(StramFrame_t);
if(lenTotal-4 != recFrm->len + sizeof(StramFrame_t))
{
printf("bad length:chn=%d,lenTotal=%d,frmLen=%d\n", recFrm->ch, lenTotal, recFrm->len);
}
}
// Compare timestamps
FY_BOOL bSendPlay = FY_FALSE; // Do you want to play
static RemoteSync_t syncFrame={
0};
static unsigned char first_comehere=1;
if(first_comehere)
{
first_comehere = 0;
// Synchronization has not been established . Be sure to play
bSendPlay = FY_TRUE;
syncFrame.iFrame = recFrm->frametype;
syncFrame.tsFrame = recFrm->timestamp;
syncFrame.tsPlay = arch_getSystemStartupMs();
//player->tsCurPlay = player->syncFrame.tsPlay;
}
else
{
// Synchronization has been established
// The playback time difference is greater than Frame time difference Just play
unsigned long long tsNow;
do
{
tsNow = arch_getSystemStartupMs();
} while ((tsNow - syncFrame.tsPlay)*1 < recFrm->timestamp - syncFrame.tsFrame);
bSendPlay = FY_TRUE;
}
if(n_1<NMAX&&bSendPlay==FY_TRUE)
{
memcpy(ringfifo_1[iput_1].buffer,recFrm->buffer,recFrm->len);
ringfifo_1[iput_1].size= recFrm->len;
if(recFrm->frametype==LXR_FRAME_TYPE_I)
{
ringfifo_1[iput_1].frame_type = FRAME_TYPE_I;
}
else
ringfifo_1[iput_1].frame_type = FRAME_TYPE_P;
iput_1 = addring(iput_1);
n_1++;
}
}
RTSP Server logic has been mentioned in previous articles for reference
Complete code download
边栏推荐
- 超好用的日志库 logzero
- 疫情当头,作为Leader如何进行代码版本和需求开发管控?| 社区征文
- GBase 8c系统表-pg_constraint
- [tutorial] chrome turns off cross domain policies CORS and samesite, and brings cookies across domains
- HW-初始准备
- Gbase 8C trigger (III)
- Add some hard dishes to the interview: how to improve throughput and timeliness in delayed task scenarios!
- Three.js本地环境搭建
- random shuffle注意
- [shutter] banner carousel component (shutter_wiper plug-in | swiper component)
猜你喜欢

C语言初阶-指针详解-庖丁解牛篇
![ASP. Net core 6 framework unveiling example demonstration [02]: application development based on routing, MVC and grpc](/img/cb/145937a27ef08050a370d5a255215a.jpg)
ASP. Net core 6 framework unveiling example demonstration [02]: application development based on routing, MVC and grpc

Deep Reinforcement Learning for Intelligent Transportation Systems: A Survey 论文阅读笔记
![[shutter] setup of shutter development environment (supplement the latest information | the latest installation tutorial on August 25, 2021)](/img/65/c1fe95f8c391394f7ff1b75c7d75b6.jpg)
[shutter] setup of shutter development environment (supplement the latest information | the latest installation tutorial on August 25, 2021)

基于can总线的A2L文件解析(2)

Super easy to use logzero

Sqlserver row to column pivot
![[fluent] JSON model conversion (JSON serialization tool | JSON manual serialization | writing dart model classes according to JSON | online automatic conversion of dart classes according to JSON)](/img/6a/ae44ddb090ce6373f04a550a15f973.jpg)
[fluent] JSON model conversion (JSON serialization tool | JSON manual serialization | writing dart model classes according to JSON | online automatic conversion of dart classes according to JSON)

从C到Capable-----利用指针作为函数参数求字符串是否为回文字符
![[hcia]no.15 communication between VLANs](/img/59/a467c5920cbccb72040f39f719d701.jpg)
[hcia]no.15 communication between VLANs
随机推荐
HTB-Devel
【翻译】后台项目加入了CNCF孵化器
[advanced ROS] Lesson 6 recording and playback in ROS (rosbag)
《MATLAB 神经网络43个案例分析》:第43章 神经网络高效编程技巧——基于MATLAB R2012b新版本特性的探讨
A2L file parsing based on CAN bus (2)
Process the dataset and use labelencoder to convert all IDs to start from 0
Gbase 8C system table PG_ attribute
SQL server queries the table structure of the specified table
GBase 8c系统表pg_cast
Counter统计数量后,如何返回有序的key
GBase 8c 触发器(一)
Can netstat still play like this?
The Linux server needs to install the agent software EPS (agent) database
How to implement append in tensor
Basic operation of binary tree (C language version)
Gbase 8C system table PG_ amop
Deep Reinforcement Learning for Intelligent Transportation Systems: A Survey 论文阅读笔记
Concrete CMS vulnerability
Summary of interview project technology stack
Strategy application of Dameng database