[*] 流程
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 心跳
|
||||
*/
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<>();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user