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

Side by Side Diff: media/gpu/v4l2_image_processor.cc

Issue 2076423004: Remove calls to MessageLoop::current() in media. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: CR Created 4 years, 5 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 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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 <errno.h> 5 #include <errno.h>
6 #include <fcntl.h> 6 #include <fcntl.h>
7 #include <linux/videodev2.h> 7 #include <linux/videodev2.h>
8 #include <poll.h> 8 #include <poll.h>
9 #include <string.h> 9 #include <string.h>
10 #include <sys/eventfd.h> 10 #include <sys/eventfd.h>
11 #include <sys/ioctl.h> 11 #include <sys/ioctl.h>
12 #include <sys/mman.h> 12 #include <sys/mman.h>
13 13
14 #include "base/bind.h" 14 #include "base/bind.h"
15 #include "base/bind_helpers.h" 15 #include "base/bind_helpers.h"
16 #include "base/callback.h" 16 #include "base/callback.h"
17 #include "base/numerics/safe_conversions.h" 17 #include "base/numerics/safe_conversions.h"
18 #include "base/single_thread_task_runner.h"
18 #include "base/threading/thread_task_runner_handle.h" 19 #include "base/threading/thread_task_runner_handle.h"
19 #include "media/gpu/v4l2_image_processor.h" 20 #include "media/gpu/v4l2_image_processor.h"
20 21
21 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_str) \ 22 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value, type_str) \
22 do { \ 23 do { \
23 if (device_->Ioctl(type, arg) != 0) { \ 24 if (device_->Ioctl(type, arg) != 0) { \
24 PLOG(ERROR) << __func__ << "(): ioctl() failed: " << type_str; \ 25 PLOG(ERROR) << __func__ << "(): ioctl() failed: " << type_str; \
25 return value; \ 26 return value; \
26 } \ 27 } \
27 } while (0) 28 } while (0)
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
228 job_record->ready_cb = cb; 229 job_record->ready_cb = cb;
229 230
230 device_thread_.message_loop()->PostTask( 231 device_thread_.message_loop()->PostTask(
231 FROM_HERE, base::Bind(&V4L2ImageProcessor::ProcessTask, 232 FROM_HERE, base::Bind(&V4L2ImageProcessor::ProcessTask,
232 base::Unretained(this), base::Passed(&job_record))); 233 base::Unretained(this), base::Passed(&job_record)));
233 } 234 }
234 235
235 void V4L2ImageProcessor::ProcessTask(std::unique_ptr<JobRecord> job_record) { 236 void V4L2ImageProcessor::ProcessTask(std::unique_ptr<JobRecord> job_record) {
236 int index = job_record->output_buffer_index; 237 int index = job_record->output_buffer_index;
237 DVLOG(3) << __func__ << ": Reusing output buffer, index=" << index; 238 DVLOG(3) << __func__ << ": Reusing output buffer, index=" << index;
238 DCHECK_EQ(device_thread_.message_loop(), base::MessageLoop::current()); 239 DCHECK(device_thread_.task_runner()->BelongsToCurrentThread());
239 240
240 EnqueueOutput(index); 241 EnqueueOutput(index);
241 input_queue_.push(make_linked_ptr(job_record.release())); 242 input_queue_.push(make_linked_ptr(job_record.release()));
242 EnqueueInput(); 243 EnqueueInput();
243 } 244 }
244 245
245 void V4L2ImageProcessor::Destroy() { 246 void V4L2ImageProcessor::Destroy() {
246 DVLOG(3) << __func__; 247 DVLOG(3) << __func__;
247 DCHECK(child_task_runner_->BelongsToCurrentThread()); 248 DCHECK(child_task_runner_->BelongsToCurrentThread());
248 249
249 weak_this_factory_.InvalidateWeakPtrs(); 250 weak_this_factory_.InvalidateWeakPtrs();
250 251
251 // If the device thread is running, destroy using posted task. 252 // If the device thread is running, destroy using posted task.
252 if (device_thread_.IsRunning()) { 253 if (device_thread_.IsRunning()) {
253 device_thread_.message_loop()->PostTask( 254 device_thread_.message_loop()->PostTask(
254 FROM_HERE, 255 FROM_HERE,
255 base::Bind(&V4L2ImageProcessor::DestroyTask, base::Unretained(this))); 256 base::Bind(&V4L2ImageProcessor::DestroyTask, base::Unretained(this)));
256 // Wait for tasks to finish/early-exit. 257 // Wait for tasks to finish/early-exit.
257 device_thread_.Stop(); 258 device_thread_.Stop();
258 } else { 259 } else {
259 // Otherwise DestroyTask() is not needed. 260 // Otherwise DestroyTask() is not needed.
260 DCHECK(!device_poll_thread_.IsRunning()); 261 DCHECK(!device_poll_thread_.IsRunning());
261 } 262 }
262 263
263 delete this; 264 delete this;
264 } 265 }
265 266
266 void V4L2ImageProcessor::DestroyTask() { 267 void V4L2ImageProcessor::DestroyTask() {
267 DCHECK_EQ(device_thread_.message_loop(), base::MessageLoop::current()); 268 DCHECK(device_thread_.task_runner()->BelongsToCurrentThread());
268 269
269 // Stop streaming and the device_poll_thread_. 270 // Stop streaming and the device_poll_thread_.
270 StopDevicePoll(); 271 StopDevicePoll();
271 } 272 }
272 273
273 bool V4L2ImageProcessor::CreateInputBuffers() { 274 bool V4L2ImageProcessor::CreateInputBuffers() {
274 DVLOG(3) << __func__; 275 DVLOG(3) << __func__;
275 DCHECK(child_task_runner_->BelongsToCurrentThread()); 276 DCHECK(child_task_runner_->BelongsToCurrentThread());
276 DCHECK(!input_streamon_); 277 DCHECK(!input_streamon_);
277 278
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 memset(&reqbufs, 0, sizeof(reqbufs)); 412 memset(&reqbufs, 0, sizeof(reqbufs));
412 reqbufs.count = 0; 413 reqbufs.count = 0;
413 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 414 reqbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
414 reqbufs.memory = V4L2_MEMORY_MMAP; 415 reqbufs.memory = V4L2_MEMORY_MMAP;
415 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs); 416 IOCTL_OR_LOG_ERROR(VIDIOC_REQBUFS, &reqbufs);
416 417
417 output_buffer_map_.clear(); 418 output_buffer_map_.clear();
418 } 419 }
419 420
420 void V4L2ImageProcessor::DevicePollTask(bool poll_device) { 421 void V4L2ImageProcessor::DevicePollTask(bool poll_device) {
421 DCHECK_EQ(device_poll_thread_.message_loop(), base::MessageLoop::current()); 422 DCHECK(device_poll_thread_.task_runner()->BelongsToCurrentThread());
422 423
423 bool event_pending; 424 bool event_pending;
424 if (!device_->Poll(poll_device, &event_pending)) { 425 if (!device_->Poll(poll_device, &event_pending)) {
425 NotifyError(); 426 NotifyError();
426 return; 427 return;
427 } 428 }
428 429
429 // All processing should happen on ServiceDeviceTask(), since we shouldn't 430 // All processing should happen on ServiceDeviceTask(), since we shouldn't
430 // touch encoder state from this thread. 431 // touch encoder state from this thread.
431 device_thread_.message_loop()->PostTask( 432 device_thread_.message_loop()->PostTask(
432 FROM_HERE, base::Bind(&V4L2ImageProcessor::ServiceDeviceTask, 433 FROM_HERE, base::Bind(&V4L2ImageProcessor::ServiceDeviceTask,
433 base::Unretained(this))); 434 base::Unretained(this)));
434 } 435 }
435 436
436 void V4L2ImageProcessor::ServiceDeviceTask() { 437 void V4L2ImageProcessor::ServiceDeviceTask() {
437 DCHECK_EQ(device_thread_.message_loop(), base::MessageLoop::current()); 438 DCHECK(device_thread_.task_runner()->BelongsToCurrentThread());
438 // ServiceDeviceTask() should only ever be scheduled from DevicePollTask(), 439 // ServiceDeviceTask() should only ever be scheduled from DevicePollTask(),
439 // so either: 440 // so either:
440 // * device_poll_thread_ is running normally 441 // * device_poll_thread_ is running normally
441 // * device_poll_thread_ scheduled us, but then a DestroyTask() shut it down, 442 // * device_poll_thread_ scheduled us, but then a DestroyTask() shut it down,
442 // in which case we should early-out. 443 // in which case we should early-out.
443 if (!device_poll_thread_.message_loop()) 444 if (!device_poll_thread_.message_loop())
444 return; 445 return;
445 446
446 Dequeue(); 447 Dequeue();
447 EnqueueInput(); 448 EnqueueInput();
(...skipping 10 matching lines...) Expand all
458 459
459 DVLOG(2) << __func__ << ": buffer counts: INPUT[" << input_queue_.size() 460 DVLOG(2) << __func__ << ": buffer counts: INPUT[" << input_queue_.size()
460 << "] => DEVICE[" << free_input_buffers_.size() << "+" 461 << "] => DEVICE[" << free_input_buffers_.size() << "+"
461 << input_buffer_queued_count_ << "/" << input_buffer_map_.size() 462 << input_buffer_queued_count_ << "/" << input_buffer_map_.size()
462 << "->" << output_buffer_map_.size() - output_buffer_queued_count_ 463 << "->" << output_buffer_map_.size() - output_buffer_queued_count_
463 << "+" << output_buffer_queued_count_ << "/" 464 << "+" << output_buffer_queued_count_ << "/"
464 << output_buffer_map_.size() << "]"; 465 << output_buffer_map_.size() << "]";
465 } 466 }
466 467
467 void V4L2ImageProcessor::EnqueueInput() { 468 void V4L2ImageProcessor::EnqueueInput() {
468 DCHECK_EQ(device_thread_.message_loop(), base::MessageLoop::current()); 469 DCHECK(device_thread_.task_runner()->BelongsToCurrentThread());
469 470
470 const int old_inputs_queued = input_buffer_queued_count_; 471 const int old_inputs_queued = input_buffer_queued_count_;
471 while (!input_queue_.empty() && !free_input_buffers_.empty()) { 472 while (!input_queue_.empty() && !free_input_buffers_.empty()) {
472 if (!EnqueueInputRecord()) 473 if (!EnqueueInputRecord())
473 return; 474 return;
474 } 475 }
475 if (old_inputs_queued == 0 && input_buffer_queued_count_ != 0) { 476 if (old_inputs_queued == 0 && input_buffer_queued_count_ != 0) {
476 // We started up a previously empty queue. 477 // We started up a previously empty queue.
477 // Queue state changed; signal interrupt. 478 // Queue state changed; signal interrupt.
478 if (!device_->SetDevicePollInterrupt()) 479 if (!device_->SetDevicePollInterrupt())
479 return; 480 return;
480 // VIDIOC_STREAMON if we haven't yet. 481 // VIDIOC_STREAMON if we haven't yet.
481 if (!input_streamon_) { 482 if (!input_streamon_) {
482 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 483 __u32 type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
483 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type); 484 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type);
484 input_streamon_ = true; 485 input_streamon_ = true;
485 } 486 }
486 } 487 }
487 } 488 }
488 489
489 void V4L2ImageProcessor::EnqueueOutput(int index) { 490 void V4L2ImageProcessor::EnqueueOutput(int index) {
490 DCHECK_EQ(device_thread_.message_loop(), base::MessageLoop::current()); 491 DCHECK(device_thread_.task_runner()->BelongsToCurrentThread());
491 492
492 const int old_outputs_queued = output_buffer_queued_count_; 493 const int old_outputs_queued = output_buffer_queued_count_;
493 if (!EnqueueOutputRecord(index)) 494 if (!EnqueueOutputRecord(index))
494 return; 495 return;
495 496
496 if (old_outputs_queued == 0 && output_buffer_queued_count_ != 0) { 497 if (old_outputs_queued == 0 && output_buffer_queued_count_ != 0) {
497 // We just started up a previously empty queue. 498 // We just started up a previously empty queue.
498 // Queue state changed; signal interrupt. 499 // Queue state changed; signal interrupt.
499 if (!device_->SetDevicePollInterrupt()) 500 if (!device_->SetDevicePollInterrupt())
500 return; 501 return;
501 // Start VIDIOC_STREAMON if we haven't yet. 502 // Start VIDIOC_STREAMON if we haven't yet.
502 if (!output_streamon_) { 503 if (!output_streamon_) {
503 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 504 __u32 type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
504 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type); 505 IOCTL_OR_ERROR_RETURN(VIDIOC_STREAMON, &type);
505 output_streamon_ = true; 506 output_streamon_ = true;
506 } 507 }
507 } 508 }
508 } 509 }
509 510
510 void V4L2ImageProcessor::Dequeue() { 511 void V4L2ImageProcessor::Dequeue() {
511 DCHECK_EQ(device_thread_.message_loop(), base::MessageLoop::current()); 512 DCHECK(device_thread_.task_runner()->BelongsToCurrentThread());
512 513
513 // Dequeue completed input (VIDEO_OUTPUT) buffers, 514 // Dequeue completed input (VIDEO_OUTPUT) buffers,
514 // and recycle to the free list. 515 // and recycle to the free list.
515 struct v4l2_buffer dqbuf; 516 struct v4l2_buffer dqbuf;
516 struct v4l2_plane planes[VIDEO_MAX_PLANES]; 517 struct v4l2_plane planes[VIDEO_MAX_PLANES];
517 while (input_buffer_queued_count_ > 0) { 518 while (input_buffer_queued_count_ > 0) {
518 DCHECK(input_streamon_); 519 DCHECK(input_streamon_);
519 memset(&dqbuf, 0, sizeof(dqbuf)); 520 memset(&dqbuf, 0, sizeof(dqbuf));
520 memset(&planes, 0, sizeof(planes)); 521 memset(&planes, 0, sizeof(planes));
521 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 522 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
637 qbuf.m.planes = qbuf_planes; 638 qbuf.m.planes = qbuf_planes;
638 qbuf.length = output_planes_count_; 639 qbuf.length = output_planes_count_;
639 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf); 640 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QBUF, &qbuf);
640 output_record.at_device = true; 641 output_record.at_device = true;
641 output_buffer_queued_count_++; 642 output_buffer_queued_count_++;
642 return true; 643 return true;
643 } 644 }
644 645
645 bool V4L2ImageProcessor::StartDevicePoll() { 646 bool V4L2ImageProcessor::StartDevicePoll() {
646 DVLOG(3) << __func__ << ": starting device poll"; 647 DVLOG(3) << __func__ << ": starting device poll";
647 DCHECK_EQ(device_thread_.message_loop(), base::MessageLoop::current()); 648 DCHECK(device_thread_.task_runner()->BelongsToCurrentThread());
648 DCHECK(!device_poll_thread_.IsRunning()); 649 DCHECK(!device_poll_thread_.IsRunning());
649 650
650 // Start up the device poll thread and schedule its first DevicePollTask(). 651 // Start up the device poll thread and schedule its first DevicePollTask().
651 if (!device_poll_thread_.Start()) { 652 if (!device_poll_thread_.Start()) {
652 LOG(ERROR) << "StartDevicePoll(): Device thread failed to start"; 653 LOG(ERROR) << "StartDevicePoll(): Device thread failed to start";
653 NotifyError(); 654 NotifyError();
654 return false; 655 return false;
655 } 656 }
656 // Enqueue a poll task with no devices to poll on - will wait only for the 657 // Enqueue a poll task with no devices to poll on - will wait only for the
657 // poll interrupt 658 // poll interrupt
658 device_poll_thread_.message_loop()->PostTask( 659 device_poll_thread_.message_loop()->PostTask(
659 FROM_HERE, base::Bind(&V4L2ImageProcessor::DevicePollTask, 660 FROM_HERE, base::Bind(&V4L2ImageProcessor::DevicePollTask,
660 base::Unretained(this), false)); 661 base::Unretained(this), false));
661 662
662 return true; 663 return true;
663 } 664 }
664 665
665 bool V4L2ImageProcessor::StopDevicePoll() { 666 bool V4L2ImageProcessor::StopDevicePoll() {
666 DVLOG(3) << __func__ << ": stopping device poll"; 667 DVLOG(3) << __func__ << ": stopping device poll";
667 if (device_thread_.IsRunning()) 668 if (device_thread_.IsRunning())
668 DCHECK_EQ(device_thread_.message_loop(), base::MessageLoop::current()); 669 DCHECK(device_thread_.task_runner()->BelongsToCurrentThread());
669 670
670 // Signal the DevicePollTask() to stop, and stop the device poll thread. 671 // Signal the DevicePollTask() to stop, and stop the device poll thread.
671 if (!device_->SetDevicePollInterrupt()) 672 if (!device_->SetDevicePollInterrupt())
672 return false; 673 return false;
673 device_poll_thread_.Stop(); 674 device_poll_thread_.Stop();
674 675
675 // Clear the interrupt now, to be sure. 676 // Clear the interrupt now, to be sure.
676 if (!device_->ClearDevicePollInterrupt()) 677 if (!device_->ClearDevicePollInterrupt())
677 return false; 678 return false;
678 679
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 return true; 712 return true;
712 } 713 }
713 714
714 void V4L2ImageProcessor::FrameReady(const FrameReadyCB& cb, 715 void V4L2ImageProcessor::FrameReady(const FrameReadyCB& cb,
715 int output_buffer_index) { 716 int output_buffer_index) {
716 DCHECK(child_task_runner_->BelongsToCurrentThread()); 717 DCHECK(child_task_runner_->BelongsToCurrentThread());
717 cb.Run(output_buffer_index); 718 cb.Run(output_buffer_index);
718 } 719 }
719 720
720 } // namespace media 721 } // namespace media
OLDNEW
« no previous file with comments | « media/capture/video/file_video_capture_device.cc ('k') | media/gpu/v4l2_slice_video_decode_accelerator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698