Chromium Code Reviews| 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. |
| +// |
|
sheu
2014/03/06 08:51:34
Extra comment line here.
shivdasp
2014/03/06 11:10:09
Done.
|
| + |
| +#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); |
|
sheu
2014/03/06 08:51:34
No HANDLE_EINTR wrapper needed for this?
shivdasp
2014/03/06 11:10:09
Done.
|
| +} |
| + |
| +bool TegraV4L2Device::Poll(bool poll_device, bool* event_pending) { |
| + if (TegraV4L2_Poll(device_fd_, poll_device, event_pending) == -1) { |
|
sheu
2014/03/06 08:51:34
No HANDLE_EINTR wrapper needed for this?
shivdasp
2014/03/06 11:10:09
Done.
|
| + 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); |
|
sheu
2014/03/06 08:51:34
Can this sort of thing be done once at startup tim
shivdasp
2014/03/06 11:10:09
Initialize() is called when the V4L2Device is crea
sheu
2014/03/07 00:18:08
We could do this once statically similar to how Va
|
| +#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), |
|
sheu
2014/03/06 08:51:34
static_cast<>; we don't use C-style casts.
shivdasp
2014/03/06 11:10:09
Done.
|
| + &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; |
|
sheu
2014/03/06 08:51:34
So as I understand it:
In the Exynos case, we exp
shivdasp
2014/03/06 11:10:09
Yes that's right. tegrav4l2lib takes care of destr
|
| +} |
| + |
| +unsigned int TegraV4L2Device::GetTextureTarget() { return GL_TEXTURE_2D; } |
| + |
| +} // namespace content |