|
@@ -27,25 +27,8 @@ public enum PQGPUImagePlayerViewStatus: Int {
|
|
|
case unknow = -1000
|
|
|
}
|
|
|
|
|
|
-public class PQGPUImagePlayerView: UIView, RenderViewDelegate {
|
|
|
- public func willDisplayFramebuffer(renderView _: RenderView, framebuffer _: Framebuffer) {}
|
|
|
-
|
|
|
- public func didDisplayFramebuffer(renderView _: RenderView, framebuffer: Framebuffer) {
|
|
|
-// if(renderView.bounds.size.width = framebuffer.size.width && renderView.bounds.size.height = framebuffer.size.height){
|
|
|
-
|
|
|
- if GLint(mCanverSize.width) == framebuffer.size.width, GLint(mCanverSize.height) == framebuffer.size.height {
|
|
|
-// DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
|
|
|
-
|
|
|
-// DispatchQueue.main.async {
|
|
|
-// renderView.isHidden = false
|
|
|
- }
|
|
|
-// }
|
|
|
- }
|
|
|
-
|
|
|
- public func shouldDisplayNextFramebufferAfterMainThreadLoop() -> Bool {
|
|
|
- return false
|
|
|
- }
|
|
|
-
|
|
|
+public class PQGPUImagePlayerView: UIView {
|
|
|
+
|
|
|
public private(set) var playbackTime: TimeInterval = 0 {
|
|
|
willSet {
|
|
|
playbackTimeChangeClosure?(newValue)
|
|
@@ -143,15 +126,25 @@ public class PQGPUImagePlayerView: UIView, RenderViewDelegate {
|
|
|
|
|
|
public var mPlayeTimeRange: CMTimeRange?
|
|
|
|
|
|
- public var mStickers: [PQEditVisionTrackMaterialsModel]?
|
|
|
-
|
|
|
- // 最后一次显示的sticker
|
|
|
- public var lastshowSticker: PQEditVisionTrackMaterialsModel?
|
|
|
-
|
|
|
+ var mStickers: [PQEditVisionTrackMaterialsModel]? {
|
|
|
+ didSet {
|
|
|
+
|
|
|
+ FilterLog(message: "设置线程为: \(Thread.current) \(OperationQueue.current?.underlyingQueue?.label as Any)")
|
|
|
+
|
|
|
+ configCache()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// 是否显示时间条
|
|
|
- public var showProgressLab: Bool = true
|
|
|
-
|
|
|
- public var cacheFilters: [PQBaseFilter] = Array()
|
|
|
+ var showProgressLab: Bool = true
|
|
|
+
|
|
|
+ // 缓存创建filter 防止 seek 100ms 慢
|
|
|
+ @Atomic var cacheFilters: Array<PQBaseFilter> = Array()
|
|
|
+ // 缓存个数
|
|
|
+ var cacheFiltersMaxCount: Int = 8
|
|
|
+
|
|
|
+ /// Use serial queue to ensure that the picture is smooth
|
|
|
+ var createFiltersQueue: DispatchQueue!
|
|
|
|
|
|
//是否显示高斯
|
|
|
public var showGaussianBlur:Bool = false
|
|
@@ -170,7 +163,7 @@ public class PQGPUImagePlayerView: UIView, RenderViewDelegate {
|
|
|
// 暂停播放view
|
|
|
lazy var playView: UIImageView = {
|
|
|
let view = UIImageView(frame: CGRect(x: (self.frame.size.width - 52) / 2, y: (self.frame.size.height - 52) / 2, width: 52, height: 52))
|
|
|
- view.image = UIImage().BF_Image(named: "gpuplayBtn")
|
|
|
+ view.image = UIImage().BF_Image(named: "gpuplayBtn")
|
|
|
view.isHidden = true
|
|
|
return view
|
|
|
|
|
@@ -218,14 +211,22 @@ public class PQGPUImagePlayerView: UIView, RenderViewDelegate {
|
|
|
addSubview(playView)
|
|
|
addSubview(progressLab)
|
|
|
backgroundColor = PQBFConfig.shared.styleBackGroundColor
|
|
|
-
|
|
|
playerEmptyView = UIImageView(frame: bounds)
|
|
|
- playerEmptyView.backgroundColor = PQBFConfig.shared.styleBackGroundColor
|
|
|
- playerEmptyView.image = UIImage().BF_Image(named: "playEmpty")
|
|
|
+ playerEmptyView.backgroundColor = .black
|
|
|
+ playerEmptyView.image = UIImage().BF_Image(named: "playEmpty")
|
|
|
playerEmptyView.contentMode = .center
|
|
|
addSubview(playerEmptyView)
|
|
|
|
|
|
addSubview(tipLab)
|
|
|
+
|
|
|
+ if #available(iOS 10.0, *) {
|
|
|
+ createFiltersQueue = DispatchQueue(label: "PQ.moveFiler.seeking111", qos: .default, attributes: .initiallyInactive, autoreleaseFrequency: .never, target: nil)
|
|
|
+ } else {
|
|
|
+ createFiltersQueue = DispatchQueue(label: "PQ.moveFiler.seeking111", qos: .userInteractive, attributes: [], autoreleaseFrequency: .inherit, target: nil)
|
|
|
+ }
|
|
|
+ if #available(iOS 10.0, *) {
|
|
|
+ createFiltersQueue.activate()
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
func showBorderLayer() {
|
|
@@ -272,7 +273,7 @@ public class PQGPUImagePlayerView: UIView, RenderViewDelegate {
|
|
|
// 设置画布比例
|
|
|
public func resetCanvasFrame(frame: CGRect) {
|
|
|
if self.frame.equalTo(frame) {
|
|
|
- BFLog(message: "新老值一样,不重置")
|
|
|
+ FilterLog(message: "新老值一样,不重置")
|
|
|
return
|
|
|
}
|
|
|
|
|
@@ -282,7 +283,7 @@ public class PQGPUImagePlayerView: UIView, RenderViewDelegate {
|
|
|
showBorderLayer()
|
|
|
}
|
|
|
|
|
|
- BFLog(message: "new frame is \(frame)")
|
|
|
+ FilterLog(message: "new frame is \(frame)")
|
|
|
renderView.isHidden = true
|
|
|
renderView.frame = CGRect(x: 0, y: 0, width: self.frame.size.width, height: self.frame.size.height)
|
|
|
renderView.resatSize()
|
|
@@ -331,10 +332,10 @@ public class PQGPUImagePlayerView: UIView, RenderViewDelegate {
|
|
|
var composition: AVMutableComposition?
|
|
|
|
|
|
let asset = AVURLAsset(url: url, options: nil)
|
|
|
- BFLog(message: "播放器初始化的音频时长\(asset.duration.seconds) url is \(url)")
|
|
|
+ FilterLog(message: "播放器初始化的音频时长\(asset.duration.seconds) url is \(url)")
|
|
|
self.asset = asset
|
|
|
if (audioMixModel != nil && audioMixModel?.localPath != nil) || (videoStickers != nil && (videoStickers?.count ?? 0) > 0) {
|
|
|
- BFLog(message: "有参加混音的数据。")
|
|
|
+ FilterLog(message: "有参加混音的数据。")
|
|
|
(audioMix, composition) = PQPlayerViewModel.setupAudioMix(originAsset: asset, bgmData: audioMixModel, videoStickers: videoStickers)
|
|
|
} else {
|
|
|
audioMix = nil
|
|
@@ -356,7 +357,7 @@ public class PQGPUImagePlayerView: UIView, RenderViewDelegate {
|
|
|
}
|
|
|
do {
|
|
|
if composition != nil {
|
|
|
- BFLog(message: "composition 方式初始化")
|
|
|
+ FilterLog(message: "composition 方式初始化")
|
|
|
movie = try PQMovieInput(asset: composition!, videoComposition: videoComposition, audioMix: audioMix, playAtActualSpeed: true, loop: isLoop, audioSettings: audioSettings)
|
|
|
} else {
|
|
|
movie = try PQMovieInput(url: url, playAtActualSpeed: true, loop: isLoop, audioSettings: audioSettings)
|
|
@@ -382,8 +383,9 @@ public class PQGPUImagePlayerView: UIView, RenderViewDelegate {
|
|
|
movie.progress = { [weak self, movie] currTime, duration, prgressValue in
|
|
|
guard let strongSelf = self else { return }
|
|
|
|
|
|
- self?.findShowStikcer(currTime: movie.currentTime.seconds)
|
|
|
-
|
|
|
+ FilterLog(message: " movie.currentTime.seconds 进度\(movie.currentTime.seconds)")
|
|
|
+ self?.changeFilter(currTime: movie.currentTime.seconds)
|
|
|
+
|
|
|
self?.progress?(currTime, duration, prgressValue)
|
|
|
|
|
|
DispatchQueue.main.async {
|
|
@@ -402,6 +404,11 @@ public class PQGPUImagePlayerView: UIView, RenderViewDelegate {
|
|
|
}
|
|
|
movie.completion = { [weak self] in
|
|
|
guard let strongSelf = self else { return }
|
|
|
+ //缓存已经用完,重新初始化缓存
|
|
|
+ if(strongSelf.filters.count == 0){
|
|
|
+ strongSelf.configCache()
|
|
|
+ }
|
|
|
+
|
|
|
DispatchQueue.main.async {
|
|
|
strongSelf.status = .stop
|
|
|
strongSelf.finishedClosure?()
|
|
@@ -414,71 +421,164 @@ public class PQGPUImagePlayerView: UIView, RenderViewDelegate {
|
|
|
applyFilters()
|
|
|
}
|
|
|
|
|
|
- func findShowStikcer(currTime: Float64) {
|
|
|
- if mStickers?.count ?? 0 == 0 {
|
|
|
- BFLog(message: "mStickers data is error")
|
|
|
- return
|
|
|
- }
|
|
|
- var currentSticker: PQEditVisionTrackMaterialsModel?
|
|
|
- var currentIdenx: Int = 0
|
|
|
- for (index, sticker) in mStickers!.enumerated() {
|
|
|
- if sticker.timelineIn <= currTime, sticker.timelineOut >= currTime {
|
|
|
- currentSticker = sticker
|
|
|
- currentIdenx = index
|
|
|
+ // 初始化缓存,默认选创建 cacheFiltersMaxCount 个缓存 filterrs
|
|
|
+ func configCache() {
|
|
|
+ cacheFilters.removeAll()
|
|
|
+ FilterLog(message: "原素材 总数:\(mStickers?.count ?? 0) ")
|
|
|
+
|
|
|
+ if mStickers?.count ?? 0 > 0 {
|
|
|
+
|
|
|
+ for (index , sticker) in mStickers!.enumerated() {
|
|
|
+ print( "mStickers timelinein:\(sticker.timelineIn) timelineout: \(sticker.timelineOut) index : \(index)")
|
|
|
|
|
|
- break
|
|
|
}
|
|
|
- }
|
|
|
- // 创建不同的filter
|
|
|
- if currentSticker == nil {
|
|
|
- BFLog(message: "sticker data is error")
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- //
|
|
|
- if movie != nil && currentSticker != lastshowSticker {
|
|
|
- BFLog(message: "sticker timelineIn is: \(currentSticker!.timelineIn) timelineOut \(currentSticker!.timelineOut) in is :\(currentSticker!.model_in) in out is :\(currentSticker!.out) sticker location::: \(String(describing: currentSticker?.locationPath))")
|
|
|
+
|
|
|
+ for (index, currentSticker) in mStickers!.enumerated() {
|
|
|
+ //到达最大缓存数退出
|
|
|
+ if index == cacheFiltersMaxCount {
|
|
|
+ break
|
|
|
+ }
|
|
|
+ var showFitler: PQBaseFilter?
|
|
|
+ if currentSticker.type == StickerType.VIDEO.rawValue {
|
|
|
+ showFitler = PQMovieFilter(movieSticker: currentSticker)
|
|
|
|
|
|
- var showFitler: PQBaseFilter?
|
|
|
- if currentSticker!.type == StickerType.VIDEO.rawValue {
|
|
|
- showFitler = PQMovieFilter(movieSticker: currentSticker!)
|
|
|
+ } else if currentSticker.type == StickerType.IMAGE.rawValue {
|
|
|
+ showFitler = PQImageFilter(sticker: currentSticker)
|
|
|
+ }
|
|
|
+ if showFitler != nil {
|
|
|
+ print( " 加入到缓存 的 filter timelinein:\(currentSticker.timelineIn) timelineout: \(currentSticker.timelineOut) in :\(currentSticker.model_in) out: \(currentSticker.out) index : \(index)")
|
|
|
+ cacheFilters.append(showFitler!)
|
|
|
+ }
|
|
|
|
|
|
- } else if currentSticker!.type == StickerType.IMAGE.rawValue {
|
|
|
- showFitler = PQImageFilter(sticker: currentSticker!)
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
+ for (index, filter) in cacheFilters.enumerated() {
|
|
|
+ FilterLog(message: " 初始化 config create currentSticker timelinein \(String(describing: filter.stickerInfo?.timelineIn)) timelineout \(String(describing: filter.stickerInfo?.timelineOut)) in :\(String(describing: filter.stickerInfo?.model_in)) out \(String(describing: filter.stickerInfo?.out)) index\(index)")
|
|
|
+ }
|
|
|
+
|
|
|
+ if(cacheFilters.first != nil){
|
|
|
+ movie?.removeAllTargets()
|
|
|
+ let showFilter: PQBaseFilter = cacheFilters.first!
|
|
|
+ movie?.addTarget(showFilter, atTargetIndex: 0)
|
|
|
+ showFilter.addTarget(renderView, atTargetIndex: 0)
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
|
|
|
- movie!.removeAllTargets()
|
|
|
- let currentTarget: ImageSource = movie!
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //创建下一个filter 数据
|
|
|
+ func createNextFilter() {
|
|
|
+ FilterLog(message: "加入前 当前的缓存个数为: \(cacheFilters.count) maxCount \(cacheFiltersMaxCount) 最后一个显示时间 \(String(describing: cacheFilters.last?.stickerInfo?.timelineIn))")
|
|
|
+ if cacheFilters.count <= cacheFiltersMaxCount {
|
|
|
+ let showIndex = mStickers?.firstIndex(where: { (sticker) -> Bool in
|
|
|
+ (cacheFilters.last?.stickerInfo == sticker)
|
|
|
+ })
|
|
|
+ FilterLog(message: "当前显示的showIndex: \(String(describing: showIndex))")
|
|
|
+ if ((showIndex ?? 0) + 1) < (mStickers?.count ?? 0) {
|
|
|
+ let currentSticker = mStickers?[(showIndex ?? 0) + 1]
|
|
|
+ if currentSticker != nil {
|
|
|
+ var showFitler: PQBaseFilter?
|
|
|
+ if currentSticker!.type == StickerType.VIDEO.rawValue {
|
|
|
+ showFitler = PQMovieFilter(movieSticker: currentSticker!)
|
|
|
+
|
|
|
+ } else if currentSticker!.type == StickerType.IMAGE.rawValue {
|
|
|
+ showFitler = PQImageFilter(sticker: currentSticker!)
|
|
|
+ }
|
|
|
+ if showFitler != nil {
|
|
|
+
|
|
|
+ cacheFilters.append(showFitler!)
|
|
|
+ }
|
|
|
+ }else{
|
|
|
+ FilterLog(message: "缓存数据加入不成功!!!!!")
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ FilterLog(message: "加入后 当前的缓存个数为: \(cacheFilters.count) maxCount \(cacheFiltersMaxCount) 最后一个显示时间 \(String(describing: cacheFilters.last?.stickerInfo?.timelineIn))")
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /// 按时间从缓存中取出要显示的filter
|
|
|
+ /// - Parameter currTime: 当前播放时间
|
|
|
+ func changeFilter(currTime: Float64) {
|
|
|
+ FilterLog(message: " 要查找的 currTime is \(currTime)")
|
|
|
+ //1,删除已经显示过的 filter
|
|
|
+ self.cacheFilters.removeAll(where: {(filter) -> Bool in
|
|
|
+
|
|
|
+ (currTime > (filter.stickerInfo?.timelineOut ?? 0.0))
|
|
|
+ })
|
|
|
+
|
|
|
+ // 2,找出一个要显示的 fitler
|
|
|
+ let showIndex = cacheFilters.firstIndex(where: { (filter) -> Bool in
|
|
|
+ (currTime >= (filter.stickerInfo?.timelineIn ?? 0.0) && currTime <= (filter.stickerInfo?.timelineOut ?? 0.0))
|
|
|
+ })
|
|
|
+
|
|
|
+ if(showIndex == nil){
|
|
|
+
|
|
|
+ for (index,bsFilter )in cacheFilters.enumerated() {
|
|
|
+ print( "22222缓存操作 没要查找到要查找的显示是为:\(currTime) 缓存数据timeline in :\(bsFilter.stickerInfo?.timelineIn ?? 0.0)) timelineOut:\(bsFilter.stickerInfo?.timelineOut ?? 0.0) 缓存数 \(cacheFilters.count) index: \(index)")
|
|
|
+ }
|
|
|
+
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ let showFilter: PQBaseFilter = cacheFilters[showIndex ?? 0]
|
|
|
+
|
|
|
+ print("缓存操作 查找到命中的显示是为:\(currTime) 缓存数据timeline in :\(showFilter.stickerInfo?.timelineIn ?? 0.0)) timelineOut:\(showFilter.stickerInfo?.timelineOut ?? 0.0) 缓存数 \(cacheFilters.count) index: \(String(describing: showIndex))")
|
|
|
+
|
|
|
+ if(!(showFilter.isShow)){
|
|
|
+ FilterLog(message: "showIndex当前时间为 \(currTime) showIndex is \(String(describing: showIndex)) 显示 filter timein is: \(String(describing: showFilter.stickerInfo?.timelineIn)) timeout is: \(String(describing: showFilter.stickerInfo?.timelineOut))")
|
|
|
+
|
|
|
+ showFilter.isShow = true
|
|
|
|
|
|
- if(currentSticker?.type == StickerType.IMAGE.rawValue && showGaussianBlur){
|
|
|
- //高斯层
|
|
|
- let json = currentSticker?.toJSONString(prettyPrint: false)
|
|
|
- if json == nil {
|
|
|
- BFLog(message: "数据转换有问题 跳转")
|
|
|
- return
|
|
|
- }
|
|
|
- let blurStickerModel: PQEditVisionTrackMaterialsModel? = Mapper<PQEditVisionTrackMaterialsModel>().map(JSONString: json!)
|
|
|
- blurStickerModel?.canvasFillType = stickerContentMode.aspectFillStr.rawValue
|
|
|
- let showGaussianFitler:PQBaseFilter = PQImageFilter(sticker: blurStickerModel!)
|
|
|
-
|
|
|
- let iosb:GaussianBlur = GaussianBlur.init()
|
|
|
- iosb.blurRadiusInPixels = 20
|
|
|
- showGaussianFitler.addTarget(iosb)
|
|
|
-
|
|
|
- currentTarget.addTarget(showGaussianFitler, atTargetIndex: 0)
|
|
|
-
|
|
|
- iosb.addTarget(showFitler!)
|
|
|
+ movie!.removeAllTargets()
|
|
|
|
|
|
- showFitler?.addTarget(renderView, atTargetIndex: 0)
|
|
|
- }else{
|
|
|
- currentTarget.addTarget(showFitler!, atTargetIndex: 0)
|
|
|
- showFitler?.addTarget(renderView, atTargetIndex: 0)
|
|
|
+ if(showFilter.stickerInfo?.type == StickerType.IMAGE.rawValue && showGaussianBlur){
|
|
|
+
|
|
|
+ self.createFiltersQueue.async {
|
|
|
+ //高斯层
|
|
|
+ let json = showFilter.stickerInfo?.toJSONString(prettyPrint: false)
|
|
|
+ if json == nil {
|
|
|
+ FilterLog(message: "数据转换有问题 跳转")
|
|
|
+ return
|
|
|
+ }
|
|
|
|
|
|
- }
|
|
|
+ let blurStickerModel: PQEditVisionTrackMaterialsModel? = Mapper<PQEditVisionTrackMaterialsModel>().map(JSONString: json!)
|
|
|
+ blurStickerModel?.canvasFillType = stickerContentMode.aspectFillStr.rawValue
|
|
|
+ let showGaussianFitler:PQBaseFilter = PQImageFilter(sticker: blurStickerModel!)
|
|
|
+
|
|
|
+ let iosb:GaussianBlur = GaussianBlur.init()
|
|
|
+ iosb.blurRadiusInPixels = 20
|
|
|
+ showGaussianFitler.addTarget(iosb)
|
|
|
+
|
|
|
+ sharedImageProcessingContext.runOperationAsynchronously{ [self] in
|
|
|
+
|
|
|
+ self.movie?.addTarget(showGaussianFitler, atTargetIndex: 0)
|
|
|
+ iosb.addTarget(showFilter)
|
|
|
+ showFilter.addTarget(self.renderView as! ImageConsumer, atTargetIndex: 0)
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
+
|
|
|
+ }else{
|
|
|
+ movie?.addTarget(showFilter, atTargetIndex: 0)
|
|
|
+ showFilter.addTarget(renderView, atTargetIndex: 0)
|
|
|
|
|
|
+ }
|
|
|
+ self.createFiltersQueue.async {
|
|
|
+ self.createNextFilter()
|
|
|
+ }
|
|
|
|
|
|
- lastshowSticker = currentSticker
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -515,7 +615,7 @@ public extension PQGPUImagePlayerView {
|
|
|
self.progressLab.isHidden = false
|
|
|
}
|
|
|
// guard status != .playing else {
|
|
|
-// BFLog(message: "已经是播放状态")
|
|
|
+// FilterLog(message: "已经是播放状态")
|
|
|
// return
|
|
|
// }
|
|
|
|
|
@@ -574,7 +674,7 @@ public extension PQGPUImagePlayerView {
|
|
|
|
|
|
// 显示提示文字
|
|
|
func showTip(show: Bool) {
|
|
|
- BFLog(message: "showTip \(show)")
|
|
|
+ FilterLog(message: "showTip \(show)")
|
|
|
tipLab.isHidden = !show
|
|
|
if show {
|
|
|
playerEmptyView.isHidden = true
|
|
@@ -609,9 +709,23 @@ public extension PQGPUImagePlayerView {
|
|
|
filters = newFilters
|
|
|
}
|
|
|
|
|
|
-// // 重置所有 filer
|
|
|
-// func appendStickers(stickers: [PQEditVisionTrackMaterialsModel]) {
|
|
|
-//
|
|
|
-// mStickers = stickers
|
|
|
-// }
|
|
|
}
|
|
|
+
|
|
|
+// MARK: - RenderViewDelegate
|
|
|
+extension PQGPUImagePlayerView: RenderViewDelegate{
|
|
|
+ public func willDisplayFramebuffer(renderView _: RenderView, framebuffer _: Framebuffer) {
|
|
|
+ FilterLog(message: "willDisplayFramebuffer")
|
|
|
+ }
|
|
|
+
|
|
|
+ public func didDisplayFramebuffer(renderView _: RenderView, framebuffer: Framebuffer) {
|
|
|
+ FilterLog(message: "didDisplayFramebuffer")
|
|
|
+ }
|
|
|
+
|
|
|
+ public func shouldDisplayNextFramebufferAfterMainThreadLoop() -> Bool {
|
|
|
+ FilterLog(message: "didDisplayFramebuffer")
|
|
|
+
|
|
|
+ return false
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|