Update to 7.0.1 (2065)

This commit is contained in:
DrKLO 2020-08-22 02:59:49 +03:00
parent 4c5f32babf
commit e33a2fbedc
48 changed files with 557 additions and 251 deletions

View file

@ -2,7 +2,7 @@ FROM gradle:6.1.1-jdk8
ENV ANDROID_SDK_URL https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip ENV ANDROID_SDK_URL https://dl.google.com/android/repository/sdk-tools-linux-3859397.zip
ENV ANDROID_API_LEVEL android-30 ENV ANDROID_API_LEVEL android-30
ENV ANDROID_BUILD_TOOLS_VERSION 30.0.1 ENV ANDROID_BUILD_TOOLS_VERSION 30.0.2
ENV ANDROID_HOME /usr/local/android-sdk-linux ENV ANDROID_HOME /usr/local/android-sdk-linux
ENV ANDROID_NDK_VERSION 21.1.6352462 ENV ANDROID_NDK_VERSION 21.1.6352462
ENV ANDROID_VERSION 30 ENV ANDROID_VERSION 30
@ -24,4 +24,4 @@ RUN $ANDROID_HOME/tools/bin/sdkmanager "build-tools;${ANDROID_BUILD_TOOLS_VERSIO
ENV PATH ${ANDROID_NDK_HOME}:$PATH ENV PATH ${ANDROID_NDK_HOME}:$PATH
ENV PATH ${ANDROID_NDK_HOME}/prebuilt/linux-x86_64/bin/:$PATH ENV PATH ${ANDROID_NDK_HOME}/prebuilt/linux-x86_64/bin/:$PATH
CMD mkdir -p /home/source/TMessagesProj/build/outputs/apk && cp -R /home/source/. /home/gradle && cd /home/gradle && gradle assembleRelease && cp -R /home/gradle/TMessagesProj/build/outputs/apk/. /home/source/TMessagesProj/build/outputs/apk CMD mkdir -p /home/source/TMessagesProj/build/outputs/apk && mkdir -p /home/source/TMessagesProj/build/intermediates/ndkBuild && cp -R /home/source/. /home/gradle && cd /home/gradle && gradle assembleRelease && cp -R /home/gradle/TMessagesProj/build/outputs/apk/. /home/source/TMessagesProj/build/outputs/apk && cp -R /home/gradle/TMessagesProj/build/intermediates/ndkBuild/. /home/source/TMessagesProj/build/intermediates/ndkBuild

View file

