30 Commits

Author SHA1 Message Date
acgist
32a828aead [+] 优化代码 2025-11-13 15:12:42 +08:00
acgist
f9de241e09 [+] 共享原生WebRTC 2025-11-13 15:01:02 +08:00
acgist
95398a0f64 [+] 配置 2025-09-28 18:02:10 +08:00
acgist
2d065876db Merge branch 'master' into dev 2025-04-21 09:34:23 +08:00
acgist
811a57a27b [~] @NonNull 2025-04-21 09:33:53 +08:00
acgist
cb9c30ddcb [~] 启动脚本优化 2025-03-05 15:52:33 +08:00
acgist
9ec8cf4216 [~] 优化 2025-03-05 15:48:35 +08:00
acgist
40149bc496 [~] 仓库 2025-02-07 08:20:09 +08:00
acgist
ec89b669c4 [~] 仓库 2025-02-07 08:14:21 +08:00
acgist
65904706ca [*] readme 2025-01-08 17:51:02 +08:00
acgist
94d18908cd [*] 修改gradle下载路径 2024-11-14 11:04:29 +08:00
acgist
0673df4d95 [*] README 2024-11-14 10:58:12 +08:00
acgist
91265b9b23 [+] build.yml 2024-11-14 10:47:47 +08:00
acgist
571aec369d [+] build.yml 2024-11-14 10:30:07 +08:00
acgist
07de78ce9c Merge branch 'dev' into release 2024-11-14 10:17:36 +08:00
acgist
a5ccc17ecb [*] 优化deps 2024-11-14 10:01:58 +08:00
acgist
ed6855feef [*] 优化deps 2024-11-14 10:00:05 +08:00
acgist
d7ee0ee99b [*] 修复异常问题 2024-09-04 13:56:31 +08:00
acgist
936f68c714 [*] 修复异常问题 2024-09-04 13:44:06 +08:00
acgist
1ab550b002 [*] setBitrate 2024-04-19 15:16:03 +08:00
acgist
cd74941a36 [*] 2024-04-11 17:35:36 +08:00
acgist
306b60887a [*] 码率 2024-04-10 17:02:59 +08:00
acgist
ebe8a62fed [*] setBitrate 2024-04-10 09:37:19 +08:00
acgist
8a850c2655 [*] java setbitrate 2024-04-09 07:41:59 +08:00
acgist
402318a080 [*] setBitrate 2024-04-09 07:16:15 +08:00
acgist
0f165a78c4 [*] deploy 2024-01-24 18:29:46 +08:00
acgist
f4ad326ecf [*] taoyao 2024-01-24 18:26:55 +08:00
acgist
d4dab26a05 [*] 判断优化 2024-01-23 11:51:15 +08:00
acgist
a3644cbb13 [*] deploy 2024-01-20 14:46:18 +08:00
acgist
fb4f64c20a [*] 部署 2024-01-20 10:03:39 +08:00
49 changed files with 543 additions and 73 deletions

View File

@@ -86,8 +86,9 @@ jobs:
- name: Checkout libmediasoupclient
uses: actions/checkout@v3
with:
repository: acgist/libmediasoupclient
repository: versatica/libmediasoupclient
path: ./taoyao-client-android/taoyao/media/deps/libmediasoupclient
ref: '97c42457b6a73a3eeef45dc37f1c90bb7d28cdff'
- name: Set up JDK
uses: actions/setup-java@v1
with:

2
.gitignore vendored
View File

@@ -9,6 +9,8 @@ build
target
node_modules
.idea
.vscode
package-lock.json

6
.gitmodules vendored
View File

@@ -1,9 +1,9 @@
[submodule "taoyao-client-media/mediasoup"]
path = taoyao-client-media/mediasoup
url = https://gitee.com/acgist/mediasoup.git
url = https://github.com/versatica/mediasoup.git
[submodule "taoyao-client-web/mediasoup-client"]
path = taoyao-client-web/mediasoup-client
url = https://gitee.com/acgist/mediasoup-client.git
url = https://github.com/versatica/mediasoup-client.git
[submodule "taoyao-client-android/libmediasoupclient"]
path = taoyao-client-android/libmediasoupclient
url = https://gitee.com/acgist/libmediasoupclient.git
url = https://github.com/versatica/libmediasoupclient.git

View File

