fix compiling on 32bit.

// FREEBIE
This commit is contained in:
Michael Kirk 2017-10-04 11:00:59 -04:00
parent f171c56488
commit ff2f9ebaf0
6 changed files with 326 additions and 112 deletions

View File

@ -124,6 +124,7 @@
450873C71D9D867B006B54F2 /* OWSIncomingMessageCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 450873C61D9D867B006B54F2 /* OWSIncomingMessageCollectionViewCell.m */; };
450873C81D9D867B006B54F2 /* OWSIncomingMessageCollectionViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 450873C61D9D867B006B54F2 /* OWSIncomingMessageCollectionViewCell.m */; };
4509E79A1DD653700025A59F /* WebRTC.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4509E7991DD653700025A59F /* WebRTC.framework */; };
450D19131F85236600970622 /* RemoteVideoView.m in Sources */ = {isa = PBXBuildFile; fileRef = 450D19121F85236600970622 /* RemoteVideoView.m */; };
450DF2051E0D74AC003D14BE /* Platform.swift in Sources */ = {isa = PBXBuildFile; fileRef = 450DF2041E0D74AC003D14BE /* Platform.swift */; };
450DF2091E0DD2C6003D14BE /* UserNotificationsAdaptee.swift in Sources */ = {isa = PBXBuildFile; fileRef = 450DF2081E0DD2C6003D14BE /* UserNotificationsAdaptee.swift */; };
451686AB1F520CDA00AC3D4B /* MultiDeviceProfileKeyUpdateJob.swift in Sources */ = {isa = PBXBuildFile; fileRef = 451686AA1F520CDA00AC3D4B /* MultiDeviceProfileKeyUpdateJob.swift */; };
@ -601,6 +602,8 @@
450873C61D9D867B006B54F2 /* OWSIncomingMessageCollectionViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OWSIncomingMessageCollectionViewCell.m; sourceTree = "<group>"; };
450873C91D9D86F4006B54F2 /* OWSExpirableMessageView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OWSExpirableMessageView.h; sourceTree = "<group>"; };
4509E7991DD653700025A59F /* WebRTC.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebRTC.framework; path = Carthage/Build/iOS/WebRTC.framework; sourceTree = "<group>"; };
450D19111F85236600970622 /* RemoteVideoView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RemoteVideoView.h; sourceTree = "<group>"; };
450D19121F85236600970622 /* RemoteVideoView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RemoteVideoView.m; sourceTree = "<group>"; };
450DF2041E0D74AC003D14BE /* Platform.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Platform.swift; sourceTree = "<group>"; };
450DF2081E0DD2C6003D14BE /* UserNotificationsAdaptee.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; name = UserNotificationsAdaptee.swift; path = UserInterface/Notifications/UserNotificationsAdaptee.swift; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };
451686AA1F520CDA00AC3D4B /* MultiDeviceProfileKeyUpdateJob.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultiDeviceProfileKeyUpdateJob.swift; sourceTree = "<group>"; };
@ -1526,6 +1529,8 @@
34F3089D1ECA580B00BB7697 /* OWSUnreadIndicatorCell.h */,
34F3089E1ECA580B00BB7697 /* OWSUnreadIndicatorCell.m */,
45A6DAD51EBBF85500893231 /* ReminderView.swift */,
450D19111F85236600970622 /* RemoteVideoView.h */,
450D19121F85236600970622 /* RemoteVideoView.m */,
);
name = Views;
path = views;
@ -2259,6 +2264,7 @@
45CD81EF1DC030E7004C9430 /* AccountManager.swift in Sources */,
45794E861E00620000066731 /* CallUIAdapter.swift in Sources */,
4585C4681ED8F8D200896AEA /* SafetyNumberConfirmationAlert.swift in Sources */,
450D19131F85236600970622 /* RemoteVideoView.m in Sources */,
FCFA64B71A24F6730007FB87 /* UIFont+OWS.m in Sources */,
B6B9ECFC198B31BA00C620D3 /* PushManager.m in Sources */,
45DF5DF21DDB843F00C936C7 /* CompareSafetyNumbersActivity.swift in Sources */,

View File

