diff options
Diffstat (limited to 'chromium/media/gpu/v4l2/v4l2_device.cc')
-rw-r--r-- | chromium/media/gpu/v4l2/v4l2_device.cc | 196 |
1 files changed, 38 insertions, 158 deletions
diff --git a/chromium/media/gpu/v4l2/v4l2_device.cc b/chromium/media/gpu/v4l2/v4l2_device.cc index 6b4fe768342..1cff2201faf 100644 --- a/chromium/media/gpu/v4l2/v4l2_device.cc +++ b/chromium/media/gpu/v4l2/v4l2_device.cc @@ -16,7 +16,6 @@ #include <linux/videodev2.h> #include <string.h> #include <sys/mman.h> -#include <sstream> #include "base/bind.h" #include "base/logging.h" @@ -34,9 +33,6 @@ #include "ui/gfx/generic_shared_memory_id.h" #include "ui/gfx/native_pixmap_handle.h" -#if defined(ARCH_CPU_ARMEL) -#include "media/gpu/v4l2/tegra_v4l2_device.h" -#endif #if defined(AML_V4L2) #include "media/gpu/v4l2/aml_v4l2_device.h" #endif @@ -70,6 +66,21 @@ struct v4l2_format BuildV4L2Format(const enum v4l2_buf_type type, return format; } +const char* V4L2BufferTypeToString(const enum v4l2_buf_type buf_type) { + switch (buf_type) { + case V4L2_BUF_TYPE_VIDEO_OUTPUT: + return "OUTPUT"; + case V4L2_BUF_TYPE_VIDEO_CAPTURE: + return "CAPTURE"; + case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: + return "OUTPUT_MPLANE"; + case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: + return "CAPTURE_MPLANE"; + default: + return "UNKNOWN"; + } +} + } // namespace V4L2ExtCtrl::V4L2ExtCtrl(uint32_t id) { @@ -116,8 +127,8 @@ class V4L2Buffer { // V4L2 data as queried by QUERYBUF. struct v4l2_buffer v4l2_buffer_; // WARNING: do not change this to a vector or something smaller than - // VIDEO_MAX_PLANES, otherwise the Tegra libv4l2 will write data beyond - // the number of allocated planes, resulting in memory corruption. + // VIDEO_MAX_PLANES (the maximum number of planes V4L2 supports). The + // element overhead is small and may avoid memory corruption bugs. struct v4l2_plane v4l2_planes_[VIDEO_MAX_PLANES]; struct v4l2_format format_; @@ -235,18 +246,21 @@ scoped_refptr<VideoFrame> V4L2Buffer::CreateVideoFrame() { return nullptr; } + // DMA buffer fds should not be invalid + for (const auto& dmabuf_fd : dmabuf_fds) { + if (!dmabuf_fd.is_valid()) { + DLOG(ERROR) << "Fail to get DMABUFs of V4L2 buffer - invalid fd"; + return nullptr; + } + } + // Duplicate the fd of the last v4l2 plane until the number of fds are the // same as the number of color planes. - while (dmabuf_fds.size() != layout->planes().size()) { - int duped_fd = -1; - // Fd in dmabuf_fds is invalid with TegraV4L2Device. An invalid fd is added - // in the case. - if (dmabuf_fds.back().is_valid()) { - duped_fd = HANDLE_EINTR(dup(dmabuf_fds.back().get())); - if (duped_fd == -1) { - DLOG(ERROR) << "Failed duplicating dmabuf fd"; - return nullptr; - } + while (dmabuf_fds.size() < layout->planes().size()) { + int duped_fd = HANDLE_EINTR(dup(dmabuf_fds.back().get())); + if (duped_fd == -1) { + DLOG(ERROR) << "Failed duplicating dmabuf fd"; + return nullptr; } dmabuf_fds.emplace_back(duped_fd); @@ -357,8 +371,8 @@ class V4L2BufferRefBase { // Data from the buffer, that users can query and/or write. struct v4l2_buffer v4l2_buffer_; // WARNING: do not change this to a vector or something smaller than - // VIDEO_MAX_PLANES, otherwise the Tegra libv4l2 will write data beyond - // the number of allocated planes, resulting in memory corruption. + // VIDEO_MAX_PLANES (the maximum number of planes V4L2 supports). The + // element overhead is small and may avoid memory corruption bugs. struct v4l2_plane v4l2_planes_[VIDEO_MAX_PLANES]; private: @@ -900,11 +914,11 @@ class V4L2BufferRefFactory { // Helper macros that print the queue type with logs. #define VPQLOGF(level) \ - VPLOGF(level) << "(" << V4L2Device::V4L2BufferTypeToString(type_) << ") " + VPLOGF(level) << "(" << V4L2BufferTypeToString(type_) << ") " #define VQLOGF(level) \ - VLOGF(level) << "(" << V4L2Device::V4L2BufferTypeToString(type_) << ") " + VLOGF(level) << "(" << V4L2BufferTypeToString(type_) << ") " #define DVQLOGF(level) \ - DVLOGF(level) << "(" << V4L2Device::V4L2BufferTypeToString(type_) << ") " + DVLOGF(level) << "(" << V4L2BufferTypeToString(type_) << ") " V4L2Queue::V4L2Queue(scoped_refptr<V4L2Device> dev, enum v4l2_buf_type type, @@ -1055,9 +1069,6 @@ size_t V4L2Queue::AllocateBuffers(size_t count, enum v4l2_memory memory) { } // First query the number of planes in the buffers we are about to request. - // This should not be required, but Tegra's VIDIOC_QUERYBUF will fail on - // output buffers if the number of specified planes does not exactly match the - // format. base::Optional<v4l2_format> format = GetFormat().first; if (!format) { VQLOGF(1) << "Cannot get format."; @@ -1253,8 +1264,8 @@ std::pair<bool, V4L2ReadableBufferRef> V4L2Queue::DequeueBuffer() { struct v4l2_buffer v4l2_buffer; memset(&v4l2_buffer, 0, sizeof(v4l2_buffer)); // WARNING: do not change this to a vector or something smaller than - // VIDEO_MAX_PLANES, otherwise the Tegra libv4l2 will write data beyond - // the number of allocated planes, resulting in memory corruption. + // VIDEO_MAX_PLANES (the maximum number of planes V4L2 supports). The + // element overhead is small and may avoid memory corruption bugs. struct v4l2_plane planes[VIDEO_MAX_PLANES]; memset(planes, 0, sizeof(planes)); v4l2_buffer.type = type_; @@ -1440,12 +1451,6 @@ scoped_refptr<V4L2Device> V4L2Device::Create() { scoped_refptr<V4L2Device> device; -#if defined(ARCH_CPU_ARMEL) - device = new TegraV4L2Device(); - if (device->Initialize()) - return device; -#endif - #if defined(AML_V4L2) device = new AmlV4L2Device(); if (device->Initialize()) @@ -1479,7 +1484,7 @@ uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile, else return V4L2_PIX_FMT_VP9; } else { - LOG(ERROR) << "Unknown profile: " << GetProfileName(profile); + DVLOGF(1) << "Unsupported profile: " << GetProfileName(profile); return 0; } } @@ -1611,29 +1616,6 @@ std::vector<VideoCodecProfile> V4L2Device::V4L2PixFmtToVideoCodecProfiles( } // static -uint32_t V4L2Device::V4L2PixFmtToDrmFormat(uint32_t format) { - switch (format) { - case V4L2_PIX_FMT_NV12: - case V4L2_PIX_FMT_NV12M: - return DRM_FORMAT_NV12; - - case V4L2_PIX_FMT_YUV420: - case V4L2_PIX_FMT_YUV420M: - return DRM_FORMAT_YUV420; - - case V4L2_PIX_FMT_YVU420: - return DRM_FORMAT_YVU420; - - case V4L2_PIX_FMT_RGB32: - return DRM_FORMAT_ARGB8888; - - default: - DVLOGF(1) << "Unrecognized format " << FourccToString(format); - return 0; - } -} - -// static int32_t V4L2Device::VideoCodecProfileToV4L2H264Profile( VideoCodecProfile profile) { switch (profile) { @@ -1795,108 +1777,6 @@ gfx::Size V4L2Device::AllocatedSizeFromV4L2Format( } // static -const char* V4L2Device::V4L2MemoryToString(const v4l2_memory memory) { - switch (memory) { - case V4L2_MEMORY_MMAP: - return "V4L2_MEMORY_MMAP"; - case V4L2_MEMORY_USERPTR: - return "V4L2_MEMORY_USERPTR"; - case V4L2_MEMORY_DMABUF: - return "V4L2_MEMORY_DMABUF"; - case V4L2_MEMORY_OVERLAY: - return "V4L2_MEMORY_OVERLAY"; - default: - return "UNKNOWN"; - } -} - -// static -const char* V4L2Device::V4L2BufferTypeToString( - const enum v4l2_buf_type buf_type) { - switch (buf_type) { - case V4L2_BUF_TYPE_VIDEO_OUTPUT: - return "OUTPUT"; - case V4L2_BUF_TYPE_VIDEO_CAPTURE: - return "CAPTURE"; - case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE: - return "OUTPUT_MPLANE"; - case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE: - return "CAPTURE_MPLANE"; - default: - return "UNKNOWN"; - } -} - -// static -std::string V4L2Device::V4L2FormatToString(const struct v4l2_format& format) { - std::ostringstream s; - s << "v4l2_format type: " << format.type; - if (format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE || - format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - // single-planar - const struct v4l2_pix_format& pix = format.fmt.pix; - s << ", width_height: " << gfx::Size(pix.width, pix.height).ToString() - << ", pixelformat: " << FourccToString(pix.pixelformat) - << ", field: " << pix.field << ", bytesperline: " << pix.bytesperline - << ", sizeimage: " << pix.sizeimage; - } else if (V4L2_TYPE_IS_MULTIPLANAR(format.type)) { - const struct v4l2_pix_format_mplane& pix_mp = format.fmt.pix_mp; - // As long as num_planes's type is uint8_t, ostringstream treats it as a - // char instead of an integer, which is not what we want. Casting - // pix_mp.num_planes unsigned int solves the issue. - s << ", width_height: " << gfx::Size(pix_mp.width, pix_mp.height).ToString() - << ", pixelformat: " << FourccToString(pix_mp.pixelformat) - << ", field: " << pix_mp.field - << ", num_planes: " << static_cast<unsigned int>(pix_mp.num_planes); - for (size_t i = 0; i < pix_mp.num_planes; ++i) { - const struct v4l2_plane_pix_format& plane_fmt = pix_mp.plane_fmt[i]; - s << ", plane_fmt[" << i << "].sizeimage: " << plane_fmt.sizeimage - << ", plane_fmt[" << i << "].bytesperline: " << plane_fmt.bytesperline; - } - } else { - s << " unsupported yet."; - } - return s.str(); -} - -// static -std::string V4L2Device::V4L2BufferToString(const struct v4l2_buffer& buffer) { - std::ostringstream s; - s << "v4l2_buffer type: " << buffer.type << ", memory: " << buffer.memory - << ", index: " << buffer.index << " bytesused: " << buffer.bytesused - << ", length: " << buffer.length; - if (buffer.type == V4L2_BUF_TYPE_VIDEO_CAPTURE || - buffer.type == V4L2_BUF_TYPE_VIDEO_OUTPUT) { - // single-planar - if (buffer.memory == V4L2_MEMORY_MMAP) { - s << ", m.offset: " << buffer.m.offset; - } else if (buffer.memory == V4L2_MEMORY_USERPTR) { - s << ", m.userptr: " << buffer.m.userptr; - } else if (buffer.memory == V4L2_MEMORY_DMABUF) { - s << ", m.fd: " << buffer.m.fd; - } - } else if (V4L2_TYPE_IS_MULTIPLANAR(buffer.type)) { - for (size_t i = 0; i < buffer.length; ++i) { - const struct v4l2_plane& plane = buffer.m.planes[i]; - s << ", m.planes[" << i << "](bytesused: " << plane.bytesused - << ", length: " << plane.length - << ", data_offset: " << plane.data_offset; - if (buffer.memory == V4L2_MEMORY_MMAP) { - s << ", m.mem_offset: " << plane.m.mem_offset; - } else if (buffer.memory == V4L2_MEMORY_USERPTR) { - s << ", m.userptr: " << plane.m.userptr; - } else if (buffer.memory == V4L2_MEMORY_DMABUF) { - s << ", m.fd: " << plane.m.fd; - } - s << ")"; - } - } else { - s << " unsupported yet."; - } - return s.str(); -} - -// static base::Optional<VideoFrameLayout> V4L2Device::V4L2FormatToVideoFrameLayout( const struct v4l2_format& format) { if (!V4L2_TYPE_IS_MULTIPLANAR(format.type)) { |