Index: media/video/capture/mac/video_capture_device_qtkit_mac.mm |
diff --git a/media/video/capture/mac/video_capture_device_qtkit_mac.mm b/media/video/capture/mac/video_capture_device_qtkit_mac.mm |
index 86d4e82d71ac2933e44a0954db702558e663120f..26e942d19fd6d136156f5fe69bae430056e5e60e 100644 |
--- a/media/video/capture/mac/video_capture_device_qtkit_mac.mm |
+++ b/media/video/capture/mac/video_capture_device_qtkit_mac.mm |
@@ -146,28 +146,8 @@ |
stringWithUTF8String:"No video capture device set, on removal."]]; |
return YES; |
} |
- if ([[captureSession_ inputs] count] > 0) { |
- // The device is still running. |
- [self stopCapture]; |
- } |
- if ([[captureSession_ outputs] count] > 0) { |
- // Only one output is set for |captureSession_|. |
- DCHECK_EQ([[captureSession_ outputs] count], 1u); |
- id output = [[captureSession_ outputs] objectAtIndex:0]; |
- [output setDelegate:nil]; |
- |
- // TODO(shess): QTKit achieves thread safety by posting messages to the |
- // main thread. As part of -addOutput:, it posts a message to the main |
- // thread which in turn posts a notification which will run in a future |
- // spin after the original method returns. -removeOutput: can post a |
- // main-thread message in between while holding a lock which the |
- // notification handler will need. Posting either -addOutput: or |
- // -removeOutput: to the main thread should fix it, remove is likely |
- // safer. http://crbug.com/152757 |
- [captureSession_ performSelectorOnMainThread:@selector(removeOutput:) |
- withObject:output |
- waitUntilDone:YES]; |
- } |
+ // Tear down input and output, stop the capture and deregister observers. |
+ [self stopCapture]; |
[captureSession_ release]; |
captureSession_ = nil; |
[captureDeviceInput_ release]; |
@@ -242,14 +222,32 @@ |
} |
- (void)stopCapture { |
- if ([[captureSession_ inputs] count] == 1) { |
- [captureSession_ removeInput:captureDeviceInput_]; |
- [captureSession_ stopRunning]; |
- } |
- |
+ // QTKit achieves thread safety and asynchronous execution by posting messages |
+ // to the main thread, e.g. -addOutput:. Both -removeOutput: and -removeInput: |
+ // post a message to the main thread while holding a lock that the |
+ // notification handler might need. To avoid a deadlock, we perform those |
+ // tasks in the main thread. See bugs http://crbug.com/152757 and |
+ // http://crbug.com/399792. |
+ [self performSelectorOnMainThread:@selector(stopCaptureOnUIThread:) |
+ withObject:nil |
+ waitUntilDone:YES]; |
[[NSNotificationCenter defaultCenter] removeObserver:self]; |
} |
+- (void)stopCaptureOnUIThread:(id)dummy { |
+ if ([[captureSession_ outputs] count] == 0u || |
+ [[captureSession_ inputs] count] == 0u) |
+ return; |
Scott Hess - ex-Googler
2014/08/19 18:27:50
If this is correct, it should be in -stopCapture i
mcasas
2014/08/20 09:08:25
I think that's reasonable. So I made it look more
|
+ DCHECK_EQ([[captureSession_ inputs] count], 1u); |
+ [captureSession_ removeInput:captureDeviceInput_]; |
+ [captureSession_ stopRunning]; |
+ |
+ DCHECK_EQ([[captureSession_ outputs] count], 1u); |
+ id output = [[captureSession_ outputs] objectAtIndex:0]; |
+ [output setDelegate:nil]; |
+ [captureSession_ removeOutput:output]; |
+} |
+ |
// |captureOutput| is called by the capture device to deliver a new frame. |
- (void)captureOutput:(QTCaptureOutput*)captureOutput |
didOutputVideoFrame:(CVImageBufferRef)videoFrame |