Android WebRTC 音视频开发总结(一)

接触Android WebRTC有一段时间了,现在将研究过程中的一些经验和知识总结出来,希望大家有所帮助。本章主要介绍下面四点:

一、WebRTC是什么?

WebRTC是Google提供的一个跨平台的音视频开源解决方案,旨在使其成为音视频通讯的标准。其实在Google将WebRTC开源之前,微软和苹果各自的通讯产品已占用很大市场份额(如Skype),估计Google也是为了快速扩大市场,所以选择将他开源。

 

二、WEBRTC代码如何获取和编译。

1、环境准备:对刚入门的人来说编译WEBRTC很头疼,特别是对没接触过linux的人来说,虽然网上有很多资料,但是实际编译过程中总会出现这样或那样的错误,很多错误都不知所措。其实编译不过的主要原因就是有些文件下载不下来(因为国家防火墙限制),所以这里给出一个编译WebRTC的最简单的解决方案:

A、买一个付费的VPN账号。

B、参考:http://www.webrtc.org/reference/getting-started,很详细,看仔细。

这个方案屡试不爽,我已经成功编译过好几次了,如果还有问题可以联系我(andorid开发者来说最好使用ubuntu 64位环境,不要在windows下面搞。)。

 

三、运行WebRTCDemo

A、安装WebRTC/Trunk/out/WebRTCDemo-debug.apk,他支持点对点视频,在其SETTINGS页签中设置好对方IP,点击MAIN页签中的StartCall即可与对方开始视频通话

 Android WebRTC 音视频开发总结(一)_第1张图片

 

四、WebRTC的工程文件在不同项目如何管理?

因为WebRTC是跨平台的,支持mac,windows,linux,但不同平台下用的工程文件格式不一样,如VisualStudio下是.vcproj,是每个开发平台下手动创建自己的工程文件吗?答案是否定的,他是通过.gyp文件来管理的,说白了.gyp文件相当于是他的工程描述文件,类似JSON格式,不同平台下编译的时候根据.gyp文件产生对应格式的工程文件,如.vcproj。

 

以上,如有不对的地方请指正,下一节介绍Android WebRTC NDK 开发。


Android WebRTC 音视频开发总结(二)

2014-03-04 13:46 by Blacker, 669 阅读, 1 评论, 收藏, 编辑

上节介绍了WebRTC代码编译和WebRTCDemo的运行,这节主要介绍WebRTCDemo的结构,以此来简单了解WebRTC的调用流程。

1、先看WebRTCDemo的代码结构,如下图:

Android WebRTC 音视频开发总结(一)_第2张图片

2WebRTCDemo中音视频管理接口--MediaEngine,包括操作音频和视频的接口,详见MediaEngine的实现。

Android WebRTC 音视频开发总结(一)_第3张图片

 

3、jni实现:细心的读者会发现WebRTCDemo下面有一个jni目录,这是android提供的调用本地代码的方式,即Java Native Call(读者如想详细了解JNI是怎么回事,可以买本书或找些相关资料来看看,这里面涉及到NDK编译,JNI语法)。

MediaEnginenative方法最终都是通过Jni下面的video_engine_jni.cc和video_engine_jni.cc来实现的,这些Jni方法最终就转到WebRTC提供的接口类中去了,即VoiceEngineVideoEngine,顺着这个思路再看源代码就比较容易理解了。 

 

4、如何调试WebRTCDemo中的c++代码?

根据JNI要求,需要用NDK编译WebRTCDemo,不过目前WebRTCDemo是直接调用现成的libwebrtcdemo-jni.so,如果要调试得自己写一个Andorid.mk文件将相关源代码加进来,几乎涉及大部分WebRTC代码,这样工作量有点大,所以放弃了,不知道大家还有没有更好的方式,谢谢指教!

Android WebRTC 音视频开发总结(三)

2014-03-24 15:56 by Blacker, 585 阅读, 5 评论, 收藏, 编辑

前面介绍了WebRTC的基本结构,本节主要介绍WebRTC音视频的实现,通过前面的例子我们知道运行WebRTCDemo即可看到P2P的效果,实际应用中我们不可能让用户自己去里面设置对方的IP和音视频端口,而且即使设置了对方的IP和端口也不一定能运行起来,因为P2P的双方如果不在同一个网段下还需穿透NAT,即打洞,下面介绍两种达到实用效果的方法:

1、增加中转服务器:增加一台公网服务器,客户端先将RTP包发给公网服务器,然后再通过服务器转发给对方,这就不存在打洞的问题了,说到这里有人可能会问,这种做法跟它里面提供的AppRTCDemo有啥区别?其实如果只做一对一视频的话AppRTCDemo可以满足要求,如果要支持多人视频会议则要考虑搭一个中转服务器了。

