| Index: media/video/capture/linux/v4l2_capture_delegate_single_plane.cc
|
| diff --git a/media/video/capture/linux/v4l2_capture_delegate_single_plane.cc b/media/video/capture/linux/v4l2_capture_delegate_single_plane.cc
|
| index e2e7e5b0da16a9c4b934b83bdfa567a1f1ab39d6..7176f094cc8f7416ffee1a321a62f7df7e9539da 100644
|
| --- a/media/video/capture/linux/v4l2_capture_delegate_single_plane.cc
|
| +++ b/media/video/capture/linux/v4l2_capture_delegate_single_plane.cc
|
| @@ -4,10 +4,30 @@
|
|
|
| #include "media/video/capture/linux/v4l2_capture_delegate_single_plane.h"
|
|
|
| +#include <linux/version.h>
|
| #include <sys/mman.h>
|
|
|
| namespace media {
|
|
|
| +V4L2CaptureDelegateSinglePlane::V4L2CaptureDelegateSinglePlane(
|
| + const VideoCaptureDevice::Name& device_name,
|
| + const scoped_refptr<base::SingleThreadTaskRunner>& v4l2_task_runner,
|
| + int power_line_frequency,
|
| + bool allow_using_dma_bufs)
|
| + : V4L2CaptureDelegate(
|
| + device_name,
|
| + v4l2_task_runner,
|
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
|
| + allow_using_dma_bufs ? V4L2_MEMORY_DMABUF : V4L2_MEMORY_MMAP,
|
| +#else
|
| + V4L2_MEMORY_MMAP,
|
| +#endif
|
| + power_line_frequency) {
|
| +}
|
| +
|
| +V4L2CaptureDelegateSinglePlane::~V4L2CaptureDelegateSinglePlane() {
|
| +}
|
| +
|
| scoped_refptr<V4L2CaptureDelegate::BufferTracker>
|
| V4L2CaptureDelegateSinglePlane::CreateBufferTracker() const {
|
| return make_scoped_refptr(new BufferTrackerSPlane());
|
| @@ -25,8 +45,32 @@ bool V4L2CaptureDelegateSinglePlane::FillV4L2Format(
|
| }
|
|
|
| void V4L2CaptureDelegateSinglePlane::FinishFillingV4L2Buffer(
|
| - v4l2_buffer* buffer) const {
|
| + v4l2_buffer* buffer,
|
| + bool for_enqueue) const {
|
| buffer->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
| +
|
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
|
| + if (memory_type() == V4L2_MEMORY_MMAP)
|
| + return;
|
| +
|
| + if (!for_enqueue) {
|
| + DCHECK_NE(buffer->m.fd, -1); // API should have filled |fd| in for dequeue.
|
| + return;
|
| + }
|
| + // For enqueueing, need to reserve an output buffer, keep it locally and pass
|
| + // its |fd| into the V4L2 API.
|
| + scoped_ptr<VideoCaptureDevice::Client::Buffer> capture_buffer =
|
| + client()->ReserveOutputBuffer(media::PIXEL_FORMAT_GPUMEMORYBUFFER,
|
| + capture_format().frame_size);
|
| + if (!capture_buffer)
|
| + return;
|
| +
|
| + DCHECK_EQ(capture_buffer->GetType(), gfx::OZONE_NATIVE_BUFFER);
|
| + buffer->m.fd = capture_buffer->AsPlatformFile();
|
| +
|
| + allocated_buffers_.push_back(capture_buffer.release());
|
| + DVLOG(1) << "Sizeof allocated_buffers_ " << allocated_buffers_.size();
|
| +#endif
|
| }
|
|
|
| void V4L2CaptureDelegateSinglePlane::SetPayloadSize(
|
| @@ -38,17 +82,48 @@ void V4L2CaptureDelegateSinglePlane::SetPayloadSize(
|
| void V4L2CaptureDelegateSinglePlane::SendBuffer(
|
| const scoped_refptr<BufferTracker>& buffer_tracker,
|
| const v4l2_format& format) const {
|
| - client()->OnIncomingCapturedData(
|
| - buffer_tracker->GetPlaneStart(0),
|
| - buffer_tracker->GetPlanePayloadSize(0),
|
| - capture_format(),
|
| - rotation(),
|
| - base::TimeTicks::Now());
|
| + DVLOG(1) << __FUNCTION__;
|
| +
|
| + if (memory_type() == V4L2_MEMORY_MMAP) {
|
| + const size_t data_length = format.fmt.pix.sizeimage;
|
| + DCHECK_GE(data_length, capture_format().ImageAllocationSize());
|
| + client()->OnIncomingCapturedData(
|
| + buffer_tracker->GetPlaneStart(0),
|
| + buffer_tracker->GetPlanePayloadSize(0),
|
| + capture_format(),
|
| + rotation(),
|
| + base::TimeTicks::Now());
|
| + return;
|
| + }
|
| +
|
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
|
| + // Search for the |fd| used for capture in |allocated_buffers_| and send it
|
| + // to client().
|
| + const int incoming_fd = buffer_tracker->GetPlaneFd(0);
|
| + ScopedVector<VideoCaptureDevice::Client::Buffer>::iterator used_buffer =
|
| + std::find_if(allocated_buffers_.begin(), allocated_buffers_.end(),
|
| + [incoming_fd](VideoCaptureDevice::Client::Buffer* b) {
|
| + return incoming_fd == b->AsPlatformFile();
|
| + });
|
| + CHECK(used_buffer != allocated_buffers_.end())
|
| + << "Uh oh, captured |fd| is not found in the list :?";
|
| + client()->OnIncomingCapturedBuffer(make_scoped_ptr(*used_buffer),
|
| + capture_format(), base::TimeTicks::Now());
|
| + allocated_buffers_.weak_erase(used_buffer);
|
| +#endif
|
| }
|
|
|
| bool V4L2CaptureDelegateSinglePlane::BufferTrackerSPlane::Init(
|
| int fd,
|
| const v4l2_buffer& buffer) {
|
| + DVLOG(1) << __FUNCTION__;
|
| +#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)
|
| + if (buffer.memory == V4L2_MEMORY_DMABUF) {
|
| + AddNonMmapedPlane(buffer.m.fd);
|
| + return true;
|
| + }
|
| +#endif
|
| +
|
| // 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,
|
|
|