我正在开发一个应用程序,该应用程序从相机捕获帧并混合由另一个线程更新的图像。我的问题是每 500 毫秒调用一次的图像创建线程消耗了影响其他线程的峰值计算能力。
这里有一些日志以供澄清:
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 倍的时间,但在此期间只消耗 1/10 的 cpu。
有什么想法可以控制吗?
谢谢克里斯