@ -43,7 +43,7 @@ dependencies {
android { android {
compileSdkVersion 30 compileSdkVersion 30
buildToolsVersion '30.0.1' buildToolsVersion '30.0.2'
ndkVersion "21.1.6352462" ndkVersion "21.1.6352462"
defaultConfig.applicationId = "org.telegram.messenger" defaultConfig.applicationId = "org.telegram.messenger"
@ -280,7 +280,7 @@ android {
} }
} }
defaultConfig.versionCode = 2064 defaultConfig.versionCode = 2065
applicationVariants.all { variant -> applicationVariants.all { variant ->
variant.outputs.all { output -> variant.outputs.all { output ->
@ -315,7 +315,7 @@ android {
defaultConfig { defaultConfig {
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 28 targetSdkVersion 28
versionName "7.0.0" versionName "7.0.1"
vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi'] vectorDrawables.generatedDensities = ['mdpi', 'hdpi', 'xhdpi', 'xxhdpi']

View file

@ -753,6 +753,7 @@ LOCAL_SRC_FILES := \
./tgcalls/ThreadLocalObject.cpp \ ./tgcalls/ThreadLocalObject.cpp \
./tgcalls/VideoCaptureInterface.cpp \ ./tgcalls/VideoCaptureInterface.cpp \
./tgcalls/VideoCaptureInterfaceImpl.cpp \ ./tgcalls/VideoCaptureInterfaceImpl.cpp \
./tgcalls/JsonConfig.cpp \
./tgcalls/reference/InstanceImplReference.cpp \ ./tgcalls/reference/InstanceImplReference.cpp \
./tgcalls/legacy/InstanceImplLegacy.cpp \ ./tgcalls/legacy/InstanceImplLegacy.cpp \
./tgcalls/platform/android/AndroidInterface.cpp \ ./tgcalls/platform/android/AndroidInterface.cpp \

View file

@ -69,14 +69,16 @@ struct InstanceHolder {
std::unique_ptr<Instance> nativeInstance; std::unique_ptr<Instance> nativeInstance;
jobject javaInstance; jobject javaInstance;
std::shared_ptr<tgcalls::VideoCaptureInterface> _videoCapture; std::shared_ptr<tgcalls::VideoCaptureInterface> _videoCapture;
std::shared_ptr<PlatformContext> _platformContext;
}; };
jclass TrafficStatsClass; jclass TrafficStatsClass;
jclass FinalStateClass; jclass FinalStateClass;
jclass NativeInstanceClass;
jmethodID FinalStateInitMethod; jmethodID FinalStateInitMethod;
jlong getInstanceHolderId(JNIEnv *env, jobject obj) { jlong getInstanceHolderId(JNIEnv *env, jobject obj) {
return env->GetLongField(obj, env->GetFieldID(env->GetObjectClass(obj), "nativePtr", "J")); return env->GetLongField(obj, env->GetFieldID(NativeInstanceClass, "nativePtr", "J"));
} }
InstanceHolder *getInstanceHolder(JNIEnv *env, jobject obj) { InstanceHolder *getInstanceHolder(JNIEnv *env, jobject obj) {
@ -231,6 +233,7 @@ void initWebRTC(JNIEnv *env) {
rtc::InitializeSSL(); rtc::InitializeSSL();
webrtcLoaded = true; webrtcLoaded = true;
NativeInstanceClass = static_cast<jclass>(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/NativeInstance")));
TrafficStatsClass = static_cast<jclass>(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/Instance$TrafficStats"))); TrafficStatsClass = static_cast<jclass>(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/Instance$TrafficStats")));
FinalStateClass = static_cast<jclass>(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/Instance$FinalState"))); FinalStateClass = static_cast<jclass>(env->NewGlobalRef(env->FindClass("org/telegram/messenger/voip/Instance$FinalState")));
FinalStateInitMethod = env->GetMethodID(FinalStateClass, "<init>", "([BLjava/lang/String;Lorg/telegram/messenger/voip/Instance$TrafficStats;Z)V"); FinalStateInitMethod = env->GetMethodID(FinalStateClass, "<init>", "([BLjava/lang/String;Lorg/telegram/messenger/voip/Instance$TrafficStats;Z)V");
@ -252,6 +255,8 @@ JNIEXPORT jlong JNICALL Java_org_telegram_messenger_voip_NativeInstance_makeNati
jobject globalRef = env->NewGlobalRef(instanceObj); jobject globalRef = env->NewGlobalRef(instanceObj);
std::shared_ptr<VideoCaptureInterface> videoCapture = videoCapturer ? std::shared_ptr<VideoCaptureInterface>(reinterpret_cast<VideoCaptureInterface *>(videoCapturer)) : nullptr; std::shared_ptr<VideoCaptureInterface> videoCapture = videoCapturer ? std::shared_ptr<VideoCaptureInterface>(reinterpret_cast<VideoCaptureInterface *>(videoCapturer)) : nullptr;
std::shared_ptr<PlatformContext> platformContext = videoCapture ? videoCapture->getPlatformContext() : std::make_shared<AndroidContext>(env);
Descriptor descriptor = { Descriptor descriptor = {
.config = Config{ .config = Config{
.initializationTimeout = configObject.getDoubleField("initializationTimeout"), .initializationTimeout = configObject.getDoubleField("initializationTimeout"),
@ -273,23 +278,25 @@ JNIEXPORT jlong JNICALL Java_org_telegram_messenger_voip_NativeInstance_makeNati
.stateUpdated = [globalRef](State state) { .stateUpdated = [globalRef](State state) {
jint javaState = asJavaState(state); jint javaState = asJavaState(state);
tgvoip::jni::DoWithJNI([globalRef, javaState](JNIEnv *env) { tgvoip::jni::DoWithJNI([globalRef, javaState](JNIEnv *env) {
env->CallVoidMethod(globalRef, env->GetMethodID(env->GetObjectClass(globalRef), "onStateUpdated", "(I)V"), javaState); env->CallVoidMethod(globalRef, env->GetMethodID(NativeInstanceClass, "onStateUpdated", "(I)V"), javaState);
}); });
}, },
.platformContext = platformContext,
.signalBarsUpdated = [globalRef](int count) { .signalBarsUpdated = [globalRef](int count) {
tgvoip::jni::DoWithJNI([globalRef, count](JNIEnv *env) { tgvoip::jni::DoWithJNI([globalRef, count](JNIEnv *env) {
env->CallVoidMethod(globalRef, env->GetMethodID(env->GetObjectClass(globalRef), "onSignalBarsUpdated", "(I)V"), count); env->CallVoidMethod(globalRef, env->GetMethodID(NativeInstanceClass, "onSignalBarsUpdated", "(I)V"), count);
}); });
}, },
.remoteMediaStateUpdated = [globalRef](AudioState audioState, VideoState videoState) { .remoteMediaStateUpdated = [globalRef](AudioState audioState, VideoState videoState) {
tgvoip::jni::DoWithJNI([globalRef, audioState, videoState](JNIEnv *env) { tgvoip::jni::DoWithJNI([globalRef, audioState, videoState](JNIEnv *env) {
env->CallVoidMethod(globalRef, env->GetMethodID(env->GetObjectClass(globalRef), "onRemoteMediaStateUpdated", "(II)V"), audioState, videoState); env->CallVoidMethod(globalRef, env->GetMethodID(NativeInstanceClass, "onRemoteMediaStateUpdated", "(II)V"), (jint) audioState, (jint )videoState);
}); });
}, },
.signalingDataEmitted = [globalRef](const std::vector<uint8_t> &data) { .signalingDataEmitted = [globalRef](const std::vector<uint8_t> &data) {
tgvoip::jni::DoWithJNI([globalRef, data](JNIEnv *env) { tgvoip::jni::DoWithJNI([globalRef, data](JNIEnv *env) {
jbyteArray arr = copyVectorToJavaByteArray(env, data); jbyteArray arr = copyVectorToJavaByteArray(env, data);
env->CallVoidMethod(globalRef, env->GetMethodID(env->GetObjectClass(globalRef), "onSignalingData", "([B)V"), arr); env->CallVoidMethod(globalRef, env->GetMethodID(NativeInstanceClass, "onSignalingData", "([B)V"), arr);
env->DeleteLocalRef(arr);
}); });
}, },
}; };
@ -336,6 +343,7 @@ JNIEXPORT jlong JNICALL Java_org_telegram_messenger_voip_NativeInstance_makeNati
holder->nativeInstance = tgcalls::Meta::Create(v, std::move(descriptor)); holder->nativeInstance = tgcalls::Meta::Create(v, std::move(descriptor));
holder->javaInstance = globalRef; holder->javaInstance = globalRef;
holder->_videoCapture = videoCapture; holder->_videoCapture = videoCapture;
holder->_platformContext = platformContext;
holder->nativeInstance->setIncomingVideoOutput(webrtc::JavaToNativeVideoSink(env, remoteSink)); holder->nativeInstance->setIncomingVideoOutput(webrtc::JavaToNativeVideoSink(env, remoteSink));
holder->nativeInstance->setNetworkType(parseNetworkType(networkType)); holder->nativeInstance->setNetworkType(parseNetworkType(networkType));
return reinterpret_cast<jlong>(holder); return reinterpret_cast<jlong>(holder);
@ -396,7 +404,7 @@ JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_stopNativ
JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded(); JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded();
const std::string &path = tgvoip::jni::JavaStringToStdString(env, JavaObject(env, instance->javaInstance).getStringField("persistentStateFilePath")); const std::string &path = tgvoip::jni::JavaStringToStdString(env, JavaObject(env, instance->javaInstance).getStringField("persistentStateFilePath"));
savePersistentState(path.c_str(), finalState.persistentState); savePersistentState(path.c_str(), finalState.persistentState);
env->CallVoidMethod(instance->javaInstance, env->GetMethodID(env->GetObjectClass(instance->javaInstance), "onStop", "(Lorg/telegram/messenger/voip/Instance$FinalState;)V"), asJavaFinalState(env, finalState)); env->CallVoidMethod(instance->javaInstance, env->GetMethodID(NativeInstanceClass, "onStop", "(Lorg/telegram/messenger/voip/Instance$FinalState;)V"), asJavaFinalState(env, finalState));
env->DeleteGlobalRef(instance->javaInstance); env->DeleteGlobalRef(instance->javaInstance);
delete instance; delete instance;
}); });
@ -446,7 +454,7 @@ JNIEXPORT void JNICALL Java_org_telegram_messenger_voip_NativeInstance_setupOutg
if (instance->_videoCapture) { if (instance->_videoCapture) {
return; return;
} }
instance->_videoCapture = tgcalls::VideoCaptureInterface::Create(std::make_shared<AndroidContext>(env)); instance->_videoCapture = tgcalls::VideoCaptureInterface::Create(instance->_platformContext);
instance->_videoCapture->setOutput(webrtc::JavaToNativeVideoSink(env, localSink)); instance->_videoCapture->setOutput(webrtc::JavaToNativeVideoSink(env, localSink));
instance->_videoCapture->setState(VideoState::Active); instance->_videoCapture->setState(VideoState::Active);
instance->nativeInstance->setVideoCapture(instance->_videoCapture); instance->nativeInstance->setVideoCapture(instance->_videoCapture);

View file

@ -773,9 +773,11 @@ std::shared_ptr<LOTAsset> LottieParserImpl::parseAsset() {
return sharedAsset; return sharedAsset;
} }
std::shared_ptr<LOTData> layer = parseLayer(); std::shared_ptr<LOTData> layer = parseLayer();
if (layer) {
staticFlag = staticFlag && layer->isStatic(); staticFlag = staticFlag && layer->isStatic();
asset->mLayers.push_back(layer); asset->mLayers.push_back(layer);
} }
}
if (!IsValid()) { if (!IsValid()) {
parsingError = true; parsingError = true;
return sharedAsset; return sharedAsset;

View file

@ -23,7 +23,7 @@ bool CompareFormats(const VideoFormat &a, const VideoFormat &b) {
} }
} }
int FormatPriority(const VideoFormat &format, const std::vector<std::string> &preferredCodecs) { int FormatPriority(const VideoFormat &format, const std::vector<std::string> &preferredCodecs, std::shared_ptr<PlatformContext> platformContext) {
static const auto kCodecs = { static const auto kCodecs = {
std::string(cricket::kAv1CodecName), std::string(cricket::kAv1CodecName),
std::string(cricket::kVp9CodecName), std::string(cricket::kVp9CodecName),
@ -31,13 +31,13 @@ int FormatPriority(const VideoFormat &format, const std::vector<std::string> &pr
std::string(cricket::kH264CodecName), std::string(cricket::kH264CodecName),
std::string(cricket::kVp8CodecName), std::string(cricket::kVp8CodecName),
}; };
static const auto kSupported = [] { static const auto kSupported = [platformContext] {
const auto platform = PlatformInterface::SharedInstance(); const auto platform = PlatformInterface::SharedInstance();
auto result = std::vector<std::string>(); auto result = std::vector<std::string>();
result.reserve(kCodecs.size()); result.reserve(kCodecs.size());
for (const auto &codec : kCodecs) { for (const auto &codec : kCodecs) {
if (platform->supportsEncoding(codec)) { if (platform->supportsEncoding(codec, platformContext)) {
result.push_back(codec); result.push_back(codec);
} }
} }
@ -62,19 +62,19 @@ int FormatPriority(const VideoFormat &format, const std::vector<std::string> &pr
return -1; return -1;
} }
bool ComparePriorities(const VideoFormat &a, const VideoFormat &b, const std::vector<std::string> &preferredCodecs) { bool ComparePriorities(const VideoFormat &a, const VideoFormat &b, const std::vector<std::string> &preferredCodecs, std::shared_ptr<PlatformContext> platformContext) {
return FormatPriority(a, preferredCodecs) < FormatPriority(b, preferredCodecs); return FormatPriority(a, preferredCodecs, platformContext) < FormatPriority(b, preferredCodecs, platformContext);
} }
std::vector<VideoFormat> FilterAndSortEncoders(std::vector<VideoFormat> list, const std::vector<std::string> &preferredCodecs) { std::vector<VideoFormat> FilterAndSortEncoders(std::vector<VideoFormat> list, const std::vector<std::string> &preferredCodecs, std::shared_ptr<PlatformContext> platformContext) {
const auto listBegin = begin(list); const auto listBegin = begin(list);
const auto listEnd = end(list); const auto listEnd = end(list);
std::sort(listBegin, listEnd, [&preferredCodecs](const VideoFormat &lhs, const VideoFormat &rhs) { std::sort(listBegin, listEnd, [&preferredCodecs, platformContext](const VideoFormat &lhs, const VideoFormat &rhs) {
return ComparePriorities(lhs, rhs, preferredCodecs); return ComparePriorities(lhs, rhs, preferredCodecs, platformContext);
}); });
auto eraseFrom = listBegin; auto eraseFrom = listBegin;
auto eraseTill = eraseFrom; auto eraseTill = eraseFrom;
while (eraseTill != listEnd && FormatPriority(*eraseTill, preferredCodecs) == -1) { while (eraseTill != listEnd && FormatPriority(*eraseTill, preferredCodecs, platformContext) == -1) {
++eraseTill; ++eraseTill;
} }
if (eraseTill != eraseFrom) { if (eraseTill != eraseFrom) {
@ -142,8 +142,9 @@ void AddDefaultFeedbackParams(cricket::VideoCodec *codec) {
VideoFormatsMessage ComposeSupportedFormats( VideoFormatsMessage ComposeSupportedFormats(
std::vector<VideoFormat> encoders, std::vector<VideoFormat> encoders,
std::vector<VideoFormat> decoders, std::vector<VideoFormat> decoders,
const std::vector<std::string> &preferredCodecs) { const std::vector<std::string> &preferredCodecs,
encoders = FilterAndSortEncoders(std::move(encoders), preferredCodecs); std::shared_ptr<PlatformContext> platformContext) {
encoders = FilterAndSortEncoders(std::move(encoders), preferredCodecs, platformContext);
auto result = VideoFormatsMessage(); auto result = VideoFormatsMessage();
result.encodersCount = (int)encoders.size(); result.encodersCount = (int)encoders.size();

View file

@ -6,6 +6,8 @@
namespace tgcalls { namespace tgcalls {
class PlatformContext;
struct CommonFormats { struct CommonFormats {
std::vector<webrtc::SdpVideoFormat> list; std::vector<webrtc::SdpVideoFormat> list;
int myEncoderIndex = -1; int myEncoderIndex = -1;
@ -19,7 +21,8 @@ struct CommonCodecs {
VideoFormatsMessage ComposeSupportedFormats( VideoFormatsMessage ComposeSupportedFormats(
std::vector<webrtc::SdpVideoFormat> encoders, std::vector<webrtc::SdpVideoFormat> encoders,
std::vector<webrtc::SdpVideoFormat> decoders, std::vector<webrtc::SdpVideoFormat> decoders,
const std::vector<std::string> &preferredCodecs); const std::vector<std::string> &preferredCodecs,
std::shared_ptr<PlatformContext> platformContext);
CommonFormats ComputeCommonFormats( CommonFormats ComputeCommonFormats(
const VideoFormatsMessage &my, const VideoFormatsMessage &my,

View file

@ -19,6 +19,7 @@ class VideoFrame;
namespace tgcalls { namespace tgcalls {
class VideoCaptureInterface; class VideoCaptureInterface;
class PlatformContext;
struct Proxy { struct Proxy {
std::string host; std::string host;
@ -203,6 +204,7 @@ struct Descriptor {
std::function<void(AudioState, VideoState)> remoteMediaStateUpdated; std::function<void(AudioState, VideoState)> remoteMediaStateUpdated;
std::function<void(float)> remotePrefferedAspectRatioUpdated; std::function<void(float)> remotePrefferedAspectRatioUpdated;
std::function<void(const std::vector<uint8_t> &)> signalingDataEmitted; std::function<void(const std::vector<uint8_t> &)> signalingDataEmitted;
std::shared_ptr<PlatformContext> platformContext;
}; };
class Meta { class Meta {

View file

@ -0,0 +1,13 @@
#include "JsonConfig.h"
namespace tgcalls {
JsonConfig::JsonConfig(Values values) : _values(values) {
}
Value JsonConfig::getValue(std::string key) {
return _values[key];
}
} // namespace tgcalls

View file

@ -0,0 +1,25 @@
#ifndef TGCALLS_JSON_CONFIG_H
#define TGCALLS_JSON_CONFIG_H
#include <string>
#include <map>
#include "absl/types/variant.h"
namespace tgcalls {
typedef absl::variant<int, double, bool, std::string> Value;
typedef std::map<std::string, Value> Values;
class JsonConfig {
public:
JsonConfig(Values values);
Value getValue(std::string key);
private:
Values _values;
};
} // namespace tgcalls
#endif

View file

@ -49,7 +49,8 @@ _remotePrefferedAspectRatioUpdated(std::move(descriptor.remotePrefferedAspectRat
_signalingDataEmitted(std::move(descriptor.signalingDataEmitted)), _signalingDataEmitted(std::move(descriptor.signalingDataEmitted)),
_signalBarsUpdated(std::move(descriptor.signalBarsUpdated)), _signalBarsUpdated(std::move(descriptor.signalBarsUpdated)),
_localPreferredVideoAspectRatio(descriptor.config.preferredAspectRatio), _localPreferredVideoAspectRatio(descriptor.config.preferredAspectRatio),
_enableHighBitrateVideo(descriptor.config.enableHighBitrateVideo) { _enableHighBitrateVideo(descriptor.config.enableHighBitrateVideo),
_platformContext(descriptor.platformContext) {
assert(_thread->IsCurrent()); assert(_thread->IsCurrent());
assert(_stateUpdated != nullptr); assert(_stateUpdated != nullptr);
assert(_signalingDataEmitted != nullptr); assert(_signalingDataEmitted != nullptr);
@ -166,7 +167,7 @@ void Manager::start() {
}); });
})); }));
bool isOutgoing = _encryptionKey.isOutgoing; bool isOutgoing = _encryptionKey.isOutgoing;
_mediaManager.reset(new ThreadLocalObject<MediaManager>(getMediaThread(), [weak, isOutgoing, thread, sendSignalingMessage, videoCapture = _videoCapture, localPreferredVideoAspectRatio = _localPreferredVideoAspectRatio, enableHighBitrateVideo = _enableHighBitrateVideo, signalBarsUpdated = _signalBarsUpdated, preferredCodecs = _preferredCodecs]() { _mediaManager.reset(new ThreadLocalObject<MediaManager>(getMediaThread(), [weak, isOutgoing, thread, sendSignalingMessage, videoCapture = _videoCapture, localPreferredVideoAspectRatio = _localPreferredVideoAspectRatio, enableHighBitrateVideo = _enableHighBitrateVideo, signalBarsUpdated = _signalBarsUpdated, preferredCodecs = _preferredCodecs, platformContext = _platformContext]() {
return new MediaManager( return new MediaManager(
getMediaThread(), getMediaThread(),
isOutgoing, isOutgoing,
@ -184,7 +185,8 @@ void Manager::start() {
signalBarsUpdated, signalBarsUpdated,
localPreferredVideoAspectRatio, localPreferredVideoAspectRatio,
enableHighBitrateVideo, enableHighBitrateVideo,
preferredCodecs); preferredCodecs,
platformContext);
})); }));
_networkManager->perform(RTC_FROM_HERE, [](NetworkManager *networkManager) { _networkManager->perform(RTC_FROM_HERE, [](NetworkManager *networkManager) {
networkManager->start(); networkManager->start();

View file

@ -57,6 +57,8 @@ private:
bool _localNetworkIsLowCost = false; bool _localNetworkIsLowCost = false;
bool _remoteNetworkIsLowCost = false; bool _remoteNetworkIsLowCost = false;
std::shared_ptr<PlatformContext> _platformContext;
}; };
} // namespace tgcalls } // namespace tgcalls

View file

@ -59,7 +59,8 @@ MediaManager::MediaManager(
std::function<void(int)> signalBarsUpdated, std::function<void(int)> signalBarsUpdated,
float localPreferredVideoAspectRatio, float localPreferredVideoAspectRatio,
bool enableHighBitrateVideo, bool enableHighBitrateVideo,
std::vector<std::string> preferredCodecs) : std::vector<std::string> preferredCodecs,
std::shared_ptr<PlatformContext> platformContext) :
_thread(thread), _thread(thread),
_eventLog(std::make_unique<webrtc::RtcEventLogNull>()), _eventLog(std::make_unique<webrtc::RtcEventLogNull>()),
_taskQueueFactory(webrtc::CreateDefaultTaskQueueFactory()), _taskQueueFactory(webrtc::CreateDefaultTaskQueueFactory()),
@ -69,7 +70,8 @@ _signalBarsUpdated(std::move(signalBarsUpdated)),
_outgoingVideoState(videoCapture ? VideoState::Active : VideoState::Inactive), _outgoingVideoState(videoCapture ? VideoState::Active : VideoState::Inactive),
_videoCapture(std::move(videoCapture)), _videoCapture(std::move(videoCapture)),
_localPreferredVideoAspectRatio(localPreferredVideoAspectRatio), _localPreferredVideoAspectRatio(localPreferredVideoAspectRatio),
_enableHighBitrateVideo(enableHighBitrateVideo) { _enableHighBitrateVideo(enableHighBitrateVideo),
_platformContext(platformContext) {
_ssrcAudio.incoming = isOutgoing ? ssrcAudioIncoming : ssrcAudioOutgoing; _ssrcAudio.incoming = isOutgoing ? ssrcAudioIncoming : ssrcAudioOutgoing;
_ssrcAudio.outgoing = (!isOutgoing) ? ssrcAudioIncoming : ssrcAudioOutgoing; _ssrcAudio.outgoing = (!isOutgoing) ? ssrcAudioIncoming : ssrcAudioOutgoing;
_ssrcAudio.fecIncoming = isOutgoing ? ssrcAudioFecIncoming : ssrcAudioFecOutgoing; _ssrcAudio.fecIncoming = isOutgoing ? ssrcAudioFecIncoming : ssrcAudioFecOutgoing;
@ -99,13 +101,14 @@ _enableHighBitrateVideo(enableHighBitrateVideo) {
mediaDeps.audio_encoder_factory = webrtc::CreateAudioEncoderFactory<webrtc::AudioEncoderOpus>(); mediaDeps.audio_encoder_factory = webrtc::CreateAudioEncoderFactory<webrtc::AudioEncoderOpus>();
mediaDeps.audio_decoder_factory = webrtc::CreateAudioDecoderFactory<webrtc::AudioDecoderOpus>(); mediaDeps.audio_decoder_factory = webrtc::CreateAudioDecoderFactory<webrtc::AudioDecoderOpus>();
mediaDeps.video_encoder_factory = PlatformInterface::SharedInstance()->makeVideoEncoderFactory(); mediaDeps.video_encoder_factory = PlatformInterface::SharedInstance()->makeVideoEncoderFactory(_platformContext);
mediaDeps.video_decoder_factory = PlatformInterface::SharedInstance()->makeVideoDecoderFactory(); mediaDeps.video_decoder_factory = PlatformInterface::SharedInstance()->makeVideoDecoderFactory(_platformContext);
_myVideoFormats = ComposeSupportedFormats( _myVideoFormats = ComposeSupportedFormats(
mediaDeps.video_encoder_factory->GetSupportedFormats(), mediaDeps.video_encoder_factory->GetSupportedFormats(),
mediaDeps.video_decoder_factory->GetSupportedFormats(), mediaDeps.video_decoder_factory->GetSupportedFormats(),
preferredCodecs); preferredCodecs,
_platformContext);
mediaDeps.audio_processing = webrtc::AudioProcessingBuilder().Create(); mediaDeps.audio_processing = webrtc::AudioProcessingBuilder().Create();
_mediaEngine = cricket::CreateMediaEngine(std::move(mediaDeps)); _mediaEngine = cricket::CreateMediaEngine(std::move(mediaDeps));
@ -121,6 +124,9 @@ _enableHighBitrateVideo(enableHighBitrateVideo) {
audioOptions.noise_suppression = true; audioOptions.noise_suppression = true;
audioOptions.audio_jitter_buffer_fast_accelerate = true; audioOptions.audio_jitter_buffer_fast_accelerate = true;
std::vector<std::string> streamIds;
streamIds.push_back("1");
_audioChannel.reset(_mediaEngine->voice().CreateMediaChannel(_call.get(), cricket::MediaConfig(), audioOptions, webrtc::CryptoOptions::NoGcm())); _audioChannel.reset(_mediaEngine->voice().CreateMediaChannel(_call.get(), cricket::MediaConfig(), audioOptions, webrtc::CryptoOptions::NoGcm()));
_videoChannel.reset(_mediaEngine->video().CreateMediaChannel(_call.get(), cricket::MediaConfig(), cricket::VideoOptions(), webrtc::CryptoOptions::NoGcm(), _videoBitrateAllocatorFactory.get())); _videoChannel.reset(_mediaEngine->video().CreateMediaChannel(_call.get(), cricket::MediaConfig(), cricket::VideoOptions(), webrtc::CryptoOptions::NoGcm(), _videoBitrateAllocatorFactory.get()));
@ -166,7 +172,9 @@ _enableHighBitrateVideo(enableHighBitrateVideo) {
audioRecvParameters.rtcp.remote_estimate = true; audioRecvParameters.rtcp.remote_estimate = true;
_audioChannel->SetRecvParameters(audioRecvParameters); _audioChannel->SetRecvParameters(audioRecvParameters);
_audioChannel->AddRecvStream(cricket::StreamParams::CreateLegacy(_ssrcAudio.incoming)); cricket::StreamParams audioRecvStreamParams = cricket::StreamParams::CreateLegacy(_ssrcAudio.incoming);
audioRecvStreamParams.set_stream_ids(streamIds);
_audioChannel->AddRecvStream(audioRecvStreamParams);
_audioChannel->SetPlayout(true); _audioChannel->SetPlayout(true);
_videoChannel->SetInterface(_videoNetworkInterface.get()); _videoChannel->SetInterface(_videoNetworkInterface.get());
@ -506,6 +514,9 @@ void MediaManager::checkIsReceivingVideoChanged(bool wasReceiving) {
videoRecvStreamParams.ssrcs = {_ssrcVideo.incoming}; videoRecvStreamParams.ssrcs = {_ssrcVideo.incoming};
videoRecvStreamParams.ssrc_groups.push_back(videoRecvSsrcGroup); videoRecvStreamParams.ssrc_groups.push_back(videoRecvSsrcGroup);
videoRecvStreamParams.cname = "cname"; videoRecvStreamParams.cname = "cname";
std::vector<std::string> streamIds;
streamIds.push_back("1");
videoRecvStreamParams.set_stream_ids(streamIds);
_videoChannel->SetRecvParameters(videoRecvParameters); _videoChannel->SetRecvParameters(videoRecvParameters);
_videoChannel->AddRecvStream(videoRecvStreamParams); _videoChannel->AddRecvStream(videoRecvStreamParams);

View file

@ -43,7 +43,8 @@ public:
std::function<void(int)> signalBarsUpdated, std::function<void(int)> signalBarsUpdated,
float localPreferredVideoAspectRatio, float localPreferredVideoAspectRatio,
bool enableHighBitrateVideo, bool enableHighBitrateVideo,
std::vector<std::string> preferredCodecs); std::vector<std::string> preferredCodecs,
std::shared_ptr<PlatformContext> platformContext);
~MediaManager(); ~MediaManager();
void start(); void start();
@ -140,6 +141,8 @@ private:
std::unique_ptr<MediaManager::NetworkInterfaceImpl> _audioNetworkInterface; std::unique_ptr<MediaManager::NetworkInterfaceImpl> _audioNetworkInterface;
std::unique_ptr<MediaManager::NetworkInterfaceImpl> _videoNetworkInterface; std::unique_ptr<MediaManager::NetworkInterfaceImpl> _videoNetworkInterface;
std::shared_ptr<PlatformContext> _platformContext;
}; };
} // namespace tgcalls } // namespace tgcalls

View file

@ -17,7 +17,7 @@ namespace rtc {
class BasicPacketSocketFactory; class BasicPacketSocketFactory;
class BasicNetworkManager; class BasicNetworkManager;
class PacketTransportInternal; class PacketTransportInternal;
class NetworkRoute; struct NetworkRoute;
} // namespace rtc } // namespace rtc
namespace cricket { namespace cricket {

View file

@ -35,6 +35,9 @@ public:
virtual void setState(VideoState state) = 0; virtual void setState(VideoState state) = 0;
virtual void setPreferredAspectRatio(float aspectRatio) = 0; virtual void setPreferredAspectRatio(float aspectRatio) = 0;
virtual void setOutput(std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) = 0; virtual void setOutput(std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) = 0;
virtual std::shared_ptr<PlatformContext> getPlatformContext() {
return nullptr;
}
}; };

View file

@ -16,7 +16,7 @@ VideoCaptureInterfaceObject::VideoCaptureInterfaceObject(std::shared_ptr<Platfor
if (this->_stateUpdated) { if (this->_stateUpdated) {
this->_stateUpdated(state); this->_stateUpdated(state);
} }
}, platformContext, _videoCapturerResolution); }, _platformContext, _videoCapturerResolution);
} }
} }
@ -86,7 +86,8 @@ void VideoCaptureInterfaceObject::setStateUpdated(std::function<void(VideoState)
} }
VideoCaptureInterfaceImpl::VideoCaptureInterfaceImpl(std::shared_ptr<PlatformContext> platformContext) : VideoCaptureInterfaceImpl::VideoCaptureInterfaceImpl(std::shared_ptr<PlatformContext> platformContext) :
_impl(Manager::getMediaThread(), [platformContext]() { _platformContext(platformContext),
_impl(Manager::getMediaThread(), [platformContext]() {
return new VideoCaptureInterfaceObject(platformContext); return new VideoCaptureInterfaceObject(platformContext);
}) { }) {
} }
@ -117,8 +118,12 @@ void VideoCaptureInterfaceImpl::setOutput(std::shared_ptr<rtc::VideoSinkInterfac
}); });
} }
std::shared_ptr<PlatformContext> VideoCaptureInterfaceImpl::getPlatformContext() {
return _platformContext;
}
ThreadLocalObject<VideoCaptureInterfaceObject> *VideoCaptureInterfaceImpl::object() { ThreadLocalObject<VideoCaptureInterfaceObject> *VideoCaptureInterfaceImpl::object() {
return &_impl; return &_impl;
} }
} // namespace tgcalls }// namespace tgcalls

View file

@ -44,11 +44,13 @@ public:
void setState(VideoState state) override; void setState(VideoState state) override;
void setPreferredAspectRatio(float aspectRatio) override; void setPreferredAspectRatio(float aspectRatio) override;
void setOutput(std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) override; void setOutput(std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink) override;
std::shared_ptr<PlatformContext> getPlatformContext() override;
ThreadLocalObject<VideoCaptureInterfaceObject> *object(); ThreadLocalObject<VideoCaptureInterfaceObject> *object();
private: private:
ThreadLocalObject<VideoCaptureInterfaceObject> _impl; ThreadLocalObject<VideoCaptureInterfaceObject> _impl;
std::shared_ptr<PlatformContext> _platformContext;
}; };

View file

@ -23,9 +23,9 @@ public:
virtual float getDisplayAspectRatio() { virtual float getDisplayAspectRatio() {
return 0.0f; return 0.0f;
} }
virtual std::unique_ptr<webrtc::VideoEncoderFactory> makeVideoEncoderFactory() = 0; virtual std::unique_ptr<webrtc::VideoEncoderFactory> makeVideoEncoderFactory(std::shared_ptr<PlatformContext> platformContext) = 0;
virtual std::unique_ptr<webrtc::VideoDecoderFactory> makeVideoDecoderFactory() = 0; virtual std::unique_ptr<webrtc::VideoDecoderFactory> makeVideoDecoderFactory(std::shared_ptr<PlatformContext> platformContext) = 0;
virtual bool supportsEncoding(const std::string &codecName) = 0; virtual bool supportsEncoding(const std::string &codecName, std::shared_ptr<PlatformContext> platformContext) = 0;
virtual rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> makeVideoSource(rtc::Thread *signalingThread, rtc::Thread *workerThread) = 0; virtual rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> makeVideoSource(rtc::Thread *signalingThread, rtc::Thread *workerThread) = 0;
virtual void adaptVideoSource(rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> videoSource, int width, int height, int fps) = 0; virtual void adaptVideoSource(rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> videoSource, int width, int height, int fps) = 0;
virtual std::unique_ptr<VideoCapturerInterface> makeVideoCapturer(rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source, bool useFrontCamera, std::function<void(VideoState)> stateUpdated, std::shared_ptr<PlatformContext> platformContext, std::pair<int, int> &outResolution) = 0; virtual std::unique_ptr<VideoCapturerInterface> makeVideoCapturer(rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source, bool useFrontCamera, std::function<void(VideoState)> stateUpdated, std::shared_ptr<PlatformContext> platformContext, std::pair<int, int> &outResolution) = 0;

View file

@ -16,6 +16,7 @@
#include "api/video_codecs/builtin_video_encoder_factory.h" #include "api/video_codecs/builtin_video_encoder_factory.h"
#include "api/video_codecs/builtin_video_decoder_factory.h" #include "api/video_codecs/builtin_video_decoder_factory.h"
#include "api/video_track_source_proxy.h" #include "api/video_track_source_proxy.h"
#include "AndroidContext.h"
namespace tgcalls { namespace tgcalls {
@ -28,29 +29,29 @@ float AndroidInterface::getDisplayAspectRatio() {
return 0; return 0;
} }
std::unique_ptr<webrtc::VideoEncoderFactory> AndroidInterface::makeVideoEncoderFactory() { std::unique_ptr<webrtc::VideoEncoderFactory> AndroidInterface::makeVideoEncoderFactory(std::shared_ptr<PlatformContext> platformContext) {
JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded(); JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded();
webrtc::ScopedJavaLocalRef<jclass> factory_class =
webrtc::GetClass(env, "org/webrtc/DefaultVideoEncoderFactory"); AndroidContext *context = (AndroidContext *) platformContext.get();
jmethodID factory_constructor = env->GetMethodID( jmethodID methodId = env->GetMethodID(context->getJavaCapturerClass(), "getSharedEGLContext", "()Lorg/webrtc/EglBase$Context;");
factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;ZZ)V"); jobject eglContext = env->CallObjectMethod(context->getJavaCapturer(), methodId);
webrtc::ScopedJavaLocalRef<jobject> factory_object(
env, env->NewObject(factory_class.obj(), factory_constructor, webrtc::ScopedJavaLocalRef<jclass> factory_class = webrtc::GetClass(env, "org/webrtc/DefaultVideoEncoderFactory");
nullptr /* shared_context */, jmethodID factory_constructor = env->GetMethodID(factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;ZZ)V");
false /* enable_intel_vp8_encoder */, webrtc::ScopedJavaLocalRef<jobject> factory_object(env, env->NewObject(factory_class.obj(), factory_constructor, eglContext, false, true));
true /* enable_h264_high_profile */));
return webrtc::JavaToNativeVideoEncoderFactory(env, factory_object.obj()); return webrtc::JavaToNativeVideoEncoderFactory(env, factory_object.obj());
} }
std::unique_ptr<webrtc::VideoDecoderFactory> AndroidInterface::makeVideoDecoderFactory() { std::unique_ptr<webrtc::VideoDecoderFactory> AndroidInterface::makeVideoDecoderFactory(std::shared_ptr<PlatformContext> platformContext) {
JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded(); JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded();
webrtc::ScopedJavaLocalRef<jclass> factory_class =
webrtc::GetClass(env, "org/webrtc/DefaultVideoDecoderFactory"); AndroidContext *context = (AndroidContext *) platformContext.get();
jmethodID factory_constructor = env->GetMethodID( jmethodID methodId = env->GetMethodID(context->getJavaCapturerClass(), "getSharedEGLContext", "()Lorg/webrtc/EglBase$Context;");
factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;)V"); jobject eglContext = env->CallObjectMethod(context->getJavaCapturer(), methodId);
webrtc::ScopedJavaLocalRef<jobject> factory_object(
env, env->NewObject(factory_class.obj(), factory_constructor, webrtc::ScopedJavaLocalRef<jclass> factory_class = webrtc::GetClass(env, "org/webrtc/DefaultVideoDecoderFactory");
nullptr /* shared_context */)); 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, eglContext));
return webrtc::JavaToNativeVideoDecoderFactory(env, factory_object.obj()); return webrtc::JavaToNativeVideoDecoderFactory(env, factory_object.obj());
} }
@ -64,18 +65,17 @@ rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> AndroidInterface::makeVide
return webrtc::VideoTrackSourceProxy::Create(signalingThread, workerThread, _source); return webrtc::VideoTrackSourceProxy::Create(signalingThread, workerThread, _source);
} }
bool AndroidInterface::supportsEncoding(const std::string &codecName) { bool AndroidInterface::supportsEncoding(const std::string &codecName, std::shared_ptr<PlatformContext> platformContext) {
if (hardwareVideoEncoderFactory == nullptr) { if (hardwareVideoEncoderFactory == nullptr) {
JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded(); JNIEnv *env = webrtc::AttachCurrentThreadIfNeeded();
webrtc::ScopedJavaLocalRef<jclass> factory_class =
webrtc::GetClass(env, "org/webrtc/HardwareVideoEncoderFactory"); AndroidContext *context = (AndroidContext *) platformContext.get();
jmethodID factory_constructor = env->GetMethodID( jmethodID methodId = env->GetMethodID(context->getJavaCapturerClass(), "getSharedEGLContext", "()Lorg/webrtc/EglBase$Context;");
factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;ZZ)V"); jobject eglContext = env->CallObjectMethod(context->getJavaCapturer(), methodId);
webrtc::ScopedJavaLocalRef<jobject> factory_object(
env, env->NewObject(factory_class.obj(), factory_constructor, webrtc::ScopedJavaLocalRef<jclass> factory_class = webrtc::GetClass(env, "org/webrtc/HardwareVideoEncoderFactory");
nullptr, jmethodID factory_constructor = env->GetMethodID(factory_class.obj(), "<init>", "(Lorg/webrtc/EglBase$Context;ZZ)V");
false, webrtc::ScopedJavaLocalRef<jobject> factory_object(env, env->NewObject(factory_class.obj(), factory_constructor, eglContext, false, true));
true));
hardwareVideoEncoderFactory = webrtc::JavaToNativeVideoEncoderFactory(env, factory_object.obj()); hardwareVideoEncoderFactory = webrtc::JavaToNativeVideoEncoderFactory(env, factory_object.obj());
} }
auto formats = hardwareVideoEncoderFactory->GetSupportedFormats(); auto formats = hardwareVideoEncoderFactory->GetSupportedFormats();

View file

@ -11,9 +11,9 @@ class AndroidInterface : public PlatformInterface {
public: public:
void configurePlatformAudio() override; void configurePlatformAudio() override;
float getDisplayAspectRatio() override; float getDisplayAspectRatio() override;
std::unique_ptr<webrtc::VideoEncoderFactory> makeVideoEncoderFactory() override; std::unique_ptr<webrtc::VideoEncoderFactory> makeVideoEncoderFactory(std::shared_ptr<PlatformContext> platformContext) override;
std::unique_ptr<webrtc::VideoDecoderFactory> makeVideoDecoderFactory() override; std::unique_ptr<webrtc::VideoDecoderFactory> makeVideoDecoderFactory(std::shared_ptr<PlatformContext> platformContext) override;
bool supportsEncoding(const std::string &codecName) 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) override; rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> makeVideoSource(rtc::Thread *signalingThread, rtc::Thread *workerThread) override;
void adaptVideoSource(rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> videoSource, int width, int height, int fps) override; void adaptVideoSource(rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> videoSource, int width, int height, int fps) override;
std::unique_ptr<VideoCapturerInterface> makeVideoCapturer(rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source, bool useFrontCamera, std::function<void(VideoState)> stateUpdated, std::shared_ptr<PlatformContext> platformContext, std::pair<int, int> &outResolution) override; std::unique_ptr<VideoCapturerInterface> makeVideoCapturer(rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> source, bool useFrontCamera, std::function<void(VideoState)> stateUpdated, std::shared_ptr<PlatformContext> platformContext, std::pair<int, int> &outResolution) override;

View file

@ -241,7 +241,8 @@ public:
_videoCapture(descriptor.videoCapture), _videoCapture(descriptor.videoCapture),
_localPreferredVideoAspectRatio(descriptor.config.preferredAspectRatio), _localPreferredVideoAspectRatio(descriptor.config.preferredAspectRatio),
_state(State::Reconnecting), _state(State::Reconnecting),
_videoState(_videoCapture ? VideoState::Active : VideoState::Inactive) { _videoState(_videoCapture ? VideoState::Active : VideoState::Inactive),
_platformContext(descriptor.platformContext) {
assert(getMediaThread()->IsCurrent()); assert(getMediaThread()->IsCurrent());
rtc::LogMessage::LogToDebug(rtc::LS_INFO); rtc::LogMessage::LogToDebug(rtc::LS_INFO);
@ -304,8 +305,8 @@ public:
mediaDeps.task_queue_factory = dependencies.task_queue_factory.get(); mediaDeps.task_queue_factory = dependencies.task_queue_factory.get();
mediaDeps.audio_encoder_factory = webrtc::CreateBuiltinAudioEncoderFactory(); mediaDeps.audio_encoder_factory = webrtc::CreateBuiltinAudioEncoderFactory();
mediaDeps.audio_decoder_factory = webrtc::CreateBuiltinAudioDecoderFactory(); mediaDeps.audio_decoder_factory = webrtc::CreateBuiltinAudioDecoderFactory();
mediaDeps.video_encoder_factory = PlatformInterface::SharedInstance()->makeVideoEncoderFactory(); mediaDeps.video_encoder_factory = PlatformInterface::SharedInstance()->makeVideoEncoderFactory(_platformContext);
mediaDeps.video_decoder_factory = PlatformInterface::SharedInstance()->makeVideoDecoderFactory(); mediaDeps.video_decoder_factory = PlatformInterface::SharedInstance()->makeVideoDecoderFactory(_platformContext);
webrtc::AudioProcessing *apm = webrtc::AudioProcessingBuilder().Create(); webrtc::AudioProcessing *apm = webrtc::AudioProcessingBuilder().Create();
webrtc::AudioProcessing::Config audioConfig; webrtc::AudioProcessing::Config audioConfig;
@ -926,6 +927,8 @@ private:
bool _didSetRemoteDescription = false; bool _didSetRemoteDescription = false;
std::vector<std::shared_ptr<IceCandidateData>> _pendingRemoteIceCandidates; std::vector<std::shared_ptr<IceCandidateData>> _pendingRemoteIceCandidates;
std::shared_ptr<PlatformContext> _platformContext;
}; };
InstanceImplReference::InstanceImplReference(Descriptor &&descriptor) : InstanceImplReference::InstanceImplReference(Descriptor &&descriptor) :

View file

@ -19,7 +19,7 @@ public class BuildVars {
public static boolean USE_CLOUD_STRINGS = true; public static boolean USE_CLOUD_STRINGS = true;
public static boolean CHECK_UPDATES = true; public static boolean CHECK_UPDATES = true;
public static boolean TON_WALLET_STANDALONE = false; public static boolean TON_WALLET_STANDALONE = false;
public static int BUILD_VERSION = 2064; public static int BUILD_VERSION = 2065;
public static String BUILD_VERSION_STRING = "7.0.0"; public static String BUILD_VERSION_STRING = "7.0.0";
public static int APP_ID = 4; public static int APP_ID = 4;
public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103"; public static String APP_HASH = "014b35b6184100b085b0d0572f9b5103";

View file

@ -880,7 +880,12 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
roundRect.set(drawRegion); roundRect.set(drawRegion);
if (isRoundRect) { if (isRoundRect) {
try {
canvas.drawRoundRect(roundRect,roundRadius[0], roundRadius[0],roundPaint); canvas.drawRoundRect(roundRect,roundRadius[0], roundRadius[0],roundPaint);
} catch (Exception e) {
onBitmapException(bitmapDrawable);
FileLog.e(e);
}
} else { } else {
for (int a = 0; a < roundRadius.length; a++) { for (int a = 0; a < roundRadius.length; a++) {
radii[a * 2] = roundRadius[a]; radii[a * 2] = roundRadius[a];
@ -930,7 +935,12 @@ public class ImageReceiver implements NotificationCenter.NotificationCenterDeleg
roundPaint.setAlpha(alpha); roundPaint.setAlpha(alpha);
if (isRoundRect) { if (isRoundRect) {
try {
canvas.drawRoundRect(roundRect, roundRadius[0], roundRadius[0], roundPaint); canvas.drawRoundRect(roundRect, roundRadius[0], roundRadius[0], roundPaint);
} catch (Exception e) {
onBitmapException(bitmapDrawable);
FileLog.e(e);
}
} else { } else {
for (int a = 0; a < roundRadius.length; a++) { for (int a = 0; a < roundRadius.length; a++) {
radii[a * 2] = roundRadius[a]; radii[a * 2] = roundRadius[a];

View file

@ -3187,8 +3187,14 @@ public class NotificationsController extends BaseController {
int selfUserId = getUserConfig().getClientUserId(); int selfUserId = getUserConfig().getClientUserId();
boolean waitingForPasscode = AndroidUtilities.needShowPasscode() || SharedConfig.isWaitingForPasscodeEnter; boolean waitingForPasscode = AndroidUtilities.needShowPasscode() || SharedConfig.isWaitingForPasscodeEnter;
int maxCount;
if (UserConfig.getActivatedAccountsCount() >= 3) {
maxCount = 7;
} else {
maxCount = 10;
}
for (int b = 0, size = sortedDialogs.size(); b < size; b++) { for (int b = 0, size = sortedDialogs.size(); b < size; b++) {
if (holders.size() >= 15) { if (holders.size() >= maxCount) {
break; break;
} }
long dialog_id = sortedDialogs.get(b); long dialog_id = sortedDialogs.get(b);

View file

@ -11,7 +11,6 @@ import androidx.annotation.Nullable;
import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ApplicationLoader;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.IOException;
/** /**
* This is a very dirty hack to allow Telegram calls to respect user's DND settings. * This is a very dirty hack to allow Telegram calls to respect user's DND settings.
@ -66,20 +65,20 @@ public class CallNotificationSoundProvider extends ContentProvider {
throw new FileNotFoundException("Unexpected application state"); throw new FileNotFoundException("Unexpected application state");
} }
try {
VoIPBaseService srv = VoIPBaseService.getSharedInstance(); VoIPBaseService srv = VoIPBaseService.getSharedInstance();
if (srv != null) { if (srv != null) {
srv.startRingtoneAndVibration(); srv.startRingtoneAndVibration();
} }
try {
ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe(); ParcelFileDescriptor[] pipe = ParcelFileDescriptor.createPipe();
ParcelFileDescriptor.AutoCloseOutputStream outputStream = new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]); ParcelFileDescriptor.AutoCloseOutputStream outputStream = new ParcelFileDescriptor.AutoCloseOutputStream(pipe[1]);
byte[] silentWav = {82, 73, 70, 70, 41, 0, 0, 0, 87, 65, 86, 69, 102, 109, 116, 32, 16, 0, 0, 0, 1, 0, 1, 0, 68, (byte) 172, 0, 0, 16, (byte) 177, 2, 0, 2, 0, 16, 0, 100, 97, 116, 97, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; byte[] silentWav = {82, 73, 70, 70, 41, 0, 0, 0, 87, 65, 86, 69, 102, 109, 116, 32, 16, 0, 0, 0, 1, 0, 1, 0, 68, (byte) 172, 0, 0, 16, (byte) 177, 2, 0, 2, 0, 16, 0, 100, 97, 116, 97, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
outputStream.write(silentWav); outputStream.write(silentWav);
outputStream.close(); outputStream.close();
return pipe[0]; return pipe[0];
} catch (IOException x) { } catch (Exception e) {
throw new FileNotFoundException(x.getMessage()); throw new FileNotFoundException(e.getMessage());
} }
} }
} }

View file

@ -330,6 +330,15 @@ public final class Instance {
public final boolean useSystemAec; public final boolean useSystemAec;
public final double hangupUiTimeout; public final double hangupUiTimeout;
public final boolean enable_vp8_encoder;
public final boolean enable_vp8_decoder;
public final boolean enable_vp9_encoder;
public final boolean enable_vp9_decoder;
public final boolean enable_h265_encoder;
public final boolean enable_h265_decoder;
public final boolean enable_h264_encoder;
public final boolean enable_h264_decoder;
private final JSONObject jsonObject; private final JSONObject jsonObject;
private ServerConfig(JSONObject jsonObject) { private ServerConfig(JSONObject jsonObject) {
@ -337,6 +346,15 @@ public final class Instance {
this.useSystemNs = jsonObject.optBoolean("use_system_ns", true); this.useSystemNs = jsonObject.optBoolean("use_system_ns", true);
this.useSystemAec = jsonObject.optBoolean("use_system_aec", true); this.useSystemAec = jsonObject.optBoolean("use_system_aec", true);
this.hangupUiTimeout = jsonObject.optDouble("hangup_ui_timeout", 5); this.hangupUiTimeout = jsonObject.optDouble("hangup_ui_timeout", 5);
this.enable_vp8_encoder = jsonObject.optBoolean("enable_vp8_encoder", true);
this.enable_vp8_decoder = jsonObject.optBoolean("enable_vp8_decoder", true);
this.enable_vp9_encoder = jsonObject.optBoolean("enable_vp9_encoder", true);
this.enable_vp9_decoder = jsonObject.optBoolean("enable_vp9_decoder", true);
this.enable_h265_encoder = jsonObject.optBoolean("enable_h265_encoder", true);
this.enable_h265_decoder = jsonObject.optBoolean("enable_h265_decoder", true);
this.enable_h264_encoder = jsonObject.optBoolean("enable_h264_encoder", true);
this.enable_h264_decoder = jsonObject.optBoolean("enable_h264_decoder", true);
} }
public String getString(String key) { public String getString(String key) {

View file

@ -5,6 +5,8 @@ import android.os.Build;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerThread; import android.os.HandlerThread;
import com.google.android.datatransport.runtime.logging.Logging;
import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.FileLog; import org.telegram.messenger.FileLog;
@ -44,6 +46,7 @@ public class VideoCameraCapturer {
if (Build.VERSION.SDK_INT < 18) { if (Build.VERSION.SDK_INT < 18) {
return; return;
} }
Logging.i("VideoCameraCapturer", "device model = " + Build.MANUFACTURER + Build.MODEL);
AndroidUtilities.runOnUIThread(() -> { AndroidUtilities.runOnUIThread(() -> {
instance = this; instance = this;
thread = new HandlerThread("CallThread"); thread = new HandlerThread("CallThread");
@ -192,5 +195,12 @@ public class VideoCameraCapturer {
}); });
} }
private EglBase.Context getSharedEGLContext() {
if (eglBase == null) {
eglBase = EglBase.create(null, EglBase.CONFIG_PLAIN);
}
return eglBase != null ? eglBase.getEglBaseContext() : null;
}
private static native CapturerObserver nativeGetJavaVideoCapturerObserver(long ptr); private static native CapturerObserver nativeGetJavaVideoCapturerObserver(long ptr);
} }

View file

@ -160,7 +160,7 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
protected long callStartTime; protected long callStartTime;
protected boolean playingSound; protected boolean playingSound;
protected boolean isOutgoing; protected boolean isOutgoing;
protected boolean videoCall; public boolean videoCall;
protected long videoCapturer; protected long videoCapturer;
protected Runnable timeoutRunnable; protected Runnable timeoutRunnable;
@ -1511,7 +1511,7 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
} }
// some non-Google devices don't implement the ConnectionService API correctly so, sadly, // some non-Google devices don't implement the ConnectionService API correctly so, sadly,
// we'll have to whitelist only a handful of known-compatible devices for now // we'll have to whitelist only a handful of known-compatible devices for now
return "angler".equals(Build.PRODUCT) // Nexus 6P return false;/*"angler".equals(Build.PRODUCT) // Nexus 6P
|| "bullhead".equals(Build.PRODUCT) // Nexus 5X || "bullhead".equals(Build.PRODUCT) // Nexus 5X
|| "sailfish".equals(Build.PRODUCT) // Pixel || "sailfish".equals(Build.PRODUCT) // Pixel
|| "marlin".equals(Build.PRODUCT) // Pixel XL || "marlin".equals(Build.PRODUCT) // Pixel XL
@ -1519,7 +1519,7 @@ public abstract class VoIPBaseService extends Service implements SensorEventList
|| "taimen".equals(Build.PRODUCT) // Pixel 2 XL || "taimen".equals(Build.PRODUCT) // Pixel 2 XL
|| "blueline".equals(Build.PRODUCT) // Pixel 3 || "blueline".equals(Build.PRODUCT) // Pixel 3
|| "crosshatch".equals(Build.PRODUCT) // Pixel 3 XL || "crosshatch".equals(Build.PRODUCT) // Pixel 3 XL
|| MessagesController.getGlobalMainSettings().getBoolean("dbg_force_connection_service", false); || MessagesController.getGlobalMainSettings().getBoolean("dbg_force_connection_service", false);*/
} }
public interface StateListener { public interface StateListener {

View file

@ -941,6 +941,7 @@ public class VoIPService extends VoIPBaseService {
PendingIntent.getActivity(VoIPService.this, 0, new Intent(VoIPService.this, VoIPFeedbackActivity.class) PendingIntent.getActivity(VoIPService.this, 0, new Intent(VoIPService.this, VoIPFeedbackActivity.class)
.putExtra("call_id", call.id) .putExtra("call_id", call.id)
.putExtra("call_access_hash", call.access_hash) .putExtra("call_access_hash", call.access_hash)
.putExtra("call_video", call.video)
.putExtra("account", currentAccount) .putExtra("account", currentAccount)
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP), 0).send(); .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP), 0).send();
} catch (Exception x) { } catch (Exception x) {

View file

@ -76,6 +76,12 @@ public class AcceptDeclineView extends View {
boolean retryMod; boolean retryMod;
Drawable rippleDrawable; Drawable rippleDrawable;
private boolean screenWasWakeup;
Paint linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
Drawable arrowDrawable;
float arrowProgress;
public AcceptDeclineView(@NonNull Context context) { public AcceptDeclineView(@NonNull Context context) {
super(context); super(context);
@ -107,12 +113,14 @@ public class AcceptDeclineView extends View {
cancelDrawable = ContextCompat.getDrawable(context, R.drawable.ic_close_white).mutate(); cancelDrawable = ContextCompat.getDrawable(context, R.drawable.ic_close_white).mutate();
cancelDrawable.setColorFilter(new PorterDuffColorFilter(Color.BLACK, PorterDuff.Mode.MULTIPLY)); cancelDrawable.setColorFilter(new PorterDuffColorFilter(Color.BLACK, PorterDuff.Mode.MULTIPLY));
acceptCirclePaint.setColor(0x3f45bc4d); acceptCirclePaint.setColor(0x3f45bc4d);
rippleDrawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(52), 0, ColorUtils.setAlphaComponent(Color.WHITE, (int) (255 * 0.3f))); rippleDrawable = Theme.createSimpleSelectorCircleDrawable(AndroidUtilities.dp(52), 0, ColorUtils.setAlphaComponent(Color.WHITE, (int) (255 * 0.3f)));
rippleDrawable.setCallback(this); rippleDrawable.setCallback(this);
arrowDrawable = ContextCompat.getDrawable(context, R.drawable.call_arrow_right);
} }
@Override @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec);
@ -122,6 +130,8 @@ public class AcceptDeclineView extends View {
callDrawable.setBounds(padding, padding, padding + AndroidUtilities.dp(28), padding + AndroidUtilities.dp(28)); callDrawable.setBounds(padding, padding, padding + AndroidUtilities.dp(28), padding + AndroidUtilities.dp(28));
cancelDrawable.setBounds(padding, padding, padding + AndroidUtilities.dp(28), padding + AndroidUtilities.dp(28)); cancelDrawable.setBounds(padding, padding, padding + AndroidUtilities.dp(28), padding + AndroidUtilities.dp(28));
linePaint.setStrokeWidth(AndroidUtilities.dp(3));
linePaint.setColor(Color.WHITE);
} }
@Override @Override
@ -200,7 +210,7 @@ public class AcceptDeclineView extends View {
animator.start(); animator.start();
leftAnimator = animator; leftAnimator = animator;
if (listener != null) { if (listener != null) {
if ((!startDrag && Math.abs(dy) < touchSlop) || leftOffsetX > maxOffset * 0.8f) { if ((!startDrag && Math.abs(dy) < touchSlop && !screenWasWakeup) || leftOffsetX > maxOffset * 0.8f) {
listener.onDicline(); listener.onDicline();
} }
} }
@ -214,7 +224,7 @@ public class AcceptDeclineView extends View {
animator.start(); animator.start();
rightAnimator = animator; rightAnimator = animator;
if (listener != null) { if (listener != null) {
if ((!startDrag && Math.abs(dy) < touchSlop) || -rigthOffsetX > maxOffset * 0.8f) { if ((!startDrag && Math.abs(dy) < touchSlop && !screenWasWakeup) || -rigthOffsetX > maxOffset * 0.8f) {
listener.onAccept(); listener.onAccept();
} }
} }
@ -263,6 +273,49 @@ public class AcceptDeclineView extends View {
invalidate(); invalidate();
} }
float k = 0.6f;
if (screenWasWakeup && !retryMod) {
arrowProgress += 16 / 1500f;
if (arrowProgress > 1) {
arrowProgress = 0;
}
int cY = (int) (AndroidUtilities.dp(40) + buttonWidth / 2f);
float startX = AndroidUtilities.dp(46) + buttonWidth + AndroidUtilities.dp(8);
float endX = getMeasuredWidth() / 2f - AndroidUtilities.dp(8);
float lineLength = AndroidUtilities.dp(10);
float stepProgress = (1f - k) / 3f;
for (int i = 0; i < 3; i++) {
int x = (int) (startX + (endX - startX - lineLength) / 3 * i);
float alpha = 0.5f;
float startAlphaFrom = i * stepProgress;
if (arrowProgress > startAlphaFrom && arrowProgress < startAlphaFrom + k) {
float p = (arrowProgress - startAlphaFrom) / k;
if (p > 0.5) p = 1f - p;
alpha = 0.5f + p;
}
canvas.save();
canvas.clipRect(leftOffsetX + AndroidUtilities.dp(46) + buttonWidth / 2,0,getMeasuredHeight(),getMeasuredWidth() >> 1);
arrowDrawable.setAlpha((int) (255 * alpha));
arrowDrawable.setBounds(x, cY - arrowDrawable.getIntrinsicHeight() / 2, x + arrowDrawable.getIntrinsicWidth(), cY + arrowDrawable.getIntrinsicHeight() / 2);
arrowDrawable.draw(canvas);
canvas.restore();
x = (int) (getMeasuredWidth() - (startX + (endX - startX - lineLength) / 3 * i));
canvas.save();
canvas.clipRect(getMeasuredWidth() >> 1, 0, rigthOffsetX + getMeasuredWidth() - AndroidUtilities.dp(46) - buttonWidth / 2, getMeasuredHeight());
canvas.rotate(180, x - arrowDrawable.getIntrinsicWidth() / 2f, cY);
arrowDrawable.setBounds(x - arrowDrawable.getIntrinsicWidth(), cY - arrowDrawable.getIntrinsicHeight() / 2, x, cY + arrowDrawable.getIntrinsicHeight() / 2);
arrowDrawable.draw(canvas);
canvas.restore();
}
invalidate();
}
bigRadius += AndroidUtilities.dp(8) * 0.005f; bigRadius += AndroidUtilities.dp(8) * 0.005f;
canvas.save(); canvas.save();
canvas.translate(0, AndroidUtilities.dp(40)); canvas.translate(0, AndroidUtilities.dp(40));
@ -330,6 +383,7 @@ public class AcceptDeclineView extends View {
public interface Listener { public interface Listener {
void onAccept(); void onAccept();
void onDicline(); void onDicline();
} }
@ -337,6 +391,7 @@ public class AcceptDeclineView extends View {
this.retryMod = retryMod; this.retryMod = retryMod;
if (retryMod) { if (retryMod) {
declineDrawable.setColor(Color.WHITE); declineDrawable.setColor(Color.WHITE);
screenWasWakeup = false;
} else { } else {
declineDrawable.setColor(0xFFe61e44); declineDrawable.setColor(0xFFe61e44);
} }
@ -421,6 +476,10 @@ public class AcceptDeclineView extends View {
return accessibilityNodeProvider; return accessibilityNodeProvider;
} }
public void setScreenWasWakeup(boolean screenWasWakeup) {
this.screenWasWakeup = screenWasWakeup;
}
private static abstract class AcceptDeclineAccessibilityNodeProvider extends AccessibilityNodeProvider { private static abstract class AcceptDeclineAccessibilityNodeProvider extends AccessibilityNodeProvider {
private final View hostView; private final View hostView;
@ -514,7 +573,9 @@ public class AcceptDeclineView extends View {
} }
protected abstract CharSequence getVirtualViewText(int virtualViewId); protected abstract CharSequence getVirtualViewText(int virtualViewId);
protected abstract void getVirtualViewBoundsInScreen(int virtualViewId, Rect outRect); protected abstract void getVirtualViewBoundsInScreen(int virtualViewId, Rect outRect);
protected abstract void getVirtualViewBoundsInParent(int virtualViewId, Rect outRect); protected abstract void getVirtualViewBoundsInParent(int virtualViewId, Rect outRect);
} }
} }

View file

@ -82,7 +82,11 @@ public class VoIPHelper {
bldr.setNeutralButton(LocaleController.getString("VoipOfflineOpenSettings", R.string.VoipOfflineOpenSettings), (dialog, which) -> activity.startActivity(settingsIntent)); bldr.setNeutralButton(LocaleController.getString("VoipOfflineOpenSettings", R.string.VoipOfflineOpenSettings), (dialog, which) -> activity.startActivity(settingsIntent));
} }
} }
try {
bldr.show(); bldr.show();
} catch (Exception e) {
FileLog.e(e);
}
return; return;
} }
@ -211,7 +215,7 @@ public class VoIPHelper {
if (d[0].equals(call.call_id + "")) { if (d[0].equals(call.call_id + "")) {
try { try {
long accessHash = Long.parseLong(d[1]); long accessHash = Long.parseLong(d[1]);
showRateAlert(context, null, call.call_id, accessHash, UserConfig.selectedAccount, true); showRateAlert(context, null, call.video, call.call_id, accessHash, UserConfig.selectedAccount, true);
} catch (Exception ignore) { } catch (Exception ignore) {
} }
return; return;
@ -219,7 +223,7 @@ public class VoIPHelper {
} }
} }
public static void showRateAlert(final Context context, final Runnable onDismiss, final long callID, final long accessHash, final int account, final boolean userInitiative) { public static void showRateAlert(final Context context, final Runnable onDismiss, boolean isVideo, final long callID, final long accessHash, final int account, final boolean userInitiative) {
final File log = getLogFile(callID); final File log = getLogFile(callID);
final int[] page = {0}; final int[] page = {0};
LinearLayout alertView = new LinearLayout(context); LinearLayout alertView = new LinearLayout(context);
@ -246,32 +250,41 @@ public class VoIPHelper {
check.setChecked(!check.isChecked(), true); check.setChecked(!check.isChecked(), true);
}; };
final String[] problems = {"echo", "noise", "interruptions", "distorted_speech", "silent_local", "silent_remote", "dropped"}; final String[] problems = {isVideo ? "distorted_video" : null, isVideo ? "pixelated_video" : null, "echo", "noise", "interruptions", "distorted_speech", "silent_local", "silent_remote", "dropped"};
for (int i = 0; i < problems.length; i++) { for (int i = 0; i < problems.length; i++) {
if (problems[i] == null) {
continue;
}
CheckBoxCell check = new CheckBoxCell(context, 1); CheckBoxCell check = new CheckBoxCell(context, 1);
check.setClipToPadding(false); check.setClipToPadding(false);
check.setTag(problems[i]); check.setTag(problems[i]);
String label = null; String label = null;
switch (i) { switch (i) {
case 0: case 0:
label = LocaleController.getString("RateCallEcho", R.string.RateCallEcho); label = LocaleController.getString("RateCallVideoDistorted", R.string.RateCallVideoDistorted);
break; break;
case 1: case 1:
label = LocaleController.getString("RateCallNoise", R.string.RateCallNoise); label = LocaleController.getString("RateCallVideoPixelated", R.string.RateCallVideoPixelated);
break; break;
case 2: case 2:
label = LocaleController.getString("RateCallInterruptions", R.string.RateCallInterruptions); label = LocaleController.getString("RateCallEcho", R.string.RateCallEcho);
break; break;
case 3: case 3:
label = LocaleController.getString("RateCallDistorted", R.string.RateCallDistorted); label = LocaleController.getString("RateCallNoise", R.string.RateCallNoise);
break; break;
case 4: case 4:
label = LocaleController.getString("RateCallSilentLocal", R.string.RateCallSilentLocal); label = LocaleController.getString("RateCallInterruptions", R.string.RateCallInterruptions);
break; break;
case 5: case 5:
label = LocaleController.getString("RateCallSilentRemote", R.string.RateCallSilentRemote); label = LocaleController.getString("RateCallDistorted", R.string.RateCallDistorted);
break; break;
case 6: case 6:
label = LocaleController.getString("RateCallSilentLocal", R.string.RateCallSilentLocal);
break;
case 7:
label = LocaleController.getString("RateCallSilentRemote", R.string.RateCallSilentRemote);
break;
case 8:
label = LocaleController.getString("RateCallDropped", R.string.RateCallDropped); label = LocaleController.getString("RateCallDropped", R.string.RateCallDropped);
break; break;
} }
@ -367,10 +380,11 @@ public class VoIPHelper {
problemTags.add("#" + check.getTag()); problemTags.add("#" + check.getTag());
} }
if (req.rating < 5) if (req.rating < 5) {
req.comment = commentBox.getText().toString(); req.comment = commentBox.getText().toString();
else } else {
req.comment = ""; req.comment = "";
}
if (!problemTags.isEmpty() && !includeLogs[0]) { if (!problemTags.isEmpty() && !includeLogs[0]) {
req.comment += " " + TextUtils.join(" ", problemTags); req.comment += " " + TextUtils.join(" ", problemTags);
} }

View file

@ -34,6 +34,7 @@ import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ApplicationLoader; import org.telegram.messenger.ApplicationLoader;
import org.telegram.messenger.FileLog; import org.telegram.messenger.FileLog;
import org.telegram.messenger.LocaleController; import org.telegram.messenger.LocaleController;
import org.telegram.messenger.NotificationCenter;
import org.telegram.messenger.R; import org.telegram.messenger.R;
import org.telegram.messenger.voip.Instance; import org.telegram.messenger.voip.Instance;
import org.telegram.messenger.voip.VideoCameraCapturer; import org.telegram.messenger.voip.VideoCameraCapturer;
@ -44,7 +45,7 @@ import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.LaunchActivity; import org.telegram.ui.LaunchActivity;
import org.telegram.ui.VoIPFragment; import org.telegram.ui.VoIPFragment;
public class VoIPPiPView implements VoIPBaseService.StateListener { public class VoIPPiPView implements VoIPBaseService.StateListener, NotificationCenter.NotificationCenterDelegate {
public final static int ANIMATION_ENTER_TYPE_SCALE = 0; public final static int ANIMATION_ENTER_TYPE_SCALE = 0;
public final static int ANIMATION_ENTER_TYPE_TRANSITION = 1; public final static int ANIMATION_ENTER_TYPE_TRANSITION = 1;
@ -148,6 +149,7 @@ public class VoIPPiPView implements VoIPBaseService.StateListener {
float y = preferences.getFloat("relativeY", 0f); float y = preferences.getFloat("relativeY", 0f);
instance.setRelativePosition(x, y); instance.setRelativePosition(x, y);
NotificationCenter.getGlobalInstance().addObserver(instance, NotificationCenter.didEndCall);
wm.addView(instance.windowView, windowLayoutParams); wm.addView(instance.windowView, windowLayoutParams);
instance.currentUserTextureView.renderer.init(VideoCameraCapturer.eglBase.getEglBaseContext(), null); instance.currentUserTextureView.renderer.init(VideoCameraCapturer.eglBase.getEglBaseContext(), null);
@ -324,6 +326,8 @@ public class VoIPPiPView implements VoIPBaseService.StateListener {
VoIPService service = VoIPService.getSharedInstance(); VoIPService service = VoIPService.getSharedInstance();
if (service != null) { if (service != null) {
service.hangUp(); service.hangUp();
} else {
finish();
} }
}); });
@ -353,6 +357,8 @@ public class VoIPPiPView implements VoIPBaseService.StateListener {
if (service != null) { if (service != null) {
service.unregisterStateListener(this); service.unregisterStateListener(this);
} }
windowView.setVisibility(View.GONE);
if (windowView.getParent() != null) {
floatingView.getRelativePosition(point); floatingView.getRelativePosition(point);
float x = Math.min(1f, Math.max(0f, point[0])); float x = Math.min(1f, Math.max(0f, point[0]));
float y = Math.min(1f, Math.max(0f, point[1])); float y = Math.min(1f, Math.max(0f, point[1]));
@ -361,15 +367,14 @@ public class VoIPPiPView implements VoIPBaseService.StateListener {
.putFloat("relativeX", x) .putFloat("relativeX", x)
.putFloat("relativeY", y) .putFloat("relativeY", y)
.apply(); .apply();
windowView.setVisibility(View.GONE);
if (windowView.getParent() != null) {
try { try {
windowManager.removeView(windowView); windowManager.removeView(windowView);
} catch (Throwable e) { } catch (Throwable e) {
FileLog.e(e); FileLog.e(e);
} }
} }
instance = null; NotificationCenter.getGlobalInstance().removeObserver(this, NotificationCenter.didEndCall);
} }
@Override @Override
@ -477,6 +482,13 @@ public class VoIPPiPView implements VoIPBaseService.StateListener {
} }
} }
@Override
public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.didEndCall) {
finish();
}
}
private class FloatingView extends FrameLayout { private class FloatingView extends FrameLayout {
@ -762,12 +774,7 @@ public class VoIPPiPView implements VoIPBaseService.StateListener {
return; return;
} }
expandedInstance.windowView.setAlpha(0); expandedInstance.windowView.setAlpha(0);
try { expandedInstance.finishInternal();
windowManager.removeView(expandedInstance.windowView);
} catch (Throwable e) {
FileLog.e(e);
}
expandedInstance = null;
expandedAnimationInProgress = false; expandedAnimationInProgress = false;
if (expanded) { if (expanded) {
AndroidUtilities.runOnUIThread(collapseRunnable, 3000); AndroidUtilities.runOnUIThread(collapseRunnable, 3000);

View file

@ -19,18 +19,21 @@ import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import org.telegram.messenger.AndroidUtilities; import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.R;
import org.telegram.ui.Components.CubicBezierInterpolator; import org.telegram.ui.Components.CubicBezierInterpolator;
import org.telegram.ui.Components.LayoutHelper; import org.telegram.ui.Components.LayoutHelper;
public class VoIPStatusTextView extends FrameLayout { public class VoIPStatusTextView extends FrameLayout {
TextView[] textView = new TextView[2]; TextView[] textView = new TextView[2];
TextView reconnectTextView;
VoIPTimerView timerView; VoIPTimerView timerView;
CharSequence nextTextToSet; CharSequence nextTextToSet;
boolean animationInProgress; boolean animationInProgress;
private TextAlphaSpan[] ellSpans = ellSpans = new TextAlphaSpan[]{new TextAlphaSpan(), new TextAlphaSpan(), new TextAlphaSpan()}; private TextAlphaSpan[] ellSpans = new TextAlphaSpan[]{new TextAlphaSpan(), new TextAlphaSpan(), new TextAlphaSpan()};
private AnimatorSet ellAnimator; private AnimatorSet ellAnimator;
private boolean attachedToWindow; private boolean attachedToWindow;
@ -47,6 +50,23 @@ public class VoIPStatusTextView extends FrameLayout {
textView[i].setGravity(Gravity.CENTER_HORIZONTAL); textView[i].setGravity(Gravity.CENTER_HORIZONTAL);
addView(textView[i]); addView(textView[i]);
} }
reconnectTextView = new TextView(context);
reconnectTextView.setTextSize(15);
reconnectTextView.setShadowLayer(AndroidUtilities.dp(3), 0, AndroidUtilities.dp(.666666667f), 0x4C000000);
reconnectTextView.setTextColor(Color.WHITE);
reconnectTextView.setGravity(Gravity.CENTER_HORIZONTAL);
addView(reconnectTextView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, 0, 0, 22, 0, 0));
SpannableStringBuilder ssb = new SpannableStringBuilder(LocaleController.getString("VoipReconnecting", R.string.VoipReconnecting));
SpannableString ell = new SpannableString("...");
ell.setSpan(ellSpans[0], 0, 1, 0);
ell.setSpan(ellSpans[1], 1, 2, 0);
ell.setSpan(ellSpans[2], 2, 3, 0);
ssb.append(ell);
reconnectTextView.setText(ssb);
reconnectTextView.setVisibility(View.GONE);
timerView = new VoIPTimerView(context); timerView = new VoIPTimerView(context);
addView(timerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT)); addView(timerView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT));
@ -97,7 +117,6 @@ public class VoIPStatusTextView extends FrameLayout {
animated = false; animated = false;
} }
if (!animated) { if (!animated) {
if (animator != null) { if (animator != null) {
animator.cancel(); animator.cancel();
@ -230,6 +249,9 @@ public class VoIPStatusTextView extends FrameLayout {
textView[0].invalidate(); textView[0].invalidate();
textView[1].invalidate(); textView[1].invalidate();
} }
if (reconnectTextView.getVisibility() == View.VISIBLE) {
reconnectTextView.invalidate();
}
}); });
a.setDuration(duration); a.setDuration(duration);
a.setStartDelay(startDelay); a.setStartDelay(startDelay);
@ -237,6 +259,29 @@ public class VoIPStatusTextView extends FrameLayout {
return a; return a;
} }
public void showReconnect(boolean showReconnecting, boolean animated) {
if (!animated) {
reconnectTextView.animate().setListener(null).cancel();
reconnectTextView.setVisibility(showReconnecting ? View.VISIBLE : View.GONE);
} else {
if (showReconnecting) {
if (reconnectTextView.getVisibility() != View.VISIBLE) {
reconnectTextView.setVisibility(View.VISIBLE);
reconnectTextView.setAlpha(0);
}
reconnectTextView.animate().setListener(null).cancel();
reconnectTextView.animate().alpha(1f).setDuration(150).start();
} else {
reconnectTextView.animate().alpha(0).setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
reconnectTextView.setVisibility(View.GONE);
}
}).setDuration(150).start();
}
}
}
private class TextAlphaSpan extends CharacterStyle { private class TextAlphaSpan extends CharacterStyle {
private int alpha; private int alpha;

View file

@ -245,6 +245,8 @@ public class VoIPToggleButton extends FrameLayout {
textView[0].setText(text); textView[0].setText(text);
crossProgress = drawCross ? 1f : 0; crossProgress = drawCross ? 1f : 0;
iconChangeColor = false; iconChangeColor = false;
replaceProgress = 0f;
invalidate();
} else { } else {
if (!iconChangeColor) { if (!iconChangeColor) {
icon[1] = ContextCompat.getDrawable(getContext(), iconRes).mutate(); icon[1] = ContextCompat.getDrawable(getContext(), iconRes).mutate();
@ -299,6 +301,7 @@ public class VoIPToggleButton extends FrameLayout {
} }
}); });
replaceAnimator.setDuration(150).start(); replaceAnimator.setDuration(150).start();
invalidate();
} }
} }

