[*] 部分功能

This commit is contained in:
acgist
2024-05-07 08:16:38 +08:00
parent c7c305c67c
commit f9dec2c79f
18 changed files with 802 additions and 59 deletions

View File

@@ -64,7 +64,7 @@
|:--|:--|:--|:--|
|Mediasoup|支持|完成|视频房间(会议模式)|
> 鸿蒙不会实现所有功能,其他功能可以参考`Web`或者`Android`自行实现。
> 鸿蒙不会实现所有功能,其他功能可以参考`Web`或者`Android`以及鸿蒙官网自行实现。
### 注意事项

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,6 @@
#include "../include/Client.hpp"
acgist::Client::Client(acgist::MediaManager* mediaManager) : mediaManager(mediaManager) {
}
acgist::Client::~Client() {}

View File

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

View File

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

View File

@@ -0,0 +1,7 @@
#include "../include/Player.hpp"
acgist::Player::Player() {
}
acgist::Player::~Player() {
}

View File

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

View File

@@ -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: 异常关闭逻辑
}

View File

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

View File

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

View File

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