自定义播放器在拖动播放时还有些问题,后面再来优化

This commit is contained in:
bluesea 2024-04-18 15:00:13 +08:00
parent a73cb139a4
commit c228bc37ee
13 changed files with 1146 additions and 149 deletions

View File

@ -21,6 +21,7 @@
006B61DE2BBCFB45003FCB49 /* CustomSheetCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 006B61DD2BBCFB45003FCB49 /* CustomSheetCell.swift */; };
0073BD142BCE80F700721885 /* ZZHCustomPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0073BD132BCE80F700721885 /* ZZHCustomPlayer.swift */; };
0073BD182BCF7B3400721885 /* ZZHCustomSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0073BD172BCF7B3400721885 /* ZZHCustomSlider.swift */; };
0073BD1A2BCFC8E800721885 /* ZZHCustomPlayerForVideoTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0073BD192BCFC8E800721885 /* ZZHCustomPlayerForVideoTask.swift */; };
009661F82BAD6C7100FCA65F /* CCSpaceAlbumFilterPopView2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 009661F72BAD6C7100FCA65F /* CCSpaceAlbumFilterPopView2.swift */; };
009661FA2BAD876200FCA65F /* PhotosUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 009661F92BAD876200FCA65F /* PhotosUI.framework */; };
009661FC2BADB20D00FCA65F /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 009661FB2BADB20D00FCA65F /* CoreMotion.framework */; };
@ -28,7 +29,6 @@
009662462BB3B39900FCA65F /* External.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 009662452BB3B39900FCA65F /* External.storyboard */; };
0096624A2BB3B45200FCA65F /* ExternalSceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 009662492BB3B45200FCA65F /* ExternalSceneDelegate.swift */; };
0096624D2BB3BA3B00FCA65F /* ZZHExternalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0096624C2BB3BA3B00FCA65F /* ZZHExternalViewController.swift */; };
0096625A2BB552E700FCA65F /* CCSpatialVideoDisplayForVideoTask.swift in Sources */ = {isa = PBXBuildFile; fileRef = 009662592BB552E700FCA65F /* CCSpatialVideoDisplayForVideoTask.swift */; };
009DFB032BC63AF0007B56E8 /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 009DFB022BC63AF0007B56E8 /* CoreImage.framework */; };
009DFB0E2BC8CFA2007B56E8 /* FeedbackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 009DFB0D2BC8CFA2007B56E8 /* FeedbackView.swift */; };
009DFB112BC8E2E9007B56E8 /* MenuVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 009DFB102BC8E2E9007B56E8 /* MenuVC.swift */; };
@ -130,6 +130,9 @@
006B61DD2BBCFB45003FCB49 /* CustomSheetCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomSheetCell.swift; sourceTree = "<group>"; };
0073BD132BCE80F700721885 /* ZZHCustomPlayer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZZHCustomPlayer.swift; sourceTree = "<group>"; };
0073BD172BCF7B3400721885 /* ZZHCustomSlider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZZHCustomSlider.swift; sourceTree = "<group>"; };
0073BD192BCFC8E800721885 /* ZZHCustomPlayerForVideoTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZZHCustomPlayerForVideoTask.swift; sourceTree = "<group>"; };
0073BD1B2BCFCC4500721885 /* CCSpatialVideoDisplayController1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CCSpatialVideoDisplayController1.swift; sourceTree = "<group>"; };
0073BD1D2BCFCC6900721885 /* CCSpatialVideoDisplayForVideoTask1.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CCSpatialVideoDisplayForVideoTask1.swift; sourceTree = "<group>"; };
009661F72BAD6C7100FCA65F /* CCSpaceAlbumFilterPopView2.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CCSpaceAlbumFilterPopView2.swift; sourceTree = "<group>"; };
009661F92BAD876200FCA65F /* PhotosUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = PhotosUI.framework; path = System/Library/Frameworks/PhotosUI.framework; sourceTree = SDKROOT; };
009661FB2BADB20D00FCA65F /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = System/Library/Frameworks/CoreMotion.framework; sourceTree = SDKROOT; };
@ -137,7 +140,6 @@
009662452BB3B39900FCA65F /* External.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = External.storyboard; sourceTree = "<group>"; };
009662492BB3B45200FCA65F /* ExternalSceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalSceneDelegate.swift; sourceTree = "<group>"; };
0096624C2BB3BA3B00FCA65F /* ZZHExternalViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZZHExternalViewController.swift; sourceTree = "<group>"; };
009662592BB552E700FCA65F /* CCSpatialVideoDisplayForVideoTask.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CCSpatialVideoDisplayForVideoTask.swift; sourceTree = "<group>"; };
009DFB022BC63AF0007B56E8 /* CoreImage.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreImage.framework; path = System/Library/Frameworks/CoreImage.framework; sourceTree = SDKROOT; };
009DFB0D2BC8CFA2007B56E8 /* FeedbackView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedbackView.swift; sourceTree = "<group>"; };
009DFB102BC8E2E9007B56E8 /* MenuVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuVC.swift; sourceTree = "<group>"; };
@ -285,6 +287,15 @@
path = CustomSheetController;
sourceTree = "<group>";
};
0072361D2BD0EEFC000595A9 /* deapt */ = {
isa = PBXGroup;
children = (
0073BD1B2BCFCC4500721885 /* CCSpatialVideoDisplayController1.swift */,
0073BD1D2BCFCC6900721885 /* CCSpatialVideoDisplayForVideoTask1.swift */,
);
path = deapt;
sourceTree = "<group>";
};
0096624B2BB3BA0100FCA65F /* ExternalScreen */ = {
isa = PBXGroup;
children = (
@ -298,9 +309,10 @@
009662582BB5527200FCA65F /* CCSpatialVideoDisplayController */ = {
isa = PBXGroup;
children = (
0072361D2BD0EEFC000595A9 /* deapt */,
1E1EA2932B9364F000A5D5D2 /* CCSpatialVideoDisplayController.swift */,
009662592BB552E700FCA65F /* CCSpatialVideoDisplayForVideoTask.swift */,
0073BD132BCE80F700721885 /* ZZHCustomPlayer.swift */,
0073BD192BCFC8E800721885 /* ZZHCustomPlayerForVideoTask.swift */,
0073BD172BCF7B3400721885 /* ZZHCustomSlider.swift */,
);
path = CCSpatialVideoDisplayController;
@ -784,6 +796,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
0073BD1A2BCFC8E800721885 /* ZZHCustomPlayerForVideoTask.swift in Sources */,
AF2120CC2B4E973800400B7F /* CCInputTextField.swift in Sources */,
AF2120C72B4E95DA00400B7F /* UIColor+Add.swift in Sources */,
AF2120C52B4E95DA00400B7F /* UIButton+Add.swift in Sources */,
@ -863,7 +876,6 @@
1E02C9322B8990C600DD3143 /* CCDeviceOperationListView.swift in Sources */,
AF2120DA2B4E9BD400400B7F /* CCAlert.swift in Sources */,
006B61D12BBA5DB4003FCB49 /* MembershipProductView.swift in Sources */,
0096625A2BB552E700FCA65F /* CCSpatialVideoDisplayForVideoTask.swift in Sources */,
1EFB8C702B88DA4800C72119 /* CCBottomMenuCell.swift in Sources */,
AF2120FA2B4EA5BD00400B7F /* CCHomeController.swift in Sources */,
0073BD182BCF7B3400721885 /* ZZHCustomSlider.swift in Sources */,

View File

@ -515,9 +515,9 @@
filePath = "SwiftProject/Project/Controller/RecordingVideo/CCSpatialVideoDisplayController/CCSpatialVideoDisplayController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "388"
endingLineNumber = "388"
landmarkName = "viewDidAppear(_:)"
startingLineNumber = "340"
endingLineNumber = "340"
landmarkName = "notification_didActiveNotification(notification:)"
landmarkType = "7">
</BreakpointContent>
</BreakpointProxy>
@ -531,9 +531,9 @@
filePath = "SwiftProject/Project/Controller/RecordingVideo/CCSpatialVideoDisplayController/CCSpatialVideoDisplayController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "552"
endingLineNumber = "552"
landmarkName = "displayUpdate(caDisplayLink:)"
startingLineNumber = "498"
endingLineNumber = "498"
landmarkName = "updateTopCenterButtonWhenIsPlayingChange()"
landmarkType = "7">
<Locations>
<Location
@ -581,6 +581,21 @@
endingLineNumber = "552"
offsetFromSymbolStart = "56">
</Location>
<Location
uuid = "BB183D45-3193-4FC7-92DB-275D529A4AE6 - 1f02ddc6d27b6aec"
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
symbolName = "SwiftProject.CCSpatialVideoDisplayController.updateTopCenterButtonWhenIsPlayingChange() -&gt; ()"
moduleName = "SwiftProject"
usesParentBreakpointCondition = "Yes"
urlString = "file:///Users/aaa/Documents/IOS%20Dev/VR/SwiftProject/SwiftProject/Project/Controller/RecordingVideo/CCSpatialVideoDisplayController/CCSpatialVideoDisplayController.swift"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "497"
endingLineNumber = "497"
offsetFromSymbolStart = "1248">
</Location>
</Locations>
</BreakpointContent>
</BreakpointProxy>

View File

@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "icon@1x.png",
"filename" : "play.png",
"idiom" : "universal",
"scale" : "1x"
},

Binary file not shown.

Before

Width:  |  Height:  |  Size: 741 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -54,9 +54,7 @@ class CCSpatialVideoDisplayController: BaseController {
(icon:"type_check",title:NSLocalizedString("交叉眼", comment: ""),isHiden:false)]
}
//UI
// DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: {
self.setttinisScreenMirroring(isScreenMirroring: self.isAirPlayActive)
// })
self.setttinisScreenMirroring(isScreenMirroring: self.isAirPlayActive)
}
@ -77,12 +75,7 @@ class CCSpatialVideoDisplayController: BaseController {
return label
}()
var assetReader:AVAssetReader?
var assetOutput:AVAssetReaderTrackOutput?
var assetTrack:AVAssetTrack?
let kNowTimeToUserDefaultKey_VideoDisplayController:String = "kNowTimeToUserDefaultKey_VideoDisplayController"
var link = false//
var isPlaying = false {//
@ -95,17 +88,18 @@ class CCSpatialVideoDisplayController: BaseController {
{
didSet{
//
customPlayer.selectedIndex = selectedIndex
}
}
let videoTranserConvertor = PlayByTransferConvertor()
// let videoTranserConvertor = PlayByTransferConvertor()
lazy var videoOriginalAsset:AVAsset = {
let asset = AVAsset(url: sourceVideoURL!)
return asset
}()
// lazy var videoOriginalAsset:AVAsset = {
// let asset = AVAsset(url: sourceVideoURL!)
// return asset
// }()
var videoOriginalPHAsset:PHAsset?
@ -113,13 +107,16 @@ class CCSpatialVideoDisplayController: BaseController {
var sourceVideoURL:URL?
var imgData:Data?
var player:AVPlayer?
// var player:AVPlayer?
// var needRestReaderTimeRange = false//
var playerController:AVPlayerViewController?
// var playerController:AVPlayerViewController?
var customPlayer:ZZHCustomPlayer = {
let cp = ZZHCustomPlayer(frame: .zero)
return cp
}()
lazy var mTopImgView:UIImageView = {
//393*236
// let view = UIImageView(frame: CGRect(x: 0, y: 0, width: SCREEN_Width, height: SCREEN_Height * 236/393))
let view = UIImageView(frame: CGRect(x: 0, y: 0, width: SCREEN_Width, height: 236))
view.image = UIImage.init(named: "BG_Top")
@ -218,9 +215,6 @@ class CCSpatialVideoDisplayController: BaseController {
let img2:UIImage = UIImage.init(named: NSLocalizedString("displayvc_desc", comment: ""))!
button.setImage(img2, for: UIControl.State.normal)
button.frame = CGRect(x: 0, y: 0, width: 173, height: 42)
// button.titleLabel?.font = KFont_Regular(14)
// button.titleLabel?.adjustsFontSizeToFitWidth = true
// button.updateBtnEdgeInsets(style: .Left, space: 8)
button.centerY = progressView.top - 70
button.centerX = self.view.centerX
@ -229,36 +223,13 @@ class CCSpatialVideoDisplayController: BaseController {
//
@objc func notification_PlayerEndTime(notification:Notification){
print("PlayerEndTime....")
player?.seek(to: .zero)
player?.play()
//
// self.playerController?.view.layer.sublayers?.forEach({ clayer in
// print("clayer.......\(clayer.self)")
// clayer.backgroundColor = UIColor.red.cgColor
// clayer.sublayers?.forEach({ sclayer in
// print("sclayer.......\(sclayer.self)")
// sclayer.backgroundColor = UIColor.blue.cgColor
// sclayer.sublayers?.forEach({ sscalyer in
// print("sscalyer.......\(sscalyer.self)")
// if let avPlayerLayer = sscalyer as? AVPlayerLayer {
// sscalyer.backgroundColor = UIColor.orange.cgColor
// sscalyer.sublayers?.forEach({ avSubLayer in
// print("avSubLayer.......\(avSubLayer.self)")
// avSubLayer.backgroundColor = UIColor.systemPink.cgColor
// if let avaPlayerLayer2 = avSubLayer as? AVPlayerLayer {
// avaPlayerLayer2.backgroundColor = UIColor.white.cgColor
//
// }
// })
// }
//
// })
// })
// })
// @objc func notification_PlayerEndTime(notification:Notification){
// print("PlayerEndTime....")
// player?.seek(to: .zero)
// player?.play()
}
// }
//
// @objc func notification_PlayerTimeJump(notification:Notification){
@ -273,38 +244,41 @@ class CCSpatialVideoDisplayController: BaseController {
super.viewDidLoad()
configureUI()
ZZHHelper.setNowTimeToUserDefaultWithKey(kNowTimeToUserDefaultKey_VideoDisplayController)
Task {
print("ccs viewdid load ---------")
await self.loadVideoAssetReader()
DispatchQueue.main.asyncAfter(deadline: .now()+0.01) {[weak self] in
self?.setUPPlayer()
// AirPlay
self?.checkAirPlayStatus()
}
}
// Task {
// print("ccs viewdid load ---------")
// await self.loadVideoAssetReader()
// DispatchQueue.main.asyncAfter(deadline: .now()+0.01) {[weak self] in
// self?.setUPPlayer()
//
//
//
//
// }
// }
self.customPlayer.setUPPlayer()
// AirPlay
self.checkAirPlayStatus()
}
func setUPPlayer(){
print("getPlayerItem ========")
player = AVPlayer()
player?.allowsExternalPlayback = true
player?.usesExternalPlaybackWhileExternalScreenIsActive = true
print("getPlayerItem >>>>>>>")
playerController = AVPlayerViewController()
playerController?.player = player
playerController!.view.backgroundColor = .clear
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.maskLabel.frame = playerController!.view.frame
self.view.addSubview(self.maskLabel)
}
// func setUPPlayer(){
// print("getPlayerItem ========")
// player = AVPlayer()
// player?.allowsExternalPlayback = true
// player?.usesExternalPlaybackWhileExternalScreenIsActive = true
//
// print("getPlayerItem >>>>>>>")
//
// playerController = AVPlayerViewController()
// playerController?.player = player
// playerController!.view.backgroundColor = .clear
// 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.maskLabel.frame = playerController!.view.frame
// self.view.addSubview(self.maskLabel)
// }
func configureUI(){
@ -322,7 +296,20 @@ class CCSpatialVideoDisplayController: BaseController {
navtionBar?.addSubview(mTopCenterTypeButton)
self.view.addSubview(tipsButton)
self.view.addSubview(self.customPlayer)
self.customPlayer.snp.makeConstraints { make in
make.left.right.centerY.equalToSuperview()
make.height.equalTo(460)
}
self.customPlayer.sourceVideoURL = sourceVideoURL
self.view.addSubview(self.maskLabel)
self.maskLabel.snp.makeConstraints { make in
make.left.equalTo(customPlayer.snp.left)
make.right.equalTo(customPlayer.snp.right)
make.top.equalTo(customPlayer.snp.top)
make.bottom.equalTo(customPlayer.snp.bottom)
}
@ -334,7 +321,7 @@ class CCSpatialVideoDisplayController: BaseController {
NotificationCenter.default.addObserver(self, selector: #selector(notification_PlayerEndTime(notification:)), name: AVPlayerItem.didPlayToEndTimeNotification, object: nil)
// NotificationCenter.default.addObserver(self, selector: #selector(notification_PlayerEndTime(notification:)), name: AVPlayerItem.didPlayToEndTimeNotification, object: nil)
// NotificationCenter.default.addObserver(self, selector: #selector(notification_PlayerTimeJump(notification:)), name: AVPlayerItem.timeJumpedNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(notificatin_failedToPlayToEndTimeNotification(notifiation: )), name: AVPlayerItem.failedToPlayToEndTimeNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(notificatin_failedToPlayToEndTimeNotification(notifiation: )), name: AVPlayerItem.newErrorLogEntryNotification, object: nil)
@ -344,7 +331,8 @@ class CCSpatialVideoDisplayController: BaseController {
//
@objc func notification_didEnterBackgroundNotification(notification:Notification) {
player?.pause()
// player?.pause()
customPlayer.play(false)
print("ccs .....notification_didEnterBackgroundNotification")
}
@ -370,7 +358,8 @@ class CCSpatialVideoDisplayController: BaseController {
if externalVC != nil {
externalVC?.playerLayer?.player = nil
}
player?.pause()
// player?.pause()
customPlayer.play(false)
releaseVideoComposition()
let sec:TimeInterval = ZZHHelper.getSecFromUserDefaultByKey(kNowTimeToUserDefaultKey_VideoDisplayController)
@ -385,18 +374,18 @@ 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()
// 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()
}
//MARK: -
@ -462,14 +451,11 @@ class CCSpatialVideoDisplayController: BaseController {
//
func dealTaskWhenExternalScreenConnect(){
// if link == true {
// return
// }
link = true
isPlaying = true
let playerItem = self.getPlayerItem()
player?.replaceCurrentItem(with: playerItem)
// let playerItem = self.getPlayerItem()
// player?.replaceCurrentItem(with: playerItem)
print("外接屏幕已连接.....")
activeSession()
@ -517,8 +503,8 @@ class CCSpatialVideoDisplayController: BaseController {
//
func dealTaskWhenExternalScreenDisConnect(){
print("外接屏幕已断开.....")
let playerItem = self.getPlayerItem()
player?.replaceCurrentItem(with: playerItem)
// let playerItem = self.getPlayerItem()
// player?.replaceCurrentItem(with: playerItem)
link = false
isPlaying = false
@ -543,8 +529,8 @@ class CCSpatialVideoDisplayController: BaseController {
//
menuView.showFooterView(isShow: false, showText: "")
externalVC?.playerLayer?.player = nil
self.playerController?.player = player
player?.play()
// self.playerController?.player = player
// player?.play()
externalVC = nil
}
@ -553,9 +539,9 @@ class CCSpatialVideoDisplayController: BaseController {
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()
// self.playerController?.player = nil
// has_exvc.playerLayer?.player = player
// player?.play()
externalDispalylink?.invalidate()
externalDispalylink = nil
}
@ -567,7 +553,6 @@ class CCSpatialVideoDisplayController: BaseController {
deinit {
print("patialvideodisplaycontroler deinit......")
releaseVideoComposition()
assetReader?.cancelReading()
NotificationCenter.default.removeObserver(self)
// player?.removeObserver(self, forKeyPath: "status")
}
@ -577,8 +562,8 @@ class CCSpatialVideoDisplayController: BaseController {
externalDispalylink?.invalidate()
externalDispalylink = nil
}
self.player?.currentItem?.videoComposition = nil
self.player?.replaceCurrentItem(with: nil)
// self.player?.currentItem?.videoComposition = nil
// self.player?.replaceCurrentItem(with: nil)
}
@ -641,26 +626,28 @@ class CCSpatialVideoDisplayController: BaseController {
isPlaying = false
if self.externalVC != nil {
externalVC?.playerLayer?.player = nil
player?.pause()
// player?.pause()
customPlayer.play(false)
releaseVideoComposition()
DispatchQueue.main.asyncAfter(deadline: .now()+0.15, execute: {[weak self] in
let playerItem = self?.getPlayerItem()
self?.player?.replaceCurrentItem(with: playerItem)
self?.playerController?.player = self?.player
self?.player?.play()
// let playerItem = self?.getPlayerItem()
// self?.player?.replaceCurrentItem(with: playerItem)
// self?.playerController?.player = self?.player
// self?.player?.play()
})
}
}
else {//
if self.externalVC != nil {
self.playerController?.player = nil
player?.pause()
releaseVideoComposition()
let playerItem = self.getPlayerItem()
player?.replaceCurrentItem(with: playerItem)
externalVC?.playerLayer?.player = player
player?.play()
// self.playerController?.player = nil
// player?.pause()
// releaseVideoComposition()
// let playerItem = self.getPlayerItem()
// player?.replaceCurrentItem(with: playerItem)
// externalVC?.playerLayer?.player = player
// player?.play()
isPlaying = true
}
}

View File

@ -9,12 +9,36 @@ import Foundation
import UIKit
import AVKit
class ZZHCustomPlayer: UIView {
//
var sourceVideoURL:URL?
var assetTrack:AVAssetTrack?
lazy var videoOriginalAsset:AVAsset = {
let asset = AVAsset(url: sourceVideoURL!)
return asset
}()
var assetReader:AVAssetReader?
var assetOutput:AVAssetReaderTrackOutput?
let videoTranserConvertor = PlayByTransferConvertor()
var selectedIndex:SpatialType = .parallelEyes//
{
didSet{
//
}
}
//ui
var playerLayerBgView:UIView?
var avPlayer:AVPlayer?
var avPlayerLayer:AVPlayerLayer?
var timeSlider:ZZHCustomSlider?
var prePlayingState:Bool?// ,player,便
let playerPauseBgColor:UIColor = UIColor(r: 245, g: 245, b: 245, a: 0.2)//
let playerPauseBgColor:UIColor = UIColor(r: 20, g: 20, b: 20, a: 0.2)//
//线
// let lock = NSLock()
lazy var maskPlayerView:UIView? = {//
let bgView = UIView()
@ -24,7 +48,7 @@ class ZZHCustomPlayer: UIView {
self.playStateImgView.snp.makeConstraints { make in
make.centerX.centerY.equalToSuperview()
make.width.height.equalTo(40)
make.width.height.equalTo(80)
}
let btn = UIButton()
@ -42,8 +66,25 @@ class ZZHCustomPlayer: UIView {
return imgView
}()
deinit {
print("zzhcustomplayer deinit......")
releaseVideoComposition()
assetReader?.cancelReading()
NotificationCenter.default.removeObserver(self)
}
func releaseVideoComposition() {
self.avPlayer?.currentItem?.videoComposition = nil
self.avPlayer?.replaceCurrentItem(with: nil)
}
override init(frame: CGRect) {
super.init(frame: frame)
NotificationCenter.default.addObserver(self, selector: #selector(notification_PlayerEndTime(notification:)), name: AVPlayerItem.didPlayToEndTimeNotification, object: nil)
let playerWidth = KScreenWidth
let playerHeight = 200
playerLayerBgView = UIView()
@ -54,10 +95,14 @@ class ZZHCustomPlayer: UIView {
make.height.equalTo(playerHeight)
}
avPlayer = AVPlayer()
avPlayer?.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: self.avPlayer?.currentItem?.duration.timescale ?? 600), queue: DispatchQueue.main, using: {[weak self] ct in
self?.updateSliderUI(ct: ct)
})
avPlayerLayer = AVPlayerLayer(player: avPlayer)
avPlayerLayer?.frame = CGRect(x: 0, y: 0, width: Int(playerWidth), height: playerHeight)
playerLayerBgView!.layer.addSublayer(avPlayerLayer!)
playerLayerBgView?.backgroundColor = UIColor.orange
playerLayerBgView?.backgroundColor = UIColor.clear
self.maskPlayerView?.frame = avPlayerLayer!.frame
playerLayerBgView?.addSubview(maskPlayerView!)
@ -65,8 +110,8 @@ class ZZHCustomPlayer: UIView {
timeSlider = ZZHCustomSlider(frame: .zero)
timeSlider?.processChangeValueCallback = { (value,isMoving) in
print("value:\(value) isMoving:\(isMoving)")
timeSlider?.processChangeValueCallback = {[weak self] (value,isMoving) in
self?.manualToSeekPlay(value:value,isMoving: isMoving)
}
self.addSubview(timeSlider!)
timeSlider!.snp.makeConstraints { make in
@ -75,8 +120,57 @@ class ZZHCustomPlayer: UIView {
make.bottom.equalToSuperview().offset(0)
make.height.equalTo(120)
}
}
//sliderseek
func manualToSeekPlay(value:Float,isMoving:Bool){
if isMoving {
self.play(false)
}
else {
let totalSec = CMTimeGetSeconds((self.avPlayer?.currentItem?.duration)!)
var atSec = Float(totalSec) * value
var timeScale:CMTimeScale? = self.avPlayer?.currentItem?.duration.timescale
if let ts = timeScale {
atSec = atSec * Float(ts)
}
else {
timeScale = CMTimeScale(1)
}
let ct = CMTime(value:CMTimeValue(atSec) , timescale: timeScale!)
quickLoadAReaderWhenSeek(startCT: ct)
// self.releaseVideoComposition()
// self.avPlayer?.replaceCurrentItem(with: self.getPlayerItem())
print("正在seek.....\(ct)")
self.avPlayer?.seek(to: ct,toleranceBefore:.zero,toleranceAfter: .zero, completionHandler: {[weak self] finished in
if finished {
self?.quickLoadAReaderWhenSeek(startCT: ct)
self?.play(true)
}
print("seek result:\(finished)")
})
}
}
//
func setUPPlayer() {
Task {[weak self] in
await self?.loadVideoAssetReader()
self?.avPlayer?.replaceCurrentItem(with: self?.getPlayerItem())
self?.play(true)
}
}
//
private func reLoadPlay(){
self.releaseVideoComposition()
self.avPlayer?.replaceCurrentItem(with: self.getPlayerItem())
self.play(true)
}
//
@ -107,12 +201,24 @@ class ZZHCustomPlayer: UIView {
updatePlayMaskView(value)
}
// func seek(ct:CMTime) {
// self.avPlayer?.seek(to: ct)
// }
//
func updatePlayMaskView(_ value:Bool) {
playStateImgView.isHidden = value
self.maskPlayerView?.backgroundColor = value ? .clear : playerPauseBgColor
}
//slider ui
func updateSliderUI(ct:CMTime) {
let sec = CMTimeGetSeconds(ct)
let totalSec = CMTimeGetSeconds((self.avPlayer?.currentItem?.duration)!)
let s = sec / totalSec
self.timeSlider?.exUpdateProcessValue(value: Float(s),currSec: Int(sec),totalSec: Int(totalSec))
}
override func draw(_ rect: CGRect) {
super.draw(rect)
@ -121,4 +227,25 @@ class ZZHCustomPlayer: UIView {
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//MARK: -
//MARK: -
//
@objc func notification_PlayerEndTime(notification:Notification){
print("PlayerEndTime....")
// self.quickLoadAReaderWhenReplayBack()
avPlayer?.seek(to: .zero,toleranceBefore: .zero,toleranceAfter: .zero,completionHandler: {[weak self] finish in
self?.quickLoadAReaderWhenReplayBack()
self?.avPlayer?.play()
})
}
}

View File

@ -0,0 +1,162 @@
//
// ZZHCustomPlayerForVideoTask.swift
// SwiftProject
//
// Created by aaa on 2024/4/17.
//
import Foundation
import AVFoundation
import Photos
import AVKit
import VideoToolbox
extension ZZHCustomPlayer {
func getPlayerItem() -> AVPlayerItem {
let temItem = AVPlayerItem(asset: self.videoOriginalAsset)
AVVideoComposition.videoComposition(with: temItem.asset) { [weak self] request in
print("正在请求解码图片frame....")
guard let weakSelf = self else {
print("self 被销毁了.....")
return
}
// self?.lock.lock()
weakSelf.convertFrame(request:request)
// self?.lock.unlock()
} completionHandler: { ac, err in
if err != nil {
print("初始化coposition报错\(err)")
}
else{
print("composition 生成ok....")
temItem.videoComposition = ac
}
}
return temItem
}
func convertFrame(request:AVAsynchronousCIImageFilteringRequest){
let compositionTime = request.compositionTime
let end:CMTime = CMTimeMake(value: Int64(compositionTime.value+1), timescale: compositionTime.timescale)
let tr = CMTimeRange(start: compositionTime, end: end)
var ciImg:CIImage? = nil
switch self.selectedIndex {
case .monocular2D://2d
ciImg = request.sourceImage
break
default :
ciImg = self.otherModeImgWithMode(mode: self.selectedIndex,tr:tr,compositionTime: compositionTime)
break
}
if let ciImg {
request.finish(with: ciImg, context: nil)
}
else {
print("未合成成功.....")
request.finish(with: request.sourceImage, context: nil)
}
}
func otherModeImgWithMode(mode:SpatialType,tr:CMTimeRange,compositionTime:CMTime)->CIImage? {
guard let ao = self.assetOutput else {
print("assetOutput 应该是没有被创建成功.....")
return nil
}
var ciImg:CIImage? = nil
switch mode {
case .crossedEyes://
ciImg = self.videoTranserConvertor.convertVideo(asset: self.videoOriginalAsset, assetOutput: ao, type: self.selectedIndex, time: compositionTime)
break
case .fsbs://3d
ciImg = self.videoTranserConvertor.convertVideo(asset: self.videoOriginalAsset, assetOutput: ao, type: self.selectedIndex, time: compositionTime)
break
case .hsbs://3d
ciImg = self.videoTranserConvertor.convertVideo(asset: self.videoOriginalAsset, assetOutput: ao, type: self.selectedIndex, time: compositionTime)
break
case .parallelEyes://
ciImg = self.videoTranserConvertor.convertVideo(asset: self.videoOriginalAsset, assetOutput: ao, type: self.selectedIndex, time: compositionTime)
break
case .redBlueSolid://
ciImg = self.videoTranserConvertor.convertVideo(asset: self.videoOriginalAsset, assetOutput: ao, type: self.selectedIndex, time: compositionTime)
break
default:
break
}
return ciImg
}
//assetReaderoutput
func loadVideoAssetReader() async {
do {
if self.assetTrack == nil {
assetTrack = try await self.videoOriginalAsset.loadTracks(withMediaType: .video).first!
}
let timeRange = CMTimeRange(start: .zero, duration: .positiveInfinity)
DispatchQueue.main.async {
self.quickLoadAReader(timeRange: timeRange)
}
} catch {
print("Error loading video: \(error)")
}
}
func quickLoadAReader(timeRange:CMTimeRange) {
// self.lock.lock()
if(assetReader != nil){
assetReader?.cancelReading()
}
assetReader = try! AVAssetReader(asset: self.videoOriginalAsset)
quickLoadAssetOutput()
assetReader!.timeRange = timeRange
assetReader!.add(assetOutput!)
assetReader!.startReading()
// self.lock.unlock()
}
//slider
func quickLoadAReaderWhenSeek(startCT:CMTime) {
let timeRange = CMTimeRange(start: startCT, duration: .positiveInfinity)
self.quickLoadAReader(timeRange: timeRange)
}
//,assetreadertimeRange
func quickLoadAReaderWhenReplayBack() {
let timeRange = CMTimeRange(start: .zero, duration: .positiveInfinity)
self.quickLoadAReader(timeRange: timeRange)
}
func quickLoadAssetOutput() {
if(assetOutput != nil){
assetOutput?.markConfigurationAsFinal()
assetOutput = nil
}
assetOutput = AVAssetReaderTrackOutput(
track: self.assetTrack!,
outputSettings: [
AVVideoDecompressionPropertiesKey: [
kVTDecompressionPropertyKey_RequestedMVHEVCVideoLayerIDs: [0, 1] as CFArray,
],
]
)
// assetOutput?.supportsRandomAccess = true
// assetOutput?.alwaysCopiesSampleData = false
}
}

View File

@ -15,10 +15,12 @@ class ZZHCustomSlider: UIView {
var timeSlider:CustomSlider?
var processChangeValueCallback:CustomSliderProcessChangeValueCallback?
var preValue:Float = 0.0 //value
var totalSec:Int = -1//
let bgView:UIView = UIView()
deinit {
print("zzhcustomslider....deinit...")
}
override init(frame: CGRect) {
super.init(frame: frame)
@ -83,12 +85,15 @@ class ZZHCustomSlider: UIView {
if isMoving {
var currentValue = max(0, min(value, 1))
//0.x
let formattedValue = String(format: "%.1f", currentValue)
let formattedValue = String(format: "%.2f", currentValue)
currentValue = Float(formattedValue)!
//2
if currentValue > preValue || currentValue < preValue {
preValue = currentValue
processChangeValueCallback(preValue,isMoving)
if self.totalSec > 0 {//
self.sLabel?.text = ZZHHelper.formatVideoTime(second: Int(preValue*Float(self.totalSec)))
}
}
}
else {
@ -98,9 +103,14 @@ class ZZHCustomSlider: UIView {
}
//
func exUpdateProcessValue(value:Float) {
self.timeSlider!.value = value
preValue = value
func exUpdateProcessValue(value:Float,currSec:Int,totalSec:Int) {
self.totalSec = totalSec
self.sLabel?.text = ZZHHelper.formatVideoTime(second: currSec)
self.eLabel?.text = ZZHHelper.formatVideoTime(second: totalSec)
let formattedValue = String(format: "%.1f", value)
let rv = Float(formattedValue)!
self.timeSlider!.setValue(value, animated: false)
preValue = rv
}

View File

@ -0,0 +1,684 @@
//
// CCSpatialVideoDisplayController.swift
// SwiftProject
//
// Created by Zhang, Joyce on 2024/3/2.
//
import UIKit
import AVFoundation
import Photos
import AVKit
import VideoToolbox
import Firebase
enum SpatialType : Int {
/*
2D
*/
case monocular2D = 1
case parallelEyes = 0
case redBlueSolid = 2
case crossedEyes = 3
//使
case hsbs = 4
case fsbs = 5
}
class CCSpatialVideoDisplayController: BaseController {
var externalDispalylink:CADisplayLink?
var externalVC:ZZHExternalViewController?
var isAirPlayActive:Bool = false {
didSet{
//selectedIndextypeData
if(isAirPlayActive){
selectedIndex = .fsbs//hsbs
typeData = [(icon:"type_check",title:"3D FSBS",isHiden:false),
(icon:"type_check",title:"3D HSBS",isHiden:false)
]
}
else{
selectedIndex = .parallelEyes//monocular2D
typeData = [
(icon:"type_check",title:NSLocalizedString("平行眼", comment: ""),isHiden:false),
(icon:"type_check",title:NSLocalizedString("单眼2D", comment: ""),isHiden:false),
(icon:"type_check",title:NSLocalizedString("红蓝立体", comment: ""),isHiden:false),
(icon:"type_check",title:NSLocalizedString("交叉眼", comment: ""),isHiden:false)]
}
//UI
// DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: {
self.setttinisScreenMirroring(isScreenMirroring: self.isAirPlayActive)
// })
}
}
lazy var maskLabel:UILabel = {
let label = UILabel()
label.numberOfLines = 0
label.textColor = .white
label.font = UIFont.systemFont(ofSize: 14)
label.textAlignment = .center
label.layer.cornerRadius = 6
label.layer.masksToBounds = true
label.backgroundColor = UIColor.colorWithRGB(_r: 60.0, _g: 60.0, _b: 60.0, alpha: 0.1)
label.text = NSLocalizedString("外部串流中", comment: "")
label.isHidden = true
return label
}()
var assetReader:AVAssetReader?
var assetOutput:AVAssetReaderTrackOutput?
var assetTrack:AVAssetTrack?
let kNowTimeToUserDefaultKey_VideoDisplayController:String = "kNowTimeToUserDefaultKey_VideoDisplayController"
var link = false//
var isPlaying = false {//
didSet {
maskLabel.isHidden = !isPlaying
}
}
var selectedIndex:SpatialType = .parallelEyes//
{
didSet{
//
}
}
let videoTranserConvertor = PlayByTransferConvertor()
lazy var videoOriginalAsset:AVAsset = {
let asset = AVAsset(url: sourceVideoURL!)
return asset
}()
var videoOriginalPHAsset:PHAsset?
//
var sourceVideoURL:URL?
var imgData:Data?
var player:AVPlayer?
// var needRestReaderTimeRange = false//
var playerController:AVPlayerViewController?
lazy var mTopImgView:UIImageView = {
//393*236
// let view = UIImageView(frame: CGRect(x: 0, y: 0, width: SCREEN_Width, height: SCREEN_Height * 236/393))
let view = UIImageView(frame: CGRect(x: 0, y: 0, width: SCREEN_Width, height: 236))
view.image = UIImage.init(named: "BG_Top")
return view
}()
lazy var transformButton: UIButton = {
//76*56
let transformButton = UIButton.init(type: UIButton.ButtonType.custom)
transformButton.tag = 201
transformButton.isSelected = false
transformButton.backgroundColor = UIColor(hexString: "#5326D6")
transformButton.addTarget(self, action: #selector(navgationButtonClick2(sender:)), for: UIControl.Event.touchUpInside)
let img2:UIImage = UIImage.init(named: "transform_button" as String)!
transformButton.setImage(img2, for: UIControl.State.normal)
transformButton.frame = CGRect(x: 0, y: 0, width: 56, height: 36)
transformButton.layer.cornerRadius = 18
transformButton.layer.masksToBounds = true
transformButton.centerY = StatuBar_Height + NavBar_Height * 0.5
transformButton.right = SCREEN_Width - 24
return transformButton
}()
lazy var mTopCenterTypeButton: UIButton = {
//173*36
let button = UIButton()
button.backgroundColor = UIColor.hexStringToColor(hexString: "#1F1E20")
button.tag = 202
button.isSelected = false
button.addTarget(self, action: #selector(navgationButtonClick2(sender:)), for: UIControl.Event.touchUpInside)
button.frame = CGRect(x: 2, y: 10, width: SCREEN_Width * 0.4 + 20, height: 36)
button.centerY = StatuBar_Height + NavBar_Height * 0.5
button.centerX = SCREEN_Width * 0.5
button.clipsToBounds = true
button.layer.cornerRadius = 18
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.white.cgColor
button.setTitle(NSLocalizedString("平行眼", comment: ""), for: UIControl.State.normal)
button.setImage(UIImage.init(named: "type_button_arrow_down"), for: .normal)
button.updateBtnEdgeInsets(style: .Right, space: 10)
button.setTitleColor(UIColor.white, for: UIControl.State.normal)
button.titleLabel?.font = KFont_Medium(14)
return button
}()
var typeData:[(icon:String,title:String,isHiden:Bool)] = [(icon:"type_check",title:NSLocalizedString("平行眼", comment: ""),isHiden:false),
(icon:"type_check",title:NSLocalizedString("单眼2D", comment: ""),isHiden:false),
(icon:"type_check",title:NSLocalizedString("红蓝立体", comment: ""),isHiden:false),
(icon:"type_check",title:NSLocalizedString("交叉眼", comment: ""),isHiden:false)]
{
didSet {
menuView.setData(datas: self.typeData)
}
}
lazy var menuView: CCSpatialDisplayTypeView = {
//
let parameters:[CCSpatialDisplayTypeConfigure] = [
.PopMenuTextColor(UIColor.white),
.popMenuItemHeight(40),
.PopMenuTextFont(KFont_Medium(12)),
.PopMenuBackgroudColor(UIColor(hexString: "#1F1E20"))
]
//init (testarrow)
let pointOnScreen = navtionImgView!.convert(CGPointMake(navtionImgView!.centerX, navtionImgView!.bottom), to: KWindow)
let popMenu = CCSpatialDisplayTypeView(menuWidth: SCREEN_Width * 0.4, arrow: pointOnScreen, datas: typeData,configures: parameters){[weak self] in
//dissmiss
self?.mTopCenterTypeButton.setImage(UIImage.init(named: "type_button_arrow_down"), for: .normal)
}
return popMenu
}()
lazy var progressView: UIProgressView = {
var view = UIProgressView (progressViewStyle:.default)
view.frame = CGRect(x: 24, y: SCREEN_Height - KStatusBarHeight - 20, width: SCREEN_Width-48, height: 36)
view.progress = 0.0 //50%
return view
}()
lazy var tipsButton: UIButton = {
//76*56
let button = UIButton.init(type: UIButton.ButtonType.custom)
button.tag = 203
button.backgroundColor = .clear
button.addTarget(self, action: #selector(navgationButtonClick2(sender:)), for: UIControl.Event.touchUpInside)
let img2:UIImage = UIImage.init(named: NSLocalizedString("displayvc_desc", comment: ""))!
button.setImage(img2, for: UIControl.State.normal)
button.frame = CGRect(x: 0, y: 0, width: 173, height: 42)
// button.titleLabel?.font = KFont_Regular(14)
// button.titleLabel?.adjustsFontSizeToFitWidth = true
// button.updateBtnEdgeInsets(style: .Left, space: 8)
button.centerY = progressView.top - 70
button.centerX = self.view.centerX
return button
}()
//
@objc func notification_PlayerEndTime(notification:Notification){
print("PlayerEndTime....")
player?.seek(to: .zero)
player?.play()
//
// self.playerController?.view.layer.sublayers?.forEach({ clayer in
// print("clayer.......\(clayer.self)")
// clayer.backgroundColor = UIColor.red.cgColor
// clayer.sublayers?.forEach({ sclayer in
// print("sclayer.......\(sclayer.self)")
// sclayer.backgroundColor = UIColor.blue.cgColor
// sclayer.sublayers?.forEach({ sscalyer in
// print("sscalyer.......\(sscalyer.self)")
// if let avPlayerLayer = sscalyer as? AVPlayerLayer {
// sscalyer.backgroundColor = UIColor.orange.cgColor
// sscalyer.sublayers?.forEach({ avSubLayer in
// print("avSubLayer.......\(avSubLayer.self)")
// avSubLayer.backgroundColor = UIColor.systemPink.cgColor
// if let avaPlayerLayer2 = avSubLayer as? AVPlayerLayer {
// avaPlayerLayer2.backgroundColor = UIColor.white.cgColor
//
// }
// })
// }
//
// })
// })
// })
}
//
// @objc func notification_PlayerTimeJump(notification:Notification){
//// needRestReaderTimeRange = true
//
// print("time jump....")
//
// }
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
ZZHHelper.setNowTimeToUserDefaultWithKey(kNowTimeToUserDefaultKey_VideoDisplayController)
Task {
print("ccs viewdid load ---------")
await self.loadVideoAssetReader()
DispatchQueue.main.asyncAfter(deadline: .now()+0.01) {[weak self] in
self?.setUPPlayer()
// AirPlay
self?.checkAirPlayStatus()
}
}
}
func setUPPlayer(){
print("getPlayerItem ========")
player = AVPlayer()
player?.allowsExternalPlayback = true
player?.usesExternalPlaybackWhileExternalScreenIsActive = true
print("getPlayerItem >>>>>>>")
playerController = AVPlayerViewController()
playerController?.player = player
playerController!.view.backgroundColor = .clear
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.maskLabel.frame = playerController!.view.frame
self.view.addSubview(self.maskLabel)
}
func configureUI(){
self.view.backgroundColor = UIColor(hexString: "#060507")
//
self.setLeftOneBtnImg(imgStr: "spatial_back_button")
self.setNavgationBarColorImg(color: .clear)
self.setNavgationBarLine(color: .clear)
self.view.addSubview(mTopImgView)
self.view.bringSubviewToFront(self.navtionBar!)
navtionBar?.addSubview(transformButton)
navtionBar?.addSubview(mTopCenterTypeButton)
self.view.addSubview(tipsButton)
// AirPlay
//
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)
// NotificationCenter.default.addObserver(self, selector: #selector(notification_PlayerTimeJump(notification:)), name: AVPlayerItem.timeJumpedNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(notificatin_failedToPlayToEndTimeNotification(notifiation: )), name: AVPlayerItem.failedToPlayToEndTimeNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(notificatin_failedToPlayToEndTimeNotification(notifiation: )), name: AVPlayerItem.newErrorLogEntryNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(notification_didEnterBackgroundNotification(notification: )), name: UIApplication.didEnterBackgroundNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(notification_didActiveNotification(notification: )), name: UIApplication.didBecomeActiveNotification, object: nil)
}
//
@objc func notification_didEnterBackgroundNotification(notification:Notification) {
player?.pause()
print("ccs .....notification_didEnterBackgroundNotification")
}
//
@objc func notification_didActiveNotification(notification:Notification) {
self.checkAirPlayStatus()
print("ccs .....notification_didEnterBackgroundNotification")
}
@objc func notificatin_failedToPlayToEndTimeNotification(notifiation:Notification) {
print("notificatin_failedToPlayToEndTimeNotification....")
}
@objc func notificatin_newErrorLogEntryNotification(notifiation:Notification) {
print("notificatin_newErrorLogEntryNotification....")
}
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])
print(".........ccs viewdid disappear....")
}
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()
}
//MARK: -
@objc private func airPlayStatusDidChange(_ notification: Notification) {
checkAirPlayStatus()
if(isAirPlayActive) {
Analytics.logEvent("streaming_live", parameters: ["refer_page":"视频预览页面"])
ZZHHelper.setNowTimeToUserDefaultWithKey("kNowTimeToUserDefaultKey_VideoDisplayController_airplay")
}
else {
let sec:TimeInterval = ZZHHelper.getSecFromUserDefaultByKey("kNowTimeToUserDefaultKey_VideoDisplayController_airplay")
Analytics.logEvent("streaming_live", parameters: ["refer_page":"视频预览页面","duration":sec])
}
}
@objc func exScreenWillConnectNotification(notification:Notification){
print("exScreenWillConnectNotification>>>>>")
airPlayStatusDidChange( notification)
}
@objc func exScreenDisConnectNotification(notification:Notification){
print("exScreenDisConnectNotification>>>>>")
airPlayStatusDidChange( notification)
}
private func checkAirPlayStatus() {
print("设备连接变化")
let currentRoute = AVAudioSession.sharedInstance().currentRoute
self.isAirPlayActive = currentRoute.outputs.contains { output in
return output.portType == AVAudioSession.Port.HDMI ||
output.portType == AVAudioSession.Port.airPlay
}
}
func setttinisScreenMirroring(isScreenMirroring:Bool){
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 externalVC != nil {
if let ed = externalDispalylink {
ed.invalidate()
}
externalDispalylink = ws.windows.first?.screen.displayLink(withTarget: self, selector: #selector(displayUpdate(caDisplayLink:)))
externalDispalylink?.add(to: RunLoop.main, forMode: RunLoop.Mode.common)
}
}
}
updateTopCenterButtonWhenIsPlayingChange()
}
//,
func updateTopCenterButtonWhenIsPlayingChange() {
//
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()
externalVC = nil
}
@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......")
releaseVideoComposition()
assetReader?.cancelReading()
NotificationCenter.default.removeObserver(self)
// player?.removeObserver(self, forKeyPath: "status")
}
func releaseVideoComposition() {
if externalDispalylink != nil {
externalDispalylink?.invalidate()
externalDispalylink = nil
}
self.player?.currentItem?.videoComposition = nil
self.player?.replaceCurrentItem(with: nil)
}
//MARK: - action
@objc public func navgationButtonClick2(sender:UIButton){
if sender.tag == 200 {
//
}else if sender.tag == 201 {
//
let transVC = VRVideoTransformController()
transVC.videoOriginalPHAsset = self.videoOriginalPHAsset
transVC.sourceVideoURL = sourceVideoURL
self.navigationController?.pushViewController(transVC, animated: true)
Analytics.logEvent("preview_trans_click", parameters: nil)
}else if sender.tag == 202 {
//
menuView.show()
if link {
//
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{
mTopCenterTypeButton.setImage(UIImage.init(named: "type_button_arrow_up"), for: .normal)
}
//click
menuView.didSelectMenuBlock = { [weak self](index:Int)->Void in
print("block select \(index)")
self?.selectedSpatialType(selectedIndex: index)
let title = self?.typeData[index].title
self?.mTopCenterTypeButton.setTitle(title, for: UIControl.State.normal)
}
//
menuView.tapFooterActionBlock = {[weak self] in
self?.startOrEndExternalVR()
}
}else if sender.tag == 203 {
//tips
let view = CCDeviceOperationListView.init(frame: CGRectMake(0, 0, KScreenWidth, KScreenHeight))
KWindow?.addSubview(view)
}
}
func startOrEndExternalVR() {
if(link == true){
if isPlaying {//
isPlaying = false
if self.externalVC != nil {
externalVC?.playerLayer?.player = nil
player?.pause()
releaseVideoComposition()
DispatchQueue.main.asyncAfter(deadline: .now()+0.15, execute: {[weak self] in
let playerItem = self?.getPlayerItem()
self?.player?.replaceCurrentItem(with: playerItem)
self?.playerController?.player = self?.player
self?.player?.play()
})
}
}
else {//
if self.externalVC != nil {
self.playerController?.player = nil
player?.pause()
releaseVideoComposition()
let playerItem = self.getPlayerItem()
player?.replaceCurrentItem(with: playerItem)
externalVC?.playerLayer?.player = player
player?.play()
isPlaying = true
}
}
}
updateTopCenterButtonWhenIsPlayingChange()
}
func selectedSpatialType(selectedIndex:Int){
var si = selectedIndex
if self.typeData.count == 2 {
si = selectedIndex + 4
}
let rsi : SpatialType = SpatialType(rawValue: si) ?? .monocular2D
self.selectedIndex = rsi
}
}

View File

@ -154,9 +154,9 @@ extension CCSpatialVideoDisplayController {
assetReader!.startReading()
//play
// DispatchQueue.main.async {
//
//
// self.player?.play()
//
//
// print("player\n err:\(self.player?.error)")
// }
}