[*] 流程

This commit is contained in:
acgist
2023-04-09 14:33:08 +08:00
parent 46f21e3a43
commit 124b161644
19 changed files with 477 additions and 162 deletions

View File

@@ -505,24 +505,26 @@ public final class Taoyao implements ITaoyao {
case "client::shutdown" -> this.clientShutdown(message, body);
case "media::consume" -> this.mediaConsume(message, body);
// case "media::audio::volume" -> this.mediaAudioVolume(message, body);
// case "media::consumer::close" -> this.mediaConsumerClose(message, body);
// case "media::consumer::pause" -> this.mediaConsumerPause(message, body);
case "media::consumer::close" -> this.mediaConsumerClose(message, body);
case "media::consumer::pause" -> this.mediaConsumerPause(message, body);
// case "media::consumer::request::key::frame" -> this.mediaConsumerRequestKeyFrame(message, body);
// case "media::consumer::resume" -> this.mediaConsumerResume(message, body);
case "media::consumer::resume" -> this.mediaConsumerResume(message, body);
// case "media::consumer::set::preferred::layers" -> this.mediaConsumerSetPreferredLayers(message, body);
// case "media::consumer::status" -> this.mediaConsumerStatus(message, body);
// case "media::producer::close" -> this.mediaProducerClose(message, body);
// case "media::producer::pause" -> this.mediaProducerPause(message, body);
// case "media::producer::resume" -> this.mediaProducerResume(message, body);
case "media::producer::close" -> this.mediaProducerClose(message, body);
case "media::producer::pause" -> this.mediaProducerPause(message, body);
case "media::producer::resume" -> this.mediaProducerResume(message, body);
// case "media::producer::video::orientation:change" -> this.mediaVideoOrientationChange(message, body);
case "room::close" -> this.roomClose(message, body);
case "room::enter" -> this.roomEnter(message, body);
// case "room::expel" -> this.roomExpel(message, body);
case "room::expel" -> this.roomExpel(message, body);
case "room::invite" -> this.roomInivte(message, body);
// case "room::leave" -> this.roomLeave(message, body);
case "room::leave" -> this.roomLeave(message, body);
case "session::call" -> this.sessionCall(message, body);
case "session::close" -> this.sessionClose(message, body);
case "session::exchange" -> this.sessionExchange(message, body);
case "session::pause" -> this.sessionPause(message, body);
case "session::resume" -> this.sessionResume(message, body);
default -> Log.d(Taoyao.class.getSimpleName(), "没有适配信令:" + content);
}
}
@@ -590,6 +592,60 @@ public final class Taoyao implements ITaoyao {
room.mediaConsume(message, body);
}
private void mediaConsumerClose(Message message, Map<String, Object> body) {
final String roomId = MapUtils.get(body, "roomId");
final Room room = this.rooms.get(roomId);
if(room == null) {
return;
}
room.mediaConsumerClose(body);
}
private void mediaConsumerPause(Message message, Map<String, Object> body) {
final String roomId = MapUtils.get(body, "roomId");
final Room room = this.rooms.get(roomId);
if(room == null) {
return;
}
room.mediaConsumerPause(body);
}
private void mediaConsumerResume(Message message, Map<String, Object> body) {
final String roomId = MapUtils.get(body, "roomId");
final Room room = this.rooms.get(roomId);
if(room == null) {
return;
}
room.mediaConsumerResume(body);
}
private void mediaProducerClose(Message message, Map<String, Object> body) {
final String roomId = MapUtils.get(body, "roomId");
final Room room = this.rooms.get(roomId);
if(room == null) {
return;
}
room.mediaProducerClose(body);
}
private void mediaProducerPause(Message message, Map<String, Object> body) {
final String roomId = MapUtils.get(body, "roomId");
final Room room = this.rooms.get(roomId);
if(room == null) {
return;
}
room.mediaProducerPause(body);
}
private void mediaProducerResume(Message message, Map<String, Object> body) {
final String roomId = MapUtils.get(body, "roomId");
final Room room = this.rooms.get(roomId);
if(room == null) {
return;
}
room.mediaProducerResume(body);
}
private void roomClose(Message message, Map<String, Object> body) {
final String roomId = MapUtils.get(body, "roomId");
final Room room = this.rooms.remove(roomId);
@@ -608,12 +664,6 @@ public final class Taoyao implements ITaoyao {
room.newRemoteClient(body);
}
private void roomInivte(Message message, Map<String, Object> body) {
final String roomId = MapUtils.get(body, "roomId");
final String password = MapUtils.get(body, "password");
this.roomEnter(roomId, password);
}
public Room roomEnter(String roomId, String password) {
final Resources resources = this.context.getResources();
final Room room = this.rooms.computeIfAbsent(
@@ -621,7 +671,7 @@ public final class Taoyao implements ITaoyao {
key -> new Room(
this.name, this.clientId,
key, password,
this.mainHandler, this,
this, this.mainHandler,
resources.getBoolean(R.bool.dataConsume),
resources.getBoolean(R.bool.audioConsume),
resources.getBoolean(R.bool.videoConsume),
@@ -630,22 +680,66 @@ public final class Taoyao implements ITaoyao {
resources.getBoolean(R.bool.videoProduce)
)
);
room.enter();
room.mediaProduce();
return room;
final boolean success = room.enter();
if(success) {
room.mediaProduce();
return room;
} else {
this.rooms.remove(roomId);
return null;
}
}
private void roomExpel(Message message, Map<String, Object> body) {
final String roomId = MapUtils.get(body, "roomId");
this.roomLeave(roomId);
}
private void roomInivte(Message message, Map<String, Object> body) {
final String roomId = MapUtils.get(body, "roomId");
final String password = MapUtils.get(body, "password");
this.roomEnter(roomId, password);
}
public void roomLeave(String roomId) {
final Room room = this.rooms.remove(roomId);
if(room == null) {
return;
}
this.push(this.buildMessage(
"room::leave",
"roomId", roomId
));
room.close();
}
private void roomLeave(Message message, Map<String, Object> body) {
final String roomId = MapUtils.get(body, "roomId");
final String clientId = MapUtils.get(body, "clientId");
final Room room = this.rooms.get(roomId);
if(room == null) {
return;
}
room.closeRemoteClient(clientId);
}
private void sessionCall(Message message, Map<String, Object> body) {
final String name = MapUtils.get(body, "name");
final String clientId = MapUtils.get(body, "clientId");
final String sessionId = MapUtils.get(body, "sessionId");
final SessionClient sessionClient = new SessionClient(sessionId, name, clientId, this.mainHandler, this);
final SessionClient sessionClient = new SessionClient(sessionId, name, clientId, this, this.mainHandler);
this.sessionClients.put(sessionId, sessionClient);
sessionClient.init();
sessionClient.offer();
}
private void sessionClose(Message message, Map<String, Object> body) {
final String sessionId = MapUtils.get(body, "sessionId");
final SessionClient sessionClient = this.sessionClients.remove(sessionId);
if(sessionClient == null) {
return;
}
sessionClient.close();
}
private void sessionExchange(Message message, Map<String, Object> body) {
@@ -658,6 +752,24 @@ public final class Taoyao implements ITaoyao {
sessionClient.exchange(message, body);
}
private void sessionPause(Message message, Map<String, Object> body) {
final String sessionId = MapUtils.get(body, "sessionId");
final SessionClient sessionClient = this.sessionClients.get(sessionId);
if(sessionClient == null) {
return;
}
sessionClient.pause();
}
private void sessionResume(Message message, Map<String, Object> body) {
final String sessionId = MapUtils.get(body, "sessionId");
final SessionClient sessionClient = this.sessionClients.get(sessionId);
if(sessionClient == null) {
return;
}
sessionClient.resume();
}
/**
* 心跳
*/

View File

@@ -278,6 +278,7 @@ public final class MediaManager {
/**
* 关闭一个终端
* 最后一个终端关闭时,释放所有资源。
* 注意:所有本地媒体关闭调用,不要直接关闭本地媒体流。
*
* @return 剩余终端数量
*/
@@ -298,7 +299,7 @@ public final class MediaManager {
public RecordClient startRecord(String path, String filename) {
synchronized (this) {
this.recordClient = new RecordClient(path, filename, this.handler, this.taoyao);
this.recordClient = new RecordClient(path, filename, this.taoyao, this.handler);
this.recordClient.start();
return this.recordClient;
}

View File

@@ -20,7 +20,7 @@ import java.io.Closeable;
*
* @author acgist
*/
public abstract class Client implements Closeable {
public abstract class Client extends CloseableClient {
/**
* 终端名称
@@ -30,29 +30,15 @@ public abstract class Client implements Closeable {
* 终端ID
*/
protected final String clientId;
/**
* Handler
*/
protected final Handler handler;
/**
* 信令通道
*/
protected final ITaoyao taoyao;
/**
* 媒体服务
*/
protected final MediaManager mediaManager;
/**
* 视频预览
*/
protected SurfaceViewRenderer surfaceViewRenderer;
public Client(String name, String clientId, Handler handler, ITaoyao taoyao) {
public Client(String name, String clientId, ITaoyao taoyao, Handler handler) {
super(taoyao, handler);
this.name = name;
this.clientId = clientId;
this.taoyao = taoyao;
this.handler = handler;
this.mediaManager = MediaManager.getInstance();
}
/**
@@ -86,8 +72,15 @@ public abstract class Client implements Closeable {
}
}
public void pause() {
}
public void resume() {
}
@Override
public void close() {
super.close();
Log.i(this.getClass().getSimpleName(), "关闭终端:" + this.clientId);
if(this.surfaceViewRenderer != null) {
this.surfaceViewRenderer.release();

View File

@@ -0,0 +1,61 @@
package com.acgist.taoyao.media.client;
import android.os.Handler;
import com.acgist.taoyao.media.MediaManager;
import com.acgist.taoyao.media.signal.ITaoyao;
import org.webrtc.PeerConnectionFactory;
import java.io.Closeable;
/**
* 需要关闭终端
*
* @author acgist
*/
public abstract class CloseableClient implements Closeable {
/**
* 是否加载
* 防止重复加载
*/
protected volatile boolean init;
/**
* 是否关闭
*/
protected volatile boolean close;
/**
* 信令通道
*/
protected final ITaoyao taoyao;
/**
* Handler
*/
protected final Handler handler;
/**
* 媒体服务
*/
protected final MediaManager mediaManager;
public CloseableClient(ITaoyao taoyao, Handler handler) {
this.init = false;
this.close = false;
this.taoyao = taoyao;
this.handler = handler;
this.mediaManager = MediaManager.getInstance();
}
/**
* 加载
*/
protected void init() {
this.init = true;
}
@Override
public void close() {
this.close = true;
}
}

View File

@@ -20,8 +20,8 @@ public class LocalClient extends RoomClient {
*/
protected MediaStream mediaStream;
public LocalClient(String name, String clientId, Handler handler, ITaoyao taoyao) {
super(name, clientId, handler, taoyao);
public LocalClient(String name, String clientId, ITaoyao taoyao, Handler handler) {
super(name, clientId, taoyao, handler);
}
public MediaStream getMediaStream() {
@@ -58,9 +58,6 @@ public class LocalClient extends RoomClient {
@Override
public void close() {
super.close();
if(this.mediaStream != null) {
this.mediaStream.dispose();
}
}
}

View File

@@ -35,10 +35,6 @@ import java.util.concurrent.Executors;
*/
public class RecordClient extends Client {
/**
* 是否正在录像
*/
private volatile boolean active;
/**
* 音频准备录制
*/
@@ -92,8 +88,8 @@ public class RecordClient extends Client {
*/
private final ExecutorService executorService;
public RecordClient(String path, String filename, Handler handler, ITaoyao taoyao) {
super("本地录像", "LocalRecordClient", handler, taoyao);
public RecordClient(String path, String filename, ITaoyao taoyao, Handler handler) {
super("本地录像", "LocalRecordClient", taoyao, handler);
this.filename = filename;
final Path filePath = Paths.get(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath(), path, filename);
final File parentFile = filePath.getParent().toFile();
@@ -105,19 +101,13 @@ public class RecordClient extends Client {
this.executorService = Executors.newFixedThreadPool(2);
}
/**
* @return 是否正在录像
*/
public boolean isActive() {
return this.active;
}
public void start() {
synchronized (this) {
if(this.active) {
if(this.init) {
return;
}
this.active = true;
super.init();
this.mediaManager.newClient(MediaManager.Type.BACK);
this.record(null, null, 1, 1);
}
}
@@ -161,7 +151,7 @@ public class RecordClient extends Client {
int outputIndex;
this.audioCodec.start();
this.audioActive = true;
while (this.active) {
while (!this.close) {
outputIndex = this.audioCodec.dequeueOutputBuffer(info, 1000L * 1000);
if (outputIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
} else if (outputIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
@@ -173,7 +163,7 @@ public class RecordClient extends Client {
this.pts = System.currentTimeMillis();
this.mediaMuxer.start();
this.notifyAll();
} else if (this.active) {
} else if (!this.close) {
try {
this.wait();
} catch (InterruptedException e) {
@@ -208,12 +198,12 @@ public class RecordClient extends Client {
}
public void putAudio(JavaAudioDeviceModule.AudioSamples audioSamples) {
if(this.active && this.audioActive) {
if(!this.close && this.audioActive) {
}
}
public void putVideo(VideoFrame videoFrame) {
if (this.active && this.videoActive) {
if (!this.close && this.videoActive) {
this.executorService.submit(() -> {
// TextureBufferImpl
// videoFrame.retain();
@@ -281,7 +271,7 @@ public class RecordClient extends Client {
int outputIndex;
this.videoCodec.start();
this.videoActive = true;
while (this.active) {
while (!this.close) {
outputIndex = this.videoCodec.dequeueOutputBuffer(info, 1000L * 1000);
if (outputIndex == MediaCodec.INFO_TRY_AGAIN_LATER) {
} else if (outputIndex == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
@@ -293,7 +283,7 @@ public class RecordClient extends Client {
this.pts = System.currentTimeMillis();
this.mediaMuxer.start();
this.notifyAll();
} else if (this.active) {
} else if (!this.close) {
try {
this.wait();
} catch (InterruptedException e) {
@@ -346,28 +336,25 @@ public class RecordClient extends Client {
}
}
private void stop() {
Log.i(RecordClient.class.getSimpleName(), "结束录制:" + this.filepath);
this.active = false;
if (audioThread != null) {
this.audioThread.quitSafely();
}
if (this.videoThread != null) {
this.videoThread.quitSafely();
}
if(this.executorService != null) {
this.executorService.shutdown();
}
synchronized (this) {
this.notifyAll();
}
}
@Override
public void close() {
synchronized (this) {
if(this.close) {
return;
}
super.close();
this.stop();
Log.i(RecordClient.class.getSimpleName(), "结束录制:" + this.filepath);
if (audioThread != null) {
this.audioThread.quitSafely();
}
if (this.videoThread != null) {
this.videoThread.quitSafely();
}
if(this.executorService != null) {
this.executorService.shutdown();
}
this.notifyAll();
this.mediaManager.closeClient();
}
}

View File

@@ -25,8 +25,8 @@ public class RemoteClient extends RoomClient {
*/
protected final Map<String, MediaStreamTrack> tracks;
public RemoteClient(String name, String clientId, Handler handler, ITaoyao taoyao) {
super(name, clientId, handler, taoyao);
public RemoteClient(String name, String clientId, ITaoyao taoyao, Handler handler) {
super(name, clientId, taoyao, handler);
this.tracks = new ConcurrentHashMap<>();
}

View File

@@ -30,14 +30,12 @@ import java.util.concurrent.ConcurrentHashMap;
*
* @author acgist
*/
public class Room implements Closeable, RouterCallback {
public class Room extends CloseableClient implements RouterCallback {
private final String name;
private final String clientId;
private final String roomId;
private final String password;
private final Handler handler;
private final ITaoyao taoyao;
private final boolean dataConsume;
private final boolean audioConsume;
private final boolean videoConsume;
@@ -45,8 +43,6 @@ public class Room implements Closeable, RouterCallback {
private final boolean audioProduce;
private final boolean videoProduce;
private final long nativeRoomPointer;
private final MediaManager mediaManager;
private volatile boolean enter;
private LocalClient localClient;
private Map<String, RemoteClient> remoteClients;
private PeerConnection.RTCConfiguration rtcConfiguration;
@@ -56,16 +52,15 @@ public class Room implements Closeable, RouterCallback {
public Room(
String name, String clientId,
String roomId, String password,
Handler handler, ITaoyao taoyao,
ITaoyao taoyao, Handler handler,
boolean dataConsume, boolean audioConsume, boolean videoConsume,
boolean dataProduce, boolean audioProduce, boolean videoProduce
) {
super(taoyao, handler);
this.name = name;
this.clientId = clientId;
this.roomId = roomId;
this.password = password;
this.handler = handler;
this.taoyao = taoyao;
this.dataConsume = dataConsume;
this.audioConsume = audioConsume;
this.videoConsume = videoConsume;
@@ -73,31 +68,33 @@ public class Room implements Closeable, RouterCallback {
this.audioProduce = audioProduce;
this.videoProduce = videoProduce;
this.nativeRoomPointer = this.nativeNewRoom(roomId, this);
this.mediaManager = MediaManager.getInstance();
this.remoteClients = new ConcurrentHashMap<>();
this.enter = false;
}
public synchronized void enter() {
if (this.enter) {
return;
public boolean enter() {
synchronized (this) {
if (this.init) {
return true;
}
super.init();
this.peerConnectionFactory = this.mediaManager.newClient(MediaManager.Type.BACK);
this.localClient = new LocalClient(this.name, this.clientId, this.taoyao, this.handler);
this.localClient.setMediaStream(this.mediaManager.getMediaStream());
// STUN | TURN
final List<PeerConnection.IceServer> iceServers = new ArrayList<>();
// TODO读取配置
final PeerConnection.IceServer iceServer = PeerConnection.IceServer.builder("stun:stun1.l.google.com:19302").createIceServer();
iceServers.add(iceServer);
this.rtcConfiguration = new PeerConnection.RTCConfiguration(iceServers);
final Message response = this.taoyao.request(this.taoyao.buildMessage("media::router::rtp::capabilities", "roomId", this.roomId));
if(response == null) {
this.close();
return false;
}
final Object rtpCapabilities = MapUtils.get(response.body(), "rtpCapabilities");
this.nativeEnter(this.nativeRoomPointer, JSONUtils.toJSON(rtpCapabilities), this.peerConnectionFactory.getNativePeerConnectionFactory(), this.rtcConfiguration);
return true;
}
final Message response = this.taoyao.request(this.taoyao.buildMessage("media::router::rtp::capabilities", "roomId", this.roomId));
if (response == null) {
Log.w(Room.class.getSimpleName(), "获取通道能力失败");
return;
}
this.localClient = new LocalClient(this.name, this.clientId, this.handler, this.taoyao);
this.localClient.setMediaStream(this.mediaManager.getMediaStream());
// STUN | TURN
final List<PeerConnection.IceServer> iceServers = new ArrayList<>();
// TODO读取配置
final PeerConnection.IceServer iceServer = PeerConnection.IceServer.builder("stun:stun1.l.google.com:19302").createIceServer();
iceServers.add(iceServer);
this.rtcConfiguration = new PeerConnection.RTCConfiguration(iceServers);
this.peerConnectionFactory = this.mediaManager.newClient(MediaManager.Type.BACK);
final Object rtpCapabilities = MapUtils.get(response.body(), "rtpCapabilities");
this.nativeEnter(this.nativeRoomPointer, JSONUtils.toJSON(rtpCapabilities), this.peerConnectionFactory.getNativePeerConnectionFactory(), this.rtcConfiguration);
}
public void mediaProduce() {
@@ -162,7 +159,7 @@ public class Room implements Closeable, RouterCallback {
final String clientId = MapUtils.get(body, "clientId");
final Map<String, Object> status = MapUtils.get(body, "status");
final String name = MapUtils.get(status, "name");
final RemoteClient remoteClient = new RemoteClient(name, clientId, this.handler, this.taoyao);
final RemoteClient remoteClient = new RemoteClient(name, clientId, this.taoyao, this.handler);
final RemoteClient old = this.remoteClients.put(clientId, remoteClient);
if(old != null) {
// 关闭旧的资源
@@ -183,11 +180,18 @@ public class Room implements Closeable, RouterCallback {
@Override
public void close() {
Log.i(Room.class.getSimpleName(), "关闭房间:" + this.roomId);
this.localClient.close();
this.remoteClients.values().forEach(v -> this.closeRemoteClient(v.clientId));
this.mediaManager.closeClient();
this.nativeCloseRoom(this.nativeRoomPointer);
synchronized (this) {
if(this.close) {
return;
}
Log.i(Room.class.getSimpleName(), "关闭房间:" + this.roomId);
super.close();
this.nativeCloseRoom(this.nativeRoomPointer);
this.remoteClients.values().forEach(v -> this.closeRemoteClient(v.clientId));
this.remoteClients.clear();
this.localClient.close();
this.mediaManager.closeClient();
}
}
public void mediaConsumerClose(String consumerId) {
@@ -198,6 +202,10 @@ public class Room implements Closeable, RouterCallback {
));
}
public void mediaConsumerClose(Map<String, Object> body) {
}
public void mediaConsumerPause(String consumerId) {
this.taoyao.push(this.taoyao.buildMessage(
"media::consumer::pause",
@@ -206,6 +214,10 @@ public class Room implements Closeable, RouterCallback {
));
}
public void mediaConsumerPause(Map<String, Object> body) {
}
public void mediaConsumerResume(String consumerId) {
this.taoyao.push(this.taoyao.buildMessage(
"media::consumer::resume",
@@ -214,6 +226,10 @@ public class Room implements Closeable, RouterCallback {
));
}
public void mediaConsumerResume(Map<String, Object> body) {
}
public void mediaProducerClose(String producerId) {
this.taoyao.push(this.taoyao.buildMessage(
"media::producer::close",
@@ -222,6 +238,10 @@ public class Room implements Closeable, RouterCallback {
));
}
public void mediaProducerClose(Map<String, Object> body) {
}
public void mediaProducerPause(String producerId) {
this.taoyao.push(this.taoyao.buildMessage(
"media::producer::pause",
@@ -230,6 +250,10 @@ public class Room implements Closeable, RouterCallback {
));
}
public void mediaProducerPause(Map<String, Object> body) {
}
public void mediaProducerResume(String producerId) {
this.taoyao.push(this.taoyao.buildMessage(
"media::producer::resume",
@@ -238,6 +262,10 @@ public class Room implements Closeable, RouterCallback {
));
}
public void mediaProducerResume(Map<String, Object> body) {
}
@Override
public void enterCallback(String rtpCapabilities, String sctpCapabilities) {
this.taoyao.request(this.taoyao.buildMessage(
@@ -247,7 +275,6 @@ public class Room implements Closeable, RouterCallback {
"rtpCapabilities", rtpCapabilities,
"sctpCapabilities", sctpCapabilities
));
this.enter = true;
}
@Override

View File

@@ -14,8 +14,8 @@ import org.webrtc.MediaStreamTrack;
*/
public class RoomClient extends Client {
public RoomClient(String name, String clientId, Handler handler, ITaoyao taoyao) {
super(name, clientId, handler, taoyao);
public RoomClient(String name, String clientId, ITaoyao taoyao, Handler handler) {
super(name, clientId, taoyao, handler);
}
@Override

View File

@@ -1,7 +1,6 @@
package com.acgist.taoyao.media.client;
import android.os.Handler;
import android.se.omapi.Session;
import android.util.Log;
import com.acgist.taoyao.boot.model.Message;
@@ -23,7 +22,6 @@ import org.webrtc.VideoTrack;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* P2P终端
@@ -64,24 +62,31 @@ public class SessionClient extends Client {
*/
private PeerConnectionFactory peerConnectionFactory;
public SessionClient(String sessionId, String name, String clientId, Handler handler, ITaoyao taoyao) {
super(name, clientId, handler, taoyao);
public SessionClient(String sessionId, String name, String clientId, ITaoyao taoyao, Handler handler) {
super(name, clientId, taoyao, handler);
this.sessionId = sessionId;
}
@Override
public void init() {
this.peerConnectionFactory = this.mediaManager.newClient(MediaManager.Type.BACK);
// STUN | TURN
final List<PeerConnection.IceServer> iceServers = new ArrayList<>();
// TODO读取配置
final PeerConnection.IceServer iceServer = PeerConnection.IceServer.builder("stun:stun1.l.google.com:19302").createIceServer();
iceServers.add(iceServer);
final PeerConnection.RTCConfiguration configuration = new PeerConnection.RTCConfiguration(iceServers);
this.observer = this.observer();
this.mediaStream = this.mediaManager.getMediaStream();
this.sdpObserver = this.sdpObserver();
this.peerConnection = this.peerConnectionFactory.createPeerConnection(configuration, this.observer);
this.peerConnection.addStream(this.mediaStream);
synchronized (this) {
if(this.init) {
return;
}
super.init();
this.peerConnectionFactory = this.mediaManager.newClient(MediaManager.Type.BACK);
// STUN | TURN
final List<PeerConnection.IceServer> iceServers = new ArrayList<>();
// TODO读取配置
final PeerConnection.IceServer iceServer = PeerConnection.IceServer.builder("stun:stun1.l.google.com:19302").createIceServer();
iceServers.add(iceServer);
final PeerConnection.RTCConfiguration configuration = new PeerConnection.RTCConfiguration(iceServers);
this.observer = this.observer();
this.mediaStream = this.mediaManager.getMediaStream();
this.sdpObserver = this.sdpObserver();
this.peerConnection = this.peerConnectionFactory.createPeerConnection(configuration, this.observer);
this.peerConnection.addStream(this.mediaStream);
}
}
public void exchange(Message message, Map<String, Object> body) {
@@ -153,6 +158,27 @@ public class SessionClient extends Client {
}
}
@Override
public void playAudio() {
super.playAudio();
if(this.remoteMediaStream == null) {
return;
}
this.remoteMediaStream.audioTracks.forEach(v -> v.setEnabled(true));
}
@Override
public void pauseAudio() {
super.pauseAudio();
this.remoteMediaStream.audioTracks.forEach(v -> v.setEnabled(false));
}
@Override
public void resumeAudio() {
super.resumeAudio();
this.remoteMediaStream.audioTracks.forEach(v -> v.setEnabled(true));
}
@Override
public void playVideo() {
super.playVideo();
@@ -168,21 +194,41 @@ public class SessionClient extends Client {
}
@Override
public void playAudio() {
super.playAudio();
if(this.remoteMediaStream == null) {
return;
}
this.remoteMediaStream.audioTracks.forEach(v -> v.setEnabled(true));
public void pauseVideo() {
super.pauseVideo();
this.mediaStream.videoTracks.forEach(v -> v.setEnabled(false));
}
@Override
public void resumeVideo() {
super.resumeVideo();
this.mediaStream.videoTracks.forEach(v -> v.setEnabled(true));
}
@Override
public void pause() {
super.pause();
this.pauseAudio();
this.pauseVideo();
}
@Override
public void resume() {
super.resume();
this.resumeAudio();
this.resumeVideo();
}
@Override
public void close() {
super.close();
// 本地资源释放不要直接关闭MediaStream共享资源
this.mediaManager.closeClient();
// 远程资源释放
this.remoteMediaStream.dispose();
synchronized (this) {
if(this.close) {
return;
}
super.close();
this.remoteMediaStream.dispose();
this.mediaManager.closeClient();
}
}
/**