在前面一个博客(地址在这里 )中,我们做到了将采集的摄像头数据编码为H.264,接下来我么讨论下如何将H.264发送,在接收端接收解码并播放。和上一篇编码的博客一样,我们也是直接调用ffmpeg.exe和ffplay.exe文件,内部的具体操作需要抽时间去阅读。


1.传输

       UDP是一种无连接的传输层协议,不对传送数据包进行可靠性保证,适合一次性传输少量数据。

       我们在编码指令的基础上增加指令,将编码后的H.264封装为UDP并发送至组播地址。

ffmpeg -f vfwcap -i 0 -vcodec libx264 encoded.h264 -f h264 udp://127.0.0.1:6666
       我这里是用自己的电脑往自己的电脑上发送,测试用,所以地址必须是:127.0.0.1。后面的6666是端口号,自己设置,只要和接收端保持一致即可。



       考虑到提高编码速度,可以添加-preset:v ultrafas和-tune:v zerolatency两个选项。如下所示:

ffmpeg - f vfwcap - i 0 - vcodec libx264 encoded.h264 -preset:v ultrafast -tune:v zerolatency -f h264 udp ://127.0.0.1:6666
       高分辨率的情况下,UDP传输会有丢包的现象。为了避免这种情况,可以添加参数-s(eg:-s 320x240)调整分辨率。


       同理,可以将H.264封装为RTP并发送至组播地址:

ffmpeg -f vfwcap -i 0 -vcodec libx264 encoded.h264 -preset:v ultrafast -tune:v zerolatency -f rtp rtp://127.0.0.1:6666 >test.sdp
       也可以把H.264发送至RTMP服务器:
ffmpeg - f vfwcap - i 0 - vcodec libx264 encoded.h264 -preset:v ultrafast -tune:v zerolatency -f flv rtmp ://localhost/oflaDemo/livestream  

       

      至此,发端的全部代码如下:

#include <stdio.h>
#include <windows.h>
int main( )
{
	char* encoded = "ffmpeg -f vfwcap -i 0 -vcodec libx264 encoded.h264 -f h264 udp://127.0.0.1:6666 ";
	WinExec(encoded, SW_SHOW);
	return 0;
}


2.接收

       接收端要实现的功能是解码和播放。在这里,我们只需要用ffplay打开传输过来的H.264文件,在打开的过程中,ffplay.exe文件会自动将H.264解码进行播放。只要udp的端口保持一致即可。

       命令如下:

ffplay -f h264 -analyzeduration 100000 -max_delay 100000 -fflags nobuffer udp://127.0.0.1:6666

       在VS工程里的全部代码:

#include <stdio.h>
#include <windows.h>
int main()
{
	char* play = "ffplay -f h264 -analyzeduration 100000 -max_delay 100000 -fflags nobuffer udp://127.0.0.1:6666";
	WinExec(play, SW_SHOW);
	return 0;
}


3.测试

       首先运行发端的代码:


       如上图,显示正在编码。出现real-time buffer xx% full ! frame dropped ! 这种提示很正常,这是因为我们是实时编码,不确定编码什么时候结束。这里有个问题,就是在编码的过程中,无法再令摄像头显示,增加一个线程也是失败,我想可能是因为编码的过程中,摄像头其实是打开的,已经被占用,所以无法再显示。

       运行发端代码后,在另一个工程里运行收端代码:



    

       在发端的工程目录下,我们找到保存在本地H.264文件,用VLC media player播放,可以与收端播放的视频做比较。

       到这里,用ffmpeg调用摄像头,编码、发送、解码、播放的全部过程就结束了,其内部的具体代码流程以后要慢慢的弄清楚。