Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
32a828aead | ||
|
|
f9de241e09 | ||
|
|
95398a0f64 | ||
|
|
2d065876db | ||
|
|
811a57a27b | ||
|
|
cb9c30ddcb | ||
|
|
9ec8cf4216 | ||
|
|
40149bc496 | ||
|
|
ec89b669c4 | ||
|
|
65904706ca | ||
|
|
94d18908cd | ||
|
|
0673df4d95 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -9,6 +9,8 @@ build
|
||||
target
|
||||
node_modules
|
||||
|
||||
.idea
|
||||
|
||||
.vscode
|
||||
|
||||
package-lock.json
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
mkdir -p /data
|
||||
cd /data
|
||||
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
# vpython
|
||||
# git checkout chrome/4147
|
||||
|
||||
# 下载源码
|
||||
mkdir -p /data/webrtc
|
||||
|
||||
@@ -4,14 +4,19 @@
|
||||
|
||||
* SDK 28~32
|
||||
* Gradle 7.5
|
||||
* WebRTC M94/4606
|
||||
* Andoird 9~12
|
||||
|
||||
> 最新支持`M120/6099`没有适配
|
||||
|
||||
## C++终端
|
||||
|
||||
* [libmediasoupclient源码](https://github.com/versatica/libmediasoupclient)
|
||||
* [libmediasoupclient文档](https://mediasoup.org/documentation/v3/libmediasoupclient)
|
||||
* [libmediasoupclient接口](https://mediasoup.org/documentation/v3/libmediasoupclient/api)
|
||||
|
||||
> 分支:`3.4.2`
|
||||
|
||||
## 项目配置
|
||||
|
||||
可以自己编译`WebRTC`依赖或者下载已有依赖,项目导入以后拷贝`libmediasoupclient`源码还有`WebRTC`头文件和库文件到`deps`目录。
|
||||
|
||||
5
taoyao-client-android/taoyao/.gitignore
vendored
5
taoyao-client-android/taoyao/.gitignore
vendored
@@ -2,9 +2,6 @@
|
||||
.idea
|
||||
.gradle
|
||||
|
||||
media/deps/webrtc
|
||||
media/deps/rnnoise/src
|
||||
media/deps/rnnoise/include
|
||||
media/deps/libmediasoupclient
|
||||
media/deps
|
||||
|
||||
local.properties
|
||||
|
||||
@@ -48,6 +48,6 @@
|
||||
<string name="videoFile"></string>
|
||||
<!-- 水印 -->
|
||||
<string name="watermark">"'TAOYAO' yyyy-MM-dd HH:mm:ss"</string>
|
||||
<!-- 视频来源:FILE|BACK|FRONT|SCREEN -->
|
||||
<!-- 视频来源:FILE|BACK|FRONT|SCREEN|SHARE -->
|
||||
<string name="videoSourceType">BACK</string>
|
||||
</resources>
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
#Mon Mar 20 09:51:37 CST 2023
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip
|
||||
#8.0????
|
||||
#distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
||||
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-8.5-bin.zip
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
|
||||
@@ -2,14 +2,20 @@ cmake_minimum_required(VERSION 3.22.1)
|
||||
|
||||
project(taoyao VERSION 1.0.0 LANGUAGES C CXX)
|
||||
|
||||
# Debug | Release
|
||||
#-DCMAKE_BUILD_TYPE=Debug
|
||||
#set(CMAKE_BUILD_TYPE Debug)
|
||||
|
||||
# C编译选项
|
||||
set(CMAKE_C_STANDARD 17)
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -std=c17 -O0 -g")
|
||||
#set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c17 -O3")
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -std=c17 -O0 -g")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -std=c17 -O3")
|
||||
|
||||
# C++编译选项
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++17 -O0 -g")
|
||||
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17 -O3")
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -std=c++17 -O0 -g")
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -std=c++17 -O3")
|
||||
|
||||
set(
|
||||
@@ -19,9 +25,12 @@ set(
|
||||
|
||||
set(
|
||||
SOURCE_FILES
|
||||
${SOURCE_DIR}/webrtc/Room.cpp
|
||||
${SOURCE_DIR}/webrtc/Rnnoise.cpp
|
||||
${SOURCE_DIR}/include/Log.hpp
|
||||
${SOURCE_DIR}/include/MediaManager.hpp
|
||||
${SOURCE_DIR}/include/Room.hpp
|
||||
${SOURCE_DIR}/include/RouterCallback.hpp
|
||||
${SOURCE_DIR}/webrtc/MediaManager.cpp
|
||||
${SOURCE_DIR}/webrtc/Room.cpp
|
||||
${SOURCE_DIR}/webrtc/RouterCallback.cpp
|
||||
)
|
||||
|
||||
@@ -41,7 +50,6 @@ endif ()
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES})
|
||||
|
||||
add_subdirectory("deps/rnnoise")
|
||||
add_subdirectory("deps/libmediasoupclient")
|
||||
|
||||
set_source_files_properties(
|
||||
@@ -51,7 +59,6 @@ set_source_files_properties(
|
||||
target_include_directories(
|
||||
${PROJECT_NAME} PUBLIC
|
||||
"${SOURCE_DIR}/include"
|
||||
"${PROJECT_SOURCE_DIR}/deps/rnnoise/include"
|
||||
"${PROJECT_SOURCE_DIR}/deps/libmediasoupclient/include"
|
||||
"${PROJECT_SOURCE_DIR}/deps/libmediasoupclient/deps/libsdptransform/include"
|
||||
)
|
||||
@@ -60,7 +67,6 @@ target_link_libraries(
|
||||
${PROJECT_NAME} PUBLIC
|
||||
log
|
||||
android
|
||||
rnnoise
|
||||
OpenSLES
|
||||
mediasoupclient
|
||||
)
|
||||
|
||||
16
taoyao-client-android/taoyao/media/README.md
Normal file
16
taoyao-client-android/taoyao/media/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
# 目录结构
|
||||
|
||||
```
|
||||
│
|
||||
├─deps
|
||||
│ ├─libmediasoupclient
|
||||
│ │ libmediasoupclient源码
|
||||
│ └─webrtc
|
||||
│ ├─lib
|
||||
│ │ └─arm64-v8a
|
||||
│ │ libwebrtc.a
|
||||
│ │ WebRTC静态库
|
||||
│ └─src
|
||||
│ ├─api
|
||||
│ │ WebRTC头文件
|
||||
```
|
||||
@@ -1,30 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.22.1)
|
||||
|
||||
project(rnnoise VERSION 1.0.0 LANGUAGES C)
|
||||
|
||||
set(CMAKE_C_STANDARD 17)
|
||||
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -std=c17 -O0 -g")
|
||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -std=c17 -O3")
|
||||
|
||||
include_directories(include)
|
||||
|
||||
set(
|
||||
SOURCE_FILES
|
||||
src/rnn.c
|
||||
src/nnet.c
|
||||
src/pitch.c
|
||||
src/denoise.c
|
||||
src/celt_lpc.c
|
||||
src/kiss_fft.c
|
||||
src/nnet_default.c
|
||||
src/rnnoise_tables.c
|
||||
src/rnnoise_data.c
|
||||
# src/rnnoise_data_little.c
|
||||
src/parse_lpcnet_weights.c
|
||||
)
|
||||
|
||||
add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES})
|
||||
|
||||
set_source_files_properties(
|
||||
${SOURCE_FILES} PROPERTIES COMPILE_FLAGS -Wall -Wextra -Wpedantic
|
||||
)
|
||||
@@ -1,57 +0,0 @@
|
||||
# RNNOISE模型
|
||||
|
||||
https://github.com/xiph/rnnoise.git
|
||||
|
||||
## FFmpeg
|
||||
|
||||
```
|
||||
ffplay -ar 48000 -ac 1 -f s16le input.pcm
|
||||
ffmpeg.exe -i .\source.wav -ar 48000 -ac 1 -f s16le -c:a pcm_s16le source.raw
|
||||
ffmpeg.exe -i .\source.ts -vn -ar 48000 -ac 1 -f s16le -c:a pcm_s16le source.raw
|
||||
```
|
||||
|
||||
## 环境
|
||||
|
||||
```
|
||||
sudo apt install pip3 python3
|
||||
|
||||
vim ~/.pip/pip.conf
|
||||
|
||||
---
|
||||
[global]
|
||||
index-url=https://pypi.tuna.tsinghua.edu.cn/simple
|
||||
---
|
||||
|
||||
pip3 install tqdm torch
|
||||
```
|
||||
|
||||
## 训练
|
||||
|
||||
训练音频`48000`采样单声道的`PCM`音频数据
|
||||
|
||||
```
|
||||
# 混合数据:mix.pcm
|
||||
# 噪音数据:noise.pcm
|
||||
# 原始数据:speech.pcm
|
||||
|
||||
# 克隆仓库
|
||||
cd /data
|
||||
git clone http://192.168.8.184:9999/dev/hsx/rnnoise.git
|
||||
cd rnnoise
|
||||
|
||||
# 编译代码
|
||||
./autogen.sh
|
||||
./configure
|
||||
make
|
||||
|
||||
# 提取特征
|
||||
./dump_features speech.pcm noise.pcm features.f32 200000
|
||||
./script/dump_features_parallel.sh ./dump_features speech.pcm noise.pcm features.f32 200000 8
|
||||
# 模型训练
|
||||
python3 train_rnnoise.py --gru-size=32 --cond-size=32 --epochs=15 features.f32 ./
|
||||
# 导出权重
|
||||
python3 dump_rnnoise_weights.py --quantize ./checkpoints/rnnoise_1.pth rnnoise_c
|
||||
|
||||
# 验证效果
|
||||
./examples/rnnoise_demo mix.pcm output.pcm
|
||||
```
|
||||
@@ -1,32 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include "rnnoise.h"
|
||||
|
||||
namespace acgist {
|
||||
|
||||
/**
|
||||
* 降噪配置
|
||||
*/
|
||||
class RnnoiseConfig {
|
||||
|
||||
public:
|
||||
// 采样位深:16
|
||||
int bits = 16;
|
||||
// 数据大小:960
|
||||
int size = 960;
|
||||
// 采样率:48000
|
||||
int rate = 48000;
|
||||
// 降噪数据大小
|
||||
int rnnoiseSize = 480;
|
||||
// 降噪数据
|
||||
float* rnnoiseData = nullptr;
|
||||
// 降噪对象
|
||||
DenoiseState* denoiseState = nullptr;
|
||||
|
||||
public:
|
||||
RnnoiseConfig();
|
||||
virtual ~RnnoiseConfig();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
#include "Rnnoise.hpp"
|
||||
|
||||
#include "jni.h"
|
||||
#include "android/log.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#ifndef RNNOISE_TAG
|
||||
#define RNNOISE_TAG "rnnoise"
|
||||
#endif
|
||||
|
||||
acgist::RnnoiseConfig::RnnoiseConfig() {
|
||||
}
|
||||
|
||||
acgist::RnnoiseConfig::~RnnoiseConfig() {
|
||||
delete[] this->rnnoiseData;
|
||||
rnnoise_destroy(this->denoiseState);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_acgist_taoyao_media_audio_RnnoiseProcesser_Init(
|
||||
JNIEnv* env,
|
||||
jobject processer,
|
||||
jint bits,
|
||||
jint size,
|
||||
jint rate
|
||||
) {
|
||||
__android_log_print(ANDROID_LOG_DEBUG, RNNOISE_TAG, "加载Rnnoise");
|
||||
acgist::RnnoiseConfig* config = new acgist::RnnoiseConfig();
|
||||
config->bits = bits;
|
||||
config->size = size;
|
||||
config->rate = rate;
|
||||
config->rnnoiseSize = size / 2;
|
||||
config->rnnoiseData = new float[config->rnnoiseSize];
|
||||
config->denoiseState = rnnoise_create(NULL);
|
||||
return (jlong) config;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jbyteArray JNICALL
|
||||
Java_com_acgist_taoyao_media_audio_RnnoiseProcesser_Rnnoise(
|
||||
JNIEnv* env,
|
||||
jobject processer,
|
||||
jlong pointer,
|
||||
jbyteArray pcm
|
||||
) {
|
||||
acgist::RnnoiseConfig* config = (acgist::RnnoiseConfig*) pointer;
|
||||
jbyte* srcBytes = env->GetByteArrayElements(pcm, 0);
|
||||
short* srcBuffer = (short*) srcBytes;
|
||||
for (int i = 0; i < config->rnnoiseSize; i++) {
|
||||
config->rnnoiseData[i] = srcBuffer[i];
|
||||
}
|
||||
rnnoise_process_frame(config->denoiseState, config->rnnoiseData, config->rnnoiseData);
|
||||
// 返回值不用释放否则需要手动释放
|
||||
const jbyteArray result = env->NewByteArray(config->size);
|
||||
jbyte dstBytes[config->size];
|
||||
for (int i = 0; i < config->rnnoiseSize; i++) {
|
||||
short v = config->rnnoiseData[i];
|
||||
if(v > std::numeric_limits<short>::max()) {
|
||||
v = std::numeric_limits<short>::max();
|
||||
} else if(v < std::numeric_limits<short>::min()) {
|
||||
v = std::numeric_limits<short>::min();
|
||||
}
|
||||
dstBytes[2 * i] = (int8_t) (v >> 0);
|
||||
dstBytes[2 * i + 1] = (int8_t) (v >> 8);
|
||||
}
|
||||
env->SetByteArrayRegion(result, 0, config->size, dstBytes);
|
||||
env->ReleaseByteArrayElements(pcm, srcBytes, 0);
|
||||
// env->DeleteLocalRef(result);
|
||||
// env->ReleaseByteArrayElements(result, dstBytes, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_acgist_taoyao_media_audio_RnnoiseProcesser_Release(
|
||||
JNIEnv* env,
|
||||
jobject processer,
|
||||
jlong pointer
|
||||
) {
|
||||
__android_log_print(ANDROID_LOG_DEBUG, RNNOISE_TAG, "释放Rnnoise");
|
||||
acgist::RnnoiseConfig* config = (acgist::RnnoiseConfig*) pointer;
|
||||
delete config;
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import com.acgist.taoyao.media.config.MediaProperties;
|
||||
import com.acgist.taoyao.media.config.MediaVideoProperties;
|
||||
import com.acgist.taoyao.media.config.WebrtcProperties;
|
||||
import com.acgist.taoyao.media.signal.ITaoyao;
|
||||
import com.acgist.taoyao.media.video.ShareVideoCapturer;
|
||||
import com.acgist.taoyao.media.video.VideoProcesser;
|
||||
import com.acgist.taoyao.media.video.WatermarkProcesser;
|
||||
|
||||
@@ -491,6 +492,8 @@ public final class MediaManager {
|
||||
this.initCameraCapturer();
|
||||
} else if (this.videoSourceType == VideoSourceType.SCREEN) {
|
||||
this.initScreenCapturerPromise();
|
||||
} else if(this.videoSourceType == VideoSourceType.SHARE) {
|
||||
this.initShareCapturer();
|
||||
} else {
|
||||
// 其他来源
|
||||
}
|
||||
@@ -544,6 +547,14 @@ public final class MediaManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载本地共享
|
||||
*/
|
||||
private void initShareCapturer() {
|
||||
this.videoCapturer = new ShareVideoCapturer();
|
||||
this.initVideoSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载屏幕采集
|
||||
*
|
||||
@@ -1050,6 +1061,18 @@ public final class MediaManager {
|
||||
|
||||
}
|
||||
|
||||
public void addShare(MediaStream mediaStream) {
|
||||
if(this.videoSourceType == VideoSourceType.SHARE) {
|
||||
((ShareVideoCapturer) this.videoCapturer).addSource(mediaStream);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeShare(MediaStream mediaStream) {
|
||||
if(this.videoSourceType == VideoSourceType.SHARE) {
|
||||
((ShareVideoCapturer) this.videoCapturer).removeSource(mediaStream);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载MediasoupClient
|
||||
*/
|
||||
|
||||
@@ -22,7 +22,13 @@ public enum VideoSourceType {
|
||||
/**
|
||||
* 屏幕共享:ScreenCapturerAndroid
|
||||
*/
|
||||
SCREEN;
|
||||
SCREEN,
|
||||
/**
|
||||
* 共享本地:ShareVideoCapturer
|
||||
*
|
||||
* 注意:这个模式只是用来测试很多功能没有兼容
|
||||
*/
|
||||
SHARE;
|
||||
|
||||
/**
|
||||
* @return 是否是摄像头
|
||||
|
||||
@@ -1,141 +0,0 @@
|
||||
package com.acgist.taoyao.media.audio;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
/**
|
||||
* Rnnoise降噪
|
||||
*
|
||||
* 注意:暂时只支持48K采样率,其他采样率需要先重新采样。
|
||||
*
|
||||
* https://github.com/xiph/rnnoise.git
|
||||
*/
|
||||
public class RnnoiseProcesser {
|
||||
|
||||
/**
|
||||
* 声道数据
|
||||
*/
|
||||
private byte[] src;
|
||||
/**
|
||||
* 降噪配置对象指针
|
||||
*/
|
||||
private long pointer;
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
private final boolean enabled = true;
|
||||
|
||||
private static final int BITS = 16;
|
||||
private static final int RATE = 48000;
|
||||
private static final int SIZE_MONO = 960;
|
||||
private static final int SIZE_STEREO = 1920;
|
||||
private static final int CHANNEL_COUNT = 1;
|
||||
|
||||
/**
|
||||
* @see #init()
|
||||
*/
|
||||
public final void init() {
|
||||
this.init(BITS, SIZE_MONO, RATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #Init(int, int, int)
|
||||
*/
|
||||
public final void init(int bits, int size, int rate) {
|
||||
if(!this.enabled) {
|
||||
return;
|
||||
}
|
||||
if(CHANNEL_COUNT == 1) {
|
||||
this.src = new byte[SIZE_MONO];
|
||||
this.pointer = Init(bits, size, rate);
|
||||
} else {
|
||||
this.src = new byte[SIZE_MONO];
|
||||
this.pointer = Init(bits, size, rate);
|
||||
}
|
||||
Log.i(RnnoiseProcesser.class.getSimpleName(), String.format("配置降噪参数:%d - %d - %d", bits, size, rate));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #rnnoise(int, int, byte[])
|
||||
*/
|
||||
public final byte[] rnnoise(byte[] pcm) {
|
||||
return this.rnnoise(0, pcm.length, pcm);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #Rnnoise(long, byte[])
|
||||
*/
|
||||
public final byte[] rnnoise(final int offset, final int capacity, final byte[] pcm) {
|
||||
if(!this.enabled) {
|
||||
return pcm;
|
||||
}
|
||||
if(this.pointer == 0L) {
|
||||
Log.w(RnnoiseProcesser.class.getSimpleName(), "降噪对象没有初始成功原样返回");
|
||||
return pcm;
|
||||
}
|
||||
if(capacity == SIZE_MONO) {
|
||||
System.arraycopy(pcm, offset, this.src, 0, SIZE_MONO);
|
||||
final byte[] dst = Rnnoise(this.pointer, this.src);
|
||||
System.arraycopy(dst, 0, pcm, offset, SIZE_MONO);
|
||||
return pcm;
|
||||
} else if(capacity == SIZE_STEREO) {
|
||||
// 提取单个声道
|
||||
for (int index = offset, jndex = 0; index < capacity + offset; index += 4, jndex += 2) {
|
||||
this.src[jndex] = pcm[index];
|
||||
this.src[jndex + 1] = pcm[index + 1];
|
||||
}
|
||||
final byte[] dst = Rnnoise(this.pointer, this.src);
|
||||
for (int index = offset, jndex = 0; index < capacity + offset; index += 4, jndex += 2) {
|
||||
pcm[index] = dst[jndex];
|
||||
pcm[index + 1] = dst[jndex + 1];
|
||||
pcm[index + 2] = dst[jndex];
|
||||
pcm[index + 3] = dst[jndex + 1];
|
||||
}
|
||||
return pcm;
|
||||
} else {
|
||||
return pcm;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #Release(long)
|
||||
*/
|
||||
public final void release() {
|
||||
if(!this.enabled) {
|
||||
return;
|
||||
}
|
||||
Log.i(RnnoiseProcesser.class.getSimpleName(), "释放降噪对象");
|
||||
if(this.pointer == 0L) {
|
||||
return;
|
||||
}
|
||||
Release(this.pointer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化
|
||||
*
|
||||
* @param bits 采样位深
|
||||
* @param size 数据大小
|
||||
* @param rate 采样率
|
||||
*
|
||||
* @return 降噪配置对象指针
|
||||
*/
|
||||
private native final long Init(int bits, int size, int rate);
|
||||
|
||||
/**
|
||||
* 降噪
|
||||
*
|
||||
* @param pointer 降噪配置对象指针
|
||||
* @param pcm PCM数据
|
||||
*
|
||||
* @return 降噪后的PCM数据
|
||||
*/
|
||||
private native final byte[] Rnnoise(long pointer, byte[] pcm);
|
||||
|
||||
/**
|
||||
* 释放资源
|
||||
*
|
||||
* @param pointer 降噪配置对象指针
|
||||
*/
|
||||
private native final void Release(long pointer);
|
||||
|
||||
}
|
||||
@@ -492,6 +492,7 @@ public class SessionClient extends Client {
|
||||
SessionClient.this.remoteMediaStream = mediaStream;
|
||||
SessionClient.this.playAudio();
|
||||
SessionClient.this.playVideo();
|
||||
SessionClient.this.mediaManager.addShare(mediaStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -499,6 +500,7 @@ public class SessionClient extends Client {
|
||||
Log.i(SessionClient.class.getSimpleName(), "删除远程媒体:" + SessionClient.this.clientId);
|
||||
mediaStream.dispose();
|
||||
SessionClient.this.remoteMediaStream = null;
|
||||
SessionClient.this.mediaManager.removeShare(mediaStream);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
package com.acgist.taoyao.media.video;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Log;
|
||||
|
||||
import org.webrtc.CapturerObserver;
|
||||
import org.webrtc.JavaI420Buffer;
|
||||
import org.webrtc.MediaStream;
|
||||
import org.webrtc.SurfaceTextureHelper;
|
||||
import org.webrtc.VideoCapturer;
|
||||
import org.webrtc.VideoFrame;
|
||||
import org.webrtc.VideoSink;
|
||||
import org.webrtc.VideoTrack;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* 注意:只是功能验证,没有实现资源释放。
|
||||
*/
|
||||
public class ShareVideoCapturer implements VideoCapturer {
|
||||
|
||||
private byte[] bytes = new byte[1024 * 1024];
|
||||
private boolean running = false;
|
||||
private CapturerObserver capturerObserver;
|
||||
private final Map<VideoTrack, VideoFrame> frames = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void initialize(SurfaceTextureHelper surfaceTextureHelper, Context applicationContext, CapturerObserver capturerObserver) {
|
||||
this.capturerObserver = capturerObserver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startCapture(int width, int height, int framerate) {
|
||||
this.running = true;
|
||||
final Thread thread = new Thread(() -> {
|
||||
final int col = 2;
|
||||
final int row = 2;
|
||||
final int stride = width;
|
||||
final int width_ = width / col;
|
||||
final int height_ = height / row;
|
||||
Log.d(ShareVideoCapturer.class.getSimpleName(), "原始宽度:" + width);
|
||||
Log.d(ShareVideoCapturer.class.getSimpleName(), "原始高度:" + height);
|
||||
Log.d(ShareVideoCapturer.class.getSimpleName(), "目标宽度:" + width_);
|
||||
Log.d(ShareVideoCapturer.class.getSimpleName(), "目标高度:" + height_);
|
||||
final JavaI420Buffer buffer = JavaI420Buffer.wrap(
|
||||
width, height,
|
||||
ByteBuffer.allocateDirect(width * height), stride,
|
||||
ByteBuffer.allocateDirect(width * height / 2), stride,
|
||||
ByteBuffer.allocateDirect(width * height / 2), stride,
|
||||
null
|
||||
);
|
||||
this.clearBuffer(buffer);
|
||||
final AtomicInteger index = new AtomicInteger(0);
|
||||
while(ShareVideoCapturer.this.running) {
|
||||
synchronized (ShareVideoCapturer.this.frames) {
|
||||
do {
|
||||
try {
|
||||
// 25帧
|
||||
ShareVideoCapturer.this.frames.wait(1000 / 25);
|
||||
} catch (Exception e) {
|
||||
Log.e(ShareVideoCapturer.class.getSimpleName(), "等待异常", e);
|
||||
}
|
||||
} while(ShareVideoCapturer.this.frames.isEmpty());
|
||||
index.set(0);
|
||||
ShareVideoCapturer.this.frames.forEach((k, v) -> {
|
||||
final VideoFrame.Buffer c = v.getBuffer();
|
||||
final VideoFrame.Buffer o = c.cropAndScale(0, 0, c.getWidth(), c.getHeight(), width_, height_);
|
||||
final VideoFrame.I420Buffer x = o.toI420();
|
||||
// 如果每个都是独立传输
|
||||
// buffer.getDataY().put(x.getDataY());
|
||||
// buffer.getDataU().put(x.getDataU());
|
||||
// buffer.getDataV().put(x.getDataV());
|
||||
final int row_ = index.get() / col;
|
||||
final int col_ = index.get() % col;
|
||||
final int dstX = col_ * width_;
|
||||
final int dstY = row_ * height_;
|
||||
ShareVideoCapturer.this.copyBuffer(x, buffer, dstX, dstY);
|
||||
x.release();
|
||||
o.release();
|
||||
v.release();
|
||||
index.incrementAndGet();
|
||||
if(index.get() >= col * row) {
|
||||
index.set(0);
|
||||
}
|
||||
});
|
||||
ShareVideoCapturer.this.frames.clear();
|
||||
final VideoFrame frame = new VideoFrame(
|
||||
buffer,
|
||||
0,
|
||||
System.nanoTime()
|
||||
);
|
||||
ShareVideoCapturer.this.capturerObserver.onFrameCaptured(frame);
|
||||
}
|
||||
}
|
||||
buffer.release();
|
||||
synchronized (ShareVideoCapturer.this.frames) {
|
||||
ShareVideoCapturer.this.frames.forEach((k, v) -> {
|
||||
v.release();
|
||||
});
|
||||
ShareVideoCapturer.this.frames.clear();
|
||||
}
|
||||
});
|
||||
thread.setName("SHARE-VIDEO-CAPTURER");
|
||||
thread.setDaemon(true);
|
||||
thread.start();
|
||||
}
|
||||
|
||||
private void clearBuffer(VideoFrame.I420Buffer buffer) {
|
||||
this.clearBuffer(buffer.getDataY());
|
||||
this.clearBuffer(buffer.getDataU());
|
||||
this.clearBuffer(buffer.getDataV());
|
||||
}
|
||||
|
||||
private void clearBuffer(ByteBuffer buffer) {
|
||||
while(buffer.hasRemaining()) {
|
||||
buffer.put((byte) 128);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyBuffer(
|
||||
VideoFrame.I420Buffer src,
|
||||
VideoFrame.I420Buffer dst,
|
||||
int dstX,
|
||||
int dstY
|
||||
) {
|
||||
final int width = src.getWidth();
|
||||
final int height = src.getHeight();
|
||||
// 复制Y平面
|
||||
this.copyPlane(
|
||||
src.getDataY(), src.getStrideY(),
|
||||
dst.getDataY(), dst.getStrideY(),
|
||||
width, height, dstX, dstY
|
||||
);
|
||||
// 复制U平面
|
||||
final int uvWidth = (width + 1) / 2;
|
||||
final int uvHeight = (height + 1) / 2;
|
||||
copyPlane(
|
||||
src.getDataU(), src.getStrideU(),
|
||||
dst.getDataU(), dst.getStrideU(),
|
||||
uvWidth, uvHeight, dstX / 2, dstY / 2
|
||||
);
|
||||
// 复制V平面
|
||||
this.copyPlane(
|
||||
src.getDataV(), src.getStrideV(),
|
||||
dst.getDataV(), dst.getStrideV(),
|
||||
uvWidth, uvHeight, dstX / 2, dstY / 2
|
||||
);
|
||||
}
|
||||
|
||||
private void copyPlane(
|
||||
ByteBuffer src, int srcStride,
|
||||
ByteBuffer dst, int dstStride,
|
||||
int width, int height, int dstX, int dstY
|
||||
) {
|
||||
for (int y = 0; y < height; y++) {
|
||||
final int srcPos = y * srcStride;
|
||||
final int dstPos = (dstY + y) * dstStride + dstX;
|
||||
src.position(srcPos);
|
||||
src.get(this.bytes, 0, width);
|
||||
dst.position(dstPos);
|
||||
dst.put(this.bytes, 0, width);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopCapture() throws InterruptedException {
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changeCaptureFormat(int width, int height, int framerate) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isScreencast() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void addSource(MediaStream mediaStream) {
|
||||
mediaStream.videoTracks.forEach(track -> {
|
||||
track.addSink(new VideoSink() {
|
||||
@Override
|
||||
public void onFrame(VideoFrame frame) {
|
||||
synchronized (ShareVideoCapturer.this.frames) {
|
||||
if(ShareVideoCapturer.this.running) {
|
||||
frame.retain();
|
||||
final VideoFrame old = ShareVideoCapturer.this.frames.put(track, frame);
|
||||
if(old != null) {
|
||||
old.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public void removeSource(MediaStream mediaStream) {
|
||||
mediaStream.videoTracks.forEach(track -> {
|
||||
synchronized (ShareVideoCapturer.this.frames) {
|
||||
final VideoFrame old = ShareVideoCapturer.this.frames.remove(track);
|
||||
if(old != null) {
|
||||
old.release();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,8 +24,6 @@ import android.os.Process;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.RequiresApi;
|
||||
|
||||
import com.acgist.taoyao.media.audio.RnnoiseProcesser;
|
||||
|
||||
import org.webrtc.CalledByNative;
|
||||
import org.webrtc.Logging;
|
||||
import org.webrtc.ThreadUtils;
|
||||
@@ -110,7 +108,6 @@ class WebRtcAudioRecord {
|
||||
private @Nullable SamplesReadyCallback audioSamplesReadyCallback;
|
||||
private final boolean isAcousticEchoCancelerSupported;
|
||||
private final boolean isNoiseSuppressorSupported;
|
||||
private RnnoiseProcesser rnnoiseProcesser;
|
||||
|
||||
/**
|
||||
* 设置录音工具
|
||||
@@ -162,8 +159,6 @@ class WebRtcAudioRecord {
|
||||
if (microphoneMute) {
|
||||
byteBuffer.clear();
|
||||
byteBuffer.put(emptyBytes);
|
||||
} else {
|
||||
WebRtcAudioRecord.this.rnnoiseProcesser.rnnoise(byteBuffer.arrayOffset(), byteBuffer.capacity(), byteBuffer.array());
|
||||
}
|
||||
// It's possible we've been shut down during the read, and stopRecording() tried and
|
||||
// failed to join this thread. To be a bit safer, try to avoid calling any native methods
|
||||
@@ -201,7 +196,6 @@ class WebRtcAudioRecord {
|
||||
try {
|
||||
if (audioRecord != null) {
|
||||
audioRecord.stop();
|
||||
WebRtcAudioRecord.this.rnnoiseProcesser.release();
|
||||
doAudioRecordStateCallback(AUDIO_RECORD_STOP);
|
||||
}
|
||||
} catch (IllegalStateException e) {
|
||||
@@ -414,8 +408,6 @@ class WebRtcAudioRecord {
|
||||
}
|
||||
}
|
||||
try {
|
||||
this.rnnoiseProcesser = new RnnoiseProcesser();
|
||||
this.rnnoiseProcesser.init();
|
||||
audioRecord.startRecording();
|
||||
} catch (IllegalStateException e) {
|
||||
reportWebRtcAudioRecordStartError(AudioRecordStartErrorCode.AUDIO_RECORD_START_EXCEPTION,
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
pluginManagement {
|
||||
repositories {
|
||||
maven { url 'https://maven.aliyun.com/repository/google' }
|
||||
maven { url 'https://maven.aliyun.com/repository/public' }
|
||||
maven { url 'https://maven.aliyun.com/repository/central' }
|
||||
maven { url 'https://maven.aliyun.com/repository/jcenter' }
|
||||
maven { url 'https://maven.aliyun.com/repository/releases' }
|
||||
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
@@ -8,6 +14,12 @@ pluginManagement {
|
||||
dependencyResolutionManagement {
|
||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||
repositories {
|
||||
maven { url 'https://maven.aliyun.com/repository/google' }
|
||||
maven { url 'https://maven.aliyun.com/repository/public' }
|
||||
maven { url 'https://maven.aliyun.com/repository/central' }
|
||||
maven { url 'https://maven.aliyun.com/repository/jcenter' }
|
||||
maven { url 'https://maven.aliyun.com/repository/releases' }
|
||||
maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
|
||||
google()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
@@ -25,9 +25,9 @@ else
|
||||
fi
|
||||
|
||||
# 启动参数
|
||||
JAVA_OPTS_GC="-XX:+UseG1GC -Xlog:gc:./logs/gc.log:time,level"
|
||||
JAVA_OPTS_GC="-XX:+UseG1GC -Xlog:gc:./logs/gc.log:time,level,tags:filecount=16,filesize=128m"
|
||||
JAVA_OPTS_MEM="-server ${taoyao.maven.jvm.mem}"
|
||||
JAVA_OPTS_EXT="-Dfile.encoding=${taoyao.maven.encoding} -Djava.awt.headless=true -Djava.net.preferIPv4Stack=true"
|
||||
JAVA_OPTS_EXT="-Dfile.encoding=${taoyao.maven.encoding} -Djava.awt.headless=true -Duser.timezone=Asia/Shanghai -Djava.net.preferIPv4Stack=true"
|
||||
JAVA_OPTS_APP="-Dspring.profiles.active=${profile}"
|
||||
JAVA_OPTS="$JAVA_OPTS_MEM $JAVA_OPTS_EXT $JAVA_OPTS_APP ${taoyao.maven.jvm.arg}"
|
||||
echo "启动参数:$JAVA_OPTS"
|
||||
|
||||
@@ -123,7 +123,7 @@ public class BootAutoConfiguration {
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Primary
|
||||
// @Primary
|
||||
@ConditionalOnMissingBean
|
||||
public TaskScheduler taskScheduler(TaskSchedulerBuilder builder) {
|
||||
return builder.build();
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.acgist.taoyao.boot.configuration;
|
||||
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
|
||||
@@ -23,7 +24,7 @@ public class WebMvcConfigurerAutoConfiguration implements WebMvcConfigurer {
|
||||
private final ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
public void addInterceptors(@NonNull InterceptorRegistry registry) {
|
||||
this.applicationContext.getBeansOfType(InterceptorAdapter.class).entrySet().stream()
|
||||
.sorted((a, z) -> a.getValue().compareTo(z.getValue()))
|
||||
.forEach(entry -> {
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
import com.acgist.taoyao.boot.config.SecurityProperties;
|
||||
@@ -63,7 +64,7 @@ public class SecurityInterceptor extends InterceptorAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception {
|
||||
if(this.permit(request) || this.authorization(request)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.acgist.taoyao.interceptor;
|
||||
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.lang.Nullable;
|
||||
|
||||
import com.acgist.taoyao.boot.config.TaoyaoProperties;
|
||||
import com.acgist.taoyao.boot.interceptor.InterceptorAdapter;
|
||||
|
||||
@@ -43,13 +46,13 @@ public class SlowInterceptor extends InterceptorAdapter {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler) throws Exception {
|
||||
this.local.set(System.currentTimeMillis());
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception e) throws Exception {
|
||||
public void afterCompletion(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @NonNull Object handler, @Nullable Exception e) throws Exception {
|
||||
final long duration = System.currentTimeMillis() - this.local.get();
|
||||
if(duration > this.taoyaoProperties.getTimeout()) {
|
||||
log.info("请求执行时间过慢:{} - {}", request.getRequestURI(), duration);
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.acgist.taoyao.listener;
|
||||
|
||||
import org.springframework.boot.context.event.ApplicationStartingEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@@ -17,7 +18,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
public class QnjrcmzListener implements ApplicationListener<ApplicationStartingEvent> {
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationStartingEvent event) {
|
||||
public void onApplicationEvent(@NonNull ApplicationStartingEvent event) {
|
||||
synchronized (QnjrcmzListener.class) {
|
||||
log.debug("配置忽略证书域名校验");
|
||||
// 配置JDK HTTPClient域名校验问题
|
||||
|
||||
@@ -2,6 +2,7 @@ package com.acgist.taoyao.listener;
|
||||
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Listener;
|
||||
import com.acgist.taoyao.boot.config.TaoyaoProperties;
|
||||
@@ -19,7 +20,7 @@ import lombok.extern.slf4j.Slf4j;
|
||||
public class ThyjxcfListener implements ApplicationListener<ApplicationReadyEvent> {
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationReadyEvent event) {
|
||||
public void onApplicationEvent(@NonNull ApplicationReadyEvent event) {
|
||||
synchronized (ThyjxcfListener.class) {
|
||||
final TaoyaoProperties taoyaoProperties = event.getApplicationContext().getBean(TaoyaoProperties.class);
|
||||
log.info("项目启动成功:{}", taoyaoProperties.getName());
|
||||
|
||||
@@ -6,6 +6,7 @@ import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.test.context.TestContext;
|
||||
import org.springframework.test.context.TestExecutionListener;
|
||||
|
||||
@@ -20,13 +21,13 @@ import lombok.extern.slf4j.Slf4j;
|
||||
public class CostedTestTestExecutionListener implements TestExecutionListener {
|
||||
|
||||
@Override
|
||||
public void afterTestMethod(TestContext testContext) throws Exception {
|
||||
public void afterTestMethod(@NonNull TestContext testContext) throws Exception {
|
||||
final CostedTest costedTest = testContext.getTestMethod().getDeclaredAnnotation(CostedTest.class);
|
||||
if(costedTest == null) {
|
||||
return;
|
||||
}
|
||||
final int count = costedTest.count();
|
||||
final int thread = costedTest.thread();
|
||||
final int count = costedTest.count();
|
||||
final int thread = costedTest.thread();
|
||||
final long timeout = costedTest.timeout();
|
||||
final TimeUnit timeUnit = costedTest.timeUnit();
|
||||
final long aTime = System.currentTimeMillis();
|
||||
|
||||
@@ -5,6 +5,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.web.socket.config.annotation.EnableWebSocket;
|
||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||
import org.springframework.web.socket.server.standard.ServletServerContainerFactoryBean;
|
||||
|
||||
import com.acgist.taoyao.signal.client.websocket.WebSocketSignal;
|
||||
|
||||
@@ -29,4 +30,13 @@ public class WebSocketSignalAutoConfiguration {
|
||||
return new ServerEndpointExporter();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ServletServerContainerFactoryBean createWebSocketContainer() {
|
||||
final ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
|
||||
container.setMaxSessionIdleTimeout(60L * 1000);
|
||||
container.setMaxTextMessageBufferSize(1024 * 1024);
|
||||
container.setMaxBinaryMessageBufferSize(1024 * 1024);
|
||||
return container;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.acgist.taoyao.signal.protocol.client;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
@@ -44,7 +45,7 @@ public class ClientCloseProtocol extends ProtocolClientAdapter implements Applic
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void onApplicationEvent(ClientCloseEvent event) {
|
||||
public void onApplicationEvent(@NonNull ClientCloseEvent event) {
|
||||
this.close(event.getClient());
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
@@ -52,7 +53,7 @@ public class ClientConfigProtocol extends ProtocolClientAdapter implements Appli
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void onApplicationEvent(ClientConfigEvent event) {
|
||||
public void onApplicationEvent(@NonNull ClientConfigEvent event) {
|
||||
final Client client = event.getClient();
|
||||
final ClientType clientType = client.getClientType();
|
||||
client.push(this.build(clientType));
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.acgist.taoyao.signal.protocol.client;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
@@ -38,7 +39,7 @@ public class ClientOfflineProtocol extends ProtocolClientAdapter implements Appl
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void onApplicationEvent(ClientOfflineEvent event) {
|
||||
public void onApplicationEvent(@NonNull ClientOfflineEvent event) {
|
||||
final String clientId = event.getClientId();
|
||||
this.clientManager.broadcast(clientId, this.build(
|
||||
Map.of(Constant.CLIENT_ID, clientId)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.acgist.taoyao.signal.protocol.client;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
@@ -49,7 +50,7 @@ public class ClientOnlineProtocol extends ProtocolClientAdapter implements Appli
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void onApplicationEvent(ClientOnlineEvent event) {
|
||||
public void onApplicationEvent(@NonNull ClientOnlineEvent event) {
|
||||
final Client client = event.getClient();
|
||||
final String clientId = event.getClientId();
|
||||
this.clientManager.broadcast(
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
@@ -61,7 +62,7 @@ public class ControlServerRecordProtocol extends ProtocolControlAdapter implemen
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void onApplicationEvent(RecorderCloseEvent event) {
|
||||
public void onApplicationEvent(@NonNull RecorderCloseEvent event) {
|
||||
final Recorder recorder = event.getRecorder();
|
||||
this.stop(recorder.getRoom(), recorder.getClientWrapper());
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
@@ -72,7 +73,7 @@ public class MediaConsumeProtocol extends ProtocolRoomAdapter implements Applica
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void onApplicationEvent(MediaConsumeEvent event) {
|
||||
public void onApplicationEvent(@NonNull MediaConsumeEvent event) {
|
||||
final Room room = event.getRoom();
|
||||
if(event.getProducer() != null) {
|
||||
// 生产媒体:其他终端消费
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.acgist.taoyao.signal.protocol.media;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
@@ -50,7 +51,7 @@ public class MediaConsumerCloseProtocol extends ProtocolRoomAdapter implements A
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void onApplicationEvent(MediaConsumerCloseEvent event) {
|
||||
public void onApplicationEvent(@NonNull MediaConsumerCloseEvent event) {
|
||||
final Room room = event.getRoom();
|
||||
final Client mediaClient = event.getMediaClient();
|
||||
final Map<String, Object> body = Map.of(
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.acgist.taoyao.signal.protocol.media;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
@@ -48,7 +49,7 @@ public class MediaConsumerPauseProtocol extends ProtocolRoomAdapter implements A
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void onApplicationEvent(MediaConsumerPauseEvent event) {
|
||||
public void onApplicationEvent(@NonNull MediaConsumerPauseEvent event) {
|
||||
final Room room = event.getRoom();
|
||||
final Client mediaClient = event.getMediaClient();
|
||||
final Map<String, Object> body = Map.of(
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.acgist.taoyao.signal.protocol.media;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
@@ -48,7 +49,7 @@ public class MediaConsumerResumeProtocol extends ProtocolRoomAdapter implements
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void onApplicationEvent(MediaConsumerResumeEvent event) {
|
||||
public void onApplicationEvent(@NonNull MediaConsumerResumeEvent event) {
|
||||
final Room room = event.getRoom();
|
||||
final Client mediaClient = event.getMediaClient();
|
||||
final Map<String, Object> body = Map.of(
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.acgist.taoyao.signal.protocol.media;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
@@ -50,7 +51,7 @@ public class MediaDataConsumerCloseProtocol extends ProtocolRoomAdapter implemen
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void onApplicationEvent(MediaDataConsumerCloseEvent event) {
|
||||
public void onApplicationEvent(@NonNull MediaDataConsumerCloseEvent event) {
|
||||
final Room room = event.getRoom();
|
||||
final Client mediaClient = event.getMediaClient();
|
||||
final Map<String, Object> body = Map.of(
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.acgist.taoyao.signal.protocol.media;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
@@ -50,7 +51,7 @@ public class MediaDataProducerCloseProtocol extends ProtocolRoomAdapter implemen
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void onApplicationEvent(MediaDataProducerCloseEvent event) {
|
||||
public void onApplicationEvent(@NonNull MediaDataProducerCloseEvent event) {
|
||||
final Room room = event.getRoom();
|
||||
final Client mediaClient = event.getMediaClient();
|
||||
final Map<String, Object> body = Map.of(
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.acgist.taoyao.signal.protocol.media;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
@@ -50,7 +51,7 @@ public class MediaProducerCloseProtocol extends ProtocolRoomAdapter implements A
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void onApplicationEvent(MediaProducerCloseEvent event) {
|
||||
public void onApplicationEvent(@NonNull MediaProducerCloseEvent event) {
|
||||
final Room room = event.getRoom();
|
||||
final Client mediaClient = event.getMediaClient();
|
||||
final Map<String, Object> body = Map.of(
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.acgist.taoyao.signal.protocol.media;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
import com.acgist.taoyao.boot.annotation.Protocol;
|
||||
@@ -43,7 +44,7 @@ public class MediaProducerPauseProtocol extends ProtocolRoomAdapter implements A
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(MediaProducerPauseEvent event) {
|
||||
public void onApplicationEvent(@NonNull MediaProducerPauseEvent event) {
|
||||
final Room room = event.getRoom();
|
||||
final Client mediaClient = event.getMediaClient();
|
||||
final Map<String, Object> body = Map.of(
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.acgist.taoyao.signal.protocol.media;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
import com.acgist.taoyao.boot.annotation.Protocol;
|
||||
@@ -43,7 +44,7 @@ public class MediaProducerResumeProtocol extends ProtocolRoomAdapter implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(MediaProducerResumeEvent event) {
|
||||
public void onApplicationEvent(@NonNull MediaProducerResumeEvent event) {
|
||||
final Room room = event.getRoom();
|
||||
final Client mediaClient = event.getMediaClient();
|
||||
final Map<String, Object> body = Map.of(
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.acgist.taoyao.signal.protocol.media;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
@@ -50,7 +51,7 @@ public class MediaTransportCloseProtocol extends ProtocolRoomAdapter implements
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void onApplicationEvent(TransportCloseEvent event) {
|
||||
public void onApplicationEvent(@NonNull TransportCloseEvent event) {
|
||||
final Room room = event.getRoom();
|
||||
final Client mediaClient = event.getMediaClient();
|
||||
final Map<String, Object> body = Map.of(
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.acgist.taoyao.signal.protocol.room;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
@@ -68,7 +69,7 @@ public class RoomClientListProtocol extends ProtocolRoomAdapter implements Appli
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void onApplicationEvent(RoomEnterEvent event) {
|
||||
public void onApplicationEvent(@NonNull RoomEnterEvent event) {
|
||||
final Room room = event.getRoom();
|
||||
final Client client = event.getClient();
|
||||
client.push(this.build(Map.of(
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.acgist.taoyao.signal.protocol.room;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
import com.acgist.taoyao.boot.annotation.Protocol;
|
||||
@@ -37,7 +38,7 @@ public class RoomCloseProtocol extends ProtocolRoomAdapter implements Applicatio
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(RoomCloseEvent event) {
|
||||
public void onApplicationEvent(@NonNull RoomCloseEvent event) {
|
||||
final Room room = event.getRoom();
|
||||
final Client mediaClient = room.getMediaClient();
|
||||
mediaClient.push(this.build(Map.of(
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.acgist.taoyao.signal.protocol.room;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
@@ -55,7 +56,7 @@ public class RoomCreateProtocol extends ProtocolClientAdapter implements Applica
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void onApplicationEvent(MediaServerRegisterEvent event) {
|
||||
public void onApplicationEvent(@NonNull MediaServerRegisterEvent event) {
|
||||
this.roomManager.recreate(event.getClient(), this.build());
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.acgist.taoyao.signal.protocol.room;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
import org.springframework.scheduling.annotation.Async;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
@@ -50,7 +51,7 @@ public class RoomLeaveProtocol extends ProtocolRoomAdapter implements Applicatio
|
||||
|
||||
@Async
|
||||
@Override
|
||||
public void onApplicationEvent(RoomLeaveEvent event) {
|
||||
public void onApplicationEvent(@NonNull RoomLeaveEvent event) {
|
||||
final Room room = event.getRoom();
|
||||
final Client client = event.getClient();
|
||||
final Map<String, String> body = Map.of(
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.acgist.taoyao.signal.protocol.session;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.lang.NonNull;
|
||||
|
||||
import com.acgist.taoyao.boot.annotation.Description;
|
||||
import com.acgist.taoyao.boot.annotation.Protocol;
|
||||
@@ -40,7 +41,7 @@ public class SessionCloseProtocol extends ProtocolSessionAdapter implements Appl
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(SessionCloseEvent event) {
|
||||
public void onApplicationEvent(@NonNull SessionCloseEvent event) {
|
||||
final Session session = event.getSession();
|
||||
session.push(this.build(Map.of(
|
||||
Constant.SESSION_ID,
|
||||
|
||||
Reference in New Issue
Block a user