[*] 部分功能
This commit is contained in:
@@ -64,7 +64,7 @@
|
||||
|:--|:--|:--|:--|
|
||||
|Mediasoup|支持|完成|视频房间(会议模式)|
|
||||
|
||||
> 鸿蒙不会实现所有功能,其他功能可以参考`Web`或者`Android`自行实现。
|
||||
> 鸿蒙不会实现所有功能,其他功能可以参考`Web`或者`Android`以及鸿蒙官网自行实现。
|
||||
|
||||
### 注意事项
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace acgist {
|
||||
*/
|
||||
std::future<std::string> OnProduceData(mediasoupclient::SendTransport* transport, const nlohmann::json& sctpStreamParameters, const std::string& label, const std::string& protocol, const nlohmann::json& appData) override {
|
||||
const std::string cTransportId = transport->GetId();
|
||||
LOG_I("生产数据:%s - %s - %s -%s", this->room->roomId.data(), cTransportId.data(), label.data(), protocol.data());
|
||||
LOG_I("生产数据:%s - %s - %s - %s", this->room->roomId.data(), cTransportId.data(), label.data(), protocol.data());
|
||||
std::promise <std::string> promise;
|
||||
return promise.get_future();
|
||||
}
|
||||
|
||||
@@ -14,15 +14,16 @@
|
||||
#include "mediasoupclient.hpp"
|
||||
|
||||
#include "./include/Room.hpp"
|
||||
#include "./include/Signal.hpp"
|
||||
#include "./include/MediaManager.hpp"
|
||||
|
||||
#include <multimedia/player_framework/native_avcapability.h>
|
||||
#include <multimedia/player_framework/native_avcodec_base.h>
|
||||
|
||||
namespace acgist {
|
||||
|
||||
static std::mutex roomMutex;
|
||||
|
||||
namespace acgist {
|
||||
|
||||
// JS环境
|
||||
static napi_env env = nullptr;
|
||||
// 是否加载
|
||||
@@ -101,7 +102,7 @@ static napi_value shutdown(napi_env env, napi_callback_info info) {
|
||||
/**
|
||||
* 发送消息
|
||||
*/
|
||||
static void send(const std::string& signal, const std::string& body) {
|
||||
void send(const std::string& signal, const std::string& body) {
|
||||
napi_value ret;
|
||||
napi_value callback = nullptr;
|
||||
napi_get_reference_value(env, acgist::sendRef, &callback);
|
||||
@@ -115,7 +116,7 @@ static void send(const std::string& signal, const std::string& body) {
|
||||
/**
|
||||
* 发送请求
|
||||
*/
|
||||
static std::string request(const std::string& signal, const std::string& body) {
|
||||
std::string request(const std::string& signal, const std::string& body) {
|
||||
napi_value ret;
|
||||
napi_value callback = nullptr;
|
||||
napi_get_reference_value(env, acgist::requestRef, &callback);
|
||||
@@ -132,7 +133,20 @@ static std::string request(const std::string& signal, const std::string& body) {
|
||||
/**
|
||||
* 房间关闭
|
||||
*/
|
||||
static napi_value roomClose(napi_env env, napi_callback_info info) { return 0; }
|
||||
static napi_value roomClose(napi_env env, napi_callback_info info) {
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(roomMutex);
|
||||
auto iterator = roomMap.find("roomId");
|
||||
if(iterator == roomMap.end()) {
|
||||
|
||||
} else {
|
||||
delete iterator->second;
|
||||
iterator->second = nullptr;
|
||||
roomMap.erase(iterator);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 进入房间
|
||||
@@ -153,30 +167,33 @@ static napi_value roomExpel(napi_env env, napi_callback_info info) { return 0; }
|
||||
* 邀请终端进入房间
|
||||
*/
|
||||
static napi_value roomInvite(napi_env env, napi_callback_info info) {
|
||||
napi_value ret;
|
||||
size_t argc = 1;
|
||||
napi_value args[1] = { nullptr };
|
||||
// TODO: 是否需要释放
|
||||
napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
|
||||
char chars[2048];
|
||||
size_t length;
|
||||
// TODO: 是否需要释放
|
||||
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"];
|
||||
std::string roomId = body["roomId"];
|
||||
std::string password = body["password"];
|
||||
std::lock_guard<std::mutex> guard(roomMutex);
|
||||
auto iterator = roomMap.find(roomId);
|
||||
if(iterator == roomMap.end()) {
|
||||
OH_LOG_INFO(LOG_APP, "进入房间:%s", roomId.c_str());
|
||||
auto room = new acgist::Room(roomId, mediaManager);
|
||||
roomMap[roomId] = room;
|
||||
int enterRet = room->enter(password);
|
||||
napi_create_int32(env, enterRet, &ret);
|
||||
} else {
|
||||
OH_LOG_INFO(LOG_APP, "已经进入房间:%s", roomId.c_str());
|
||||
napi_create_int32(env, -1, &ret);
|
||||
napi_value ret;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(roomMutex);
|
||||
auto iterator = roomMap.find(roomId);
|
||||
if(iterator == roomMap.end()) {
|
||||
OH_LOG_INFO(LOG_APP, "进入房间:%s", roomId.c_str());
|
||||
auto room = new acgist::Room(roomId, mediaManager);
|
||||
roomMap[roomId] = room;
|
||||
int enterRet = room->enter(password);
|
||||
if(enterRet == acgist::SUCCESS_CODE) {
|
||||
room->produceMedia();
|
||||
}
|
||||
napi_create_int32(env, enterRet, &ret);
|
||||
} else {
|
||||
OH_LOG_INFO(LOG_APP, "已经进入房间:%s", roomId.c_str());
|
||||
napi_create_int32(env, -1, &ret);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,22 @@
|
||||
|
||||
namespace acgist {
|
||||
|
||||
/**
|
||||
* 终端
|
||||
*/
|
||||
class Client {
|
||||
|
||||
public:
|
||||
// 媒体管理
|
||||
acgist::MediaManager* mediaManager = nullptr;
|
||||
// 音频轨道
|
||||
webrtc::AudioTrackInterface* audioTrack = nullptr;
|
||||
// 视频轨道
|
||||
webrtc::VideoTrackInterface* videoTrack = nullptr;
|
||||
|
||||
public:
|
||||
Client(acgist::MediaManager* mediaManager);
|
||||
virtual ~Client();
|
||||
|
||||
public:
|
||||
/**
|
||||
@@ -22,18 +37,45 @@ public:
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 房间终端
|
||||
*/
|
||||
class RoomClient : public Client {
|
||||
|
||||
public:
|
||||
acgist::MediaManager* mediaManager;
|
||||
RoomClient(acgist::MediaManager* mediaManager);
|
||||
virtual ~RoomClient();
|
||||
|
||||
public:
|
||||
virtual bool release() override;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 本地终端
|
||||
*/
|
||||
class LocalClient : public RoomClient {
|
||||
|
||||
public:
|
||||
LocalClient(acgist::MediaManager* mediaManager);
|
||||
virtual ~LocalClient();
|
||||
|
||||
public:
|
||||
virtual bool release() override;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 远程终端
|
||||
*/
|
||||
class RemoteClient : public RoomClient {
|
||||
|
||||
public:
|
||||
RemoteClient(acgist::MediaManager* mediaManager);
|
||||
virtual ~RemoteClient();
|
||||
|
||||
public:
|
||||
virtual bool release() override;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* 播放器
|
||||
*
|
||||
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/media/video-playback.md
|
||||
* 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_H
|
||||
#define TAOYAO_PALYER_H
|
||||
|
||||
namespace acgist {
|
||||
|
||||
class Player {};
|
||||
|
||||
class AudioPlayer {};
|
||||
|
||||
class VideoPlayer {};
|
||||
|
||||
}
|
||||
|
||||
#endif //TAOYAO_PALYER_H
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* 播放器
|
||||
*
|
||||
* https://docs.openharmony.cn/pages/v4.1/zh-cn/application-dev/media/media/video-playback.md
|
||||
* 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
|
||||
|
||||
namespace acgist {
|
||||
|
||||
/**
|
||||
* 播放器
|
||||
*/
|
||||
class Player {
|
||||
|
||||
public:
|
||||
Player();
|
||||
virtual ~Player();
|
||||
|
||||
public:
|
||||
// 开始播放
|
||||
virtual bool start() = 0;
|
||||
// 结束播放
|
||||
virtual bool stop() = 0;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 音频播放器
|
||||
*/
|
||||
class AudioPlayer: public Player {
|
||||
|
||||
public:
|
||||
AudioPlayer();
|
||||
virtual ~AudioPlayer();
|
||||
|
||||
public:
|
||||
virtual bool start() override;
|
||||
virtual bool stop() override;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 视频播放器
|
||||
*
|
||||
* TODO: 实现留给有缘人了~.~!
|
||||
*/
|
||||
class VideoPlayer: public Player {
|
||||
|
||||
public:
|
||||
VideoPlayer();
|
||||
virtual ~VideoPlayer();
|
||||
|
||||
public:
|
||||
virtual bool start() override;
|
||||
virtual bool stop() override;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //TAOYAO_PALYER_HPP
|
||||
@@ -6,29 +6,243 @@
|
||||
#ifndef taoyao_Room_HPP
|
||||
#define taoyao_Room_HPP
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "./Client.hpp"
|
||||
#include "./Signal.hpp"
|
||||
#include "./MediaManager.hpp"
|
||||
|
||||
#include "mediasoupclient.hpp"
|
||||
|
||||
namespace acgist {
|
||||
|
||||
class Room;
|
||||
|
||||
/**
|
||||
* 发送通道监听器
|
||||
*/
|
||||
class SendListener : public mediasoupclient::SendTransport::Listener {
|
||||
|
||||
public:
|
||||
/**
|
||||
* 房间指针
|
||||
*/
|
||||
Room* room;
|
||||
|
||||
public:
|
||||
/**
|
||||
* 发送通道监听器
|
||||
*
|
||||
* @param room 房间指针
|
||||
*/
|
||||
explicit SendListener(Room* room);
|
||||
/**
|
||||
* 析构函数
|
||||
*/
|
||||
virtual ~SendListener();
|
||||
|
||||
public:
|
||||
/**
|
||||
* 连接通道
|
||||
*
|
||||
* @param transport 通道指针
|
||||
* @param dtlsParameters DTLS参数
|
||||
*
|
||||
* @return future
|
||||
*/
|
||||
std::future<void> OnConnect(mediasoupclient::Transport* transport, const nlohmann::json& dtlsParameters) override;
|
||||
|
||||
/**
|
||||
* 通道状态改变
|
||||
*
|
||||
* @param transport 通道指针
|
||||
* @param connectionState 当前状态
|
||||
*/
|
||||
void OnConnectionStateChange(mediasoupclient::Transport* transport, const std::string& connectionState) override;
|
||||
|
||||
/**
|
||||
* 通道生产媒体
|
||||
*
|
||||
* @param transport 通道指针
|
||||
* @param kind 媒体类型
|
||||
* @param rtpParameters RTP参数
|
||||
* @param appData 应用数据
|
||||
*
|
||||
* @return 生产者ID
|
||||
*/
|
||||
std::future<std::string> OnProduce(mediasoupclient::SendTransport* transport, const std::string& kind, nlohmann::json rtpParameters, const nlohmann::json& appData) override;
|
||||
|
||||
/**
|
||||
* 通道生产数据
|
||||
* 注意:需要自己实现
|
||||
*
|
||||
* @param transport 通道指针
|
||||
* @param sctpStreamParameters SCTP参数
|
||||
* @param label 标记
|
||||
* @param protocol 协议
|
||||
* @param appData 应用数据
|
||||
*
|
||||
* @return 生产者ID
|
||||
*/
|
||||
std::future<std::string> OnProduceData(mediasoupclient::SendTransport* transport, const nlohmann::json& sctpStreamParameters, const std::string& label, const std::string& protocol, const nlohmann::json& appData) override;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 接收通道监听器
|
||||
*/
|
||||
class RecvListener : public mediasoupclient::RecvTransport::Listener {
|
||||
|
||||
public:
|
||||
/**
|
||||
* 房间指针
|
||||
*/
|
||||
Room* room;
|
||||
|
||||
public:
|
||||
/**
|
||||
* 接收通道监听器
|
||||
*
|
||||
* @param room 房间指针
|
||||
*/
|
||||
explicit RecvListener(Room* room);
|
||||
/**
|
||||
* 析构函数
|
||||
*/
|
||||
virtual ~RecvListener();
|
||||
|
||||
/**
|
||||
* 连接通道
|
||||
*
|
||||
* @param transport 通道指针
|
||||
* @param dtlsParameters DTLS参数
|
||||
*
|
||||
* @return future
|
||||
*/
|
||||
std::future<void> OnConnect(mediasoupclient::Transport* transport, const nlohmann::json& dtlsParameters) override;
|
||||
|
||||
/**
|
||||
* 通道状态改变
|
||||
*
|
||||
* @param transport 通道指针
|
||||
* @param connectionState 通道状态
|
||||
*/
|
||||
void OnConnectionStateChange(mediasoupclient::Transport* transport, const std::string& connectionState) override;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 生产者监听器
|
||||
*/
|
||||
class ProducerListener : public mediasoupclient::Producer::Listener {
|
||||
|
||||
public:
|
||||
/**
|
||||
* 房间指针
|
||||
*/
|
||||
Room* room;
|
||||
|
||||
public:
|
||||
/**
|
||||
* 生产者监听器
|
||||
*
|
||||
* @param room 房间指针
|
||||
*/
|
||||
explicit ProducerListener(Room* room);
|
||||
/**
|
||||
* 析构函数
|
||||
*/
|
||||
virtual ~ProducerListener();
|
||||
|
||||
/**
|
||||
* 通道关闭
|
||||
*
|
||||
* @param producer 生产者
|
||||
*/
|
||||
void OnTransportClose(mediasoupclient::Producer* producer) override;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 消费者监听器
|
||||
*/
|
||||
class ConsumerListener : public mediasoupclient::Consumer::Listener {
|
||||
|
||||
public:
|
||||
/**
|
||||
* 房间指针
|
||||
*/
|
||||
Room* room;
|
||||
|
||||
public:
|
||||
/**
|
||||
* 消费者监听器
|
||||
*
|
||||
* @param room 房间指针
|
||||
*/
|
||||
explicit ConsumerListener(Room* room);
|
||||
/**
|
||||
* 析构函数
|
||||
*/
|
||||
virtual ~ConsumerListener();
|
||||
|
||||
/**
|
||||
* 通道关闭
|
||||
*
|
||||
* @param consumer 消费者
|
||||
*/
|
||||
void OnTransportClose(mediasoupclient::Consumer* consumer) override;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* 房间
|
||||
*/
|
||||
class Room {
|
||||
|
||||
public:
|
||||
// 生产消息:没有实现
|
||||
bool dataProduce = false;
|
||||
// 生产音频
|
||||
bool audioProduce = true;
|
||||
// 生产视频
|
||||
bool videoProduce = true;
|
||||
// 消费音频
|
||||
bool audioConsume = true;
|
||||
// 消费视频
|
||||
bool videoConsume = true;
|
||||
// 房间ID
|
||||
std::string roomId = "";
|
||||
// 媒体管理
|
||||
acgist::MediaManager* mediaManager = nullptr;
|
||||
// 本地终端
|
||||
acgist::LocalClient* client = nullptr;
|
||||
// 远程终端
|
||||
std::vector<acgist::RemoteClient*> clients;
|
||||
// 媒体管理
|
||||
acgist::MediaManager* mediaManager = nullptr;
|
||||
|
||||
std::map<std::string, acgist::RemoteClient*> clients;
|
||||
// WebRTC配置
|
||||
webrtc::PeerConnectionInterface::RTCConfiguration rtcConfiguration;
|
||||
// 房间Device
|
||||
mediasoupclient::Device* device = nullptr;
|
||||
// 发送通道
|
||||
mediasoupclient::SendTransport* sendTransport = nullptr;
|
||||
// 接收通道
|
||||
mediasoupclient::RecvTransport* recvTransport = nullptr;
|
||||
// 发送监听器
|
||||
mediasoupclient::SendTransport::Listener* sendListener = nullptr;
|
||||
// 接收监听器
|
||||
mediasoupclient::RecvTransport::Listener* recvListener = nullptr;
|
||||
// 音频生产者
|
||||
mediasoupclient::Producer* audioProducer = nullptr;
|
||||
// 视频生产者
|
||||
mediasoupclient::Producer* videoProducer = nullptr;
|
||||
// 生产者监听器
|
||||
mediasoupclient::Producer::Listener* producerListener = nullptr;
|
||||
// 消费者监听器
|
||||
mediasoupclient::Consumer::Listener* consumerListener = nullptr;
|
||||
// 消费者列表
|
||||
std::map<std::string, mediasoupclient::Consumer*> consumers;
|
||||
|
||||
public:
|
||||
Room(const std::string& roomId, acgist::MediaManager* mediaManager);
|
||||
virtual ~Room();
|
||||
@@ -39,10 +253,24 @@ public:
|
||||
*
|
||||
* @param password 密码
|
||||
*
|
||||
* @return 是否成功
|
||||
* @return 状态
|
||||
*/
|
||||
int enter(const std::string& password);
|
||||
/**
|
||||
* 生成媒体
|
||||
*
|
||||
* @return 状态
|
||||
*/
|
||||
int produceMedia();
|
||||
int createSendTransport();
|
||||
int createRecvTransport();
|
||||
int produceAudio();
|
||||
int produceVideo();
|
||||
int close();
|
||||
int closeConsumer();
|
||||
int closeAudioProducer();
|
||||
int closeVideoProducer();
|
||||
int closeTransport();
|
||||
int newRemoteClient();
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* 信令
|
||||
*/
|
||||
#ifndef TAOYAO_SIGNAL_HPP
|
||||
#define TAOYAO_SIGNAL_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <json.hpp>
|
||||
|
||||
namespace acgist {
|
||||
|
||||
// 成功状态编码
|
||||
extern const int SUCCESS_CODE = 0;
|
||||
|
||||
/**
|
||||
* 发送消息
|
||||
*
|
||||
* @param signal 信令
|
||||
* @param body 主体
|
||||
*/
|
||||
extern void send(const std::string& signal, const std::string& body);
|
||||
|
||||
/**
|
||||
* 发送请求
|
||||
*
|
||||
* @param signal 信令
|
||||
* @param body 主体
|
||||
*
|
||||
* @return 响应
|
||||
*/
|
||||
extern std::string request(const std::string& signal, const std::string& body);
|
||||
|
||||
}
|
||||
|
||||
#endif //TAOYAO_SIGNAL_HPP
|
||||
@@ -0,0 +1,11 @@
|
||||
#include "../include/Player.hpp"
|
||||
|
||||
acgist::AudioPlayer::AudioPlayer() {
|
||||
}
|
||||
|
||||
acgist::AudioPlayer::~AudioPlayer() {
|
||||
}
|
||||
|
||||
bool acgist::AudioPlayer::start() { return true; }
|
||||
|
||||
bool acgist::AudioPlayer::stop() { return true; }
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
#include "../include/Client.hpp"
|
||||
|
||||
acgist::Client::Client(acgist::MediaManager* mediaManager) : mediaManager(mediaManager) {
|
||||
}
|
||||
|
||||
acgist::Client::~Client() {}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
#include "../include/Client.hpp"
|
||||
|
||||
acgist::LocalClient::LocalClient(acgist::MediaManager* mediaManager) : acgist::RoomClient(mediaManager) {
|
||||
this->mediaManager->newLocalClient();
|
||||
}
|
||||
|
||||
acgist::LocalClient::~LocalClient() {
|
||||
this->release();
|
||||
this->mediaManager->releaseLocalClient();
|
||||
}
|
||||
|
||||
bool acgist::LocalClient::release() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "../include/MediaManager.hpp"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "hilog/log.h"
|
||||
|
||||
#include "api/create_peerconnection_factory.h"
|
||||
@@ -12,6 +14,8 @@
|
||||
#include <api/video_codecs/builtin_video_decoder_factory.h>
|
||||
#include <api/video_codecs/builtin_video_encoder_factory.h>
|
||||
|
||||
static std::mutex refMutex;
|
||||
|
||||
acgist::MediaManager::MediaManager() {
|
||||
}
|
||||
|
||||
@@ -52,7 +56,17 @@ bool acgist::MediaManager::initPeerConnectionFactory() {
|
||||
}
|
||||
|
||||
int acgist::MediaManager::newLocalClient() {
|
||||
this->localClientRef++;
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(refMutex);
|
||||
this->localClientRef++;
|
||||
}
|
||||
}
|
||||
|
||||
int acgist::MediaManager::releaseLocalClient() {
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(refMutex);
|
||||
this->localClientRef--;
|
||||
}
|
||||
}
|
||||
|
||||
bool acgist::MediaManager::startCapture() {
|
||||
@@ -71,7 +85,7 @@ bool acgist::MediaManager::startVideoCapture() {
|
||||
|
||||
rtc::scoped_refptr<webrtc::AudioTrackInterface> acgist::MediaManager::getAudioTrack() {
|
||||
cricket::AudioOptions options;
|
||||
options.highpass_filter = true;
|
||||
options.highpass_filter = true;
|
||||
options.auto_gain_control = true;
|
||||
options.echo_cancellation = true;
|
||||
options.noise_suppression = true;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "../include/Player.hpp"
|
||||
|
||||
acgist::Player::Player() {
|
||||
}
|
||||
|
||||
acgist::Player::~Player() {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "../include/Client.hpp"
|
||||
|
||||
acgist::RemoteClient::RemoteClient(acgist::MediaManager* mediaManager) : RoomClient(mediaManager) {}
|
||||
|
||||
acgist::RemoteClient::~RemoteClient() {}
|
||||
|
||||
bool acgist::RemoteClient::release() { return true; }
|
||||
|
||||
@@ -1,20 +1,317 @@
|
||||
#include "../include/Room.hpp"
|
||||
#include "Client.hpp"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
#include "hilog/log.h"
|
||||
|
||||
static std::mutex roomMutex;
|
||||
|
||||
acgist::Room::Room(const std::string& roomId, acgist::MediaManager* mediaManager) : roomId(roomId), mediaManager(mediaManager) {
|
||||
|
||||
this->device = new mediasoupclient::Device();
|
||||
this->sendListener = new acgist::SendListener(this);
|
||||
this->recvListener = new acgist::RecvListener(this);
|
||||
this->producerListener = new acgist::ProducerListener(this);
|
||||
this->consumerListener = new acgist::ConsumerListener(this);
|
||||
}
|
||||
|
||||
acgist::Room::~Room() {
|
||||
this->close();
|
||||
// rtcConfiguration
|
||||
if (this->device != nullptr) {
|
||||
delete this->device;
|
||||
this->device = nullptr;
|
||||
}
|
||||
if (this->sendListener != nullptr) {
|
||||
delete this->sendListener;
|
||||
this->sendListener = nullptr;
|
||||
}
|
||||
if (this->sendTransport != nullptr) {
|
||||
delete this->sendTransport;
|
||||
this->sendTransport = nullptr;
|
||||
}
|
||||
if (this->recvListener != nullptr) {
|
||||
delete this->recvListener;
|
||||
this->recvListener = nullptr;
|
||||
}
|
||||
if (this->recvTransport != nullptr) {
|
||||
delete this->recvTransport;
|
||||
this->recvTransport = nullptr;
|
||||
}
|
||||
if (this->audioProducer != nullptr) {
|
||||
delete this->audioProducer;
|
||||
this->audioProducer = nullptr;
|
||||
}
|
||||
if (this->videoProducer != nullptr) {
|
||||
delete this->videoProducer;
|
||||
this->videoProducer = nullptr;
|
||||
}
|
||||
if (this->producerListener != nullptr) {
|
||||
delete this->producerListener;
|
||||
this->producerListener = nullptr;
|
||||
}
|
||||
if (this->consumerListener != nullptr) {
|
||||
delete this->consumerListener;
|
||||
this->consumerListener = nullptr;
|
||||
}
|
||||
if(this->client != nullptr) {
|
||||
this->client->release();
|
||||
delete this->client;
|
||||
this->client = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int acgist::Room::enter(const std::string& password) {
|
||||
this->mediaManager->newLocalClient();
|
||||
// this->client = new LocalClient();
|
||||
if (this->device->IsLoaded()) {
|
||||
OH_LOG_WARN(LOG_APP, "Device配置已经加载:%s", this->roomId.data());
|
||||
return -1;
|
||||
}
|
||||
// 本地终端
|
||||
this->client = new acgist::LocalClient(this->mediaManager);
|
||||
// 房间能力
|
||||
nlohmann::json requestBody = {
|
||||
{ "roomId", this->roomId }
|
||||
};
|
||||
std::string response = acgist::request("media::router::rtp::capabilities", requestBody.dump());
|
||||
nlohmann::json json = nlohmann::json::parse(response);
|
||||
nlohmann::json responseBody = json["body"];
|
||||
nlohmann::json rtpCapabilities = responseBody["rtpCapabilities"];
|
||||
// 加载设备
|
||||
// this->rtcConfiguration->set_cpu_adaptation(false);
|
||||
mediasoupclient::PeerConnection::Options options;
|
||||
options.config = this->rtcConfiguration;
|
||||
options.factory = this->mediaManager->peerConnectionFactory.get();
|
||||
this->device->Load(rtpCapabilities, &options);
|
||||
// 进入房间
|
||||
requestBody = {
|
||||
{ "roomId", this->roomId },
|
||||
{ "password", password },
|
||||
{ "rtpCapabilities", this->device->GetRtpCapabilities().dump() },
|
||||
{ "sctpCapabilities", this->device->GetSctpCapabilities().dump() }
|
||||
};
|
||||
response = acgist::request("room::enter", requestBody.dump());
|
||||
OH_LOG_INFO(LOG_APP, "进入房间:%s", this->roomId.data());
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acgist::Room::produceMedia() {
|
||||
OH_LOG_INFO(LOG_APP, "生成媒体:%s", this->roomId.data());
|
||||
if(this->audioProduce || this->videoProduce) {
|
||||
this->createSendTransport();
|
||||
}
|
||||
if(this->audioConsume || this->videoConsume) {
|
||||
this->createRecvTransport();
|
||||
}
|
||||
if(this->audioProduce) {
|
||||
this->produceAudio();
|
||||
}
|
||||
if(this->videoProduce) {
|
||||
this->produceVideo();
|
||||
}
|
||||
}
|
||||
|
||||
int acgist::Room::createSendTransport() {
|
||||
nlohmann::json requestBody = {
|
||||
{ "roomId", this->roomId },
|
||||
{ "forceTcp", false },
|
||||
{ "producing", true },
|
||||
{ "consuming", false },
|
||||
// { "sctpCapabilities", sctpCapabilities },
|
||||
};
|
||||
std::string response = acgist::request("media::transport::webrtc::create", requestBody.dump());
|
||||
nlohmann::json json = nlohmann::json::parse(response);
|
||||
nlohmann::json responseBody = json["body"];
|
||||
mediasoupclient::PeerConnection::Options options;
|
||||
options.config = this->rtcConfiguration;
|
||||
options.factory = this->mediaManager->peerConnectionFactory.get();
|
||||
this->sendTransport = this->device->CreateSendTransport(
|
||||
this->sendListener,
|
||||
responseBody["transportId"],
|
||||
responseBody["iceParameters"],
|
||||
responseBody["iceCandidates"],
|
||||
responseBody["dtlsParameters"],
|
||||
responseBody["sctpParameters"],
|
||||
&options
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acgist::Room::createRecvTransport() {
|
||||
nlohmann::json requestBody = {
|
||||
{ "roomId", this->roomId },
|
||||
{ "forceTcp", false },
|
||||
{ "producing", false },
|
||||
{ "consuming", true },
|
||||
// { "sctpCapabilities", sctpCapabilities },
|
||||
};
|
||||
std::string response = acgist::request("media::transport::webrtc::create", requestBody.dump());
|
||||
nlohmann::json json = nlohmann::json::parse(response);
|
||||
nlohmann::json responseBody = json["body"];
|
||||
mediasoupclient::PeerConnection::Options options;
|
||||
options.config = this->rtcConfiguration;
|
||||
options.factory = this->mediaManager->peerConnectionFactory.get();
|
||||
this->recvTransport = this->device->CreateRecvTransport(
|
||||
this->recvListener,
|
||||
json["transportId"],
|
||||
json["iceParameters"],
|
||||
json["iceCandidates"],
|
||||
json["dtlsParameters"],
|
||||
json["sctpParameters"],
|
||||
&options
|
||||
);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acgist::Room::produceAudio() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acgist::Room::produceVideo() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acgist::Room::close() {
|
||||
OH_LOG_INFO(LOG_APP, "关闭房间:%s", this->roomId.data());
|
||||
this->closeConsumer();
|
||||
this->closeAudioProducer();
|
||||
this->closeVideoProducer();
|
||||
this->closeTransport();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acgist::Room::closeConsumer() {
|
||||
std::lock_guard<std::mutex> lockRoom(roomMutex);
|
||||
for (auto iterator = this->consumers.begin(); iterator != this->consumers.end(); ++iterator) {
|
||||
if (iterator->second == nullptr) {
|
||||
continue;
|
||||
}
|
||||
OH_LOG_INFO(LOG_APP, "关闭消费者:%s", iterator->second->GetId().data());
|
||||
iterator->second->Close();
|
||||
delete iterator->second;
|
||||
iterator->second = nullptr;
|
||||
}
|
||||
this->consumers.clear();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acgist::Room::closeAudioProducer() {
|
||||
std::lock_guard<std::mutex> lockRoom(roomMutex);
|
||||
if (this->audioProducer != nullptr) {
|
||||
this->audioProducer->Close();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acgist::Room::closeVideoProducer() {
|
||||
std::lock_guard<std::mutex> lockRoom(roomMutex);
|
||||
if (this->videoProducer != nullptr) {
|
||||
this->videoProducer->Close();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int acgist::Room::closeTransport() {
|
||||
std::lock_guard<std::mutex> lockRoom(roomMutex);
|
||||
if (this->sendTransport != nullptr) {
|
||||
this->sendTransport->Close();
|
||||
}
|
||||
if (this->recvTransport != nullptr) {
|
||||
this->recvTransport->Close();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
acgist::SendListener::SendListener(Room* room) : room(room) {
|
||||
}
|
||||
|
||||
acgist::SendListener::~SendListener() {
|
||||
}
|
||||
|
||||
std::future<void> acgist::SendListener::OnConnect(mediasoupclient::Transport* transport, const nlohmann::json& dtlsParameters) {
|
||||
OH_LOG_INFO(LOG_APP, "连接发送通道:%s - %s", this->room->roomId.data(), transport->GetId().data());
|
||||
nlohmann::json requestBody = {
|
||||
{ "roomId", this->roomId },
|
||||
{ "transportId", transport->GetId() },
|
||||
{ "dtlsParameters", dtlsParameters },
|
||||
};
|
||||
std::string response = acgist::send("media::transport::webrtc::connect", requestBody.dump());
|
||||
std::promise<void> promise;
|
||||
promise.set_value();
|
||||
return promise.get_future();
|
||||
}
|
||||
|
||||
void acgist::SendListener::OnConnectionStateChange(mediasoupclient::Transport* transport, const std::string& connectionState) {
|
||||
OH_LOG_INFO(LOG_APP, "发送通道状态改变:%s - %s - %s", this->room->roomId.data(), transport->GetId().data(), connectionState.data());
|
||||
// TODO: 异常关闭逻辑
|
||||
}
|
||||
|
||||
std::future<std::string> acgist::SendListener::OnProduce(mediasoupclient::SendTransport* transport, const std::string& kind, nlohmann::json rtpParameters, const nlohmann::json& appData) override {
|
||||
OH_LOG_INFO(LOG_APP, "生产媒体:%s - %s - %s", this->room->roomId.data(), transport->GetId().data(), kind.data());
|
||||
nlohmann::json requestBody = {
|
||||
{ "kind", kind },
|
||||
{ "roomId", this.roomId },
|
||||
{ "transportId", transport->GetId() },
|
||||
{ "rtpParameters", rtpParameters },
|
||||
};
|
||||
std::string response = acgist::request("media::produce", requestBody.dump());
|
||||
nlohmann::json json = nlohmann::json::parse(response);
|
||||
nlohmann::json responseBody = json["body"];
|
||||
std::string producerId = responseBody["producerId"];
|
||||
std::promise<std::string> promise;
|
||||
promise.set_value(producerId);
|
||||
return promise.get_future();
|
||||
}
|
||||
|
||||
std::future<std::string> acgist::SendListener::OnProduceData(mediasoupclient::SendTransport* transport, const nlohmann::json& sctpStreamParameters, const std::string& label, const std::string& protocol, const nlohmann::json& appData) override; {
|
||||
OH_LOG_INFO(LOG_APP, "生产数据:%s - %s - %s - %s", this->room->roomId.data(), transport->GetId().data(), label.data(), protocol.data());
|
||||
// TODO: 代码实现
|
||||
std::promise<std::string> promise;
|
||||
// promise.set_value("producerId");
|
||||
return promise.get_future();
|
||||
}
|
||||
|
||||
acgist::RecvListener::RecvListener(acgist::Room* room) : room(room) {
|
||||
}
|
||||
|
||||
acgist::RecvListener::~RecvListener() {
|
||||
}
|
||||
|
||||
std::future<void> acgist::RecvListener::OnConnect(mediasoupclient::Transport* transport, const nlohmann::json& dtlsParameters) {
|
||||
OH_LOG_INFO(LOG_APP, "连接接收通道:%s - %s", this->room->roomId.data(), transport->GetId().data());
|
||||
nlohmann::json requestBody = {
|
||||
{ "roomId", this->roomId },
|
||||
{ "transportId", transport->GetId() },
|
||||
{ "dtlsParameters", dtlsParameters },
|
||||
};
|
||||
std::string response = acgist::send("media::transport::webrtc::connect", requestBody.dump());
|
||||
std::promise<void> promise;
|
||||
promise.set_value();
|
||||
return promise.get_future();
|
||||
}
|
||||
|
||||
void acgist::RecvListener::OnConnectionStateChange(mediasoupclient::Transport* transport, const std::string& connectionState) {
|
||||
OH_LOG_INFO(LOG_APP, "接收通道状态改变:%s - %s - %s", this->room->roomId.data(), transport->GetId().data(), connectionState.data());
|
||||
// TODO: 异常关闭逻辑
|
||||
}
|
||||
|
||||
acgist::ProducerListener::ProducerListener(acgist::Room* room) : room(room) {
|
||||
}
|
||||
|
||||
acgist::ProducerListener::~ProducerListener() {
|
||||
}
|
||||
|
||||
void acgist::ProducerListener::OnTransportClose(mediasoupclient::Producer* producer) {
|
||||
OH_LOG_INFO(LOG_APP, "生产者通道关闭:%s - %s", this->room->roomId.data(), producer->GetId().data());
|
||||
producer->Close();
|
||||
// TODO: 异常关闭逻辑
|
||||
}
|
||||
|
||||
acgist::ConsumerListener::ConsumerListener(acgist::Room* room) : room(room) {
|
||||
}
|
||||
|
||||
acgist::ConsumerListener::~ConsumerListener() {
|
||||
}
|
||||
|
||||
void acgist::ConsumerListener::OnTransportClose(mediasoupclient::Consumer* consumer) {
|
||||
OH_LOG_INFO(LOG_APP, "消费者通道关闭:%s - %s", this->room->roomId.data(), consumer->GetId().data());
|
||||
consumer->Close();
|
||||
// TODO: 异常关闭逻辑
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "../include/Client.hpp"
|
||||
|
||||
acgist::RoomClient::RoomClient(acgist::MediaManager* mediaManager) : acgist::Client(mediaManager) {}
|
||||
|
||||
acgist::RoomClient::~RoomClient() {}
|
||||
|
||||
bool acgist::RoomClient::release() { return true; }
|
||||
|
||||
@@ -147,13 +147,12 @@ static void OnNewOutputBuffer(OH_AVCodec* codec, uint32_t index, OH_AVBuffer* bu
|
||||
OH_AVErrCode ret = OH_AVBuffer_GetBufferAttr(buffer, &info);
|
||||
char* data = reinterpret_cast<char*>(OH_AVBuffer_GetAddr(buffer));
|
||||
// TODO: 解析
|
||||
rtc::scoped_refptr<webrtc::I420Buffer> videoFrameBuffer = webrtc::I420Buffer::Copy(width, height, (uint8_t*)data, 0, (uint8_t*)data, 0, (uint8_t*)data, 0);
|
||||
rtc::scoped_refptr<webrtc::I420Buffer> videoFrameBuffer = webrtc::I420Buffer::Copy(width, height, (uint8_t*) data, 0, (uint8_t*) data, 0, (uint8_t*) data, 0);
|
||||
// webrtc::NV12Buffer::Create(width, height);
|
||||
webrtc::VideoFrame::Builder builder;
|
||||
webrtc::VideoFrame videoFrame = builder
|
||||
.set_timestamp_ms(rtc::TimeMillis())
|
||||
.set_video_frame_buffer(videoFrameBuffer)
|
||||
.set_rotation(webrtc::VideoRotation::kVideoRotation_0)
|
||||
.build();
|
||||
for (auto iterator = videoCapturer->map.begin(); iterator != videoCapturer->map.end(); ++iterator) {
|
||||
iterator->second->OnFrame(videoFrame);
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#include "../include/Player.hpp"
|
||||
|
||||
acgist::VideoPlayer::VideoPlayer() {
|
||||
}
|
||||
|
||||
acgist::VideoPlayer::~VideoPlayer() {
|
||||
}
|
||||
|
||||
bool acgist::VideoPlayer::start() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool acgist::VideoPlayer::stop() {
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user