我正在研究一個應用程序,該應用程序捕獲來自攝像機的幀,並混合由另一個線程更新的圖像。我的問題是,每500ms調用一次的圖像創建線程會消耗影響其他線程的峯值計算能力。GCD設置調度/線程之間的優先級
這裏是一些日誌說明:
captureOutput(): used time: 0.027741014957428 , frame rate: 36.0477077545513
captureOutput(): used time: 0.0285720229148865 , frame rate: 34.9992719444091
captureOutput(): used time: 0.0310209989547729 , frame rate: 32.2362281581567
captureOutput(): used time: 0.0268059968948364 , frame rate: 37.3050852733863
captureOutput(): used time: 0.0263729691505432 , frame rate: 37.9176115624965
motionCallback(): starting drawing:
captureOutput(): used time: 0.0376390218734741 , frame rate: 26.5681718127947
motionCallback(): elapesed time: 0.0835540294647217
captureOutput(): used time: 0.0581380128860474 , frame rate: 17.2004502795793
captureOutput(): used time: 0.0364410281181335 , frame rate: 27.4415967836645
captureOutput(): used time: 0.0278580188751221 , frame rate: 35.8963070734734
captureOutput(): used time: 0.0283130407333374 , frame rate: 35.3194137435949
captureOutput(): used time: 0.0271909832954407 , frame rate: 36.7768972947616
captureOutput(): used time: 0.0268760323524475 , frame rate: 37.2078730552999
正如你可以看到captureOutput擁有超過30 fps的幀速率。只要motionCallback創建圖像,幀速率就會下降,然後再次上升。請注意,motionCallback()僅在每個第15個捕獲幀中調用,因此平均計算能力應該足夠了。
captureOutput()是在這樣創造了一個隊列運行:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.m_captureSessionQueue = DispatchQueue(label: "CaptureSessionOutputQueue", attributes: DispatchQueueAttributes.serial)
}
對我設置AVCapture後來是這樣的:
videoDataOutput.setSampleBufferDelegate(self, queue: self.m_captureSessionQueue)
motionCallback()設置這樣的:
let interval = 0.4
if m_manager.isDeviceMotionAvailable {
m_manager.showsDeviceMovementDisplay = true
m_manager.deviceMotionUpdateInterval = interval
// XArbitraryCorrectedZVertical
m_manager.startDeviceMotionUpdates(using: CMAttitudeReferenceFrame.xArbitraryCorrectedZVertical , to: OperationQueue.main, withHandler: motionCallback)
print("viewDidLoad(): CM initialized !")
}
及更高版本:
func motionCallback(_ motion: CMDeviceMotion?, error: NSError?) -> Void {
guard let mot = motion else {return}
print("motionCallback(): starting drawing: ")
let start = NSDate() // <<<<<<<<<< Start time
self.m_instrview?.update(attitude: mot.attitude)
self.m_overlayImage = CIImage(image: self.m_instrview!.generateImage()!)
let end = NSDate() // <<<<<<<<<< end time
let timeInterval: Double = end.timeIntervalSince(start as Date)
print("motionCallback(): elapesed time: ", timeInterval)
}
和generateImage()這樣的:
func generateImage() -> UIImage {
UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.main().scale)
drawHierarchy(in: self.bounds, afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return image!
}
的想法是創建每次CoreMotion系統讓我更新,我會生成一個新的形象。
我的問題是我如何平均motionCallback()的計算時間,以便它不會消耗導致幀速率下降的峯值CPU功率?所以我會接受它運行10倍,但在此期間只消耗CPU的十分之一。
任何想法如何可以控制?
感謝 克里斯
您的動作回調位於主隊列中,其中包括對「generateImage」的調用,這似乎是CPU密集型的功能。請注意,如果您將其分派到後臺隊列中,您仍然必須在主隊列上執行UI更新。 – Paulw11
是的,這正是我的問題,必須在主線程上調用CPU密集型功能。因此,如果我不能對motionCallBack進行優先級排序,那麼優先捕獲線程的優先順序是什麼?我怎樣才能做到這一點 ? – Chris
爲什麼說cpu密集函數必須在主線程上調用? generateImage是cpu密集型的,但可以在後臺線程上運行。一旦完成,在主線程上分派CIImage的分配。使用低優先級線程處理核心運動事件 – Paulw11