OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #import "media/video/capture/mac/video_capture_device_qtkit_mac.h" | 5 #import "media/video/capture/mac/video_capture_device_qtkit_mac.h" |
6 | 6 |
7 #import <QTKit/QTKit.h> | 7 #import <QTKit/QTKit.h> |
8 | 8 |
9 #include "base/debug/crash_logging.h" | 9 #include "base/debug/crash_logging.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
137 [captureDecompressedOutput setPixelBufferAttributes:captureDictionary]; | 137 [captureDecompressedOutput setPixelBufferAttributes:captureDictionary]; |
138 | 138 |
139 return YES; | 139 return YES; |
140 } else { | 140 } else { |
141 // Remove the previously set capture device. | 141 // Remove the previously set capture device. |
142 if (!captureDeviceInput_) { | 142 if (!captureDeviceInput_) { |
143 [self sendErrorString:[NSString | 143 [self sendErrorString:[NSString |
144 stringWithUTF8String:"No video capture device set, on removal."]]; | 144 stringWithUTF8String:"No video capture device set, on removal."]]; |
145 return YES; | 145 return YES; |
146 } | 146 } |
147 if ([[captureSession_ inputs] count] > 0) { | 147 // Tear down input and output, stop the capture and deregister observers. |
148 // The device is still running. | 148 [self stopCapture]; |
149 [self stopCapture]; | |
150 } | |
151 if ([[captureSession_ outputs] count] > 0) { | |
152 // Only one output is set for |captureSession_|. | |
153 DCHECK_EQ([[captureSession_ outputs] count], 1u); | |
154 id output = [[captureSession_ outputs] objectAtIndex:0]; | |
155 [output setDelegate:nil]; | |
156 | |
157 // TODO(shess): QTKit achieves thread safety by posting messages to the | |
158 // main thread. As part of -addOutput:, it posts a message to the main | |
159 // thread which in turn posts a notification which will run in a future | |
160 // spin after the original method returns. -removeOutput: can post a | |
161 // main-thread message in between while holding a lock which the | |
162 // notification handler will need. Posting either -addOutput: or | |
163 // -removeOutput: to the main thread should fix it, remove is likely | |
164 // safer. http://crbug.com/152757 | |
165 [captureSession_ performSelectorOnMainThread:@selector(removeOutput:) | |
166 withObject:output | |
167 waitUntilDone:YES]; | |
168 } | |
169 [captureSession_ release]; | 149 [captureSession_ release]; |
170 captureSession_ = nil; | 150 captureSession_ = nil; |
171 [captureDeviceInput_ release]; | 151 [captureDeviceInput_ release]; |
172 captureDeviceInput_ = nil; | 152 captureDeviceInput_ = nil; |
173 return YES; | 153 return YES; |
174 } | 154 } |
175 } | 155 } |
176 | 156 |
177 - (BOOL)setCaptureHeight:(int)height | 157 - (BOOL)setCaptureHeight:(int)height |
178 width:(int)width | 158 width:(int)width |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
233 [notificationCenter addObserver:self | 213 [notificationCenter addObserver:self |
234 selector:@selector(handleNotification:) | 214 selector:@selector(handleNotification:) |
235 name:QTCaptureSessionRuntimeErrorNotification | 215 name:QTCaptureSessionRuntimeErrorNotification |
236 object:captureSession_]; | 216 object:captureSession_]; |
237 [captureSession_ startRunning]; | 217 [captureSession_ startRunning]; |
238 } | 218 } |
239 return YES; | 219 return YES; |
240 } | 220 } |
241 | 221 |
242 - (void)stopCapture { | 222 - (void)stopCapture { |
243 if ([[captureSession_ inputs] count] == 1) { | 223 // QTKit achieves thread safety and asynchronous execution by posting messages |
244 [captureSession_ removeInput:captureDeviceInput_]; | 224 // to main thread, e.g. -addOutput:. Both -removeOutput: and -removeInput: |
245 [captureSession_ stopRunning]; | 225 // post a message to main thread while holding a lock that the notification |
246 } | 226 // handler might need. To avoid q deadlock, we perform those tasks in the UI |
Scott Hess - ex-Googler
2014/08/18 18:23:40
is the 'q' meant to be an 'a'?
Also straighten up
mcasas
2014/08/19 15:24:59
Done. I use them interchangeably, but is true that
Scott Hess - ex-Googler
2014/08/19 18:27:50
Mostly I'm aiming for consistent use w/in a single
| |
227 // thread. See bug http://crbug.com/152757 and http://crbug.com/399792. | |
228 [self performSelectorOnMainThread:@selector(stopCaptureOnUIThread:) | |
229 withObject:captureSession_ | |
230 waitUntilDone:YES]; | |
231 [[NSNotificationCenter defaultCenter] removeObserver:self]; | |
232 } | |
247 | 233 |
248 [[NSNotificationCenter defaultCenter] removeObserver:self]; | 234 - (void)stopCaptureOnUIThread:(QTCaptureSession*)captureSession { |
Scott Hess - ex-Googler
2014/08/18 18:23:40
You never use |captureSession|, instead preferring
mcasas
2014/08/19 15:24:59
Done.
| |
235 DCHECK_EQ([[captureSession_ inputs] count], 1u); | |
236 [captureSession_ removeInput:captureDeviceInput_]; | |
237 [captureSession_ stopRunning]; | |
238 | |
239 DCHECK_EQ([[captureSession_ outputs] count], 1u); | |
240 id output = [[captureSession_ outputs] objectAtIndex:0]; | |
241 [output setDelegate:nil]; | |
242 [captureSession_ removeOutput:output]; | |
Scott Hess - ex-Googler
2014/08/18 18:23:40
Previously, the code handled 0 values for either c
mcasas
2014/08/19 15:24:59
I changed a bit the code to reflect your sharp obs
| |
249 } | 243 } |
250 | 244 |
251 // |captureOutput| is called by the capture device to deliver a new frame. | 245 // |captureOutput| is called by the capture device to deliver a new frame. |
252 - (void)captureOutput:(QTCaptureOutput*)captureOutput | 246 - (void)captureOutput:(QTCaptureOutput*)captureOutput |
253 didOutputVideoFrame:(CVImageBufferRef)videoFrame | 247 didOutputVideoFrame:(CVImageBufferRef)videoFrame |
254 withSampleBuffer:(QTSampleBuffer*)sampleBuffer | 248 withSampleBuffer:(QTSampleBuffer*)sampleBuffer |
255 fromConnection:(QTCaptureConnection*)connection { | 249 fromConnection:(QTCaptureConnection*)connection { |
256 [lock_ lock]; | 250 [lock_ lock]; |
257 if(!frameReceiver_) { | 251 if(!frameReceiver_) { |
258 [lock_ unlock]; | 252 [lock_ unlock]; |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
339 | 333 |
340 - (void)sendErrorString:(NSString*)error { | 334 - (void)sendErrorString:(NSString*)error { |
341 DLOG(ERROR) << [error UTF8String]; | 335 DLOG(ERROR) << [error UTF8String]; |
342 [lock_ lock]; | 336 [lock_ lock]; |
343 if (frameReceiver_) | 337 if (frameReceiver_) |
344 frameReceiver_->ReceiveError([error UTF8String]); | 338 frameReceiver_->ReceiveError([error UTF8String]); |
345 [lock_ unlock]; | 339 [lock_ unlock]; |
346 } | 340 } |
347 | 341 |
348 @end | 342 @end |
OLD | NEW |