diff --git a/taoyao-client-android/taoyao/media/src/main/cpp/include/Log.hpp b/taoyao-client-android/taoyao/media/src/main/cpp/include/Log.hpp index 217272c..f4337ef 100644 --- a/taoyao-client-android/taoyao/media/src/main/cpp/include/Log.hpp +++ b/taoyao-client-android/taoyao/media/src/main/cpp/include/Log.hpp @@ -1,19 +1,19 @@ #pragma once +/** + * 日志头文件 + */ namespace acgist { #include "android/log.h" -#define LOG_TAG "libtaoyao" - -#define LOG_D(format, ...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, "%s " format, __func__, ##__VA_ARGS__) -#define LOG_I(format, ...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, "%s " format, __func__, ##__VA_ARGS__) -#define LOG_W(format, ...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, "%s " format, __func__, ##__VA_ARGS__) -#define LOG_E(format, ...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, "%s " format, __func__, ##__VA_ARGS__) - -//#define LOG_D(...) acgist::__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) -//#define LOG_I(...) acgist::__android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__) -//#define LOG_W(...) acgist::__android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__) -//#define LOG_E(...) acgist::__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__) +// TODO:优化INFO提示 +#ifndef LOG_TAG_TAOYAO +#define LOG_TAG_TAOYAO "libtaoyao" +#define LOG_D(format, ...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG_TAOYAO, "%s " format, __func__, ##__VA_ARGS__) +#define LOG_I(format, ...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG_TAOYAO, "%s " format, __func__, ##__VA_ARGS__) +#define LOG_W(format, ...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG_TAOYAO, "%s " format, __func__, ##__VA_ARGS__) +#define LOG_E(format, ...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG_TAOYAO, "%s " format, __func__, ##__VA_ARGS__) +#endif } diff --git a/taoyao-client-android/taoyao/media/src/main/cpp/include/MediaManager.hpp b/taoyao-client-android/taoyao/media/src/main/cpp/include/MediaManager.hpp index 6282938..5908c93 100644 --- a/taoyao-client-android/taoyao/media/src/main/cpp/include/MediaManager.hpp +++ b/taoyao-client-android/taoyao/media/src/main/cpp/include/MediaManager.hpp @@ -6,15 +6,25 @@ #include "sdk/android/src/jni/jvm.h" +/** + * 媒体管理器头文件 + */ namespace acgist { /** * 全局JavaVM指针 */ extern JavaVM* taoyaoJavaVM; - + /** + * 绑定Java线程 + * + * @param env JNIEnv + * @param name Java线程名称 + */ extern void bindJavaThread(JNIEnv** env, const char* name = "C++Thread"); - + /** + * 解绑Java线程 + */ extern void unbindJavaThread(); } \ No newline at end of file diff --git a/taoyao-client-android/taoyao/media/src/main/cpp/include/Room.hpp b/taoyao-client-android/taoyao/media/src/main/cpp/include/Room.hpp index e2c2182..346c3f6 100644 --- a/taoyao-client-android/taoyao/media/src/main/cpp/include/Room.hpp +++ b/taoyao-client-android/taoyao/media/src/main/cpp/include/Room.hpp @@ -10,39 +10,170 @@ #include "Log.hpp" #include "RouterCallback.hpp" +/** + * 视频房间头文件 + */ namespace acgist { + /** + * 视频房间 + */ class Room : public RouterCallback { public: + /** + * 房间ID + */ std::string roomId; + /** + * 全局共用PeerConnectionFactory + */ webrtc::PeerConnectionFactoryInterface* factory; + /** + * 全局共用RTCConfiguration + */ webrtc::PeerConnectionInterface::RTCConfiguration* rtcConfiguration; + /** + * 房间Device + */ mediasoupclient::Device* device; + /** + * 发送通道 + */ mediasoupclient::SendTransport* sendTransport; + /** + * 接收通道 + */ mediasoupclient::RecvTransport* recvTransport; + /** + * 发送监听器 + */ mediasoupclient::SendTransport::Listener* sendListener; + /** + * 接收监听器 + */ mediasoupclient::RecvTransport::Listener* recvListener; + /** + * 音频生产者 + */ mediasoupclient::Producer* audioProducer; + /** + * 视频生产者 + */ mediasoupclient::Producer* videoProducer; + /** + * 生产者监听器 + */ mediasoupclient::Producer::Listener* producerListener; + /** + * 消费者监听器 + */ mediasoupclient::Consumer::Listener* consumerListener; + /** + * 消费者列表 + */ std::map consumers; public: + /** + * @param roomId 房间ID + * @param routerCallback 房间路由回调 + */ Room(const std::string& roomId, const jobject& routerCallback); + /** + * 析构函数 + */ virtual ~Room(); public: + /** + * 进入房间 + * + * @param env JNIEnv + * @param rtpCapabilities RTP协商 + * @param factory PeerConnectionFactory + * @param rtcConfiguration RTCConfiguration + */ void enterRoom(JNIEnv* env, const std::string& rtpCapabilities, webrtc::PeerConnectionFactoryInterface* factory, webrtc::PeerConnectionInterface::RTCConfiguration& rtcConfiguration); + /** + * 创建发送通道 + * + * @param env JNIEnv + * @param body 信令主体 + */ void createSendTransport(JNIEnv* env, const std::string& body); + /** + * 创建接收通道 + * + * @param env JNIEnv + * @param body 信令主体 + */ void createRecvTransport(JNIEnv* env, const std::string& body); + /** + * 生成音频 + * + * @param env JNIEnv + * @param mediaStream 媒体流 + */ void mediaProduceAudio(JNIEnv* env, webrtc::MediaStreamInterface* mediaStream); + /** + * 生成视频 + * + * @param env JNIEnv + * @param mediaStream 媒体流 + */ void mediaProduceVideo(JNIEnv* env, webrtc::MediaStreamInterface* mediaStream); + /** + * 消费媒体 + * + * @param env JNIEnv + * @param message 信令消息 + */ void mediaConsume(JNIEnv* env, const std::string& message); + /** + * 暂停生产者 + * + * @param env JNIEnv + * @param producerId 生产者ID + */ void mediaProducerPause(JNIEnv* env, const std::string& producerId); + /** + * 恢复生产者 + * + * @param env JNIEnv + * @param producerId 生产者ID + */ void mediaProducerResume(JNIEnv* env, const std::string& producerId); + /** + * 关闭生产者 + * + * @param env JNIEnv + * @param producerId 生产者ID + */ void mediaProducerClose(JNIEnv* env, const std::string& producerId); + /** + * 暂停消费者 + * + * @param env JNIEnv + * @param consumerId 消费者ID + */ void mediaConsumerPause(JNIEnv* env, const std::string& consumerId); + /** + * 恢复消费者 + * + * @param env JNIEnv + * @param consumerId 消费者ID + */ void mediaConsumerResume(JNIEnv* env, const std::string& consumerId); + /** + * 关闭消费者 + * + * @param env JNIEnv + * @param consumerId 消费者ID + */ void mediaConsumerClose(JNIEnv* env, const std::string& consumerId); + /** + * 关闭房间 + * + * @param env JNIEnv + */ void closeRoom(JNIEnv* env); }; diff --git a/taoyao-client-android/taoyao/media/src/main/java/com/acgist/taoyao/media/MediaManager.java b/taoyao-client-android/taoyao/media/src/main/java/com/acgist/taoyao/media/MediaManager.java index f05d67b..8af4ad3 100644 --- a/taoyao-client-android/taoyao/media/src/main/java/com/acgist/taoyao/media/MediaManager.java +++ b/taoyao-client-android/taoyao/media/src/main/java/com/acgist/taoyao/media/MediaManager.java @@ -403,8 +403,9 @@ public final class MediaManager { // }); final JavaAudioDeviceModule javaAudioDeviceModule = JavaAudioDeviceModule.builder(this.context) // .setSampleRate(48000) -// .setAudioSource(MediaRecorder.AudioSource.MIC) +// .setSampleRate(mediaAudioProperties.getSampleRate()) // .setAudioFormat(AudioFormat.ENCODING_PCM_16BIT) +// .setAudioSource(MediaRecorder.AudioSource.MIC) // .setAudioAttributes(audioAttributes) // 超低延迟 // .setUseLowLatency() diff --git a/taoyao-client-web/src/components/Taoyao.js b/taoyao-client-web/src/components/Taoyao.js index 890c6c6..217457d 100644 --- a/taoyao-client-web/src/components/Taoyao.js +++ b/taoyao-client-web/src/components/Taoyao.js @@ -332,16 +332,26 @@ class Session { this.localVideoEnabled = false; this.remoteAudioEnabled = false; this.remoteVideoEnabled = false; - this.localAudioTrack.stop(); - this.localAudioTrack = null; - this.localVideoTrack.stop(); - this.localVideoTrack = null; - this.remoteAudioTrack.stop(); - this.remoteAudioTrack = null; - this.remoteVideoTrack.stop(); - this.remoteVideoTrack = null; - this.peerConnection.close(); - this.peerConnection = null; + if(this.localAudioTrack) { + this.localAudioTrack.stop(); + this.localAudioTrack = null; + } + if(this.localVideoTrack) { + this.localVideoTrack.stop(); + this.localVideoTrack = null; + } + if(this.remoteAudioTrack) { + this.remoteAudioTrack.stop(); + this.remoteAudioTrack = null; + } + if(this.remoteVideoTrack) { + this.remoteVideoTrack.stop(); + this.remoteVideoTrack = null; + } + if(this.peerConnection) { + this.peerConnection.close(); + this.peerConnection = null; + } } async addIceCandidate(candidate) { @@ -769,7 +779,6 @@ class Taoyao extends RemoteClient { // const stream = await this._getExternalVideoStream(); // track = stream.getVideoTracks()[0].clone(); } else if (self.videoSource === "camera") { - console.debug("enableWebcam() | calling getUserMedia()"); // TODO:参数 stream = await navigator.mediaDevices.getUserMedia({ audio: self.audioConfig, @@ -846,6 +855,8 @@ class Taoyao extends RemoteClient { ideal: audio.sampleSize, max: media.maxSampleSize, }; + // 强制修改 + // me.audioConfig.sampleRate = 8000; me.audioConfig.sampleRate = { min: media.minSampleRate, ideal: audio.sampleRate,