View file

@ -673,7 +673,7 @@ public class LaunchActivity extends Activity implements ActionBarLayout.ActionBa
if (BuildVars.LOGS_ENABLED) { if (BuildVars.LOGS_ENABLED) {
FileLog.d("OS name " + os1 + " " + os2); FileLog.d("OS name " + os1 + " " + os2);
} }
if (os1.contains("flyme") || os2.contains("flyme")) { if ((os1.contains("flyme") || os2.contains("flyme")) && Build.VERSION.SDK_INT <= 24) {
AndroidUtilities.incorrectDisplaySizeFix = true; AndroidUtilities.incorrectDisplaySizeFix = true;
final View view = getWindow().getDecorView().getRootView(); final View view = getWindow().getDecorView().getRootView();
view.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener = () -> { view.getViewTreeObserver().addOnGlobalLayoutListener(onGlobalLayoutListener = () -> {

View file

@ -364,7 +364,7 @@ public class PaymentFormActivity extends BaseFragment implements NotificationCen
currentItemName = message.messageOwner.media.title; currentItemName = message.messageOwner.media.title;
validateRequest = request; validateRequest = request;
saveShippingInfo = true; saveShippingInfo = true;
if (saveCard) { if (saveCard || currentStep == 4) {
saveCardInfo = saveCard; saveCardInfo = saveCard;
} else { } else {
saveCardInfo = paymentForm.saved_credentials != null; saveCardInfo = paymentForm.saved_credentials != null;

View file

@ -3415,6 +3415,10 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
color2 = Theme.getColor(Theme.key_windowBackgroundWhite); color2 = Theme.getColor(Theme.key_windowBackgroundWhite);
verifiedCheckDrawable.setColorFilter(AndroidUtilities.getOffsetColor(color1, color2, value, 1.0f), PorterDuff.Mode.MULTIPLY); verifiedCheckDrawable.setColorFilter(AndroidUtilities.getOffsetColor(color1, color2, value, 1.0f), PorterDuff.Mode.MULTIPLY);
} }
if (avatarsViewPagerIndicatorView.getSecondaryMenuItem() != null && videoCallItemVisible) {
needLayoutText(Math.min(1f, extraHeight / AndroidUtilities.dp(88f)));
}
} }
@Override @Override
@ -3932,7 +3936,8 @@ public class ProfileActivity extends BaseFragment implements NotificationCenter.
} }
int viewWidth = AndroidUtilities.isTablet() ? AndroidUtilities.dp(490) : AndroidUtilities.displaySize.x; int viewWidth = AndroidUtilities.isTablet() ? AndroidUtilities.dp(490) : AndroidUtilities.displaySize.x;
int buttonsWidth = AndroidUtilities.dp(118 + 8 + (40 + (callItemVisible || editItemVisible || searchItem != null ? 48 : 0) + (videoCallItemVisible ? 48 : 0))); ActionBarMenuItem item = avatarsViewPagerIndicatorView.getSecondaryMenuItem();
int buttonsWidth = AndroidUtilities.dp(118 + 8 + (40 + (item != null ? 48 * (1.0f - mediaHeaderAnimationProgress) : 0) + (videoCallItemVisible ? 48 * (1.0f - mediaHeaderAnimationProgress) : 0)));
int minWidth = viewWidth - buttonsWidth; int minWidth = viewWidth - buttonsWidth;
int width = (int) (viewWidth - buttonsWidth * Math.max(0.0f, 1.0f - (diff != 1.0f ? diff * 0.15f / (1.0f - diff) : 1.0f)) - nameTextView[1].getTranslationX()); int width = (int) (viewWidth - buttonsWidth * Math.max(0.0f, 1.0f - (diff != 1.0f ? diff * 0.15f / (1.0f - diff) : 1.0f)) - nameTextView[1].getTranslationX());

View file

@ -16,12 +16,7 @@ public class VoIPFeedbackActivity extends Activity {
setContentView(new View(this)); setContentView(new View(this));
VoIPHelper.showRateAlert(this, new Runnable(){ VoIPHelper.showRateAlert(this, this::finish, getIntent().getBooleanExtra("call_video", false), getIntent().getLongExtra("call_id", 0), getIntent().getLongExtra("call_access_hash", 0), getIntent().getIntExtra("account", 0), false);
@Override
public void run(){
finish();
}
}, getIntent().getLongExtra("call_id", 0), getIntent().getLongExtra("call_access_hash", 0), getIntent().getIntExtra("account", 0), false);
} }
@Override @Override

