2016-04-20 5 views
2

Я пишу приложение для длительной экспозиции изображения.сделалOutputSampleBuffer кадры кадры

Я использовал func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) получить CMSampleBuffer для нанесения CIFilter с помощью CILightenBlendMode.

Проблема в том, что смешение занимает слишком много времени и приведет к падению кадров. Я попытался скопировать буфер:

var copiedBuffer:CMSampleBuffer? 
CMSampleBufferCreateCopy(nil, sampleBuffer, &copiedBuffer) 
blendImages(copiedBuffer!) 

Но это не помогло, кадры по-прежнему падает.

Полный код:

func captureOutput(captureOutput: AVCaptureOutput!, didOutputSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) { 

    if(CameraService.longExposureRunning){ 
     var copiedBuffer:CMSampleBuffer? 
     CMSampleBufferCreateCopy(nil, sampleBuffer, &copiedBuffer) 
     blendImages(copiedBuffer!) 
    } 
} 

func captureOutput(captureOutput: AVCaptureOutput!, didDropSampleBuffer sampleBuffer: CMSampleBuffer!, fromConnection connection: AVCaptureConnection!) { 
    print("Dropped") 

} 


func blendImages(buffer:CMSampleBuffer){ 

    let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT 
    dispatch_async(dispatch_get_global_queue(priority, 0)){ 
     let pixelBuffer = CMSampleBufferGetImageBuffer(buffer) 

     let cameraImage = CIImage(CVPixelBuffer: pixelBuffer!) 

     if let backgroundImage = self.lastImage{ 
      let blendEffect = CIFilter(name: "CILightenBlendMode") 
      blendEffect?.setValue(backgroundImage, forKey: kCIInputBackgroundImageKey) 
      blendEffect?.setValue(cameraImage, forKey: kCIInputImageKey) 
      self.lastImage = blendEffect?.outputImage 
      print("Blending") 
     }else{ 
      self.lastImage = cameraImage 
     } 

     let filteredImage = UIImage(CIImage: self.lastImage!) 
     dispatch_async(dispatch_get_main_queue()) 
     { 
      imageView.image = filteredImage 
     } 
    } 
} 

ответ

1

Я подозреваю, что CoreImage является конкатенация все кадры в одно огромное ядро. Вы можете найти CIImageAccumulator, но я могу заставить ваш код работать, заставляя Core Image отображать цепочку и начинать с каждого кадра.

Я изменил тип вашей lastImage переменного, чем опциональный UIImage и добавил константу с именем context который является CIContext. С ними на месте это прекрасно работает:

Использование: let context:CIContext = CIContext(options: [kCIContextUseSoftwareRenderer:false]) для графического процессора вместо рендеринга ЦП.

func blendImages(buffer:CMSampleBuffer){ 

let priority = DISPATCH_QUEUE_PRIORITY_DEFAULT 
dispatch_async(dispatch_get_global_queue(priority, 0)){ 
    let pixelBuffer = CMSampleBufferGetImageBuffer(buffer) 

    let cameraImage = CIImage(CVPixelBuffer: pixelBuffer!) 

    if let backgroundImage = self.lastImage { 
    let blendEffect = CIFilter(name: "CILightenBlendMode")! 

    blendEffect.setValue(
     CIImage(image: backgroundImage), 
     forKey: kCIInputBackgroundImageKey) 

    blendEffect.setValue(
     cameraImage, forKey: 
     kCIInputImageKey) 

    let imageRef = self.context.createCGImage(
     blendEffect.outputImage!, 
     fromRect: blendEffect.outputImage!.extent) 

    self.lastImage = UIImage(CGImage: imageRef) 
    print("Blending") 
    }else{ 
    let imageRef = self.context.createCGImage(
     cameraImage, 
     fromRect: cameraImage.extent) 

    self.lastImage = UIImage(CGImage: imageRef) 
    } 

    let filteredImage = self.lastImage 
    dispatch_async(dispatch_get_main_queue()) 
    { 
    self.imageView.image = filteredImage 
    } 
} 
} 

Веселый эффект!

Simon

+0

Спасибо, я буду проверять это завтра :) – ferdyyy

+0

Итак, я внедрил ваш метод, он по-прежнему отбрасывает много кадров в моем приложении. Но теперь он уменьшает количество кадров. Я получаю каждый 20-й кадр для обработки. Как вы создали CIContext? – ferdyyy

+1

На моем iPad Pro у меня не было никаких капель. Возможно, стоит рассмотреть возможность использования целевого объекта на основе GPU и отображения с помощью GLKit 'GLKView'. В моих тестах я использовал контекст процессора: 'let context = Context()'. –

0

Самая очевидная вещь, которую я могу думать о том, чтобы проверить При настройке выходов.

Убедитесь, что на вашем AVAssetWriterInput установлено значение true для параметра DataInRealTime.

https://developer.apple.com/library/tvos/documentation/AVFoundation/Reference/AVAssetWriterInput_Class/index.html#//apple_ref/occ/instp/AVAssetWriterInput/expectsMediaDataInRealTime

+0

На самом деле я не использую AVAssetWriterInput. Я не совсем уверен, что это поможет мне в этом случае, но я могу ошибаться. Как вы могли бы использовать его для смешивания изображений позже? – ferdyyy

+0

AVAssetWriterInput также будет продавать CMSampleBuffers, но когда дело доходит до их обработки, это может быть действительно «коротко», если ожидать, чтоMediaDataInRealTime не установлено в true, поскольку в этом случае он оптимизируется для обработки с диска в реальном времени. Это просто мысль - я видел выходные видеоролики, которые много зацепляли, когда я использую вход в режиме реального времени, но забыл установить этот параметр. –