Repo created

This commit is contained in:
Fr4nz D13trich 2025-11-22 14:04:28 +01:00
parent 81b91f4139
commit f8c34fa5ee
22732 changed files with 4815320 additions and 2 deletions

View file

@ -0,0 +1,62 @@
#include "AndroidContext.h"
#include "sdk/android/native_api/jni/jvm.h"
#include "tgnet/FileLog.h"
namespace tgcalls {
AndroidContext::AndroidContext(JNIEnv *env, jobject peerInstance, jobject groupInstance, bool screencast) {
VideoCapturerDeviceClass = (jclass) env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/VideoCapturerDevice"));
jmethodID initMethodId = env->GetMethodID(VideoCapturerDeviceClass, "<init>", "(Z)V");
javaCapturer = env->NewGlobalRef(env->NewObject(VideoCapturerDeviceClass, initMethodId, screencast));
if (peerInstance) {
javaPeerInstance = env->NewGlobalRef(peerInstance);
}
if (groupInstance) {
javaGroupInstance = env->NewGlobalRef(groupInstance);
}
}
AndroidContext::~AndroidContext() {
JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded();
jmethodID onDestroyMethodId = env->GetMethodID(VideoCapturerDeviceClass, "onDestroy", "()V");
env->CallVoidMethod(javaCapturer, onDestroyMethodId);
env->DeleteGlobalRef(javaCapturer);
javaCapturer = nullptr;
env->DeleteGlobalRef(VideoCapturerDeviceClass);
if (javaPeerInstance) {
env->DeleteGlobalRef(javaPeerInstance);
}
if (javaGroupInstance) {
env->DeleteGlobalRef(javaGroupInstance);
}
}
void AndroidContext::setJavaPeerInstance(JNIEnv *env, jobject instance) {
javaPeerInstance = env->NewGlobalRef(instance);
}
void AndroidContext::setJavaGroupInstance(JNIEnv *env, jobject instance) {
javaGroupInstance = env->NewGlobalRef(instance);
}
jobject AndroidContext::getJavaPeerInstance() {
return javaPeerInstance;
}
jobject AndroidContext::getJavaGroupInstance() {
return javaGroupInstance;
}
jobject AndroidContext::getJavaCapturer() {
return javaCapturer;
}
jclass AndroidContext::getJavaCapturerClass() {
return VideoCapturerDeviceClass;
}
} // namespace tgcalls

View file

@ -0,0 +1,39 @@
#ifndef TGCALLS_ANDROID_CONTEXT_H
#define TGCALLS_ANDROID_CONTEXT_H
#include "PlatformContext.h"
#include <jni.h>
#include <voip/tgcalls/group/GroupInstanceImpl.h>
namespace tgcalls {
class AndroidContext final : public PlatformContext {
public:
AndroidContext(JNIEnv *env, jobject peerInstance, jobject groupInstance, bool screencast);
~AndroidContext() override;
jobject getJavaCapturer();
jobject getJavaPeerInstance();
jobject getJavaGroupInstance();
jclass getJavaCapturerClass();
void setJavaPeerInstance(JNIEnv *env, jobject instance);
void setJavaGroupInstance(JNIEnv *env, jobject instance);
std::vector<std::shared_ptr<BroadcastPartTask>> audioStreamTasks;
std::vector<std::shared_ptr<BroadcastPartTask>> videoStreamTasks;
std::vector<std::shared_ptr<RequestMediaChannelDescriptionTask>> descriptionTasks;
private:
jclass VideoCapturerDeviceClass = nullptr;
jobject javaCapturer = nullptr;
jobject javaPeerInstance = nullptr;
jobject javaGroupInstance = nullptr;
};
} // namespace tgcalls
#endif

View file

