WebRTC使用流程文述

WebRTC使用流程文述

WebRtc使用时需要先搭建两个服务器一个是信令服务器,一个是ICE服务器,搭建方法请见此博客
https://blog.csdn.net/u011077027/article/details/86225524

1,每个客户端到服务器的链路路径称之为SDP

2,WebRTC拿到每个客户端的SDP后,通过webRtc的算法算出每个客户端之间的最短路径,从而让他自己实现p2p打洞连接

3,首先要搭建服务器端,一个是信令服务器,也就是房间服务器,用于SDP交换;一个是ICE服务器,也就是打洞服务器,交换内网最近的路由

4,可以在客户端也就是android端搭建一个WebSocketManager,用于房间服务器的连接,另一个是PeerConnectionManager,用于打洞服务器连接,再用一个WebRtcManager用于管理它两

5,在WebRtc中写一个connect方法用于链接房间服务器,调用WebSocketManager的connect方法,调用时传递socket地址进去

6,在WebSocketManager的connect方法,通过new WebSocketClient(uri)实例化连接客户端,并在onOpen方法中去做连接好后的一些事情,比如跳转到视频通话页面

mWebSocketClient = new WebSocketClient(uri) {
	@Override
	public void onOpen(ServerHandshake handshakedata) {
		//连接好房间服务器后做的事情,跳转到聊天页面,加入房间服务器
	}
}

7,在WebSocketManager方法中写一个joinRoom的方法

public void joinRoom(String roomId) {
	//1,组装一个地址ID信息的json
	//发送出去
	mWebSocketClient.send();
}

8,服务器返回的几种参数的意思

_join //加入房间服务器
_peers //房间服务器加入成功
_now_peer //多了一个人
_offer //主动发起,请求视频通话
_ice_candidate //SDP交换
_answer //被叫方 同意或拒绝请求

9,在WebSocket的构造方法中初始化PeerConnectionManager,当发起连接后得到服务器同意连接响应后,
我们调用PeerConnectionManager的joinToRoom的方法

public void joinToRoom(WebSocketManager javaWebSocket, boolean isVideoEnable, String myID) {
	//建立本地预览,建立线程池
	executor.execute(new Runnable() {
		@Override
		public void run() {
			//创建工厂
		}
	})
}

10,使用WebRTC自带库来处理音频源和视频源

private PeerConnectionFactory creatConnectionFactory() {
	//视频编码 视频解码
	//音频编码 音频解码
	VideoEncoderFactory encodeFactory = new DefaultVideoEncoderFactory(
		rootEglBase.getEglBaseContext(), true, true);
	VideoDecoderFactory decoderFactory = new DefaultVideoDecoferFactory(
		rootFglBase.getEglBaseContext());
	//初始化
	peerConnectionFactory.initialize(PeerConnection, InitializationOption.builder(context).
		creatInitializationOptions());
	//设置参数
	PeerConnectionFactory.option options = new PeerConnectionFactory.Options();
	
	PeerConnectionFactory peerConnectionFactory = PeerConnectionFactory.builder().setOptions(options).
		setAudioPericeModule(JavaAudioDeviceModule.builder(context).creatAudioDeviceMoudle().
		setVideoDecoderFactory(decoderFactory).
		setViodeEncoderFactory(encoderFactory).creatPeerConnectionFactory());
	
	return peerConnectionFactory;
}

11, 在run方法内主要做这么几件事

//webrtc 链接工厂
//添加视频流 音频流
//完成传输层的业务,比方处理有人进来了,出去了之类的
//给每个人发送链接请求
//p2p链接

12,run方法实现

//创建工厂
factory = creatConnectionFactory();
//添加一个总流
//音频是数据源,创建一个音频轨道,新建一个类来管理音频创建

13,首先创建一个MediaConstras,这是一个集合,每个集合对应的是key value

private MediaConstraints creatAudioConstraints() {
	MediaConstraints audioConstraints = new MediaConstraints();
	//设置音频各种参数
	audioConstrains.mandatory.add(new MediaConstraints.keyValuePair(/*四种参数*/,true));

	//四种参数
	//googEchoCancelLation 回音消除
	private static final String AUDIO_ECHO_CANCELLATION_CONSTRATNT = "googEchoCancelLation";
	//googNoiseSuppression 噪音抑制
	AUDIO_NOISE_SUPPRESSION_CONSTRAINT
	//googAutoGainControl 自动增益控制
	AUDIO_AUTO_GAIN_CONTROL_CONTRAINT
	//googAlighPassFilter 高通滤波器
	AUDIO_HIGH_PASS_FILTER_CONTRAINT
}

14, 再回到run方法

//添加一个总流
AudioSource audioSource = factory.createAudioSource(creatAudioConstraints());
//音频是数据源,创建一个音频轨道
AudioTrack audioTrack = factory.creatAudioTrack("ARDAMSa0", audioSource);
//音频轨道创建成功,成功设置音频轨道的数据源
mediaStream.addTrack(audioTrack);

15, 创建视频源

