[+] Android音视频接入成功

This commit is contained in:
acgist
2023-04-27 08:21:49 +08:00
parent 4cda1ef114
commit 0aa1c00a22
6 changed files with 120 additions and 102 deletions

View File

@@ -182,7 +182,7 @@ public class MainActivity extends AppCompatActivity implements Serializable {
}
this.threadHandler.post(() -> {
// 进入房间
Taoyao.taoyao.roomEnter("53a5d97d-2860-4659-9531-095bdecf3745", null);
Taoyao.taoyao.roomEnter("4f19f6fc-1763-499b-a352-d8c955af5a6e", null);
// Taoyao.taoyao.sessionCall("taoyao");
});
}

View File

@@ -1,6 +1,7 @@
#pragma once
#include <map>
#include <string>
#include "jni.h"
#include "sdk/android/src/jni/pc/peer_connection.h"
@@ -16,6 +17,7 @@ namespace acgist {
public:
std::string roomId;
webrtc::PeerConnectionFactoryInterface* factory;
webrtc::PeerConnectionInterface::RTCConfiguration* rtcConfiguration;
mediasoupclient::Device* device;
mediasoupclient::SendTransport* sendTransport;
mediasoupclient::RecvTransport* recvTransport;

View File

@@ -11,19 +11,19 @@ namespace acgist {
public:
jobject routerCallback;
public:
void enterRoomCallback(JNIEnv* env, std::string rtpCapabilities, std::string sctpCapabilities);
void enterRoomCallback(JNIEnv* env, const std::string& rtpCapabilities, const std::string& sctpCapabilities);
void closeRoomCallback(JNIEnv* env);
void sendTransportConnectCallback(JNIEnv* env, std::string transportId, std::string dtlsParameters);
void recvTransportConnectCallback(JNIEnv* env, std::string transportId, std::string dtlsParameters);
std::string sendTransportProduceCallback(JNIEnv* env, std::string kind, std::string transportId, std::string rtpParameters);
void producerNewCallback(JNIEnv* env, std::string kind, std::string producerId, mediasoupclient::Producer* producerPointer, webrtc::MediaStreamTrackInterface* producerMediaTrackPointer);
void producerCloseCallback(JNIEnv* env, std::string producerId);
void producerPauseCallback(JNIEnv* env, std::string producerId);
void producerResumeCallback(JNIEnv* env, std::string producerId);
void consumerNewCallback(JNIEnv* env, std::string message, mediasoupclient::Consumer* consumerPointer, webrtc::MediaStreamTrackInterface* consumerMediaTrackPointer);
void consumerCloseCallback(JNIEnv* env, std::string consumerId);
void consumerPauseCallback(JNIEnv* env, std::string consumerId);
void consumerResumeCallback(JNIEnv* env, std::string consumerId);
void sendTransportConnectCallback(JNIEnv* env, const std::string& transportId, const std::string& dtlsParameters);
void recvTransportConnectCallback(JNIEnv* env, const std::string& transportId, const std::string& dtlsParameters);
std::string sendTransportProduceCallback(JNIEnv* env, const std::string& kind, const std::string& transportId, const std::string& rtpParameters);
void producerNewCallback(JNIEnv* env, const std::string& kind, const std::string& producerId, mediasoupclient::Producer* producerPointer, webrtc::MediaStreamTrackInterface* producerMediaTrackPointer);
void producerCloseCallback(JNIEnv* env, const std::string& producerId);
void producerPauseCallback(JNIEnv* env, const std::string& producerId);
void producerResumeCallback(JNIEnv* env, const std::string& producerId);
void consumerNewCallback(JNIEnv* env, const std::string& message, mediasoupclient::Consumer* consumerPointer, webrtc::MediaStreamTrackInterface* consumerMediaTrackPointer);
void consumerCloseCallback(JNIEnv* env, const std::string& consumerId);
void consumerPauseCallback(JNIEnv* env, const std::string& consumerId);
void consumerResumeCallback(JNIEnv* env, const std::string& consumerId);
};
}

View File

