首页 > 其他分享 >WebSocket-FLV H264/H265服务器基本实现

WebSocket-FLV H264/H265服务器基本实现

时间:2024-01-13 18:36:18浏览次数:34  
标签:pCodecTagData WebSocket H264 H265 strData back strSPS push

场景

HTTP-FLV: 基于HTTP流式IO传输FLV,依赖浏览器支持播放FLV。但是由于同源的限制问题,浏览器只能播放六路视频,因此采用WebSocket-FLV

WebSocket-FLV: 基于WebSocket传输FLV,依赖浏览器支持播放FLV。WebSocket建立在HTTP之上,建立WebSocket连接前还要先建立HTTP连接。


视频参数代码

H264

SPS十六进制数值如下:

67 4d 00 1e 96 35 41 60 24 d3 70 10 10 14 00 00 1c 20 00 05 7e 40 10

	char* pCodecTagData = (char*)calloc(512, sizeof(char));
	pCodecTagData[0] = 0x17;
	pCodecTagData[1] = 0x00;// AVC sequence header
	pCodecTagData[2] = 0x00;
	pCodecTagData[3] = 0x00;
	pCodecTagData[4] = 0x00;// composition time
	pCodecTagData[5] = 0x01;/* version */
 	pCodecTagData[6] = m_strSPS[1]; /* profile */
 	pCodecTagData[7] = m_strSPS[2];/* profile compat */
 	pCodecTagData[8] = m_strSPS[3]; /* level */
	pCodecTagData[9] = 0xff;/* 6 bits reserved (111111) + 2 bits nal size length - 1 (11) */
	pCodecTagData[10] = 0xe0 | nSPSNumber;/* 3 bits reserved (111) + 5 bits number of sps */
	avio_wb16(&pCodecTagData[11], m_strSPS.length());
	memcpy(&pCodecTagData[13], m_strSPS.c_str(), m_strSPS.length());
	pCodecTagData[13 + m_strSPS.length()] = nPPSNumber;
	avio_wb16(&pCodecTagData[14 + m_strSPS.length()], m_strPPS.length());
	memcpy(&pCodecTagData[16+ m_strSPS.length()], m_strPPS.c_str(), m_strPPS.length());
	int nCodecLen = 16 + m_strSPS.length() + m_strPPS.length();

H265

SPS十六进制数值如下:

42 01 01 01 60 00 00 03 00 b0 00 00 03 00 00 03 00 5a a0 05 82 00 90 58 da e4 93 2f 4d c0 40 40 40 20

	std::string strData;
	strData.push_back(0x1c);
	strData.push_back(0x00);
	strData.push_back(0x00);
	strData.push_back(0x00);
	strData.push_back(0x00);
	//8bit configurationVersion (always 0x01)
	strData.push_back(0x01);
	//8bit [2bit general_profile_space   1bit general_tier_flag   5bit general_profile_idc]
	strData.push_back(m_strSPS[1]);
	//32bit general_profile_compatibility_flags 
	strData.push_back(m_strSPS[2]);
	strData.push_back(m_strSPS[3]);
	strData.push_back(m_strSPS[4]);
	strData.push_back(m_strSPS[5]);
	//48bit general_constraint_indicator_flags NULL nothing deal in rtmp
	strData.push_back(m_strSPS[6]);
	strData.push_back(m_strSPS[7]);
	strData.push_back(m_strSPS[8]);
	strData.push_back(m_strSPS[9]);
	strData.push_back(m_strSPS[10]);
	strData.push_back(m_strSPS[11]);
	//8bit general_level_idc
	strData.push_back(m_strSPS[12]);
	//48bit NULL nothing deal in rtmp
	//4 reserved('1111') 12 min_spatial_segmentation_idc
	strData.push_back(0x00);
	strData.push_back(0x00);
	//6bit reserved('111111') 2bit parallismType
	strData.push_back(0x00);
	//5bit reserved('111111') 2bit chromaFormat
	strData.push_back(0x00);
	//5bit reserved('111111') 3bit bitDepthLumaMinus8
	strData.push_back(0x00);
	//6bit reserved('111111') 3bit bitDepthChromaMinus8
	strData.push_back(0x00);
	// bit(16) avgFrameRate;
	strData.push_back(0x00);
	strData.push_back(0x00);
	
	/* bit(2) constantFrameRate */
	/* bit(3) numTemporalLayers */
	/* bit(1) temporalIdNested */
	/* bit(2) lengthSizeMinusOne*/
	strData.push_back(0x83);
	/* unsigned int(8) numOfArrays; 03 */
	strData.push_back(0x03);

