Added support for controlling the streams max bps
This commit is contained in:
parent
a233915064
commit
8be83fc51d
@ -1 +1 @@
|
||||
Subproject commit b07d170e7b5260d341db2617187e0df7edc71b3c
|
||||
Subproject commit 366ba5ba42e7503afcb2e81b367209c9e4f5c5d7
|
2
rtclib
2
rtclib
@ -1 +1 @@
|
||||
Subproject commit ea13ab489529ef0ebc72c15505c6be52ed484269
|
||||
Subproject commit 2c08b8759268095b96f3904757300905db1ea61d
|
@ -478,7 +478,7 @@ void VirtualServer::client_move(
|
||||
}
|
||||
if(auto client{dynamic_pointer_cast<VoiceClient>(target)}; client) {
|
||||
/* Start normal broadcasting, what the client expects */
|
||||
this->rtc_server().start_broadcast(client->rtc_client_id, 1, 1);
|
||||
this->rtc_server().start_broadcast_audio(client->rtc_client_id, 1);
|
||||
}
|
||||
} else {
|
||||
/* client left the server */
|
||||
|
@ -619,7 +619,7 @@ namespace ts {
|
||||
//handleCommandDummy_ConnectFailed
|
||||
//handleCommandDummy_ConnectionLost
|
||||
|
||||
//Not needed - completly useless
|
||||
//Not needed - completely useless
|
||||
//CMD_TODO handleCommandCustomInfo
|
||||
//CMD_TODO handleCommandCustomSearch
|
||||
//CMD_TODO serverquerycmd
|
||||
|
@ -15,6 +15,7 @@
|
||||
#include "misc/timer.h"
|
||||
#include "../manager/ActionLogger.h"
|
||||
#include "./voice/VoiceClient.h"
|
||||
#include "../rtc/imports.h"
|
||||
|
||||
using namespace std::chrono;
|
||||
using namespace ts;
|
||||
@ -620,13 +621,22 @@ command_result SpeakingClient::handleCommand(Command &command) {
|
||||
} else if(command.command() == "rtcicecandidate") {
|
||||
return this->handleCommandRtcIceCandidate(command);
|
||||
} else if(command.command() == "rtcbroadcast") {
|
||||
/* TODO: Remove this command once the first 1.5.0 stable is out */
|
||||
return this->handleCommandRtcBroadcast(command);
|
||||
} else if(command.command() == "rtcsessionreset") {
|
||||
return this->handleCommandRtcSessionReset(command);
|
||||
} else if(command.command() == "broadcastaudio") {
|
||||
return this->handleCommandBroadcastAudio(command);
|
||||
} else if(command.command() == "broadcastvideo") {
|
||||
return this->handleCommandBroadcastVideo(command);
|
||||
} else if(command.command() == "broadcastvideojoin") {
|
||||
return this->handleCommandBroadcastVideoJoin(command);
|
||||
} else if(command.command() == "broadcastvideoleave") {
|
||||
return this->handleCommandBroadcastVideoLeave(command);
|
||||
} else if(command.command() == "broadcastvideoconfig") {
|
||||
return this->handleCommandBroadcastVideoConfig(command);
|
||||
} else if(command.command() == "broadcastvideoconfigure") {
|
||||
return this->handleCommandBroadcastVideoConfigure(command);
|
||||
}
|
||||
}
|
||||
return ConnectedClient::handleCommand(command);
|
||||
@ -676,7 +686,7 @@ command_result SpeakingClient::handleCommandRtcSessionReset(Command &command) {
|
||||
this->server->rtc_server().reset_rtp_session(this->rtc_client_id);
|
||||
if(this->getType() == ClientType::CLIENT_TEASPEAK) {
|
||||
/* registering the broadcast again since rtp session reset resets the broadcasts as well */
|
||||
this->server->rtc_server().start_broadcast(this->rtc_client_id, 1, 1);
|
||||
this->server->rtc_server().start_broadcast_audio(this->rtc_client_id, 1);
|
||||
}
|
||||
return command_result{error::ok};
|
||||
}
|
||||
@ -696,6 +706,128 @@ command_result SpeakingClient::handleCommandRtcIceCandidate(Command &command) {
|
||||
return command_result{error::ok};
|
||||
}
|
||||
|
||||
ts::command_result parse_broadcast_options(ParameterBulk &cmd, VideoBroadcastOptions& options, bool requires_all) {
|
||||
if(cmd.has("broadcast_bitrate_max")) {
|
||||
options.update_mask |= VideoBroadcastOptions::kOptionBitrate;
|
||||
options.bitrate = cmd["broadcast_bitrate_max"];
|
||||
} else if(requires_all) {
|
||||
return ts::command_result{error::parameter_missing, "broadcast_bitrate_max"};
|
||||
}
|
||||
|
||||
if(cmd.has("broadcast_keyframe_interval")) {
|
||||
options.update_mask |= VideoBroadcastOptions::kOptionKeyframeInterval;
|
||||
options.keyframe_interval = cmd["broadcast_keyframe_interval"];
|
||||
} else if(requires_all) {
|
||||
return ts::command_result{error::parameter_missing, "broadcast_keyframe_interval"};
|
||||
}
|
||||
|
||||
return ts::command_result{error::ok};
|
||||
}
|
||||
|
||||
void simplify_broadcast_options(const VideoBroadcastOptions& current_options, VideoBroadcastOptions& target_options) {
|
||||
if(target_options.bitrate == current_options.bitrate) {
|
||||
target_options.update_mask &= ~VideoBroadcastOptions::kOptionBitrate;
|
||||
}
|
||||
|
||||
if(target_options.keyframe_interval == current_options.keyframe_interval) {
|
||||
target_options.update_mask &= ~VideoBroadcastOptions::kOptionKeyframeInterval;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if the client has permissions to use the target broadcast options
|
||||
* @param client
|
||||
* @param channel_id
|
||||
* @param options
|
||||
* @return
|
||||
*/
|
||||
ts::command_result test_broadcast_options(SpeakingClient& client, ChannelId channel_id, const VideoBroadcastOptions& options) {
|
||||
if(options.update_mask & VideoBroadcastOptions::kOptionBitrate) {
|
||||
auto required_value = options.bitrate == 0 ? -1 : (permission::PermissionValue) (options.bitrate / 1000);
|
||||
if(!permission::v2::permission_granted(required_value, client.calculate_permission(permission::i_video_max_kbps, channel_id))) {
|
||||
return ts::command_result{permission::i_video_max_kbps};
|
||||
}
|
||||
}
|
||||
|
||||
return ts::command_result{error::ok};
|
||||
}
|
||||
|
||||
inline command_result broadcast_start_result_to_command_result(rtc::BroadcastStartResult broadcast_result) {
|
||||
switch(broadcast_result) {
|
||||
case rtc::BroadcastStartResult::Success:
|
||||
return ts::command_result{error::ok};
|
||||
case rtc::BroadcastStartResult::InvalidBroadcastType:
|
||||
return ts::command_result{error::parameter_invalid, "type"};
|
||||
case rtc::BroadcastStartResult::InvalidStreamId:
|
||||
return ts::command_result{error::rtc_missing_target_channel};
|
||||
case rtc::BroadcastStartResult::ClientHasNoChannel:
|
||||
return ts::command_result{error::vs_critical, "no channel"};
|
||||
case rtc::BroadcastStartResult::InvalidClient:
|
||||
return ts::command_result{error::vs_critical, "invalid client"};
|
||||
case rtc::BroadcastStartResult::UnknownError:
|
||||
default:
|
||||
return ts::command_result{error::vs_critical, "unknown error"};
|
||||
}
|
||||
}
|
||||
|
||||
command_result SpeakingClient::handleCommandBroadcastAudio(Command &command) {
|
||||
CMD_REQ_SERVER;
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(5);
|
||||
|
||||
auto ssrc = command[0].has("ssrc") ? command["ssrc"].as<uint32_t>() : (uint32_t) 0;
|
||||
auto broadcast_result = this->server->rtc_server().start_broadcast_audio(this->rtc_client_id, ssrc);
|
||||
return broadcast_start_result_to_command_result(broadcast_result);
|
||||
}
|
||||
|
||||
command_result SpeakingClient::handleCommandBroadcastVideo(Command &command) {
|
||||
CMD_REQ_SERVER;
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(15);
|
||||
|
||||
auto ssrc = command[0].has("ssrc") ? command["ssrc"].as<uint32_t>() : (uint32_t) 0;
|
||||
auto type = (rtc::VideoBroadcastType) command["type"].as<uint8_t>();
|
||||
|
||||
switch(type) {
|
||||
case rtc::VideoBroadcastType::Screen:
|
||||
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_video_screen, this->getChannelId()), false)) {
|
||||
return ts::command_result{permission::b_video_screen};
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
|
||||
case rtc::VideoBroadcastType::Camera:
|
||||
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_video_camera, this->getChannelId()), false)) {
|
||||
return ts::command_result{permission::b_video_camera};
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
return ts::command_result{error::parameter_invalid, "type"};
|
||||
}
|
||||
|
||||
VideoBroadcastOptions options;
|
||||
memset(&options, 0, sizeof(options));
|
||||
if(ssrc != 0) {
|
||||
ts::command_result result;
|
||||
|
||||
result.reset(parse_broadcast_options(command[0], options, true));
|
||||
if(result.has_error()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result.reset(test_broadcast_options(*this, this->getChannelId(), options));
|
||||
if(result.has_error()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result.release_data();
|
||||
}
|
||||
|
||||
auto broadcast_result = this->server->rtc_server().start_broadcast_video(this->rtc_client_id, type, ssrc, &options);
|
||||
return broadcast_start_result_to_command_result(broadcast_result);
|
||||
}
|
||||
|
||||
command_result SpeakingClient::handleCommandRtcBroadcast(Command &command) {
|
||||
CMD_REQ_SERVER;
|
||||
CMD_CHK_AND_INC_FLOOD_POINTS(15);
|
||||
@ -703,6 +835,7 @@ command_result SpeakingClient::handleCommandRtcBroadcast(Command &command) {
|
||||
std::vector<std::tuple<uint8_t, uint32_t>> broadcasts{};
|
||||
broadcasts.reserve(command.bulkCount());
|
||||
|
||||
ts::command_result_bulk result{};
|
||||
for(size_t index{0}; index < command.bulkCount(); index++) {
|
||||
auto& bulk = command[index];
|
||||
|
||||
@ -716,54 +849,37 @@ command_result SpeakingClient::handleCommandRtcBroadcast(Command &command) {
|
||||
}
|
||||
|
||||
broadcasts.push_back(std::make_tuple(type, ssrc));
|
||||
}
|
||||
|
||||
/* TODO: Apply constraints like bandwidth? */
|
||||
|
||||
ts::command_result_bulk result{};
|
||||
for(size_t index{0}; index < command.bulkCount(); index++) {
|
||||
auto broadcast_type = std::get<0>(broadcasts[index]);
|
||||
switch(broadcast_type) {
|
||||
case 2:
|
||||
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_video_camera, this->getChannelId()), false)) {
|
||||
result.emplace_result(permission::b_video_camera);
|
||||
continue;
|
||||
}
|
||||
switch(type) {
|
||||
case 1: {
|
||||
ts::Command cmd{""};
|
||||
cmd["ssrc"] = ssrc;
|
||||
result.insert_result(this->handleCommandBroadcastAudio(cmd));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_video_screen, this->getChannelId()), false)) {
|
||||
result.emplace_result(permission::b_video_screen);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
case 2: {
|
||||
ts::Command cmd{""};
|
||||
cmd["broadcast_bitrate_max"] = 1500000;
|
||||
cmd["broadcast_keyframe_interval"] = 7;
|
||||
cmd["ssrc"] = ssrc;
|
||||
cmd["type"] = (uint8_t) rtc::VideoBroadcastType::Camera;
|
||||
result.insert_result(this->handleCommandBroadcastVideo(cmd));
|
||||
break;
|
||||
|
||||
}
|
||||
case 3: {
|
||||
ts::Command cmd{""};
|
||||
cmd["broadcast_bitrate_max"] = 1500000;
|
||||
cmd["broadcast_keyframe_interval"] = 7;
|
||||
cmd["ssrc"] = ssrc;
|
||||
cmd["type"] = (uint8_t) rtc::VideoBroadcastType::Screen;
|
||||
result.insert_result(this->handleCommandBroadcastVideo(cmd));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
auto broadcast_result = this->server->rtc_server().start_broadcast(this->rtc_client_id, std::get<0>(broadcasts[index]), std::get<1>(broadcasts[index]));
|
||||
switch(broadcast_result) {
|
||||
case rtc::BroadcastStartResult::Success:
|
||||
result.emplace_result(error::ok);
|
||||
break;
|
||||
case rtc::BroadcastStartResult::InvalidBroadcastType:
|
||||
result.emplace_result(error::parameter_invalid, "type");
|
||||
break;
|
||||
case rtc::BroadcastStartResult::InvalidStreamId:
|
||||
result.emplace_result(error::rtc_missing_target_channel);
|
||||
break;
|
||||
case rtc::BroadcastStartResult::ClientHasNoChannel:
|
||||
result.emplace_result(error::vs_critical, "no channel");
|
||||
break;
|
||||
case rtc::BroadcastStartResult::InvalidClient:
|
||||
result.emplace_result(error::vs_critical, "invalid client");
|
||||
break;
|
||||
case rtc::BroadcastStartResult::UnknownError:
|
||||
default:
|
||||
result.emplace_result(error::vs_critical, "unknown error");
|
||||
}
|
||||
}
|
||||
|
||||
return ts::command_result{std::move(result)};
|
||||
}
|
||||
|
||||
@ -818,8 +934,6 @@ command_result SpeakingClient::handleCommandBroadcastVideoJoin(Command &cmd) {
|
||||
/* The client is free to join his own broadcast */
|
||||
}
|
||||
|
||||
/* TODO: Configure the broadcast? */
|
||||
|
||||
using VideoBroadcastJoinResult = rtc::VideoBroadcastJoinResult;
|
||||
switch(this->server->rtc_server().join_video_broadcast(this->rtc_client_id, broadcast_id, broadcast_type)) {
|
||||
case VideoBroadcastJoinResult::Success:
|
||||
@ -848,4 +962,101 @@ command_result SpeakingClient::handleCommandBroadcastVideoLeave(Command &cmd) {
|
||||
|
||||
this->server->rtc_server().leave_video_broadcast(this->rtc_client_id, broadcast_id, broadcast_type);
|
||||
return ts::command_result{error::ok};
|
||||
}
|
||||
|
||||
command_result SpeakingClient::handleCommandBroadcastVideoConfig(Command &cmd) {
|
||||
CMD_REQ_SERVER;
|
||||
|
||||
auto broadcast_type = (rtc::VideoBroadcastType) cmd["bt"].as<uint8_t>();
|
||||
|
||||
VideoBroadcastOptions options;
|
||||
auto result = this->server->rtc_server().client_broadcast_video_config(this->rtc_client_id, broadcast_type, &options);
|
||||
switch(result) {
|
||||
case rtc::VideoBroadcastConfigureResult::Success:
|
||||
break;
|
||||
|
||||
case rtc::VideoBroadcastConfigureResult::InvalidBroadcast:
|
||||
return ts::command_result{error::broadcast_invalid_id};
|
||||
|
||||
case rtc::VideoBroadcastConfigureResult::InvalidBroadcastType:
|
||||
return ts::command_result{error::broadcast_invalid_type};
|
||||
|
||||
case rtc::VideoBroadcastConfigureResult::InvalidClient:
|
||||
return ts::command_result{error::client_invalid_id};
|
||||
|
||||
case rtc::VideoBroadcastConfigureResult::UnknownError:
|
||||
default:
|
||||
return ts::command_result{error::vs_critical};
|
||||
}
|
||||
|
||||
ts::command_builder notify{this->notify_response_command("notifybroadcastvideoconfig")};
|
||||
notify.put_unchecked(0, "bt", (uint8_t) broadcast_type);
|
||||
notify.put_unchecked(0, "broadcast_keyframe_interval", options.keyframe_interval);
|
||||
notify.put_unchecked(0, "broadcast_bitrate_max", options.bitrate);
|
||||
this->sendCommand(notify);
|
||||
|
||||
return ts::command_result{error::ok};
|
||||
}
|
||||
|
||||
inline command_result broadcast_config_result_to_command_result(rtc::VideoBroadcastConfigureResult result) {
|
||||
switch(result) {
|
||||
case rtc::VideoBroadcastConfigureResult::Success:
|
||||
return ts::command_result{error::ok};
|
||||
|
||||
case rtc::VideoBroadcastConfigureResult::InvalidBroadcast:
|
||||
return ts::command_result{error::broadcast_invalid_id};
|
||||
|
||||
case rtc::VideoBroadcastConfigureResult::InvalidBroadcastType:
|
||||
return ts::command_result{error::broadcast_invalid_type};
|
||||
|
||||
case rtc::VideoBroadcastConfigureResult::InvalidClient:
|
||||
return ts::command_result{error::client_invalid_id};
|
||||
|
||||
case rtc::VideoBroadcastConfigureResult::UnknownError:
|
||||
default:
|
||||
return ts::command_result{error::vs_critical};
|
||||
}
|
||||
}
|
||||
|
||||
command_result SpeakingClient::handleCommandBroadcastVideoConfigure(Command &cmd) {
|
||||
CMD_REQ_SERVER;
|
||||
|
||||
auto broadcast_type = (rtc::VideoBroadcastType) cmd["bt"].as<uint8_t>();
|
||||
|
||||
VideoBroadcastOptions current_options;
|
||||
auto query_result = this->server->rtc_server().client_broadcast_video_config(this->rtc_client_id, broadcast_type, ¤t_options);
|
||||
if(query_result != rtc::VideoBroadcastConfigureResult::Success) {
|
||||
return broadcast_config_result_to_command_result(query_result);
|
||||
}
|
||||
|
||||
VideoBroadcastOptions options;
|
||||
memset(&options, 0, sizeof(options));
|
||||
{
|
||||
ts::command_result result;
|
||||
|
||||
result.reset(parse_broadcast_options(cmd[0], options, false));
|
||||
if(result.has_error()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
simplify_broadcast_options(current_options, options);
|
||||
result.reset(test_broadcast_options(*this, this->getChannelId(), options));
|
||||
if(result.has_error()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result.release_data();
|
||||
}
|
||||
|
||||
{
|
||||
auto result = test_broadcast_options(*this, this->getChannelId(), options);
|
||||
if(result.has_error()) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result.release_data();
|
||||
}
|
||||
|
||||
auto result = this->server->rtc_server().client_broadcast_video_configure(this->rtc_client_id, broadcast_type, &options);
|
||||
return broadcast_config_result_to_command_result(result);
|
||||
}
|
@ -70,9 +70,13 @@ namespace ts::server {
|
||||
virtual command_result handleCommandRtcSessionDescribe(Command &command);
|
||||
virtual command_result handleCommandRtcSessionReset(Command &command);
|
||||
virtual command_result handleCommandRtcIceCandidate(Command &);
|
||||
virtual command_result handleCommandRtcBroadcast(Command &);
|
||||
virtual command_result handleCommandRtcBroadcast(Command &); /* Old method used 'till 1.5.0b4 */
|
||||
virtual command_result handleCommandBroadcastAudio(Command &);
|
||||
virtual command_result handleCommandBroadcastVideo(Command &);
|
||||
virtual command_result handleCommandBroadcastVideoJoin(Command &);
|
||||
virtual command_result handleCommandBroadcastVideoLeave(Command &);
|
||||
virtual command_result handleCommandBroadcastVideoConfig(Command &);
|
||||
virtual command_result handleCommandBroadcastVideoConfigure(Command &);
|
||||
|
||||
void triggerVoiceEnd();
|
||||
inline void updateSpeak(bool onlyUpdate, const std::chrono::system_clock::time_point &time);
|
||||
|
@ -156,6 +156,8 @@ inline bool permission_require_granted_value(ts::permission::PermissionType type
|
||||
case permission::i_client_ban_max_bantime:
|
||||
case permission::i_client_max_idletime:
|
||||
case permission::i_group_sort_id:
|
||||
|
||||
case permission::i_video_max_kbps:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
|
@ -45,7 +45,7 @@ if(!result && result.msg().find(ignore) == string::npos){
|
||||
#define RESIZE_COLUMN(tblName, rowName, size) up vote EXECUTE("Could not change column size", "ALTER TABLE " tblName " ALTER COLUMN " rowName " varchar(" size ")");
|
||||
|
||||
#define CURRENT_DATABASE_VERSION 17
|
||||
#define CURRENT_PERMISSION_VERSION 7
|
||||
#define CURRENT_PERMISSION_VERSION 8
|
||||
|
||||
#define CLIENT_UID_LENGTH "64"
|
||||
#define CLIENT_NAME_LENGTH "128"
|
||||
@ -841,6 +841,7 @@ bool SqlDataManager::update_permissions(std::string &error) {
|
||||
if(!auto_update(permission::update::type, name, {value, value != permNotGranted}, false, false, {granted, granted != permNotGranted})) \
|
||||
return false;
|
||||
|
||||
/* Attention: Due to a mistake the "i_video_max_kbps" permission has bit and not kbit values. In version 7 we divide by 1000. */
|
||||
do_auto_update(QUERY_ADMIN, "b_video_screen", 1, 100);
|
||||
do_auto_update(QUERY_ADMIN, "b_video_camera", 1, 100);
|
||||
do_auto_update(QUERY_ADMIN, "i_video_max_kbps", 20 * 1000 * 1000, 100);
|
||||
@ -871,6 +872,14 @@ if(!auto_update(permission::update::type, name, {value, value != permNotGranted}
|
||||
|
||||
perm_version(7);
|
||||
|
||||
case 7:
|
||||
result = sql::command(this->sql(), "UPDATE `permissions` SET `value` = `value` / 1000 WHERE permId = 'i_video_max_kbps'").execute();
|
||||
if(!result) {
|
||||
LOG_SQL_CMD(result);
|
||||
return false;
|
||||
}
|
||||
|
||||
perm_version(8);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -45,6 +45,15 @@ struct RtpClientConfigureOptions {
|
||||
uint16_t stun_port;
|
||||
};
|
||||
|
||||
struct VideoBroadcastOptions {
|
||||
constexpr static auto kOptionBitrate{0x01};
|
||||
constexpr static auto kOptionKeyframeInterval{0x02};
|
||||
|
||||
uint32_t update_mask;
|
||||
uint32_t bitrate;
|
||||
uint32_t keyframe_interval;
|
||||
};
|
||||
|
||||
extern const char* librtc_version();
|
||||
extern void librtc_free_str(const char* /* ptr */);
|
||||
|
||||
@ -79,14 +88,21 @@ extern void librtc_destroy_audio_source_supplier(void* /* sender */);
|
||||
|
||||
extern uint32_t librtc_create_channel(void* /* server */);
|
||||
extern uint32_t librtc_assign_channel(void* /* server */, uint32_t /* client id */, uint32_t /* channel id */);
|
||||
extern uint32_t librtc_client_broadcast(void* /* server */, uint32_t /* client id */, uint8_t /* broadcast type */, uint32_t /* stream id */);
|
||||
extern uint32_t librtc_video_broadcast_join(void* /* server */, uint32_t /* client id */, uint32_t /* target client id */, uint8_t /* broadcast type */);
|
||||
extern void librtc_video_broadcast_leave(void* /* server */, uint32_t /* client id */, uint32_t /* target client id */, uint8_t /* broadcast type */);
|
||||
extern void librtc_destroy_channel(void* /* server */, uint32_t /* channel */);
|
||||
|
||||
/* Audio functions */
|
||||
extern uint32_t librtc_client_broadcast_audio(void* /* server */, uint32_t /* client id */, uint32_t /* stream id */);
|
||||
extern const char* librtc_whisper_configure(void* /* server */, uint32_t /* client id */, uint32_t /* source stream id */, uint32_t* /* client ids */, uint32_t /* client id count */);
|
||||
extern void librtc_whisper_reset(void* /* server */, uint32_t /* client id */);
|
||||
|
||||
/* Video functions */
|
||||
extern uint32_t librtc_client_broadcast_video(void* /* server */, uint32_t /* client id */, uint8_t /* broadcast type */, uint32_t /* stream id */, const VideoBroadcastOptions* /* options */);
|
||||
extern uint32_t librtc_client_broadcast_video_configure(void* /* callback data */, uint32_t /* client id */, uint8_t /* broadcast type */, const VideoBroadcastOptions* /* options */);
|
||||
extern uint32_t librtc_client_broadcast_video_config(void* /* callback data */, uint32_t /* client id */, uint8_t /* broadcast type */, VideoBroadcastOptions* /* options */);
|
||||
|
||||
extern uint32_t librtc_video_broadcast_join(void* /* server */, uint32_t /* client id */, uint32_t /* target client id */, uint8_t /* broadcast type */);
|
||||
extern void librtc_video_broadcast_leave(void* /* server */, uint32_t /* client id */, uint32_t /* target client id */, uint8_t /* broadcast type */);
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
@ -324,6 +324,30 @@ bool Server::client_video_stream_count(uint32_t client_id, uint32_t *camera, uin
|
||||
return librtc_client_video_stream_count(this->server_ptr, client_id, camera, desktop) == 0;
|
||||
}
|
||||
|
||||
VideoBroadcastConfigureResult Server::client_broadcast_video_configure(RTCClientId client_id, VideoBroadcastType broadcast_type,
|
||||
const VideoBroadcastOptions *options) {
|
||||
auto result = librtc_client_broadcast_video_configure(this->server_ptr, client_id, (uint8_t) broadcast_type, options);
|
||||
switch(result) {
|
||||
case 0x00: return VideoBroadcastConfigureResult::Success;
|
||||
case 0x01: return VideoBroadcastConfigureResult::InvalidBroadcastType;
|
||||
case 0x02: return VideoBroadcastConfigureResult::InvalidClient;
|
||||
case 0x03: return VideoBroadcastConfigureResult::InvalidBroadcast;
|
||||
default: return VideoBroadcastConfigureResult::UnknownError;
|
||||
}
|
||||
}
|
||||
|
||||
VideoBroadcastConfigureResult Server::client_broadcast_video_config(RTCClientId client_id, VideoBroadcastType broadcast_type,
|
||||
VideoBroadcastOptions *options) {
|
||||
auto result = librtc_client_broadcast_video_config(this->server_ptr, client_id, (uint8_t) broadcast_type, options);
|
||||
switch(result) {
|
||||
case 0x00: return VideoBroadcastConfigureResult::Success;
|
||||
case 0x01: return VideoBroadcastConfigureResult::InvalidBroadcastType;
|
||||
case 0x02: return VideoBroadcastConfigureResult::InvalidClient;
|
||||
case 0x03: return VideoBroadcastConfigureResult::InvalidBroadcast;
|
||||
default: return VideoBroadcastConfigureResult::UnknownError;
|
||||
}
|
||||
}
|
||||
|
||||
void Server::reset_rtp_session(RTCClientId client_id) {
|
||||
librtc_reset_rtp_session(this->server_ptr, client_id);
|
||||
}
|
||||
@ -368,7 +392,7 @@ uint32_t Server::create_channel() {
|
||||
return librtc_create_channel(this->server_ptr);
|
||||
}
|
||||
|
||||
ChannelAssignResult Server::assign_channel(uint32_t client_id, uint32_t channel_id) {
|
||||
ChannelAssignResult Server::assign_channel(RTCClientId client_id, RTCChannelId channel_id) {
|
||||
auto result = librtc_assign_channel(this->server_ptr, client_id, channel_id);
|
||||
switch(result) {
|
||||
case 0x00: return ChannelAssignResult::Success;
|
||||
@ -378,8 +402,22 @@ ChannelAssignResult Server::assign_channel(uint32_t client_id, uint32_t channel_
|
||||
}
|
||||
}
|
||||
|
||||
BroadcastStartResult Server::start_broadcast(uint32_t client_id, uint8_t btype, uint32_t track_id) {
|
||||
auto result = librtc_client_broadcast(this->server_ptr, client_id, btype, track_id);
|
||||
BroadcastStartResult Server::start_broadcast_audio(RTCClientId client_id, RTCStreamId track_id) {
|
||||
auto result = librtc_client_broadcast_audio(this->server_ptr, client_id, track_id);
|
||||
switch(result) {
|
||||
case 0x00: return BroadcastStartResult::Success;
|
||||
case 0x01: return BroadcastStartResult::InvalidClient;
|
||||
case 0x02: return BroadcastStartResult::ClientHasNoChannel;
|
||||
case 0x03: return BroadcastStartResult::InvalidBroadcastType;
|
||||
case 0x04: return BroadcastStartResult::InvalidStreamId;
|
||||
default:
|
||||
logCritical(LOG_GENERAL, "Audio broadcast start returned unknown error code: {}", result);
|
||||
return BroadcastStartResult::UnknownError;
|
||||
}
|
||||
}
|
||||
|
||||
BroadcastStartResult Server::start_broadcast_video(RTCClientId client_id, VideoBroadcastType broadcast_type, RTCStreamId track_id, const VideoBroadcastOptions* options) {
|
||||
auto result = librtc_client_broadcast_video(this->server_ptr, client_id, (uint8_t) broadcast_type, track_id, options);
|
||||
switch(result) {
|
||||
case 0x00: return BroadcastStartResult::Success;
|
||||
case 0x01: return BroadcastStartResult::InvalidClient;
|
||||
|
@ -8,6 +8,8 @@ namespace ts::server {
|
||||
class SpeakingClient;
|
||||
}
|
||||
|
||||
struct VideoBroadcastOptions;
|
||||
|
||||
namespace ts::rtc {
|
||||
typedef uint32_t RTCClientId;
|
||||
typedef uint32_t RTCChannelId;
|
||||
@ -45,6 +47,14 @@ namespace ts::rtc {
|
||||
UnknownError
|
||||
};
|
||||
|
||||
enum struct VideoBroadcastConfigureResult {
|
||||
Success,
|
||||
InvalidClient,
|
||||
InvalidBroadcast, /* Client might not be broadcasting */
|
||||
InvalidBroadcastType,
|
||||
UnknownError
|
||||
};
|
||||
|
||||
class NativeAudioSourceSupplier;
|
||||
class Server {
|
||||
public:
|
||||
@ -71,14 +81,21 @@ namespace ts::rtc {
|
||||
/* channel actions */
|
||||
uint32_t create_channel();
|
||||
ChannelAssignResult assign_channel(RTCClientId /* client id */, RTCChannelId /* channel id */);
|
||||
BroadcastStartResult start_broadcast(RTCClientId /* client id */, uint8_t /* broadcast type */, RTCStreamId /* stream id */);
|
||||
VideoBroadcastJoinResult join_video_broadcast(RTCClientId /* client id */, RTCClientId /* target id */, VideoBroadcastType /* broadcast type */);
|
||||
void leave_video_broadcast(RTCClientId /* client id */, RTCClientId /* target id */, VideoBroadcastType /* broadcast type */);
|
||||
void destroy_channel(RTCChannelId /* channel id */);
|
||||
|
||||
/* whisper actions */
|
||||
/* Audio */
|
||||
BroadcastStartResult start_broadcast_audio(RTCClientId /* client id */, RTCStreamId /* stream id */);
|
||||
|
||||
bool configure_whisper_session(std::string& /* error */, RTCClientId /* client id */, uint32_t /* source stream id */, RTCClientId* /* session members */, size_t /* session member count */);
|
||||
void reset_whisper_session(RTCClientId /* client id */);
|
||||
|
||||
/* Video */
|
||||
BroadcastStartResult start_broadcast_video(RTCClientId /* client id */, VideoBroadcastType /* broadcast type */, RTCStreamId /* stream id */, const VideoBroadcastOptions* /* options */);
|
||||
VideoBroadcastConfigureResult client_broadcast_video_configure(RTCClientId /* client id */, VideoBroadcastType /* broadcast type */, const VideoBroadcastOptions* /* options */);
|
||||
VideoBroadcastConfigureResult client_broadcast_video_config(RTCClientId /* client id */, VideoBroadcastType /* broadcast type */, VideoBroadcastOptions* /* options */);
|
||||
|
||||
VideoBroadcastJoinResult join_video_broadcast(RTCClientId /* client id */, RTCClientId /* target id */, VideoBroadcastType /* broadcast type */);
|
||||
void leave_video_broadcast(RTCClientId /* client id */, RTCClientId /* target id */, VideoBroadcastType /* broadcast type */);
|
||||
private:
|
||||
void* server_ptr{nullptr};
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user