diff --git a/td/generate/scheme/td_api.tl b/td/generate/scheme/td_api.tl index 2ebd11f16..1898e0005 100644 --- a/td/generate/scheme/td_api.tl +++ b/td/generate/scheme/td_api.tl @@ -2178,6 +2178,18 @@ callStateDiscarded reason:CallDiscardReason need_rating:Bool need_debug_informat callStateError error:error = CallState; +//@class GroupCallVideoQuality @description Describes the quality of a group call video + +//@description The worst available video quality +groupCallVideoQualityThumbnail = GroupCallVideoQuality; + +//@description The medium video quality +groupCallVideoQualityMedium = GroupCallVideoQuality; + +//@description The best available video quality +groupCallVideoQualityFull = GroupCallVideoQuality; + + //@description Describes a recently speaking participant in a group call @participant_id Group call participant identifier @is_speaking True, is the user has spoken recently groupCallRecentSpeaker participant_id:MessageSender is_speaking:Bool = GroupCallRecentSpeaker; @@ -4894,11 +4906,13 @@ leaveGroupCall group_call_id:int32 = Ok; //@description Discards a group call. Requires groupCall.can_be_managed @group_call_id Group call identifier discardGroupCall group_call_id:int32 = Ok; -//@description Returns a file with a segment of a group call stream in a modified OGG format +//@description Returns a file with a segment of a group call stream in a modified OGG format for audio or MPEG-4 format for video //@group_call_id Group call identifier //@time_offset Point in time when the stream segment begins; Unix timestamp in milliseconds //@scale Segment duration scale; 0-1. Segment's duration is 1000/(2**scale) milliseconds -getGroupCallStreamSegment group_call_id:int32 time_offset:int53 scale:int32 = FilePart; +//@channel_id Identifier of an audio/video channel to get as received from tgcalls +//@video_quality Video quality as received from tgcalls +getGroupCallStreamSegment group_call_id:int32 time_offset:int53 scale:int32 channel_id:int32 video_quality:GroupCallVideoQuality = FilePart; //@description Changes the block state of a message sender. Currently, only users and supergroup chats can be blocked @sender Message Sender @is_blocked New value of is_blocked diff --git a/td/telegram/GroupCallManager.cpp b/td/telegram/GroupCallManager.cpp index 96f17000f..8439f5457 100644 --- a/td/telegram/GroupCallManager.cpp +++ b/td/telegram/GroupCallManager.cpp @@ -38,10 +38,11 @@ class GetGroupCallStreamQuery final : public Td::ResultHandler { explicit GetGroupCallStreamQuery(Promise &&promise) : promise_(std::move(promise)) { } - void send(InputGroupCallId input_group_call_id, DcId stream_dc_id, int64 time_offset, int32 scale) { + void send(InputGroupCallId input_group_call_id, DcId stream_dc_id, int64 time_offset, int32 scale, int32 channel_id, + int32 video_quality) { int32 stream_flags = 0; auto input_stream = make_tl_object( - stream_flags, input_group_call_id.get_input_group_call(), time_offset, scale, 0, 0); + stream_flags, input_group_call_id.get_input_group_call(), time_offset, scale, channel_id, video_quality); int32 flags = 0; auto query = G()->net_query_creator().create( telegram_api::upload_getFile(flags, false /*ignored*/, false /*ignored*/, std::move(input_stream), 0, 1 << 20), @@ -2322,6 +2323,8 @@ int32 GroupCallManager::cancel_join_group_call_presentation_request(InputGroupCa } void GroupCallManager::get_group_call_stream_segment(GroupCallId group_call_id, int64 time_offset, int32 scale, + int32 channel_id, + td_api::object_ptr quality, Promise &&promise) { if (G()->close_flag()) { return promise.set_error(Status::Error(500, "Request aborted")); @@ -2332,16 +2335,16 @@ void GroupCallManager::get_group_call_stream_segment(GroupCallId group_call_id, auto *group_call = get_group_call(input_group_call_id); if (group_call == nullptr || !group_call->is_inited) { reload_group_call(input_group_call_id, - PromiseCreator::lambda( - [actor_id = actor_id(this), group_call_id, time_offset, scale, promise = std::move(promise)]( - Result> &&result) mutable { - if (result.is_error()) { - promise.set_error(result.move_as_error()); - } else { - send_closure(actor_id, &GroupCallManager::get_group_call_stream_segment, group_call_id, - time_offset, scale, std::move(promise)); - } - })); + PromiseCreator::lambda([actor_id = actor_id(this), group_call_id, time_offset, scale, channel_id, + quality = std::move(quality), promise = std::move(promise)]( + Result> &&result) mutable { + if (result.is_error()) { + promise.set_error(result.move_as_error()); + } else { + send_closure(actor_id, &GroupCallManager::get_group_call_stream_segment, group_call_id, + time_offset, scale, channel_id, std::move(quality), std::move(promise)); + } + })); return; } if (!group_call->is_active || !group_call->stream_dc_id.is_exact()) { @@ -2349,14 +2352,14 @@ void GroupCallManager::get_group_call_stream_segment(GroupCallId group_call_id, } if (!group_call->is_joined) { if (is_group_call_being_joined(input_group_call_id) || group_call->need_rejoin) { - group_call->after_join.push_back( - PromiseCreator::lambda([actor_id = actor_id(this), group_call_id, time_offset, scale, - promise = std::move(promise)](Result &&result) mutable { + group_call->after_join.push_back(PromiseCreator::lambda( + [actor_id = actor_id(this), group_call_id, time_offset, scale, channel_id, quality = std::move(quality), + promise = std::move(promise)](Result &&result) mutable { if (result.is_error()) { promise.set_error(result.move_as_error()); } else { send_closure(actor_id, &GroupCallManager::get_group_call_stream_segment, group_call_id, time_offset, - scale, std::move(promise)); + scale, channel_id, std::move(quality), std::move(promise)); } })); return; @@ -2364,6 +2367,23 @@ void GroupCallManager::get_group_call_stream_segment(GroupCallId group_call_id, return promise.set_error(Status::Error(400, "GROUPCALL_JOIN_MISSING")); } + int32 video_quality = 0; + if (quality != nullptr) { + switch (quality->get_id()) { + case td_api::groupCallVideoQualityThumbnail::ID: + video_quality = 0; + break; + case td_api::groupCallVideoQualityMedium::ID: + video_quality = 1; + break; + case td_api::groupCallVideoQualityFull::ID: + video_quality = 2; + break; + default: + UNREACHABLE(); + } + } + auto query_promise = PromiseCreator::lambda([actor_id = actor_id(this), input_group_call_id, audio_source = group_call->audio_source, promise = std::move(promise)](Result &&result) mutable { @@ -2371,7 +2391,7 @@ void GroupCallManager::get_group_call_stream_segment(GroupCallId group_call_id, audio_source, std::move(result), std::move(promise)); }); td_->create_handler(std::move(query_promise)) - ->send(input_group_call_id, group_call->stream_dc_id, time_offset, scale); + ->send(input_group_call_id, group_call->stream_dc_id, time_offset, scale, channel_id, video_quality); } void GroupCallManager::finish_get_group_call_stream_segment(InputGroupCallId input_group_call_id, int32 audio_source, diff --git a/td/telegram/GroupCallManager.h b/td/telegram/GroupCallManager.h index cdb14a71e..791c554a3 100644 --- a/td/telegram/GroupCallManager.h +++ b/td/telegram/GroupCallManager.h @@ -60,7 +60,8 @@ class GroupCallManager final : public Actor { void reload_group_call(InputGroupCallId input_group_call_id, Promise> &&promise); - void get_group_call_stream_segment(GroupCallId group_call_id, int64 time_offset, int32 scale, + void get_group_call_stream_segment(GroupCallId group_call_id, int64 time_offset, int32 scale, int32 channel_id, + td_api::object_ptr quality, Promise &&promise); void start_scheduled_group_call(GroupCallId group_call_id, Promise &&promise); diff --git a/td/telegram/Td.cpp b/td/telegram/Td.cpp index 2b4f538a0..1c5651d9b 100644 --- a/td/telegram/Td.cpp +++ b/td/telegram/Td.cpp @@ -6156,7 +6156,7 @@ void Td::on_request(uint64 id, const td_api::discardGroupCall &request) { group_call_manager_->discard_group_call(GroupCallId(request.group_call_id_), std::move(promise)); } -void Td::on_request(uint64 id, const td_api::getGroupCallStreamSegment &request) { +void Td::on_request(uint64 id, td_api::getGroupCallStreamSegment &request) { CHECK_IS_USER(); CREATE_REQUEST_PROMISE(); auto query_promise = PromiseCreator::lambda([promise = std::move(promise)](Result result) mutable { @@ -6169,7 +6169,8 @@ void Td::on_request(uint64 id, const td_api::getGroupCallStreamSegment &request) } }); group_call_manager_->get_group_call_stream_segment(GroupCallId(request.group_call_id_), request.time_offset_, - request.scale_, std::move(query_promise)); + request.scale_, request.channel_id_, + std::move(request.video_quality_), std::move(query_promise)); } void Td::on_request(uint64 id, const td_api::upgradeBasicGroupChatToSupergroupChat &request) { diff --git a/td/telegram/Td.h b/td/telegram/Td.h index 75bfdb3ba..3e2ab2c34 100644 --- a/td/telegram/Td.h +++ b/td/telegram/Td.h @@ -764,7 +764,7 @@ class Td final : public NetQueryCallback { void on_request(uint64 id, const td_api::discardGroupCall &request); - void on_request(uint64 id, const td_api::getGroupCallStreamSegment &request); + void on_request(uint64 id, td_api::getGroupCallStreamSegment &request); void on_request(uint64 id, const td_api::upgradeBasicGroupChatToSupergroupChat &request); diff --git a/td/telegram/cli.cpp b/td/telegram/cli.cpp index 1d1ba6885..10aba36f2 100644 --- a/td/telegram/cli.cpp +++ b/td/telegram/cli.cpp @@ -2760,8 +2760,11 @@ class CliClient final : public Actor { } else if (op == "ggc") { send_request(td_api::make_object(as_group_call_id(args))); } else if (op == "ggcss") { - send_request(td_api::make_object(as_group_call_id(args), - (std::time(nullptr) - 5) * 1000, 0)); + string group_call_id; + int32 channel_id; + get_args(args, group_call_id, channel_id); + send_request(td_api::make_object( + as_group_call_id(group_call_id), (std::time(nullptr) - 5) * 1000, 0, channel_id, nullptr)); } else if (op == "ssgc") { send_request(td_api::make_object(as_group_call_id(args))); } else if (op == "tgcesn" || op == "tgcesne") {