Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(55)

Side by Side Diff: media/video/capture/mac/video_capture_device_qtkit_mac.mm

Issue 464363003: Mac QTKit Video Capture: Run QTCaptureSession teardown in UI thread, clean up -stopCapture use. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: shess@ comments: Moved input/output removal to one place, cleaned up input/output count Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698