当前位置:网站首页>Hisilicon hi3531 | Ruixin micro rk1109 realizes H264 streaming with RTSP client
Hisilicon hi3531 | Ruixin micro rk1109 realizes H264 streaming with RTSP client
2022-07-22 08:59:00 【I&You】
Hayes Hi3531|| Ruixin micro RK1109 use rtsp Client implementation h264 Pull flow
know RTP Baotou and h264 Of nalu head
Refer to the header of the server
know RTSP agreement
Reference server RTSP_state_machine Function pair RTSP Interpretation of the agreement
Client source code
Connect to server
send out RTSP agreement
/* MAXBUF use to receive message from stream server */
bzero(buffer, MAXBUF + 1);
/* send message to server */
Handel_OPTION(buffer);// Send to server RTSP Of option agreement
len = send(sockfd, buffer, strlen(buffer), 0);
if (len < 0)
printf("_____%d_____OPTION Reply Msg:\n %s send error! error code is %d, error content is %s \n", __LINE__,buffer, errno, strerror(errno));
else
printf("_____%d_____OPTION Reply Msg:\n %s send successfully,total content is %d bytes!\n", __LINE__, buffer, len);
bzero(buffer, MAXBUF + 1);
printf("____%d____\n",__LINE__);
/* receive message from server */
len = recv(sockfd, buffer, MAXBUF, 0); /* Confirm that the server replies OPTION Reply */
if (len < 0){
printf("_____%d_____OPTION Reply Msg:\n %s receive error! error code is %d, error content is %s \n", __LINE__, buffer, errno, strerror(errno));
}
else{
printf("_____%d_____OPTION Reply Msg:\n %s receive successfully,total content is %dbytes!\n", __LINE__,buffer, len);
}
if (memcmp(buffer, successfullyReplyStr, sizeof(successfullyReplyStr) -1) == 0){
Handel_DESCRIBE(buffer, sockfd);// Send to server RTSP Of DESCRIBE agreement
}
else{
printf("_____%d_____the OPTION answer Msg is wrong!\n", __LINE__);
return 0;
}
bzero(buffer, MAXBUF + 1);
/* DESCRIBE Reply */
len = recv(sockfd, buffer, MAXBUF, 0);/* Confirm that the server replies OPTION Reply */
if (len < 0){
printf("_____%d_____DESCRIBE Reply Msg:\n %s receive error! error code is %d, error content is %s \n", __LINE__,buffer, errno, strerror(errno));
}
else{
printf("_____%d_____DESCRIBE Reply Msg:\n %s receive successfully,total content is %dbytes!\n", __LINE__,buffer, len);
}
if (memcmp(buffer, successfullyReplyStr, sizeof(successfullyReplyStr)-1) == 0){
Handel_SETUP(buffer, sockfd);// Send to server RTSP Of SETUP agreement
}
else{
printf("_____%d_____the DESCRIBE answer Msg is wrong!\n",__LINE__);
return 0;
}
bzero(buffer, MAXBUF + 1);
len = recv(sockfd, buffer, MAXBUF, 0);/* Confirm that the server replies OPTION Reply */
if (len < 0){
printf("_____%d_____SETUP Reply Msg:\n %s receive error! error code is %d, error content is %s \n", __LINE__,buffer, errno, strerror(errno));
}
else{
printf("_____%d_____SETUP Reply Msg:\n %s receive successfully,total content is %dbytes!\n", __LINE__,buffer, len);
}
char sessionIdTmp[30];
bzero(sessionIdTmp,sizeof(sessionIdTmp));
strsearch(buffer, "Session: ", 9, sessionIdTmp);
printf("___%d___sessionIDTmp:%s\n",__LINE__,sessionIdTmp);
if (memcmp(buffer, successfullyReplyStr, sizeof(successfullyReplyStr)-1) == 0)
{
char searchStrTmp[13]="port=";
udpPort=intsearch(buffer,searchStrTmp,5);
if(udpPort==0){
return 0;
}
printf("the udp port is %d\n",udpPort);
bzero(&RTPAddr,sizeof(RTPAddr));
bzero(&RTCPAddr,sizeof(RTCPAddr));
rtpsockfd = init_udpsocket(udpPort, &RTPAddr, mcast_addr);
//rtcpsockfd = init_udpsocket(udpPort+1, &RTCPAddr, mcast_addr);
Handel_PLAY(buffer, sockfd,sessionIdTmp);// Send to server RTSP Of SETUP agreement
}
else
{
printf("_____%d_____the SETUP answer Msg is wrong!\n",__LINE__);
return 0;
}
bzero(buffer, MAXBUF + 1);
len = recv(sockfd, buffer, MAXBUF, 0);/* Confirm that the server replies OPTION Reply */
if (len < 0){
printf("_____%d_____PLAY Reply Msg:\n %s receive error! error code is %d, error content is %s \n", __LINE__,buffer, errno, strerror(errno));
}else{
printf("_____%d_____PLAY Reply Msg:\n %s receive successfully,total content is %dbytes!\n", __LINE__,buffer, len);
}
if (memcmp(buffer, successfullyReplyStr, sizeof(successfullyReplyStr)-1) != 0){
printf("_____%d_____the play answer Msg is wrong!\n",__LINE__);
return 0;
}
printf("_____%d_____now,receiving RTP packets data......\n",__LINE__);
The key function
int H264rtp_Handle(unsigned char *write_buf, int write_size)
{
rtp_header_t *rtp_header = (rtp_header_t *)write_buf;// obtain RTP The baotou
unsigned char *rtp_payload = write_buf + RTP_HEADER_LEN; // Address offset obtains the starting position of data
uint8_t nalu_type = rtp_payload[0] & 0x1F; // NaluHeader After 5 position or FuIndicator After 5 position , Reference resources NALU The head and FU Description of subcontracting header , They can be distinguished here
stream_p pointer_addr = calloc(sizeof(stream), 1);
pointer_addr->stream_buffer = NULL;
if (pointer_addr == NULL)
{
perror("calloc failed");
return 0;
}
if (nalu_type == 0x1C) // 0x1C by FU Package, otherwise NALU package
{
uint8_t fua_type = rtp_payload[1] & 0xE0; // FuHeader The top three of , The first package is 100b, Tundish 000, Tail package 010 Reference resources FU Package introduction
int header_len = RTP_HEADER_LEN + FU_INDICATOR_LEN + FU_HEADER_LEN;
unsigned char *nalu_payload = write_buf + header_len; // Address offset
if (fua_type == 0x80) // Fu Package for Nalu Starting position , Need to write NaluStarter + NaluHeader + NaluPayload.
{
uint8_t nalu_header = (rtp_payload[0] & 0xE0) | (rtp_payload[1] & 0x1F); // FuIndicator Before 3 Bit and FuHeader After 5 position
int input_size = NALU_STARTER_LEN + NALU_HEADER_LEN + (write_size - header_len);
pointer_addr->stream_buffer = calloc(input_size,1);
if (pointer_addr->stream_buffer == NULL)
{
perror("calloc failed");
return 0;
}
memset(pointer_addr->stream_buffer, 0, input_size);
pointer_addr->stream_buffer[NALU_STARTER_LEN - 1] = 1; // NaluStarter - [00, 00, 00, 01]
memcpy(pointer_addr->stream_buffer + NALU_STARTER_LEN, &nalu_header, NALU_HEADER_LEN); // NaluHeader
memcpy(pointer_addr->stream_buffer + NALU_STARTER_LEN + NALU_HEADER_LEN, nalu_payload, write_size - header_len); // NaluPayload
pointer_addr->stream_size = input_size;
tail_insert_in_ker_list(stream_head, pointer_addr);
printf("111%d\n", input_size);
}
else // Fu Package for Nalu Other places , Just write NaluPayload.
{
int input_size = write_size - header_len;
pointer_addr->stream_buffer = calloc(input_size, 1);
if (pointer_addr->stream_buffer == NULL)
{
perror("calloc failed");
return 0;
}
memset(pointer_addr->stream_buffer, 0, input_size);
memcpy(pointer_addr->stream_buffer, nalu_payload, input_size); // NaluPayload
pointer_addr->stream_size = input_size;
tail_insert_in_ker_list(stream_head, pointer_addr);
printf("222%d\n", input_size);
}
}
else // complete Nalu The package needs to be written NaluStarter + NaluHeader + NaluPayload.
{
int input_size = NALU_STARTER_LEN + (write_size - RTP_HEADER_LEN);
pointer_addr->stream_buffer = calloc(input_size, 1);
if (pointer_addr->stream_buffer == NULL)
{
perror("calloc failed");
return 0;
}
memset(pointer_addr->stream_buffer, 0, input_size);
pointer_addr->stream_buffer[NALU_STARTER_LEN - 1] = 1; // NaluStarter - [00, 00, 00, 01]
memcpy(pointer_addr->stream_buffer + NALU_STARTER_LEN, rtp_payload, write_size - RTP_HEADER_LEN); // RtpPayload = NaluHeader + NaluPayload.
pointer_addr->stream_size = input_size;
tail_insert_in_ker_list(stream_head, pointer_addr);
printf("3333%d\n", input_size);
}
}
Effect unpacking data is saved to file , use VLC Played successfully ~~
The code download ( Click here )
It's not easy to blog , It's helpful for you. Remember to collect some likes. Thank you ~~~, What questions can be consulted VX:a812417530
边栏推荐
- 登录式shell和非登录式shell
- 指针总结篇
- 动态内存管理
- js 对象深拷贝
- ts 学习记录(一)sudo忘记密码(乌龙)Try changing the ‘lib’ compiler option to include ‘dom’.
- 指针深度解刨《二》(指针指向自己)
- Solve the problem that the plug-in center of idea is not connected to the network
- Soft test intermediate [Database System Engineer] Chapter 0: how to prepare for the test by self-study, test introduction, test preparation materials, size score distribution in the morning and aftern
- 人脑的算力真的很弱吗
- v-7
猜你喜欢
基于[海思Hi3516dv300]开发的内核定时器中断
Postman configures the global variable postman sets the global token
What is RPA? Recommend automated tools that allow e-commerce operators to operate 10 times more efficiently
mysql
Weak foundation, shaking earth and mountains, Niu Ke brushes the title "II"
Depth analysis of pointer "Five"
ASP.NET Core部署手册:2.Hyper-V虚拟机
Self study the definition of golang [3.5go language array, range keyword] array, and use the for loop to traverse one-dimensional array
指针的深度解刨《七》(函数指针相关知识)
管正雄:基于预训练模型、智能运维的QA生成算法落地
随机推荐
QML drag pictures and objects across windows
三星6818基于uboot的流水灯程序
重写dispatchTouchEvent实现播放画面锁功能
serialization and deserialization
List、Set、Map的区别与联系
[step on pit] solution to NPM installation error
刨根问底丨落后的技术,能否造出好卖的产品?
Depth analysis of pointer "Five"
How to build a smart park with 5g and mobile edge computing servers
openlayers 使用canvas绘制圆形头像图标
指针的深度解刨《五》
Self study golang [3.6 slice practice code] slice length, upper limit, copy, delete and increase
Typo in static class property declarationeslint
动态内存管理
RunTime+compiler和RunTime only版本的区别
Soft test intermediate [Database System Engineer] Chapter 0: how to prepare for the test by self-study, test introduction, test preparation materials, size score distribution in the morning and aftern
三星6818LED驱动的编写
海思Hi3531||瑞芯微RK1109用rtsp服务器实现h264推流
函数栈帧的形成和销毁(26张图助你深入理解函数栈帧)
MySQL builds temporary tables through parameters