@ -0,0 +1,160 @@
#include "AndroidInterface.h"
#include <rtc_base/ssl_adapter.h>
#include <modules/utility/include/jvm_android.h>
#include <sdk/android/src/jni/android_video_track_source.h>
#include <media/base/media_constants.h>
#include "VideoCapturerInterfaceImpl.h"
#include "sdk/android/native_api/base/init.h"
#include "sdk/android/native_api/codecs/wrapper.h"
#include "sdk/android/native_api/jni/class_loader.h"
#include "sdk/android/native_api/jni/jvm.h"
#include "sdk/android/native_api/jni/scoped_java_ref.h"
#include "sdk/android/native_api/video/video_source.h"
#include "api/video_codecs/builtin_video_encoder_factory.h"
#include "api/video_codecs/builtin_video_decoder_factory.h"
#include "pc/video_track_source_proxy.h"
#include "sdk/android/src/jni/android_network_monitor.h"
#include "api/video_track_source_proxy_factory.h"
#include "AndroidContext.h"
#include "media/engine/simulcast_encoder_adapter.h"
namespace tgcalls {
void AndroidInterface::configurePlatformAudio(int numChannels) {
}
class SimulcastVideoEncoderFactory : public webrtc::VideoEncoderFactory {
public:
std::unique_ptr<webrtc::VideoEncoderFactory> main_factory;
std::unique_ptr<webrtc::SimulcastEncoderAdapter> simulcast_adapter;
SimulcastVideoEncoderFactory(
std::unique_ptr<webrtc::VideoEncoderFactory> main_factory
): main_factory(std::move(main_factory)) {}
std::vector<webrtc::SdpVideoFormat> GetSupportedFormats() const override {
return main_factory->GetSupportedFormats();
}
std::vector<webrtc::SdpVideoFormat> GetImplementations() const override {
return main_factory->GetImplementations();
}
std::unique_ptr<EncoderSelectorInterface> GetEncoderSelector() const override {
return main_factory->GetEncoderSelector();
}
std::unique_ptr<webrtc::VideoEncoder> CreateVideoEncoder(const webrtc::SdpVideoFormat& format) override {
return std::make_unique<webrtc::SimulcastEncoderAdapter>(main_factory.get(), format);
}
CodecSupport QueryCodecSupport(
const webrtc::SdpVideoFormat& format,
absl::optional<std::string> scalability_mode) const override {
return main_factory->QueryCodecSupport(format, scalability_mode);
}
};
std::unique_ptr<webrtc::VideoEncoderFactory> AndroidInterface::makeVideoEncoderFactory(std::shared_ptr<PlatformContext> platformContext, bool preferHardwareEncoding, bool isScreencast) {
JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded();
// AndroidContext *context = (AndroidContext *) platformContext.get();
// jmethodID methodId = env->GetMethodID(context->getJavaCapturerClass(), "getSharedEGLContext", "()Lorg/webrtc/EglBase$Context;");
// jobject eglContext = env->CallObjectMethod(context->getJavaCapturer(), methodId);
webrtc::ScopedJavaLocalRef<jclass> factory_class =
webrtc::GetClass(env, "org/webrtc/DefaultVideoEncoderFactory");
jmethodID factory_constructor = env->GetMethodID(
factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;ZZ)V");
webrtc::ScopedJavaLocalRef<jobject> factory_object(
env, env->NewObject(factory_class.obj(), factory_constructor,
nullptr /* shared_context */,
false /* enable_intel_vp8_encoder */,
true /* enable_h264_high_profile */));
// return webrtc::JavaToNativeVideoEncoderFactory(env, factory_object.obj());
return std::make_unique<SimulcastVideoEncoderFactory>(webrtc::JavaToNativeVideoEncoderFactory(env, factory_object.obj()));
}
std::unique_ptr<webrtc::VideoDecoderFactory> AndroidInterface::makeVideoDecoderFactory(std::shared_ptr<PlatformContext> platformContext) {
JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded();
// AndroidContext *context = (AndroidContext *) platformContext.get();
// jmethodID methodId = env->GetMethodID(context->getJavaCapturerClass(), "getSharedEGLContext", "()Lorg/webrtc/EglBase$Context;");
// jobject eglContext = env->CallObjectMethod(context->getJavaCapturer(), methodId);
webrtc::ScopedJavaLocalRef<jclass> factory_class =
webrtc::GetClass(env, "org/webrtc/DefaultVideoDecoderFactory");
jmethodID factory_constructor = env->GetMethodID(
factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;)V");
webrtc::ScopedJavaLocalRef<jobject> factory_object(
env, env->NewObject(factory_class.obj(), factory_constructor,
nullptr /* shared_context */));
return webrtc::JavaToNativeVideoDecoderFactory(env, factory_object.obj());
}
void AndroidInterface::adaptVideoSource(rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> videoSource, int width, int height, int fps) {
}
rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> AndroidInterface::makeVideoSource(rtc::Thread *signalingThread, rtc::Thread *workerThread, bool screencapture) {
JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded();
_source[screencapture ? 1 : 0] = webrtc::CreateJavaVideoSource(env, signalingThread, false, false);
return webrtc::CreateVideoTrackSourceProxy(signalingThread, workerThread, _source[screencapture ? 1 : 0].get());
}
bool AndroidInterface::supportsEncoding(const std::string &codecName, std::shared_ptr<PlatformContext> platformContext) {
if (hardwareVideoEncoderFactory == nullptr) {
JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded();
// AndroidContext *context = (AndroidContext *) platformContext.get();
// jmethodID methodId = env->GetMethodID(context->getJavaCapturerClass(), "getSharedEGLContext", "()Lorg/webrtc/EglBase$Context;");
// jobject eglContext = env->CallObjectMethod(context->getJavaCapturer(), methodId);
webrtc::ScopedJavaLocalRef<jclass> factory_class =
webrtc::GetClass(env, "org/webrtc/HardwareVideoEncoderFactory");
jmethodID factory_constructor = env->GetMethodID(
factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;ZZ)V");
webrtc::ScopedJavaLocalRef<jobject> factory_object(
env, env->NewObject(factory_class.obj(), factory_constructor,
nullptr,
false,
true));
hardwareVideoEncoderFactory = webrtc::JavaToNativeVideoEncoderFactory(env, factory_object.obj());
}
auto formats = hardwareVideoEncoderFactory->GetSupportedFormats();
for (auto format : formats) {
if (format.name == codecName) {
return true;
}
}
return codecName == cricket::kVp8CodecName;
}
std::unique_ptr<VideoCapturerInterface> AndroidInterface::makeVideoCapturer(
rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source,
std::string deviceId,
std::function<void(VideoState)> stateUpdated,
std::function<void(PlatformCaptureInfo)> captureInfoUpdated,
std::shared_ptr<PlatformContext> platformContext,
std::pair<int, int> &outResolution
) {
return std::make_unique<VideoCapturerInterfaceImpl>(_source[deviceId == "screen" ? 1 : 0], deviceId, stateUpdated, platformContext);
}
std::unique_ptr<rtc::NetworkMonitorFactory> AndroidInterface::createNetworkMonitorFactory() {
return std::make_unique<webrtc::jni::AndroidNetworkMonitorFactory>();
}
std::unique_ptr<PlatformInterface> CreatePlatformInterface() {
return std::make_unique<AndroidInterface>();
}
} // namespace tgcalls

