Windows远程桌面实现之五(FFMPEG实现桌面屏幕RTSP( 二 )


而且要实现可以同时朝多个混合器写数据 。也就是我们可以同时保存到本地MP4文件,
也同时可以朝多个RTSP或RTMP服务器做推流 。
如下图的配置界面,就是最新版本程序做的推流的网页方式的配置界面:

Windows远程桌面实现之五(FFMPEG实现桌面屏幕RTSP

文章插图
图中设置了三个推流地址,分别朝RTSP, RTMP服务器推送音视频,同时保存到d盘的t.mp4视频文件中 。
在我们的远程桌面控制程序中,编码好的桌面图像数据和声音数据,
一边要发送给多个通讯的网页客户端,一边要发送给多个原生客户端(当然还包括发送给中转服务端),
现在还要发送给RTMP,RTSP,同时保存到本地文件等,
如果朝每个终端发送音视频流都做一次编码,是不现实的 。这就是为何要把.c例子代码里边的编码部分剥离出去,
只保留把编码好的音视频帧直接写入混合器的功能 。
我们先来看看调用的API的流程,其实是挺简单,函数也不多:
首先调用 创建变量,最后一个参数就是推流地址,或者保存本地的完整路径,
比如:
* ctx;
【Windows远程桌面实现之五(FFMPEG实现桌面屏幕RTSP】(&ctx, NULL, "flv", "rtmp://192.168.88.1/hls/test"); // 以RTMP协议推送
(&ctx, NULL, "rtsp", "rtsp://192.168.88.1/test"); // 以RTSP协议推送
(&ctx, NULL,NULL, "d:\\.mp4") ; //保存到本地 .mp4视频文件中 。
之后调用函数创建视频流和音频流,并且添加到ctx变量中 。
比如如下代码就是创建编码类型为H264和AAC的视频和音频流:
*fmt = ctx->;
固定 H264 + AAC 编码
fmt-> = ;
fmt-> = ;
codec = ();
* st = ( ctx, codec);
...... //其他初始化
codec = ();
* st = ( ctx , codec);
...... //其他初始化
因为RTSP,RTMP都是网络通讯,网络环境复杂多变就必须面临一个通讯超时问题,写到本地磁盘倒不必关心这个 。
结构提供了一个变量,用来设置回调函数,我们可以设置这个回调函数,用来检测超时 。
如下设置:
ctx->. = ; // 这个是我们的回调函数,在此函数中用于检测写操作是否超时 。
ctx->. = this; //
如果不是写到本地磁盘,而是网络通讯,我们还必须调用来初始化网络 。如下所示:
if (!(fmt->flags & )) {
以写方式打开,因为我们是推流,只写不读,就是RTSP,RTMP的URL地址 。
ret = (&ctx->pb, .c_str(), , &ctx->, NULL );
}
初始化就这样完成了 。接下来,需要把头信息写入,这时候调用 r 函数来写头部信息 。
写完头部信息,我们就可以不断调用 或者,把已经编码好的视频帧和音频帧写入 。
底层框架会根据不同协议,做不同的推送处理 。
等推流结束了,调用写入尾部信息,
如果是写到本地视频文件,一定需要调用,否则视频文件无法正常使用 。
以上流程应该是非常简洁明了的 。
在这里我们只需要的混合器功能,不需要打开编码器,因此与.c例子不同的是,在创建流之后,
不必调用来打开具体的编码设备 。
既然不打开具体的编码设备,在调用r 写头部信息的时候,框架是不清楚要写哪些头部信息的,
因此,我们在调用 r 前,必须还做些额外的工作:
那就是填写 每个编码器的字段,告诉,头部应该写些什么进去 。
比如对于H264编码的视频,我们应该填写 H264 AVCC 格式的头,用来存储 SPS,PPS。
这个几乎是固定的填写方法,如下:
假设SPS,PPS的和长度分别是:, 和 , 。
* c = ->codec; //是创建视频流返回的对象 。