WebSocket 的诞生

做客户端开发时,接触最多的应用层网络协议,就是 HTTP 协议,而今天介绍的 WebSocket,下层和 HTTP 一样也是基于 TCP 协议,这是一种轻量级网络通信协议,也属于应用层协议。

WebSocket-FLV H264/H265服务器基本实现_H265

WebSocket 与 HTTP/2 一样,其实都是为了解决 HTTP/1.1 的一些缺陷而诞生的,而 WebSocket 针对的就是「请求-应答」这种"半双工"的模式的通信缺陷。

「请求-应答」是"半双工"的通信模式,数据的传输必须经过一次请求应答,这个完整的通信过程,通信的同一时刻数据只能在一个方向上传递。它最大的问题在于,HTTP 是一种被动的通信模式,服务端必须等待客户端请求才可以返回数据,无法主动向客户端发送数据。

这也导致在 WebSocket 出现之前,一些对实时性有要求的服务,通常是基于轮询(Polling)这种简单的模式来实现。轮询就是由客户端定时发起请求,如果服务端有需要传递的数据,可以借助这个请求去响应数据。轮询的缺点也非常明显,大量空闲的时间,其实是在反复发送无效的请求,这显然是一种资源的损耗。

虽然在之后的 HTTP/2、HTTP/3 中,针对这种半双工的缺陷新增了 Stream、Server Push 等特性,但是「请求-应答」依然是 HTTP 协议主要的通信方式。

WebSocket 协议是由 HTML5 规范定义的,原本是为了浏览器而设计的,可以避免同源的限制,浏览器可以与任意服务端通信,现代浏览器基本上都已经支持 WebSocket。

虽然 WebSocket 原本是被定义在 HTML5 中,但它也适用于移动端,尽管移动端也可以直接通过 Socket 与服务端通信,但借助 WebSocket,可以利用 80(HTTP) 或 443(HTTPS)端口通信,有效的避免一些防火墙的拦截。

WebSocket-FLV H264/H265服务器基本实现_服务端_02

 WebSocket 是真正意义上的全双工模式,也就是我们俗称的「长连接」。当完成握手连接后,客户端和服务端均可以主动的发起请求,回复响应,并且两边的传输都是相互独立的。

WebSocket 的特点

WebSocket 的数据传输,是基于 TCP 协议,但是在传输之前,还有一个握手的过程,双方确认过眼神,才能够正式的传输数据。

WebSocket 的握手过程,符合其 "Web" 的特性,是利用 HTTP 本身的 "协议升级" 来实现。

在建立连接前,客户端还需要知道服务端的地址,WebSocket 并没有另辟蹊径,而是沿用了 HTTP 的 URL 格式,但协议标识符变成了 "ws" 或者 "wss",分别表示明文和加密的 WebSocket 协议,这一点和 HTTP 与 HTTPS 的关系类似。

ws://cxmydev.com/some/path

ws://cxmydev.com:8080/some/path

wss://cxmydev.com:443?uid=xxx

Websocket的世界

通信协议格式是WebSocket格式,服务器端采用Tcp Socket方式接收数据,进行解析,协议格式如下:

WebSocket-FLV H264/H265服务器基本实现_服务端_03

首先我们需要知道数据在物理层,数据链路层是以二进制进行传递的,而在应用层是以16进制字节流进行传输的。

 第一个字节:

WebSocket-FLV H264/H265服务器基本实现_WebSocket-FLV_04

FIN:1位,用于描述消息是否结束,如果为1则该消息为消息尾部,如果为零则还有后续数据包;

 RSV1,RSV2,RSV3:各1位,用于扩展定义的,如果没有扩展约定的情况则必须为0

 OPCODE:4位,用于表示消息接收类型,如果接收到未知的opcode,接收端必须关闭连接。长连接探活包就是这里标识的。

 OPCODE定义的范围:

   0x0表示附加数据帧

   0x1表示文本数据帧

   0x2表示二进制数据帧

   0x3-7暂时无定义,为以后的非控制帧保留

   0x8表示连接关闭

   0x9表示ping

   0xA表示pong

   0xB-F暂时无定义,为以后的控制帧保留


第二个字节以及以后字节:

WebSocket-FLV H264/H265服务器基本实现_WebSocket-FLV_05

WebSocket-FLV H264/H265服务器基本实现_HTTP_06

