• 从零开始写一个发送h264的rtsp服务器(上)


    转自:http://blog.csdn.net/jychen105/article/details/47006345

    一、什么是RTSP

    通常所说的rtsp协议其实包含三个协议: rtsp协议, rtp协议, rtcp协议

    各协议运作流程概要:

    第一阶段:rtsp协议负责沟通传输什么数据,传的是图像还是声音,还是两者混合?图像的话传是h264流,还是h265流,还是jpeg流?后续的rtp,rtcp协议是采用tcp还是udp,端口号是多少都是通过第一阶段的rtsp协议确定的。

    第二阶段:通过rtp协议传输数据,rtcp进行网络传输质量的监控

    第三阶段:通过rtsp协议中断整个协议的传输

    二、RTSP协议详解

    rtsp协议是个文本协议,运行于tcp协议之上,服务器默认监听端口554,当然也可以修改成其他端口,一般不改。

    协议包格式

    • 客户端协议格式

    第一行:方法名:XXX

    第二行:CSeq:XXX

    第N行:XXX

    • 服务器端协议格式

    第一行:RTSP/1.0 XXX

    第二行:CSeq:XXX

    第N行:XXX

    协议最终都是以两个 分隔

    rtsp通信精简版

    步骤客户端服务端含义
    1 请求OPTIONS 回应OPTIONS 查询服务器支持哪些命令或者方法
    2 请求DESCRIBE 回应DESCRIBE 查询服务器发送流的描述信息
    3 请求SETUP 回应SETUP 告诉服务器以TCP or UDP建立RTP,RTCP连接,并告诉端口号
    4 请求PLAY 回应PLAY 告诉服务器可以用RTP协议发送数据过来了
    最后一步 请求TEARDOWN 关闭连接 告诉服务器关闭连接

    rtsp通信详细版本

    客户端:192.168.1.109 
    服务端:192.168.1.188

    1. OPTIONS

    客户端请求:

    OPTIONS rtsp://192.168.1.188/h264 RTSP/1.0
    CSeq: 2
    User-Agent: LibVLC/2.1.2 (LIVE555 Streaming Media v2013.12.05)

    服务端回应:

    RTSP/1.0 200 OK
    CSeq: 2
    Date: Mon, Jul 21 2014 09:07:56 GMT
    Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, GET_PARAMETER, SET_PARAMETER

    需注意的点:

    • 回应的CSeq与请求的CSeq必须一致,后续rtsp命令下同。

    • PAUSE, GET_PARAMETER, SET_PARAMETER这几个命令可无,也就是一些命令服务器可以不实现。OPTIONS, SETUP, PLAY是一定要有的,其他的未认真调查。

    2. DESCRIBE

    客户端请求:

    DESCRIBE rtsp://192.168.1.188/h264 RTSP/1.0
    CSeq: 3
    User-Agent: LibVLC/2.1.2 (LIVE555 Streaming Media v2013.12.05)
    Accept: application/sdp

    服务端回应:

    RTSP/1.0 200 OK
    CSeq: 3
    Date: Mon, Jul 21 2014 09:07:56 GMT
    Content-Base: rtsp://192.168.1.188/h264/
    Content-Type: application/sdp
    Content-Length: 547
    
    v=0
    o=- 1405932398518315 1 IN IP4 192.168.1.188
    s=Session streamed by "hua_an"
    i=h264
    t=0 0
    a=tool:LIVE555 Streaming Media v2012.10.24
    a=type:broadcast
    a=control:*
    a=range:npt=0-
    a=x-qt-text-nam:Session streamed by "hua_an"
    a=x-qt-text-inf:h264
    m=video 0 RTP/AVP 96
    c=IN IP4 0.0.0.0
    b=AS:500
    a=rtpmap:96 H264/90000
    a=fmtp:96 packetization-mode=1;profile-level-id=64002A;sprop-parameter-sets=J2QAKq2EBUViuKxUcQgKisVxWKjiECSFITk8nyfk/k/J8nm5s00IEkKQnJ5Pk/J/J+T5PNzZpsqAUAW6bIAAAfQAAGGocAAABbjYAAD0JBe91lA=,KP4Briw=
    a=control:track1

    注意的点:

    • 服务端回应了两个协议,一个是rtsp的回应,还回应了一个sdp协议(Session Description Protocol),sdp协议最后一个只有一个 。 rtsp协议是两个 结尾。

    • sdp协议中描述了发送的流为h264,采样率为90000Hz (h264的采样率为90000HZ,因此时间戳的单位为1(秒)/90000,因此如果当前视频帧率为25fps,那时间戳间隔或者说增量应该为3600, 即每个naul单元的时间间隔为3600。此句话可以放在rtp协议封装h264时理解。)

    • sprop-parameter-sets为sps跟pps的base64编码组合。(sps,pps为h264 nalu单元的Sequence Parameter Sets (SPS) 和Picture Parameter Set (PPS), 后续会介绍)

    3. SETUP

    客户端请求:

    SETUP rtsp://192.168.1.188/h264/track1 RTSP/1.0
    CSeq: 4
    User-Agent: LibVLC/2.1.2 (LIVE555 Streaming Media v2013.12.05)
    Transport: RTP/AVP/TCP;unicast;interleaved=0-1

    服务端回应:

    RTSP/1.0 200 OK
    CSeq: 4
    Date: Mon, Jul 21 2014 09:07:56 GMT
    Transport: RTP/AVP/TCP;unicast;destination=192.168.1.109;source=192.168.1.188;interleaved=0-1
    Session: 5C01EACE

    此处为TCP建立RTP跟RTCP。RTP,RTCP都是利用此路连接,不再建立新连接,只是数据包格式不一样而以。 
    注意interleaved=0-1, 0为传送RTP数据,1为RTCP数据

    4. PLAY

    客户端请求

    PLAY rtsp://192.168.1.188/h264/ RTSP/1.0
    CSeq: 5
    User-Agent: LibVLC/2.1.2 (LIVE555 Streaming Media v2013.12.05)
    Session: 5C01EACE
    Range: npt=0.000-

    服务端回应

    RTSP/1.0 200 OK
    CSeq: 5
    Date: Mon, Jul 21 2014 09:07:56 GMT
    Range: npt=0.000-
    Session: 5C01EACE
    RTP-Info: url=rtsp://192.168.1.188/h264/track1;seq=28626;rtptime=98136845

    播放,开始传输rtp数据。同时告知开始序号为28626, 开始时间戳为98136845

    5. 最后一步

    客户端请求:

    TEARDOWN rtsp://192.168.1.188/h264/ RTSP/1.0
    CSeq: 7
    User-Agent: LibVLC/2.1.2 (LIVE555 Streaming Media v2013.12.05)
    Session: 5C01EACE

    服务端回应:

    关闭RTSP连接

    三、RTP协议

    根据之前rtsp的协议,rtp即可以通过tcp,也可以通过udp传输。但是数据包协议格式是一样的。

    • tcp传输
    协议格式‘$’0长度(=RTP协议头长度+RTP数据长度)RTP协议头RTP数据
    长度信息 1字节 1字节 2字节 sizeof(RTP协议头) N
    • udp传输
    协议格式RTP协议头RTP数据
    长度信息 sizeof(RTP协议头) N

    – 数据传输采用网络字节序

    – RTP数据长度小于MTU长度, 一般是1500, 目的是为了网络传输避免分片,未深究如何避免分片的。

    – 传输的流媒体数据就是封装在RTP数据部分

    RTP协议头

    0                   1                   2                   3
    0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |V=2|P|X|  CC   |M|     PT      |       sequence number         |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |                           timestamp                           |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    |           synchronization source (SSRC) identifier            |
    +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
    |            contributing source (CSRC) identifiers             |
    |                             ....                              |
    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
    
    //set CC = 0, so there is no CSRC

    转成c语言结构体(小端字节序):

    typedef struct 
    {
        /* byte 0 */
        unsigned char csrc_len:4;  /* CC expect 0 */
        unsigned char extension:1; /* X  expect 1, see RTP_OP below */
        unsigned char padding:1;   /* P  expect 0 */
        unsigned char version:2;   /* V  expect 2 */
    
        /* byte 1 */
        unsigned char payload:7;   /* PT  RTP_PAYLOAD_RTSP */
        unsigned char marker:1;    /* M   expect 1 */
    
        /* byte 2,3 */
        unsigned short seq_no;     /*sequence number*/
    
        /* byte 4-7 */
        unsigned  long timestamp;  /*time stamp*/
    
        /* byte 8-11 */
        unsigned long ssrc;        /* stream number is used here. */
    } RTPHeader;/*12 bytes*/

    四、RTCP

    rtcp主要是用来解决网络流控的,如果是自实现rtsp服务器传输实时流,可以不实现此部分。

    如果是实现rtsp客户端,建立实现一个Recvive Report包就行了,此包主要是报告丢包率,网络延迟是多少,方便服务器端调节。 
    因为发的都是实时流,简单起见,recvive report封包时,丢包率为0,延迟也为0

    五、h264是如何通过rtsp发送的

    下篇

  • 相关阅读:
    LeetCode44——用搜索的思路去理解动态规划算法
    在vscode中配置LeetCode插件,从此愉快地刷题
    分布式专题——详解Google levelDB底层原理
    高等数学——求解不定积分经典换元法
    动态规划入门——详解完全背包与多重背包问题
    详解聚类算法Kmeans的两大优化——mini-batch和Kmeans++
    Python专题——详解enumerate和zip
    LeetCode42题,单调栈、构造法、two pointers,这道Hard题的解法这么多?
    零基础学Python--------第11章 使用Python操作数据库
    零基础学Python--------第10章 文件及目录操作
  • 原文地址:https://www.cnblogs.com/x_wukong/p/8603480.html
Copyright © 2020-2023  润新知