| Index: content/common/gpu/media/tegra_v4l2_video_device.cc
|
| diff --git a/content/common/gpu/media/tegra_v4l2_video_device.cc b/content/common/gpu/media/tegra_v4l2_video_device.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..a857f7ea383e50ed437a7abb44ac885b8e278b5a
|
| --- /dev/null
|
| +++ b/content/common/gpu/media/tegra_v4l2_video_device.cc
|
| @@ -0,0 +1,154 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +//
|
| +
|
| +#include <dlfcn.h>
|
| +#include <fcntl.h>
|
| +
|
| +#include "base/debug/trace_event.h"
|
| +#include "base/posix/eintr_wrapper.h"
|
| +#include "content/common/gpu/media/tegra_v4l2_video_device.h"
|
| +#include "ui/gl/gl_bindings.h"
|
| +
|
| +namespace content {
|
| +
|
| +namespace {
|
| +const char kDevice[] = "/dev/tegra_avpchannel";
|
| +}
|
| +
|
| +typedef int32 (*TegraV4L2Open)(const char* name, int32 flags);
|
| +typedef int32 (*TegraV4L2Close)(int32 fd);
|
| +typedef int32 (*TegraV4L2Ioctl)(int32 fd, unsigned long cmd, ...);
|
| +typedef int32 (*TegraV4L2Poll)(int32 fd, bool poll_device, bool* event_pending);
|
| +typedef int32 (*TegraV4L2SetDevicePollInterrupt)(int32 fd);
|
| +typedef int32 (*TegraV4L2ClearDevicePollInterrupt)(int32 fd);
|
| +typedef void* (*TegraV4L2Mmap)(void* addr,
|
| + size_t length,
|
| + int prot,
|
| + int flags,
|
| + int fd,
|
| + unsigned int offset);
|
| +typedef int32 (*TegraV4L2Munmap)(void* addr, size_t length);
|
| +typedef int32 (*TegraV4L2UseEglImage)(int fd,
|
| + unsigned int buffer_index,
|
| + void* egl_image);
|
| +
|
| +#define TEGRAV4L2_SYM(name) TegraV4L2##name TegraV4L2_##name = NULL
|
| +
|
| +TEGRAV4L2_SYM(Open);
|
| +TEGRAV4L2_SYM(Close);
|
| +TEGRAV4L2_SYM(Ioctl);
|
| +TEGRAV4L2_SYM(Poll);
|
| +TEGRAV4L2_SYM(SetDevicePollInterrupt);
|
| +TEGRAV4L2_SYM(ClearDevicePollInterrupt);
|
| +TEGRAV4L2_SYM(Mmap);
|
| +TEGRAV4L2_SYM(Munmap);
|
| +TEGRAV4L2_SYM(UseEglImage);
|
| +
|
| +#undef TEGRAV4L2_SYM
|
| +
|
| +TegraV4L2Device::TegraV4L2Device(EGLContext egl_context)
|
| + : device_fd_(-1), egl_context_(egl_context) {}
|
| +
|
| +TegraV4L2Device::~TegraV4L2Device() {
|
| + if (device_fd_ != -1) {
|
| + TegraV4L2_Close(device_fd_);
|
| + device_fd_ = -1;
|
| + }
|
| +}
|
| +
|
| +int TegraV4L2Device::Ioctl(int flags, void* arg) {
|
| + return TegraV4L2_Ioctl(device_fd_, flags, arg);
|
| +}
|
| +
|
| +bool TegraV4L2Device::Poll(bool poll_device, bool* event_pending) {
|
| + if (TegraV4L2_Poll(device_fd_, poll_device, event_pending) == -1) {
|
| + DLOG(ERROR) << "TegraV4L2Poll returned -1 ";
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +void* TegraV4L2Device::Mmap(void* addr,
|
| + unsigned int len,
|
| + int prot,
|
| + int flags,
|
| + unsigned int offset) {
|
| + return TegraV4L2_Mmap(addr, len, prot, flags, device_fd_, offset);
|
| +}
|
| +
|
| +void TegraV4L2Device::Munmap(void* addr, unsigned int len) {
|
| + TegraV4L2_Munmap(addr, len);
|
| +}
|
| +
|
| +bool TegraV4L2Device::SetDevicePollInterrupt() {
|
| + if (HANDLE_EINTR(TegraV4L2_SetDevicePollInterrupt(device_fd_)) == -1) {
|
| + DLOG(ERROR) << "Error in calling TegraV4L2SetDevicePollInterrupt";
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool TegraV4L2Device::ClearDevicePollInterrupt() {
|
| + if (HANDLE_EINTR(TegraV4L2_ClearDevicePollInterrupt(device_fd_)) == -1) {
|
| + DLOG(ERROR) << "Error in calling TegraV4L2ClearDevicePollInterrupt";
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool TegraV4L2Device::Initialize() {
|
| +#define TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(name) \
|
| + do { \
|
| + TegraV4L2_##name = reinterpret_cast<TegraV4L2##name>( \
|
| + dlsym(RTLD_DEFAULT, "TegraV4L2_" #name)); \
|
| + if (TegraV4L2_##name == NULL) { \
|
| + LOG(ERROR) << "Failed to dlsym TegraV4L2_" #name; \
|
| + return false; \
|
| + } \
|
| + } while (0)
|
| +
|
| + TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(Open);
|
| + TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(Close);
|
| + TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(Ioctl);
|
| + TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(Poll);
|
| + TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(SetDevicePollInterrupt);
|
| + TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(ClearDevicePollInterrupt);
|
| + TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(Mmap);
|
| + TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(Munmap);
|
| + TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(UseEglImage);
|
| +#undef TEGRAV4L2_DLSYM
|
| +
|
| + device_fd_ =
|
| + HANDLE_EINTR(TegraV4L2_Open(kDevice, O_RDWR | O_NONBLOCK | O_CLOEXEC));
|
| + if (device_fd_ == -1) {
|
| + DLOG(ERROR) << "Unable to open tegra_v4l2_open ";
|
| + return false;
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +EGLImageKHR TegraV4L2Device::CreateEGLImage(EGLDisplay egl_display,
|
| + EGLint[] /*attrib*/,
|
| + unsigned int texture_id,
|
| + unsigned int buffer_index) {
|
| + EGLint attr = EGL_NONE;
|
| + EGLImageKHR egl_image = eglCreateImageKHR(egl_display,
|
| + egl_context_,
|
| + EGL_GL_TEXTURE_2D_KHR,
|
| + (EGLClientBuffer)(texture_id),
|
| + &attr);
|
| + if (egl_image == EGL_NO_IMAGE_KHR) {
|
| + return egl_image;
|
| + }
|
| + if (TegraV4L2_UseEglImage(device_fd_, buffer_index, egl_image) != 0) {
|
| + eglDestroyImageKHR(egl_display, egl_image);
|
| + egl_image = EGL_NO_IMAGE_KHR;
|
| + }
|
| + return egl_image;
|
| +}
|
| +
|
| +unsigned int TegraV4L2Device::GetTextureTarget() { return GL_TEXTURE_2D; }
|
| +
|
| +} // namespace content
|
|
|