2、搭建STUN服务器:打洞的原理理解了其实很简单,主要思路就是自己发一个包给STUN服务器,STUN服务器告诉我们自己在公网上的IP和端口,然后将这个公网IP和端口发给对方,对方也是做同样的事情,彼此都得到了对方在共网上的IP和端口后即可开始音视频了,开源STUN代码很多,网上也有很多介绍这方面的问题,有兴趣的可以看下。

实际应用中可能得考虑上面两种方法结合使用,原因如下:

1、P2P方式性能明显优于服务器中转,毕竟手机上受到带宽和硬件性能的限制,效果肯定没有PC好,所以P2P方式更适合用户。

2、在打洞不成功的情况下(有些网络是不能打洞成功的,如进程严格受限的那种路由器),必须使用中转模式。

下一节介绍WEBRTC通信过程。

Android WebRTC 音视频开发总结(四)

2014-03-27 09:50 by Blacker, 581 阅读, 1 评论, 收藏, 编辑

在介绍WebRTC通讯之前我们先来看一个P2P视频聊天包括的主要过程:音视频数据采集->编码->发送->接收->解码->播放。

编码、解码、以及会用到加密、解密、回声消除等针对不同系统处理方式都一样,与平台无关。但像Socket通信涉及到的数据发送、接收不同平台则有不同的处理方式,

如Socket模型,windows里面用的是WSASocket,Linux下用的则是socket,所以他通过模版模式来创建不同类型。具体到代码就是udp_transport.vcproj工程,结构如下:Android WebRTC 音视频开发总结(一)_第4张图片

其中:udp_socket_wrapper.h主要负责Socket相关操作,如Socket创建、启动、端口绑定、停止。

       udp_socket2_windows.h主要负责windows平台上的Socket相关操作,与之对应的就是linux平台上的udp_socket_posix.h

       udp_transport.h主要负责包的发送和接收。

对客户端调用来说主要就是做四件事情:

  1、设置音视频远端地址和端口(包括远端音视频的RTP、RTCP端口和本地接收音视频的RTP、RTCP端口)。

  2、启动音视频数据的发送。

  3、启动音视频数据的接收。

  4、启动音视频数据的播放。

具体代码结构如下:

复制代码
1 public void start() {
2         this.setRemoteIp(WebRTCClient.str_remote_ip);WebRTCClient.str_to);
3         if (audioEnabled) {
4             startVoE();
5         }
6         if (receiveVideo || sendVideo) {
7             startViE();
8         }
9     }
复制代码
复制代码
1 public void startVoE() {
2         check(!voeRunning, "VoE already started");
3         check(voe.startListen(audioChannel) == 0, "Failed StartListen");
4         check(voe.startPlayout(audioChannel) == 0, "VoE start playout failed");
5         check(voe.startSend(audioChannel) == 0, "VoE start send failed");
6         voeRunning = true;
7     }
复制代码
复制代码
 1 public void startViE() {
 2         check(!vieRunning, "ViE already started");
 3 
 4         if (receiveVideo) {
 5             if (viewSelection == context.getResources().getInteger(R.integer.openGl)) {
 6                 svRemote = ViERenderer.CreateRenderer(context, true);
 7             } else if (viewSelection == context.getResources().getInteger(R.integer.surfaceView)) {
 8                 svRemote = ViERenderer.CreateRenderer(context, false);
 9             } else {
10                 externalCodec = new MediaCodecVideoDecoder(context);
11                 svRemote = externalCodec.getView();
12             }
13             if (externalCodec != null) {
14                 check(vie.registerExternalReceiveCodec(videoChannel, VCM_VP8_PAYLOAD_TYPE,
15                         externalCodec, true) == 0, "Failed to register external decoder");
16             } else {
17                 check(vie.addRenderer(videoChannel, svRemote, 0, 0, 0, 1, 1) == 0,
18                         "Failed AddRenderer");
19                 check(vie.startRender(videoChannel) == 0, "Failed StartRender");
20             }
21             check(vie.startReceive(videoChannel) == 0, "Failed StartReceive");
22         }
23         if (sendVideo) {
24             startCamera();
25             check(vie.startSend(videoChannel) == 0, "Failed StartSend");
26         }
27         vieRunning = true;
28     }
复制代码

以上就是WebRTC通讯过程中主要涉及的操作,希望对您所帮助,如有不对之处敬请指教,谢谢!


你可能感兴趣的:(Android WebRTC 音视频开发总结(一))