ffmpeg获取rtsp h265_基于ffmpeg的rtsp拉流代码分析流水账

概念

RTP: Real-time Transport Protocol,实时传输协议,一般用于多媒体数据的传输。

RTCP: RTP Control Protocol,实时传输控制协议,同RTP一起用于数据传输的监视,控制功能。

RTSP: Real Time Streaming Protocol,实时流协议,用于多媒体数据流的控制,如播放,暂停等。

RTP/RTCP相对于底层传输层,和RTSP,SIP等上层协议一起可以实现视频会议,视频直播等应用

RTP/RTSP/RTCP的区别 用一句简单的话总结:RTSP发起/终结流媒体、RTP传输流媒体数据 、RTCP对RTP进行控制,同步。

UDP:

TCP:

HTTP:

SDP:

rtsp服务器配置

基本流程 rtsp服务器配置

但是有一点需要主要的

将此mkv文件复制到和上面live555MediaServer可执行文件的同一个目录,

这里不需要将媒体文件放在live555MediaServer同一个目录,具体是看执行live555MediaServer进程的所在文件夹

例如:

Download $ ~/vendor/live/mediaServer/live555MediaServer

这时视频是Download目录下的

live555MediaServer传输1080p视频

默认配置,在terminal会打印如下错误

MultiFramedRTPSink::afterGettingFrame1(): The input frame data was too large for our buffer size (100452). 27300 bytes of trailing data was dropped! Correct this by increasing "OutPacketBuffer::maxSize" to at least 127300, *before* creating this 'RTPSink'. (Current value is 100000.)

OutPacketBuffer::maxSize默认大小为100000

需要修改DynamicRTSPServer的代码

} else if (strcmp(extension, ".264") == 0) {

// Assumed to be a H.264 Video Elementary Stream file:

NEW_SMS("H.264 Video");

OutPacketBuffer::maxSize = 157300; // allow for some possibly large H.264 frames

sms->addSubsession(H264VideoFileServerMediaSubsession::createNew(env, fileName, reuseSource));

}

然后重新编译

如何使用rtp over tcp

在ffmpeg 命令中

-rtsp_transport tcp -i rtsp://192.168.0.172:8554/bb.264 ./bbo.264

在ffmpeg 代码中

if (av_stristart(filename, "rtsp", NULL)) {

av_dict_set(&o->g->format_opts, "rtsp_transport", "tcp", 0);

}

err = avformat_open_input(&ic, filename, file_iformat, &o->g->format_opts);

rtsp over http

这时候就不要使用live555MediaServer开启时打印信息中的http端口

例如

(We use port 8000 for optional RTSP-over-HTTP tunneling, or for HTTP live streaming (for indexed Transport Stream files only).)

把url的端口号换一下

if (av_stristart(filename, "rtsp", NULL)) {

av_dict_set(&o->g->format_opts, "rtsp_transport", "tcp", 0);

}

err = avformat_open_input(&ic, filename, file_iformat, &o->g->format_opts);

rtp over udp和rtp over tcp(unicast 和 mutlicat)

ffmpeg默认是rtp over udp,关于rtp over udp和rtp over tcp的区别可以看看如下文章

http://blog.csdn.net/cloume/article/details/11771403

http://wiki.yak.net/916/multicast-rtp-etc.html

ffmpeg代码分析

ffmpeg rtsp代码位置

liveformat/rtsp.c 这个是udp里面的实现

liveformat/rtspdec.c

avformat_open_input

avformat_open_input >>

rtsp_read_header >>

ff_rtsp_connect>>

ff_rtsp_setup_input_streams

rtsp连接 ff_rtsp_connect

rtsp的控制方式

RTSP_MODE_PLAIN 普通rtsp

RTSP_MODE_TUNNEL 基于HTTP

分割url:proto, auth, host ,port ,path

rtsp HTTP打开连接

ffmpeg会在http的请求报文头发送如下格式

"x-sessioncookie: %s\r\n"

"Accept: application/x-rtsp-tunnelled\r\n"

"Pragma: no-cache\r\n"

"Cache-Control: no-cache\r\n",

x-sessioncookie:只是一个随机的值

即使不看方法体也能猜出来

snprintf(sessioncookie, sizeof(sessioncookie), "%08x%08x",

av_get_random_seed(), av_get_random_seed());

rtsp tcp打开连接

简单的建立信道

rtsp 发送OPTIONS命令,获取支持的命令

rtsp 传输方式

RAW/RAW ::Support receiving plain data over UDP without any RTP encapsulation

