# openharmony_1.0.1实现RTSPServer ## 概述 openharmony中实现RTSPServer播放视频主要分为如下5部分。其中视频采集与视频编码平台芯片3518EV300与3516DV300已支持,将编码后的视频数据(H.265)存放至环形缓冲区,最后通过RTSPServer发送,RTSPClient由VLC播放器实现。 代码路径:[3516DV300](https://gitee.com/openharmony-sig/knowledge_demo_smart_home/blob/master/dev/docs/smart_door_viewer_3516/README.md) 代码路径:[3518EV300](https://gitee.com/openharmony-sig/knowledge_demo_smart_home/blob/master/dev/docs/smart_door_viewer_3518/README.md) ![](figures/_20211231155410.png) ## RTSPServer实现 RTSP流媒体播放实现主要涉及两个线程:1、将编码后的视频数据存储在环形缓冲区内。2、创建RTSPServer发送环形缓冲区数据。 ![](figures/_20220104161434.png) ### 环形缓冲区 环形缓冲区主要目的是为了将视频编码(H.265)产生的数据通过RTSPServer实时地发送到RTSPClient端。 #### H.265数据原理 H.265=若干序列集。 序列集=1IDR帧+1VPS帧+1SPS帧+1PPS帧+1SEI帧+若干P帧组成。 每帧通过00 00 00 01分割以后的下一个字节就是NALU(网络抽象层单元)类型, - 1: 00 00 00 01 40 01 .... ,(0x40 & 0x7E)>> 1 值为 32, 语义为视频参数集 VPS - 2: 00 00 00 01 42 01 .... ,(0x42 & 0x7E)>> 1 值为 33, 语义为序列参数集 SPS - 3: 00 00 00 01 44 01 .... ,(0x44 & 0x7E)>> 1 值为 34, 语义为图像参数集 PPS - 4: 00 00 00 01 4E 01 ....,(0x4E & 0x7E)>> 1 值为 39, 语义为补充加强信息 SEI - 5: 00 00 00 01 26 01 .... ,(0x26 & 0x7E)>> 1 值为 19, 语义为可能有RADL图像的IDR图像的SS编码数据 IDR - 6: 00 00 00 01 02 01 .... ,(0x02 & 0x7E)>> 1 值为 1, 语义为被参考的后置图像P帧 - 如下图,左边是h265原始数据,右边是通过RTP发送去掉头数据。 ![](figures/_20220105113750.png) 在进行RTP分包发送时会将IDR、VPS、SPS、PPS、SEI拼凑为一起作为主要帧发送,因此头一帧数据 非常重要。 为了解决视频编码与RTSP线程线程同步的问题,缓冲区设计如下: ``` 文件路径:recorder_impl.cpp 实现函数:void VideoSourceProcess(const SourceManager *videoSourceManager, const RecorderSink *recorderSink) ``` 缓冲区为16*256K长度的数组buff。put为编码线程存放缓冲区偏移值,get为RTSPServer线程获取缓冲区的偏移值。 ![](figures/_20220104142410.png) 初始情况下put与get的位置均在开头。 ![](figures/_20220104143327.png) 当视频编码有数据时填充buff并put向前移。 ![](figures/_20220104143330.png) RTSP通过get将视频编码数据发送,然后释放buff,get向前移。 ![](figures/_20220104143339.png) 当put与get偏移超过16时重新置1,其中设置get数据的时间get与put的间隔不会超过3个buff。 ![](figures/_20220104143946.png) ### RTSPServer RTSP(Real Time Streaming Protocol)实时流协议作为一个应用层协议,RTSP提供了一个可供扩展的框架,它的意义在于使得实时流媒体数据的受控和点播变得可能。总的说来,RTSP是一个流媒体表示协议,通过RTSP传输控制命令与RTP传输视频流达到控制具有实时特性的数据发送。RTSP可以对流媒体提供诸如播放、暂停、快进等操作,它负责定义具体的控制消息、操作方法、状态码等,此外还描述了与RTP间的交互操作。 ![](figures/_20220104104509.png) RTSP C(Client)与 S(Server)交互流程图解 RTSP 中的 C(Client)与 S(Server)交互流程图解 ![](figures/_20220104095638.png) #### RTSP 关键字段说明 ##### 关键字:OPTIONS 得到服务器提供的可用方法(OPTION、DESCRIBE、SETUP、TEARDOWN、PLAY、PAUSE、SCALE、GET_PARAMETER、SET_PARAMETER)。 ##### 关键字:DESCRIBE 请求流的 SDP 信息。 注解:此处需要了解 H265 Law Data 如何生成 SPS PPS 信息。 ##### 关键字:SETUP 客户端提醒服务器建立会话,并建立传输模式。 注解:此处确定了 RTP 传输交互式采用 TCP(面向连接)还是 UDP(无连接)模式。 ##### 关键字:PLAY 客户端发送播放请求。 注解:此处引入 RTP 协议。 ##### 关键字:PAUSE 播放暂停请求。 注解:此关键字经常用在录像回放当中,实时视频流几乎用不到。 ##### 关键字:TEARDOWN 客户端发送关闭请求 #### RTP分包 其中RtpHeader(Rtp头)加payload(负载数据)。 ![](figures/_20220104150345.png) ##### RtpHeader数据 ``` csrcLen CSC计数,在没有RTP混频器的情况下通常为0 extension 扩展名,必须为0 padding 填充位,不得使用填充,默认为0 version 版本号 payloadType 数据帧类型(h265)。 marker 将一帧分片时区分头片 seq 序列号为了以每片为单位 timestamp 时间戳 以每帧为单位 ssrc 数据信源号 ``` ##### payload数据 RTP包最大为1400个字节,因此打包分为两种。 1. 一种是一个nal单元打包到一个rtp包中。 2. 一种是nal单元比较大,分片打包在多个rtp中。 单个nal直接发送即可 nal单元比较大,分片打包在多个rtp中,分片格式如下: ![](figures/_20220104155903.png) 其中PayloadHdr固定为49。FUheader数据为: ![](figures/_20220104160446.png) S置1表示起始片,E置1表示最后片,FuType就是实际的Nal type类型。 实现代码函数 ``` 文件:rtp.cpp 实现函数:int Rtp::UdpSendFrame(uint8_t *pNalBuf, int s32NalBufSize) ```