[+] 控制

This commit is contained in:
acgist
2024-05-07 17:51:02 +08:00
parent 754e4beb2c
commit 4b33910488
25 changed files with 792 additions and 152 deletions

View File

@@ -3,8 +3,10 @@
## 支持版本
* SDK 28~32
* WebRTC m94
* Gradle 7.5
* Andoird 9~12
* libmediasoupclient 3.4.0
## C++终端

View File

@@ -2,6 +2,7 @@
.idea
.gradle
media/deps
media/deps/webrtc
media/deps/libmediasoupclient
local.properties

View File

@@ -0,0 +1,17 @@
# 依赖
[WebRTC](https://pan.baidu.com/s/1E_DXv32D9ODyj5J-o-ji_g?pwd=hudc)
下载文件放到响应目录
```
deps
├─libmediasoupclient
└─webrtc
├─lib
│ ├─arm64-v8a
│ ├─armeabi-v7a
│ ├─x86
│ └─x86_64
└─src
```

View File

@@ -3,6 +3,8 @@
## 支持版本
* SDK 11
* WebRTC m114
* libmediasoupclient m120
## C++终端

View File

@@ -8,7 +8,9 @@
local.properties
oh-package-lock.json5
deps
build
oh_modules
node_modules
media/src/main/cpp/deps/webrtc
media/src/main/cpp/deps/libmediasoupclient

View File

@@ -5,6 +5,7 @@
"path": "./src/main/cpp/CMakeLists.txt",
"cppFlags" : "",
"arguments" : "",
// 不要自作多情添加一些配置🤡🤡🤡🤡
// "cppFlags" : "-D_LIBCPP_STD_VER=17",
// "arguments" : "-DOHOS_STL=c++_static",
// "arguments" : "-DOHOS_STL=c++_shared",

View File

@@ -1,11 +1,11 @@
{
"main" : "",
"name" : "media",
"author": "acgist",
"main" : "",
"name" : "media",
"author" : "acgist",
"version": "1.0.0",
"license": "Apache-2.0",
"description": "桃夭媒体终端",
"dependencies" : {
"description" : "桃夭媒体终端",
"dependencies": {
"libtaoyao.so": "file:./src/main/cpp/types/libtaoyao"
},
"devDependencies" : {},

View File

@@ -20,10 +20,41 @@
#include <multimedia/player_framework/native_avcapability.h>
#include <multimedia/player_framework/native_avcodec_base.h>
static std::mutex taoyaoMutex;
static std::mutex roomMutex;
#ifndef TAOYAO_JSON_SIZE
#define TAOYAO_JSON_SIZE 2048
#endif
#ifndef TAOYAO_JSON_BODY
#define TAOYAO_JSON_BODY() \
napi_value ret; \
size_t argc = 1; \
napi_value args[1] = {nullptr}; \
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr); \
size_t length; \
char chars[2048]; \
napi_get_value_string_utf8(env, args[0], chars, sizeof(chars), &length); \
nlohmann::json json = nlohmann::json::parse(chars); \
nlohmann::json body = json["body"];
#endif
#ifndef TAOYAO_ROOM_CHECK
#define TAOYAO_ROOM_CHECK(action) \
std::string roomId = body["roomId"]; \
auto room = acgist::roomMap.find(roomId); \
if(room == acgist::roomMap.end()) { \
OH_LOG_WARN(LOG_APP, "房间无效:%s %s", #action, roomId.data()); \
napi_create_int32(env, -1, &ret); \
return ret; \
}
#endif
namespace acgist {
// 终端ID
static std::string clientId = "";
// JS环境
static napi_env env = nullptr;
// 是否加载
@@ -55,48 +86,60 @@ static void printSupportCodec() {
/**
* 加载系统
*/
static void init() {
if(initTaoyao) {
return;
static void init(napi_env env, napi_callback_info info) {
{
std::lock_guard<std::mutex> taoyaoLock(taoyaoMutex);
if(initTaoyao) {
return;
}
initTaoyao = true;
}
initTaoyao = true;
TAOYAO_JSON_BODY();
acgist::clientId = json["clientId"];
OH_LOG_INFO(LOG_APP, "加载libtaoyao");
// 编码能力
printSupportCodec();
std::string version = mediasoupclient::Version();
OH_LOG_INFO(LOG_APP, "加载MediasoupClient%s", version.data());
mediasoupclient::Initialize();
OH_LOG_INFO(LOG_APP, "加载媒体功能");
mediaManager = new MediaManager();
mediaManager->initPeerConnectionFactory();
mediaManager->init();
}
/**
* 卸载系统
*/
static napi_value shutdown(napi_env env, napi_callback_info info) {
if(!initTaoyao) {
OH_LOG_INFO(LOG_APP, "已经卸载libtaoyao");
return 0;
{
std::lock_guard<std::mutex> taoyaoLock(taoyaoMutex);
if(!initTaoyao) {
OH_LOG_INFO(LOG_APP, "已经卸载libtaoyao");
return 0;
}
initTaoyao = false;
}
initTaoyao = false;
OH_LOG_INFO(LOG_APP, "卸载libtaoyao");
OH_LOG_INFO(LOG_APP, "释放mediasoupclient");
mediasoupclient::Cleanup();
// 删除房间
for(auto iterator = roomMap.begin(); iterator != roomMap.end(); ++iterator) {
OH_LOG_INFO(LOG_APP, "清空房间");
for(auto iterator = acgist::roomMap.begin(); iterator != acgist::roomMap.end(); ++iterator) {
delete iterator->second;
iterator->second = nullptr;
}
roomMap.clear();
// 关闭媒体
acgist::roomMap.clear();
OH_LOG_INFO(LOG_APP, "关闭媒体");
if (mediaManager != nullptr) {
delete mediaManager;
mediaManager = nullptr;
}
OH_LOG_INFO(LOG_APP, "释放全局变量");
// napi_delete_reference(env, acgist::sendRef);
// napi_delete_reference(env, acgist::requestRef);
return 0;
env = nullptr;
// 返回结果
napi_value ret;
napi_create_int32(env, 0, &ret);
return ret;
}
/**
@@ -124,9 +167,12 @@ std::string request(const std::string& signal, const std::string& body) {
napi_create_string_utf8(acgist::env, signal.data(), NAPI_AUTO_LENGTH, &data[0]);
napi_create_string_utf8(acgist::env, body.data(), NAPI_AUTO_LENGTH, &data[1]);
napi_call_function(acgist::env, nullptr, callback, 2, data, &ret);
char chars[2048];
char chars[TAOYAO_JSON_SIZE];
size_t length;
napi_get_value_string_utf8(env, ret, chars, sizeof(chars), &length);
// TODO: promise
// napi_create_promise
// napi_resolve_deferred
return chars;
}
@@ -134,18 +180,23 @@ std::string request(const std::string& signal, const std::string& body) {
* 房间关闭
*/
static napi_value roomClose(napi_env env, napi_callback_info info) {
TAOYAO_JSON_BODY();
{
std::lock_guard<std::mutex> guard(roomMutex);
auto iterator = roomMap.find("roomId");
if(iterator == roomMap.end()) {
std::lock_guard<std::mutex> roomLock(roomMutex);
std::string roomId = body["roomId"];
auto iterator = acgist::roomMap.find(roomId);
if(iterator == acgist::roomMap.end()) {
OH_LOG_WARN(LOG_APP, "关闭房间无效:%s", roomId.data());
napi_create_int32(env, -1, &ret);
} else {
OH_LOG_INFO(LOG_APP, "关闭房间:%s", roomId.data());
delete iterator->second;
iterator->second = nullptr;
roomMap.erase(iterator);
acgist::roomMap.erase(iterator);
napi_create_int32(env, 0, &ret);
}
}
return 0;
return ret;
}
/**
@@ -153,44 +204,64 @@ static napi_value roomClose(napi_env env, napi_callback_info info) {
* 其他终端进入房间,自己进入房间逻辑参考房间邀请。
*/
static napi_value roomEnter(napi_env env, napi_callback_info info) {
return 0;
TAOYAO_JSON_BODY();
TAOYAO_ROOM_CHECK("进入房间");
std::string clientId = body["clientId"];
OH_LOG_INFO(LOG_APP, "进入房间:%s %s", roomId.data(), clientId.data());
if(clientId == acgist::clientId) {
// 忽略关闭自己
napi_create_int32(env, -2, &ret);
return ret;
}
nlohmann::json status = body["status"];
std::string name = status["name"];
int result = room->newRemoteClient(clientId, name);
napi_create_int32(env, result, &ret);
return ret;
}
/**
* 踢出房间
* 踢出房间以后终端离开房间
*/
static napi_value roomExpel(napi_env env, napi_callback_info info) { return 0; }
static napi_value roomExpel(napi_env env, napi_callback_info info) {
TAOYAO_JSON_BODY();
TAOYAO_ROOM_CHECK("踢出房间");
OH_LOG_INFO(LOG_APP, "进入房间:%s", roomId.data());
nlohmann::json requestBody = {
{ "roomId", roomId },
};
acgist::send("room::leave", requestBody.dump());
delete room->second;
room->second = nullptr;
acgist::roomMap.erase(room);
napi_create_int32(env, 0, &ret);
return ret;
}
/**
* 房间邀请
* 邀请终端进入房间
*/
static napi_value roomInvite(napi_env env, napi_callback_info info) {
size_t argc = 1;
napi_value args[1] = { nullptr };
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
size_t length;
char chars[2048];
napi_get_value_string_utf8(env, args[0], chars, sizeof(chars), &length);
nlohmann::json json = nlohmann::json::parse(chars);
nlohmann::json body = json["body"];
// TODO: 试试引用
std::string roomId = body["roomId"];
std::string password = body["password"];
napi_value ret;
TAOYAO_JSON_BODY();
{
std::lock_guard<std::mutex> guard(roomMutex);
auto iterator = roomMap.find(roomId);
if(iterator == roomMap.end()) {
std::lock_guard<std::mutex> roomLock(roomMutex);
// TODO: 试试引用
std::string roomId = body["roomId"];
std::string password = body["password"];
auto oldRoom = acgist::roomMap.find(roomId);
if(oldRoom == acgist::roomMap.end()) {
OH_LOG_INFO(LOG_APP, "进入房间:%s", roomId.data());
auto room = new acgist::Room(roomId, mediaManager);
roomMap[roomId] = room;
int enterRet = room->enter(password);
if(enterRet == acgist::SUCCESS_CODE) {
int result = room->enter(password);
if(result == acgist::SUCCESS_CODE) {
acgist::roomMap.insert({ roomId, room });
room->produceMedia();
} else {
delete room;
}
napi_create_int32(env, enterRet, &ret);
napi_create_int32(env, result, &ret);
} else {
OH_LOG_INFO(LOG_APP, "已经进入房间:%s", roomId.data());
napi_create_int32(env, -1, &ret);
@@ -203,48 +274,137 @@ static napi_value roomInvite(napi_env env, napi_callback_info info) {
* 离开房间
* 其他终端离开房间
*/
static napi_value roomLeave(napi_env env, napi_callback_info info) { return 0; }
static napi_value roomLeave(napi_env env, napi_callback_info info) {
TAOYAO_JSON_BODY();
TAOYAO_ROOM_CHECK("离开房间");
std::string clientId = body["clientId"];
OH_LOG_INFO(LOG_APP, "离开房间:%s %s", roomId.data(), clientId.data());
if(clientId == acgist::clientId) {
// 忽略关闭自己
napi_create_int32(env, -2, &ret);
return ret;
}
int result = room->second->closeRemoteClient(clientId);
napi_create_int32(env, result, &ret);
return ret;
}
/**
* 终端列表
* 房间所有终端列表首次进入方便加载终端列表信息
*/
static napi_value roomClientList(napi_env env, napi_callback_info info) { return 0; }
static napi_value roomClientList(napi_env env, napi_callback_info info) {
TAOYAO_JSON_BODY();
TAOYAO_ROOM_CHECK("终端列表");
nlohmann::json clients = body["clients"];
if(clients.empty()) {
napi_create_int32(env, 0, &ret);
return ret;
}
for(auto client = clients.begin(); client != clients.end(); ++client) {
std::string clientId = (*client)["clientId"];
std::string name = (*client)["name"];
if(clientId == acgist::clientId) {
// 忽略关闭自己
continue;
}
room->second->newRemoteClient(clientId, name);
}
napi_create_int32(env, 0, &ret);
return ret;
}
/**
* 媒体消费(被动通知)
*/
static napi_value mediaConsume(napi_env env, napi_callback_info info) { return 0; }
static napi_value mediaConsume(napi_env env, napi_callback_info info) {
TAOYAO_JSON_BODY();
TAOYAO_ROOM_CHECK();
TAOYAO_ROOM_CHECK("媒体消费");
int result = room->second->newConsumer(body);
acgist::send(chars);
// acgist::send(json.dump());
napi_create_int32(env, result, &ret);
return ret;
}
/**
* 消费者关闭(被动通知)
*/
static napi_value mediaConsumerClose(napi_env env, napi_callback_info info) { return 0; }
static napi_value mediaConsumerClose(napi_env env, napi_callback_info info) {
TAOYAO_JSON_BODY();
TAOYAO_ROOM_CHECK("消费者关闭");
std::string consumerId = body["consumerId"];
TAOYAO_ROOM_CHECK("消费者关闭:%s", consumerId.data());
int result = room->second->closeConsumer(consumerId);
napi_create_int32(env, result, &ret);
return ret;
}
/**
* 消费者暂停(被动通知)
*/
static napi_value mediaConsumerPause(napi_env env, napi_callback_info info) { return 0; }
static napi_value mediaConsumerPause(napi_env env, napi_callback_info info) {
TAOYAO_JSON_BODY();
TAOYAO_ROOM_CHECK("消费者暂停");
std::string consumerId = body["consumerId"];
TAOYAO_ROOM_CHECK("消费者暂停:%s", consumerId.data());
int result = room->second->pauseConsumer(consumerId);
napi_create_int32(env, result, &ret);
return ret;
}
/**
* 消费者恢复(被动通知)
*/
static napi_value mediaConsumerResume(napi_env env, napi_callback_info info) { return 0; }
static napi_value mediaConsumerResume(napi_env env, napi_callback_info info) {
TAOYAO_JSON_BODY();
TAOYAO_ROOM_CHECK("消费者恢复");
std::string consumerId = body["consumerId"];
TAOYAO_ROOM_CHECK("消费者恢复:%s", consumerId.data());
int result = room->second->resumeConsumer(consumerId);
napi_create_int32(env, result, &ret);
return ret;
}
/**
* 生产者关闭(被动通知)
*/
static napi_value mediaProducerClose(napi_env env, napi_callback_info info) { return 0; }
static napi_value mediaProducerClose(napi_env env, napi_callback_info info) {
TAOYAO_JSON_BODY();
TAOYAO_ROOM_CHECK("生产者关闭");
std::string producerId = body["producerId"];
TAOYAO_ROOM_CHECK("生产者关闭:%s", producerId.data());
int result = room->second->closeProducer(producerId);
napi_create_int32(env, result, &ret);
return ret;
}
/**
* 生产者暂停(被动通知)
*/
static napi_value mediaProducerPause(napi_env env, napi_callback_info info) { return 0; }
static napi_value mediaProducerPause(napi_env env, napi_callback_info info) {
TAOYAO_JSON_BODY();
TAOYAO_ROOM_CHECK("生产者暂停");
std::string producerId = body["producerId"];
TAOYAO_ROOM_CHECK("生产者暂停:%s", producerId.data());
int result = room->second->pauseProducer(producerId);
napi_create_int32(env, result, &ret);
return ret;
}
/**
* 生产者恢复(被动通知)
*/
static napi_value mediaProducerResume(napi_env env, napi_callback_info info) { return 0; }
static napi_value mediaProducerResume(napi_env env, napi_callback_info info) {
TAOYAO_JSON_BODY();
TAOYAO_ROOM_CHECK("生产者恢复");
std::string producerId = body["producerId"];
TAOYAO_ROOM_CHECK("生产者恢复:%s", producerId.data());
int result = room->second->resumeProducer(producerId);
napi_create_int32(env, result, &ret);
return ret;
}
/**
* 注册发送回调
@@ -265,8 +425,6 @@ static napi_value registerRequest(napi_env env, napi_callback_info info) {
napi_value args[1] = { nullptr };
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
napi_create_reference(env, args[0], 1, &acgist::requestRef);
// napi_create_promise
// napi_resolve_deferred
return 0;
}
@@ -276,6 +434,7 @@ EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
acgist::env = env;
napi_property_descriptor desc[] = {
{ "init", nullptr, acgist::init, nullptr, nullptr, nullptr, napi_default, nullptr },
{ "shutdown", nullptr, acgist::shutdown, nullptr, nullptr, nullptr, napi_default, nullptr },
{ "roomClose", nullptr, acgist::roomClose, nullptr, nullptr, nullptr, napi_default, nullptr },
{ "roomEnter", nullptr, acgist::roomEnter, nullptr, nullptr, nullptr, napi_default, nullptr },

View File

@@ -0,0 +1,13 @@
# 依赖
[WebRTC](https://pan.baidu.com/s/1E_DXv32D9ODyj5J-o-ji_g?pwd=hudc)
下载文件放到响应目录
```
deps
├─libmediasoupclient
└─webrtc
├─lib
└─src
```

View File

@@ -12,8 +12,9 @@
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/camera/native-camera-recording.md
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/audio/using-ohaudio-for-recording.md
*/
#ifndef taoyao_Capturer_HPP
#define taoyao_Capturer_HPP
#ifndef TAOYAO_CAPTURER_HPP
#define TAOYAO_CAPTURER_HPP
#include <map>
@@ -172,4 +173,4 @@ public:
}
#endif // taoyao_Capturer_HPP
#endif // TAOYAO_CAPTURER_HPP

View File

@@ -3,11 +3,14 @@
*
* @author acgist
*/
#ifndef taoyao_Client_HPP
#define taoyao_Client_HPP
#ifndef TAOYAO_CLIENT_HPP
#define TAOYAO_CLIENT_HPP
#include "MediaManager.hpp"
#include "mediasoupclient.hpp"
namespace acgist {
/**
@@ -16,6 +19,10 @@ namespace acgist {
class Client {
public:
// 终端ID
std::string clientId;
// 终端名称
std::string name;
// 媒体管理
acgist::MediaManager* mediaManager = nullptr;
// 音频轨道
@@ -28,12 +35,6 @@ public:
virtual ~Client();
public:
/**
* 资源释放
*
* @return 是否成功
*/
virtual bool release() = 0;
};
@@ -47,7 +48,6 @@ public:
virtual ~RoomClient();
public:
virtual bool release() override;
};
@@ -61,7 +61,6 @@ public:
virtual ~LocalClient();
public:
virtual bool release() override;
};
@@ -70,15 +69,26 @@ public:
*/
class RemoteClient : public RoomClient {
public:
// 消费者列表
std::map<std::string, mediasoupclient::Consumer*> consumers;
public:
RemoteClient(acgist::MediaManager* mediaManager);
virtual ~RemoteClient();
public:
virtual bool release() override;
// 添加消费者
bool addConsumer(const std::string& consuemrId, mediasoupclient::Consumer* consumer);
// 关闭消费者
bool closeConsumer(const std::string& consumerId);
// 暂停消费者
bool pauseConsumer(const std::string& consumerId);
// 恢复消费者
bool resumeConsumer(const std::string& consumerId);
};
}
#endif // taoyao_Client_HPP
#endif // TAOYAO_CLIENT_HPP

View File

@@ -6,8 +6,9 @@
*
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/avcodec/obtain-supported-codecs.md
*/
#ifndef taoyao_MediaManager_HPP
#define taoyao_MediaManager_HPP
#ifndef TAOYAO_MEDIAMANAGER_HPP
#define TAOYAO_MEDIAMANAGER_HPP
#include <memory>
#include <thread>
@@ -20,30 +21,36 @@
namespace acgist {
class TaoyaoAudioSink : public webrtc::AudioTrackSinkInterface {
};
class TaoyaoVideoSource : public webrtc::VideoTrackSourceInterface {
};
class TaoyaoVideoSink : public rtc::VideoSinkInterface<webrtc::RecordableEncodedFrame> {
};
class MediaManager {
public:
MediaManager();
~MediaManager();
virtual ~MediaManager();
public:
int localClientRef = 0;
std::unique_ptr<rtc::Thread> networkThread = nullptr;
std::unique_ptr<rtc::Thread> signalingThread = nullptr;
std::unique_ptr<rtc::Thread> workerThread = nullptr;
rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peerConnectionFactory = nullptr;
public:
protected:
// 加载PC工厂
bool initPeerConnectionFactory();
bool newPeerConnectionFactory();
// 释放PC工厂
bool releasePeerConnectionFactory();
public:
// 加载媒体
bool init();
// 新增本地终端
int newLocalClient();
// 释放本地终端
@@ -64,8 +71,9 @@ public:
rtc::scoped_refptr<webrtc::AudioTrackInterface> getAudioTrack();
// 视频来源
rtc::scoped_refptr<webrtc::VideoTrackInterface> getVideoTrack();
};
}
#endif // taoyao_MediaManager_HPP
#endif // TAOYAO_MEDIAMANAGER_HPP

View File

@@ -5,6 +5,7 @@
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/audio/audio-playback-overview.md
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/media/using-ndk-avplayer-for-playerback.md
*/
#ifndef TAOYAO_PALYER_HPP
#define TAOYAO_PALYER_HPP

View File

@@ -3,8 +3,9 @@
*
* @author acgist
*/
#ifndef taoyao_Room_HPP
#define taoyao_Room_HPP
#ifndef TAOYAO_ROOM_HPP
#define TAOYAO_ROOM_HPP
#include <map>
#include <string>
@@ -218,7 +219,9 @@ public:
acgist::MediaManager* mediaManager = nullptr;
// 本地终端
acgist::LocalClient* client = nullptr;
// 远程终端
// ID映射consumerId = clientId
std::map<std::string, std::string> consumerIdClientId;
// 远程终端clientId = RemoteClient
std::map<std::string, acgist::RemoteClient*> clients;
// WebRTC配置
webrtc::PeerConnectionInterface::RTCConfiguration rtcConfiguration;
@@ -240,8 +243,10 @@ public:
mediasoupclient::Producer::Listener* producerListener = nullptr;
// 消费者监听器
mediasoupclient::Consumer::Listener* consumerListener = nullptr;
// 消费者列表
std::map<std::string, mediasoupclient::Consumer*> consumers;
// 本地音频
rtc::scoped_refptr<webrtc::AudioTrackInterface> audioTrack = nullptr;
// 本地视频
rtc::scoped_refptr<webrtc::VideoTrackInterface> videoTrack = nullptr;
public:
Room(const std::string& roomId, acgist::MediaManager* mediaManager);
@@ -262,19 +267,47 @@ public:
* @return 状态
*/
int produceMedia();
// 创建发送通道
int createSendTransport();
// 创建接收通道
int createRecvTransport();
// 生产音频
int produceAudio();
// 生产视频
int produceVideo();
// 关闭房间
int close();
int closeConsumer();
// 关闭本地消费者
int closeClient();
// 关闭远程消费者
int closeClients();
// 关闭音频生产者
int closeAudioProducer();
// 关闭视频生产者
int closeVideoProducer();
// 关闭通道
int closeTransport();
int newRemoteClient();
// 新建远程终端
int newRemoteClient(const std::string& clientId, const std::string& name);
// 删除远程终端
int closeRemoteClient(const std::string& clientId);
// 新增消费者
int newConsumer(nlohmann::json& body);
// 删除消费者
int closeConsumer(const std::string& consumerId);
// 暂停消费者
int pauseConsumer(const std::string& consumerId);
// 恢复消费者
int resumeConsumer(const std::string& consumerId);
// 关闭生产者
int closeProducer(const std::string& producerId);
// 暂停生产者
int pauseProducer(const std::string& producerId);
// 恢复生产者
int resumeProducer(const std::string& producerId);
};
}
#endif // taoyao_Room_HPP
#endif // TAOYAO_ROOM_HPP

View File

@@ -1,6 +1,7 @@
/**
* 信令
*/
#ifndef TAOYAO_SIGNAL_HPP
#define TAOYAO_SIGNAL_HPP

View File

@@ -5,10 +5,5 @@ acgist::LocalClient::LocalClient(acgist::MediaManager* mediaManager) : acgist::R
}
acgist::LocalClient::~LocalClient() {
this->release();
this->mediaManager->releaseLocalClient();
}
bool acgist::LocalClient::release() {
return true;
}

View File

@@ -14,7 +14,7 @@
#include <api/video_codecs/builtin_video_decoder_factory.h>
#include <api/video_codecs/builtin_video_encoder_factory.h>
static std::mutex refMutex;
static std::mutex lockMutex;
acgist::MediaManager::MediaManager() {
}
@@ -23,7 +23,11 @@ acgist::MediaManager::~MediaManager() {
// TODO验证是否需要释放线程和工厂
}
bool acgist::MediaManager::initPeerConnectionFactory() {
bool acgist::MediaManager::init() {
return true;
}
bool acgist::MediaManager::newPeerConnectionFactory() {
OH_LOG_INFO(LOG_APP, "加载PeerConnectionFactory");
this->networkThread = rtc::Thread::CreateWithSocketServer();
this->signalingThread = rtc::Thread::Create();
@@ -33,6 +37,7 @@ bool acgist::MediaManager::initPeerConnectionFactory() {
this->workerThread->SetName("worker_thread", nullptr);
if (!this->networkThread->Start() || !this->signalingThread->Start() || !this->workerThread->Start()) {
OH_LOG_WARN(LOG_APP, "WebRTC线程启动失败");
// TODO: 释放线程
return false;
}
this->peerConnectionFactory = webrtc::CreatePeerConnectionFactory(
@@ -47,25 +52,43 @@ bool acgist::MediaManager::initPeerConnectionFactory() {
nullptr,
nullptr,
// TODO: 视频工厂
// webrtc::CreateBuiltinVideoEncoderFactory(),
// webrtc::CreateBuiltinVideoDecoderFactory(),
// webrtc::CreateBuiltinVideoEncoderFactory(),
// webrtc::CreateBuiltinVideoDecoderFactory(),
nullptr /* audio_mixer */,
nullptr /* audio_processing */
);
return this->peerConnectionFactory != nullptr;
}
bool acgist::MediaManager::releasePeerConnectionFactory() {
OH_LOG_INFO(LOG_APP, "释放PeerConnectionFactory");
// TODO释放
return true;
}
int acgist::MediaManager::newLocalClient() {
{
std::lock_guard<std::mutex> guard(refMutex);
std::lock_guard<std::mutex> mediaLock(lockMutex);
this->localClientRef++;
if(this->localClientRef > 0) {
this->newPeerConnectionFactory();
this->startCapture();
}
}
}
int acgist::MediaManager::releaseLocalClient() {
{
std::lock_guard<std::mutex> guard(refMutex);
std::lock_guard<std::mutex> mediaLock(lockMutex);
this->localClientRef--;
if(this->localClientRef <= 0) {
if(this->localClientRef < 0) {
this->localClientRef = 0;
} else {
this->stopCapture();
this->releasePeerConnectionFactory();
}
}
}
}
@@ -83,6 +106,18 @@ bool acgist::MediaManager::startVideoCapture() {
return true;
}
bool acgist::MediaManager::stopCapture() {
return true;
}
bool acgist::MediaManager::stopAudioCapture() {
return true;
}
bool acgist::MediaManager::stopVideoCapture() {
return true;
}
rtc::scoped_refptr<webrtc::AudioTrackInterface> acgist::MediaManager::getAudioTrack() {
cricket::AudioOptions options;
options.highpass_filter = true;

View File

@@ -1,7 +1,74 @@
#include "../include/Client.hpp"
#include <mutex>
#include "hilog/log.h"
static std::mutex clientMutex;
acgist::RemoteClient::RemoteClient(acgist::MediaManager* mediaManager) : RoomClient(mediaManager) {}
acgist::RemoteClient::~RemoteClient() {}
acgist::RemoteClient::~RemoteClient() {
for(auto iterator = this->consumers.begin(); iterator != this->consumers.end(); ++iterator) {
iterator->second->Close();
delete iterator->second;
iterator->second = nullptr;
}
this->consumers.clear();
}
bool acgist::RemoteClient::release() { return true; }
bool acgist::RemoteClient::addConsumer(const std::string& consumerId, mediasoupclient::Consumer* consumer) {
std::lock_guard<std::mutex> clientLock(lockMutex);
auto oldConsumer = this->consumers.find(clientId);
if(oldConsumer != this->consumers.end()) {
OH_LOG_INFO(LOG_APP, "关闭旧的消费者:%s", consumerId.data());
oldConsumer->second->Close();
delete oldConsumer->second;
oldConsumer->second = nullptr;
this->consumers.erase(oldConsumer);
}
OH_LOG_INFO(LOG_APP, "添加新的消费者:%s", consumerId.data());
this->consumers.insert({ consumerId, consumer });
webrtc::MediaStreamTrackInterface* trackPointer = consumer->GetTrack();
// TODO: 播放
return true;
}
bool acgist::RemoteClient::closeConsumer(const std::string& consumerId) {
std::lock_guard<std::mutex> clientLock(lockMutex);
auto consumer = this->consumers.find(consumerId);
if(consumer == this->consumers.end()) {
OH_LOG_INFO(LOG_APP, "消费者已经关闭:%s", consumerId.data());
return false;
}
OH_LOG_INFO(LOG_APP, "关闭消费者:%s", consumerId.data());
consumer->second->Close();
delete consumer->second;
consumer->second = nullptr;
this->consumers.erase(consumer);
return true;
}
bool acgist::RemoteClient::pauseConsumer(const std::string& consumerId) {
std::lock_guard<std::mutex> clientLock(lockMutex);
auto consumer = this->consumers.find(consumerId);
if(consumer == this->consumers.end()) {
OH_LOG_INFO(LOG_APP, "无效消费者:%s", consumerId.data());
return false;
}
OH_LOG_INFO(LOG_APP, "暂停消费者:%s", consumerId.data());
consumer->second->Pause();
return true;
}
bool acgist::RemoteClient::resumeConsumer(const std::string& consumerId) {
std::lock_guard<std::mutex> clientLock(lockMutex);
auto consumer = this->consumers.find(consumerId);
if(consumer == this->consumers.end()) {
OH_LOG_INFO(LOG_APP, "无效消费者:%s", consumerId.data());
return false;
}
OH_LOG_INFO(LOG_APP, "恢复消费者:%s", consumerId.data());
consumer->second->Resume();
return true;
}

View File

@@ -16,6 +16,7 @@ acgist::Room::Room(const std::string& roomId, acgist::MediaManager* mediaManager
acgist::Room::~Room() {
this->close();
this->consumerIdClientId.clear();
// rtcConfiguration
if (this->device != nullptr) {
delete this->device;
@@ -53,10 +54,10 @@ acgist::Room::~Room() {
delete this->consumerListener;
this->consumerListener = nullptr;
}
if(this->client != nullptr) {
delete this->client;
this->client = nullptr;
}
// TODO: delete audio track
// TODO: delete video track
// TODO: delete local client
// TODO: delete remote client
}
int acgist::Room::enter(const std::string& password) {
@@ -109,6 +110,7 @@ int acgist::Room::produceMedia() {
}
int acgist::Room::createSendTransport() {
OH_LOG_INFO(LOG_APP, "创建发送通道:%s", this->roomId.data());
nlohmann::json requestBody = {
{ "roomId", this->roomId },
{ "forceTcp", false },
@@ -135,6 +137,7 @@ int acgist::Room::createSendTransport() {
}
int acgist::Room::createRecvTransport() {
OH_LOG_INFO(LOG_APP, "创建接收通道:%s", this->roomId.data());
nlohmann::json requestBody = {
{ "roomId", this->roomId },
{ "forceTcp", false },
@@ -161,39 +164,112 @@ int acgist::Room::createRecvTransport() {
}
int acgist::Room::produceAudio() {
if(!this->device->CanProduce("audio") || this->audioProducer == nullptr) {
OH_LOG_INFO(LOG_APP, "不能生产音频媒体:%s", this->roomId.data());
return -1;
}
// TODO:track
if(this->audioTrack->state() == webrtc::MediaStreamTrackInterface::TrackState::kEnded) {
OH_LOG_INFO(LOG_APP, "音频媒体状态错误:%s", this->roomId.data());
return -2;
}
OH_LOG_INFO(LOG_APP, "生产音频媒体:%s", this->roomId.data());
nlohmann::json codecOptions = {
{ "opusStereo", true },
{ "opusDtx", true }
};
this->audioProducer = this->sendTransport->Produce(
this->producerListener,
this->audioTrack,
nullptr,
&codecOptions,
nullptr
);
return 0;
}
int acgist::Room::produceVideo() {
if(!this->device->CanProduce("video") || this->videoProducer == nullptr) {
OH_LOG_INFO(LOG_APP, "不能生产视频媒体:%s", this->roomId.data());
return -1;
}
// TODO:track
if(this->videoTrack->state() == webrtc::MediaStreamTrackInterface::TrackState::kEnded) {
OH_LOG_INFO(LOG_APP, "视频媒体状态错误:%s", this->roomId.data());
return -2;
}
OH_LOG_INFO(LOG_APP, "生产视频媒体:%s", this->roomId.data());
// TODO配置读取同时测试效果
nlohmann::json codecOptions = {
// x-google-start-bitrate
{ "videoGoogleStartBitrate", 1200 },
// x-google-min-bitrate
{ "videoGoogleMinBitrate", 800 },
// x-google-max-bitrate
{ "videoGoogleMaxBitrate", 1600 }
};
// 如果需要使用`Simulcast`打开下面配置
// std::vector<webrtc::RtpEncodingParameters> encodings;
// webrtc::RtpEncodingParameters min;
// webrtc::RtpEncodingParameters mid;
// webrtc::RtpEncodingParameters max;
// min.active = true;
// min.max_framerate = 15;
// min.min_bitrate_bps = 400;
// min.max_bitrate_bps = 800;
// encodings.emplace_back(min);
// encodings.emplace_back(mid);
// encodings.emplace_back(max);
// 强制设置编码器
// nlohmann::json codec = this->device->GetRtpCapabilities()["codec"];
this->videoProducer = this->sendTransport->Produce(
this->producerListener,
this->videoTrack,
nullptr,
&codecOptions,
nullptr
);
return 0;
}
int acgist::Room::close() {
OH_LOG_INFO(LOG_APP, "关闭房间:%s", this->roomId.data());
this->closeConsumer();
this->closeClient();
this->closeClients();
this->closeAudioProducer();
this->closeVideoProducer();
this->closeTransport();
return 0;
}
int acgist::Room::closeConsumer() {
int acgist::Room::closeClient() {
std::lock_guard<std::mutex> lockRoom(roomMutex);
for (auto iterator = this->consumers.begin(); iterator != this->consumers.end(); ++iterator) {
OH_LOG_INFO(LOG_APP, "关闭本地终端:%s", this->roomId.data());
if(this->client != nullptr) {
delete this->client;
this->client = nullptr;
}
return 0;
}
int acgist::Room::closeClients() {
std::lock_guard<std::mutex> lockRoom(roomMutex);
OH_LOG_INFO(LOG_APP, "关闭远程终端:%s", this->roomId.data());
for (auto iterator = this->clients.begin(); iterator != this->clients.end(); ++iterator) {
if (iterator->second == nullptr) {
continue;
}
OH_LOG_INFO(LOG_APP, "关闭消费者:%s", iterator->second->GetId().data());
iterator->second->Close();
OH_LOG_INFO(LOG_APP, "关闭消费者:%s", iterator->first.data());
delete iterator->second;
iterator->second = nullptr;
}
this->consumers.clear();
this->clients.clear();
return 0;
}
int acgist::Room::closeAudioProducer() {
std::lock_guard<std::mutex> lockRoom(roomMutex);
OH_LOG_INFO(LOG_APP, "关闭音频生产者:%s", this->roomId.data());
if (this->audioProducer != nullptr) {
this->audioProducer->Close();
}
@@ -202,6 +278,7 @@ int acgist::Room::closeAudioProducer() {
int acgist::Room::closeVideoProducer() {
std::lock_guard<std::mutex> lockRoom(roomMutex);
OH_LOG_INFO(LOG_APP, "关闭视频生产者:%s", this->roomId.data());
if (this->videoProducer != nullptr) {
this->videoProducer->Close();
}
@@ -210,6 +287,7 @@ int acgist::Room::closeVideoProducer() {
int acgist::Room::closeTransport() {
std::lock_guard<std::mutex> lockRoom(roomMutex);
OH_LOG_INFO(LOG_APP, "关闭通道:%s", this->roomId.data());
if (this->sendTransport != nullptr) {
this->sendTransport->Close();
}
@@ -219,6 +297,165 @@ int acgist::Room::closeTransport() {
return 0;
}
int acgist::Room::newRemoteClient(const std::string& clientId, const std::string& name) {
std::lock_guard<std::mutex> lockRoom(roomMutex);
auto oldClient = this->clients.find(clientId);
if(oldClient != this->clients.end()) {
OH_LOG_INFO(LOG_APP, "已经存在远程终端:%s", clientId.data());
delete oldClient->second;
oldClient->second = null;
this->clients.erase(oldClient);
}
OH_LOG_INFO(LOG_APP, "新增远程终端:%s", clientId.data());
acgist::RemoteClient* client = new acgist::RemoteClient(this->mediaManager);
client->clientId = clientId;
client->name = name;
this->clients.insert({ clientId, client });
return 0;
}
int acgist::Room::closeRemoteClient(const std::string& clientId) {
std::lock_guard<std::mutex> lockRoom(roomMutex);
auto client = this->clients.find(clientId);
if(client == this->clients.end()) {
OH_LOG_INFO(LOG_APP, "远程终端已经删除:%s", clientId.data());
return -1;
}
OH_LOG_INFO(LOG_APP, "删除远程终端:%s", clientId.data());
delete client->second;
client->second = nullptr;
this->clients->erase(client);
// TODO: 清理consumerIdClientId
return 0;
}
int acgist::Room::newConsumer(nlohmann::json& body) {
std::lock_guard<std::mutex> lockRoom(roomMutex);
mediasoupclient::Consumer* consumer = this->recvTransport->Consume(
this->consumerListener,
body["consumerId"],
body["producerId"],
body["kind"],
&body["rtpParameters"]
);
std::string kind = body["kind"];
std::string sourceId = body["sourceId"];
std::string consumerId = body["consumerId"];
OH_LOG_INFO(LOG_APP, "新增媒体消费:%s %s %s", kind.data(), sourceId.data(), consumerId.data());
auto oldClient = this->clients.find(sourceId);
acgist::RemoteClient* client = nullptr;
if(oldClient == this->clients.end()) {
// 假如媒体上来时间比进入房间消息快:基本上不可能出现这种情况
client = new acgist::RemoteClient(this->mediaManager);
client->clientId = clientId;
client->name = clientId;
this->clients.insert({ clientId, client });
} else {
client = oldClient->second;
}
client->addConsumer(consumer->GetId(), consumer);
this->consumerIdClientId.insert({ consumer->GetId(), sourceId });
return 0;
}
int acgist::Room::closeConsumer(const std::string& consumerId) {
std::lock_guard<std::mutex> lockRoom(roomMutex);
auto clientId = this->consumerIdClientId.find(consumerId);
if(clientId == this->consumerIdClientId.end()) {
OH_LOG_INFO(LOG_APP, "关闭消费者无效:%s", consumerId.data());
return -1;
}
auto client = this->clients.find(clientId->second);
if(client == this->clients.end()) {
OH_LOG_INFO(LOG_APP, "关闭消费者无效:%s %s", consumerId.data(), clientId->second.data());
return -2;
}
client->second->closeConsumer(consumerId);
return 0;
}
int acgist::Room::pauseConsumer(const std::string& consumerId) {
std::lock_guard<std::mutex> lockRoom(roomMutex);
auto clientId = this->consumerIdClientId.find(consumerId);
if(clientId == this->consumerIdClientId.end()) {
OH_LOG_INFO(LOG_APP, "暂停消费者无效:%s", consumerId.data());
return -1;
}
auto client = this->clients.find(clientId->second);
if(client == this->clients.end()) {
OH_LOG_INFO(LOG_APP, "暂停消费者无效:%s %s", consumerId.data(), clientId->second.data());
return -2;
}
client->second->pauseConsumer(consumerId);
return 0;
}
int acgist::Room::resumeConsumer(const std::string& consumerId) {
std::lock_guard<std::mutex> lockRoom(roomMutex);
auto clientId = this->consumerIdClientId.find(consumerId);
if(clientId == this->consumerIdClientId.end()) {
OH_LOG_INFO(LOG_APP, "恢复消费者无效:%s", consumerId.data());
return -1;
}
auto client = this->clients.find(clientId->second);
if(client == this->clients.end()) {
OH_LOG_INFO(LOG_APP, "恢复消费者无效:%s %s", consumerId.data(), clientId->second.data());
return -2;
}
client->second->resumeConsumer(consumerId);
return 0;
}
int acgist::Room::closeProducer(const std::string& producerId) {
std::lock_guard<std::mutex> lockRoom(roomMutex);
if(this->audioProducer != nullptr && this->audioProducer->GetId() == producerId) {
OH_LOG_INFO(LOG_APP, "关闭音频生产者:%s", producerId.data());
this->audioProducer->Close();
delete this->audioProducer;
this->audioProducer == nullptr;
// TODO: 释放
// this->videoTrack->Dspo
} else if(this->videoProducer != nullptr && this->videoProducer->GetId() == producerId) {
OH_LOG_INFO(LOG_APP, "关闭视频生产者:%s", producerId.data());
this->videoProducer->Close();
delete this->videoProducer;
this->videoProducer == nullptr;
// TODO: 释放
// this->videoTrack->Dspo
} else {
return -1;
}
return 0;
}
int acgist::Room::pauseProducer(const std::string& producerId) {
std::lock_guard<std::mutex> lockRoom(roomMutex);
if(this->audioProducer != nullptr && this->audioProducer->GetId() == producerId) {
OH_LOG_INFO(LOG_APP, "暂停音频生产者:%s", producerId.data());
this->audioProducer->Pause();
} else if(this->videoProducer != nullptr && this->videoProducer->GetId() == producerId) {
OH_LOG_INFO(LOG_APP, "暂停视频生产者:%s", producerId.data());
this->videoProducer->Pause();
} else {
return -1;
}
return 0;
}
int acgist::Room::resumeProducer(const std::string& producerId) {
std::lock_guard<std::mutex> lockRoom(roomMutex);
if(this->audioProducer != nullptr && this->audioProducer->GetId() == producerId) {
OH_LOG_INFO(LOG_APP, "恢复音频生产者:%s", producerId.data());
this->audioProducer->Resume();
} else if(this->videoProducer != nullptr && this->videoProducer->GetId() == producerId) {
OH_LOG_INFO(LOG_APP, "恢复视频生产者:%s", producerId.data());
this->videoProducer->Resume();
} else {
return -1;
}
return 0;
}
acgist::SendListener::SendListener(Room* room) : room(room) {
}

View File

@@ -3,5 +3,3 @@
acgist::RoomClient::RoomClient(acgist::MediaManager* mediaManager) : acgist::Client(mediaManager) {}
acgist::RoomClient::~RoomClient() {}
bool acgist::RoomClient::release() { return true; }

View File

@@ -1,3 +1,4 @@
export const init : (json: string) => number;
export const shutdown : (json: string) => number;
export const roomClose : (json: string) => number;
export const roomEnter : (json: string) => number;

View File

@@ -1,33 +1,33 @@
import hilog from '@ohos.hilog';
import window from '@ohos.window';
import UIAbility from '@ohos.app.ability.UIAbility';
import hilog from "@ohos.hilog";
import window from "@ohos.window";
import UIAbility from "@ohos.app.ability.UIAbility";
export default class EntryAbility extends UIAbility {
onCreate(want, launchParam) {
hilog.info(0x0000, 'EntryAbility', 'onCreate');
hilog.info(0x0000, "EntryAbility", "onCreate");
}
onDestroy() {
hilog.info(0x0000, 'EntryAbility', 'onDestroy');
hilog.info(0x0000, "EntryAbility", "onDestroy");
}
onWindowStageCreate(windowStage: window.WindowStage) {
hilog.info(0x0000, 'EntryAbility', 'onWindowStageCreate');
windowStage.loadContent('pages/Index', (err, data) => {
hilog.info(0x0000, "EntryAbility", "onWindowStageCreate");
windowStage.loadContent("pages/Index", (err, data) => {
});
}
onWindowStageDestroy() {
hilog.info(0x0000, 'EntryAbility', 'onWindowStageDestroy');
hilog.info(0x0000, "EntryAbility", "onWindowStageDestroy");
}
onForeground() {
hilog.info(0x0000, 'EntryAbility', 'onForeground');
hilog.info(0x0000, "EntryAbility", "onForeground");
}
onBackground() {
hilog.info(0x0000, 'EntryAbility', 'onBackground');
hilog.info(0x0000, "EntryAbility", "onBackground");
}
};

View File

@@ -14,7 +14,7 @@ struct Index {
signal.connect();
});
}
.width('50%');
.width("50%");
Column() {
Button("断开信令")
.fontSize(20)
@@ -23,9 +23,9 @@ struct Index {
signal.close();
});
}
.width('50%');
.width("50%");
}
.height('100%');
.height("100%");
}
}

View File

@@ -5,26 +5,28 @@
*/
class Signal {
// 终端名称
name: string = "鸿蒙";
name : string = "鸿蒙";
// 终端ID
clientId: string = "harmony";
clientId : string = "harmony";
// 终端类型
clientType: string = "MOBILE";
// 信令账号
username: string = "taoyao";
username : string = "taoyao";
// 信令密码
password: string = "taoyao";
password : string = "taoyao";
};
class Setting {
// 信令地址
signalAddress: string = "wss://192.168.8.204:8888/websocket.signal";
signalAddress: string = "wss://192.168.1.100:8888/websocket.signal";
// 信令版本
version: string = "1.0.0";
// 信令配置
signal: Signal = new Signal();
signal : Signal = new Signal();
};

View File

@@ -1,5 +1,5 @@
/**
* 信令连接
* 信令
*
* @author acgist
*/
@@ -44,7 +44,6 @@ class TaoyaoSignal {
this.socket.close();
}
this.connected = false;
hilog.info(0x0000, "TaoyaoSignal", "连接信令:%s", setting.signalAddress);
this.socket = webSocket.createWebSocket();
this.socket.on("open", (err: BusinessError, value: Object) => {
hilog.info(0x0000, "TaoyaoSignal", "打开信令:%s", setting.signalAddress, value, err);
@@ -52,11 +51,12 @@ class TaoyaoSignal {
this.connected = true;
});
this.socket.on("message", (err: BusinessError, value: string | ArrayBuffer) => {
hilog.debug(0x0000, "TaoyaoSignal", "信令消息:%s", value, err);
const message = value?.toString();
hilog.debug(0x0000, "TaoyaoSignal", "信令消息:%s", message, err);
try {
this.onMessage(value.toString());
this.onMessage(message);
} catch (error) {
hilog.error(0x0000, "TaoyaoSignal", "处理信令消息异常:%s", value, error);
hilog.error(0x0000, "TaoyaoSignal", "处理信令消息异常:%s", message, error);
}
});
this.socket.on("close", (err: BusinessError, value: Object) => {
@@ -67,6 +67,7 @@ class TaoyaoSignal {
hilog.error(0x0000, "TaoyaoSignal", "信令异常:%s", setting.signalAddress, err);
this.reconnect();
});
hilog.info(0x0000, "TaoyaoSignal", "连接信令:%s", setting.signalAddress);
this.socket.connect(setting.signalAddress, (err: BusinessError, value: boolean) => {
hilog.info(0x0000, "TaoyaoSignal", "信令连接成功:%s", setting.signalAddress, value, err);
});
@@ -109,15 +110,15 @@ class TaoyaoSignal {
"battery" : 100,
"charging" : true
});
const body : Record<string, Object> = response.body as Record<string, Object>;
const index : number = body.index as number;
const body = response.body as Record<string, Object>;
const index = body.index as number;
this.clientIndex = index;
hilog.info(0x0000, "TaoyaoSignal", "信令注册成功:%d", index);
this.heartbeat();
}
/**
* 心跳
* 心跳信令
*/
heartbeat() {
if(this.heartbeatTimer) {
@@ -166,7 +167,7 @@ class TaoyaoSignal {
"body" : body
};
try {
hilog.debug(0x0000, "TaoyaoSignal", "发送消息:%o", message);
hilog.debug(0x0000, "TaoyaoSignal", "发送消息:%o", message);
this.socket?.send(JSON.stringify(message));
} catch (error) {
hilog.error(0x0000, "TaoyaoSignal", "发送消息异常:%o", message, error);
@@ -182,8 +183,8 @@ class TaoyaoSignal {
* @returns 响应
*/
async request(signal: string, body: Record<string, Object>): Promise<Record<string, Object>> {
const id = this.buildId();
return new Promise<Record<string, Object>>((resolve, reject) => {
const id = this.buildId();
const header: Record<string, Object> = {
"v" : setting.version,
"id" : id,
@@ -224,13 +225,12 @@ class TaoyaoSignal {
onMessage(message: string) {
const json : Record<string, Object> = JSON.parse(message);
const header: Record<string, Object> = json.header as Record<string, Object>;
const body : Record<string, Object> = json.body as Record<string, Object>;
const id : number = header.id as number;
const signal: string = header.signal as string;
if (this.callbackMapping.has(id)) {
hilog.debug(0x0000, "TaoyaoSignal", "处理同步消息:%s", message);
try {
const callback: Function = this.callbackMapping.get(id) as Function;
const callback = this.callbackMapping.get(id) as Function;
if(callback(json)) {
return;
}
@@ -238,21 +238,73 @@ class TaoyaoSignal {
this.callbackMapping.delete(id);
}
}
hilog.debug(0x0000, "TaoyaoSignal", "处理异步消息:%s", message);
let ret: number = 0;
switch (signal) {
case "room::close":
ret = taoyaoModule.roomClose(message);
break;
case "room::enter":
ret = taoyaoModule.roomEnter(message);
break;
case "room::expel":
ret = taoyaoModule.roomExpel(message);
break;
case "room::invite":
taoyaoModule.roomInvite(message);
ret = taoyaoModule.roomInvite(message);
break;
case "room::leave":
ret = taoyaoModule.roomLeave(message);
break;
case "room::client::list":
ret = taoyaoModule.roomClientList(message);
break;
case "media::consume":
ret = taoyaoModule.mediaConsume(message);
break;
case "media::consumer::close":
ret = taoyaoModule.mediaConsumerClose(message);
break;
case "media::consumer::pause":
ret = taoyaoModule.mediaConsumerPause(message);
break;
case "media::consumer::resume":
ret = taoyaoModule.mediaConsumerResume(message);
break;
case "media::producer::close":
ret = taoyaoModule.mediaProducerClose(message);
break;
case "media::producer::pause":
ret = taoyaoModule.mediaProducerPause(message);
break;
case "media::producer::resume":
ret = taoyaoModule.mediaProducerResume(message);
break;
default:
hilog.error(0x0000, "TaoyaoSignal", "没有适配信令:%s", signal);
ret = -1;
hilog.warn(0x0000, "TaoyaoSignal", "没有适配信令:%s", signal);
break;
}
hilog.debug(0x0000, "TaoyaoSignal", "处理异步消息:%d %s", ret, message);
}
/**
* 注册发送消息
*
* @param signal 信令
* @param body 主体
*/
nativeSend(signal: string, body: string) {
this.send(signal, JSON.parse(body));
}
/**
* 注册请求消息
*
* @param signal 信令
* @param body 主体
*
* @returns 响应
*/
async nativeRequest(signal: string, body: string): Promise<string> {
const response = await this.request(signal, JSON.parse(body));
return JSON.stringify(response);
@@ -262,6 +314,8 @@ class TaoyaoSignal {
const signal = new TaoyaoSignal();
// 加载系统
taoyaoModule.init(JSON.stringify(setting.signal));
// 注册回调
taoyaoModule.registerSend(signal.nativeSend);
taoyaoModule.registerRequest(signal.nativeRequest);