View file

@ -202,6 +202,9 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
} }
}; };
private boolean lockOnScreen; private boolean lockOnScreen;
private boolean screenWasWakeup;
private boolean isVideoCall;
public static void show(Activity activity) { public static void show(Activity activity) {
show(activity, false); show(activity, false);
@ -252,6 +255,15 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
} }
}; };
instance.deviceIsLocked = ((KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE)).inKeyguardRestrictedInputMode(); instance.deviceIsLocked = ((KeyguardManager) activity.getSystemService(Context.KEYGUARD_SERVICE)).inKeyguardRestrictedInputMode();
PowerManager pm = (PowerManager) activity.getSystemService(Context.POWER_SERVICE);
boolean screenOn;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT_WATCH) {
screenOn = pm.isInteractive();
} else {
screenOn = pm.isScreenOn();
}
instance.screenWasWakeup = !screenOn;
windowView.setLockOnScreen(instance.deviceIsLocked); windowView.setLockOnScreen(instance.deviceIsLocked);
fragment.windowView = windowView; fragment.windowView = windowView;
@ -406,6 +418,10 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
public void didReceivedNotification(int id, int account, Object... args) { public void didReceivedNotification(int id, int account, Object... args) {
if (id == NotificationCenter.voipServiceCreated) { if (id == NotificationCenter.voipServiceCreated) {
if (currentState == VoIPService.STATE_BUSY && VoIPService.getSharedInstance() != null) { if (currentState == VoIPService.STATE_BUSY && VoIPService.getSharedInstance() != null) {
currentUserTextureView.renderer.release();
callingUserTextureView.renderer.release();
callingUserMiniTextureRenderer.release();
initRenderers();
VoIPService.getSharedInstance().registerStateListener(this); VoIPService.getSharedInstance().registerStateListener(this);
} }
} }
@ -430,6 +446,9 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
@Override @Override
public void onMediaStateUpdated(int audioState, int videoState) { public void onMediaStateUpdated(int audioState, int videoState) {
previousState = currentState; previousState = currentState;
if (videoState == Instance.VIDEO_STATE_ACTIVE && !isVideoCall) {
isVideoCall = true;
}
updateViewState(); updateViewState();
} }
@ -442,6 +461,9 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
@Override @Override
public void onVideoAvailableChange(boolean isAvailable) { public void onVideoAvailableChange(boolean isAvailable) {
previousState = currentState; previousState = currentState;
if (isAvailable && !isVideoCall) {
isVideoCall = true;
}
updateViewState(); updateViewState();
} }
@ -559,7 +581,7 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
lastContentTapTime = System.currentTimeMillis(); lastContentTapTime = System.currentTimeMillis();
callingUserMiniFloatingLayout.setRelativePosition(currentUserCameraFloatingLayout); callingUserMiniFloatingLayout.setRelativePosition(currentUserCameraFloatingLayout);
cameraForceExpanded = true; cameraForceExpanded = true;
currentState = previousState; previousState = currentState;
updateViewState(); updateViewState();
} }
}); });
@ -585,7 +607,7 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
lastContentTapTime = System.currentTimeMillis(); lastContentTapTime = System.currentTimeMillis();
currentUserCameraFloatingLayout.setRelativePosition(callingUserMiniFloatingLayout); currentUserCameraFloatingLayout.setRelativePosition(callingUserMiniFloatingLayout);
cameraForceExpanded = false; cameraForceExpanded = false;
currentState = previousState; previousState = currentState;
updateViewState(); updateViewState();
} }
}); });
@ -700,7 +722,6 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
bottomButtons[i] = new VoIPToggleButton(context); bottomButtons[i] = new VoIPToggleButton(context);
buttonsLayout.addView(bottomButtons[i]); buttonsLayout.addView(bottomButtons[i]);
} }
acceptDeclineView = new AcceptDeclineView(context); acceptDeclineView = new AcceptDeclineView(context);
acceptDeclineView.setListener(new AcceptDeclineView.Listener() { acceptDeclineView.setListener(new AcceptDeclineView.Listener() {
@Override @Override
@ -710,6 +731,8 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
intent.putExtra("user_id", callingUser.id); intent.putExtra("user_id", callingUser.id);
intent.putExtra("is_outgoing", true); intent.putExtra("is_outgoing", true);
intent.putExtra("start_incall_activity", false); intent.putExtra("start_incall_activity", false);
intent.putExtra("video_call", isVideoCall);
intent.putExtra("can_video_call", isVideoCall);
intent.putExtra("account", UserConfig.selectedAccount); intent.putExtra("account", UserConfig.selectedAccount);
try { try {
activity.startService(intent); activity.startService(intent);
@ -741,6 +764,7 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
} }
} }
}); });
acceptDeclineView.setScreenWasWakeup(screenWasWakeup);
frameLayout.addView(buttonsLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM)); frameLayout.addView(buttonsLayout, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, LayoutHelper.WRAP_CONTENT, Gravity.BOTTOM));
frameLayout.addView(acceptDeclineView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 186, Gravity.BOTTOM)); frameLayout.addView(acceptDeclineView, LayoutHelper.createFrame(LayoutHelper.MATCH_PARENT, 186, Gravity.BOTTOM));
@ -789,11 +813,19 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
VoIPService service = VoIPService.getSharedInstance(); VoIPService service = VoIPService.getSharedInstance();
if (service != null) { if (service != null) {
if (!isVideoCall) {
isVideoCall = service.call != null && service.call.video;
}
initRenderers();
}
return frameLayout;
}
private void initRenderers() {
if (VideoCameraCapturer.eglBase == null) { if (VideoCameraCapturer.eglBase == null) {
VideoCameraCapturer.eglBase = EglBase.create(null, EglBase.CONFIG_PLAIN); VideoCameraCapturer.eglBase = EglBase.create(null, EglBase.CONFIG_PLAIN);
} }
currentUserTextureView.renderer.init(VideoCameraCapturer.eglBase.getEglBaseContext(), new RendererCommon.RendererEvents() { currentUserTextureView.renderer.init(VideoCameraCapturer.eglBase.getEglBaseContext(), new RendererCommon.RendererEvents() {
@Override @Override
public void onFirstFrameRendered() { public void onFirstFrameRendered() {
@ -822,9 +854,6 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
callingUserMiniTextureRenderer.init(VideoCameraCapturer.eglBase.getEglBaseContext(), null); callingUserMiniTextureRenderer.init(VideoCameraCapturer.eglBase.getEglBaseContext(), null);
} }
return frameLayout;
}
public void switchToPip() { public void switchToPip() {
if (isFinished || !AndroidUtilities.checkInlinePermissions(activity) || instance == null) { if (isFinished || !AndroidUtilities.checkInlinePermissions(activity) || instance == null) {
return; return;
@ -907,6 +936,7 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
notificationsLayout.setAlpha(0f); notificationsLayout.setAlpha(0f);
callingUserPhotoView.setAlpha(0f); callingUserPhotoView.setAlpha(0f);
currentUserCameraFloatingLayout.switchingToPip = true;
AndroidUtilities.runOnUIThread(() -> { AndroidUtilities.runOnUIThread(() -> {
VoIPPiPView.switchingToPip = false; VoIPPiPView.switchingToPip = false;
VoIPPiPView.finish(); VoIPPiPView.finish();
@ -921,7 +951,6 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
notificationsLayout.animate().alpha(1f).setDuration(350).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); notificationsLayout.animate().alpha(1f).setDuration(350).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
callingUserPhotoView.animate().alpha(1f).setDuration(350).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); callingUserPhotoView.animate().alpha(1f).setDuration(350).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
currentUserCameraFloatingLayout.switchingToPip = true;
animator.addListener(new AnimatorListenerAdapter() { animator.addListener(new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
@ -936,8 +965,8 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
animator.setDuration(350); animator.setDuration(350);
animator.setInterpolator(CubicBezierInterpolator.DEFAULT); animator.setInterpolator(CubicBezierInterpolator.DEFAULT);
animator.start(); animator.start();
}, 64); }, 32);
}, 64); }, 32);
} }
@ -1113,6 +1142,7 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
boolean animated = previousState != -1; boolean animated = previousState != -1;
boolean showAcceptDeclineView = false; boolean showAcceptDeclineView = false;
boolean showTimer = false; boolean showTimer = false;
boolean showReconnecting = false;
boolean showCallingAvatarMini = false; boolean showCallingAvatarMini = false;
int statusLayoutOffset = 0; int statusLayoutOffset = 0;
@ -1120,6 +1150,9 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
if (service != null) { if (service != null) {
callingUserIsVideo = service.getCurrentVideoState() == Instance.VIDEO_STATE_ACTIVE; callingUserIsVideo = service.getCurrentVideoState() == Instance.VIDEO_STATE_ACTIVE;
currentUserIsVideo = service.getVideoState() == Instance.VIDEO_STATE_ACTIVE || service.getVideoState() == Instance.VIDEO_STATE_PAUSED; currentUserIsVideo = service.getVideoState() == Instance.VIDEO_STATE_ACTIVE || service.getVideoState() == Instance.VIDEO_STATE_PAUSED;
if (currentUserIsVideo && !isVideoCall) {
isVideoCall = true;
}
} }
if (animated) { if (animated) {
@ -1134,7 +1167,7 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
statusLayoutOffset = AndroidUtilities.dp(24); statusLayoutOffset = AndroidUtilities.dp(24);
acceptDeclineView.setRetryMod(false); acceptDeclineView.setRetryMod(false);
if (service != null && service.call.video) { if (service != null && service.call.video) {
if (currentUserIsVideo) { if (currentUserIsVideo && callingUser.photo != null) {
showCallingAvatarMini = true; showCallingAvatarMini = true;
} else { } else {
showCallingAvatarMini = false; showCallingAvatarMini = false;
@ -1177,6 +1210,9 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
updateKeyView(animated); updateKeyView(animated);
} }
showTimer = true; showTimer = true;
if (currentState == VoIPService.STATE_RECONNECTING) {
showReconnecting = true;
}
break; break;
case VoIPBaseService.STATE_ENDED: case VoIPBaseService.STATE_ENDED:
currentUserTextureView.saveCameraLastBitmap(); currentUserTextureView.saveCameraLastBitmap();
@ -1192,9 +1228,42 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
final String message = LocaleController.formatString("VoipPeerIncompatible", R.string.VoipPeerIncompatible, name); final String message = LocaleController.formatString("VoipPeerIncompatible", R.string.VoipPeerIncompatible, name);
showErrorDialog(AndroidUtilities.replaceTags(message)); showErrorDialog(AndroidUtilities.replaceTags(message));
} else if (TextUtils.equals(lastError, Instance.ERROR_PEER_OUTDATED)) { } else if (TextUtils.equals(lastError, Instance.ERROR_PEER_OUTDATED)) {
final String name = ContactsController.formatName(callingUser.first_name, callingUser.last_name); if (isVideoCall) {
final String name = UserObject.getFirstName(callingUser);
final String message = LocaleController.formatString("VoipPeerVideoOutdated", R.string.VoipPeerVideoOutdated, name);
boolean[] callAgain = new boolean[1];
AlertDialog dlg = new DarkAlertDialog.Builder(activity)
.setTitle(LocaleController.getString("VoipFailed", R.string.VoipFailed))
.setMessage(AndroidUtilities.replaceTags(message))
.setNegativeButton(LocaleController.getString("Cancel", R.string.Cancel), (dialogInterface, i) -> windowView.finish())
.setPositiveButton(LocaleController.getString("VoipPeerVideoOutdatedMakeVoice", R.string.VoipPeerVideoOutdatedMakeVoice), (dialogInterface, i) -> {
callAgain[0] = true;
currentState = VoIPService.STATE_BUSY;
Intent intent = new Intent(activity, VoIPService.class);
intent.putExtra("user_id", callingUser.id);
intent.putExtra("is_outgoing", true);
intent.putExtra("start_incall_activity", false);
intent.putExtra("video_call", false);
intent.putExtra("can_video_call", false);
intent.putExtra("account", UserConfig.selectedAccount);
try {
activity.startService(intent);
} catch (Throwable e) {
FileLog.e(e);
}
})
.show();
dlg.setCanceledOnTouchOutside(true);
dlg.setOnDismissListener(dialog -> {
if (!callAgain[0]) {
windowView.finish();
}
});
} else {
final String name = UserObject.getFirstName(callingUser);
final String message = LocaleController.formatString("VoipPeerOutdated", R.string.VoipPeerOutdated, name); final String message = LocaleController.formatString("VoipPeerOutdated", R.string.VoipPeerOutdated, name);
showErrorDialog(AndroidUtilities.replaceTags(message)); showErrorDialog(AndroidUtilities.replaceTags(message));
}
} else if (TextUtils.equals(lastError, Instance.ERROR_PRIVACY)) { } else if (TextUtils.equals(lastError, Instance.ERROR_PRIVACY)) {
final String name = ContactsController.formatName(callingUser.first_name, callingUser.last_name); final String name = ContactsController.formatName(callingUser.first_name, callingUser.last_name);
final String message = LocaleController.formatString("CallNotAvailable", R.string.CallNotAvailable, name); final String message = LocaleController.formatString("CallNotAvailable", R.string.CallNotAvailable, name);
@ -1286,12 +1355,17 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
backIcon.setAlpha(lockOnScreen ? 0 : 1f); backIcon.setAlpha(lockOnScreen ? 0 : 1f);
notificationsLayout.setTranslationY(-AndroidUtilities.dp(16) - (uiVisible ? AndroidUtilities.dp(80) : 0)); notificationsLayout.setTranslationY(-AndroidUtilities.dp(16) - (uiVisible ? AndroidUtilities.dp(80) : 0));
} }
if (currentState != VoIPService.STATE_HANGING_UP && currentState != VoIPService.STATE_ENDED) {
updateButtons(animated); updateButtons(animated);
}
if (showTimer) { if (showTimer) {
statusTextView.showTimer(animated); statusTextView.showTimer(animated);
} }
statusTextView.showReconnect(showReconnecting, animated);
if (animated) { if (animated) {
if (statusLayoutOffset != statusLayoutAnimateToOffset) { if (statusLayoutOffset != statusLayoutAnimateToOffset) {
statusLayout.animate().translationY(statusLayoutOffset).setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT).start(); statusLayout.animate().translationY(statusLayoutOffset).setDuration(150).setInterpolator(CubicBezierInterpolator.DEFAULT).start();
@ -1749,6 +1823,7 @@ public class VoIPFragment implements VoIPBaseService.StateListener, Notification
view.announceForAccessibility(text); view.announceForAccessibility(text);
} }
serviceInstance.setMicMute(micMute); serviceInstance.setMicMute(micMute);
previousState = currentState;
updateViewState(); updateViewState();
} }
}); });

