Chromium Code Reviews| Index: media/video/capture/linux/video_capture_device_linux.cc |
| diff --git a/media/video/capture/linux/video_capture_device_linux.cc b/media/video/capture/linux/video_capture_device_linux.cc |
| index 6097a1e753c075f90df35a1ec7e54fac1724c832..c42c4c74da2f4c623e6c4a8c023e11a3fdc68b1a 100644 |
| --- a/media/video/capture/linux/video_capture_device_linux.cc |
| +++ b/media/video/capture/linux/video_capture_device_linux.cc |
| @@ -26,6 +26,8 @@ |
| namespace media { |
| +#define GET_V4L2_FOURCC_CHAR(a, index) ((char)( ((a) >> (8 * index)) & 0xff)) |
| + |
| // Max number of video buffers VideoCaptureDeviceLinux can allocate. |
| enum { kMaxVideoBuffers = 2 }; |
| // Timeout in milliseconds v4l2_thread_ blocks waiting for a frame from the hw. |
| @@ -55,7 +57,7 @@ static const char kVidPathTemplate[] = |
| static const char kPidPathTemplate[] = |
| "/sys/class/video4linux/%s/device/../idProduct"; |
| -bool ReadIdFile(const std::string path, std::string* id) { |
| +static bool ReadIdFile(const std::string path, std::string* id) { |
| char id_buf[kVidPidSize]; |
| FILE* file = fopen(path.c_str(), "rb"); |
| if (!file) |
| @@ -68,11 +70,18 @@ bool ReadIdFile(const std::string path, std::string* id) { |
| return true; |
| } |
| +//static |
| +int VideoCaptureDeviceLinux::Ioctl(const base::ScopedFD& device_fd, |
| + int request, |
| + void* arg) { |
| + return HANDLE_EINTR(ioctl(device_fd.get(), request, arg)); |
|
perkj_chrome
2014/12/16 10:34:43
I think this is less readable than calling HANDLE_
mcasas
2014/12/16 18:08:17
Reverted then.
Just FTR I'd say it was cleaner to
|
| +} |
| + |
| // This function translates Video4Linux pixel formats to Chromium pixel formats, |
| // should only support those listed in GetListOfUsableFourCCs. |
| // static |
| -VideoPixelFormat VideoCaptureDeviceLinux::V4l2ColorToVideoCaptureColorFormat( |
| - int32 v4l2_fourcc) { |
| +VideoPixelFormat VideoCaptureDeviceLinux::V4l2FourCcToChromiumPixelFormat( |
| + uint32 v4l2_fourcc) { |
| VideoPixelFormat result = PIXEL_FORMAT_UNKNOWN; |
| switch (v4l2_fourcc) { |
| case V4L2_PIX_FMT_YUV420: |
| @@ -89,24 +98,30 @@ VideoPixelFormat VideoCaptureDeviceLinux::V4l2ColorToVideoCaptureColorFormat( |
| result = PIXEL_FORMAT_MJPEG; |
| break; |
| default: |
| - DVLOG(1) << "Unsupported pixel format " << std::hex << v4l2_fourcc; |
| + DVLOG(1) << "Unsupported pixel format: " |
| + << GET_V4L2_FOURCC_CHAR(v4l2_fourcc, 0) |
| + << GET_V4L2_FOURCC_CHAR(v4l2_fourcc, 1) |
| + << GET_V4L2_FOURCC_CHAR(v4l2_fourcc, 2) |
| + << GET_V4L2_FOURCC_CHAR(v4l2_fourcc, 3); |
| } |
| return result; |
| } |
| // static |
| -void VideoCaptureDeviceLinux::GetListOfUsableFourCCs(bool favour_mjpeg, |
| - std::list<int>* fourccs) { |
| +std::list<int> VideoCaptureDeviceLinux::GetListOfUsableFourCCs( |
| + bool favour_mjpeg) { |
| + std::list<int> fourccs; |
| for (size_t i = 0; i < arraysize(kV4l2RawFmts); ++i) |
| - fourccs->push_back(kV4l2RawFmts[i]); |
| + fourccs.push_back(kV4l2RawFmts[i]); |
| if (favour_mjpeg) |
| - fourccs->push_front(V4L2_PIX_FMT_MJPEG); |
| + fourccs.push_front(V4L2_PIX_FMT_MJPEG); |
| else |
| - fourccs->push_back(V4L2_PIX_FMT_MJPEG); |
| + fourccs.push_back(V4L2_PIX_FMT_MJPEG); |
| // JPEG works as MJPEG on some gspca webcams from field reports. |
| // Put it as the least preferred format. |
| - fourccs->push_back(V4L2_PIX_FMT_JPEG); |
| + fourccs.push_back(V4L2_PIX_FMT_JPEG); |
| + return fourccs; |
| } |
| const std::string VideoCaptureDevice::Name::GetModel() const { |
| @@ -216,7 +231,7 @@ void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, |
| // Test if this is a V4L2 capture device. |
| v4l2_capability cap; |
| - if (!((HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYCAP, &cap)) == 0) && |
| + if (!((Ioctl(device_fd_, VIDIOC_QUERYCAP, &cap) == 0) && |
| (cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) && |
| !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT))) { |
| // This is not a V4L2 video capture device. |
| @@ -227,22 +242,16 @@ void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, |
| // Get supported video formats in preferred order. |
| // For large resolutions, favour mjpeg over raw formats. |
| - std::list<int> v4l2_formats; |
| - GetListOfUsableFourCCs(width > kMjpegWidth || height > kMjpegHeight, |
| - &v4l2_formats); |
| + const std::list<int>& desired_v4l2_formats = |
| + GetListOfUsableFourCCs(width > kMjpegWidth || height > kMjpegHeight); |
| + std::list<int>::const_iterator best = desired_v4l2_formats.end(); |
| v4l2_fmtdesc fmtdesc = {0}; |
| fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| - |
| - // Enumerate image formats. |
| - std::list<int>::iterator best = v4l2_formats.end(); |
| - while (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_ENUM_FMT, &fmtdesc)) == |
| - 0) { |
| - best = std::find(v4l2_formats.begin(), best, fmtdesc.pixelformat); |
| - fmtdesc.index++; |
| + for (; Ioctl(device_fd_, VIDIOC_ENUM_FMT, &fmtdesc) == 0; ++fmtdesc.index) { |
| + best = std::find(desired_v4l2_formats.begin(), best, fmtdesc.pixelformat); |
| } |
| - |
| - if (best == v4l2_formats.end()) { |
| + if (best == desired_v4l2_formats.end()) { |
| SetErrorState("Failed to find a supported camera format."); |
| return; |
| } |
| @@ -256,7 +265,7 @@ void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, |
| video_fmt.fmt.pix.height = height; |
| video_fmt.fmt.pix.pixelformat = *best; |
| - if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_FMT, &video_fmt)) < 0) { |
| + if (Ioctl(device_fd_, VIDIOC_S_FMT, &video_fmt) < 0) { |
| SetErrorState( |
| base::StringPrintf("Failed to set camera format: %s", strerror(errno))); |
| return; |
| @@ -267,7 +276,7 @@ void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, |
| memset(&streamparm, 0, sizeof(v4l2_streamparm)); |
| streamparm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| // The following line checks that the driver knows about framerate get/set. |
| - if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_G_PARM, &streamparm)) >= 0) { |
| + if (Ioctl(device_fd_, VIDIOC_G_PARM, &streamparm) >= 0) { |
| // Now check if the device is able to accept a capture framerate set. |
| if (streamparm.parm.capture.capability & V4L2_CAP_TIMEPERFRAME) { |
| // |frame_rate| is float, approximate by a fraction. |
| @@ -277,8 +286,7 @@ void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, |
| (frame_rate * media::kFrameRatePrecision) : |
| (kTypicalFramerate * media::kFrameRatePrecision); |
| - if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_PARM, &streamparm)) < |
| - 0) { |
| + if (Ioctl(device_fd_, VIDIOC_S_PARM, &streamparm) < 0) { |
| SetErrorState("Failed to set camera framerate"); |
| return; |
| } |
| @@ -308,18 +316,16 @@ void VideoCaptureDeviceLinux::OnAllocateAndStart(int width, |
| video_fmt.fmt.pix.height); |
| capture_format_.frame_rate = frame_rate; |
| capture_format_.pixel_format = |
| - V4l2ColorToVideoCaptureColorFormat(video_fmt.fmt.pix.pixelformat); |
| + V4l2FourCcToChromiumPixelFormat(video_fmt.fmt.pix.pixelformat); |
| - // Start capturing. |
| if (!AllocateVideoBuffers()) { |
| - // Error, We can not recover. |
| - SetErrorState("Allocate buffer failed"); |
| + SetErrorState("Allocate buffers failed"); |
| return; |
| } |
| // Start UVC camera. |
| v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| - if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMON, &type)) == -1) { |
| + if (Ioctl(device_fd_, VIDIOC_STREAMON, &type) == -1) { |
| SetErrorState("VIDIOC_STREAMON failed"); |
| return; |
| } |
| @@ -336,17 +342,16 @@ void VideoCaptureDeviceLinux::OnStopAndDeAllocate() { |
| DCHECK_EQ(v4l2_thread_.message_loop(), base::MessageLoop::current()); |
| v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| - if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMOFF, &type)) < 0) { |
| + if (Ioctl(device_fd_, VIDIOC_STREAMOFF, &type) < 0) { |
| SetErrorState("VIDIOC_STREAMOFF failed"); |
| return; |
| } |
| - // We don't dare to deallocate the buffers if we can't stop |
| - // the capture device. |
| + // We don't dare to deallocate the buffers if we can't stop the capture |
| + // device. |
| DeAllocateVideoBuffers(); |
| - // We need to close and open the device if we want to change the settings |
| - // Otherwise VIDIOC_S_FMT will return error |
| - // Sad but true. |
| + // We need to close and open the device if we want to change the settings. |
| + // Otherwise VIDIOC_S_FMT will return error. Sad but true. |
| device_fd_.reset(); |
| is_capturing_ = false; |
| client_.reset(); |
| @@ -387,7 +392,7 @@ void VideoCaptureDeviceLinux::OnCaptureTask() { |
| buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; |
| buffer.memory = V4L2_MEMORY_MMAP; |
| // Dequeue a buffer. |
| - if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_DQBUF, &buffer)) == 0) { |
| + if (Ioctl(device_fd_, VIDIOC_DQBUF, &buffer) == 0) { |
| client_->OnIncomingCapturedData( |
| static_cast<uint8*>(buffer_pool_[buffer.index].start), |
| buffer.bytesused, |
| @@ -396,7 +401,7 @@ void VideoCaptureDeviceLinux::OnCaptureTask() { |
| base::TimeTicks::Now()); |
| // Enqueue the buffer again. |
| - if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) == -1) { |
| + if (Ioctl(device_fd_, VIDIOC_QBUF, &buffer) == -1) { |
| SetErrorState(base::StringPrintf( |
| "Failed to enqueue capture buffer errno %d", errno)); |
| } |