RTSP服务器简单实战

RTSP服务器

RTSP是一个实时传输流协议,是一个应用层的协议(通常包括RTSP协议、RTP协议、RTCP协议)

  • RTSP协议:负责服务器与客户端之间的请求与响应
  • RTP协议:负责服务器与客户端之间传输媒体数据
  • RTCP协议:负责提供有关RTP传输质量的反馈,就是确保RTP传输的质量

三者的关系:RTSP并不会发送媒体数据,只是完成服务器和客户端之间的信令交互;RTP协议负责媒体数据传输;RTCP负责RTP数据包的监视和反馈。RTP和RTCP并未规定传输层的类型,TCP/UDP;而RTSP的传输层则要求是基于TCP。
源码:https://gitee.com/Vanishi/BXC_RtspServer_study

实现一个基于UDP的RTP传输h264的RTSP服务器,并能够进行rtsp拉流播放

# ffmpeg命令行解封装.mp4生成.h264视频文件
ffmpeg -i test.mp4 -codec copy -bsf: h264_mp4toannexb -f h264 test.h264
#pragma once
#pragma comment(lib, "ws2_32.lib")
#include <stdint.h>

#define RTP_VESION              2

#define RTP_PAYLOAD_TYPE_H264   96
#define RTP_PAYLOAD_TYPE_AAC    97

#define RTP_HEADER_SIZE         12
#define RTP_MAX_PKT_SIZE        1400

/*
  *    0                   1                   2                   3
  *    7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0
  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *   |V=2|P|X|  CC   |M|     PT      |       sequence number         |
  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *   |                           timestamp                           |
  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *   |           synchronization source (SSRC) identifier            |
  *   +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  *   |            contributing source (CSRC) identifiers             |
  *   :                             ....                              :
  *   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  *
  */
struct RtpHeader
{
/* byte 0 */
uint8_t csrcLen : 4;//CSRC计数器,占4位,指示CSRC 标识符的个数。
uint8_t extension : 1;//占1位,如果X=1,则在RTP报头后跟有一个扩展报头。
uint8_t padding : 1;//填充标志,占1位,如果P=1,则在该报文的尾部填充一个或多个额外的八位组,它们不是有效载荷的一部分。
uint8_t version : 2;//RTP协议的版本号,占2位,当前协议版本号为2。

/* byte 1 */
uint8_t payloadType : 7;//有效载荷类型,占7位,用于说明RTP报文中有效载荷的类型,如GSM音频、JPEM图像等。
uint8_t marker : 1;//标记,占1位,不同的有效载荷有不同的含义,对于视频,标记一帧的结束;对于音频,标记会话的开始。

/* bytes 2,3 */
uint16_t seq;//占16位,用于标识发送者所发送的RTP报文的序列号,每发送一个报文,序列号增1。接收者通过序列号来检测报文丢失情况,重新排序报文,恢复数据。

/* bytes 4-7 */
uint32_t timestamp;//占32位,时戳反映了该RTP报文的第一个八位组的采样时刻。接收者使用时戳来计算延迟和延迟抖动,并进行同步控制。

/* bytes 8-11 */
uint32_t ssrc;//占32位,用于标识同步信源。该标识符是随机选择的,参加同一视频会议的两个同步信源不能有相同的SSRC。

/*标准的RTP Header 还可能存在 0-15个特约信源(CSRC)标识符
   
   每个CSRC标识符占32位,可以有0~15个。每个CSRC标识了包含在该RTP报文有效载荷中的所有特约信源

   */
};

struct RtpPacket
{
struct RtpHeader rtpHeader;
uint8_t payload[0];
};

实现一个基于UDP的RTP传输音频aac的RTSP服务器,并能够进行rtsp拉流播放

  • 客户端建立与RTSP服务端的连接,并且在RTSP服务端回复客户端的Play请求以后,服务端需要源源不断的读取一个本地aac音频文件,并将读取到的aac音频码流封装到RTP数据包中,再推送至客户端。
  • 麦克风在录音采样后,直接获得的就是音频原始数据pcm,但pcm数据较大,所以通常需要压缩之后才能传输或保存,常见的音频压缩技术有aac,g711,mp3等

AAC音频有两种:

  1. ADIF - 音频数据交换格式:只有一个统一的头,必须得到所有数据后解码,适用于本地文件
  2. ADTS - 音视数据传输流:每一帧都有头信息,任意帧解码,适用于传输流
# ffmpeg命令行 从mp4视频文件提取aac音频文件
ffmpeg -i test.mp4  -vn -acodec aac test.aac
# ffmpeg 从aac音频文件解码为pcm音频文件
ffmpeg -i test.aac -f s16le test.pcm
# ffplay 播放.pcm音频文件
ffplay -ar 44100 -ac 2 -f s16le -i test.pcm
struct AdtsHeader {
    unsigned int syncword;  //12 bit 同步字 '1111 1111 1111',一个ADTS帧的开始
    uint8_t id;        //1 bit 0代表MPEG-4, 1代表MPEG-2。
    uint8_t layer;     //2 bit 必须为0
    uint8_t protectionAbsent;  //1 bit 1代表没有CRC,0代表有CRC
    uint8_t profile;           //1 bit AAC级别(MPEG-2 AAC中定义了3种profile,MPEG-4 AAC中定义了6种profile)
    uint8_t samplingFreqIndex; //4 bit 采样率
    uint8_t privateBit;        //1bit 编码时设置为0,解码时忽略
    uint8_t channelCfg;        //3 bit 声道数量
    uint8_t originalCopy;      //1bit 编码时设置为0,解码时忽略
    uint8_t home;               //1 bit 编码时设置为0,解码时忽略

    uint8_t copyrightIdentificationBit;   //1 bit 编码时设置为0,解码时忽略
    uint8_t copyrightIdentificationStart; //1 bit 编码时设置为0,解码时忽略
    unsigned int aacFrameLength;               //13 bit 一个ADTS帧的长度包括ADTS头和AAC原始流
    unsigned int adtsBufferFullness;           //11 bit 缓冲区充满度,0x7FF说明是码率可变的码流,不需要此字段。CBR可能需要此字段,不同编码器使用情况不同。这个在使用音频编码的时候需要注意。

    /* number_of_raw_data_blocks_in_frame
     * 表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧
     * 所以说number_of_raw_data_blocks_in_frame == 0
     * 表示说ADTS帧中有一个AAC数据块并不是说没有。(一个AAC原始帧包含一段时间内1024个采样及相关数据)
     */
    uint8_t numberOfRawDataBlockInFrame; //2 bit
};

实现一个基于TCP的RTP同时传输h264和aac的RTSP服务器,并能够进行rtsp拉流播放

  1. 客户端请求RTSP的Describe请求时,RTSP服务器返回的SDP协议,需要同时包含音频流和视频流的信息
  2. 客户端请求RTSP的Setup请求时,RTSP服务器不需要再对应创建RTP和RTCP的UDP连接通道,因为基于TCP的RTP传输,客户端与服务器交互时,无论是RTSP信令还是RTP数据包或者是RTCP数据包,都是使用同一个TCP连接通道。(TCP连接通道在发送RTP数据包或RTCP数据包时,需添加一些分隔字节)
  3. 客户端请求RTSP的Play请求时,RTSP服务器对Play请求进行回复后,源源不断的同时向客户端发送音频流和视频流的RTP数据包
# rtp通道是tcp时需要加参数,否则默认是UDP的!
ffplay -i -rtsp_transport tcp rtsp://127.0.0.1:8554
  • 15
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值