View file

@ -63,9 +63,9 @@ public class GlShader {
// part of the program object." // part of the program object."
// But in practice, detaching shaders from the program seems to break some devices. Deleting the // But in practice, detaching shaders from the program seems to break some devices. Deleting the
// shaders are fine however - it will delete them when they are no longer attached to a program. // shaders are fine however - it will delete them when they are no longer attached to a program.
GLES20.glDeleteShader(vertexShader); //GLES20.glDeleteShader(vertexShader); delete crashes on xiaomi
GLES20.glDeleteShader(fragmentShader); //GLES20.glDeleteShader(fragmentShader);
GlUtil.checkNoGLES2Error("Creating GlShader"); //GlUtil.checkNoGLES2Error("Creating GlShader");
} }
public int getAttribLocation(String label) { public int getAttribLocation(String label) {

View file

@ -11,8 +11,10 @@
package org.webrtc; package org.webrtc;
import android.media.MediaCodecInfo; import android.media.MediaCodecInfo;
import org.telegram.messenger.voip.Instance;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import java.util.Arrays;
/** Factory for Android hardware VideoDecoders. */ /** Factory for Android hardware VideoDecoders. */
public class HardwareVideoDecoderFactory extends MediaCodecVideoDecoderFactory { public class HardwareVideoDecoderFactory extends MediaCodecVideoDecoderFactory {
@ -20,7 +22,27 @@ public class HardwareVideoDecoderFactory extends MediaCodecVideoDecoderFactory {
new Predicate<MediaCodecInfo>() { new Predicate<MediaCodecInfo>() {
@Override @Override
public boolean test(MediaCodecInfo arg) { public boolean test(MediaCodecInfo arg) {
return MediaCodecUtils.isHardwareAccelerated(arg); if (!MediaCodecUtils.isHardwareAccelerated(arg)) {
return false;
}
String[] types = arg.getSupportedTypes();
if (types == null || types.length == 0) {
return false;
}
Instance.ServerConfig config = Instance.getGlobalServerConfig();
for (int a = 0; a < types.length; a++) {
switch (types[a]) {
case "video/x-vnd.on2.vp8":
return config.enable_vp8_decoder;
case "video/x-vnd.on2.vp9":
return config.enable_vp9_decoder;
case "video/avc":
return config.enable_h264_decoder;
case "video/hevc":
return config.enable_h265_decoder;
}
}
return true;
} }
}; };

View file

@ -18,12 +18,12 @@ import static org.webrtc.MediaCodecUtils.HISI_PREFIX;
import android.media.MediaCodecInfo; import android.media.MediaCodecInfo;
import android.media.MediaCodecList; import android.media.MediaCodecList;
import android.os.Build; import android.os.Build;
import org.telegram.messenger.voip.Instance;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set;
/** Factory for android hardware video encoders. */ /** Factory for android hardware video encoders. */
@SuppressWarnings("deprecation") // API 16 requires the use of deprecated methods. @SuppressWarnings("deprecation") // API 16 requires the use of deprecated methods.
@ -40,63 +40,6 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
private final boolean enableH264HighProfile; private final boolean enableH264HighProfile;
@Nullable private final Predicate<MediaCodecInfo> codecAllowedPredicate; @Nullable private final Predicate<MediaCodecInfo> codecAllowedPredicate;
private static final List<String> H264_HW_EXCEPTION_MODELS =
Arrays.asList("samsung-sgh-i337", "nexus7", "nexus4", "pixel3xl", "pixel3");
private static final List<String> VP8_HW_EXCEPTION_MODELS =
Arrays.asList("pixel3xl", "pixel3");
private static Set<String> HW_EXCEPTION_MODELS = new HashSet<String>() {{
add("sm-a310f");
add("sm-a310f/ds");
add("sm-a310y");
add("sm-a310m");
add("sm-g920f");
add("sm-g920fd");
add("sm-g920fq");
add("sm-g920i");
add("sm-g920a");
add("sm-g920t");
add("sm-g930f");
add("sm-g930fd");
add("sm-g930w8");
add("sm-g930s");
add("sm-g930k");
add("sm-g930l");
add("sm-g935f");
add("sm-g935fd");
add("sm-g935w8");
add("sm-g935s");
add("sm-g935k");
add("sm-g935l");
add("i537");
add("sgh-i537");
add("gt-i9295");
add("sgh-i337");
add("gt-i9505g");
add("gt-i9505");
add("gt-i9515");
add("f240");
add("e980");
add("ls980");
add("e988");
add("e986");
add("f240l");
add("f240s");
add("v9815");
add("nx403a");
add("f310l");
add("f310lr");
add("onem7");
add("onemax");
add("pn071");
add("htc6500lvw");
add("butterflys");
add("mi2s");
add("n1");
}};
/** /**
* Creates a HardwareVideoEncoderFactory that supports surface texture encoding. * Creates a HardwareVideoEncoderFactory that supports surface texture encoding.
* *
@ -249,13 +192,9 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
// Returns true if the given MediaCodecInfo indicates a hardware module that is supported on the // Returns true if the given MediaCodecInfo indicates a hardware module that is supported on the
// current SDK. // current SDK.
private static String getModel() {
return Build.MODEL != null ? Build.MODEL.toLowerCase().replace(" ", "") : "nomodel";
}
private boolean isHardwareSupportedInCurrentSdk(MediaCodecInfo info, VideoCodecMimeType type) { private boolean isHardwareSupportedInCurrentSdk(MediaCodecInfo info, VideoCodecMimeType type) {
if (HW_EXCEPTION_MODELS.contains(getModel())) { Instance.ServerConfig config = Instance.getGlobalServerConfig();
if (!config.enable_h264_encoder && !config.enable_h265_encoder && !config.enable_vp8_encoder && !config.enable_vp9_encoder) {
return false; return false;
} }
switch (type) { switch (type) {
@ -272,7 +211,7 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
} }
private boolean isHardwareSupportedInCurrentSdkVp8(MediaCodecInfo info) { private boolean isHardwareSupportedInCurrentSdkVp8(MediaCodecInfo info) {
if (VP8_HW_EXCEPTION_MODELS.contains(getModel())) { if (!Instance.getGlobalServerConfig().enable_vp8_encoder) {
return false; return false;
} }
String name = info.getName(); String name = info.getName();
@ -288,6 +227,9 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
} }
private boolean isHardwareSupportedInCurrentSdkVp9(MediaCodecInfo info) { private boolean isHardwareSupportedInCurrentSdkVp9(MediaCodecInfo info) {
if (!Instance.getGlobalServerConfig().enable_vp9_encoder) {
return false;
}
String name = info.getName(); String name = info.getName();
return (name.startsWith(QCOM_PREFIX) || name.startsWith(EXYNOS_PREFIX) || name.startsWith(HISI_PREFIX)) return (name.startsWith(QCOM_PREFIX) || name.startsWith(EXYNOS_PREFIX) || name.startsWith(HISI_PREFIX))
// Both QCOM and Exynos VP9 encoders are supported in N or later. // Both QCOM and Exynos VP9 encoders are supported in N or later.
@ -295,8 +237,7 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
} }
private boolean isHardwareSupportedInCurrentSdkH264(MediaCodecInfo info) { private boolean isHardwareSupportedInCurrentSdkH264(MediaCodecInfo info) {
// First, H264 hardware might perform poorly on this model. if (!Instance.getGlobalServerConfig().enable_h264_encoder) {
if (H264_HW_EXCEPTION_MODELS.contains(getModel())) {
return false; return false;
} }
String name = info.getName(); String name = info.getName();
@ -308,6 +249,9 @@ public class HardwareVideoEncoderFactory implements VideoEncoderFactory {
} }
private boolean isHardwareSupportedInCurrentSdkH265(MediaCodecInfo info) { private boolean isHardwareSupportedInCurrentSdkH265(MediaCodecInfo info) {
if (!Instance.getGlobalServerConfig().enable_h265_encoder) {
return false;
}
String name = info.getName(); String name = info.getName();
// QCOM H265 encoder is supported in KITKAT or later. // QCOM H265 encoder is supported in KITKAT or later.
return (name.startsWith(QCOM_PREFIX) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) return (name.startsWith(QCOM_PREFIX) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)

Binary file not shown.

After

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 516 B

View file

@ -3023,6 +3023,8 @@
<string name="NoCallLog">You haven\'t made any calls yet.</string> <string name="NoCallLog">You haven\'t made any calls yet.</string>
<string name="VoipPeerIncompatible">**%1$s**\'s app is using an incompatible protocol. They need to update their app before you can call them.</string> <string name="VoipPeerIncompatible">**%1$s**\'s app is using an incompatible protocol. They need to update their app before you can call them.</string>
<string name="VoipPeerOutdated">**%1$s**\'s app does not support calls. They need to update their app before you can call them.</string> <string name="VoipPeerOutdated">**%1$s**\'s app does not support calls. They need to update their app before you can call them.</string>
<string name="VoipPeerVideoOutdated">Sorry, **%1$s** is using an old version of Telegram that doesn\'t support video calls.</string>
<string name="VoipPeerVideoOutdatedMakeVoice">Make a voice call</string>
<string name="VoipRateCallAlert">Please rate the quality of your Telegram call</string> <string name="VoipRateCallAlert">Please rate the quality of your Telegram call</string>
<string name="VoipNeedMicPermission">Telegram needs access to your microphone so that you can make calls.</string> <string name="VoipNeedMicPermission">Telegram needs access to your microphone so that you can make calls.</string>
<string name="VoipNeedMicCameraPermission">Telegram needs access to your microphone and camera so that you can make video calls.</string> <string name="VoipNeedMicCameraPermission">Telegram needs access to your microphone and camera so that you can make video calls.</string>
@ -3065,6 +3067,8 @@
<string name="RateCallSilentLocal">I couldn\'t hear the other side</string> <string name="RateCallSilentLocal">I couldn\'t hear the other side</string>
<string name="RateCallSilentRemote">The other side couldn\'t hear me</string> <string name="RateCallSilentRemote">The other side couldn\'t hear me</string>
<string name="RateCallDropped">Call ended unexpectedly</string> <string name="RateCallDropped">Call ended unexpectedly</string>
<string name="RateCallVideoDistorted">Video was distorted</string>
<string name="RateCallVideoPixelated">Video was pixelated</string>
<string name="TapToTurnCamera">Tap here to turn on your camera</string> <string name="TapToTurnCamera">Tap here to turn on your camera</string>
<string name="VoipUnmute">Unmute</string> <string name="VoipUnmute">Unmute</string>
<string name="VoipMute">Mute</string> <string name="VoipMute">Mute</string>
@ -3676,4 +3680,5 @@
<string name="RemindTodayAt">\'Remind today at\' HH:mm</string> <string name="RemindTodayAt">\'Remind today at\' HH:mm</string>
<string name="RemindDayAt">\'Remind on\' MMM d \'at\' HH:mm</string> <string name="RemindDayAt">\'Remind on\' MMM d \'at\' HH:mm</string>
<string name="RemindDayYearAt">\'Remind on\' MMM d yyyy \'at\' HH:mm</string> <string name="RemindDayYearAt">\'Remind on\' MMM d yyyy \'at\' HH:mm</string>
<string name="VoipReconnecting">Reconnecting</string>
</resources> </resources>