@ -32,6 +32,7 @@
#import "ProfileViewController.h"
#import "PushManager.h"
#import "Release.h"
#import "RemoteVideoView.h"
#import "TSMessageAdapter.h"
#import "ThreadUtil.h"
#import "UIColor+OWS.h"
@ -110,11 +111,4 @@
#import <SignalServiceKit/TSThread.h>
#import <WebRTC/RTCAudioSession.h>
#import <WebRTC/RTCCameraPreviewView.h>
#import <WebRTC/RTCEAGLVideoView.h>
#import <WebRTC/RTCMTLVideoView.h>
#import <WebRTC/RTCVideoRenderer.h>
#import <YYImage/YYImage.h>
@interface RTCMTLVideoView (MakePrivatePublic)
+ (BOOL)isMetalAvailable;
@end

View File

@ -8,7 +8,8 @@ import PromiseKit
// TODO: Add category so that button handlers can be defined where button is created.
// TODO: Ensure buttons enabled & disabled as necessary.
class CallViewController: OWSViewController, CallObserver, CallServiceObserver, RTCEAGLVideoViewDelegate {
//class CallViewController: OWSViewController, CallObserver, CallServiceObserver, RTCEAGLVideoViewDelegate {
class CallViewController: OWSViewController, CallObserver, CallServiceObserver {
let TAG = "[CallViewController]"
@ -60,14 +61,14 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
// MARK: Video Views
// var remoteVideoView: RTCEAGLVideoView!
var remoteVideoView: (UIView & RTCVideoRenderer)!
// var remoteVideoView = UIView()
// var remoteVideoRenderView: (UIView & RTCVideoRenderer)!
var remoteVideoView: RemoteVideoView!
var localVideoView: RTCCameraPreviewView!
weak var localVideoTrack: RTCVideoTrack?
weak var remoteVideoTrack: RTCVideoTrack?
// TODO delete?
var remoteVideoSize: CGSize! = CGSize.zero
// TODO delete?
var remoteVideoConstraints: [NSLayoutConstraint] = []
var localVideoConstraints: [NSLayoutConstraint] = []
@ -236,37 +237,35 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
func createVideoViews() {
localVideoView = RTCCameraPreviewView()
if #available(iOS 9, *) {
if RTCMTLVideoView.isMetalAvailable() {
remoteVideoView = RTCMTLVideoView(frame: CGRect(x: 50, y: 50, width: 200, height: 300))
remoteVideoView.setSize(self.view.frame.size)
}
}
// Fallback on earlier versions
if remoteVideoView == nil {
let eaglVideoView = RTCEAGLVideoView()
eaglVideoView.delegate = self
remoteVideoView = eaglVideoView
}
// if isMetalAvailable {
// if #available(iOS 9, *) {
// remoteVideoView = RTCMTLVideoView(frame: CGRect(x: 50, y: 50, width: 200, height: 300))
//// remoteVideoView.setSize(self.view.frame.size)
// } else {
// owsFail("metal should only be available on ios9+")
// }
// } else {
// let eaglVideoView = RTCEAGLVideoView()
// eaglVideoView.delegate = self
// remoteVideoView = eaglVideoView
// }
//
// guard let remoteVideoView = self.remoteVideoView else {
// owsFail("Failed to make remoteVideoView")
// return
// }
guard let remoteVideoView = self.remoteVideoView else {
owsFail("Failed to make remoteVideoView")
return
}
remoteVideoView = RemoteVideoView()
remoteVideoView.backgroundColor = UIColor.yellow
remoteVideoView.isUserInteractionEnabled = false
remoteVideoView.layoutMargins = UIEdgeInsets.zero
remoteVideoView.isHidden = true
// remoteVideoView.isHidden = false
localVideoView.isHidden = true
self.view.addSubview(remoteVideoView)
self.view.addSubview(localVideoView)
remoteVideoView.autoPinEdgesToSuperviewEdges()
}
func createContactViews() {
@ -575,6 +574,8 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
localVideoView.autoSetDimension(.width, toSize:localVideoSize)
localVideoView.autoSetDimension(.height, toSize:localVideoSize)
remoteVideoView.autoPinEdgesToSuperviewEdges()
contactNameLabel.autoPinEdge(toSuperviewEdge:.top, withInset:topMargin)
contactNameLabel.autoPinLeadingToSuperview(withMargin: contactHMargin)
contactNameLabel.setContentHuggingVerticalHigh()
@ -615,67 +616,8 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
}
internal func updateRemoteVideoLayout() {
// return
//
// switch self.remoteVideoView {
// case let videoView as RTCMTLVideoView:
// videoView.frame = self.remoteVideView.bounds
// default:
if #available(iOS 9, *) {
if let mtlView = remoteVideoView as? RTCMTLVideoView {
mtlView.setSize(self.view.frame.size)
}
}
NSLayoutConstraint.deactivate(self.remoteVideoConstraints)
var constraints: [NSLayoutConstraint] = []
if (self.hasRemoteVideoTrack) {
// We fill the screen with the remote video. The remote video's
// aspect ratio may not (and in fact will very rarely) match the
// aspect ratio of the current device, so parts of the remote
// video will be hidden offscreen.
//
// It's better to trim the remote video than to adopt a letterboxed
// layout.
if remoteVideoSize.width > 0 && remoteVideoSize.height > 0 &&
self.view.bounds.size.width > 0 && self.view.bounds.size.height > 0 {
var remoteVideoWidth = self.view.bounds.size.width
var remoteVideoHeight = self.view.bounds.size.height
if remoteVideoSize.width / self.view.bounds.size.width > remoteVideoSize.height / self.view.bounds.size.height {
remoteVideoWidth = round(self.view.bounds.size.height * remoteVideoSize.width / remoteVideoSize.height)
} else {
remoteVideoHeight = round(self.view.bounds.size.width * remoteVideoSize.height / remoteVideoSize.width)
}
constraints.append(remoteVideoView.autoSetDimension(.width, toSize:remoteVideoWidth))
constraints.append(remoteVideoView.autoSetDimension(.height, toSize:remoteVideoHeight))
constraints += remoteVideoView.autoCenterInSuperview()
remoteVideoView.frame = CGRect(origin:CGPoint.zero,
size:CGSize(width:remoteVideoWidth,
height:remoteVideoHeight))
remoteVideoView.isHidden = false
} else {
remoteVideoView.frame = self.view.bounds
remoteVideoView.isHidden = false
}
} else {
constraints += remoteVideoView.autoPinEdgesToSuperviewEdges()
remoteVideoView.isHidden = true
}
self.remoteVideoConstraints = constraints
// We need to force relayout to occur immediately (and not
// wait for a UIKit layout/render pass) or the remoteVideoView
// (which presumably is updating its CALayer directly) will
// ocassionally appear to have bad frames.
remoteVideoView.setNeedsLayout()
remoteVideoView.superview?.setNeedsLayout()
remoteVideoView.layoutIfNeeded()
remoteVideoView.superview?.layoutIfNeeded()
remoteVideoView.isHidden = !self.hasRemoteVideoTrack
self.remoteVideoView.updateRemoteVideoLayout()
updateCallUI(callState: call.state)
}
@ -1033,6 +975,7 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
var hasRemoteVideoTrack: Bool {
return self.remoteVideoTrack != nil
}
internal func updateRemoteVideoTrack(remoteVideoTrack: RTCVideoTrack?) {
AssertIsOnMainThread()
guard self.remoteVideoTrack != remoteVideoTrack else {
@ -1112,22 +1055,53 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
updateLocalVideoTrack(localVideoTrack: localVideoTrack)
updateRemoteVideoTrack(remoteVideoTrack: remoteVideoTrack)
}
// MARK: - RTCEAGLVideoViewDelegate
internal func videoView(_ videoView: RTCEAGLVideoView, didChangeVideoSize size: CGSize) {
AssertIsOnMainThread()
if #available(iOS 9, *) {
assert(!RTCMTLVideoView.isMetalAvailable())
}
if videoView != remoteVideoView {
return
}
Logger.info("\(TAG) \(#function): \(size)")
remoteVideoSize = size
updateRemoteVideoLayout()
}
//
// // MARK: - RTCEAGLVideoViewDelegate
//
// internal func videoView(_ videoView: RTCEAGLVideoView, didChangeVideoSize size: CGSize) {
// AssertIsOnMainThread()
// assert(!isMetalAvailable)
//
// if videoView != remoteVideoView {
// return
// }
//
// Logger.info("\(TAG) \(#function): \(size)")
//
// remoteVideoSize = size
// updateRemoteVideoLayout()
// }
}
//protocol RemoteVideoViewAdaptee: RTCVideoRenderer {
//
//}
//
//class RemoteVideoViewAdapter: UIView, RTCVideoRenderer {
// let adaptee: RemoteVideoViewAdaptee
//
// var isMetalAvailable: Bool {
// // MetalKit is available on 64bit devices running iOS9+
// if #available(iOS 9, *) {
// return objc_getClass("RTCMTLVideoView") != nil && RTCMTLVideoView.isMetalAvailable()
// } else {
// return false
// }
// }
//
// init() {
// #if defined(RTC_SUPPORTS_METAL)
// if #available(iOS 9, *) {
// adaptee = RTCMTLVideoView(frame: CGRect.zero)
// }
// #endif
//
// if adaptee == nil {
// let eaglVideoView = RTCEAGLVideoView()
// eaglVideoView.delegate = self
// adaptee = eaglVideoView
// }
//
// super.init()
// }
//}

