Fix errors in camera_V4L2
1. REQBUFS ioctl should be after munmap. Otherwise, device is busy.
2. Frame rate should be float. Some devices may support (2/15) frame rate.
BUG=chromium:718278
TEST=test on nyan_big and pass the test.
Change-Id: I7dc1cb5f16a8c772ea2e38a47066175a97218ac8
Reviewed-on: https://chromium-review.googlesource.com/495947
Commit-Ready: Heng-ruey Hsu <henryhsu@google.com>
Tested-by: Heng-ruey Hsu <henryhsu@google.com>
Reviewed-by: Hung-yu Wu <hywu@chromium.org>
diff --git a/client/site_tests/camera_V4L2/src/camera_characteristics.cc b/client/site_tests/camera_V4L2/src/camera_characteristics.cc
index fa8eec0..cc315d8 100644
--- a/client/site_tests/camera_V4L2/src/camera_characteristics.cc
+++ b/client/site_tests/camera_V4L2/src/camera_characteristics.cc
@@ -79,7 +79,7 @@
const base::FilePath path(kCameraCharacteristicsConfigFile);
FILE* file = base::OpenFile(path, "r");
if (!file) {
- LOG(ERROR) << __func__ << ": Can't open file "
+ LOG(INFO) << __func__ << ": Can't open file "
<< kCameraCharacteristicsConfigFile
<< ". Use default characteristics instead";
DeviceInfos device_infos;
diff --git a/client/site_tests/camera_V4L2/src/common_types.h b/client/site_tests/camera_V4L2/src/common_types.h
index f16d143..6dcd505 100644
--- a/client/site_tests/camera_V4L2/src/common_types.h
+++ b/client/site_tests/camera_V4L2/src/common_types.h
@@ -52,7 +52,7 @@
// pixelformat. This is not sorted. For example, suppose width, height, and
// fourcc are 640x480 YUYV. If frameRates are 15.0 and 30.0, the camera
// supports outputting 640X480 YUYV in 15fps or 30fps.
- std::vector<uint32_t> frame_rates;
+ std::vector<float> frame_rates;
};
typedef std::vector<SupportedFormat> SupportedFormats;
diff --git a/client/site_tests/camera_V4L2/src/media_v4l2_device.cc b/client/site_tests/camera_V4L2/src/media_v4l2_device.cc
index 447585b..08bf5e2 100644
--- a/client/site_tests/camera_V4L2/src/media_v4l2_device.cc
+++ b/client/site_tests/camera_V4L2/src/media_v4l2_device.cc
@@ -83,7 +83,7 @@
uint32_t width,
uint32_t height,
uint32_t pixfmt,
- uint32_t fps) {
+ float fps) {
io_ = io;
// Crop/Format setting could live across session.
// We should always initialized them when supported.
@@ -140,10 +140,10 @@
fps = GetFrameRate();
} else {
// TODO(jiesun): probably we should derive this from VIDIOC_G_STD
- fps = 30;
+ fps = 30.0;
}
- printf("actual format for capture %dx%d %c%c%c%c picture at %d fps\n",
+ printf("actual format for capture %dx%d %c%c%c%c picture at %.2f fps\n",
fmt.fmt.pix.width, fmt.fmt.pix.height,
(pixfmt >> 0) & 0xff, (pixfmt >> 8) & 0xff,
(pixfmt >> 16) & 0xff, (pixfmt >> 24 ) & 0xff, fps);
@@ -169,24 +169,32 @@
}
bool V4L2Device::UninitDevice() {
+ v4l2_requestbuffers req;
+ memset(&req, 0, sizeof(req));
+ req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
switch (io_) {
case IO_METHOD_MMAP:
- v4l2_requestbuffers req;
- memset(&req, 0, sizeof(req));
- req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- req.memory = V4L2_MEMORY_MMAP;
- if (-1 == DoIoctl(VIDIOC_REQBUFS, &req)) {
- printf("<<< Error: VIDIOC_REQBUFS failed on %s.>>>\n", dev_name_);
- return false;
- }
-
for (uint32_t i = 0; i < num_buffers_; ++i)
if (-1 == munmap(v4l2_buffers_[i].start, v4l2_buffers_[i].length)) {
printf("<<< Error: munmap() on %s failed.>>>\n", dev_name_);
return false;
}
+
+ req.memory = V4L2_MEMORY_MMAP;
+ if (-1 == DoIoctl(VIDIOC_REQBUFS, &req)) {
+ printf("<<< Error: VIDIOC_REQBUFS for MMAP failed on %s: %s.>>>\n",
+ dev_name_, strerror(errno));
+ return false;
+ }
break;
case IO_METHOD_USERPTR:
+ req.memory = V4L2_MEMORY_USERPTR;
+ if (-1 == DoIoctl(VIDIOC_REQBUFS, &req)) {
+ printf("<<< Error: VIDIOC_REQBUFS for USERPTR failed on %s.: %s>>>\n",
+ dev_name_, strerror(errno));
+ return false;
+ }
+
for (uint32_t i = 0; i < num_buffers_; ++i)
free(v4l2_buffers_[i].start);
break;
@@ -424,7 +432,8 @@
if (EINVAL == errno)
printf("<<< Error: mmap() io is not supported on %s.>>>\n", dev_name_);
else
- printf("<<< Error: VIDIOC_REQBUFS failed on %s.>>>\n", dev_name_);
+ printf("<<< Error: VIDIOC_REQBUFS for MMAP(%d) failed on %s: %s.>>>\n",
+ min_buffers_, dev_name_, strerror(errno));
return false;
}
@@ -476,7 +485,8 @@
if (EINVAL == errno)
printf("<<< Error: user pointer is not supported on %s.>>>\n", dev_name_);
else
- printf("<<< Error: VIDIOC_REQBUFS failed on %s.>>>\n", dev_name_);
+ printf("<<< Error: VIDIOC_REQBUFS for USERPTR(%d) failed on %s: %s.>>>\n",
+ min_buffers_, dev_name_, strerror(errno));
return false;
}
@@ -801,7 +811,7 @@
bool V4L2Device::GetFrameInterval(
uint32_t index, uint32_t pixfmt, uint32_t width, uint32_t height,
- uint32_t* frame_rate) {
+ float* frame_rate) {
v4l2_frmivalenum frm_interval;
memset(&frm_interval, 0, sizeof(frm_interval));
frm_interval.pixel_format = pixfmt;
@@ -819,13 +829,7 @@
}
if (frame_rate) {
- if (frm_interval.discrete.denominator %
- frm_interval.discrete.numerator) {
- printf("<<< Error: frame rate is a floating point %d/%d.>>>\n",
- frm_interval.discrete.denominator, frm_interval.discrete.numerator);
- return false;
- }
- *frame_rate = frm_interval.discrete.denominator /
+ *frame_rate = static_cast<float>(frm_interval.discrete.denominator) /
frm_interval.discrete.numerator;
}
return true;
@@ -931,21 +935,23 @@
return true;
}
-bool V4L2Device::SetFrameRate(uint32_t fps) {
+bool V4L2Device::SetFrameRate(float fps) {
v4l2_streamparm param;
if (!GetParam(¶m))
return false;
- param.parm.capture.timeperframe.numerator = 1;
- param.parm.capture.timeperframe.denominator = fps;
+
+ const int kFrameRatePrecision = 10000;
+ param.parm.capture.timeperframe.numerator = kFrameRatePrecision;
+ param.parm.capture.timeperframe.denominator = fps * kFrameRatePrecision;
return SetParam(¶m);
}
-uint32_t V4L2Device::GetFrameRate() {
+float V4L2Device::GetFrameRate() {
v4l2_streamparm param;
if (!GetParam(¶m))
return -1;
- return (param.parm.capture.timeperframe.denominator /
- param.parm.capture.timeperframe.numerator);
+ return static_cast<float>(param.parm.capture.timeperframe.denominator) /
+ param.parm.capture.timeperframe.numerator;
}
uint64_t V4L2Device::Now() {
diff --git a/client/site_tests/camera_V4L2/src/media_v4l2_device.h b/client/site_tests/camera_V4L2/src/media_v4l2_device.h
index a890302..ce4eb19 100644
--- a/client/site_tests/camera_V4L2/src/media_v4l2_device.h
+++ b/client/site_tests/camera_V4L2/src/media_v4l2_device.h
@@ -40,7 +40,7 @@
uint32_t width,
uint32_t height,
uint32_t pixfmt,
- uint32_t fps);
+ float fps);
virtual bool UninitDevice();
virtual bool StartCapture();
virtual bool StopCapture();
@@ -65,14 +65,14 @@
bool SetCrop(v4l2_crop* crop);
bool GetParam(v4l2_streamparm* param);
bool SetParam(v4l2_streamparm* param);
- bool SetFrameRate(uint32_t fps);
+ bool SetFrameRate(float fps);
bool GetPixelFormat(uint32_t index, uint32_t* pixfmt);
bool GetFrameSize(
uint32_t index, uint32_t pixfmt, uint32_t *width, uint32_t *height);
bool GetFrameInterval(
uint32_t index, uint32_t pixfmt, uint32_t width, uint32_t height,
- uint32_t* frame_rate);
- uint32_t GetFrameRate();
+ float* frame_rate);
+ float GetFrameRate();
bool Stop();
// Getter.
diff --git a/client/site_tests/camera_V4L2/src/media_v4l2_test.cc b/client/site_tests/camera_V4L2/src/media_v4l2_test.cc
index ad11f8e..8288b01 100644
--- a/client/site_tests/camera_V4L2/src/media_v4l2_test.cc
+++ b/client/site_tests/camera_V4L2/src/media_v4l2_test.cc
@@ -32,7 +32,7 @@
int RunTest(V4L2Device* device, V4L2Device::IOMethod io,
uint32_t buffers, uint32_t capture_time_in_sec, uint32_t width,
- uint32_t height, uint32_t pixfmt, uint32_t fps) {
+ uint32_t height, uint32_t pixfmt, float fps) {
int32_t retcode = 0;
if (!device->InitDevice(io, width, height, pixfmt, fps))
retcode = 1;
@@ -84,7 +84,7 @@
};
format.frame_rates.clear();
- uint32_t frame_rate;
+ float frame_rate;
for (uint32_t k = 0; k < num_frame_rate; ++k) {
if (!device->GetFrameInterval(k, format.fourcc, format.width,
format.height, &frame_rate)) {
@@ -92,7 +92,7 @@
return false;
};
// All supported resolution should have at least 1 fps.
- if (frame_rate == 0) {
+ if (frame_rate < 1.0) {
printf("[Error] Frame rate should be at least 1.\n");
return false;
}
@@ -137,7 +137,7 @@
uint32_t width = 640;
uint32_t height = 480;
uint32_t pixfmt = V4L2_PIX_FMT_YUYV;
- uint32_t fps = 30;
+ float fps = 30.0;
uint32_t time_to_capture = 3; // The unit is second.
bool check_1280x960 = false;
@@ -188,13 +188,13 @@
SupportedFormat max_resolution = GetMaximumResolution(supported_formats);
SupportedFormats required_resolutions;
- required_resolutions.push_back(SupportedFormat(320, 240, 0, 30));
- required_resolutions.push_back(SupportedFormat(640, 480, 0, 30));
- required_resolutions.push_back(SupportedFormat(1280, 720, 0, 30));
- required_resolutions.push_back(SupportedFormat(1920, 1080, 0, 30));
- required_resolutions.push_back(SupportedFormat(1600, 1200, 0, 30));
+ required_resolutions.push_back(SupportedFormat(320, 240, 0, 30.0));
+ required_resolutions.push_back(SupportedFormat(640, 480, 0, 30.0));
+ required_resolutions.push_back(SupportedFormat(1280, 720, 0, 30.0));
+ required_resolutions.push_back(SupportedFormat(1920, 1080, 0, 30.0));
+ required_resolutions.push_back(SupportedFormat(1600, 1200, 0, 30.0));
if (check_1280x960) {
- required_resolutions.push_back(SupportedFormat(1280, 960, 0, 30));
+ required_resolutions.push_back(SupportedFormat(1280, 960, 0, 30.0));
}
for (const auto& test_resolution : required_resolutions) {
@@ -222,9 +222,9 @@
if (RunTest(device.get(), io, buffers, time_to_capture,
test_format->width, test_format->height, test_format->fourcc,
frame_rate)) {
- printf("[Error] Could not capture frames for %dx%d (%08X) in %s\n",
- test_format->width, test_format->height, test_format->fourcc,
- dev_name.c_str());
+ printf("[Error] Could not capture frames for %dx%d (%08X) %.2f fps in "
+ "%s\n", test_format->width, test_format->height,
+ test_format->fourcc, frame_rate, dev_name.c_str());
return false;
}
@@ -234,9 +234,9 @@
test_format->height != fmt.fmt.pix.height ||
test_format->fourcc != fmt.fmt.pix.pixelformat ||
frame_rate != device->GetFrameRate()) {
- printf("[Error] Capture test %dx%d (%08X) failed in %s\n",
+ printf("[Error] Capture test %dx%d (%08X) %.2f fps failed in %s\n",
test_format->width, test_format->height, test_format->fourcc,
- dev_name.c_str());
+ frame_rate, dev_name.c_str());
}
}
if (!frame_rate_tested) {