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

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

Issue 597473002: Change log level to show real errors in release mode (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: address review comments Created 6 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 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 <fcntl.h> 5 #include <fcntl.h>
6 #include <linux/videodev2.h> 6 #include <linux/videodev2.h>
7 #include <poll.h> 7 #include <poll.h>
8 #include <sys/eventfd.h> 8 #include <sys/eventfd.h>
9 #include <sys/ioctl.h> 9 #include <sys/ioctl.h>
10 #include <sys/mman.h> 10 #include <sys/mman.h>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/bind_helpers.h" 13 #include "base/bind_helpers.h"
14 #include "base/callback.h" 14 #include "base/callback.h"
15 #include "base/message_loop/message_loop_proxy.h" 15 #include "base/message_loop/message_loop_proxy.h"
16 #include "base/numerics/safe_conversions.h" 16 #include "base/numerics/safe_conversions.h"
17 #include "content/common/gpu/media/v4l2_image_processor.h" 17 #include "content/common/gpu/media/v4l2_image_processor.h"
18 #include "media/base/bind_to_current_loop.h" 18 #include "media/base/bind_to_current_loop.h"
19 19
20 #define NOTIFY_ERROR() \ 20 #define NOTIFY_ERROR() \
21 do { \ 21 do { \
22 DLOG(ERROR) << "calling NotifyError()"; \ 22 LOG(ERROR) << "calling NotifyError()"; \
23 NotifyError(); \ 23 NotifyError(); \
24 } while (0) 24 } while (0)
25 25
26 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value) \ 26 #define IOCTL_OR_ERROR_RETURN_VALUE(type, arg, value) \
27 do { \ 27 do { \
28 if (device_->Ioctl(type, arg) != 0) { \ 28 if (device_->Ioctl(type, arg) != 0) { \
29 DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \ 29 PLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
30 return value; \ 30 return value; \
31 } \ 31 } \
32 } while (0) 32 } while (0)
33 33
34 #define IOCTL_OR_ERROR_RETURN(type, arg) \ 34 #define IOCTL_OR_ERROR_RETURN(type, arg) \
35 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, ((void)0)) 35 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, ((void)0))
36 36
37 #define IOCTL_OR_ERROR_RETURN_FALSE(type, arg) \ 37 #define IOCTL_OR_ERROR_RETURN_FALSE(type, arg) \
38 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, false) 38 IOCTL_OR_ERROR_RETURN_VALUE(type, arg, false)
39 39
40 #define IOCTL_OR_LOG_ERROR(type, arg) \ 40 #define IOCTL_OR_LOG_ERROR(type, arg) \
41 do { \ 41 do { \
42 if (device_->Ioctl(type, arg) != 0) \ 42 if (device_->Ioctl(type, arg) != 0) \
43 DPLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \ 43 PLOG(ERROR) << __func__ << "(): ioctl() failed: " << #type; \
44 } while (0) 44 } while (0)
45 45
46 namespace content { 46 namespace content {
47 47
48 V4L2ImageProcessor::InputRecord::InputRecord() : at_device(false) { 48 V4L2ImageProcessor::InputRecord::InputRecord() : at_device(false) {
49 } 49 }
50 50
51 V4L2ImageProcessor::OutputRecord::OutputRecord() 51 V4L2ImageProcessor::OutputRecord::OutputRecord()
52 : at_device(false), at_client(false) { 52 : at_device(false), at_client(false) {
53 } 53 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
103 DCHECK_EQ(input_format, media::VideoFrame::I420); 103 DCHECK_EQ(input_format, media::VideoFrame::I420);
104 DCHECK_EQ(output_format, media::VideoFrame::NV12); 104 DCHECK_EQ(output_format, media::VideoFrame::NV12);
105 105
106 input_format_ = input_format; 106 input_format_ = input_format;
107 output_format_ = output_format; 107 output_format_ = output_format;
108 input_format_fourcc_ = V4L2Device::VideoFrameFormatToV4L2PixFmt(input_format); 108 input_format_fourcc_ = V4L2Device::VideoFrameFormatToV4L2PixFmt(input_format);
109 output_format_fourcc_ = 109 output_format_fourcc_ =
110 V4L2Device::VideoFrameFormatToV4L2PixFmt(output_format); 110 V4L2Device::VideoFrameFormatToV4L2PixFmt(output_format);
111 111
112 if (!input_format_fourcc_ || !output_format_fourcc_) { 112 if (!input_format_fourcc_ || !output_format_fourcc_) {
113 DLOG(ERROR) << "Unrecognized format(s)"; 113 LOG(ERROR) << "Unrecognized format(s)";
114 return false; 114 return false;
115 } 115 }
116 116
117 input_visible_size_ = input_visible_size; 117 input_visible_size_ = input_visible_size;
118 output_visible_size_ = output_visible_size; 118 output_visible_size_ = output_visible_size;
119 output_allocated_size_ = output_allocated_size; 119 output_allocated_size_ = output_allocated_size;
120 120
121 input_planes_count_ = media::VideoFrame::NumPlanes(input_format); 121 input_planes_count_ = media::VideoFrame::NumPlanes(input_format);
122 DCHECK_LE(input_planes_count_, static_cast<size_t>(VIDEO_MAX_PLANES)); 122 DCHECK_LE(input_planes_count_, static_cast<size_t>(VIDEO_MAX_PLANES));
123 output_planes_count_ = media::VideoFrame::NumPlanes(output_format); 123 output_planes_count_ = media::VideoFrame::NumPlanes(output_format);
124 DCHECK_LE(output_planes_count_, static_cast<size_t>(VIDEO_MAX_PLANES)); 124 DCHECK_LE(output_planes_count_, static_cast<size_t>(VIDEO_MAX_PLANES));
125 125
126 // Capabilities check. 126 // Capabilities check.
127 struct v4l2_capability caps; 127 struct v4l2_capability caps;
128 memset(&caps, 0, sizeof(caps)); 128 memset(&caps, 0, sizeof(caps));
129 const __u32 kCapsRequired = V4L2_CAP_VIDEO_CAPTURE_MPLANE | 129 const __u32 kCapsRequired = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
130 V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING; 130 V4L2_CAP_VIDEO_OUTPUT_MPLANE | V4L2_CAP_STREAMING;
131 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps); 131 IOCTL_OR_ERROR_RETURN_FALSE(VIDIOC_QUERYCAP, &caps);
132 if ((caps.capabilities & kCapsRequired) != kCapsRequired) { 132 if ((caps.capabilities & kCapsRequired) != kCapsRequired) {
133 DLOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: " 133 LOG(ERROR) << "Initialize(): ioctl() failed: VIDIOC_QUERYCAP: "
134 "caps check failed: 0x" << std::hex << caps.capabilities; 134 "caps check failed: 0x" << std::hex << caps.capabilities;
135 return false; 135 return false;
136 } 136 }
137 137
138 if (!CreateInputBuffers() || !CreateOutputBuffers()) 138 if (!CreateInputBuffers() || !CreateOutputBuffers())
139 return false; 139 return false;
140 140
141 if (!device_thread_.Start()) { 141 if (!device_thread_.Start()) {
142 DLOG(ERROR) << "Initialize(): encoder thread failed to start"; 142 LOG(ERROR) << "Initialize(): encoder thread failed to start";
143 return false; 143 return false;
144 } 144 }
145 145
146 // StartDevicePoll will NOTIFY_ERROR on failure, so IgnoreResult is fine here. 146 // StartDevicePoll will NOTIFY_ERROR on failure, so IgnoreResult is fine here.
147 device_thread_.message_loop()->PostTask( 147 device_thread_.message_loop()->PostTask(
148 FROM_HERE, 148 FROM_HERE,
149 base::Bind(base::IgnoreResult(&V4L2ImageProcessor::StartDevicePoll), 149 base::Bind(base::IgnoreResult(&V4L2ImageProcessor::StartDevicePoll),
150 base::Unretained(this))); 150 base::Unretained(this)));
151 151
152 DVLOG(1) << "V4L2ImageProcessor initialized for " 152 DVLOG(1) << "V4L2ImageProcessor initialized for "
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 memset(&planes, 0, sizeof(planes)); 496 memset(&planes, 0, sizeof(planes));
497 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; 497 dqbuf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
498 dqbuf.memory = V4L2_MEMORY_USERPTR; 498 dqbuf.memory = V4L2_MEMORY_USERPTR;
499 dqbuf.m.planes = planes; 499 dqbuf.m.planes = planes;
500 dqbuf.length = input_planes_count_; 500 dqbuf.length = input_planes_count_;
501 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { 501 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
502 if (errno == EAGAIN) { 502 if (errno == EAGAIN) {
503 // EAGAIN if we're just out of buffers to dequeue. 503 // EAGAIN if we're just out of buffers to dequeue.
504 break; 504 break;
505 } 505 }
506 DPLOG(ERROR) << "ioctl() failed: VIDIOC_DQBUF"; 506 PLOG(ERROR) << "ioctl() failed: VIDIOC_DQBUF";
507 NOTIFY_ERROR(); 507 NOTIFY_ERROR();
508 return; 508 return;
509 } 509 }
510 InputRecord& input_record = input_buffer_map_[dqbuf.index]; 510 InputRecord& input_record = input_buffer_map_[dqbuf.index];
511 DCHECK(input_record.at_device); 511 DCHECK(input_record.at_device);
512 input_record.at_device = false; 512 input_record.at_device = false;
513 input_record.frame = NULL; 513 input_record.frame = NULL;
514 free_input_buffers_.push_back(dqbuf.index); 514 free_input_buffers_.push_back(dqbuf.index);
515 input_buffer_queued_count_--; 515 input_buffer_queued_count_--;
516 } 516 }
517 517
518 // Dequeue completed output (VIDEO_CAPTURE) buffers, recycle to the free list. 518 // Dequeue completed output (VIDEO_CAPTURE) buffers, recycle to the free list.
519 // Return the finished buffer to the client via the job ready callback. 519 // Return the finished buffer to the client via the job ready callback.
520 while (output_buffer_queued_count_ > 0) { 520 while (output_buffer_queued_count_ > 0) {
521 DCHECK(output_streamon_); 521 DCHECK(output_streamon_);
522 memset(&dqbuf, 0, sizeof(dqbuf)); 522 memset(&dqbuf, 0, sizeof(dqbuf));
523 memset(&planes, 0, sizeof(planes)); 523 memset(&planes, 0, sizeof(planes));
524 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 524 dqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
525 dqbuf.memory = V4L2_MEMORY_DMABUF; 525 dqbuf.memory = V4L2_MEMORY_DMABUF;
526 dqbuf.m.planes = planes; 526 dqbuf.m.planes = planes;
527 dqbuf.length = output_planes_count_; 527 dqbuf.length = output_planes_count_;
528 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) { 528 if (device_->Ioctl(VIDIOC_DQBUF, &dqbuf) != 0) {
529 if (errno == EAGAIN) { 529 if (errno == EAGAIN) {
530 // EAGAIN if we're just out of buffers to dequeue. 530 // EAGAIN if we're just out of buffers to dequeue.
531 break; 531 break;
532 } 532 }
533 DPLOG(ERROR) << "ioctl() failed: VIDIOC_DQBUF"; 533 PLOG(ERROR) << "ioctl() failed: VIDIOC_DQBUF";
534 NOTIFY_ERROR(); 534 NOTIFY_ERROR();
535 return; 535 return;
536 } 536 }
537 OutputRecord& output_record = output_buffer_map_[dqbuf.index]; 537 OutputRecord& output_record = output_buffer_map_[dqbuf.index];
538 DCHECK(output_record.at_device); 538 DCHECK(output_record.at_device);
539 output_record.at_device = false; 539 output_record.at_device = false;
540 output_record.at_client = true; 540 output_record.at_client = true;
541 output_buffer_queued_count_--; 541 output_buffer_queued_count_--;
542 542
543 // Jobs are always processed in FIFO order. 543 // Jobs are always processed in FIFO order.
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
641 return true; 641 return true;
642 } 642 }
643 643
644 bool V4L2ImageProcessor::StartDevicePoll() { 644 bool V4L2ImageProcessor::StartDevicePoll() {
645 DVLOG(3) << __func__ << ": starting device poll"; 645 DVLOG(3) << __func__ << ": starting device poll";
646 DCHECK_EQ(device_thread_.message_loop(), base::MessageLoop::current()); 646 DCHECK_EQ(device_thread_.message_loop(), base::MessageLoop::current());
647 DCHECK(!device_poll_thread_.IsRunning()); 647 DCHECK(!device_poll_thread_.IsRunning());
648 648
649 // Start up the device poll thread and schedule its first DevicePollTask(). 649 // Start up the device poll thread and schedule its first DevicePollTask().
650 if (!device_poll_thread_.Start()) { 650 if (!device_poll_thread_.Start()) {
651 DLOG(ERROR) << "StartDevicePoll(): Device thread failed to start"; 651 LOG(ERROR) << "StartDevicePoll(): Device thread failed to start";
652 NOTIFY_ERROR(); 652 NOTIFY_ERROR();
653 return false; 653 return false;
654 } 654 }
655 // Enqueue a poll task with no devices to poll on - will wait only for the 655 // Enqueue a poll task with no devices to poll on - will wait only for the
656 // poll interrupt 656 // poll interrupt
657 device_poll_thread_.message_loop()->PostTask( 657 device_poll_thread_.message_loop()->PostTask(
658 FROM_HERE, 658 FROM_HERE,
659 base::Bind( 659 base::Bind(
660 &V4L2ImageProcessor::DevicePollTask, base::Unretained(this), false)); 660 &V4L2ImageProcessor::DevicePollTask, base::Unretained(this), false));
661 661
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
710 output_record.at_device = false; 710 output_record.at_device = false;
711 if (!output_record.at_client) 711 if (!output_record.at_client)
712 free_output_buffers_.push_back(i); 712 free_output_buffers_.push_back(i);
713 } 713 }
714 output_buffer_queued_count_ = 0; 714 output_buffer_queued_count_ = 0;
715 715
716 return true; 716 return true;
717 } 717 }
718 718
719 } // namespace content 719 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/tegra_v4l2_video_device.cc ('k') | content/common/gpu/media/v4l2_video_decode_accelerator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698