BradLarson / GPUImage

An open source iOS framework for GPU-based image and video processing
http://www.sunsetlakesoftware.com/2012/02/12/introducing-gpuimage-framework
BSD 3-Clause "New" or "Revised" License
20.25k stars 4.61k forks source link

__copy_helper_block_ crash in AVFoundation #1994

Open hip4yes opened 9 years ago

hip4yes commented 9 years ago

I have a strange crash in my video processing app. It uses AVFoundation to work with video & audio and GPUImage for filtering. I have never faced this issue myself but after releasing it to the App Store it appeared in Crashlytics quite often. Here is the log of the crash:

Thread : Crashed: AVPlayerItemOutput queue 0 libobjc.A.dylib 0x00000001986f80b4 objc_retain + 20 1 libsystem_blocks.dylib 0x0000000198d79bf8 _Block_object_assign + 320 2 AVFoundation 0x0000000186895a34 copy_helper_block_171 + 36 3 libsystem_blocks.dylib 0x0000000198d79738 _Block_copy_internal + 384 4 libdispatch.dylib 0x0000000198d252fc _dispatch_Block_copy + 36 5 libdispatch.dylib 0x0000000198d2685c dispatch_async + 68 6 AVFoundation 0x00000001868959ac -[AVPlayerItemVideoOutput _dispatchOutputSequenceWasFlushed] + 112 7 libdispatch.dylib 0x0000000198d2536c _dispatch_client_callout + 16 8 libdispatch.dylib 0x0000000198d2e6e8 _dispatch_barrier_sync_f_invoke + 76 9 AVFoundation 0x00000001868940a8 AVPlayerItemVideoOutput_figVCSequentialAvailable + 196 10 MediaToolbox 0x000000018a3c16f8 FigVisualContextImageAvailableSequential + 108 11 MediaToolbox 0x000000018a348ce8 itemremote_postNotificationWithPayload + 3996 12 MediaToolbox 0x000000018a342d60 FigPlayerRemoteCallbacksServer_SendNotifyPing + 924 13 MediaToolbox 0x000000018a342998 _XSendNotifyPing + 60 14 MediaToolbox 0x000000018a33f0d4 figmoviecallbacks_server + 112 15 MediaToolbox 0x000000018a33f018 fpr_ClientPortCallBack + 208 16 CoreFoundation 0x0000000187f44ce0 CFMachPortPerform + 180 17 CoreFoundation 0x0000000187f598fc CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION + 56 18 CoreFoundation 0x0000000187f5985c CFRunLoopDoSource1 + 436 19 CoreFoundation 0x0000000187f577dc CFRunLoopRun + 1640 20 CoreFoundation 0x0000000187e851f4 CFRunLoopRunSpecific + 396 21 GraphicsServices 0x00000001910135a4 GSEventRunModal + 168 22 UIKit 0x000000018c7b6784 UIApplicationMain + 1488 23 MerryVideoEditor 0x000000010024b804 main (main.m:16) 24 libdyld.dylib 0x0000000198d4ea08 start + 4

This is how I connect AVFoundation to GPUImage:

class ProjectEditorViewController: UIViewController { private var videoPlayerView = VideoPlayerView() private var movieFile: GPUImageMovie!
private var currentComposition: AVComposition! //...and other properties }

// MARK: - Filtering & Playback extension ProjectEditorViewController{ func updatePlayer() {

  currentFilter.removeAllTargets()
  movieFile?.removeAllTargets()
  movieFile?.endProcessing()

  let time = self.videoPlayerView.player?.currentItem.currentTime() ?? kCMTimeZero

  let (composition, audioMix) = compositionBuilder.buildCompositionFromTimeLine(timeLine)
  videoPlayerView.setAsset(composition)
  videoPlayerView.playerItem.audioMix = audioMix

  movieFile = GPUImageMovie(playerItem: videoPlayerView.player.currentItem)
  currentFilter.applyFromOutput(movieFile, toInput: gpuPlayerView)
  movieFile.startProcessing()

  addSyncLayerIfNeededForComposition(composition)

  videoPlayerView.player.seekToTime(time, toleranceBefore: kPlayerToleranceSeekTime, toleranceAfter: kPlayerToleranceSeekTime)
  currentComposition = composition

}

func updatePlayerFilter(){
if movieFile != nil{ movieFile.removeAllTargets() currentFilter.applyFromOutput(movieFile, toInput: gpuPlayerView) if(!videoPlayerView.isPlaying) { movieFile.startProcessing() } addSyncLayerIfNeededForComposition(currentComposition) }else{ updatePlayer() } }
} Any ideas what is wrong with my code?

gjritter commented 9 years ago

We've encountered the same stack trace in our app as well. Were you able to track down the source of the problem in yours?

shmakovigor commented 9 years ago

This is an issue in GPUImageMovie - when instance adds itself as AVPlayerItemVideoOutput delegate: [playerItemOutput setDelegate:self queue:videoProcessingQueue], playerItemOutput doesn't release its delegate when GPUImageMovie instance is deallocating. Later, this results in a method call from the deallocated object (outputSequenceWasFlushed:) and u get crash. This was found with help of NSZombie detector and I fixed it by adding this in GPUImageMovie dealloc method: [playerItemOutput setDelegate:nil queue:nil]; Good luck, Nikita ;)

juanmao commented 7 years ago

add [playerItemOutput setDelegate:nil queue:nil] in endProcess func is better, because when call multi startProcess, there will be lots of output, and the others delegate will not be set nil.