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) {
|
if(auto client{dynamic_pointer_cast<VoiceClient>(target)}; client) {
|
||||||
/* Start normal broadcasting, what the client expects */
|
/* 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 {
|
} else {
|
||||||
/* client left the server */
|
/* client left the server */
|
||||||
|
@ -619,7 +619,7 @@ namespace ts {
|
|||||||
//handleCommandDummy_ConnectFailed
|
//handleCommandDummy_ConnectFailed
|
||||||
//handleCommandDummy_ConnectionLost
|
//handleCommandDummy_ConnectionLost
|
||||||
|
|
||||||
//Not needed - completly useless
|
//Not needed - completely useless
|
||||||
//CMD_TODO handleCommandCustomInfo
|
//CMD_TODO handleCommandCustomInfo
|
||||||
//CMD_TODO handleCommandCustomSearch
|
//CMD_TODO handleCommandCustomSearch
|
||||||
//CMD_TODO serverquerycmd
|
//CMD_TODO serverquerycmd
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include "misc/timer.h"
|
#include "misc/timer.h"
|
||||||
#include "../manager/ActionLogger.h"
|
#include "../manager/ActionLogger.h"
|
||||||
#include "./voice/VoiceClient.h"
|
#include "./voice/VoiceClient.h"
|
||||||
|
#include "../rtc/imports.h"
|
||||||
|
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
using namespace ts;
|
using namespace ts;
|
||||||
@ -620,13 +621,22 @@ command_result SpeakingClient::handleCommand(Command &command) {
|
|||||||
} else if(command.command() == "rtcicecandidate") {
|
} else if(command.command() == "rtcicecandidate") {
|
||||||
return this->handleCommandRtcIceCandidate(command);
|
return this->handleCommandRtcIceCandidate(command);
|
||||||
} else if(command.command() == "rtcbroadcast") {
|
} else if(command.command() == "rtcbroadcast") {
|
||||||
|
/* TODO: Remove this command once the first 1.5.0 stable is out */
|
||||||
return this->handleCommandRtcBroadcast(command);
|
return this->handleCommandRtcBroadcast(command);
|
||||||
} else if(command.command() == "rtcsessionreset") {
|
} else if(command.command() == "rtcsessionreset") {
|
||||||
return this->handleCommandRtcSessionReset(command);
|
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") {
|
} else if(command.command() == "broadcastvideojoin") {
|
||||||
return this->handleCommandBroadcastVideoJoin(command);
|
return this->handleCommandBroadcastVideoJoin(command);
|
||||||
} else if(command.command() == "broadcastvideoleave") {
|
} else if(command.command() == "broadcastvideoleave") {
|
||||||
return this->handleCommandBroadcastVideoLeave(command);
|
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);
|
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);
|
this->server->rtc_server().reset_rtp_session(this->rtc_client_id);
|
||||||
if(this->getType() == ClientType::CLIENT_TEASPEAK) {
|
if(this->getType() == ClientType::CLIENT_TEASPEAK) {
|
||||||
/* registering the broadcast again since rtp session reset resets the broadcasts as well */
|
/* 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};
|
return command_result{error::ok};
|
||||||
}
|
}
|
||||||
@ -696,6 +706,128 @@ command_result SpeakingClient::handleCommandRtcIceCandidate(Command &command) {
|
|||||||
return command_result{error::ok};
|
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) {
|
command_result SpeakingClient::handleCommandRtcBroadcast(Command &command) {
|
||||||
CMD_REQ_SERVER;
|
CMD_REQ_SERVER;
|
||||||
CMD_CHK_AND_INC_FLOOD_POINTS(15);
|
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{};
|
std::vector<std::tuple<uint8_t, uint32_t>> broadcasts{};
|
||||||
broadcasts.reserve(command.bulkCount());
|
broadcasts.reserve(command.bulkCount());
|
||||||
|
|
||||||
|
ts::command_result_bulk result{};
|
||||||
for(size_t index{0}; index < command.bulkCount(); index++) {
|
for(size_t index{0}; index < command.bulkCount(); index++) {
|
||||||
auto& bulk = command[index];
|
auto& bulk = command[index];
|
||||||
|
|
||||||
@ -716,54 +849,37 @@ command_result SpeakingClient::handleCommandRtcBroadcast(Command &command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
broadcasts.push_back(std::make_tuple(type, ssrc));
|
broadcasts.push_back(std::make_tuple(type, ssrc));
|
||||||
}
|
switch(type) {
|
||||||
|
case 1: {
|
||||||
/* TODO: Apply constraints like bandwidth? */
|
ts::Command cmd{""};
|
||||||
|
cmd["ssrc"] = ssrc;
|
||||||
ts::command_result_bulk result{};
|
result.insert_result(this->handleCommandBroadcastAudio(cmd));
|
||||||
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;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case 3:
|
case 2: {
|
||||||
if(!permission::v2::permission_granted(1, this->calculate_permission(permission::b_video_screen, this->getChannelId()), false)) {
|
ts::Command cmd{""};
|
||||||
result.emplace_result(permission::b_video_screen);
|
cmd["broadcast_bitrate_max"] = 1500000;
|
||||||
continue;
|
cmd["broadcast_keyframe_interval"] = 7;
|
||||||
}
|
cmd["ssrc"] = ssrc;
|
||||||
|
cmd["type"] = (uint8_t) rtc::VideoBroadcastType::Camera;
|
||||||
|
result.insert_result(this->handleCommandBroadcastVideo(cmd));
|
||||||
break;
|
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:
|
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");
|
result.emplace_result(error::parameter_invalid, "type");
|
||||||
break;
|
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)};
|
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 */
|
/* The client is free to join his own broadcast */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TODO: Configure the broadcast? */
|
|
||||||
|
|
||||||
using VideoBroadcastJoinResult = rtc::VideoBroadcastJoinResult;
|
using VideoBroadcastJoinResult = rtc::VideoBroadcastJoinResult;
|
||||||
switch(this->server->rtc_server().join_video_broadcast(this->rtc_client_id, broadcast_id, broadcast_type)) {
|
switch(this->server->rtc_server().join_video_broadcast(this->rtc_client_id, broadcast_id, broadcast_type)) {
|
||||||
case VideoBroadcastJoinResult::Success:
|
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);
|
this->server->rtc_server().leave_video_broadcast(this->rtc_client_id, broadcast_id, broadcast_type);
|
||||||
return ts::command_result{error::ok};
|
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 handleCommandRtcSessionDescribe(Command &command);
|
||||||
virtual command_result handleCommandRtcSessionReset(Command &command);
|
virtual command_result handleCommandRtcSessionReset(Command &command);
|
||||||
virtual command_result handleCommandRtcIceCandidate(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 handleCommandBroadcastVideoJoin(Command &);
|
||||||
virtual command_result handleCommandBroadcastVideoLeave(Command &);
|
virtual command_result handleCommandBroadcastVideoLeave(Command &);
|
||||||
|
virtual command_result handleCommandBroadcastVideoConfig(Command &);
|
||||||
|
virtual command_result handleCommandBroadcastVideoConfigure(Command &);
|
||||||
|
|
||||||
void triggerVoiceEnd();
|
void triggerVoiceEnd();
|
||||||
inline void updateSpeak(bool onlyUpdate, const std::chrono::system_clock::time_point &time);
|
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_ban_max_bantime:
|
||||||
case permission::i_client_max_idletime:
|
case permission::i_client_max_idletime:
|
||||||
case permission::i_group_sort_id:
|
case permission::i_group_sort_id:
|
||||||
|
|
||||||
|
case permission::i_video_max_kbps:
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
return true;
|
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 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_DATABASE_VERSION 17
|
||||||
#define CURRENT_PERMISSION_VERSION 7
|
#define CURRENT_PERMISSION_VERSION 8
|
||||||
|
|
||||||
#define CLIENT_UID_LENGTH "64"
|
#define CLIENT_UID_LENGTH "64"
|
||||||
#define CLIENT_NAME_LENGTH "128"
|
#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})) \
|
if(!auto_update(permission::update::type, name, {value, value != permNotGranted}, false, false, {granted, granted != permNotGranted})) \
|
||||||
return false;
|
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_screen", 1, 100);
|
||||||
do_auto_update(QUERY_ADMIN, "b_video_camera", 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);
|
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);
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -45,6 +45,15 @@ struct RtpClientConfigureOptions {
|
|||||||
uint16_t stun_port;
|
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 const char* librtc_version();
|
||||||
extern void librtc_free_str(const char* /* ptr */);
|
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_create_channel(void* /* server */);
|
||||||
extern uint32_t librtc_assign_channel(void* /* server */, uint32_t /* client id */, uint32_t /* channel id */);
|
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 */);
|
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 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 */);
|
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
|
#ifdef __cplusplus
|
||||||
};
|
};
|
||||||
#endif
|
#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;
|
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) {
|
void Server::reset_rtp_session(RTCClientId client_id) {
|
||||||
librtc_reset_rtp_session(this->server_ptr, 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);
|
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);
|
auto result = librtc_assign_channel(this->server_ptr, client_id, channel_id);
|
||||||
switch(result) {
|
switch(result) {
|
||||||
case 0x00: return ChannelAssignResult::Success;
|
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) {
|
BroadcastStartResult Server::start_broadcast_audio(RTCClientId client_id, RTCStreamId track_id) {
|
||||||
auto result = librtc_client_broadcast(this->server_ptr, client_id, btype, 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) {
|
switch(result) {
|
||||||
case 0x00: return BroadcastStartResult::Success;
|
case 0x00: return BroadcastStartResult::Success;
|
||||||
case 0x01: return BroadcastStartResult::InvalidClient;
|
case 0x01: return BroadcastStartResult::InvalidClient;
|
||||||
|
@ -8,6 +8,8 @@ namespace ts::server {
|
|||||||
class SpeakingClient;
|
class SpeakingClient;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct VideoBroadcastOptions;
|
||||||
|
|
||||||
namespace ts::rtc {
|
namespace ts::rtc {
|
||||||
typedef uint32_t RTCClientId;
|
typedef uint32_t RTCClientId;
|
||||||
typedef uint32_t RTCChannelId;
|
typedef uint32_t RTCChannelId;
|
||||||
@ -45,6 +47,14 @@ namespace ts::rtc {
|
|||||||
UnknownError
|
UnknownError
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum struct VideoBroadcastConfigureResult {
|
||||||
|
Success,
|
||||||
|
InvalidClient,
|
||||||
|
InvalidBroadcast, /* Client might not be broadcasting */
|
||||||
|
InvalidBroadcastType,
|
||||||
|
UnknownError
|
||||||
|
};
|
||||||
|
|
||||||
class NativeAudioSourceSupplier;
|
class NativeAudioSourceSupplier;
|
||||||
class Server {
|
class Server {
|
||||||
public:
|
public:
|
||||||
@ -71,14 +81,21 @@ namespace ts::rtc {
|
|||||||
/* channel actions */
|
/* channel actions */
|
||||||
uint32_t create_channel();
|
uint32_t create_channel();
|
||||||
ChannelAssignResult assign_channel(RTCClientId /* client id */, RTCChannelId /* channel id */);
|
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 */);
|
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 */);
|
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 */);
|
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:
|
private:
|
||||||
void* server_ptr{nullptr};
|
void* server_ptr{nullptr};
|
||||||
};
|
};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user