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

Side by Side Diff: media/video/capture/linux/video_capture_device_linux.cc

Issue 25388002: Eliminates the use of VideoCaptureDevice1 in VideoCaptureDeviceLinux. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 7 years, 2 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
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 #include "media/video/capture/linux/video_capture_device_linux.h" 5 #include "media/video/capture/linux/video_capture_device_linux.h"
6 6
7 #include <errno.h> 7 #include <errno.h>
8 #include <fcntl.h> 8 #include <fcntl.h>
9 #if defined(OS_OPENBSD) 9 #if defined(OS_OPENBSD)
10 #include <sys/videoio.h> 10 #include <sys/videoio.h>
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
189 delete self; 189 delete self;
190 return NULL; 190 return NULL;
191 } 191 }
192 close(fd); 192 close(fd);
193 193
194 return self; 194 return self;
195 } 195 }
196 196
197 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name) 197 VideoCaptureDeviceLinux::VideoCaptureDeviceLinux(const Name& device_name)
198 : state_(kIdle), 198 : state_(kIdle),
199 client_(NULL),
200 device_name_(device_name), 199 device_name_(device_name),
201 device_fd_(-1), 200 device_fd_(-1),
202 v4l2_thread_("V4L2Thread"), 201 v4l2_thread_("V4L2Thread"),
203 buffer_pool_(NULL), 202 buffer_pool_(NULL),
204 buffer_pool_size_(0), 203 buffer_pool_size_(0),
205 timeout_count_(0) { 204 timeout_count_(0) {}
206 }
207 205
208 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() { 206 VideoCaptureDeviceLinux::~VideoCaptureDeviceLinux() {
209 state_ = kIdle; 207 state_ = kIdle;
210 // Check if the thread is running. 208 // Check if the thread is running.
211 // This means that the device have not been DeAllocated properly. 209 // This means that the device have not been DeAllocated properly.
212 DCHECK(!v4l2_thread_.IsRunning()); 210 DCHECK(!v4l2_thread_.IsRunning());
213 211
214 v4l2_thread_.Stop(); 212 v4l2_thread_.Stop();
215 if (device_fd_ >= 0) { 213 if (device_fd_ >= 0) {
216 close(device_fd_); 214 close(device_fd_);
217 } 215 }
218 } 216 }
219 217
220 void VideoCaptureDeviceLinux::Allocate( 218 void VideoCaptureDeviceLinux::AllocateAndStart(
221 const VideoCaptureCapability& capture_format, 219 const VideoCaptureCapability& capture_format,
222 VideoCaptureDevice::Client* client) { 220 scoped_ptr<VideoCaptureDevice::Client> client) {
223 if (v4l2_thread_.IsRunning()) { 221 if (v4l2_thread_.IsRunning()) {
224 return; // Wrong state. 222 return; // Wrong state.
225 } 223 }
226 v4l2_thread_.Start(); 224 v4l2_thread_.Start();
227 v4l2_thread_.message_loop() 225 v4l2_thread_.message_loop()->PostTask(
228 ->PostTask(FROM_HERE, 226 FROM_HERE,
229 base::Bind(&VideoCaptureDeviceLinux::OnAllocate, 227 base::Bind(&VideoCaptureDeviceLinux::OnAllocateAndStart,
230 base::Unretained(this), 228 base::Unretained(this),
231 capture_format.width, 229 capture_format.width,
232 capture_format.height, 230 capture_format.height,
233 capture_format.frame_rate, 231 capture_format.frame_rate,
234 client)); 232 base::Passed(&client)));
235 } 233 }
236 234
237 void VideoCaptureDeviceLinux::Start() { 235 void VideoCaptureDeviceLinux::StopAndDeAllocate() {
238 if (!v4l2_thread_.IsRunning()) { 236 if (!v4l2_thread_.IsRunning()) {
239 return; // Wrong state. 237 return; // Wrong state.
240 } 238 }
241 v4l2_thread_.message_loop()->PostTask( 239 v4l2_thread_.message_loop()->PostTask(
242 FROM_HERE, 240 FROM_HERE,
243 base::Bind(&VideoCaptureDeviceLinux::OnStart, base::Unretained(this))); 241 base::Bind(&VideoCaptureDeviceLinux::OnStopAndDeAllocate,
244 }
245
246 void VideoCaptureDeviceLinux::Stop() {
247 if (!v4l2_thread_.IsRunning()) {
248 return; // Wrong state.
249 }
250 v4l2_thread_.message_loop()->PostTask(
251 FROM_HERE,
252 base::Bind(&VideoCaptureDeviceLinux::OnStop, base::Unretained(this)));
253 }
254
255 void VideoCaptureDeviceLinux::DeAllocate() {
256 if (!v4l2_thread_.IsRunning()) {
257 return; // Wrong state.
258 }
259 v4l2_thread_.message_loop()->PostTask(
260 FROM_HERE,
261 base::Bind(&VideoCaptureDeviceLinux::OnDeAllocate,
262 base::Unretained(this))); 242 base::Unretained(this)));
263 v4l2_thread_.Stop(); 243 v4l2_thread_.Stop();
264
265 // Make sure no buffers are still allocated. 244 // Make sure no buffers are still allocated.
266 // This can happen (theoretically) if an error occurs when trying to stop 245 // This can happen (theoretically) if an error occurs when trying to stop
267 // the camera. 246 // the camera.
268 DeAllocateVideoBuffers(); 247 DeAllocateVideoBuffers();
269 } 248 }
270 249
271 const VideoCaptureDevice::Name& VideoCaptureDeviceLinux::device_name() { 250 void VideoCaptureDeviceLinux::OnAllocateAndStart(int width,
272 return device_name_; 251 int height,
273 } 252 int frame_rate,
274 253 scoped_ptr<Client> client) {
275 void VideoCaptureDeviceLinux::OnAllocate(int width,
276 int height,
277 int frame_rate,
278 Client* client) {
279 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); 254 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
280 255
281 client_ = client; 256 client_ = client.Pass();
282 257
283 // Need to open camera with O_RDWR after Linux kernel 3.3. 258 // Need to open camera with O_RDWR after Linux kernel 3.3.
284 if ((device_fd_ = open(device_name_.id().c_str(), O_RDWR)) < 0) { 259 if ((device_fd_ = open(device_name_.id().c_str(), O_RDWR)) < 0) {
285 SetErrorState("Failed to open V4L2 device driver."); 260 SetErrorState("Failed to open V4L2 device driver.");
286 return; 261 return;
287 } 262 }
288 263
289 // Test if this is a V4L2 capture device. 264 // Test if this is a V4L2 capture device.
290 v4l2_capability cap; 265 v4l2_capability cap;
291 if (!((ioctl(device_fd_, VIDIOC_QUERYCAP, &cap) == 0) && 266 if (!((ioctl(device_fd_, VIDIOC_QUERYCAP, &cap) == 0) &&
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 // Store our current width and height. 336 // Store our current width and height.
362 VideoCaptureCapability current_settings; 337 VideoCaptureCapability current_settings;
363 current_settings.color = V4l2ColorToVideoCaptureColorFormat( 338 current_settings.color = V4l2ColorToVideoCaptureColorFormat(
364 video_fmt.fmt.pix.pixelformat); 339 video_fmt.fmt.pix.pixelformat);
365 current_settings.width = video_fmt.fmt.pix.width; 340 current_settings.width = video_fmt.fmt.pix.width;
366 current_settings.height = video_fmt.fmt.pix.height; 341 current_settings.height = video_fmt.fmt.pix.height;
367 current_settings.frame_rate = frame_rate; 342 current_settings.frame_rate = frame_rate;
368 current_settings.expected_capture_delay = 0; 343 current_settings.expected_capture_delay = 0;
369 current_settings.interlaced = false; 344 current_settings.interlaced = false;
370 345
371 state_ = kAllocated;
372 // Report the resulting frame size to the client. 346 // Report the resulting frame size to the client.
373 client_->OnFrameInfo(current_settings); 347 client_->OnFrameInfo(current_settings);
374 }
375 348
376 void VideoCaptureDeviceLinux::OnDeAllocate() { 349 // Start capturing.
377 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
378
379 // If we are in error state or capturing
380 // try to stop the camera.
381 if (state_ == kCapturing) {
382 OnStop();
383 }
384 if (state_ == kAllocated) {
385 state_ = kIdle;
386 }
387
388 // We need to close and open the device if we want to change the settings
389 // Otherwise VIDIOC_S_FMT will return error
390 // Sad but true.
391 close(device_fd_);
392 device_fd_ = -1;
393 }
394
395 void VideoCaptureDeviceLinux::OnStart() {
396 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
397
398 if (state_ != kAllocated) {
399 return;
400 }
401
402 if (!AllocateVideoBuffers()) { 350 if (!AllocateVideoBuffers()) {
403 // Error, We can not recover. 351 // Error, We can not recover.
404 SetErrorState("Allocate buffer failed"); 352 SetErrorState("Allocate buffer failed");
405 return; 353 return;
406 } 354 }
407 355
408 // Start UVC camera. 356 // Start UVC camera.
409 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 357 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
410 if (ioctl(device_fd_, VIDIOC_STREAMON, &type) == -1) { 358 if (ioctl(device_fd_, VIDIOC_STREAMON, &type) == -1) {
411 SetErrorState("VIDIOC_STREAMON failed"); 359 SetErrorState("VIDIOC_STREAMON failed");
412 return; 360 return;
413 } 361 }
414 362
415 state_ = kCapturing; 363 state_ = kCapturing;
416 // Post task to start fetching frames from v4l2. 364 // Post task to start fetching frames from v4l2.
417 v4l2_thread_.message_loop()->PostTask( 365 v4l2_thread_.message_loop()->PostTask(
418 FROM_HERE, 366 FROM_HERE,
419 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask, 367 base::Bind(&VideoCaptureDeviceLinux::OnCaptureTask,
420 base::Unretained(this))); 368 base::Unretained(this)));
421 } 369 }
422 370
423 void VideoCaptureDeviceLinux::OnStop() { 371 void VideoCaptureDeviceLinux::OnStopAndDeAllocate() {
424 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); 372 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
425 373
426 state_ = kAllocated;
427
428 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 374 v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
429 if (ioctl(device_fd_, VIDIOC_STREAMOFF, &type) < 0) { 375 if (ioctl(device_fd_, VIDIOC_STREAMOFF, &type) < 0) {
430 SetErrorState("VIDIOC_STREAMOFF failed"); 376 SetErrorState("VIDIOC_STREAMOFF failed");
431 return; 377 return;
432 } 378 }
433 // We don't dare to deallocate the buffers if we can't stop 379 // We don't dare to deallocate the buffers if we can't stop
434 // the capture device. 380 // the capture device.
435 DeAllocateVideoBuffers(); 381 DeAllocateVideoBuffers();
382
383 // We need to close and open the device if we want to change the settings
384 // Otherwise VIDIOC_S_FMT will return error
385 // Sad but true.
386 close(device_fd_);
387 device_fd_ = -1;
388 state_ = kIdle;
389 client_.reset();
436 } 390 }
437 391
438 void VideoCaptureDeviceLinux::OnCaptureTask() { 392 void VideoCaptureDeviceLinux::OnCaptureTask() {
439 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); 393 DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current());
440 394
441 if (state_ != kCapturing) { 395 if (state_ != kCapturing) {
442 return; 396 return;
443 } 397 }
444 398
445 fd_set r_set; 399 fd_set r_set;
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
574 if (ioctl(device_fd_, VIDIOC_REQBUFS, &r_buffer) < 0) { 528 if (ioctl(device_fd_, VIDIOC_REQBUFS, &r_buffer) < 0) {
575 SetErrorState("Failed to reset buf."); 529 SetErrorState("Failed to reset buf.");
576 } 530 }
577 531
578 delete [] buffer_pool_; 532 delete [] buffer_pool_;
579 buffer_pool_ = NULL; 533 buffer_pool_ = NULL;
580 buffer_pool_size_ = 0; 534 buffer_pool_size_ = 0;
581 } 535 }
582 536
583 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) { 537 void VideoCaptureDeviceLinux::SetErrorState(const std::string& reason) {
538 DCHECK(!v4l2_thread_.IsRunning() ||
539 v4l2_thread_.message_loop() == base::MessageLoop::current());
584 DVLOG(1) << reason; 540 DVLOG(1) << reason;
585 state_ = kError; 541 state_ = kError;
586 client_->OnError(); 542 client_->OnError();
587 } 543 }
588 544
589 } // namespace media 545 } // namespace media
OLDNEW
« no previous file with comments | « media/video/capture/linux/video_capture_device_linux.h ('k') | media/video/capture/video_capture_device_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698