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

Unified Diff: media/capture/video/linux/v4l2_capture_delegate.cc

Issue 1685713003: Remove V4L2CaptureDelegate{Single,Multi}Plane, VCD::Client::OnIncomingCapturedYuvData() (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: perkj@ comments and reverted change to WeakPtr Created 4 years, 10 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 side-by-side diff with in-line comments
Download patch
Index: media/capture/video/linux/v4l2_capture_delegate.cc
diff --git a/media/capture/video/linux/v4l2_capture_delegate.cc b/media/capture/video/linux/v4l2_capture_delegate.cc
index 612672b48aa132201a7a7789b087078e4689661e..c49ecb7b5d04fae04df001926074cede4b03ba49 100644
--- a/media/capture/video/linux/v4l2_capture_delegate.cc
+++ b/media/capture/video/linux/v4l2_capture_delegate.cc
@@ -16,8 +16,6 @@
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "media/base/bind_to_current_loop.h"
-#include "media/capture/video/linux/v4l2_capture_delegate_multi_plane.h"
-#include "media/capture/video/linux/v4l2_capture_delegate_single_plane.h"
#include "media/capture/video/linux/video_capture_device_linux.h"
namespace media {
@@ -48,44 +46,76 @@ static struct {
{V4L2_PIX_FMT_YUYV, PIXEL_FORMAT_YUY2, 1},
{V4L2_PIX_FMT_UYVY, PIXEL_FORMAT_UYVY, 1},
{V4L2_PIX_FMT_RGB24, PIXEL_FORMAT_RGB24, 1},
-#if !defined(OS_OPENBSD)
- // TODO(mcasas): add V4L2_PIX_FMT_YVU420M when available in bots.
- {V4L2_PIX_FMT_YUV420M, PIXEL_FORMAT_I420, 3},
-#endif
// MJPEG is usually sitting fairly low since we don't want to have to
- // decode.
- // However, is needed for large resolutions due to USB bandwidth
- // limitations,
- // so GetListOfUsableFourCcs() can duplicate it on top, see that method.
+ // decode. However, it is needed for large resolutions due to USB bandwidth
+ // limitations, so GetListOfUsableFourCcs() can duplicate it on top, see
+ // that method.
{V4L2_PIX_FMT_MJPEG, PIXEL_FORMAT_MJPEG, 1},
// JPEG works as MJPEG on some gspca webcams from field reports, see
// https://code.google.com/p/webrtc/issues/detail?id=529, put it as the
- // least
- // preferred format.
+ // least preferred format.
{V4L2_PIX_FMT_JPEG, PIXEL_FORMAT_MJPEG, 1},
};
-// static
-scoped_refptr<V4L2CaptureDelegate>
-V4L2CaptureDelegate::CreateV4L2CaptureDelegate(
- const VideoCaptureDevice::Name& device_name,
- const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner,
- int power_line_frequency) {
- switch (device_name.capture_api_type()) {
- case VideoCaptureDevice::Name::V4L2_SINGLE_PLANE:
- return make_scoped_refptr(new V4L2CaptureDelegateSinglePlane(
- device_name, v4l2_task_runner, power_line_frequency));
- case VideoCaptureDevice::Name::V4L2_MULTI_PLANE:
-#if !defined(OS_OPENBSD)
- return make_scoped_refptr(new V4L2CaptureDelegateMultiPlane(
- device_name, v4l2_task_runner, power_line_frequency));
- default:
-#endif
- NOTIMPLEMENTED() << "Unknown V4L2 capture API type";
- return scoped_refptr<V4L2CaptureDelegate>();
- }
+// Fill in |format| with the given parameters.
+static void FillV4L2Format(v4l2_format* format,
+ uint32_t width,
+ uint32_t height,
+ uint32_t pixelformat_fourcc) {
+ memset(format, 0, sizeof(*format));
+ format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ format->fmt.pix.width = width;
+ format->fmt.pix.height = height;
+ format->fmt.pix.pixelformat = pixelformat_fourcc;
+}
+
+// Fills all parts of |buffer|.
+static void FillV4L2Buffer(v4l2_buffer* buffer, int index) {
+ memset(buffer, 0, sizeof(*buffer));
+ buffer->memory = V4L2_MEMORY_MMAP;
+ buffer->index = index;
+ buffer->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+}
+
+static void FillV4L2RequestBuffer(v4l2_requestbuffers* request_buffer,
+ int count) {
+ memset(request_buffer, 0, sizeof(*request_buffer));
+ request_buffer->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ request_buffer->memory = V4L2_MEMORY_MMAP;
+ request_buffer->count = count;
+}
+
+// Returns the input |fourcc| as a std::string four char representation.
+static std::string FourccToString(uint32_t fourcc) {
+ return base::StringPrintf("%c%c%c%c", fourcc & 0xFF, (fourcc >> 8) & 0xFF,
+ (fourcc >> 16) & 0xFF, (fourcc >> 24) & 0xFF);
}
+// Class keeping track of a SPLANE V4L2 buffer, mmap()ed on construction and
+// munmap()ed on destruction.
+class V4L2CaptureDelegate::BufferTracker
+ : public base::RefCounted<BufferTracker> {
+ public:
+ BufferTracker();
+ // Abstract method to mmap() given |fd| according to |buffer|.
+ bool Init(int fd, const v4l2_buffer& buffer);
+
+ const uint8_t* start() const { return start_; }
+ size_t payload_size() const { return payload_size_; }
+ void set_payload_size(size_t payload_size) {
+ DCHECK_LE(payload_size, length_);
+ payload_size_ = payload_size;
+ }
+
+ private:
+ friend class base::RefCounted<BufferTracker>;
+ virtual ~BufferTracker();
+
+ uint8_t* start_;
+ size_t length_;
+ size_t payload_size_;
+};
+
// static
size_t V4L2CaptureDelegate::GetNumPlanesForFourCc(uint32_t fourcc) {
for (const auto& fourcc_and_pixel_format : kSupportedFormatsAndPlanarity) {
@@ -124,51 +154,16 @@ std::list<uint32_t> V4L2CaptureDelegate::GetListOfUsableFourCcs(
return supported_formats;
}
-// static
-std::string V4L2CaptureDelegate::FourccToString(uint32_t fourcc) {
- return base::StringPrintf("%c%c%c%c", fourcc & 0xFF, (fourcc >> 8) & 0xFF,
- (fourcc >> 16) & 0xFF, (fourcc >> 24) & 0xFF);
-}
-
-V4L2CaptureDelegate::BufferTracker::BufferTracker() {
-}
-
-V4L2CaptureDelegate::BufferTracker::~BufferTracker() {
- for (const auto& plane : planes_) {
- if (plane.start == nullptr)
- continue;
- const int result = munmap(plane.start, plane.length);
- PLOG_IF(ERROR, result < 0) << "Error munmap()ing V4L2 buffer";
- }
-}
-
-void V4L2CaptureDelegate::BufferTracker::AddMmapedPlane(uint8_t* const start,
- size_t length) {
- Plane plane;
- plane.start = start;
- plane.length = length;
- plane.payload_size = 0;
- planes_.push_back(plane);
-}
-
V4L2CaptureDelegate::V4L2CaptureDelegate(
const VideoCaptureDevice::Name& device_name,
const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner,
int power_line_frequency)
- : capture_type_((device_name.capture_api_type() ==
- VideoCaptureDevice::Name::V4L2_SINGLE_PLANE)
- ? V4L2_BUF_TYPE_VIDEO_CAPTURE
- : V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE),
- v4l2_task_runner_(v4l2_task_runner),
+ : v4l2_task_runner_(v4l2_task_runner),
device_name_(device_name),
power_line_frequency_(power_line_frequency),
is_capturing_(false),
timeout_count_(0),
- rotation_(0) {
-}
-
-V4L2CaptureDelegate::~V4L2CaptureDelegate() {
-}
+ rotation_(0) {}
void V4L2CaptureDelegate::AllocateAndStart(
int width,
@@ -188,23 +183,21 @@ void V4L2CaptureDelegate::AllocateAndStart(
v4l2_capability cap = {};
if (!((HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QUERYCAP, &cap)) == 0) &&
- ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE ||
- cap.capabilities & V4L2_CAP_VIDEO_CAPTURE_MPLANE) &&
- !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT) &&
- !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT_MPLANE)))) {
+ ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) &&
+ !(cap.capabilities & V4L2_CAP_VIDEO_OUTPUT)))) {
device_fd_.reset();
SetErrorState(FROM_HERE, "This is not a V4L2 video capture device");
return;
}
- // Get supported video formats in preferred order.
- // For large resolutions, favour mjpeg over raw formats.
+ // Get supported video formats in preferred order. For large resolutions,
+ // favour mjpeg over raw formats.
const std::list<uint32_t>& desired_v4l2_formats =
GetListOfUsableFourCcs(width > kMjpegWidth || height > kMjpegHeight);
std::list<uint32_t>::const_iterator best = desired_v4l2_formats.end();
v4l2_fmtdesc fmtdesc = {};
- fmtdesc.type = capture_type_;
+ fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
for (; HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_ENUM_FMT, &fmtdesc)) == 0;
++fmtdesc.index) {
best = std::find(desired_v4l2_formats.begin(), best, fmtdesc.pixelformat);
@@ -215,12 +208,7 @@ void V4L2CaptureDelegate::AllocateAndStart(
}
DVLOG(1) << "Chosen pixel format is " << FourccToString(*best);
-
- video_fmt_.type = capture_type_;
- if (!FillV4L2Format(&video_fmt_, width, height, *best)) {
- SetErrorState(FROM_HERE, "Failed filling in V4L2 Format");
- return;
- }
+ FillV4L2Format(&video_fmt_, width, height, *best);
if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_S_FMT, &video_fmt_)) < 0) {
SetErrorState(FROM_HERE, "Failed to set video capture format");
@@ -235,7 +223,7 @@ void V4L2CaptureDelegate::AllocateAndStart(
// Set capture framerate in the form of capture interval.
v4l2_streamparm streamparm = {};
- streamparm.type = capture_type_;
+ 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) {
// Now check if the device is able to accept a capture framerate set.
@@ -279,10 +267,8 @@ void V4L2CaptureDelegate::AllocateAndStart(
capture_format_.frame_rate = frame_rate;
capture_format_.pixel_format = pixel_format;
- v4l2_requestbuffers r_buffer = {};
- r_buffer.type = capture_type_;
- r_buffer.memory = V4L2_MEMORY_MMAP;
- r_buffer.count = kNumVideoBuffers;
+ v4l2_requestbuffers r_buffer;
+ FillV4L2RequestBuffer(&r_buffer, kNumVideoBuffers);
if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0) {
SetErrorState(FROM_HERE, "Error requesting MMAP buffers from V4L2");
return;
@@ -294,7 +280,8 @@ void V4L2CaptureDelegate::AllocateAndStart(
}
}
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMON, &capture_type_)) <
+ v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMON, &capture_type)) <
0) {
SetErrorState(FROM_HERE, "VIDIOC_STREAMON failed");
return;
@@ -310,7 +297,8 @@ void V4L2CaptureDelegate::StopAndDeAllocate() {
DCHECK(v4l2_task_runner_->BelongsToCurrentThread());
// The order is important: stop streaming, clear |buffer_pool_|,
// thus munmap()ing the v4l2_buffers, and then return them to the OS.
- if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMOFF, &capture_type_)) <
+ v4l2_buf_type capture_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_STREAMOFF, &capture_type)) <
0) {
SetErrorState(FROM_HERE, "VIDIOC_STREAMOFF failed");
return;
@@ -318,10 +306,8 @@ void V4L2CaptureDelegate::StopAndDeAllocate() {
buffer_tracker_pool_.clear();
- v4l2_requestbuffers r_buffer = {};
- r_buffer.type = capture_type_;
- r_buffer.memory = V4L2_MEMORY_MMAP;
- r_buffer.count = 0;
+ v4l2_requestbuffers r_buffer;
+ FillV4L2RequestBuffer(&r_buffer, 0);
if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_REQBUFS, &r_buffer)) < 0)
SetErrorState(FROM_HERE, "Failed to VIDIOC_REQBUFS with count = 0");
@@ -338,6 +324,8 @@ void V4L2CaptureDelegate::SetRotation(int rotation) {
rotation_ = rotation;
}
+V4L2CaptureDelegate::~V4L2CaptureDelegate() {}
+
bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) {
v4l2_buffer buffer;
FillV4L2Buffer(&buffer, index);
@@ -347,7 +335,7 @@ bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) {
return false;
}
- const scoped_refptr<BufferTracker>& buffer_tracker = CreateBufferTracker();
+ const scoped_refptr<BufferTracker> buffer_tracker(new BufferTracker());
if (!buffer_tracker->Init(device_fd_.get(), buffer)) {
DLOG(ERROR) << "Error creating BufferTracker";
return false;
@@ -362,13 +350,6 @@ bool V4L2CaptureDelegate::MapAndQueueBuffer(int index) {
return true;
}
-void V4L2CaptureDelegate::FillV4L2Buffer(v4l2_buffer* buffer, int i) const {
- memset(buffer, 0, sizeof(*buffer));
- buffer->memory = V4L2_MEMORY_MMAP;
- buffer->index = i;
- FinishFillingV4L2Buffer(buffer);
-}
-
void V4L2CaptureDelegate::DoCapture() {
DCHECK(v4l2_task_runner_->BelongsToCurrentThread());
if (!is_capturing_)
@@ -406,8 +387,12 @@ void V4L2CaptureDelegate::DoCapture() {
return;
}
- SetPayloadSize(buffer_tracker_pool_[buffer.index], buffer);
- SendBuffer(buffer_tracker_pool_[buffer.index], video_fmt_);
+ buffer_tracker_pool_[buffer.index]->set_payload_size(buffer.bytesused);
+ const scoped_refptr<BufferTracker>& buffer_tracker =
+ buffer_tracker_pool_[buffer.index];
+ client_->OnIncomingCapturedData(
+ buffer_tracker->start(), buffer_tracker->payload_size(),
+ capture_format_, rotation_, base::TimeTicks::Now());
if (HANDLE_EINTR(ioctl(device_fd_.get(), VIDIOC_QBUF, &buffer)) < 0) {
SetErrorState(FROM_HERE, "Failed to enqueue capture buffer");
@@ -427,4 +412,29 @@ void V4L2CaptureDelegate::SetErrorState(
client_->OnError(from_here, reason);
}
+V4L2CaptureDelegate::BufferTracker::BufferTracker() {}
+
+V4L2CaptureDelegate::BufferTracker::~BufferTracker() {
+ if (start_ == nullptr)
+ return;
+ const int result = munmap(start_, length_);
+ PLOG_IF(ERROR, result < 0) << "Error munmap()ing V4L2 buffer";
+}
+
+bool V4L2CaptureDelegate::BufferTracker::Init(int fd,
+ const v4l2_buffer& buffer) {
+ // Some devices require mmap() to be called with both READ and WRITE.
+ // See http://crbug.com/178582.
+ void* const start = mmap(NULL, buffer.length, PROT_READ | PROT_WRITE,
+ MAP_SHARED, fd, buffer.m.offset);
+ if (start == MAP_FAILED) {
+ DLOG(ERROR) << "Error mmap()ing a V4L2 buffer into userspace";
+ return false;
+ }
+ start_ = static_cast<uint8_t*>(start);
+ length_ = buffer.length;
+ payload_size_ = 0;
+ return true;
+}
+
} // namespace media
« no previous file with comments | « media/capture/video/linux/v4l2_capture_delegate.h ('k') | media/capture/video/linux/v4l2_capture_delegate_multi_plane.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698