mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-10-09 03:20:48 +00:00
Merge branch 'master' of gitlab.com:peter-iakovlev/telegram-ios into mac-video-calls-temp
# Conflicts: # submodules/TgVoipWebrtc/tgcalls
This commit is contained in:
commit
9b3f279e8c
2
Makefile
2
Makefile
@ -3,7 +3,7 @@
|
||||
include Utils.makefile
|
||||
|
||||
|
||||
APP_VERSION="7.0"
|
||||
APP_VERSION="7.0.1"
|
||||
CORE_COUNT=$(shell sysctl -n hw.logicalcpu)
|
||||
CORE_COUNT_MINUS_ONE=$(shell expr ${CORE_COUNT} \- 1)
|
||||
|
||||
|
@ -1 +1 @@
|
||||
LS3VfNVetXNy6mHmek8hegOh0wsvmJs0hcrc7PLA9eI=
|
||||
NC8Ilqd9zpOXIij3OOYFUJxDucj8mEwygMYgxbeBpE0=
|
||||
|
@ -99,15 +99,15 @@ public func childWindowHostView(parent: UIView) -> WindowHostView {
|
||||
}
|
||||
|
||||
view.invalidateDeferScreenEdgeGestureImpl = { [weak hostView] in
|
||||
return hostView?.invalidateDeferScreenEdgeGesture?()
|
||||
hostView?.invalidateDeferScreenEdgeGesture?()
|
||||
}
|
||||
|
||||
view.invalidatePrefersOnScreenNavigationHiddenImpl = { [weak hostView] in
|
||||
return hostView?.invalidatePrefersOnScreenNavigationHidden?()
|
||||
hostView?.invalidatePrefersOnScreenNavigationHidden?()
|
||||
}
|
||||
|
||||
view.invalidateSupportedOrientationsImpl = { [weak hostView] in
|
||||
return hostView?.invalidateSupportedOrientations?()
|
||||
hostView?.invalidateSupportedOrientations?()
|
||||
}
|
||||
|
||||
view.cancelInteractiveKeyboardGesturesImpl = { [weak hostView] in
|
||||
|
@ -409,15 +409,15 @@ public func nativeWindowHostView() -> (UIWindow & WindowHost, WindowHostView) {
|
||||
}
|
||||
|
||||
window.invalidateDeferScreenEdgeGestureImpl = { [weak hostView] in
|
||||
return hostView?.invalidateDeferScreenEdgeGesture?()
|
||||
hostView?.invalidateDeferScreenEdgeGesture?()
|
||||
}
|
||||
|
||||
window.invalidatePrefersOnScreenNavigationHiddenImpl = { [weak hostView] in
|
||||
return hostView?.invalidatePrefersOnScreenNavigationHidden?()
|
||||
hostView?.invalidatePrefersOnScreenNavigationHidden?()
|
||||
}
|
||||
|
||||
window.invalidateSupportedOrientationsImpl = { [weak hostView] in
|
||||
return hostView?.invalidateSupportedOrientations?()
|
||||
hostView?.invalidateSupportedOrientations?()
|
||||
}
|
||||
|
||||
window.cancelInteractiveKeyboardGesturesImpl = { [weak hostView] in
|
||||
|
@ -100,7 +100,7 @@
|
||||
};
|
||||
|
||||
[model.interfaceView updateSelectionInterface:selectionContext.count counterVisible:(selectionContext.count > 0) animated:false];
|
||||
model.interfaceView.donePressed = ^(TGClipboardGalleryPhotoItem *item)
|
||||
model.interfaceView.donePressed = ^(id<TGModernGalleryItem> item)
|
||||
{
|
||||
__strong TGClipboardGalleryMixin *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -109,18 +109,18 @@
|
||||
strongSelf->_galleryModel.dismiss(true, false);
|
||||
|
||||
if (strongSelf.completeWithItem != nil)
|
||||
strongSelf.completeWithItem(item);
|
||||
strongSelf.completeWithItem((TGClipboardGalleryPhotoItem *)item);
|
||||
};
|
||||
|
||||
modernGallery.model = model;
|
||||
modernGallery.itemFocused = ^(TGClipboardGalleryPhotoItem *item)
|
||||
modernGallery.itemFocused = ^(id<TGModernGalleryItem> item)
|
||||
{
|
||||
__strong TGClipboardGalleryMixin *strongSelf = weakSelf;
|
||||
if (strongSelf != nil && strongSelf.itemFocused != nil)
|
||||
strongSelf.itemFocused(item);
|
||||
strongSelf.itemFocused((TGClipboardGalleryPhotoItem *)item);
|
||||
};
|
||||
|
||||
modernGallery.beginTransitionIn = ^UIView *(TGClipboardGalleryPhotoItem *item, TGModernGalleryItemView *itemView)
|
||||
modernGallery.beginTransitionIn = ^UIView *(id<TGModernGalleryItem> item, TGModernGalleryItemView *itemView)
|
||||
{
|
||||
__strong TGClipboardGalleryMixin *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -130,12 +130,12 @@
|
||||
strongSelf.willTransitionIn();
|
||||
|
||||
if (strongSelf.referenceViewForItem != nil)
|
||||
return strongSelf.referenceViewForItem(item);
|
||||
return strongSelf.referenceViewForItem((TGClipboardGalleryPhotoItem *)item);
|
||||
|
||||
return nil;
|
||||
};
|
||||
|
||||
modernGallery.finishedTransitionIn = ^(__unused TGClipboardGalleryPhotoItem *item, __unused TGModernGalleryItemView *itemView)
|
||||
modernGallery.finishedTransitionIn = ^(__unused id<TGModernGalleryItem> item, __unused TGModernGalleryItemView *itemView)
|
||||
{
|
||||
__strong TGClipboardGalleryMixin *strongSelf = weakSelf;
|
||||
if (strongSelf == nil)
|
||||
@ -144,7 +144,7 @@
|
||||
[strongSelf->_galleryModel.interfaceView setSelectedItemsModel:strongSelf->_galleryModel.selectedItemsModel];
|
||||
};
|
||||
|
||||
modernGallery.beginTransitionOut = ^UIView *(TGClipboardGalleryPhotoItem *item, TGModernGalleryItemView *itemView)
|
||||
modernGallery.beginTransitionOut = ^UIView *(id<TGModernGalleryItem> item, TGModernGalleryItemView *itemView)
|
||||
{
|
||||
__strong TGClipboardGalleryMixin *strongSelf = weakSelf;
|
||||
if (strongSelf != nil)
|
||||
@ -153,7 +153,7 @@
|
||||
strongSelf.willTransitionOut();
|
||||
|
||||
if (strongSelf.referenceViewForItem != nil)
|
||||
return strongSelf.referenceViewForItem(item);
|
||||
return strongSelf.referenceViewForItem((TGClipboardGalleryPhotoItem *)item);
|
||||
}
|
||||
return nil;
|
||||
};
|
||||
|
@ -100,7 +100,7 @@
|
||||
|
||||
[strongSelf setCurrentItemWithIndex:index];
|
||||
};
|
||||
_interfaceView.captionSet = ^(id<TGModernGalleryEditableItem> item, NSString *caption, NSArray *entities)
|
||||
_interfaceView.captionSet = ^(id<TGModernGalleryItem> item, NSString *caption, NSArray *entities)
|
||||
{
|
||||
__strong TGClipboardGalleryModel *strongSelf = weakSelf;
|
||||
if (strongSelf == nil || strongSelf.saveItemCaption == nil)
|
||||
|
@ -359,10 +359,11 @@
|
||||
NSString *text = nil;
|
||||
__block bool hasPhoto = false;
|
||||
__block bool hasVideo = false;
|
||||
[strongSelf->_selectionContext enumerateSelectedItems:^(TGMediaAsset *asset) {
|
||||
if (![asset isKindOfClass:[TGMediaAsset class]])
|
||||
[strongSelf->_selectionContext enumerateSelectedItems:^(id<TGMediaSelectableItem> asset) {
|
||||
NSObject *value = (NSObject *)asset;
|
||||
if (![value isKindOfClass:[TGMediaAsset class]])
|
||||
return;
|
||||
if (asset.isVideo) {
|
||||
if (((TGMediaAsset *)asset).isVideo) {
|
||||
hasVideo = true;
|
||||
} else {
|
||||
hasPhoto = true;
|
||||
|
@ -210,7 +210,7 @@
|
||||
|
||||
[strongSelf setCurrentItemWithIndex:index];
|
||||
};
|
||||
_interfaceView.captionSet = ^(id<TGModernGalleryEditableItem> item, NSString *caption, NSArray *entities)
|
||||
_interfaceView.captionSet = ^(id<TGModernGalleryItem> item, NSString *caption, NSArray *entities)
|
||||
{
|
||||
__strong TGMediaPickerGalleryModel *strongSelf = weakSelf;
|
||||
if (strongSelf == nil || strongSelf.saveItemCaption == nil)
|
||||
|
@ -172,7 +172,7 @@ private final class CallVideoNode: ASDisplayNode {
|
||||
self.currentCornerRadius = cornerRadius
|
||||
|
||||
var rotationAngle: CGFloat
|
||||
if isOutgoing {
|
||||
if isOutgoing && isCompactLayout {
|
||||
rotationAngle = CGFloat.pi / 2.0
|
||||
} else {
|
||||
switch self.currentOrientation {
|
||||
@ -181,9 +181,17 @@ private final class CallVideoNode: ASDisplayNode {
|
||||
case .rotation90:
|
||||
rotationAngle = CGFloat.pi / 2.0
|
||||
case .rotation180:
|
||||
rotationAngle = CGFloat.pi
|
||||
if isCompactLayout {
|
||||
rotationAngle = CGFloat.pi
|
||||
} else {
|
||||
rotationAngle = 0.0
|
||||
}
|
||||
case .rotation270:
|
||||
rotationAngle = -CGFloat.pi / 2.0
|
||||
if isCompactLayout {
|
||||
rotationAngle = -CGFloat.pi / 2.0
|
||||
} else {
|
||||
rotationAngle = CGFloat.pi / 2.0
|
||||
}
|
||||
}
|
||||
|
||||
var additionalAngle: CGFloat = 0.0
|
||||
@ -1274,16 +1282,48 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro
|
||||
insets.left = interpolate(from: expandedInset, to: insets.left, value: 1.0 - self.pictureInPictureTransitionFraction)
|
||||
insets.right = interpolate(from: expandedInset, to: insets.right, value: 1.0 - self.pictureInPictureTransitionFraction)
|
||||
|
||||
let previewVideoSide = interpolate(from: 350.0, to: 200.0, value: 1.0 - self.pictureInPictureTransitionFraction)
|
||||
let previewVideoSide = interpolate(from: 300.0, to: 150.0, value: 1.0 - self.pictureInPictureTransitionFraction)
|
||||
var previewVideoSize = layout.size.aspectFitted(CGSize(width: previewVideoSide, height: previewVideoSide))
|
||||
previewVideoSize = CGSize(width: 30.0, height: 45.0).aspectFitted(previewVideoSize)
|
||||
if let minimizedVideoNode = self.minimizedVideoNode {
|
||||
switch minimizedVideoNode.currentOrientation {
|
||||
case .rotation90, .rotation270:
|
||||
break
|
||||
default:
|
||||
previewVideoSize = CGSize(width: previewVideoSize.height, height: previewVideoSize.width)
|
||||
var aspect = minimizedVideoNode.currentAspect
|
||||
var rotationCount = 0
|
||||
if minimizedVideoNode === self.outgoingVideoNodeValue {
|
||||
aspect = 3.0 / 4.0
|
||||
} else {
|
||||
if aspect < 1.0 {
|
||||
aspect = 3.0 / 4.0
|
||||
} else {
|
||||
aspect = 4.0 / 3.0
|
||||
}
|
||||
|
||||
switch minimizedVideoNode.currentOrientation {
|
||||
case .rotation90, .rotation270:
|
||||
rotationCount += 1
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
var mappedDeviceOrientation = self.deviceOrientation
|
||||
if case .regular = layout.metrics.widthClass, case .regular = layout.metrics.heightClass {
|
||||
mappedDeviceOrientation = .portrait
|
||||
}
|
||||
|
||||
switch mappedDeviceOrientation {
|
||||
case .landscapeLeft, .landscapeRight:
|
||||
rotationCount += 1
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
if rotationCount % 2 != 0 {
|
||||
aspect = 1.0 / aspect
|
||||
}
|
||||
}
|
||||
|
||||
let unboundVideoSize = CGSize(width: aspect * 10000.0, height: 10000.0)
|
||||
|
||||
previewVideoSize = unboundVideoSize.aspectFitted(CGSize(width: previewVideoSide, height: previewVideoSide))
|
||||
}
|
||||
let previewVideoY: CGFloat
|
||||
let previewVideoX: CGFloat
|
||||
@ -1530,7 +1570,7 @@ final class CallControllerNode: ViewControllerTracingNode, CallControllerNodePro
|
||||
self.animationForExpandedVideoSnapshotView = nil
|
||||
}
|
||||
minimizedVideoTransition.updateFrame(node: minimizedVideoNode, frame: previewVideoFrame)
|
||||
minimizedVideoNode.updateLayout(size: previewVideoFrame.size, cornerRadius: interpolate(from: 14.0, to: 24.0, value: self.pictureInPictureTransitionFraction), isOutgoing: minimizedVideoNode === self.outgoingVideoNodeValue, deviceOrientation: .portrait, isCompactLayout: false, transition: minimizedVideoTransition)
|
||||
minimizedVideoNode.updateLayout(size: previewVideoFrame.size, cornerRadius: interpolate(from: 14.0, to: 24.0, value: self.pictureInPictureTransitionFraction), isOutgoing: minimizedVideoNode === self.outgoingVideoNodeValue, deviceOrientation: mappedDeviceOrientation, isCompactLayout: false, transition: minimizedVideoTransition)
|
||||
if transition.isAnimated && didAppear {
|
||||
minimizedVideoNode.layer.animateSpring(from: 0.1 as NSNumber, to: 1.0 as NSNumber, keyPath: "transform.scale", duration: 0.5)
|
||||
}
|
||||
|
@ -246,6 +246,7 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
private var droppedCall = false
|
||||
private var dropCallKitCallTimer: SwiftSignalKit.Timer?
|
||||
|
||||
private var useFrontCamera: Bool = true
|
||||
private var videoCapturer: OngoingCallVideoCapturer?
|
||||
|
||||
init(
|
||||
@ -1029,6 +1030,7 @@ public final class PresentationCallImpl: PresentationCall {
|
||||
}
|
||||
|
||||
public func switchVideoCamera() {
|
||||
self.videoCapturer?.switchCamera()
|
||||
self.useFrontCamera = !self.useFrontCamera
|
||||
self.videoCapturer?.switchVideoInput(isFront: self.useFrontCamera)
|
||||
}
|
||||
}
|
||||
|
@ -323,8 +323,8 @@ public func searchMessages(account: Account, location: SearchMessagesLocation, q
|
||||
|> mapToSignal { result, additionalResult -> Signal<(SearchMessagesResult, SearchMessagesState), NoError> in
|
||||
return account.postbox.transaction { transaction -> (SearchMessagesResult, SearchMessagesState) in
|
||||
var additional: SearchMessagesPeerState? = mergedState(transaction: transaction, state: state?.additional, result: additionalResult)
|
||||
if state?.additional == nil, case .general = location {
|
||||
let secretMessages = transaction.searchMessages(peerId: nil, query: query, tags: nil)
|
||||
if state?.additional == nil, case let .general(tags) = location {
|
||||
let secretMessages = transaction.searchMessages(peerId: nil, query: query, tags: tags)
|
||||
var readStates: [PeerId: CombinedPeerReadState] = [:]
|
||||
for message in secretMessages {
|
||||
if let readState = transaction.getCombinedPeerReadState(message.id.peerId) {
|
||||
|
@ -336,8 +336,8 @@ public final class OngoingCallVideoCapturer {
|
||||
self.impl = OngoingCallThreadLocalContextVideoCapturer()
|
||||
}
|
||||
|
||||
public func switchCamera() {
|
||||
self.impl.switchVideoCamera()
|
||||
public func switchVideoInput(isFront: Bool) {
|
||||
self.impl.switchVideoInput(isFront)
|
||||
}
|
||||
|
||||
public func makeOutgoingVideoView(completion: @escaping (OngoingCallContextPresentationCallVideoView?) -> Void) {
|
||||
|
@ -95,23 +95,25 @@ typedef NS_ENUM(int32_t, OngoingCallDataSavingWebrtc) {
|
||||
@protocol OngoingCallThreadLocalContextWebrtcVideoView <NSObject>
|
||||
|
||||
@property (nonatomic, readonly) OngoingCallVideoOrientationWebrtc orientation;
|
||||
@property (nonatomic, readonly) CGFloat aspect;
|
||||
|
||||
- (void)setOnFirstFrameReceived:(void (^ _Nullable)(float))onFirstFrameReceived;
|
||||
- (void)setOnOrientationUpdated:(void (^ _Nullable)(OngoingCallVideoOrientationWebrtc))onOrientationUpdated;
|
||||
- (void)setOnOrientationUpdated:(void (^ _Nullable)(OngoingCallVideoOrientationWebrtc, CGFloat))onOrientationUpdated;
|
||||
- (void)setOnIsMirroredUpdated:(void (^ _Nullable)(bool))onIsMirroredUpdated;
|
||||
#ifdef WEBRTC_MAC
|
||||
#if defined(WEBRTC_MAC) && !defined(WEBRTC_IOS)
|
||||
- (void)setVideoContentMode:(CALayerContentsGravity _Nonnull )mode;
|
||||
- (void)setForceMirrored:(bool)forceMirrored;
|
||||
#endif
|
||||
@end
|
||||
|
||||
@interface OngoingCallThreadLocalContextVideoCapturer : NSObject
|
||||
|
||||
- (instancetype _Nonnull)init;
|
||||
- (instancetype _Nonnull)initWithDeviceId:(NSString * _Nonnull)deviceId;
|
||||
|
||||
- (void)switchVideoCamera;
|
||||
- (void)switchVideoInput:(NSString * _Nonnull)deviceId;
|
||||
- (void)setIsVideoEnabled:(bool)isVideoEnabled;
|
||||
- (void)enableScreenCast;
|
||||
- (void)disableScreenCast;
|
||||
|
||||
- (void)makeOutgoingVideoView:(void (^_Nonnull)(UIView<OngoingCallThreadLocalContextWebrtcVideoView> * _Nullable))completion;
|
||||
|
||||
@end
|
||||
@ -126,7 +128,7 @@ typedef NS_ENUM(int32_t, OngoingCallDataSavingWebrtc) {
|
||||
@property (nonatomic, copy) void (^ _Nullable stateChanged)(OngoingCallStateWebrtc, OngoingCallVideoStateWebrtc, OngoingCallRemoteVideoStateWebrtc, OngoingCallRemoteAudioStateWebrtc, OngoingCallRemoteBatteryLevelWebrtc, float);
|
||||
@property (nonatomic, copy) void (^ _Nullable signalBarsChanged)(int32_t);
|
||||
|
||||
- (instancetype _Nonnull)initWithVersion:(NSString * _Nonnull)version queue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing connections:(NSArray<OngoingCallConnectionDescriptionWebrtc *> * _Nonnull)connections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath sendSignalingData:(void (^ _Nonnull)(NSData * _Nonnull))sendSignalingData videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer preferredAspectRatio:(float)preferredAspectRatio enableHighBitrateVideoCalls:(bool)enableHighBitrateVideoCalls;
|
||||
- (instancetype _Nonnull)initWithVersion:(NSString * _Nonnull)version queue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing connections:(NSArray<OngoingCallConnectionDescriptionWebrtc *> * _Nonnull)connections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P allowTCP:(BOOL)allowTCP enableStunMarking:(BOOL)enableStunMarking logPath:(NSString * _Nonnull)logPath statsLogPath:(NSString * _Nonnull)statsLogPath sendSignalingData:(void (^ _Nonnull)(NSData * _Nonnull))sendSignalingData videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer preferredVideoCodec:(NSString * _Nullable)preferredVideoCodec;
|
||||
|
||||
- (void)beginTermination;
|
||||
- (void)stop:(void (^_Nullable)(NSString * _Nullable debugLog, int64_t bytesSentWifi, int64_t bytesReceivedWifi, int64_t bytesSentMobile, int64_t bytesReceivedMobile))completion;
|
||||
@ -142,6 +144,7 @@ typedef NS_ENUM(int32_t, OngoingCallDataSavingWebrtc) {
|
||||
- (void)setNetworkType:(OngoingCallNetworkTypeWebrtc)networkType;
|
||||
- (void)makeIncomingVideoView:(void (^_Nonnull)(UIView<OngoingCallThreadLocalContextWebrtcVideoView> * _Nullable))completion;
|
||||
- (void)requestVideo:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer;
|
||||
- (void)setRequestedVideoAspect:(float)aspect;
|
||||
- (void)disableVideo;
|
||||
- (void)addSignalingData:(NSData * _Nonnull)data;
|
||||
|
||||
|
@ -49,12 +49,14 @@
|
||||
@protocol OngoingCallThreadLocalContextWebrtcVideoViewImpl <NSObject>
|
||||
|
||||
@property (nonatomic, readwrite) OngoingCallVideoOrientationWebrtc orientation;
|
||||
@property (nonatomic, readonly) CGFloat aspect;
|
||||
|
||||
@end
|
||||
|
||||
@interface VideoMetalView (VideoViewImpl) <OngoingCallThreadLocalContextWebrtcVideoView, OngoingCallThreadLocalContextWebrtcVideoViewImpl>
|
||||
|
||||
@property (nonatomic, readwrite) OngoingCallVideoOrientationWebrtc orientation;
|
||||
@property (nonatomic, readonly) CGFloat aspect;
|
||||
|
||||
@end
|
||||
|
||||
@ -64,14 +66,18 @@
|
||||
return (OngoingCallVideoOrientationWebrtc)self.internalOrientation;
|
||||
}
|
||||
|
||||
- (CGFloat)aspect {
|
||||
return self.internalAspect;
|
||||
}
|
||||
|
||||
- (void)setOrientation:(OngoingCallVideoOrientationWebrtc)orientation {
|
||||
[self setInternalOrientation:(int)orientation];
|
||||
}
|
||||
|
||||
- (void)setOnOrientationUpdated:(void (^ _Nullable)(OngoingCallVideoOrientationWebrtc))onOrientationUpdated {
|
||||
- (void)setOnOrientationUpdated:(void (^ _Nullable)(OngoingCallVideoOrientationWebrtc, CGFloat))onOrientationUpdated {
|
||||
if (onOrientationUpdated) {
|
||||
[self internalSetOnOrientationUpdated:^(int value) {
|
||||
onOrientationUpdated((OngoingCallVideoOrientationWebrtc)value);
|
||||
[self internalSetOnOrientationUpdated:^(int value, CGFloat aspect) {
|
||||
onOrientationUpdated((OngoingCallVideoOrientationWebrtc)value, aspect);
|
||||
}];
|
||||
} else {
|
||||
[self internalSetOnOrientationUpdated:nil];
|
||||
@ -93,6 +99,7 @@
|
||||
@interface GLVideoView (VideoViewImpl) <OngoingCallThreadLocalContextWebrtcVideoView, OngoingCallThreadLocalContextWebrtcVideoViewImpl>
|
||||
|
||||
@property (nonatomic, readwrite) OngoingCallVideoOrientationWebrtc orientation;
|
||||
@property (nonatomic, readonly) CGFloat aspect;
|
||||
|
||||
@end
|
||||
|
||||
@ -102,14 +109,18 @@
|
||||
return (OngoingCallVideoOrientationWebrtc)self.internalOrientation;
|
||||
}
|
||||
|
||||
- (CGFloat)aspect {
|
||||
return self.internalAspect;
|
||||
}
|
||||
|
||||
- (void)setOrientation:(OngoingCallVideoOrientationWebrtc)orientation {
|
||||
[self setInternalOrientation:(int)orientation];
|
||||
}
|
||||
|
||||
- (void)setOnOrientationUpdated:(void (^ _Nullable)(OngoingCallVideoOrientationWebrtc))onOrientationUpdated {
|
||||
- (void)setOnOrientationUpdated:(void (^ _Nullable)(OngoingCallVideoOrientationWebrtc, CGFloat))onOrientationUpdated {
|
||||
if (onOrientationUpdated) {
|
||||
[self internalSetOnOrientationUpdated:^(int value) {
|
||||
onOrientationUpdated((OngoingCallVideoOrientationWebrtc)value);
|
||||
[self internalSetOnOrientationUpdated:^(int value, CGFloat aspect) {
|
||||
onOrientationUpdated((OngoingCallVideoOrientationWebrtc)value, aspect);
|
||||
}];
|
||||
} else {
|
||||
[self internalSetOnOrientationUpdated:nil];
|
||||
@ -131,25 +142,23 @@
|
||||
@implementation OngoingCallThreadLocalContextVideoCapturer
|
||||
|
||||
- (instancetype _Nonnull)init {
|
||||
return [self initWithDeviceId:@""];
|
||||
}
|
||||
|
||||
- (instancetype _Nonnull)initWithDeviceId:(NSString * _Nonnull)deviceId {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_interface = tgcalls::VideoCaptureInterface::Create();
|
||||
_interface = tgcalls::VideoCaptureInterface::Create(deviceId.UTF8String);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
- (void)dealloc {
|
||||
}
|
||||
|
||||
- (void)switchVideoCamera {
|
||||
_interface->switchCamera();
|
||||
}
|
||||
|
||||
-(void)enableScreenCast {
|
||||
_interface->enableScreenCast();
|
||||
}
|
||||
- (void)disableScreenCast {
|
||||
_interface->disableScreenCast();
|
||||
- (void)switchVideoInput:(NSString * _Nonnull)deviceeId {
|
||||
_interface->switchToDevice(deviceeId.UTF8String);
|
||||
}
|
||||
|
||||
- (void)setIsVideoEnabled:(bool)isVideoEnabled {
|
||||
@ -166,9 +175,7 @@
|
||||
if ([VideoMetalView isSupported]) {
|
||||
VideoMetalView *remoteRenderer = [[VideoMetalView alloc] initWithFrame:CGRectZero];
|
||||
remoteRenderer.videoContentMode = UIViewContentModeScaleAspectFill;
|
||||
#if !TARGET_OS_IPHONE
|
||||
[remoteRenderer setIsForceMirrored:YES];
|
||||
#endif
|
||||
|
||||
std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink = [remoteRenderer getSink];
|
||||
interface->setOutput(sink);
|
||||
|
||||
@ -176,10 +183,6 @@
|
||||
} else {
|
||||
GLVideoView *remoteRenderer = [[GLVideoView alloc] initWithFrame:CGRectZero];
|
||||
|
||||
remoteRenderer.videoContentMode = UIViewContentModeScaleAspectFill;
|
||||
#if !TARGET_OS_IPHONE
|
||||
[remoteRenderer setIsForceMirrored:YES];
|
||||
#endif
|
||||
std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink = [remoteRenderer getSink];
|
||||
interface->setOutput(sink);
|
||||
|
||||
@ -220,7 +223,7 @@
|
||||
NSTimeInterval _callPacketTimeout;
|
||||
|
||||
std::unique_ptr<tgcalls::Instance> _tgVoip;
|
||||
OngoingCallThreadLocalContextWebrtcTerminationResult *_terminationResult;
|
||||
bool _didStop;
|
||||
|
||||
OngoingCallStateWebrtc _state;
|
||||
OngoingCallVideoStateWebrtc _videoState;
|
||||
@ -238,7 +241,6 @@
|
||||
void (^_sendSignalingData)(NSData *);
|
||||
|
||||
float _remotePreferredAspectRatio;
|
||||
|
||||
}
|
||||
|
||||
- (void)controllerStateChanged:(tgcalls::State)state;
|
||||
@ -312,15 +314,21 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
||||
return 92;
|
||||
}
|
||||
|
||||
+ (NSArray<NSString *> * _Nonnull)versionsWithIncludeReference:(bool)includeReference {
|
||||
if (includeReference) {
|
||||
return @[@"2.7.7", @"2.8.8"];
|
||||
+ (NSArray<NSString *> * _Nonnull)versionsWithIncludeReference:(bool)__unused includeReference {
|
||||
return @[@"2.7.7", @"3.0.0"];
|
||||
}
|
||||
|
||||
+ (tgcalls::ProtocolVersion)protocolVersionFromLibraryVersion:(NSString *)version {
|
||||
if ([version isEqualToString:@"2.7.7"]) {
|
||||
return tgcalls::ProtocolVersion::V0;
|
||||
} else if ([version isEqualToString:@"3.0.0"]) {
|
||||
return tgcalls::ProtocolVersion::V1;
|
||||
} else {
|
||||
return @[@"2.7.7"];
|
||||
return tgcalls::ProtocolVersion::V0;
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype _Nonnull)initWithVersion:(NSString * _Nonnull)version queue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing connections:(NSArray<OngoingCallConnectionDescriptionWebrtc *> * _Nonnull)connections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath sendSignalingData:(void (^)(NSData * _Nonnull))sendSignalingData videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer preferredAspectRatio:(float)preferredAspectRatio enableHighBitrateVideoCalls:(bool)enableHighBitrateVideoCalls {
|
||||
- (instancetype _Nonnull)initWithVersion:(NSString * _Nonnull)version queue:(id<OngoingCallThreadLocalContextQueueWebrtc> _Nonnull)queue proxy:(VoipProxyServerWebrtc * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtc)networkType dataSaving:(OngoingCallDataSavingWebrtc)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing connections:(NSArray<OngoingCallConnectionDescriptionWebrtc *> * _Nonnull)connections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P allowTCP:(BOOL)allowTCP enableStunMarking:(BOOL)enableStunMarking logPath:(NSString * _Nonnull)logPath statsLogPath:(NSString * _Nonnull)statsLogPath sendSignalingData:(void (^)(NSData * _Nonnull))sendSignalingData videoCapturer:(OngoingCallThreadLocalContextVideoCapturer * _Nullable)videoCapturer preferredVideoCodec:(NSString * _Nullable)preferredVideoCodec {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_version = version;
|
||||
@ -383,6 +391,11 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> preferredVideoCodecs;
|
||||
if (preferredVideoCodec != nil) {
|
||||
preferredVideoCodecs.push_back([preferredVideoCodec UTF8String]);
|
||||
}
|
||||
|
||||
std::vector<tgcalls::Endpoint> endpoints;
|
||||
|
||||
tgcalls::Config config = {
|
||||
@ -390,14 +403,18 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
||||
.receiveTimeout = _callPacketTimeout,
|
||||
.dataSaving = callControllerDataSavingForType(dataSaving),
|
||||
.enableP2P = (bool)allowP2P,
|
||||
.allowTCP = (bool)allowTCP,
|
||||
.enableStunMarking = (bool)enableStunMarking,
|
||||
.enableAEC = false,
|
||||
.enableNS = true,
|
||||
.enableAGC = true,
|
||||
.enableCallUpgrade = false,
|
||||
.logPath = "",//logPath.length == 0 ? "" : std::string(logPath.UTF8String),
|
||||
.logPath = logPath.length == 0 ? "" : std::string(logPath.UTF8String),
|
||||
.statsLogPath = statsLogPath.length == 0 ? "" : std::string(statsLogPath.UTF8String),
|
||||
.maxApiLayer = [OngoingCallThreadLocalContextWebrtc maxLayer],
|
||||
.preferredAspectRatio = preferredAspectRatio,
|
||||
.enableHighBitrateVideo = enableHighBitrateVideoCalls
|
||||
.enableHighBitrateVideo = true,
|
||||
.preferredVideoCodecs = preferredVideoCodecs,
|
||||
.protocolVersion = [OngoingCallThreadLocalContextWebrtc protocolVersionFromLibraryVersion:version]
|
||||
};
|
||||
|
||||
auto encryptionKeyValue = std::make_shared<std::array<uint8_t, 256>>();
|
||||
@ -409,7 +426,6 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
tgcalls::Register<tgcalls::InstanceImpl>();
|
||||
tgcalls::Register<tgcalls::InstanceImplReference>();
|
||||
});
|
||||
_tgVoip = tgcalls::Meta::Create([version UTF8String], (tgcalls::Descriptor){
|
||||
.config = config,
|
||||
@ -542,29 +558,16 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
- (void)stopInstanceIfNeeded {
|
||||
if (!_tgVoip) {
|
||||
return;
|
||||
}
|
||||
tgcalls::FinalState finalState = _tgVoip->stop();
|
||||
_tgVoip.reset();
|
||||
_terminationResult = [[OngoingCallThreadLocalContextWebrtcTerminationResult alloc] initWithFinalState:finalState];
|
||||
}
|
||||
|
||||
- (void)beginTermination {
|
||||
[self stopInstanceIfNeeded];
|
||||
}
|
||||
|
||||
- (void)stop:(void (^)(NSString *, int64_t, int64_t, int64_t, int64_t))completion {
|
||||
[self stopInstanceIfNeeded];
|
||||
|
||||
+ (void)stopWithTerminationResult:(OngoingCallThreadLocalContextWebrtcTerminationResult *)terminationResult completion:(void (^)(NSString *, int64_t, int64_t, int64_t, int64_t))completion {
|
||||
if (completion) {
|
||||
if (_terminationResult) {
|
||||
NSString *debugLog = [NSString stringWithUTF8String:_terminationResult.finalState.debugLog.c_str()];
|
||||
_lastDerivedState = [[NSData alloc] initWithBytes:_terminationResult.finalState.persistentState.value.data() length:_terminationResult.finalState.persistentState.value.size()];
|
||||
if (terminationResult) {
|
||||
NSString *debugLog = [NSString stringWithUTF8String:terminationResult.finalState.debugLog.c_str()];
|
||||
|
||||
if (completion) {
|
||||
completion(debugLog, _terminationResult.finalState.trafficStats.bytesSentWifi, _terminationResult.finalState.trafficStats.bytesReceivedWifi, _terminationResult.finalState.trafficStats.bytesSentMobile, _terminationResult.finalState.trafficStats.bytesReceivedMobile);
|
||||
completion(debugLog, terminationResult.finalState.trafficStats.bytesSentWifi, terminationResult.finalState.trafficStats.bytesReceivedWifi, terminationResult.finalState.trafficStats.bytesSentMobile, terminationResult.finalState.trafficStats.bytesReceivedMobile);
|
||||
}
|
||||
} else {
|
||||
if (completion) {
|
||||
@ -574,6 +577,36 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stop:(void (^)(NSString *, int64_t, int64_t, int64_t, int64_t))completion {
|
||||
if (!_tgVoip) {
|
||||
return;
|
||||
}
|
||||
if (completion == nil) {
|
||||
if (!_didStop) {
|
||||
_tgVoip->stop([](tgcalls::FinalState finalState) {
|
||||
});
|
||||
}
|
||||
_tgVoip.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
__weak OngoingCallThreadLocalContextWebrtc *weakSelf = self;
|
||||
id<OngoingCallThreadLocalContextQueueWebrtc> queue = _queue;
|
||||
_didStop = true;
|
||||
_tgVoip->stop([weakSelf, queue, completion = [completion copy]](tgcalls::FinalState finalState) {
|
||||
[queue dispatch:^{
|
||||
__strong OngoingCallThreadLocalContextWebrtc *strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
strongSelf->_tgVoip.reset();
|
||||
}
|
||||
|
||||
OngoingCallThreadLocalContextWebrtcTerminationResult *terminationResult = [[OngoingCallThreadLocalContextWebrtcTerminationResult alloc] initWithFinalState:finalState];
|
||||
|
||||
[OngoingCallThreadLocalContextWebrtc stopWithTerminationResult:terminationResult completion:completion];
|
||||
}];
|
||||
});
|
||||
}
|
||||
|
||||
- (NSString *)debugInfo {
|
||||
if (_tgVoip != nullptr) {
|
||||
NSString *version = [self version];
|
||||
@ -679,7 +712,7 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
||||
if ([VideoMetalView isSupported]) {
|
||||
VideoMetalView *remoteRenderer = [[VideoMetalView alloc] initWithFrame:CGRectZero];
|
||||
#if TARGET_OS_IPHONE
|
||||
remoteRenderer.videoContentMode = UIViewContentModeScaleAspectFill;
|
||||
remoteRenderer.videoContentMode = UIViewContentModeScaleToFill;
|
||||
#else
|
||||
remoteRenderer.videoContentMode = UIViewContentModeScaleAspect;
|
||||
#endif
|
||||
@ -695,11 +728,7 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
||||
completion(remoteRenderer);
|
||||
} else {
|
||||
GLVideoView *remoteRenderer = [[GLVideoView alloc] initWithFrame:CGRectZero];
|
||||
#if TARGET_OS_IPHONE
|
||||
remoteRenderer.videoContentMode = UIViewContentModeScaleAspectFill;
|
||||
#else
|
||||
remoteRenderer.videoContentMode = UIViewContentModeScaleAspect;
|
||||
#endif
|
||||
|
||||
std::shared_ptr<rtc::VideoSinkInterface<webrtc::VideoFrame>> sink = [remoteRenderer getSink];
|
||||
__strong OngoingCallThreadLocalContextWebrtc *strongSelf = weakSelf;
|
||||
if (strongSelf) {
|
||||
@ -726,6 +755,12 @@ static void (*InternalVoipLoggingFunction)(NSString *) = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setRequestedVideoAspect:(float)aspect {
|
||||
if (_tgVoip) {
|
||||
_tgVoip->setRequestedVideoAspect(aspect);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)disableVideo {
|
||||
if (_tgVoip) {
|
||||
_videoCapturer = nil;
|
||||
|
Loading…
x
Reference in New Issue
Block a user