@@ -2,7 +2,7 @@
namespace acgist {
JavaVM* taoyaoJavaVM;
JavaVM* taoyaoJavaVM = nullptr;
/**
* 非常重要

View File

@@ -11,22 +11,24 @@ namespace acgist {
explicit SendListener(Room* room) {
this->room = room;
}
virtual ~SendListener() {
}
public:
std::future<void> OnConnect(mediasoupclient::Transport* transport, const nlohmann::json& dtlsParameters) override {
const std::string& cTransportId = transport->GetId();
const std::string cTransportId = transport->GetId();
const std::string cDtlsParameters = dtlsParameters.dump();
JNIEnv* env;
if(taoyaoJavaVM->GetEnv((void**) &env, JNI_VERSION_1_6) == JNI_OK) {
JNIEnv* env = webrtc::jni::GetEnv();
// if(taoyaoJavaVM->GetEnv((void**) &env, JNI_VERSION_1_6) == JNI_EDETACHED) {
this->room->sendTransportConnectCallback(env, cTransportId, cDtlsParameters);
} else {
JavaVMAttachArgs args;
// args.version = JNI_VERSION_1_6;
// args.name = "name";
taoyaoJavaVM->AttachCurrentThreadAsDaemon(&env, &args);
this->room->sendTransportConnectCallback(env, cTransportId, cDtlsParameters);
taoyaoJavaVM->DetachCurrentThread();
}
// } else {
// JavaVMAttachArgs args;
// args.name = "C++Callback";
// args.version = JNI_VERSION_1_6;
// taoyaoJavaVM->AttachCurrentThreadAsDaemon(&env, &args);
// this->room->sendTransportConnectCallback(env, cTransportId, cDtlsParameters);
// taoyaoJavaVM->DetachCurrentThread();
// }
std::promise <void> promise;
promise.set_value();
return promise.get_future();
@@ -37,17 +39,17 @@ namespace acgist {
}
std::future<std::string> OnProduce(mediasoupclient::SendTransport* transport, const std::string& kind, nlohmann::json rtpParameters, const nlohmann::json& appData) override {
const std::string& cTransportId = transport->GetId();
const std::string cRtpParameters = rtpParameters.dump();
JNIEnv* env;
std::string result;
if(taoyaoJavaVM->GetEnv((void**) &env, JNI_VERSION_1_6) == JNI_OK) {
const std::string cTransportId = transport->GetId();
const std::string cRtpParameters = rtpParameters.dump();
JNIEnv* env = webrtc::jni::GetEnv();
// if(taoyaoJavaVM->GetEnv((void**) &env, JNI_VERSION_1_6) == JNI_EDETACHED) {
result = this->room->sendTransportProduceCallback(env, kind, cTransportId, cRtpParameters);
} else {
taoyaoJavaVM->AttachCurrentThreadAsDaemon(&env, nullptr);
result = this->room->sendTransportProduceCallback(env, kind, cTransportId, cRtpParameters);
taoyaoJavaVM->DetachCurrentThread();
}
// } else {
// taoyaoJavaVM->AttachCurrentThreadAsDaemon(&env, nullptr);
// result = this->room->sendTransportProduceCallback(env, kind, cTransportId, cRtpParameters);
// taoyaoJavaVM->DetachCurrentThread();
// }
std::promise <std::string> promise;
promise.set_value(result);
return promise.get_future();
@@ -70,18 +72,20 @@ namespace acgist {
explicit RecvListener(Room* room) {
this->room = room;
}
virtual ~RecvListener() {
}
std::future<void> OnConnect(mediasoupclient::Transport* transport, const nlohmann::json& dtlsParameters) override {
const std::string& cTransportId = transport->GetId();
const std::string& cDtlsParameters = dtlsParameters.dump();
JNIEnv* env;
if(taoyaoJavaVM->GetEnv((void**) &env, JNI_VERSION_1_6) == JNI_OK) {
const std::string cTransportId = transport->GetId();
const std::string cDtlsParameters = dtlsParameters.dump();
JNIEnv* env = webrtc::jni::GetEnv();
// if(taoyaoJavaVM->GetEnv((void**) &env, JNI_VERSION_1_6) == JNI_EDETACHED) {
this->room->recvTransportConnectCallback(env, cTransportId, cDtlsParameters);
} else {
taoyaoJavaVM->AttachCurrentThreadAsDaemon(&env, nullptr);
this->room->recvTransportConnectCallback(env, cTransportId, cDtlsParameters);
taoyaoJavaVM->DetachCurrentThread();
}
// } else {
// taoyaoJavaVM->AttachCurrentThreadAsDaemon(&env, nullptr);
// this->room->recvTransportConnectCallback(env, cTransportId, cDtlsParameters);
// taoyaoJavaVM->DetachCurrentThread();
// }
std::promise <void> promise;
promise.set_value();
return promise.get_future();
@@ -101,17 +105,19 @@ namespace acgist {
explicit ProducerListener(Room* room) {
this->room = room;
}
virtual ~ProducerListener() {
}
void OnTransportClose(mediasoupclient::Producer* producer) override {
producer->Close();
JNIEnv* env;
if(taoyaoJavaVM->GetEnv((void**) &env, JNI_VERSION_1_6) == JNI_OK) {
JNIEnv* env = webrtc::jni::GetEnv();
// if(taoyaoJavaVM->GetEnv((void**) &env, JNI_VERSION_1_6) == JNI_EDETACHED) {
this->room->producerCloseCallback(env, producer->GetId());
} else {
taoyaoJavaVM->AttachCurrentThreadAsDaemon(&env, nullptr);
this->room->producerCloseCallback(env, producer->GetId());
taoyaoJavaVM->DetachCurrentThread();
}
// } else {
// taoyaoJavaVM->AttachCurrentThreadAsDaemon(&env, nullptr);
// this->room->producerCloseCallback(env, producer->GetId());
// taoyaoJavaVM->DetachCurrentThread();
// }
}
};
@@ -125,17 +131,20 @@ namespace acgist {
explicit ConsumerListener(Room* room) {
this->room = room;
}
virtual ~ConsumerListener() {
// mediasoupclient::Consumer::Listener::~Listener();
}
void OnTransportClose(mediasoupclient::Consumer* consumer) override {
consumer->Close();
JNIEnv* env;
if(taoyaoJavaVM->GetEnv((void**) &env, JNI_VERSION_1_6) == JNI_OK) {
JNIEnv* env = webrtc::jni::GetEnv();
// if(taoyaoJavaVM->GetEnv((void**) &env, JNI_VERSION_1_6) == JNI_EDETACHED) {
this->room->consumerCloseCallback(env, consumer->GetId());
} else {
taoyaoJavaVM->AttachCurrentThreadAsDaemon(&env, nullptr);
this->room->consumerCloseCallback(env, consumer->GetId());
taoyaoJavaVM->DetachCurrentThread();
}
// } else {
// taoyaoJavaVM->AttachCurrentThreadAsDaemon(&env, nullptr);
// this->room->consumerCloseCallback(env, consumer->GetId());
// taoyaoJavaVM->DetachCurrentThread();
// }
}
};
@@ -144,21 +153,23 @@ namespace acgist {
const std::string& roomId,
const jobject& routerCallback
) {
this->routerCallback = routerCallback;
this->roomId = roomId;
this->factory = nullptr;
this->device = new mediasoupclient::Device();
this->sendTransport = nullptr;
this->recvTransport = nullptr;
this->sendListener = new SendListener(this);
this->recvListener = new RecvListener(this);
this->audioProducer = nullptr;
this->videoProducer = nullptr;
this->routerCallback = routerCallback;
this->roomId = roomId;
this->factory = nullptr;
this->rtcConfiguration = nullptr;
this->device = new mediasoupclient::Device();
this->sendTransport = nullptr;
this->recvTransport = nullptr;
this->sendListener = new SendListener(this);
this->recvListener = new RecvListener(this);
this->audioProducer = nullptr;
this->videoProducer = nullptr;
this->producerListener = new ProducerListener(this);
this->consumerListener = new ConsumerListener(this);
}
Room::~Room() {
delete this->rtcConfiguration;
delete this->device;
delete this->sendListener;
delete this->sendTransport;
@@ -168,8 +179,8 @@ namespace acgist {
delete this->videoProducer;
delete this->producerListener;
delete this->consumerListener;
JNIEnv* env;
if(taoyaoJavaVM->GetEnv((void**) &env, JNI_VERSION_1_6) == JNI_OK) {
JNIEnv* env = nullptr;
if(taoyaoJavaVM->GetEnv((void**) &env, JNI_VERSION_1_6) == JNI_EDETACHED) {
env->DeleteGlobalRef(this->routerCallback);
} else {
taoyaoJavaVM->AttachCurrentThreadAsDaemon(&env, nullptr);
@@ -184,8 +195,8 @@ namespace acgist {
webrtc::PeerConnectionFactoryInterface* factory,
webrtc::PeerConnectionInterface::RTCConfiguration& rtcConfiguration
) {
this->factory = factory;
// TODO全局
this->factory = factory;
this->rtcConfiguration = new webrtc::PeerConnectionInterface::RTCConfiguration(rtcConfiguration);
mediasoupclient::PeerConnection::Options options;
options.config = rtcConfiguration;
options.factory = factory;
@@ -199,6 +210,7 @@ namespace acgist {
void Room::createSendTransport(JNIEnv* env, const std::string& body) {
nlohmann::json json = nlohmann::json::parse(body);
mediasoupclient::PeerConnection::Options options;
options.config = *this->rtcConfiguration;
options.factory = this->factory;
this->sendTransport = this->device->CreateSendTransport(
this->sendListener,
@@ -215,6 +227,7 @@ namespace acgist {
void Room::createRecvTransport(JNIEnv* env, const std::string& body) {
nlohmann::json json = nlohmann::json::parse(body);
mediasoupclient::PeerConnection::Options options;
options.config = *this->rtcConfiguration;
options.factory = this->factory;
this->recvTransport = this->device->CreateRecvTransport(
this->recvListener,
@@ -248,7 +261,7 @@ namespace acgist {
}
void Room::mediaProduceVideo(JNIEnv* env, webrtc::MediaStreamInterface* mediaStream) {
if(this->device->CanProduce("video")) {
if(!this->device->CanProduce("video")) {
return;
}
// TODO配置读取
@@ -270,7 +283,7 @@ namespace acgist {
// encodings.emplace_back(min);
// encodings.emplace_back(mid);
// encodings.emplace_back(max);
// 强制设置编码器
// 强制设置编码器
// nlohmann::json codec = this->device->GetRtpCapabilities()["codec"];
this->videoProducer = this->sendTransport->Produce(
this->producerListener,
@@ -361,12 +374,14 @@ namespace acgist {
if(this->videoProducer != nullptr) {
this->videoProducer->Close();
}
std::map<std::string, mediasoupclient::Consumer *>::iterator iterator;
std::map<std::string, mediasoupclient::Consumer*>::iterator iterator;
for (iterator = this->consumers.begin(); iterator != this->consumers.end(); iterator++) {
iterator->second->Close();
delete iterator->second;
}
// std::for_each(this->consumers.begin(), this->consumers.end(), [](mediasoupclient::Consumer* consumer) {
// consumer->Close();
// std::for_each(this->consumers.begin(), this->consumers.end(), [](std::pair<std::string, mediasoupclient::Consumer*> entry) {
// entry.second->Close();
// delete entry.second;
// });
this->consumers.clear();
if(this->sendTransport != nullptr) {
@@ -375,8 +390,9 @@ namespace acgist {
if(this->recvTransport != nullptr) {
this->recvTransport->Close();
}
JNIEnv* env;
if(taoyaoJavaVM->GetEnv((void**) &env, JNI_VERSION_1_6) == JNI_OK) {
JNIEnv* env = nullptr;
// JNIEnv* env = webrtc::jni::GetEnv();
if(taoyaoJavaVM->GetEnv((void**) &env, JNI_VERSION_1_6) == JNI_EDETACHED) {
this->closeRoomCallback(env);
} else {
taoyaoJavaVM->AttachCurrentThreadAsDaemon(&env, nullptr);
@@ -450,15 +466,13 @@ namespace acgist {
extern "C" JNIEXPORT void JNICALL
Java_com_acgist_taoyao_media_client_Room_nativeMediaProduceAudio(JNIEnv* env, jobject me, jlong nativeRoomPointer, jlong mediaStreamPointer) {
Room* room = (Room*) nativeRoomPointer;
webrtc::MediaStreamInterface* mediaStream = (webrtc::MediaStreamInterface*) mediaStreamPointer;
room->mediaProduceAudio(env, mediaStream);
room->mediaProduceAudio(env, (webrtc::MediaStreamInterface*) mediaStreamPointer);
}
extern "C" JNIEXPORT void JNICALL
Java_com_acgist_taoyao_media_client_Room_nativeMediaProduceVideo(JNIEnv* env, jobject me, jlong nativeRoomPointer, jlong mediaStreamPointer) {
Room* room = (Room*) nativeRoomPointer;
webrtc::MediaStreamInterface* mediaStream = (webrtc::MediaStreamInterface*) mediaStreamPointer;
room->mediaProduceVideo(env, mediaStream);
room->mediaProduceVideo(env, (webrtc::MediaStreamInterface*) mediaStreamPointer);
}
extern "C" JNIEXPORT void JNICALL

View File

@@ -1,8 +1,10 @@
#include "RouterCallback.hpp"
#include <locale>
#include <codecvt>
namespace acgist {
void RouterCallback::enterRoomCallback(JNIEnv* env, std::string rtpCapabilities, std::string sctpCapabilities) {
void RouterCallback::enterRoomCallback(JNIEnv* env, const std::string& rtpCapabilities, const std::string& sctpCapabilities) {
jclass jCallbackClazz = env->GetObjectClass(this->routerCallback);
jmethodID recvTransportConnectCallback = env->GetMethodID(jCallbackClazz, "enterRoomCallback", "(Ljava/lang/String;Ljava/lang/String;)V");
const char* cRtpCapabilities = rtpCapabilities.data();
@@ -30,7 +32,7 @@ namespace acgist {
env->DeleteLocalRef(jCallbackClazz);
}
void RouterCallback::sendTransportConnectCallback(JNIEnv* env, std::string transportId, std::string dtlsParameters) {
void RouterCallback::sendTransportConnectCallback(JNIEnv* env, const std::string& transportId, const std::string& dtlsParameters) {
jclass jCallbackClazz = env->GetObjectClass(this->routerCallback);
jmethodID sendTransportConnectCallback = env->GetMethodID(jCallbackClazz, "sendTransportConnectCallback", "(Ljava/lang/String;Ljava/lang/String;)V");
const char* cTransportId = transportId.data();
@@ -48,7 +50,7 @@ namespace acgist {
env->DeleteLocalRef(jCallbackClazz);
}
void RouterCallback::recvTransportConnectCallback(JNIEnv* env, std::string transportId, std::string dtlsParameters) {
void RouterCallback::recvTransportConnectCallback(JNIEnv* env, const std::string& transportId, const std::string& dtlsParameters) {
jclass jCallbackClazz = env->GetObjectClass(this->routerCallback);
jmethodID recvTransportConnectCallback = env->GetMethodID(jCallbackClazz, "recvTransportConnectCallback", "(Ljava/lang/String;Ljava/lang/String;)V");
const char* cTransportId = transportId.data();
@@ -66,15 +68,15 @@ namespace acgist {
env->DeleteLocalRef(jCallbackClazz);
}
std::string RouterCallback::sendTransportProduceCallback(JNIEnv* env, std::string kind, std::string transportId, std::string rtpParameters) {
std::string RouterCallback::sendTransportProduceCallback(JNIEnv* env, const std::string& kind, const std::string& transportId, const std::string& rtpParameters) {
jclass jCallbackClazz = env->GetObjectClass(this->routerCallback);
jmethodID sendTransportProduceCallback = env->GetMethodID(jCallbackClazz, "sendTransportProduceCallback", "(Ljava/lang/String;Ljava/lang/String;)V");
jmethodID sendTransportProduceCallback = env->GetMethodID(jCallbackClazz, "sendTransportProduceCallback", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
const char* cKind = kind.data();
const char* cTransportId = transportId.data();
const char* cRtpParameters = rtpParameters.data();
jstring jKind = env->NewStringUTF(cKind);
jstring jTransportId = env->NewStringUTF(cTransportId);
jstring jRtpParameters = env->NewStringUTF(cRtpParameters);
jstring jTransportId = env->NewStringUTF(cTransportId);
jstring jKind = env->NewStringUTF(cKind);
jstring jRtpParameters = env->NewStringUTF(cRtpParameters);
jstring jResult = (jstring) env->CallObjectMethod(
this->routerCallback,
sendTransportProduceCallback,
@@ -88,7 +90,7 @@ namespace acgist {
}
const char* result = env->GetStringUTFChars(jResult, nullptr);
env->DeleteLocalRef(jResult);
env->ReleaseStringUTFChars(jResult, result);
// env->ReleaseStringUTFChars(jResult, result);
env->DeleteLocalRef(jKind);
env->DeleteLocalRef(jTransportId);
env->DeleteLocalRef(jRtpParameters);
@@ -96,9 +98,9 @@ namespace acgist {
return result;
}
void RouterCallback::producerNewCallback(JNIEnv* env, std::string kind, std::string producerId, mediasoupclient::Producer* producerPointer, webrtc::MediaStreamTrackInterface* producerMediaTrackPointer) {
void RouterCallback::producerNewCallback(JNIEnv* env, const std::string& kind, const std::string& producerId, mediasoupclient::Producer* producerPointer, webrtc::MediaStreamTrackInterface* producerMediaTrackPointer) {
jclass jCallbackClazz = env->GetObjectClass(this->routerCallback);
jmethodID producerNewCallback = env->GetMethodID(jCallbackClazz, "producerNewCallback", "(Ljava/lang/String;java/lang/String;J;J;)V");
jmethodID producerNewCallback = env->GetMethodID(jCallbackClazz, "producerNewCallback", "(Ljava/lang/String;Ljava/lang/String;JJ)V");
const char* cKind = kind.data();
jstring jKind = env->NewStringUTF(cKind);
const char* cProducerId = producerId.data();
@@ -113,18 +115,18 @@ namespace acgist {
);
env->DeleteLocalRef(jKind);
env->DeleteLocalRef(jProducerId);
env->DeleteLocalRef(jCallbackClazz);
// env->DeleteLocalRef(jCallbackClazz);
}
void RouterCallback::producerCloseCallback(JNIEnv* env, std::string producerId) {}
void RouterCallback::producerCloseCallback(JNIEnv* env, const std::string& producerId) {}
void RouterCallback::producerPauseCallback(JNIEnv* env, std::string producerId) {}
void RouterCallback::producerPauseCallback(JNIEnv* env, const std::string& producerId) {}
void RouterCallback::producerResumeCallback(JNIEnv* env, std::string producerId) {}
void RouterCallback::producerResumeCallback(JNIEnv* env, const std::string& producerId) {}
void RouterCallback::consumerNewCallback(JNIEnv* env, std::string message, mediasoupclient::Consumer* consumerPointer, webrtc::MediaStreamTrackInterface* consumerMediaTrackPointer) {
void RouterCallback::consumerNewCallback(JNIEnv* env, const std::string& message, mediasoupclient::Consumer* consumerPointer, webrtc::MediaStreamTrackInterface* consumerMediaTrackPointer) {
jclass jCallbackClazz = env->GetObjectClass(this->routerCallback);
jmethodID consumerNewCallback = env->GetMethodID(jCallbackClazz, "consumerNewCallback", "(Ljava/lang/String;J;J;)V");
jmethodID consumerNewCallback = env->GetMethodID(jCallbackClazz, "consumerNewCallback", "(Ljava/lang/String;JJ)V");
const char* cMessage = message.data();
jstring jMessage = env->NewStringUTF(cMessage);
env->CallVoidMethod(
@@ -138,10 +140,10 @@ namespace acgist {
env->DeleteLocalRef(jCallbackClazz);
}
void RouterCallback::consumerCloseCallback(JNIEnv* env, std::string producerId) {}
void RouterCallback::consumerCloseCallback(JNIEnv* env, const std::string& producerId) {}
void RouterCallback::consumerPauseCallback(JNIEnv* env, std::string producerId) {}
void RouterCallback::consumerPauseCallback(JNIEnv* env, const std::string& producerId) {}
void RouterCallback::consumerResumeCallback(JNIEnv* env, std::string producerId) {}
void RouterCallback::consumerResumeCallback(JNIEnv* env, const std::string& producerId) {}
}