View file

@ -0,0 +1,30 @@
#ifndef TGCALLS_ANDROID_INTERFACE_H
#define TGCALLS_ANDROID_INTERFACE_H
#include "sdk/android/native_api/video/video_source.h"
#include "platform/PlatformInterface.h"
#include "VideoCapturerInterface.h"
namespace tgcalls {
class AndroidInterface : public PlatformInterface {
public:
void configurePlatformAudio(int numChannels = 1) override;
std::unique_ptr<webrtc::VideoEncoderFactory> makeVideoEncoderFactory(std::shared_ptr<PlatformContext> platformContext, bool preferHardwareEncoding = false, bool isScreencast = false) override;
std::unique_ptr<webrtc::VideoDecoderFactory> makeVideoDecoderFactory(std::shared_ptr<PlatformContext> platformContext) override;
bool supportsEncoding(const std::string &codecName, std::shared_ptr<PlatformContext> platformContext) override;
rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> makeVideoSource(rtc::Thread *signalingThread, rtc::Thread *workerThread, bool screencapture) override;
void adaptVideoSource(rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> videoSource, int width, int height, int fps) override;
std::unique_ptr<VideoCapturerInterface> makeVideoCapturer(webrtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source, std::string deviceId, std::function<void(VideoState)> stateUpdated, std::function<void(PlatformCaptureInfo)> captureInfoUpdated, std::shared_ptr<PlatformContext> platformContext, std::pair<int, int> &outResolution) override;
std::unique_ptr<rtc::NetworkMonitorFactory> createNetworkMonitorFactory() override;
private:
rtc::scoped_refptr<webrtc::JavaVideoTrackSourceInterface> _source[2];
std::unique_ptr<webrtc::VideoEncoderFactory> hardwareVideoEncoderFactory;
std::unique_ptr<webrtc::VideoEncoderFactory> softwareVideoEncoderFactory;
};
} // namespace tgcalls
#endif