View File

@ -418,7 +418,8 @@ struct AudioSource: Hashable {
guard let availableInputs = session.availableInputs else {
// I'm not sure when this would happen.
owsFail("No available inputs or inputs not ready")
// TODO this happens when the call ends (at leas ton iOS8)
// owsFail("No available inputs or inputs not ready")
return [AudioSource.builtInSpeaker]
}

View File

@ -0,0 +1,15 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import <WebRTC/RTCVideoRenderer.h>
/**
* Drives the full screen remote video, this class is backed by either the modern MetalKit backed view on supported
* systems or the leagacy EAGL view. MetalKit is supported on 64bit systems running iOS8 or newer.
*/
@interface RemoteVideoView : UIView <RTCVideoRenderer>
- (void)updateRemoteVideoLayout;
@end

View File

@ -0,0 +1,224 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "RemoteVideoView.h"
#import <WebRTC/RTCEAGLVideoView.h>
#import <WebRTC/RTCMTLVideoView.h>
#import <WebRTC/RTCVideoRenderer.h>
#import <PureLayout/PureLayout.h>
@interface RTCMTLVideoView (MakePrivatePublic)
+ (BOOL)isMetalAvailable;
@end
@interface RemoteVideoView () <RTCEAGLVideoViewDelegate>
@property (nonatomic, readonly) __kindof UIView<RTCVideoRenderer> *adaptee;
// Used for legacy EAGLVideoView
@property (nonatomic) CGSize remoteVideoSize;
@property (nullable, nonatomic) NSMutableArray<NSLayoutConstraint *> *remoteVideoConstraints;
@end
@implementation RemoteVideoView
//@implementation RemoteVideoViewAdapter
//protocol RemoteVideoViewAdaptee: RTCVideoRenderer {
//
//}
//
//
//#if defined(RTC_SUPPORTS_METAL)
// if #available(iOS 9, *) {
//
// }
//#endif
//
// if adaptee == nil {
// let eaglVideoView = RTCEAGLVideoView()
// eaglVideoView.delegate = self
// adaptee = eaglVideoView
// }
//
// super.init()
// }
//}
- (instancetype)init
{
self = [super init];
if (!self) {
return self;
}
// This class is defined in objc in order to access this compile time macro
#if defined(RTC_SUPPORTS_METAL)
if ([RTCMTLVideoView isMetalAvailable]) {
_adaptee = [[RTCMTLVideoView alloc] initWithFrame:CGRectZero];
}
#endif
if (_adaptee == nil) {
RTCEAGLVideoView *eaglVideoView = [RTCEAGLVideoView new];
eaglVideoView.delegate = self;
_adaptee = eaglVideoView;
}
[self addSubview:_adaptee];
[_adaptee autoPinEdgesToSuperviewEdges];
return self;
}
- (void)updateRemoteVideoLayout
{
// if isMetalAvailable {
// if #available(iOS 9, *) {
// assert(remoteVideoView as? RTCMTLVideoView != nil)
// } else {
// owsFail("metal should only be available on iOS9+")
// }
// Logger.debug("no additional layout needed for RTCMTLVideoView")
// } else if let videoView = remoteVideoView as? RTCEAGLVideoView {
// NSLayoutConstraint.deactivate(self.remoteVideoConstraints)
//
// var constraints: [NSLayoutConstraint] = []
// // We fill the screen with the remote video. The remote video's
// // aspect ratio may not (and in fact will very rarely) match the
// // aspect ratio of the current device, so parts of the remote
// // video will be hidden offscreen.
// //
// // It's better to trim the remote video than to adopt a letterboxed
// // layout.
// if remoteVideoSize.width > 0 && remoteVideoSize.height > 0 &&
// self.view.bounds.size.width > 0 && self.view.bounds.size.height > 0 {
//
// var remoteVideoWidth = self.view.bounds.size.width
// var remoteVideoHeight = self.view.bounds.size.height
// if remoteVideoSize.width / self.view.bounds.size.width > remoteVideoSize.height / self.view.bounds.size.height {
// remoteVideoWidth = round(self.view.bounds.size.height * remoteVideoSize.width / remoteVideoSize.height)
// } else {
// remoteVideoHeight = round(self.view.bounds.size.width * remoteVideoSize.height / remoteVideoSize.width)
// }
// constraints.append(videoView.autoSetDimension(.width, toSize:remoteVideoWidth))
// constraints.append(videoView.autoSetDimension(.height, toSize:remoteVideoHeight))
// constraints += videoView.autoCenterInSuperview()
//
// videoView.frame = CGRect(origin:CGPoint.zero,
// size:CGSize(width:remoteVideoWidth,
// height:remoteVideoHeight))
//
// } else {
// constraints += videoView.autoPinEdgesToSuperviewEdges()
// }
// self.remoteVideoConstraints = constraints
// // We need to force relayout to occur immediately (and not
// // wait for a UIKit layout/render pass) or the remoteVideoView
// // (which presumably is updating its CALayer directly) will
// // ocassionally appear to have bad frames.
// videoView.setNeedsLayout()
// videoView.superview?.setNeedsLayout()
// videoView.layoutIfNeeded()
// videoView.superview?.layoutIfNeeded()
// } else {
// owsFail("in \(#function) with unhandled remoteVideoView type: \(remoteVideoView)")
// }
UIView *containingView = [self superview];
if (containingView == nil) {
DDLogDebug(@"%@ Cannot layout video view without superview", self.logTag);
return;
}
// We fill the screen with the remote video. The remote video's
// aspect ratio may not (and in fact will very rarely) match the
// aspect ratio of the current device, so parts of the remote
// video will be hidden offscreen.
//
// It's better to trim the remote video than to adopt a letterboxed
// layout.
// This is only required on the legacy EAGL view. The modern MetalKit
// backed view can scale using the AspectFill content mode
if ([self.adaptee isKindOfClass:[RTCEAGLVideoView class]]) {
RTCEAGLVideoView *videoView = (RTCEAGLVideoView *)self.adaptee;
[NSLayoutConstraint deactivateConstraints:self.remoteVideoConstraints];
CGSize remoteVideoSize = self.remoteVideoSize;
NSMutableArray<NSLayoutConstraint *> *constraints = [NSMutableArray new];
if (remoteVideoSize.width > 0 && remoteVideoSize.height > 0 &&
containingView.bounds.size.width > 0 && containingView.bounds.size.height > 0) {
CGFloat remoteVideoWidth = containingView.bounds.size.width;
CGFloat remoteVideoHeight = containingView.bounds.size.height;
if (remoteVideoSize.width / containingView.bounds.size.width > remoteVideoSize.height / containingView.bounds.size.height) {
remoteVideoWidth = round(containingView.bounds.size.height * remoteVideoSize.width / remoteVideoSize.height);
} else {
remoteVideoHeight = round(containingView.bounds.size.width * remoteVideoSize.height / remoteVideoSize.width);
}
[constraints addObject:[videoView autoSetDimension:ALDimensionWidth toSize:remoteVideoWidth]];
[constraints addObject:[videoView autoSetDimension:ALDimensionHeight toSize:remoteVideoHeight]];
[constraints addObjectsFromArray:[videoView autoCenterInSuperview]];
videoView.frame = CGRectMake(0, 0, remoteVideoWidth, remoteVideoHeight);
} else {
[constraints addObjectsFromArray:[videoView autoPinEdgesToSuperviewEdges]];
}
self.remoteVideoConstraints = constraints;
// We need to force relayout to occur immediately (and not
// wait for a UIKit layout/render pass) or the remoteVideoView
// (which presumably is updating its CALayer directly) will
// ocassionally appear to have bad frames.
[videoView setNeedsLayout];
[[videoView superview] setNeedsLayout];
[videoView layoutIfNeeded];
[[videoView superview] layoutIfNeeded];
}
}
// MARK: - RTCEAGLVideoViewDelegate
- (void)videoView:(RTCEAGLVideoView *)videoView didChangeVideoSize:(CGSize)size
{
AssertIsOnMainThread();
// TODO
// if videoView != remoteVideoView {
// return
// }
DDLogInfo(@"%s called", __PRETTY_FUNCTION__);
self.remoteVideoSize = size;
[self updateRemoteVideoLayout];
}
#pragma mark - RTCVideoRenderer
/** The size of the frame. */
- (void)setSize:(CGSize)size
{
[self.adaptee setSize:size];
}
/** The frame to be displayed. */
- (void)renderFrame:(nullable RTCVideoFrame *)frame
{
[self.adaptee renderFrame:frame];
}
#pragma mark - Logging
+ (NSString *)logTag
{
return [NSString stringWithFormat:@"[%@]", self.class];
}
- (NSString *)logTag
{
return self.class.logTag;
}
@end