RTP/AVP: RTP transport / audio , video , control protocol

x-pn-tng: 不懂

rtsp 发送 SETUP命令 ff_rtsp_make_setup_request()函数

status_code = 461 /* Unsupported protocol */

status_

验证c s两端的协议,必须一致(大概是怕我们乱改代码)

interleaved :

The channel identifier is defined in the Transport header with the

interleaved parameter(Section 12.39).

个人理解,tcp是一个持续的流,所以需要一个interleaved来分割包

ff_rtsp_make_setup_request

ffmpeg会执行三个动作

OPTIONS

查看支持命令

这里的live555并没有收到任何的报文信息

DESCRIBE 获取视频信息 --就是SDP报文

SETUP 建立RTP通道

rtsp_read_play

ff_read_packet

rtsp_read_packet >> ff_rtsp_fetch_packet

rtp playload格式

packetization-mode 0 : 单一NALU

单NAL单元包(Single NAL Unit Packet):负载中只包含单一的NAL单元。NAL头的类型等同于原始的NAL单元类型,也就是,1~23的范围。此种包必须只包含单个NAL单元,聚合包和分片单元都不能在这种包内使用。必须按解码顺序发送.

packetization-mode 1 : non-interleaved 非交错封包模式

用于聚合多个NAL单元为单个RTP负载。这种包存在四种版本:单时间聚合包(STAP-A),单时间聚合包(STAP-B),多时间聚合包(MTAP)带16位偏移(MTAP16),多时间聚合包(MTAP)带24位偏移(MTAP24). NAL类型号分配给STAP-A,STAP-B,MTAP16和MTAP24分别为24,25,26,27。

packetization-mode 2 : interleaved 交错封包模式

用于分割单一的NAL单元为多个RTP包,共有两个版本,FU-A和FU-B. 它们的NAL类型号分别为28,29.

分片的原因是为了传输大于64KB的NAL单元。

分片针对单个NAL单元,而不是聚合包。

FU不能嵌套。

FU的时戳设置为被分片NAL单元的NALU时间

FU-A包括一个字节的FU indicator+一个字节的FU header+FU payload

FU-B比FU-A多了一个字节的decoding order number(DON).

FU-B必须只被用在交叉包装模式下NAL分片的第一片。换句话说,在交叉包装模式,每个NALU被分片为FU-B+FU-A+FU-A+...+FU-A

ff_rtsp_fetch_packet

ff_rtsp_fetch_packet 根据lower_transport 调用不同协议read_packet的方法

执行流程

OPTIONS-> DESCRIBE->RTSP/SDP

SDP(Session Description Protocol)

SDP 会话描述协议

简单报文分析

v=0 协议版本

o=- 1476286318262307 1 IN IP4 192.168.31.194 (所有者/创建者和会话标识符)

s=H.264 Video, streamed by the LIVE555 Media Server (会话名称)

i=bb.264(会话信息)

t=0 0(会话活动时间)

a=tool:LIVE555 Streaming Media v2016.09.22

a=type:broadcast

a=control:*

a=range:npt=0-

a=x-qt-text-nam:H.264 Video, streamed by the LIVE555 Media Server

a=x-qt-text-inf:bb.264

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=640028;sprop-parametersets=Z2QAKKzZQHgCJ+WEAAADAAQAAAMA8Dxgxlg=,aOvjyyLA

a=control:track1

a=rtpmap

H264 编码名称

90000 时钟频率

96 dynamically assigned

"a=rtpmap" 行中的编码名称必须是 "H264".

"a=rtpmap" 行中的时钟频率必须是 90000.

packetization-mode:表示支持的封包模式.

当 packetization-mode 的值为 0 时或不存在时, 必须使用单一 NALU 单元模式.

当 packetization-mode 的值为 1 时必须使用非交错(non-interleaved)封包模式.

当 packetization-mode 的值为 2 时必须使用交错(interleaved)封包模式.

sprop-parameter-sets: SPS,PPS

这个参数可以用于传输 H.264 的序列参数集和图像参数 NAL 单元. 这个参数的值

采用 Base64 进行编码. 不同的参数集间用","号隔开

profile-level-id:

这个参数用于指示 H.264 流的 profile 类型和级别. 由 Base16(十六进制) 表示的 3 个字节. 第一个字节表示 H.264 的 Profile 类型, 第三个字节表示 H.264 的 Profile 级别:

参考资料

你可能感兴趣的:(ffmpeg获取rtsp,h265)