@@ -10,14 +10,14 @@ Maven >= 3.8.0
CMake >= 3.26.0
NodeJS >= v18.16.0
Python >= 3.8.0 with PIP
ffmpeg >= 4.3.0
gcc/g++ >= 10.2.0
FFmpeg >= 4.3.0
GCC/G++ >= 10.2.0
Android >= 9.0
```
## Debian
`CentOS 7`实在是太旧了,软件更新非常麻烦,所以直接使用`Debian`作为测试,系统配置全部使用`root`用户
`CentOS 7`实在是太旧了,软件更新非常麻烦,所以直接使用`Debian`作为测试。
### 系统参数
@@ -66,6 +66,7 @@ set nocompatible
vi /etc/network/interfaces
---
auto enp0s3
iface enp0s3 inet static
address 192.168.1.110
gateway 192.168.1.1
@@ -80,6 +81,17 @@ ifup enp0s3
### 设置国内镜像
```
# DNS
sudo vim /etc/systemd/resolved.conf
---
DNS=233.5.5.5 233.6.6.6 114.114.114.114 8.8.8.8
---
sudo systemctl restart systemd-resolved
sudo systemctl enable systemd-resolved
sudo ln -sf /run/systemd/resolve/resolv.conf /etc/resolv.conf
# 配置
vi /etc/apt/sources.list
@@ -96,6 +108,7 @@ deb-src https://mirrors.aliyun.com/debian/ bullseye-backports main non-free cont
# 更新系统
apt update
apt upgrade
```
### 安装依赖
@@ -177,7 +190,7 @@ sudo apt install git
git --version
```
## 安装gcc/g++
## 安装GCC/G++
```
# 安装
@@ -335,7 +348,7 @@ trusted-host = mirrors.aliyun.com
pip config list
```
## 安装ffmpeg
## 安装FFmpeg
```
mkdir -p /data/dev/ffmpeg ; cd $_
@@ -395,11 +408,11 @@ wget http://www.ffmpeg.org/releases/ffmpeg-5.1.3.tar.xz
tar -Jxvf ffmpeg-5.1.3.tar.xz
cd ffmpeg-5.1.3/
PKG_CONFIG_PATH="/usr/local/lib/pkgconfig/"
./configure \
--enable-static \
--enable-shared \
--enable-gpl \
--enable-libvpx \
./configure \
--enable-static \
--enable-shared \
--enable-gpl \
--enable-libvpx \
--enable-libopus \
--enable-libx264 \
--enable-libx265 \
@@ -407,6 +420,15 @@ PKG_CONFIG_PATH="/usr/local/lib/pkgconfig/"
--enable-encoder=libvpx_vp9 --enable-decoder=vp9 --enable-parser=vp9
make && sudo make install
# 链接文件
vim /etc/ld.so.conf
---
/usr/local/lib/
---
ldconfig
# 验证
ffmpeg -version
ffmpeg -decoders
@@ -488,7 +510,7 @@ pm2 start|stop|restart taoyao-client-media
> 下载依赖建议备份方便再次编译使用
### Mediasoup单独编译
### Mediasoup单独编译(旧版)
编译媒体服务时会自动编译`mediasoup`所以忽略单独编译
@@ -502,6 +524,16 @@ make
make clean
```
### Mediasoup单独编译新版
* 需要`python3``pip3`
* 源码[mediasoup-3.13.16.zip](https://pan.baidu.com/s/1E_DXv32D9ODyj5J-o-ji_g?pwd=hudc)(包含依赖)
```
npm install
node npm-scripts.mjs worker:build
```
## 安装Web终端
`Nginx``PM2`选择一种启动即可
@@ -625,7 +657,7 @@ openssl pkcs12 -export -clcerts -in server.crt -inkey server.key -out server.p12
# 设置密码:-deststorepass 123456
```
## gcc/g++路径配置
## GCC/G++路径配置
```
# 安装路径
@@ -645,11 +677,11 @@ openssl pkcs12 -export -clcerts -in server.crt -inkey server.key -out server.p12
## 清理源码
```
sudo rm -rf \
/data/dev/cmake \
sudo rm -rf \
/data/dev/cmake \
/data/dev/ffmpeg \
/data/dev/python \
/data/dev/maven/apache-maven-3.8.8-bin.tar.gz \
/data/dev/maven/apache-maven-3.8.8-bin.tar.gz \
/data/dev/nodejs/node-v18.16.0-linux-x64.tar.xz \
/data/dev/java/openjdk-17.0.2_linux-x64_bin.tar.gz
```

View File

@@ -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

View File

@@ -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`目录。
@@ -37,6 +42,12 @@
* WebRtcAudioRecord
* WebRtcAudioTrack
## 动态修改码率
```
HardwareVideoEncoder#updateBitrate
```
## 学习资料
* https://developer.android.google.cn/docs?hl=zh-cn

View File

@@ -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>

View File

@@ -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

View File

@@ -0,0 +1,16 @@
# 目录结构
```
├─deps
│ ├─libmediasoupclient
│ │ libmediasoupclient源码
│ └─webrtc
│ ├─lib
│ │ └─arm64-v8a
│ │ libwebrtc.a
│ │ WebRTC静态库
│ └─src
│ ├─api
│ │ WebRTC头文件
```

View File

@@ -175,6 +175,14 @@ namespace acgist {
* @param env JNIEnv
*/
void closeRoom(JNIEnv* env);
/**
* 设置码率
*
* @param maxFramerate 最大帧率
* @param minBitrate 最小码率
* @param maxBitrate 最大码率
*/
void setBitrate(int maxFramerate, int minBitrate, int maxBitrate);
};
}

View File

@@ -342,6 +342,8 @@ namespace acgist {
}
this->factory = factory;
this->rtcConfiguration = new webrtc::PeerConnectionInterface::RTCConfiguration(rtcConfiguration);
// this->rtcConfiguration->set_cpu_adaptation(false);
// this->rtcConfiguration->set_experiment_cpu_load_estimator(false);
mediasoupclient::PeerConnection::Options options;
options.config = rtcConfiguration;
options.factory = factory;
@@ -418,7 +420,7 @@ namespace acgist {
nlohmann::json codecOptions =
{
// x-google-start-bitrate
{ "videoGoogleStartBitrate", 400 },
{ "videoGoogleStartBitrate", 1200 },
// x-google-min-bitrate
{ "videoGoogleMinBitrate", 800 },
// x-google-max-bitrate
@@ -552,6 +554,53 @@ namespace acgist {
this->closeRoomCallback(env);
}
void Room::setBitrate(int maxFramerate, int minBitrate, int maxBitrate) {
// if(
// this->sendTransport == nullptr ||
// this->sendTransport->sendHandler == nullptr ||
// this->sendTransport->sendHandler->pc == nullptr ||
// this->sendTransport->sendHandler->pc->pc == nullptr
// ) {
// return;
// }
// webrtc::BitrateSettings settings;
// settings.min_bitrate_bps = minBitrate;
// settings.max_bitrate_bps = maxBitrate;
// settings.start_bitrate_bps = minBitrate;
// this->sendTransport->sendHandler->pc->pc->SetBitrate(settings);
webrtc::RtpSenderInterface* rtpSender;
if(
this->videoProducer == nullptr ||
(rtpSender = this->videoProducer->GetRtpSender()) == nullptr
) {
return;
}
webrtc::RtpParameters rtpParameters = rtpSender->GetParameters();
auto& encodings = rtpParameters.encodings;
for(
auto iterator = encodings.begin();
iterator != encodings.end();
++iterator
) {
if(maxFramerate > 0) {
LOG_I("当前最大帧率:%d - %d", maxFramerate, iterator->max_framerate);
iterator->max_framerate = maxFramerate;
}
if(minBitrate > 0) {
LOG_I("当前最小码率:%d - %d", minBitrate, iterator->min_bitrate_bps);
iterator->min_bitrate_bps = minBitrate;
}
if(maxBitrate > 0) {
LOG_I("当前最大码率:%d - %d", maxBitrate, iterator->max_bitrate_bps);
iterator->max_bitrate_bps = maxBitrate;
}
// iterator->bitrate_priority = 4.0;
// iterator->network_priority = webrtc::Priority::kHigh;
// iterator->scale_resolution_down_by = 2;
}
rtpSender->SetParameters(rtpParameters);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_acgist_taoyao_media_client_Room_nativeNewRoom(
JNIEnv* env, jobject me,
@@ -727,4 +776,13 @@ namespace acgist {
env->ReleaseStringUTFChars(jConsumerId, consumerId);
}
extern "C" JNIEXPORT void JNICALL
Java_com_acgist_taoyao_media_client_Room_nativeSetBitrate(JNIEnv* env, jobject me, jlong nativeRoomPointer, jint maxFramerate, jint minBitrate, jint maxBitrate) {
Room* room = (Room*) nativeRoomPointer;
if(room == nullptr) {
return;
}
room->setBitrate(maxFramerate, minBitrate, maxBitrate);
}
}

View File

@@ -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
*/

View File

@@ -22,7 +22,13 @@ public enum VideoSourceType {
/**
* 屏幕共享ScreenCapturerAndroid
*/
SCREEN;
SCREEN,
/**
* 共享本地ShareVideoCapturer
*
* 注意:这个模式只是用来测试很多功能没有兼容
*/
SHARE;
/**
* @return 是否是摄像头

View File

@@ -207,6 +207,7 @@ public class Room extends CloseableClient implements RouterCallback {
iceServers = new ArrayList<>();
}
this.rtcConfiguration = new PeerConnection.RTCConfiguration(iceServers);
// this.rtcConfiguration.enableCpuOveruseDetection = true;
// 开始协商
return this.taoyao.requestFuture(
this.taoyao.buildMessage("media::router::rtp::capabilities", "roomId", this.roomId),
@@ -288,7 +289,7 @@ public class Room extends CloseableClient implements RouterCallback {
"forceTcp", false,
"producing", false,
"consuming", true,
"sctpCapabilities", this.dataProduce ? this.sctpCapabilities : null
"sctpCapabilities", this.dataConsume ? this.sctpCapabilities : null
),
response -> {
this.nativeCreateRecvTransport(this.nativeRoomPointer, JSONUtils.toJSON(response.body()));
@@ -382,6 +383,19 @@ public class Room extends CloseableClient implements RouterCallback {
remoteClient.close();
}
/**
* 动态设置帧率码率
*
* HardwareVideoEncoder#updateBitrate()
*
* @param maxFramerate 最大帧率
* @param minBitrate 最小码率
* @param maxBitrate 最大码率
*/
public void setBitrate(int maxFramerate, int minBitrate, int maxBitrate) {
this.nativeSetBitrate(this.nativeRoomPointer, maxFramerate, minBitrate, maxBitrate);
}
@Override
public void close() {
synchronized (this) {
@@ -773,4 +787,14 @@ public class Room extends CloseableClient implements RouterCallback {
*/
private native void nativeMediaConsumerClose(long nativeRoomPointer, String consumerId);
/**
* Mediasoup设置码率
*
* @param nativeRoomPointer 房间指针
* @param maxFramerate 最大帧率
* @param minBitrate 最小码率
* @param maxBitrate 最大码率
*/
private native void nativeSetBitrate(long nativeRoomPointer, int maxFramerate, int minBitrate, int maxBitrate);
}

View File

@@ -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

View File

@@ -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();
}
}
});
}
}

View File

@@ -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()
}

View File

@@ -2329,6 +2329,9 @@ class Taoyao extends RemoteClient {
videoSource: this.videoSource
},
});
// let oldParameters = this.videoProducer.rtpSender.getParameters();
// oldParameters.encodings[0].maxBitrate = 800000;
// this.videoProducer.rtpSender.setParameters(oldParameters);
this.callbackTrack(this.clientId, track);
if (this.proxy && this.proxy.media) {
this.proxy.media(track, this.videoProducer);
@@ -2839,7 +2842,7 @@ class Taoyao extends RemoteClient {
forceTcp : this.forceTcp,
producing : false,
consuming : true,
sctpCapabilities: this.dataProduce ? this.mediasoupDevice.sctpCapabilities : undefined,
sctpCapabilities: this.dataConsume ? this.mediasoupDevice.sctpCapabilities : undefined,
}));
const {
transportId,

View File

@@ -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"

View File

@@ -123,7 +123,7 @@ public class BootAutoConfiguration {
}
@Bean
@Primary
// @Primary
@ConditionalOnMissingBean
public TaskScheduler taskScheduler(TaskSchedulerBuilder builder) {
return builder.build();

View File

@@ -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 -> {

View File

@@ -207,7 +207,7 @@ public final class DateUtils {
*
* @return 日期字符串
*/
public static String format(LocalDate localDate, DateStyle format) {
public static final String format(LocalDate localDate, DateStyle format) {
return localDate != null && format != null ? format.getDateTimeFormatter().format(localDate) : null;
}
@@ -219,7 +219,7 @@ public final class DateUtils {
*
* @return 时间字符串
*/
public static String format(LocalTime localTime, TimeStyle format) {
public static final String format(LocalTime localTime, TimeStyle format) {
return localTime != null && format != null ? format.getDateTimeFormatter().format(localTime) : null;
}
@@ -231,7 +231,7 @@ public final class DateUtils {
*
* @return 日期时间字符串
*/
public static String format(LocalDateTime localDateTime, DateTimeStyle format) {
public static final String format(LocalDateTime localDateTime, DateTimeStyle format) {
return localDateTime != null && format != null ? format.getDateTimeFormatter().format(localDateTime) : null;
}

View File

@@ -102,11 +102,14 @@ public final class ErrorUtils {
final MessageCode messageCode = messageCodeException.getMessageCode();
status = messageCode.getStatus();
message = Message.fail(messageCode, messageCodeException.getMessage());
} else if(rootError instanceof Throwable throwable) {
} else if(
rootError instanceof Throwable rootThrowable &&
globalError instanceof Throwable globalThrowable
) {
// 未知异常:异常转换
final MessageCode messageCode = ErrorUtils.messageCode(status, throwable);
final MessageCode messageCode = ErrorUtils.messageCode(status, globalThrowable, rootThrowable);
status = messageCode.getStatus();
message = Message.fail(messageCode, ErrorUtils.message(messageCode, throwable));
message = Message.fail(messageCode, ErrorUtils.message(messageCode, rootThrowable));
} else {
// 没有异常
final MessageCode messageCode = MessageCode.of(status);
@@ -193,20 +196,35 @@ public final class ErrorUtils {
}
/**
* @param status 原始状态编码
* @param throwable 异常
* @see #messageCode(int, Throwable, Throwable)
*/
public static final MessageCode messageCode(int status, Throwable throwable) {
return ErrorUtils.messageCode(status, throwable, throwable);
}
/**
* @param status 原始状态
* @param globalThrowable 外层异常
* @param rootThrowable 原始异常
*
* @return 状态编码
* @return 响应状态
*
* @see ResponseEntityExceptionHandler
* @see DefaultHandlerExceptionResolver
*/
public static final MessageCode messageCode(int status, Throwable throwable) {
final Class<?> clazz = throwable.getClass();
public static final MessageCode messageCode(int status, Throwable globalThrowable, Throwable rootThrowable) {
if(rootThrowable == null || globalThrowable == null) {
return MessageCode.CODE_9999;
}
final Class<?> rootClazz = rootThrowable.getClass();
final Class<?> globalClazz = globalThrowable.getClass();
return CODE_MAPPING.entrySet().stream()
.filter(entry -> {
final Class<?> mappingClazz = entry.getKey();
return mappingClazz.equals(clazz) || mappingClazz.isAssignableFrom(clazz);
return mappingClazz.equals(globalClazz) ||
mappingClazz.isAssignableFrom(globalClazz) ||
mappingClazz.equals(rootClazz) ||
mappingClazz.isAssignableFrom(rootClazz);
})
.map(Map.Entry::getValue)
.findFirst()
@@ -271,7 +289,7 @@ public final class ErrorUtils {
if(cause instanceof MessageCodeException) {
return cause;
}
} while(cause != null && (cause = cause.getCause()) != null);
} while(cause != null && cause.getCause() != null && (cause = cause.getCause()) != null);
// 返回原始异常
return t;
}

View File

@@ -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;
}

View File

@@ -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);

View File

@@ -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域名校验问题

View File

@@ -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());

View File

@@ -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();

View File

@@ -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;
}
}

View File

@@ -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());
}

View File

@@ -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));

View File

@@ -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)

View File

@@ -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(

View File

@@ -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());
}

View File

@@ -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) {
// 生产媒体:其他终端消费

View File

@@ -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(

View File

@@ -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(

View File

@@ -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(

View File

@@ -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(

View File

@@ -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(

View File

@@ -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(

View File

@@ -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(

View File

@@ -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(

View File

@@ -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(

View File

@@ -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(

View File

@@ -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(

View File

@@ -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());
}

View File

@@ -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(

View File

@@ -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,