自定义播放器在拖动播放时还有些问题,后面再来优化
This commit is contained in:
parent
a73cb139a4
commit
c228bc37ee
@ -21,6 +21,7 @@
|
|||||||
006B61DE2BBCFB45003FCB49 /* CustomSheetCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 006B61DD2BBCFB45003FCB49 /* CustomSheetCell.swift */; };
|
006B61DE2BBCFB45003FCB49 /* CustomSheetCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 006B61DD2BBCFB45003FCB49 /* CustomSheetCell.swift */; };
|
||||||
0073BD142BCE80F700721885 /* ZZHCustomPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0073BD132BCE80F700721885 /* ZZHCustomPlayer.swift */; };
|
0073BD142BCE80F700721885 /* ZZHCustomPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0073BD132BCE80F700721885 /* ZZHCustomPlayer.swift */; };
|
||||||
0073BD182BCF7B3400721885 /* ZZHCustomSlider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0073BD172BCF7B3400721885 /* ZZHCustomSlider.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 */; };
|
009661F82BAD6C7100FCA65F /* CCSpaceAlbumFilterPopView2.swift in Sources */ = {isa = PBXBuildFile; fileRef = 009661F72BAD6C7100FCA65F /* CCSpaceAlbumFilterPopView2.swift */; };
|
||||||
009661FA2BAD876200FCA65F /* PhotosUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 009661F92BAD876200FCA65F /* PhotosUI.framework */; };
|
009661FA2BAD876200FCA65F /* PhotosUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 009661F92BAD876200FCA65F /* PhotosUI.framework */; };
|
||||||
009661FC2BADB20D00FCA65F /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 009661FB2BADB20D00FCA65F /* CoreMotion.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 */; };
|
009662462BB3B39900FCA65F /* External.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 009662452BB3B39900FCA65F /* External.storyboard */; };
|
||||||
0096624A2BB3B45200FCA65F /* ExternalSceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 009662492BB3B45200FCA65F /* ExternalSceneDelegate.swift */; };
|
0096624A2BB3B45200FCA65F /* ExternalSceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 009662492BB3B45200FCA65F /* ExternalSceneDelegate.swift */; };
|
||||||
0096624D2BB3BA3B00FCA65F /* ZZHExternalViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0096624C2BB3BA3B00FCA65F /* ZZHExternalViewController.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 */; };
|
009DFB032BC63AF0007B56E8 /* CoreImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 009DFB022BC63AF0007B56E8 /* CoreImage.framework */; };
|
||||||
009DFB0E2BC8CFA2007B56E8 /* FeedbackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 009DFB0D2BC8CFA2007B56E8 /* FeedbackView.swift */; };
|
009DFB0E2BC8CFA2007B56E8 /* FeedbackView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 009DFB0D2BC8CFA2007B56E8 /* FeedbackView.swift */; };
|
||||||
009DFB112BC8E2E9007B56E8 /* MenuVC.swift in Sources */ = {isa = PBXBuildFile; fileRef = 009DFB102BC8E2E9007B56E8 /* MenuVC.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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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; };
|
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; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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; };
|
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>"; };
|
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>"; };
|
009DFB102BC8E2E9007B56E8 /* MenuVC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuVC.swift; sourceTree = "<group>"; };
|
||||||
@ -285,6 +287,15 @@
|
|||||||
path = CustomSheetController;
|
path = CustomSheetController;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
0072361D2BD0EEFC000595A9 /* deapt */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
0073BD1B2BCFCC4500721885 /* CCSpatialVideoDisplayController1.swift */,
|
||||||
|
0073BD1D2BCFCC6900721885 /* CCSpatialVideoDisplayForVideoTask1.swift */,
|
||||||
|
);
|
||||||
|
path = deapt;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
0096624B2BB3BA0100FCA65F /* ExternalScreen */ = {
|
0096624B2BB3BA0100FCA65F /* ExternalScreen */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@ -298,9 +309,10 @@
|
|||||||
009662582BB5527200FCA65F /* CCSpatialVideoDisplayController */ = {
|
009662582BB5527200FCA65F /* CCSpatialVideoDisplayController */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
0072361D2BD0EEFC000595A9 /* deapt */,
|
||||||
1E1EA2932B9364F000A5D5D2 /* CCSpatialVideoDisplayController.swift */,
|
1E1EA2932B9364F000A5D5D2 /* CCSpatialVideoDisplayController.swift */,
|
||||||
009662592BB552E700FCA65F /* CCSpatialVideoDisplayForVideoTask.swift */,
|
|
||||||
0073BD132BCE80F700721885 /* ZZHCustomPlayer.swift */,
|
0073BD132BCE80F700721885 /* ZZHCustomPlayer.swift */,
|
||||||
|
0073BD192BCFC8E800721885 /* ZZHCustomPlayerForVideoTask.swift */,
|
||||||
0073BD172BCF7B3400721885 /* ZZHCustomSlider.swift */,
|
0073BD172BCF7B3400721885 /* ZZHCustomSlider.swift */,
|
||||||
);
|
);
|
||||||
path = CCSpatialVideoDisplayController;
|
path = CCSpatialVideoDisplayController;
|
||||||
@ -784,6 +796,7 @@
|
|||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
|
0073BD1A2BCFC8E800721885 /* ZZHCustomPlayerForVideoTask.swift in Sources */,
|
||||||
AF2120CC2B4E973800400B7F /* CCInputTextField.swift in Sources */,
|
AF2120CC2B4E973800400B7F /* CCInputTextField.swift in Sources */,
|
||||||
AF2120C72B4E95DA00400B7F /* UIColor+Add.swift in Sources */,
|
AF2120C72B4E95DA00400B7F /* UIColor+Add.swift in Sources */,
|
||||||
AF2120C52B4E95DA00400B7F /* UIButton+Add.swift in Sources */,
|
AF2120C52B4E95DA00400B7F /* UIButton+Add.swift in Sources */,
|
||||||
@ -863,7 +876,6 @@
|
|||||||
1E02C9322B8990C600DD3143 /* CCDeviceOperationListView.swift in Sources */,
|
1E02C9322B8990C600DD3143 /* CCDeviceOperationListView.swift in Sources */,
|
||||||
AF2120DA2B4E9BD400400B7F /* CCAlert.swift in Sources */,
|
AF2120DA2B4E9BD400400B7F /* CCAlert.swift in Sources */,
|
||||||
006B61D12BBA5DB4003FCB49 /* MembershipProductView.swift in Sources */,
|
006B61D12BBA5DB4003FCB49 /* MembershipProductView.swift in Sources */,
|
||||||
0096625A2BB552E700FCA65F /* CCSpatialVideoDisplayForVideoTask.swift in Sources */,
|
|
||||||
1EFB8C702B88DA4800C72119 /* CCBottomMenuCell.swift in Sources */,
|
1EFB8C702B88DA4800C72119 /* CCBottomMenuCell.swift in Sources */,
|
||||||
AF2120FA2B4EA5BD00400B7F /* CCHomeController.swift in Sources */,
|
AF2120FA2B4EA5BD00400B7F /* CCHomeController.swift in Sources */,
|
||||||
0073BD182BCF7B3400721885 /* ZZHCustomSlider.swift in Sources */,
|
0073BD182BCF7B3400721885 /* ZZHCustomSlider.swift in Sources */,
|
||||||
|
|||||||
Binary file not shown.
@ -515,9 +515,9 @@
|
|||||||
filePath = "SwiftProject/Project/Controller/RecordingVideo/CCSpatialVideoDisplayController/CCSpatialVideoDisplayController.swift"
|
filePath = "SwiftProject/Project/Controller/RecordingVideo/CCSpatialVideoDisplayController/CCSpatialVideoDisplayController.swift"
|
||||||
startingColumnNumber = "9223372036854775807"
|
startingColumnNumber = "9223372036854775807"
|
||||||
endingColumnNumber = "9223372036854775807"
|
endingColumnNumber = "9223372036854775807"
|
||||||
startingLineNumber = "388"
|
startingLineNumber = "340"
|
||||||
endingLineNumber = "388"
|
endingLineNumber = "340"
|
||||||
landmarkName = "viewDidAppear(_:)"
|
landmarkName = "notification_didActiveNotification(notification:)"
|
||||||
landmarkType = "7">
|
landmarkType = "7">
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
</BreakpointProxy>
|
</BreakpointProxy>
|
||||||
@ -531,9 +531,9 @@
|
|||||||
filePath = "SwiftProject/Project/Controller/RecordingVideo/CCSpatialVideoDisplayController/CCSpatialVideoDisplayController.swift"
|
filePath = "SwiftProject/Project/Controller/RecordingVideo/CCSpatialVideoDisplayController/CCSpatialVideoDisplayController.swift"
|
||||||
startingColumnNumber = "9223372036854775807"
|
startingColumnNumber = "9223372036854775807"
|
||||||
endingColumnNumber = "9223372036854775807"
|
endingColumnNumber = "9223372036854775807"
|
||||||
startingLineNumber = "552"
|
startingLineNumber = "498"
|
||||||
endingLineNumber = "552"
|
endingLineNumber = "498"
|
||||||
landmarkName = "displayUpdate(caDisplayLink:)"
|
landmarkName = "updateTopCenterButtonWhenIsPlayingChange()"
|
||||||
landmarkType = "7">
|
landmarkType = "7">
|
||||||
<Locations>
|
<Locations>
|
||||||
<Location
|
<Location
|
||||||
@ -581,6 +581,21 @@
|
|||||||
endingLineNumber = "552"
|
endingLineNumber = "552"
|
||||||
offsetFromSymbolStart = "56">
|
offsetFromSymbolStart = "56">
|
||||||
</Location>
|
</Location>
|
||||||
|
<Location
|
||||||
|
uuid = "BB183D45-3193-4FC7-92DB-275D529A4AE6 - 1f02ddc6d27b6aec"
|
||||||
|
shouldBeEnabled = "Yes"
|
||||||
|
ignoreCount = "0"
|
||||||
|
continueAfterRunningActions = "No"
|
||||||
|
symbolName = "SwiftProject.CCSpatialVideoDisplayController.updateTopCenterButtonWhenIsPlayingChange() -> ()"
|
||||||
|
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>
|
</Locations>
|
||||||
</BreakpointContent>
|
</BreakpointContent>
|
||||||
</BreakpointProxy>
|
</BreakpointProxy>
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"filename" : "icon@1x.png",
|
"filename" : "play.png",
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 741 KiB |
BIN
SwiftProject/SwiftProject/Assets.xcassets/customPlayer/custom_playBtn.imageset/play.png
vendored
Normal file
BIN
SwiftProject/SwiftProject/Assets.xcassets/customPlayer/custom_playBtn.imageset/play.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.0 KiB |
@ -54,9 +54,7 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
(icon:"type_check",title:NSLocalizedString("交叉眼", comment: ""),isHiden:false)]
|
(icon:"type_check",title:NSLocalizedString("交叉眼", comment: ""),isHiden:false)]
|
||||||
}
|
}
|
||||||
//更新串流UI
|
//更新串流UI
|
||||||
// DispatchQueue.main.asyncAfter(deadline: .now() + 5, execute: {
|
self.setttinisScreenMirroring(isScreenMirroring: self.isAirPlayActive)
|
||||||
self.setttinisScreenMirroring(isScreenMirroring: self.isAirPlayActive)
|
|
||||||
// })
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,11 +75,6 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
return label
|
return label
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var assetReader:AVAssetReader?
|
|
||||||
|
|
||||||
var assetOutput:AVAssetReaderTrackOutput?
|
|
||||||
|
|
||||||
var assetTrack:AVAssetTrack?
|
|
||||||
|
|
||||||
let kNowTimeToUserDefaultKey_VideoDisplayController:String = "kNowTimeToUserDefaultKey_VideoDisplayController"
|
let kNowTimeToUserDefaultKey_VideoDisplayController:String = "kNowTimeToUserDefaultKey_VideoDisplayController"
|
||||||
var link = false//是否已连接设备
|
var link = false//是否已连接设备
|
||||||
@ -95,17 +88,18 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
{
|
{
|
||||||
didSet{
|
didSet{
|
||||||
//进行相应解码操作,边解边播
|
//进行相应解码操作,边解边播
|
||||||
|
customPlayer.selectedIndex = selectedIndex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let videoTranserConvertor = PlayByTransferConvertor()
|
// let videoTranserConvertor = PlayByTransferConvertor()
|
||||||
|
|
||||||
lazy var videoOriginalAsset:AVAsset = {
|
// lazy var videoOriginalAsset:AVAsset = {
|
||||||
let asset = AVAsset(url: sourceVideoURL!)
|
// let asset = AVAsset(url: sourceVideoURL!)
|
||||||
return asset
|
// return asset
|
||||||
}()
|
// }()
|
||||||
|
|
||||||
var videoOriginalPHAsset:PHAsset?
|
var videoOriginalPHAsset:PHAsset?
|
||||||
|
|
||||||
@ -113,13 +107,16 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
var sourceVideoURL:URL?
|
var sourceVideoURL:URL?
|
||||||
var imgData:Data?
|
var imgData:Data?
|
||||||
|
|
||||||
var player:AVPlayer?
|
// var player:AVPlayer?
|
||||||
// var needRestReaderTimeRange = false//标识是否需呀重置时间读取范围
|
// var needRestReaderTimeRange = false//标识是否需呀重置时间读取范围
|
||||||
var playerController:AVPlayerViewController?
|
// var playerController:AVPlayerViewController?
|
||||||
|
var customPlayer:ZZHCustomPlayer = {
|
||||||
|
let cp = ZZHCustomPlayer(frame: .zero)
|
||||||
|
return cp
|
||||||
|
}()
|
||||||
|
|
||||||
lazy var mTopImgView:UIImageView = {
|
lazy var mTopImgView:UIImageView = {
|
||||||
//393*236
|
//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))
|
let view = UIImageView(frame: CGRect(x: 0, y: 0, width: SCREEN_Width, height: 236))
|
||||||
|
|
||||||
view.image = UIImage.init(named: "BG_Top")
|
view.image = UIImage.init(named: "BG_Top")
|
||||||
@ -218,9 +215,6 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
let img2:UIImage = UIImage.init(named: NSLocalizedString("displayvc_desc", comment: ""))!
|
let img2:UIImage = UIImage.init(named: NSLocalizedString("displayvc_desc", comment: ""))!
|
||||||
button.setImage(img2, for: UIControl.State.normal)
|
button.setImage(img2, for: UIControl.State.normal)
|
||||||
button.frame = CGRect(x: 0, y: 0, width: 173, height: 42)
|
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.centerY = progressView.top - 70
|
||||||
button.centerX = self.view.centerX
|
button.centerX = self.view.centerX
|
||||||
|
|
||||||
@ -229,36 +223,13 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
|
|
||||||
|
|
||||||
//监听播放完毕
|
//监听播放完毕
|
||||||
@objc func notification_PlayerEndTime(notification:Notification){
|
// @objc func notification_PlayerEndTime(notification:Notification){
|
||||||
print("PlayerEndTime....")
|
// print("PlayerEndTime....")
|
||||||
player?.seek(to: .zero)
|
// player?.seek(to: .zero)
|
||||||
player?.play()
|
// 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){
|
// @objc func notification_PlayerTimeJump(notification:Notification){
|
||||||
@ -273,38 +244,41 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
configureUI()
|
configureUI()
|
||||||
ZZHHelper.setNowTimeToUserDefaultWithKey(kNowTimeToUserDefaultKey_VideoDisplayController)
|
ZZHHelper.setNowTimeToUserDefaultWithKey(kNowTimeToUserDefaultKey_VideoDisplayController)
|
||||||
Task {
|
// Task {
|
||||||
print("ccs viewdid load ---------")
|
// print("ccs viewdid load ---------")
|
||||||
await self.loadVideoAssetReader()
|
// await self.loadVideoAssetReader()
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now()+0.01) {[weak self] in
|
// DispatchQueue.main.asyncAfter(deadline: .now()+0.01) {[weak self] in
|
||||||
self?.setUPPlayer()
|
// self?.setUPPlayer()
|
||||||
// 检查当前是否已连接到 AirPlay 设备
|
//
|
||||||
self?.checkAirPlayStatus()
|
//
|
||||||
|
//
|
||||||
|
//
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
self.customPlayer.setUPPlayer()
|
||||||
|
// 检查当前是否已连接到 AirPlay 设备
|
||||||
|
self.checkAirPlayStatus()
|
||||||
}
|
}
|
||||||
|
|
||||||
func setUPPlayer(){
|
// func setUPPlayer(){
|
||||||
print("getPlayerItem ========")
|
// print("getPlayerItem ========")
|
||||||
player = AVPlayer()
|
// player = AVPlayer()
|
||||||
player?.allowsExternalPlayback = true
|
// player?.allowsExternalPlayback = true
|
||||||
player?.usesExternalPlaybackWhileExternalScreenIsActive = true
|
// player?.usesExternalPlaybackWhileExternalScreenIsActive = true
|
||||||
|
//
|
||||||
print("getPlayerItem >>>>>>>")
|
// print("getPlayerItem >>>>>>>")
|
||||||
|
//
|
||||||
playerController = AVPlayerViewController()
|
// playerController = AVPlayerViewController()
|
||||||
playerController?.player = player
|
// playerController?.player = player
|
||||||
playerController!.view.backgroundColor = .clear
|
// playerController!.view.backgroundColor = .clear
|
||||||
playerController?.view.frame = CGRect.init(x: 0, y: 170, width: self.view.frame.size.width, height: 400)
|
// playerController?.view.frame = CGRect.init(x: 0, y: 170, width: self.view.frame.size.width, height: 400)
|
||||||
|
//
|
||||||
self.addChild(playerController!)
|
// self.addChild(playerController!)
|
||||||
self.view.addSubview(playerController!.view)
|
// self.view.addSubview(playerController!.view)
|
||||||
|
//
|
||||||
self.maskLabel.frame = playerController!.view.frame
|
// self.maskLabel.frame = playerController!.view.frame
|
||||||
self.view.addSubview(self.maskLabel)
|
// self.view.addSubview(self.maskLabel)
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
func configureUI(){
|
func configureUI(){
|
||||||
@ -322,7 +296,20 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
navtionBar?.addSubview(mTopCenterTypeButton)
|
navtionBar?.addSubview(mTopCenterTypeButton)
|
||||||
|
|
||||||
self.view.addSubview(tipsButton)
|
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(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.failedToPlayToEndTimeNotification, object: nil)
|
||||||
NotificationCenter.default.addObserver(self, selector: #selector(notificatin_failedToPlayToEndTimeNotification(notifiation: )), name: AVPlayerItem.newErrorLogEntryNotification, 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) {
|
@objc func notification_didEnterBackgroundNotification(notification:Notification) {
|
||||||
player?.pause()
|
// player?.pause()
|
||||||
|
customPlayer.play(false)
|
||||||
|
|
||||||
print("ccs .....notification_didEnterBackgroundNotification")
|
print("ccs .....notification_didEnterBackgroundNotification")
|
||||||
}
|
}
|
||||||
@ -370,7 +358,8 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
if externalVC != nil {
|
if externalVC != nil {
|
||||||
externalVC?.playerLayer?.player = nil
|
externalVC?.playerLayer?.player = nil
|
||||||
}
|
}
|
||||||
player?.pause()
|
// player?.pause()
|
||||||
|
customPlayer.play(false)
|
||||||
releaseVideoComposition()
|
releaseVideoComposition()
|
||||||
|
|
||||||
let sec:TimeInterval = ZZHHelper.getSecFromUserDefaultByKey(kNowTimeToUserDefaultKey_VideoDisplayController)
|
let sec:TimeInterval = ZZHHelper.getSecFromUserDefaultByKey(kNowTimeToUserDefaultKey_VideoDisplayController)
|
||||||
@ -385,18 +374,18 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
override func viewDidAppear(_ animated: Bool) {
|
override func viewDidAppear(_ animated: Bool) {
|
||||||
super.viewDidAppear(animated)
|
super.viewDidAppear(animated)
|
||||||
|
|
||||||
if self.player?.currentItem == nil {//此处需要判断是否为空:1,在didload的时候会设置一次,在viewDidDisappear的时候会被置空
|
// if self.player?.currentItem == nil {//此处需要判断是否为空:1,在didload的时候会设置一次,在viewDidDisappear的时候会被置空
|
||||||
let playerItem = self.getPlayerItem()
|
// let playerItem = self.getPlayerItem()
|
||||||
self.player?.replaceCurrentItem(with: playerItem)
|
// self.player?.replaceCurrentItem(with: playerItem)
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
if self.externalVC != nil {//恢复外接屏幕的视频播放
|
// if self.externalVC != nil {//恢复外接屏幕的视频播放
|
||||||
if self.externalVC?.playerLayer?.player == nil {
|
// if self.externalVC?.playerLayer?.player == nil {
|
||||||
self.activeSession()
|
// self.activeSession()
|
||||||
self.externalVC?.playerLayer?.player = self.player
|
// self.externalVC?.playerLayer?.player = self.player
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
self.player?.play()
|
// self.player?.play()
|
||||||
}
|
}
|
||||||
|
|
||||||
//MARK: - 监听设备投流
|
//MARK: - 监听设备投流
|
||||||
@ -462,14 +451,11 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
|
|
||||||
//当外接屏幕连接时
|
//当外接屏幕连接时
|
||||||
func dealTaskWhenExternalScreenConnect(){
|
func dealTaskWhenExternalScreenConnect(){
|
||||||
// if link == true {
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
link = true
|
link = true
|
||||||
isPlaying = true
|
isPlaying = true
|
||||||
let playerItem = self.getPlayerItem()
|
// let playerItem = self.getPlayerItem()
|
||||||
player?.replaceCurrentItem(with: playerItem)
|
// player?.replaceCurrentItem(with: playerItem)
|
||||||
print("外接屏幕已连接.....")
|
print("外接屏幕已连接.....")
|
||||||
activeSession()
|
activeSession()
|
||||||
|
|
||||||
@ -517,8 +503,8 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
//当外接屏幕断开时
|
//当外接屏幕断开时
|
||||||
func dealTaskWhenExternalScreenDisConnect(){
|
func dealTaskWhenExternalScreenDisConnect(){
|
||||||
print("外接屏幕已断开.....")
|
print("外接屏幕已断开.....")
|
||||||
let playerItem = self.getPlayerItem()
|
// let playerItem = self.getPlayerItem()
|
||||||
player?.replaceCurrentItem(with: playerItem)
|
// player?.replaceCurrentItem(with: playerItem)
|
||||||
|
|
||||||
link = false
|
link = false
|
||||||
isPlaying = false
|
isPlaying = false
|
||||||
@ -543,8 +529,8 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
//隐藏弹出列表尾部
|
//隐藏弹出列表尾部
|
||||||
menuView.showFooterView(isShow: false, showText: "")
|
menuView.showFooterView(isShow: false, showText: "")
|
||||||
externalVC?.playerLayer?.player = nil
|
externalVC?.playerLayer?.player = nil
|
||||||
self.playerController?.player = player
|
// self.playerController?.player = player
|
||||||
player?.play()
|
// player?.play()
|
||||||
externalVC = nil
|
externalVC = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,9 +539,9 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
if has_exvc.playerLayer?.player == nil {
|
if has_exvc.playerLayer?.player == nil {
|
||||||
has_exvc.imageView?.isHidden = true
|
has_exvc.imageView?.isHidden = true
|
||||||
has_exvc.playerLayer?.isHidden = false
|
has_exvc.playerLayer?.isHidden = false
|
||||||
self.playerController?.player = nil
|
// self.playerController?.player = nil
|
||||||
has_exvc.playerLayer?.player = player
|
// has_exvc.playerLayer?.player = player
|
||||||
player?.play()
|
// player?.play()
|
||||||
externalDispalylink?.invalidate()
|
externalDispalylink?.invalidate()
|
||||||
externalDispalylink = nil
|
externalDispalylink = nil
|
||||||
}
|
}
|
||||||
@ -567,7 +553,6 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
deinit {
|
deinit {
|
||||||
print("patialvideodisplaycontroler deinit......")
|
print("patialvideodisplaycontroler deinit......")
|
||||||
releaseVideoComposition()
|
releaseVideoComposition()
|
||||||
assetReader?.cancelReading()
|
|
||||||
NotificationCenter.default.removeObserver(self)
|
NotificationCenter.default.removeObserver(self)
|
||||||
// player?.removeObserver(self, forKeyPath: "status")
|
// player?.removeObserver(self, forKeyPath: "status")
|
||||||
}
|
}
|
||||||
@ -577,8 +562,8 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
externalDispalylink?.invalidate()
|
externalDispalylink?.invalidate()
|
||||||
externalDispalylink = nil
|
externalDispalylink = nil
|
||||||
}
|
}
|
||||||
self.player?.currentItem?.videoComposition = nil
|
// self.player?.currentItem?.videoComposition = nil
|
||||||
self.player?.replaceCurrentItem(with: nil)
|
// self.player?.replaceCurrentItem(with: nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -641,26 +626,28 @@ class CCSpatialVideoDisplayController: BaseController {
|
|||||||
isPlaying = false
|
isPlaying = false
|
||||||
if self.externalVC != nil {
|
if self.externalVC != nil {
|
||||||
externalVC?.playerLayer?.player = nil
|
externalVC?.playerLayer?.player = nil
|
||||||
player?.pause()
|
// player?.pause()
|
||||||
|
customPlayer.play(false)
|
||||||
releaseVideoComposition()
|
releaseVideoComposition()
|
||||||
DispatchQueue.main.asyncAfter(deadline: .now()+0.15, execute: {[weak self] in
|
DispatchQueue.main.asyncAfter(deadline: .now()+0.15, execute: {[weak self] in
|
||||||
let playerItem = self?.getPlayerItem()
|
// let playerItem = self?.getPlayerItem()
|
||||||
self?.player?.replaceCurrentItem(with: playerItem)
|
// self?.player?.replaceCurrentItem(with: playerItem)
|
||||||
self?.playerController?.player = self?.player
|
// self?.playerController?.player = self?.player
|
||||||
self?.player?.play()
|
// self?.player?.play()
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {//开始串流
|
else {//开始串流
|
||||||
if self.externalVC != nil {
|
if self.externalVC != nil {
|
||||||
self.playerController?.player = nil
|
// self.playerController?.player = nil
|
||||||
player?.pause()
|
// player?.pause()
|
||||||
releaseVideoComposition()
|
// releaseVideoComposition()
|
||||||
let playerItem = self.getPlayerItem()
|
// let playerItem = self.getPlayerItem()
|
||||||
player?.replaceCurrentItem(with: playerItem)
|
// player?.replaceCurrentItem(with: playerItem)
|
||||||
externalVC?.playerLayer?.player = player
|
// externalVC?.playerLayer?.player = player
|
||||||
player?.play()
|
// player?.play()
|
||||||
isPlaying = true
|
isPlaying = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,12 +9,36 @@ import Foundation
|
|||||||
import UIKit
|
import UIKit
|
||||||
import AVKit
|
import AVKit
|
||||||
class ZZHCustomPlayer: UIView {
|
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 playerLayerBgView:UIView?
|
||||||
var avPlayer:AVPlayer?
|
var avPlayer:AVPlayer?
|
||||||
var avPlayerLayer:AVPlayerLayer?
|
var avPlayerLayer:AVPlayerLayer?
|
||||||
var timeSlider:ZZHCustomSlider?
|
var timeSlider:ZZHCustomSlider?
|
||||||
var prePlayingState:Bool?//标记 在滑块拖动前,player的播放状态,以便在拖动完毕之后回复播放状态
|
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? = {//播放按钮 背景
|
lazy var maskPlayerView:UIView? = {//播放按钮 背景
|
||||||
let bgView = UIView()
|
let bgView = UIView()
|
||||||
@ -24,7 +48,7 @@ class ZZHCustomPlayer: UIView {
|
|||||||
|
|
||||||
self.playStateImgView.snp.makeConstraints { make in
|
self.playStateImgView.snp.makeConstraints { make in
|
||||||
make.centerX.centerY.equalToSuperview()
|
make.centerX.centerY.equalToSuperview()
|
||||||
make.width.height.equalTo(40)
|
make.width.height.equalTo(80)
|
||||||
}
|
}
|
||||||
|
|
||||||
let btn = UIButton()
|
let btn = UIButton()
|
||||||
@ -42,8 +66,25 @@ class ZZHCustomPlayer: UIView {
|
|||||||
return imgView
|
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) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
NotificationCenter.default.addObserver(self, selector: #selector(notification_PlayerEndTime(notification:)), name: AVPlayerItem.didPlayToEndTimeNotification, object: nil)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let playerWidth = KScreenWidth
|
let playerWidth = KScreenWidth
|
||||||
let playerHeight = 200
|
let playerHeight = 200
|
||||||
playerLayerBgView = UIView()
|
playerLayerBgView = UIView()
|
||||||
@ -54,10 +95,14 @@ class ZZHCustomPlayer: UIView {
|
|||||||
make.height.equalTo(playerHeight)
|
make.height.equalTo(playerHeight)
|
||||||
}
|
}
|
||||||
avPlayer = AVPlayer()
|
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 = AVPlayerLayer(player: avPlayer)
|
||||||
avPlayerLayer?.frame = CGRect(x: 0, y: 0, width: Int(playerWidth), height: playerHeight)
|
avPlayerLayer?.frame = CGRect(x: 0, y: 0, width: Int(playerWidth), height: playerHeight)
|
||||||
playerLayerBgView!.layer.addSublayer(avPlayerLayer!)
|
playerLayerBgView!.layer.addSublayer(avPlayerLayer!)
|
||||||
playerLayerBgView?.backgroundColor = UIColor.orange
|
playerLayerBgView?.backgroundColor = UIColor.clear
|
||||||
|
|
||||||
self.maskPlayerView?.frame = avPlayerLayer!.frame
|
self.maskPlayerView?.frame = avPlayerLayer!.frame
|
||||||
playerLayerBgView?.addSubview(maskPlayerView!)
|
playerLayerBgView?.addSubview(maskPlayerView!)
|
||||||
@ -65,8 +110,8 @@ class ZZHCustomPlayer: UIView {
|
|||||||
|
|
||||||
|
|
||||||
timeSlider = ZZHCustomSlider(frame: .zero)
|
timeSlider = ZZHCustomSlider(frame: .zero)
|
||||||
timeSlider?.processChangeValueCallback = { (value,isMoving) in
|
timeSlider?.processChangeValueCallback = {[weak self] (value,isMoving) in
|
||||||
print("value:\(value) isMoving:\(isMoving)")
|
self?.manualToSeekPlay(value:value,isMoving: isMoving)
|
||||||
}
|
}
|
||||||
self.addSubview(timeSlider!)
|
self.addSubview(timeSlider!)
|
||||||
timeSlider!.snp.makeConstraints { make in
|
timeSlider!.snp.makeConstraints { make in
|
||||||
@ -75,8 +120,57 @@ class ZZHCustomPlayer: UIView {
|
|||||||
make.bottom.equalToSuperview().offset(0)
|
make.bottom.equalToSuperview().offset(0)
|
||||||
make.height.equalTo(120)
|
make.height.equalTo(120)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//通过slider进行seek播放时间点
|
||||||
|
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)
|
updatePlayMaskView(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func seek(ct:CMTime) {
|
||||||
|
// self.avPlayer?.seek(to: ct)
|
||||||
|
// }
|
||||||
|
|
||||||
//根据状态更新播放器遮罩视图显示与隐藏
|
//根据状态更新播放器遮罩视图显示与隐藏
|
||||||
func updatePlayMaskView(_ value:Bool) {
|
func updatePlayMaskView(_ value:Bool) {
|
||||||
playStateImgView.isHidden = value
|
playStateImgView.isHidden = value
|
||||||
self.maskPlayerView?.backgroundColor = value ? .clear : playerPauseBgColor
|
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) {
|
override func draw(_ rect: CGRect) {
|
||||||
super.draw(rect)
|
super.draw(rect)
|
||||||
|
|
||||||
@ -121,4 +227,25 @@ class ZZHCustomPlayer: UIView {
|
|||||||
required init?(coder: NSCoder) {
|
required init?(coder: NSCoder) {
|
||||||
fatalError("init(coder:) has not been implemented")
|
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()
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//加载assetReader和output
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
//用于循环播放时调用,重置assetreader的timeRange
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -15,10 +15,12 @@ class ZZHCustomSlider: UIView {
|
|||||||
var timeSlider:CustomSlider?
|
var timeSlider:CustomSlider?
|
||||||
var processChangeValueCallback:CustomSliderProcessChangeValueCallback?
|
var processChangeValueCallback:CustomSliderProcessChangeValueCallback?
|
||||||
var preValue:Float = 0.0 //更新进度前的value
|
var preValue:Float = 0.0 //更新进度前的value
|
||||||
|
var totalSec:Int = -1//代表视频总时长
|
||||||
let bgView:UIView = UIView()
|
let bgView:UIView = UIView()
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
print("zzhcustomslider....deinit...")
|
||||||
|
}
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
@ -83,12 +85,15 @@ class ZZHCustomSlider: UIView {
|
|||||||
if isMoving {
|
if isMoving {
|
||||||
var currentValue = max(0, min(value, 1))
|
var currentValue = max(0, min(value, 1))
|
||||||
//格式化为0.x
|
//格式化为0.x
|
||||||
let formattedValue = String(format: "%.1f", currentValue)
|
let formattedValue = String(format: "%.2f", currentValue)
|
||||||
currentValue = Float(formattedValue)!
|
currentValue = Float(formattedValue)!
|
||||||
|
//保证相邻2次的值不同才有必要去触发进度的改变
|
||||||
if currentValue > preValue || currentValue < preValue {
|
if currentValue > preValue || currentValue < preValue {
|
||||||
preValue = currentValue
|
preValue = currentValue
|
||||||
processChangeValueCallback(preValue,isMoving)
|
processChangeValueCallback(preValue,isMoving)
|
||||||
|
if self.totalSec > 0 {//已经获取到总时长的情况下再去更新起始位置的时间文本值
|
||||||
|
self.sLabel?.text = ZZHHelper.formatVideoTime(second: Int(preValue*Float(self.totalSec)))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -98,9 +103,14 @@ class ZZHCustomSlider: UIView {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//外部播放时的更新当前滑块
|
//外部播放时的更新当前滑块
|
||||||
func exUpdateProcessValue(value:Float) {
|
func exUpdateProcessValue(value:Float,currSec:Int,totalSec:Int) {
|
||||||
self.timeSlider!.value = value
|
self.totalSec = totalSec
|
||||||
preValue = value
|
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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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{
|
||||||
|
//跟新selectedIndex、typeData的值
|
||||||
|
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 (test随机生成点位置,注意:arrow点是基于屏幕的位置)
|
||||||
|
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
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Binary file not shown.
Loading…
Reference in New Issue
Block a user