mirror of
https://github.com/oxen-io/session-ios.git
synced 2023-12-13 21:30:14 +01:00
Video calls use MetalKit when available
Taking advantage of the new RTCMTLVideoView where available (64bit && >=iOS9), should help performance (battery and rendering quality). // FREEBIE
This commit is contained in:
parent
7e39e58fc6
commit
f171c56488
3 changed files with 89 additions and 35 deletions
|
@ -111,4 +111,10 @@
|
|||
#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
|
||||
|
|
|
@ -60,7 +60,10 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
|
|||
|
||||
// MARK: Video Views
|
||||
|
||||
var remoteVideoView: RTCEAGLVideoView!
|
||||
// var remoteVideoView: RTCEAGLVideoView!
|
||||
var remoteVideoView: (UIView & RTCVideoRenderer)!
|
||||
// var remoteVideoView = UIView()
|
||||
// var remoteVideoRenderView: (UIView & RTCVideoRenderer)!
|
||||
var localVideoView: RTCCameraPreviewView!
|
||||
weak var localVideoTrack: RTCVideoTrack?
|
||||
weak var remoteVideoTrack: RTCVideoTrack?
|
||||
|
@ -232,14 +235,38 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
|
|||
}
|
||||
|
||||
func createVideoViews() {
|
||||
remoteVideoView = RTCEAGLVideoView()
|
||||
remoteVideoView.delegate = self
|
||||
remoteVideoView.isUserInteractionEnabled = false
|
||||
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
|
||||
}
|
||||
|
||||
guard let remoteVideoView = self.remoteVideoView else {
|
||||
owsFail("Failed to make remoteVideoView")
|
||||
return
|
||||
}
|
||||
|
||||
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() {
|
||||
|
@ -588,41 +615,56 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
|
|||
}
|
||||
|
||||
internal func updateRemoteVideoLayout() {
|
||||
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)
|
||||
// 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)
|
||||
}
|
||||
constraints.append(remoteVideoView.autoSetDimension(.width, toSize:remoteVideoWidth))
|
||||
constraints.append(remoteVideoView.autoSetDimension(.height, toSize:remoteVideoHeight))
|
||||
constraints += remoteVideoView.autoCenterInSuperview()
|
||||
}
|
||||
|
||||
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 {
|
||||
|
||||
remoteVideoView.frame = CGRect(origin:CGPoint.zero,
|
||||
size:CGSize(width:remoteVideoWidth,
|
||||
height:remoteVideoHeight))
|
||||
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.isHidden = false
|
||||
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
|
||||
|
@ -988,6 +1030,9 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
|
|||
updateLocalVideoLayout()
|
||||
}
|
||||
|
||||
var hasRemoteVideoTrack: Bool {
|
||||
return self.remoteVideoTrack != nil
|
||||
}
|
||||
internal func updateRemoteVideoTrack(remoteVideoTrack: RTCVideoTrack?) {
|
||||
AssertIsOnMainThread()
|
||||
guard self.remoteVideoTrack != remoteVideoTrack else {
|
||||
|
@ -1064,14 +1109,17 @@ class CallViewController: OWSViewController, CallObserver, CallServiceObserver,
|
|||
remoteVideoTrack: RTCVideoTrack?) {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
updateLocalVideoTrack(localVideoTrack:localVideoTrack)
|
||||
updateRemoteVideoTrack(remoteVideoTrack:remoteVideoTrack)
|
||||
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
|
||||
|
|
|
@ -209,7 +209,7 @@ protocol CallServiceObserver: class {
|
|||
didSet {
|
||||
AssertIsOnMainThread()
|
||||
|
||||
Logger.info("\(self.TAG) \(#function)")
|
||||
Logger.info("\(self.TAG) \(#function): \(isRemoteVideoEnabled)")
|
||||
|
||||
fireDidUpdateVideoTracks()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue