[*] 进步一点点

This commit is contained in:
acgist
2023-04-07 21:12:25 +08:00
parent 2ae6fbdf0a
commit 9978039c9d
5 changed files with 202 additions and 73 deletions

View File

@@ -5,37 +5,31 @@
#include <iostream> #include <iostream>
#include "jni.h" #include "jni.h"
#include "Log.hpp"
#include "mediasoupclient.hpp"
#include "sdk/android/src/jni/pc/peer_connection.h" #include "sdk/android/src/jni/pc/peer_connection.h"
#include "sdk/android/native_api/jni/scoped_java_ref.h" #include "sdk/android/native_api/jni/scoped_java_ref.h"
#include "Log.hpp"
#include "mediasoupclient.hpp"
namespace acgist { namespace acgist {
class Room { class Room {
public: public:
mediasoupclient::Device *device; mediasoupclient::Device *device;
mediasoupclient::PeerConnection *peerConnection;
mediasoupclient::SendTransport *sendTransport; mediasoupclient::SendTransport *sendTransport;
mediasoupclient::RecvTransport *recvTransport; mediasoupclient::RecvTransport *recvTransport;
mediasoupclient::PeerConnection *peerConnection;
mediasoupclient::SendTransport::Listener *sendListener; mediasoupclient::SendTransport::Listener *sendListener;
mediasoupclient::RecvTransport::Listener *recvListener; mediasoupclient::RecvTransport::Listener *recvListener;
jstring roomId; std::string roomId;
public: public:
/** JNIEnv *env;
* 新建Transport回调 jobject routerCallback;
*/
jmethodID newCallback;
/**
* 房间关闭回调
*/
jmethodID closeCallback;
public: public:
Room(jstring roomId); Room(std::string roomId, JNIEnv *env, jobject routerCallback);
virtual ~Room(); virtual ~Room();
public: public:
void load( void enter(
std::string rtpCapabilities, std::string rtpCapabilities,
webrtc::PeerConnectionFactoryInterface *factory, webrtc::PeerConnectionFactoryInterface *factory,
webrtc::PeerConnectionInterface::RTCConfiguration &rtcConfiguration webrtc::PeerConnectionInterface::RTCConfiguration &rtcConfiguration

View File

@@ -4,18 +4,77 @@ namespace acgist {
class SendListener : public mediasoupclient::SendTransport::Listener { class SendListener : public mediasoupclient::SendTransport::Listener {
public:
Room *room;
JNIEnv *env;
jobject routerCallback;
public:
SendListener(Room *room, JNIEnv *env, jobject routerCallback) {
this->room = room;
this->env = env;
this->routerCallback = routerCallback;
}
public:
std::future<void> OnConnect(mediasoupclient::Transport *transport, const nlohmann::json &dtlsParameters) override { std::future<void> OnConnect(mediasoupclient::Transport *transport, const nlohmann::json &dtlsParameters) override {
jclass jCallbackClazz = this->env->GetObjectClass(this->routerCallback);
jmethodID sendTransportConnectCallback = this->env->GetMethodID(jCallbackClazz, "sendTransportConnectCallback", "(Ljava/lang/String;Ljava/lang/String;)V");
const char *cTransportId = transport->GetId().data();
jstring jTransportId = env->NewStringUTF(cTransportId);
const char *cDtlsParameters = dtlsParameters.dump().data();
jstring jDtlsParameters = env->NewStringUTF(cDtlsParameters);
this->env->CallVoidMethod(
this->routerCallback,
sendTransportConnectCallback,
jTransportId,
jDtlsParameters
);
env->DeleteLocalRef(jTransportId);
env->ReleaseStringUTFChars(jTransportId, cTransportId);
env->DeleteLocalRef(jDtlsParameters);
env->ReleaseStringUTFChars(jDtlsParameters, cDtlsParameters);
env->DeleteLocalRef(jCallbackClazz);
return std::future<void>(); return std::future<void>();
} }
void OnConnectionStateChange(mediasoupclient::Transport *transport, const std::string &connectionState) override { void OnConnectionStateChange(mediasoupclient::Transport *transport, const std::string &connectionState) override {
// 状态变化
} }
std::future<std::string> OnProduce(mediasoupclient::SendTransport *transport, const std::string &kind, nlohmann::json rtpParameters, const nlohmann::json &appData) override { std::future<std::string> OnProduce(mediasoupclient::SendTransport *transport, const std::string &kind, nlohmann::json rtpParameters, const nlohmann::json &appData) override {
jclass jCallbackClazz = this->env->GetObjectClass(this->routerCallback);
jmethodID sendTransportProduceCallback = this->env->GetMethodID(jCallbackClazz, "sendTransportProduceCallback", "(Ljava/lang/String;Ljava/lang/String;)V");
const char *cKind = kind.data();
jstring jKind = env->NewStringUTF(cKind);
const char *cTransportId = transport->GetId().data();
jstring jTransportId = env->NewStringUTF(cTransportId);
const char *cRtpParameters = rtpParameters.dump().data();
jstring jRtpParameters = env->NewStringUTF(cRtpParameters);
jstring jResult = (jstring) this->env->CallObjectMethod(
this->routerCallback,
sendTransportProduceCallback,
jKind,
jTransportId,
jRtpParameters
);
const char *cResult = env->GetStringUTFChars(jResult, 0);
std::string result(cResult);
env->DeleteLocalRef(jResult);
env->DeleteLocalRef(jKind);
env->ReleaseStringUTFChars(jKind, cKind);
env->DeleteLocalRef(jResult);
env->ReleaseStringUTFChars(jResult, cResult);
env->DeleteLocalRef(jTransportId);
env->ReleaseStringUTFChars(jTransportId, cTransportId);
env->DeleteLocalRef(jRtpParameters);
env->ReleaseStringUTFChars(jRtpParameters, cRtpParameters);
env->DeleteLocalRef(jCallbackClazz);
return std::future<std::string>(); return std::future<std::string>();
} }
std::future<std::string> OnProduceData(mediasoupclient::SendTransport *transport, const nlohmann::json &sctpStreamParameters, const std::string &label, const std::string &protocol, const nlohmann::json &appData) override { std::future<std::string> OnProduceData(mediasoupclient::SendTransport *transport, const nlohmann::json &sctpStreamParameters, const std::string &label, const std::string &protocol, const nlohmann::json &appData) override {
// 数据生产
return std::future<std::string>(); return std::future<std::string>();
} }
@@ -23,20 +82,56 @@ namespace acgist {
class RecvListener : public mediasoupclient::RecvTransport::Listener { class RecvListener : public mediasoupclient::RecvTransport::Listener {
public:
Room *room;
JNIEnv *env;
jobject routerCallback;
public:
RecvListener(Room *room, JNIEnv *env, jobject routerCallback) {
this->room = room;
this->env = env;
this->routerCallback = routerCallback;
}
std::future<void> OnConnect(mediasoupclient::Transport *transport, const nlohmann::json &dtlsParameters) override { std::future<void> OnConnect(mediasoupclient::Transport *transport, const nlohmann::json &dtlsParameters) override {
jclass jCallbackClazz = env->GetObjectClass(this->routerCallback);
jmethodID recvTransportConnectCallback = this->env->GetMethodID(jCallbackClazz, "recvTransportConnectCallback", "(Ljava/lang/String;Ljava/lang/String;)V");
const char *cTransportId = transport->GetId().data();
jstring jTransportId = env->NewStringUTF(cTransportId);
const char *cDtlsParameters = dtlsParameters.dump().data();
jstring jDtlsParameters = env->NewStringUTF(cDtlsParameters);
this->env->CallVoidMethod(
this->routerCallback,
recvTransportConnectCallback,
jTransportId,
jDtlsParameters
);
env->DeleteLocalRef(jTransportId);
env->ReleaseStringUTFChars(jTransportId, cTransportId);
env->DeleteLocalRef(jDtlsParameters);
env->ReleaseStringUTFChars(jDtlsParameters, cDtlsParameters);
env->DeleteLocalRef(jCallbackClazz);
return std::future<void>(); return std::future<void>();
} }
void OnConnectionStateChange(mediasoupclient::Transport *transport, const std::string &connectionState) override { void OnConnectionStateChange(mediasoupclient::Transport *transport, const std::string &connectionState) override {
// 状态变化
} }
}; };
Room::Room(jstring roomId) { Room::Room(
std::string roomId,
JNIEnv *env,
jobject routerCallback
) {
this->roomId = roomId; this->roomId = roomId;
this->env = env;
this->routerCallback = routerCallback;
this->device = new mediasoupclient::Device(); this->device = new mediasoupclient::Device();
this->sendListener = new SendListener(); this->sendListener = new SendListener(this, env, routerCallback);
this->recvListener = new RecvListener(); this->recvListener = new RecvListener(this, env, routerCallback);
} }
Room::~Room() { Room::~Room() {
@@ -45,9 +140,11 @@ namespace acgist {
delete this->sendTransport; delete this->sendTransport;
delete this->recvListener; delete this->recvListener;
delete this->recvTransport; delete this->recvTransport;
env->DeleteLocalRef(this->routerCallback);
env->DeleteGlobalRef(this->routerCallback);
} }
void Room::load( void Room::enter(
std::string rtpCapabilities, std::string rtpCapabilities,
webrtc::PeerConnectionFactoryInterface *factory, webrtc::PeerConnectionFactoryInterface *factory,
webrtc::PeerConnectionInterface::RTCConfiguration &rtcConfiguration webrtc::PeerConnectionInterface::RTCConfiguration &rtcConfiguration
@@ -93,11 +190,10 @@ namespace acgist {
void Room::close() { void Room::close() {
delete this->device; delete this->device;
this->device = nullptr;
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_com_acgist_taoyao_media_client_Room_nativeLoad( Java_com_acgist_taoyao_media_client_Room_nativeEnter(
JNIEnv* env, jobject me, JNIEnv* env, jobject me,
jlong nativeRoomPointer, jstring jRtpCapabilities, jlong nativeRoomPointer, jstring jRtpCapabilities,
jlong factoryPointer, jobject jRtcConfiguration jlong factoryPointer, jobject jRtcConfiguration
@@ -105,48 +201,36 @@ namespace acgist {
Room* room = (Room*) nativeRoomPointer; Room* room = (Room*) nativeRoomPointer;
webrtc::PeerConnectionInterface::RTCConfiguration rtcConfiguration(webrtc::PeerConnectionInterface::RTCConfigurationType::kAggressive); webrtc::PeerConnectionInterface::RTCConfiguration rtcConfiguration(webrtc::PeerConnectionInterface::RTCConfigurationType::kAggressive);
// TODO为什么不能转换测试是否因为stun配置问题 // TODO为什么不能转换测试是否因为stun配置问题
jobject jRtcConfigurationGlobal = webrtc::jni::NewGlobalRef(env, jRtcConfiguration); webrtc::JavaParamRef<jobject> jRtcConfigurationRef(jRtcConfiguration);
webrtc::JavaParamRef<jobject> jRtcConfigurationRef(jRtcConfigurationGlobal);
// webrtc::jni::JavaToNativeMediaConstraints() // webrtc::jni::JavaToNativeMediaConstraints()
webrtc::jni::JavaToNativeRTCConfiguration(env, jRtcConfigurationRef, &rtcConfiguration); webrtc::jni::JavaToNativeRTCConfiguration(env, jRtcConfigurationRef, &rtcConfiguration);
webrtc::jni::DeleteGlobalRef(env, jRtcConfigurationGlobal);
const char* rtpCapabilities = env->GetStringUTFChars(jRtpCapabilities, 0); const char* rtpCapabilities = env->GetStringUTFChars(jRtpCapabilities, 0);
room->load( room->enter(
rtpCapabilities, rtpCapabilities,
reinterpret_cast<webrtc::PeerConnectionFactoryInterface*>(factoryPointer), reinterpret_cast<webrtc::PeerConnectionFactoryInterface*>(factoryPointer),
// (webrtc::PeerConnectionFactoryInterface*) factoryPointer, // (webrtc::PeerConnectionFactoryInterface*) factoryPointer,
rtcConfiguration rtcConfiguration
); );
env->ReleaseStringUTFChars(jRtpCapabilities, rtpCapabilities); env->ReleaseStringUTFChars(jRtpCapabilities, rtpCapabilities);
env->DeleteLocalRef(jRtpCapabilities);
env->DeleteLocalRef(jRtcConfiguration);
// delete rtpCapabilities; // delete rtpCapabilities;
} }
extern "C" JNIEXPORT jlong JNICALL extern "C" JNIEXPORT jlong JNICALL
Java_com_acgist_taoyao_media_client_Room_nativeNewRoom(JNIEnv *env, jobject me, jstring roomId) { Java_com_acgist_taoyao_media_client_Room_nativeNewRoom(
const Room* room = new Room(roomId); JNIEnv *env, jobject me,
jstring jRoomId, jobject jRouterCallback
) {
const char* roomId = env->GetStringUTFChars(jRoomId, 0);
jobject routerCallback = env->NewGlobalRef(jRouterCallback);
Room* room = new Room(roomId, env, routerCallback);
env->ReleaseStringUTFChars(jRoomId, roomId);
return (jlong) room; return (jlong) room;
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_com_acgist_taoyao_media_client_Room_nativeCloseRoom(JNIEnv *env, jobject me, jlong nativeRoomPointer) { Java_com_acgist_taoyao_media_client_Room_nativeCloseRoom(JNIEnv *env, jobject me, jlong nativeRoomPointer) {
// JNIEXPORT void JNICALL
// Java_nativeMethod
// (JNIEnv *env, jobject thiz) {
// MyCPlusObj *obj = new MyCPlusObj();
// jclass clazz = (jclass)(*env).GetObjectClass(thiz);
// jfieldID fid = (jfieldID)(*env).GetFieldID(clazz, "mObj", "I");
// (*env).SetIntField(thiz, fid, (jint)obj);
// }
// jclass objClazz = (jclass)env->GetObjectClass(obj);//obj为对应的JAVA对象
// jfieldID fid = env->GetFieldID(objClazz, "mObj", "I");
// jlong p = (jlong)env->GetObjectField(obj, fid);
// MyCPlusObj *cPlusObj = (MyCPlusObj *)p;
////cPlusObj 为JAVA对象对应的C++对象
// jobject gThiz = (jobject)env->NewGlobalRef(thiz);//thiz为JAVA对象
// (*obj).javaObj = (jint)gThiz;
Room* room = (Room*) nativeRoomPointer; Room* room = (Room*) nativeRoomPointer;
room->close(); room->close();
delete room; delete room;
@@ -163,6 +247,9 @@ namespace acgist {
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL
Java_com_acgist_taoyao_media_client_Room_nativeCreateRecvTransport(JNIEnv *env, jobject me, jlong nativeRoomPointer, jstring jBody) { Java_com_acgist_taoyao_media_client_Room_nativeCreateRecvTransport(JNIEnv *env, jobject me, jlong nativeRoomPointer, jstring jBody) {
Room* room = (Room*) nativeRoomPointer; Room* room = (Room*) nativeRoomPointer;
const char* body = env->GetStringUTFChars(jBody, 0);
room->createRecvTransport(body);
env->ReleaseStringUTFChars(jBody, body);
} }
extern "C" JNIEXPORT void JNICALL extern "C" JNIEXPORT void JNICALL

View File

@@ -7,7 +7,12 @@ package com.acgist.taoyao.media;
*/ */
public interface RouterCallback { public interface RouterCallback {
default void enterCallback() {}; default void enterCallback(String rtpCapabilities, String sctpCapabilities) {};
default void sendTransportConnectCallback(String transportId, String dtlsParameters) {};
default String sendTransportProduceCallback(String kind, String transportId, String rtpParameters) {
return null;
};
default void recvTransportConnectCallback(String transportId, String dtlsParameters) {};
default void newRemoteClientCallback() {}; default void newRemoteClientCallback() {};
default void closeRemoteClientCallback() {}; default void closeRemoteClientCallback() {};
default void consumerPauseCallback() {}; default void consumerPauseCallback() {};

View File

@@ -66,7 +66,7 @@ public class Room implements Closeable, RouterCallback {
this.dataProduce = dataProduce; this.dataProduce = dataProduce;
this.audioProduce = audioProduce; this.audioProduce = audioProduce;
this.videoProduce = videoProduce; this.videoProduce = videoProduce;
this.nativeRoomPointer = this.nativeNewRoom(roomId); this.nativeRoomPointer = this.nativeNewRoom(roomId, this);
this.mediaManager = MediaManager.getInstance(); this.mediaManager = MediaManager.getInstance();
this.remoteClients = new CopyOnWriteArrayList<>(); this.remoteClients = new CopyOnWriteArrayList<>();
this.enter = false; this.enter = false;
@@ -95,7 +95,7 @@ public class Room implements Closeable, RouterCallback {
this.rtcConfiguration = new PeerConnection.RTCConfiguration(iceServers); this.rtcConfiguration = new PeerConnection.RTCConfiguration(iceServers);
this.peerConnectionFactory = this.mediaManager.newClient(MediaManager.Type.BACK); this.peerConnectionFactory = this.mediaManager.newClient(MediaManager.Type.BACK);
final Object rtpCapabilities = MapUtils.get(response.body(), "rtpCapabilities"); final Object rtpCapabilities = MapUtils.get(response.body(), "rtpCapabilities");
this.nativeLoad(this.nativeRoomPointer, JSONUtils.toJSON(rtpCapabilities), this.peerConnectionFactory.getNativePeerConnectionFactory(), this.rtcConfiguration); this.nativeEnter(this.nativeRoomPointer, JSONUtils.toJSON(rtpCapabilities), this.peerConnectionFactory.getNativePeerConnectionFactory(), this.rtcConfiguration);
} }
public void produceMedia() { public void produceMedia() {
@@ -121,11 +121,22 @@ public class Room implements Closeable, RouterCallback {
Log.w(Room.class.getSimpleName(), "创建发送通道失败"); Log.w(Room.class.getSimpleName(), "创建发送通道失败");
return; return;
} }
final Map<String, Object> body = response.body(); this.nativeCreateSendTransport(this.nativeRoomPointer, JSONUtils.toJSON(response.body()));
this.nativeCreateSendTransport(this.nativeRoomPointer, JSONUtils.toJSON(body));
} }
private void createRecvTransport() { private void createRecvTransport() {
final Message response = this.taoyao.request(this.taoyao.buildMessage(
"media::transport::webrtc::create",
"forceTcp", false,
"producing", false,
"consuming", true,
"sctpCapabilities", this.dataProduce ? this.sctpCapabilities : null
));
if(response == null) {
Log.w(Room.class.getSimpleName(), "创建接收通道失败");
return;
}
this.nativeCreateRecvTransport(this.nativeRoomPointer, JSONUtils.toJSON(response.body()));
} }
/** /**
@@ -150,6 +161,7 @@ public class Room implements Closeable, RouterCallback {
this.nativeCloseRoom(this.nativeRoomPointer); this.nativeCloseRoom(this.nativeRoomPointer);
} }
@Override
public void enterCallback(String rtpCapabilities, String sctpCapabilities) { public void enterCallback(String rtpCapabilities, String sctpCapabilities) {
this.taoyao.request(this.taoyao.buildMessage( this.taoyao.request(this.taoyao.buildMessage(
"room::enter", "room::enter",
@@ -161,13 +173,46 @@ public class Room implements Closeable, RouterCallback {
this.enter = true; this.enter = true;
} }
private native void nativeLoad( @Override
public void sendTransportConnectCallback(String transportId, String dtlsParameters) {
this.taoyao.request(this.taoyao.buildMessage(
"media::transport::webrtc::connect",
"roomId", this.roomId,
"transportId", transportId,
"dtlsParameters", JSONUtils.toMap(dtlsParameters)
));
}
@Override
public String sendTransportProduceCallback(String kind, String transportId, String rtpParameters) {
final Message response = this.taoyao.request(this.taoyao.buildMessage(
"media::produce",
"kind", kind,
"roomId", this.roomId,
"transportId", transportId,
"rtpParameters", JSONUtils.toMap(rtpParameters)
));
final Map<String, Object> body = response.body();
return MapUtils.get(body, "producerId");
}
@Override
public void recvTransportConnectCallback(String transportId, String dtlsParameters) {
this.taoyao.request(this.taoyao.buildMessage(
"media::transport::webrtc::connect",
"roomId", this.roomId,
"transportId", transportId,
"dtlsParameters", JSONUtils.toMap(dtlsParameters)
));
}
private native void nativeEnter(
long nativePointer, long nativePointer,
String rtpCapabilities, String rtpCapabilities,
long peerConnectionFactoryPointer, long peerConnectionFactoryPointer,
PeerConnection.RTCConfiguration rtcConfiguration PeerConnection.RTCConfiguration rtcConfiguration
); );
private native long nativeNewRoom(String roomId); private native long nativeNewRoom(String roomId, RouterCallback routerCallback);
private native void nativeCloseRoom(long nativePointer); private native void nativeCloseRoom(long nativePointer);
private native void nativeCreateSendTransport(long nativeRoomPointer, String body); private native void nativeCreateSendTransport(long nativeRoomPointer, String body);
private native void nativeCreateRecvTransport(long nativeRoomPointer, String body); private native void nativeCreateRecvTransport(long nativeRoomPointer, String body);

View File

@@ -1644,16 +1644,15 @@ class Taoyao extends RemoteClient {
self.sendTransport.on( self.sendTransport.on(
"connect", "connect",
({ dtlsParameters }, callback, errback) => { ({ dtlsParameters }, callback, errback) => {
self self.request(
.request( protocol.buildMessage("media::transport::webrtc::connect", {
protocol.buildMessage("media::transport::webrtc::connect", { roomId: self.roomId,
roomId: self.roomId, transportId: self.sendTransport.id,
transportId: self.sendTransport.id, dtlsParameters,
dtlsParameters, })
}) )
) .then(callback)
.then(callback) .catch(errback);
.catch(errback);
} }
); );
self.sendTransport.on( self.sendTransport.on(
@@ -1742,16 +1741,15 @@ class Taoyao extends RemoteClient {
callback, callback,
errback // eslint-disable-line no-shadow errback // eslint-disable-line no-shadow
) => { ) => {
self self.request(
.request( protocol.buildMessage("media::transport::webrtc::connect", {
protocol.buildMessage("media::transport::webrtc::connect", { roomId: self.roomId,
roomId: self.roomId, transportId: self.recvTransport.id,
transportId: self.recvTransport.id, dtlsParameters,
dtlsParameters, })
}) )
) .then(callback)
.then(callback) .catch(errback);
.catch(errback);
} }
); );
} }