ソースを参照

1导出视频时也使用缓存机制加载fitler

jsonwang 3 年 前
コミット
00a96434fe

+ 192 - 1
BFFramework/Classes/PQGPUImage/akfilters/Tools/PQCompositionExporter.swift

@@ -36,6 +36,14 @@ public class PQCompositionExporter {
     
     //是否显示高斯
     public var showGaussianBlur:Bool = false
+    
+    // 缓存创建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 init(asset: AVAsset, videoComposition: AVVideoComposition? = nil, audioMix: AVAudioMix? = nil, filters: [ImageProcessingOperation]? = nil,stickers:[PQEditVisionTrackMaterialsModel]? = nil, animationTool: AVVideoCompositionCoreAnimationTool? = nil, exportURL: URL) {
         self.asset = asset
@@ -57,6 +65,17 @@ public class PQCompositionExporter {
         guard !FileManager.default.fileExists(atPath: exportURL.absoluteString) else {
             return false
         }
+        
+        
+        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()
+        }
+        
         //        guard let videoTrack = asset.tracks(withMediaType:AVMediaType.video).first else { return false }
         let audioTrack = asset.tracks(withMediaType: AVMediaType.audio).first
 
@@ -131,11 +150,16 @@ public class PQCompositionExporter {
 
             currentTarget.addTarget(output!, atTargetIndex: 0)
 
+        }else{
+
+            configCache(beginTime: mStickers?.first?.timelineIn ?? 0)
+        
         }
  
         return true
     }
     
+ 
    public  func  findShowStikcer(currTime:Float64)  {
          
         if(mStickers?.count ?? 0 == 0){
@@ -216,7 +240,7 @@ public class PQCompositionExporter {
         input?.progress = { [weak self] currTime, duration, progress in
             
             if(self?.mStickers?.count ?? 0 > 0){
-                self?.findShowStikcer(currTime: CMTimeGetSeconds(self?.input?.currentTime ?? .zero) )
+                self?.changeFilter(currTime: CMTimeGetSeconds(self?.input?.currentTime ?? .zero) )
             }
             DispatchQueue.main.async {[weak self] in
                 self?.progressClosure?(Float(currTime), Float(duration), Float(progress))
@@ -282,4 +306,171 @@ public class PQCompositionExporter {
             }
         }
     }
+    
+    
+    
+    /// 初始化缓存,默认选创建 cacheFiltersMaxCount 个缓存 filterrs
+    /// - Parameter beginTime: 开始缓存的开始时间,用在 seek操作时 老的缓存已经无效不能在使用了
+    func configCache(beginTime: Float64 ) {
+        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)")
+
+            }
+            
+            for (index, currentSticker) in mStickers!.enumerated() {
+               //到达最大缓存数退出
+                if cacheFilters.count == cacheFiltersMaxCount {
+                    break
+                }
+                //小于缓存的开始时间继续查找
+                if(currentSticker.timelineOut < beginTime){
+                    continue
+                }
+                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!)
+                }
+
+            }
+            
+            
+            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){
+                input?.removeAllTargets()
+                let showFilter: PQBaseFilter = cacheFilters.first!
+                input?.addTarget(showFilter, atTargetIndex: 0)
+                showFilter.addTarget(output!, atTargetIndex: 0)
+            }
+      
+        }
+
+   
+
+  
+    }
+
+    //创建下一个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
+            
+            input!.removeAllTargets()
+        
+            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.input?.addTarget(showGaussianFitler, atTargetIndex: 0)
+                        iosb.addTarget(showFilter)
+                        showFilter.addTarget(output!, atTargetIndex: 0)
+                        
+                    }
+//                }
+            
+           
+                
+            }else{
+                input?.addTarget(showFilter, atTargetIndex: 0)
+                showFilter.addTarget(output!, atTargetIndex: 0)
+            }
+//            self.createFiltersQueue.async {
+                self.createNextFilter()
+//            }
+
+        }
+    }
 }