WebSocket-FLV H264/H265服务器基本实现_HTTP_07

 MASK:1位,用于标识PayloadData是否经过掩码处理,客户端发出的数据帧需要进行掩码处理,所以此位是1。数据需要解码。

 Payload length === x,如果

 如果 x值在0-125,则是payload的真实长度。

 如果 x值是126,则后面2个字节形成的16位无符号整型数的值是payload的真实长度。

 如果 x值是127,则后面8个字节形成的64位无符号整型数的值是payload的真实长度。

 此外,如果payload length占用了多个字节的话,payload length的二进制表达采用网络序(big endian,重要的位在前)。

参考

WebSocket协议理解-数据包格式解析 - zhangmingda - 博客园 (cnblogs.com)

标签:pCodecTagData,WebSocket,H264,H265,strData,back,strSPS,push
From: https://blog.51cto.com/fengyuzaitu/9232753

相关文章

  • Winform中使用Fleck实现Websocket服务端并读取SQLite数据库中数据定时循环群发消息
    场景Winform中使用Websocket4Net实现Websocket客户端并定时存储接收数据到SQLite中:Winform中使用Websocket4Net实现Websocket客户端并定时存储接收数据到SQLite中-Winform中操作Sqlite数据增删改查、程序启动时执行创建表初始化操作:Winform中操作Sqlite数据增删改查、程序启动时执......
  • Winform中使用Websocket4Net实现Websocket客户端并定时存储接收数据到SQLite中
    场景SpringBoot+Vue整合WebSocket实现前后端消息推送:SpringBoot+Vue整合WebSocket实现前后端消息推送_websocketvue3.0springboot往客户端推送上面实现ws推送数据流程后,需要在windows上使用ws客户端定时记录收到的数据到文件中,这里文件使用SQLite数据库进行存储。Winform中操作S......
  • http和websocket的一些思考
    InCivetWeb,thetermsCivetHandlerandCivetWebSocketHandlerarerelatedtodifferenttypesofrequesthandling.CivetHandler:CivetHandlerisagenericclassinCivetWebthatisusedforhandlingHTTPrequests.Whenyoucreateaclassthatinheritsfr......
  • WebSocket与JavaScript:实现实时地理位置定位系统的关键技术
    Laravel是一个流行的PHP框架,它具有出色的可测试性,可以帮助开发人员在更短的时间内编写可靠的代码。但是,即使使用了这个框架,也可能会出现测试覆盖率较低的情况。测试覆盖率是指代码中已由测试案例覆盖的部分比例。测试覆盖率越高,代码质量越高。在本文中,我们将分享几种技巧,帮助您提......
  • 如何使用WebSocket和JavaScript实现在线人脸识别系统
    Laravel是一个流行的PHP框架,它具有出色的可测试性,可以帮助开发人员在更短的时间内编写可靠的代码。但是,即使使用了这个框架,也可能会出现测试覆盖率较低的情况。测试覆盖率是指代码中已由测试案例覆盖的部分比例。测试覆盖率越高,代码质量越高。在本文中,我们将分享几种技巧,帮助您提......
  • SpringBoot WebSocket 样例
    SpringBootWebSocket样例pom.xml依赖配置<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-websocket</artifactId></dependency><dependency><groupId>javax.webso......
  • 用 Socket.D 替代原生 WebSocket 做前端开发
    socket.d.js是基于websocket包装的socket.d协议的实现。就是用ws传输数据,但功能更强大。功能原生websocketsocket.d说明listen有有监听消息send有有发消息sendAndRequest无有发消息并接收一个响应(类似于http)sendAndSubscribe无有发消息......
  • SpringBoot集成WebSocket实现消息推送
    一、前言WebSocket是一种新型的通信协议,它可以在客户端和服务端之间实现双向通信,具有低延迟、高效性等特点,适用于实时通信场景。它是一种基于TCP协议实现的全双工通信协议,使用它可以实现实时通信,不必担心HTTP协议的短连接问题。SpringBoot可以很方便的集成WebSocket实现高效实时的......
  • go SSH远程终端及WebSocket
      目前chisel基于tcphttpwebsocket的ssh代理!!所以这个东西不就是可以直接远程登录了吗?就行jumpserver一样和chisel一样使用ssh goget"github.com/gorilla/websocket"goget"golang.org/x/crypto/ssh"//等库基于Web的Terminal终端控制台完成这样一个WebTermi......
  • aspnetcore使用websocket实时更新商品信息
    先演示一下效果,再展示代码逻辑。中间几次调用过程省略。。。暂时只用到了下面四个项目1.产品展示页面中第一次通过接口去获取数据库的列表数据///<summary>///获取指定的商品目录///</summary>///<paramname="pageSize"></param>///<paramname="pageIndex"></p......