diff --git a/SwiftProject/SwiftProject.xcworkspace/xcuserdata/aaa.xcuserdatad/UserInterfaceState.xcuserstate b/SwiftProject/SwiftProject.xcworkspace/xcuserdata/aaa.xcuserdatad/UserInterfaceState.xcuserstate index 2d93018..7468d8d 100644 Binary files a/SwiftProject/SwiftProject.xcworkspace/xcuserdata/aaa.xcuserdatad/UserInterfaceState.xcuserstate and b/SwiftProject/SwiftProject.xcworkspace/xcuserdata/aaa.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/SwiftProject/SwiftProject.xcworkspace/xcuserdata/aaa.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/SwiftProject/SwiftProject.xcworkspace/xcuserdata/aaa.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index 4b893ad..9c301ba 100644 --- a/SwiftProject/SwiftProject.xcworkspace/xcuserdata/aaa.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/SwiftProject/SwiftProject.xcworkspace/xcuserdata/aaa.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -563,42 +563,10 @@ filePath = "SwiftProject/Project/Controller/RecordingVideo/CCSpatialVideoDisplayController/CCSpatialVideoDisplayController.swift" startingColumnNumber = "9223372036854775807" endingColumnNumber = "9223372036854775807" - startingLineNumber = "440" - endingLineNumber = "440" + startingLineNumber = "567" + endingLineNumber = "567" landmarkName = "navgationButtonClick2(sender:)" landmarkType = "7"> - - - - - - Bool { -// Task { - FirebaseApp.configure() -// } + + FirebaseApp.configure() + + do { + try AVAudioSession.sharedInstance().setActive(true) + try AVAudioSession.sharedInstance().setCategory(.playback,options: .allowAirPlay) + } + catch { + print("err: set audiosession:\(error)") + } + SVProgressHUD.setDefaultStyle(.dark) diff --git a/SwiftProject/SwiftProject/ExternalScreen/ExternalSceneDelegate.swift b/SwiftProject/SwiftProject/ExternalScreen/ExternalSceneDelegate.swift index 3c8a5e4..c2213a1 100644 --- a/SwiftProject/SwiftProject/ExternalScreen/ExternalSceneDelegate.swift +++ b/SwiftProject/SwiftProject/ExternalScreen/ExternalSceneDelegate.swift @@ -6,6 +6,8 @@ // import UIKit +import AVKit +import AVFoundation class ExternalSceneDelegate: UIResponder, UIWindowSceneDelegate { @@ -14,13 +16,19 @@ class ExternalSceneDelegate: UIResponder, UIWindowSceneDelegate { func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) { print("ExternalSceneDelegate scene.......") - +// let ac = UISceneActivationConditions() +// ac.canActivateForTargetContentIdentifierPredicate = NSPredicate(value: true) +// ac.prefersToActivateForTargetContentIdentifierPredicate = NSPredicate(value: true) +// scene.activationConditions = ac // self.window?.rootViewController = ZZHExternalViewController() // guard let _ = (scene as? UIWindowScene) else { return } // guard let rootViewController = window?.rootViewController else { // return // } + + + } func sceneDidDisconnect(_ scene: UIScene) { @@ -36,6 +44,7 @@ class ExternalSceneDelegate: UIResponder, UIWindowSceneDelegate { // Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive. print("ExternalSceneDelegate sceneDidBecomeActive") } + func sceneWillResignActive(_ scene: UIScene) { // Called when the scene will move from an active state to an inactive state. diff --git a/SwiftProject/SwiftProject/ExternalScreen/ZZHExternalViewController.swift b/SwiftProject/SwiftProject/ExternalScreen/ZZHExternalViewController.swift index 508ff62..87b2ccc 100644 --- a/SwiftProject/SwiftProject/ExternalScreen/ZZHExternalViewController.swift +++ b/SwiftProject/SwiftProject/ExternalScreen/ZZHExternalViewController.swift @@ -7,10 +7,14 @@ import Foundation import UIKit +import AVKit + class ZZHExternalViewController: UIViewController { var imageView: UIImageView? - +// var avplayerController:AVPlayerViewController? +// var player:AVPlayer? + var playerLayer:AVPlayerLayer? override func viewDidLoad() { super.viewDidLoad() print("ZZHExternalViewController viewDidLoad..") @@ -22,5 +26,17 @@ class ZZHExternalViewController: UIViewController { make.left.top.right.bottom.equalTo(0) }) + +// player = AVPlayer() + playerLayer = AVPlayerLayer() + playerLayer!.frame = self.view.bounds + self.view.layer.addSublayer(playerLayer!) +//// player?.allowsExternalPlayback = true +//// player?.usesExternalPlaybackWhileExternalScreenIsActive = true +// avplayerController = AVPlayerViewController() +// avplayerController?.player = player +// self.addChild(avplayerController!) +// self.view.addSubview(avplayerController!.view) +// avplayerController!.view.frame = self.view.bounds } } diff --git a/SwiftProject/SwiftProject/Info.plist b/SwiftProject/SwiftProject/Info.plist index cfb9a95..4602d82 100644 --- a/SwiftProject/SwiftProject/Info.plist +++ b/SwiftProject/SwiftProject/Info.plist @@ -39,5 +39,9 @@ + UIBackgroundModes + + audio + diff --git a/SwiftProject/SwiftProject/Project/Controller/RecordingVideo/CCSpatialPhotoDisplayController/CCSpatialPhotoDisplayController.swift b/SwiftProject/SwiftProject/Project/Controller/RecordingVideo/CCSpatialPhotoDisplayController/CCSpatialPhotoDisplayController.swift index 0723428..8b02f65 100644 --- a/SwiftProject/SwiftProject/Project/Controller/RecordingVideo/CCSpatialPhotoDisplayController/CCSpatialPhotoDisplayController.swift +++ b/SwiftProject/SwiftProject/Project/Controller/RecordingVideo/CCSpatialPhotoDisplayController/CCSpatialPhotoDisplayController.swift @@ -278,85 +278,22 @@ class CCSpatialPhotoDisplayController: BaseController { externalVC = ws.windows.first?.rootViewController as? ZZHExternalViewController externalDispalylink = ws.windows.first?.screen.displayLink(withTarget: self, selector: #selector(displayUpdate(caDisplayLink:))) externalDispalylink?.add(to: RunLoop.main, forMode: RunLoop.Mode.common) - + externalVC?.imageView?.isHidden = false + externalVC?.playerLayer?.isHidden = true } } - // 获取所有打开的会话 -// let sessions:Set = UIApplication.shared.openSessions -// sessions.forEach { ss in -// print("role:\(ss.role.rawValue)") -// } -// // 过滤会话以找到来自其他屏幕的场景 -// let otherScreenSessions:Set = sessions.filter { -// $0.role.rawValue.contains("External") -// } -// -// otherScreenSessions.forEach { ssn in -// print("ssn role:\(ssn.role.rawValue) first:\(otherScreenSessions.first)") -// } -// -// UIApplication.shared.connectedScenes.forEach { us in -// print("conn sc:\(us)") -// } - - - -// if let session = otherScreenSessions.first{ -// let ssar = UISceneSessionActivationRequest.init(session: session) -// UIApplication.shared.activateSceneSession(for: ssar) { err in -// print("error:\(err)") -// } -// guard let scene = session.scene else { -// return -// } -// self.externalWindow.windowScene = scene as! UIWindowScene -// let nvc = UIViewController() -// self.externalWindow.rootViewController = nvc -// var imageView = UIImageView(frame: CGRectMake(0, 0, KScreenHeight*2, KScreenHeight*2)) -// imageView.contentMode = .scaleAspectFit -// externalImageView = imageView -// nvc.view.addSubview(imageView) -// self.externalWindow.isHidden = false -// var dispalylink:CADisplayLink? = self.externalWindow.windowScene?.windows.first?.screen.displayLink(withTarget: self, selector: #selector(displayUpdate(caDisplayLink:))) -// dispalylink?.add(to: RunLoop.main, forMode: RunLoop.Mode.common) -// } -// else { -// print("未发现外接屏....") -// } } else{ print("变化为 断开。。。。") externalVC = nil externalDispalylink?.invalidate() externalDispalylink = nil -// if let imv = externalImageView{ -// imv .removeFromSuperview() -// } -// externalImageView = nil -// self.externalWindow.isHidden = true -// self.externalWindow.rootViewController = nil - - } } -// @objc func hasNewWindowExternal(notification:Notification){ -// print("hasNewWindowExternal notifi...") -// let window = notification.userInfo?["newwindow"] as! UIWindow -// let imageView = UIImageView(frame: CGRectMake(0, 0, KScreenHeight*2, KScreenHeight*2)) -// imageView.contentMode = .scaleAspectFit -// externalImageView = imageView -// window.rootViewController?.view.addSubview(imageView) -// let dispalylink:CADisplayLink? = window.screen.displayLink(withTarget: self, selector: #selector(displayUpdate(caDisplayLink:))) -// dispalylink?.add(to: RunLoop.main, forMode: RunLoop.Mode.common) -// -// } + @objc func displayUpdate(caDisplayLink:CADisplayLink) { -// if externalImageView?.image != mImgView.image { -// externalImageView?.image = mImgView.image -// } - if let has_exvc = externalVC { has_exvc.imageView?.image = mImgView.image } diff --git a/SwiftProject/SwiftProject/Project/Controller/RecordingVideo/CCSpatialVideoDisplayController/CCSpatialVideoDisplayController.swift b/SwiftProject/SwiftProject/Project/Controller/RecordingVideo/CCSpatialVideoDisplayController/CCSpatialVideoDisplayController.swift index c799341..2ebc763 100644 --- a/SwiftProject/SwiftProject/Project/Controller/RecordingVideo/CCSpatialVideoDisplayController/CCSpatialVideoDisplayController.swift +++ b/SwiftProject/SwiftProject/Project/Controller/RecordingVideo/CCSpatialVideoDisplayController/CCSpatialVideoDisplayController.swift @@ -31,7 +31,8 @@ enum SpatialType : Int { } class CCSpatialVideoDisplayController: BaseController { - + var externalDispalylink:CADisplayLink? + var externalVC:ZZHExternalViewController? var isAirPlayActive:Bool = false { didSet{ //跟新selectedIndex、typeData的值 @@ -53,7 +54,10 @@ class CCSpatialVideoDisplayController: BaseController { (icon:"type_check",title:NSLocalizedString("交叉眼", comment: ""),isHiden:false)] } //更新串流UI - setttinisScreenMirroring(isScreenMirroring: isAirPlayActive) +// DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: { + self.setttinisScreenMirroring(isScreenMirroring: self.isAirPlayActive) +// }) + } @@ -231,7 +235,7 @@ class CCSpatialVideoDisplayController: BaseController { await self.loadVideoAssetReader() DispatchQueue.main.async { self.configureInfo() - print("ccs viewdid load +++++++") +// print("ccs viewdid load +++++++") // 检查当前是否已连接到 AirPlay 设备 self.checkAirPlayStatus() } @@ -241,9 +245,14 @@ class CCSpatialVideoDisplayController: BaseController { func configureInfo(){ print("getPlayerItem ========") - let playerItem = self.getPlayerItem() +// let playerItem = self.getPlayerItem() + +// player = AVPlayer(playerItem: playerItem) + player = AVPlayer() + player?.allowsExternalPlayback = true + player?.usesExternalPlaybackWhileExternalScreenIsActive = true + - player = AVPlayer(playerItem: playerItem) print("getPlayerItem >>>>>>>") self.view.backgroundColor = UIColor(hexString: "#060507") @@ -264,15 +273,17 @@ class CCSpatialVideoDisplayController: BaseController { playerController?.view.frame = CGRect.init(x: 0, y: 170, width: self.view.frame.size.width, height: 400) self.addChild(playerController!) self.view.addSubview(playerController!.view) - - self.view.addSubview(tipsButton) // 监听 AirPlay 设备的连接状态 - NotificationCenter.default.addObserver(self, selector: #selector(airPlayStatusDidChange(_:)), name: AVAudioSession.routeChangeNotification, object: nil) + //添加外接屏幕链接通知 + NotificationCenter.default.addObserver(self, selector: #selector(exScreenWillConnectNotification(notification:)), name: UIScene.willConnectNotification, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(exScreenDisConnectNotification(notification:)), name: UIScene.didDisconnectNotification, object: nil) + + NotificationCenter.default.addObserver(self, selector: #selector(notification_PlayerEndTime(notification:)), name: AVPlayerItem.didPlayToEndTimeNotification, object: nil) @@ -291,10 +302,16 @@ class CCSpatialVideoDisplayController: BaseController { override func viewDidDisappear(_ animated: Bool) { super.viewDidDisappear(animated) + if externalVC != nil { + externalVC?.playerLayer?.player = nil + } player?.pause() + releaseVideoComposition() + let sec:TimeInterval = ZZHHelper.getSecFromUserDefaultByKey(kNowTimeToUserDefaultKey_VideoDisplayController) Analytics.logEvent("preview_pv", parameters: ["refer_page":"视频预览页面","duration":sec]) + } override func viewWillDisappear(_ animated: Bool) { @@ -304,7 +321,31 @@ class CCSpatialVideoDisplayController: BaseController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) + + if self.player?.currentItem == nil {//此处需要判断是否为空:1,在didload的时候会设置一次,在viewDidDisappear的时候会被置空 + let playerItem = self.getPlayerItem() + self.player?.replaceCurrentItem(with: playerItem) + } + if self.externalVC != nil {//恢复外接屏幕的视频播放 + if self.externalVC?.playerLayer?.player == nil { + self.activeSession() + self.externalVC?.playerLayer?.player = self.player + } + } + self.player?.play() +// else if self.playerController?.player { +// let playerItem = self.getPlayerItem() +// Task { +// print("ccs viewdid load ---------") +// await self.loadVideoAssetReader() +// DispatchQueue.main.async {[weak self] in +// self?.player?.replaceCurrentItem(with: playerItem) +// self?.player?.play() +// } +// } +// } + } //MARK: - 监听设备投流 @@ -320,6 +361,17 @@ class CCSpatialVideoDisplayController: BaseController { } } + @objc func exScreenWillConnectNotification(notification:Notification){ + print("exScreenWillConnectNotification>>>>>") + airPlayStatusDidChange( notification) + } + + @objc func exScreenDisConnectNotification(notification:Notification){ + print("exScreenDisConnectNotification>>>>>") + airPlayStatusDidChange( notification) + } + + private func checkAirPlayStatus() { print("设备连接变化") @@ -331,74 +383,149 @@ class CCSpatialVideoDisplayController: BaseController { } func setttinisScreenMirroring(isScreenMirroring:Bool){ - //已连接 - if(isScreenMirroring){ - print("已连接") - link = true - isPlaying = true - playerController!.player!.usesExternalPlaybackWhileExternalScreenIsActive = true - playerController!.player!.allowsExternalPlayback = true - - //串流播放中 - mTopCenterTypeButton.setImage(UIImage.init(named: "linked_button"), for: .normal) - mTopCenterTypeButton.setTitleColor(UIColor(hexString: "#D0C0FF"), for: .normal) - mTopCenterTypeButton.layer.borderColor = UIColor(hexString: "#D0C0FF").cgColor - mTopCenterTypeButton.backgroundColor = UIColor(hexString: "#5326D6") - mTopCenterTypeButton.updateBtnEdgeInsets(style: .Left, space: 5) - - - //展示弹出列表尾部 - if isPlaying { - //正在串流中 --- 按钮显示为【结束串流】 - menuView.showFooterView(isShow: true, showText: NSLocalizedString("结束串流", comment: "")) - mTopCenterTypeButton.setTitle(NSLocalizedString("外部串流中", comment: ""), for: UIControl.State.normal) - }else{ - //未串流 --- 按钮显示为【开始串流】 - menuView.showFooterView(isShow: true, showText: NSLocalizedString("开始串流", comment: "")) - mTopCenterTypeButton.setTitle(NSLocalizedString("已连接外部设备", comment: ""), for: UIControl.State.normal) - } - - - }else{ - //未连接 - print("未连接") - link = false - isPlaying = false - // 当前未连接到 AirPlay 设备 - playerController!.player!.usesExternalPlaybackWhileExternalScreenIsActive = false - playerController!.player!.allowsExternalPlayback = false - - if self.selectedIndex == .monocular2D { - mTopCenterTypeButton.setTitle(NSLocalizedString("单眼2D", comment: ""), for: UIControl.State.normal) - }else if self.selectedIndex == .redBlueSolid { - mTopCenterTypeButton.setTitle(NSLocalizedString("红蓝立体", comment: ""), for: UIControl.State.normal) - }else if self.selectedIndex == .crossedEyes { - mTopCenterTypeButton.setTitle(NSLocalizedString("交叉眼", comment: ""), for: UIControl.State.normal) - } - else if self.selectedIndex == .parallelEyes { - mTopCenterTypeButton.setTitle(NSLocalizedString("平行眼", comment: ""), for: UIControl.State.normal) - } - - mTopCenterTypeButton.setImage(UIImage.init(named: "type_button_arrow_down"), for: .normal) - mTopCenterTypeButton.setTitleColor(UIColor.white, for: UIControl.State.normal) - mTopCenterTypeButton.layer.borderColor = UIColor.white.cgColor - mTopCenterTypeButton.backgroundColor = UIColor(hexString: "#1F1E20") - mTopCenterTypeButton.updateBtnEdgeInsets(style: .Right, space: 10) - - //隐藏弹出列表尾部 - menuView.showFooterView(isShow: false, showText: "") - + releaseVideoComposition() + + //已连接 + if(isScreenMirroring){ + self.dealTaskWhenExternalScreenConnect() + + + }else{ + //未连接 + self.dealTaskWhenExternalScreenDisConnect() + } + + + } + + //激活一下session + func activeSession(){ + do { + try AVAudioSession.sharedInstance().setActive(true) + try AVAudioSession.sharedInstance().setCategory(.playback,options: .allowAirPlay) + } + catch { + print("err: set audiosession:\(error)") } } + //当外接屏幕连接时 + func dealTaskWhenExternalScreenConnect(){ + if link == true { + return + } + + link = true + isPlaying = true + let playerItem = self.getPlayerItem() + player?.replaceCurrentItem(with: playerItem) + print("外接屏幕已连接.....") + activeSession() + + UIApplication.shared.connectedScenes.forEach { us in + print("uisence:\(us)\n") + let ws = us as! UIWindowScene + if ws.session.role.rawValue == "UIWindowSceneSessionRoleExternalDisplayNonInteractive"{ + externalVC = ws.windows.first?.rootViewController as? ZZHExternalViewController + if let evc = externalVC { + if let ed = externalDispalylink { + externalDispalylink?.invalidate() + externalDispalylink = nil + } + externalDispalylink = ws.windows.first?.screen.displayLink(withTarget: self, selector: #selector(displayUpdate(caDisplayLink:))) + externalDispalylink?.add(to: RunLoop.main, forMode: RunLoop.Mode.common) + + } + + } + } + + + //串流播放中 + mTopCenterTypeButton.setImage(UIImage.init(named: "linked_button"), for: .normal) + mTopCenterTypeButton.setTitleColor(UIColor(hexString: "#D0C0FF"), for: .normal) + mTopCenterTypeButton.layer.borderColor = UIColor(hexString: "#D0C0FF").cgColor + mTopCenterTypeButton.backgroundColor = UIColor(hexString: "#5326D6") + mTopCenterTypeButton.updateBtnEdgeInsets(style: .Left, space: 5) + + + //展示弹出列表尾部 + if isPlaying { + //正在串流中 --- 按钮显示为【结束串流】 + menuView.showFooterView(isShow: true, showText: NSLocalizedString("结束串流", comment: "")) + mTopCenterTypeButton.setTitle(NSLocalizedString("外部串流中", comment: ""), for: UIControl.State.normal) + }else{ + //未串流 --- 按钮显示为【开始串流】 + menuView.showFooterView(isShow: true, showText: NSLocalizedString("开始串流", comment: "")) + mTopCenterTypeButton.setTitle(NSLocalizedString("已连接外部设备", comment: ""), for: UIControl.State.normal) + } + } + + //当外接屏幕断开时 + func dealTaskWhenExternalScreenDisConnect(){ + print("外接屏幕已断开.....") + let playerItem = self.getPlayerItem() + player?.replaceCurrentItem(with: playerItem) + + link = false + isPlaying = false + // 当前未连接到 AirPlay 设备 + if self.selectedIndex == .monocular2D { + mTopCenterTypeButton.setTitle(NSLocalizedString("单眼2D", comment: ""), for: UIControl.State.normal) + }else if self.selectedIndex == .redBlueSolid { + mTopCenterTypeButton.setTitle(NSLocalizedString("红蓝立体", comment: ""), for: UIControl.State.normal) + }else if self.selectedIndex == .crossedEyes { + mTopCenterTypeButton.setTitle(NSLocalizedString("交叉眼", comment: ""), for: UIControl.State.normal) + } + else if self.selectedIndex == .parallelEyes { + mTopCenterTypeButton.setTitle(NSLocalizedString("平行眼", comment: ""), for: UIControl.State.normal) + } + + mTopCenterTypeButton.setImage(UIImage.init(named: "type_button_arrow_down"), for: .normal) + mTopCenterTypeButton.setTitleColor(UIColor.white, for: UIControl.State.normal) + mTopCenterTypeButton.layer.borderColor = UIColor.white.cgColor + mTopCenterTypeButton.backgroundColor = UIColor(hexString: "#1F1E20") + mTopCenterTypeButton.updateBtnEdgeInsets(style: .Right, space: 10) + + //隐藏弹出列表尾部 + menuView.showFooterView(isShow: false, showText: "") + externalVC?.playerLayer?.player = nil + self.playerController?.player = player + player?.play() + } + + @objc func displayUpdate(caDisplayLink:CADisplayLink) { + if let has_exvc = externalVC { + if has_exvc.playerLayer?.player == nil { + has_exvc.imageView?.isHidden = true + has_exvc.playerLayer?.isHidden = false + self.playerController?.player = nil + has_exvc.playerLayer?.player = player + player?.play() +// externalDispalylink?.invalidate() +// externalDispalylink = nil + } + } + + } + + deinit { print("patialvideodisplaycontroler deinit......") - self.player?.currentItem?.videoComposition = nil - + releaseVideoComposition() assetReader?.cancelReading() NotificationCenter.default.removeObserver(self) } + func releaseVideoComposition() { + if let ed = externalDispalylink { + externalDispalylink?.invalidate() + externalDispalylink = nil + } + self.player?.currentItem?.videoComposition = nil + self.player?.replaceCurrentItem(with: nil) + } + //MARK: - action @objc public func navgationButtonClick2(sender:UIButton){ diff --git a/SwiftProject/SwiftProject/Project/Controller/RecordingVideo/VRVideoTransformController.swift b/SwiftProject/SwiftProject/Project/Controller/RecordingVideo/VRVideoTransformController.swift index afdf33d..ec61147 100644 --- a/SwiftProject/SwiftProject/Project/Controller/RecordingVideo/VRVideoTransformController.swift +++ b/SwiftProject/SwiftProject/Project/Controller/RecordingVideo/VRVideoTransformController.swift @@ -113,6 +113,11 @@ class VRVideoTransformController: BaseController { Analytics.logEvent("transcode_video_pv", parameters: ["refer_page":"视频转码页面","duration":sec]) } + override func viewWillDisappear(_ animated: Bool) { + super.viewWillDisappear(animated) + self.mAvPlayer?.player?.pause() + } + deinit { print("deinit--class:\(String(describing: object_getClass(self))) objc:\(self)") }