View file

@ -0,0 +1,62 @@
#include "VideoCameraCapturer.h"
#include <stdint.h>
#include <memory>
#include <algorithm>
#include "AndroidInterface.h"
#include "AndroidContext.h"
#include "sdk/android/native_api/jni/jvm.h"
namespace tgcalls {
VideoCameraCapturer::VideoCameraCapturer(rtc::scoped_refptr<webrtc::JavaVideoTrackSourceInterface> source, std::string deviceId, std::function<void(VideoState)> stateUpdated, std::shared_ptr<PlatformContext> platformContext) : _source(source), _stateUpdated(stateUpdated), _platformContext(platformContext) {
AndroidContext *context = (AndroidContext *) platformContext.get();
JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded();
jmethodID methodId = env->GetMethodID(context->getJavaCapturerClass(), "init", "(JLjava/lang/String;)V");
env->CallVoidMethod(context->getJavaCapturer(), methodId, (jlong) (intptr_t) this, env->NewStringUTF(deviceId.c_str()));
}
void VideoCameraCapturer::setState(VideoState state) {
_state = state;
if (_stateUpdated) {
_stateUpdated(_state);
}
JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded();
auto context = (AndroidContext *) _platformContext.get();
jmethodID methodId = env->GetMethodID(context->getJavaCapturerClass(), "onStateChanged", "(JI)V");
env->CallVoidMethod(context->getJavaCapturer(), methodId, (jlong) (intptr_t) this, (jint) state);
}
void VideoCameraCapturer::setPreferredCaptureAspectRatio(float aspectRatio) {
_aspectRatio = aspectRatio;
JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded();
auto context = (AndroidContext *) _platformContext.get();
jmethodID methodId = env->GetMethodID(context->getJavaCapturerClass(), "onAspectRatioRequested", "(F)V");
env->CallVoidMethod(context->getJavaCapturer(), methodId, (jfloat) aspectRatio);
}
void VideoCameraCapturer::setUncroppedSink(std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) {
if (_uncroppedSink != nullptr) {
_source->RemoveSink(_uncroppedSink.get());
}
if (sink != nullptr) {
_source->AddOrUpdateSink(sink.get(), rtc::VideoSinkWants());
}
_uncroppedSink = sink;
}
webrtc::ScopedJavaLocalRef<jobject> VideoCameraCapturer::GetJavaVideoCapturerObserver(JNIEnv *env) {
return _source->GetJavaVideoCapturerObserver(env);
}
} // namespace tgcalls
extern "C" {
JNIEXPORT jobject Java_org_telegram_messenger_voip_VideoCapturerDevice_nativeGetJavaVideoCapturerObserver(JNIEnv *env, jclass clazz, jlong ptr) {
tgcalls::VideoCameraCapturer *capturer = (tgcalls::VideoCameraCapturer *) (intptr_t) ptr;
return capturer->GetJavaVideoCapturerObserver(env).Release();
}
}

View file

@ -0,0 +1,45 @@
#ifndef TGCALLS_VIDEO_CAMERA_CAPTURER_H
#define TGCALLS_VIDEO_CAMERA_CAPTURER_H
#include "api/scoped_refptr.h"
#include "api/media_stream_interface.h"
#include "modules/video_capture/video_capture.h"
#include "sdk/android/native_api/jni/scoped_java_ref.h"
#include "sdk/android/native_api/video/video_source.h"
#include "VideoCaptureInterface.h"
#include <memory>
#include <vector>
#include <stddef.h>
#include <jni.h>
namespace tgcalls {
class VideoCameraCapturer;
class VideoCameraCapturer {
public:
VideoCameraCapturer(rtc::scoped_refptr<webrtc::JavaVideoTrackSourceInterface> source, std::string deviceId, std::function<void(VideoState)> stateUpdated, std::shared_ptr<PlatformContext> platformContext);
void setState(VideoState state);
void setPreferredCaptureAspectRatio(float aspectRatio);
void setUncroppedSink(std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink);
webrtc::ScopedJavaLocalRef<jobject> GetJavaVideoCapturerObserver(JNIEnv* env);
private:
rtc::scoped_refptr<webrtc::JavaVideoTrackSourceInterface> _source;
std::function<void(VideoState)> _stateUpdated;
VideoState _state;
std::shared_ptr<PlatformContext> _platformContext;
float _aspectRatio;
std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> _uncroppedSink;
};
} // namespace tgcalls
#endif

View file

@ -0,0 +1,31 @@
#include "VideoCapturerInterfaceImpl.h"
#include "VideoCameraCapturer.h"
namespace tgcalls {
VideoCapturerInterfaceImpl::VideoCapturerInterfaceImpl(rtc::scoped_refptr<webrtc::JavaVideoTrackSourceInterface> source, std::string deviceId, std::function<void(VideoState)> stateUpdated, std::shared_ptr<PlatformContext> platformContext) {
_capturer = std::make_unique<VideoCameraCapturer>(source, deviceId, stateUpdated, platformContext);
}
void VideoCapturerInterfaceImpl::setState(VideoState state) {
_capturer->setState(state);
}
void VideoCapturerInterfaceImpl::setPreferredCaptureAspectRatio(float aspectRatio) {
_capturer->setPreferredCaptureAspectRatio(aspectRatio);
}
void VideoCapturerInterfaceImpl::setUncroppedOutput(std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) {
_capturer->setUncroppedSink(sink);
}
int VideoCapturerInterfaceImpl::VideoCapturerInterfaceImpl::getRotation() {
return 0;
}
void VideoCapturerInterfaceImpl::setOnFatalError(std::function<void()> error) {
}
} // namespace tgcalls

View file

@ -0,0 +1,32 @@
#ifndef TGCALLS_VIDEO_CAPTURER_INTERFACE_IMPL_H
#define TGCALLS_VIDEO_CAPTURER_INTERFACE_IMPL_H
#include "VideoCapturerInterface.h"
#include "VideoCameraCapturer.h"
#include "api/media_stream_interface.h"
namespace tgcalls {
class VideoCapturerInterfaceImpl final : public VideoCapturerInterface {
public:
VideoCapturerInterfaceImpl(
rtc::scoped_refptr<webrtc::JavaVideoTrackSourceInterface> source,
std::string deviceId,
std::function<void(VideoState)> stateUpdated,
std::shared_ptr<PlatformContext> platformContext
);
void setState(VideoState state) override;
void setPreferredCaptureAspectRatio(float aspectRatio) override;
void setUncroppedOutput(std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) override;
int getRotation() override;
void setOnFatalError(std::function<void()> error) override;
private:
std::unique_ptr<VideoCameraCapturer> _capturer;
};
} // namespace tgcalls
#endif