//创建视频源,也就是Camera
VideoCapturer videoCapture;
//判断一下手机是否支持Camera2
if (Camera2Enumrator.isSupported(context)) {
	//Camera2 大于21就支持
	Camera2Enumerator enumerator = new Camera2Enumerator(context);
	//前置摄像头的捕获,没有就直接用后置
	videoCapture = createCameraCapture(enumerator);
} else {
	Camera1Enumrator enumerator = new Camera1Enumerator(context);
	videoCapture = createCameraCapture(enumerator);
}

16,创建视频轨

//数据源
VideoSource videoSource = factory.createVideoSource(videoCapturer.isScreencast());

//如果用户打开视频轨道
if (videoEnable) {
	//视频源,摄像投捕获设备
	VideoCapturer viodeoCapturer = creatVideoCapture();
	//创建预览surface
	SurfaceTextureHelper surfaceTextureHelp = SurfaceTextureHelper,creat("catureThread",
		rootEglBase.getEglBaseContext());
	//摄像头的数据和videoSource进行绑定
	viodeoCapturer.initialize(surfaceTextureHelp, context, videoSource.getCaptureObserver())
	//设置预览窗口大小
	viodeoCapturer.startCapture(320, 240, 10);
	//videoSource和videoTrack进行关联
	VideoTrack videoTrack = factory.createVideoTrack("ARDAMSv0", videoSource);
	//添加视频轨
	mediaStream.addTrack(videoTrack);
}

17,在ChatRoomActivity中新建方法onSetLocalStream

public void onSetLoacalStream(MediaStream stream, String useID) {
	//总流 音频流 视频流
	if (stream.videoTracks.size() > 0) {
		localVideoTrack = stream.videoTracks.get(0);
	}
}

18, //如果有多人聊天要动态变化添加SurfaceView

runOnUiThread(new Runnable() {
	@Override
	public void run() {
		addView(userID, stream);
	}
});

19, 新建一个方法addView专门处理添加SurfaceView逻辑

private void addView(String useID, MediaStream stream) {
	//不用surfaceView 用webrtc给我们提供的surfaceRender
	SurfaceViewRenderer surfaceViewRenderer = new SurfaceViewRenderer(this);
	//初始化SurfaceViewRenderer
	surfaceViewRenderer.init(rootEglBase.getEglBaseContext(), null);
	//设置缩放模式
	surfaceViewRenderer.setScalingType(RendererCommon.ScalingType.SCALE_ASPECT_FIT);
	//设置屏幕
	surfaceViewRenderer.setMirror(true);
	... ...
}

20, //关联数据源

	if (stream.videoTrack.size()>0) {
		stream.videoTrack.get(0).addsink(surfaceViewRenderer);
	}

21, //计算布局

videoViews.put(userID, surfaceViewRenderer);
persons.add(userID);
int size = videoView.Size();
for (int i = 0; i < size; i++) {
	//设置surfaceViewRenderer的layoutParams
	render1.setLayoutParams(layoutParams);
}

22, 当我们加入到一个有人的房间,到WebSocketManager的handleJoinRoom(Map map)中,创建peerConnection

PeerConnection.RTCConfiguration rtcConfiguration = new PeerConnection.RTCConfiguration(ICEServers);

return factory.creatPeerConnection(rtcConfiguration, new ICEObserver());

23, 新建一个ICEObserver

private class ICEObserver implements PeerConnection.Observer{
	
	@Override
	public void onSignalingChange(PeerConnection.SignalingState){
		//当网络发生变换会调用此方法
	}
}

24,这个链接的每个人都会创建一个PeerConnection

connectionPeerPic.put(str, peer);

25,这是建立了一个链接,但是是一个空的链接,没有初始化

creatPeerConnections();
//给房间服务器的其他人发送一个offer
creatOffer();

26, 我们只需在本地做这两件事就好,其他的WebRTC会帮我们完成

//设置本地SDP
pc.setLoacalDescription();
//设置远端的SDP
pc.setRemoteDescription();

26,接下来进行两个比较重要的环节,一个是进行SDP交换,一个是ICE交换,也就是打洞

SDP交换过程

1,首先offer方通过new RTCPeerConnection(config)建立PeerConnection

2, offer方通过creatOffer生成sessionDescription,设置localDescription,并通过信令服务器发送给Answer

3,Answer方收到offer,发现并没有与之对应的peerConnection,新建peerConnection,并设置remoteDecription

4,Answer方通过creatAnswer生成sessionDescription,设置localDescription,并通过信令服务器发送answer

5, offer方收到answer,设置remoteDescription

6,SDP交换结束

ICE交换流程

ICE交换也就是打洞的过程,它是指P2P直接通信;使用STUN服务器实现突破NAT的P2P通信;使TURN中继服务器实现突破防火墙的中继通信。

1,双方在new RTCPeerConnection(config)建立连接后,当网络候选者可用时,会触发icecandidate事件

2,在onIcecandidtate时间处理程序中,将Candidate通过信令服务器发送给对方

3,双方在接受彼此的candidate后,通过addIceCandidate将对方的candidate加入到PeerConnection实例中

结束:

在连接建立前或连接后调用peerConnection.addStream();

方法将本地视频/音频数据流加入到connection中;

当对方接受到视频流的时候会触发addStream事件,使其处理程序中我们可以接受数据流将其显示。

你可能感兴趣的:(音视频,webrtc,android,面试,音视频,通讯)