| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include <dlfcn.h> | 5 #include <dlfcn.h> |
| 6 #include <fcntl.h> | 6 #include <fcntl.h> |
| 7 #include <linux/videodev2.h> | 7 #include <linux/videodev2.h> |
| 8 | 8 |
| 9 #include "base/debug/trace_event.h" | 9 #include "base/debug/trace_event.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 TEGRAV4L2_SYM(Munmap); | 48 TEGRAV4L2_SYM(Munmap); |
| 49 TEGRAV4L2_SYM(UseEglImage); | 49 TEGRAV4L2_SYM(UseEglImage); |
| 50 | 50 |
| 51 #undef TEGRAV4L2_SYM | 51 #undef TEGRAV4L2_SYM |
| 52 | 52 |
| 53 class TegraFunctionSymbolFinder { | 53 class TegraFunctionSymbolFinder { |
| 54 public: | 54 public: |
| 55 TegraFunctionSymbolFinder() : initialized_(false) { | 55 TegraFunctionSymbolFinder() : initialized_(false) { |
| 56 if (!dlopen("/usr/lib/libtegrav4l2.so", | 56 if (!dlopen("/usr/lib/libtegrav4l2.so", |
| 57 RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE)) { | 57 RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE)) { |
| 58 DLOG(ERROR) << "Failed to load libtegrav4l2.so "; | 58 DLOG(ERROR) << "Failed to load libtegrav4l2.so"; |
| 59 return; | 59 return; |
| 60 } | 60 } |
| 61 #define TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(name) \ | 61 #define TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(name) \ |
| 62 do { \ | 62 do { \ |
| 63 TegraV4L2_##name = reinterpret_cast<TegraV4L2##name>( \ | 63 TegraV4L2_##name = reinterpret_cast<TegraV4L2##name>( \ |
| 64 dlsym(RTLD_DEFAULT, "TegraV4L2_" #name)); \ | 64 dlsym(RTLD_DEFAULT, "TegraV4L2_" #name)); \ |
| 65 if (TegraV4L2_##name == NULL) { \ | 65 if (TegraV4L2_##name == NULL) { \ |
| 66 LOG(ERROR) << "Failed to dlsym TegraV4L2_" #name; \ | 66 LOG(ERROR) << "Failed to dlsym TegraV4L2_" #name; \ |
| 67 return; \ | 67 return; \ |
| 68 } \ | 68 } \ |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 } | 102 } |
| 103 } | 103 } |
| 104 | 104 |
| 105 int TegraV4L2Device::Ioctl(int flags, void* arg) { | 105 int TegraV4L2Device::Ioctl(int flags, void* arg) { |
| 106 return HANDLE_EINTR(TegraV4L2_Ioctl(device_fd_, flags, arg)); | 106 return HANDLE_EINTR(TegraV4L2_Ioctl(device_fd_, flags, arg)); |
| 107 } | 107 } |
| 108 | 108 |
| 109 bool TegraV4L2Device::Poll(bool poll_device, bool* event_pending) { | 109 bool TegraV4L2Device::Poll(bool poll_device, bool* event_pending) { |
| 110 if (HANDLE_EINTR(TegraV4L2_Poll(device_fd_, poll_device, event_pending)) == | 110 if (HANDLE_EINTR(TegraV4L2_Poll(device_fd_, poll_device, event_pending)) == |
| 111 -1) { | 111 -1) { |
| 112 DLOG(ERROR) << "TegraV4L2Poll returned -1 "; | 112 LOG(ERROR) << "TegraV4L2Poll returned -1 "; |
| 113 return false; | 113 return false; |
| 114 } | 114 } |
| 115 return true; | 115 return true; |
| 116 } | 116 } |
| 117 | 117 |
| 118 void* TegraV4L2Device::Mmap(void* addr, | 118 void* TegraV4L2Device::Mmap(void* addr, |
| 119 unsigned int len, | 119 unsigned int len, |
| 120 int prot, | 120 int prot, |
| 121 int flags, | 121 int flags, |
| 122 unsigned int offset) { | 122 unsigned int offset) { |
| 123 return TegraV4L2_Mmap(addr, len, prot, flags, device_fd_, offset); | 123 return TegraV4L2_Mmap(addr, len, prot, flags, device_fd_, offset); |
| 124 } | 124 } |
| 125 | 125 |
| 126 void TegraV4L2Device::Munmap(void* addr, unsigned int len) { | 126 void TegraV4L2Device::Munmap(void* addr, unsigned int len) { |
| 127 TegraV4L2_Munmap(addr, len); | 127 TegraV4L2_Munmap(addr, len); |
| 128 } | 128 } |
| 129 | 129 |
| 130 bool TegraV4L2Device::SetDevicePollInterrupt() { | 130 bool TegraV4L2Device::SetDevicePollInterrupt() { |
| 131 if (HANDLE_EINTR(TegraV4L2_SetDevicePollInterrupt(device_fd_)) == -1) { | 131 if (HANDLE_EINTR(TegraV4L2_SetDevicePollInterrupt(device_fd_)) == -1) { |
| 132 DLOG(ERROR) << "Error in calling TegraV4L2SetDevicePollInterrupt"; | 132 LOG(ERROR) << "Error in calling TegraV4L2SetDevicePollInterrupt"; |
| 133 return false; | 133 return false; |
| 134 } | 134 } |
| 135 return true; | 135 return true; |
| 136 } | 136 } |
| 137 | 137 |
| 138 bool TegraV4L2Device::ClearDevicePollInterrupt() { | 138 bool TegraV4L2Device::ClearDevicePollInterrupt() { |
| 139 if (HANDLE_EINTR(TegraV4L2_ClearDevicePollInterrupt(device_fd_)) == -1) { | 139 if (HANDLE_EINTR(TegraV4L2_ClearDevicePollInterrupt(device_fd_)) == -1) { |
| 140 DLOG(ERROR) << "Error in calling TegraV4L2ClearDevicePollInterrupt"; | 140 LOG(ERROR) << "Error in calling TegraV4L2ClearDevicePollInterrupt"; |
| 141 return false; | 141 return false; |
| 142 } | 142 } |
| 143 return true; | 143 return true; |
| 144 } | 144 } |
| 145 | 145 |
| 146 bool TegraV4L2Device::Initialize() { | 146 bool TegraV4L2Device::Initialize() { |
| 147 const char* device_path = NULL; | 147 const char* device_path = NULL; |
| 148 switch (type_) { | 148 switch (type_) { |
| 149 case kDecoder: | 149 case kDecoder: |
| 150 device_path = kDecoderDevice; | 150 device_path = kDecoderDevice; |
| 151 break; | 151 break; |
| 152 case kEncoder: | 152 case kEncoder: |
| 153 device_path = kEncoderDevice; | 153 device_path = kEncoderDevice; |
| 154 break; | 154 break; |
| 155 case kImageProcessor: | 155 case kImageProcessor: |
| 156 DVLOG(1) << "Device type " << type_ << " not supported on this platform"; | 156 DVLOG(1) << "Device type " << type_ << " not supported on this platform"; |
| 157 return false; | 157 return false; |
| 158 } | 158 } |
| 159 | 159 |
| 160 if (!g_tegra_function_symbol_finder_.Get().initialized()) { | 160 if (!g_tegra_function_symbol_finder_.Get().initialized()) { |
| 161 DLOG(ERROR) << "Unable to initialize functions "; | 161 DLOG(ERROR) << "Unable to initialize functions"; |
| 162 return false; | 162 return false; |
| 163 } | 163 } |
| 164 device_fd_ = HANDLE_EINTR( | 164 device_fd_ = HANDLE_EINTR( |
| 165 TegraV4L2_Open(device_path, O_RDWR | O_NONBLOCK | O_CLOEXEC)); | 165 TegraV4L2_Open(device_path, O_RDWR | O_NONBLOCK | O_CLOEXEC)); |
| 166 if (device_fd_ == -1) { | 166 if (device_fd_ == -1) { |
| 167 DLOG(ERROR) << "Unable to open device " << device_path; | 167 DLOG(ERROR) << "Unable to open device " << device_path; |
| 168 return false; | 168 return false; |
| 169 } | 169 } |
| 170 return true; | 170 return true; |
| 171 } | 171 } |
| 172 | 172 |
| 173 EGLImageKHR TegraV4L2Device::CreateEGLImage(EGLDisplay egl_display, | 173 EGLImageKHR TegraV4L2Device::CreateEGLImage(EGLDisplay egl_display, |
| 174 EGLContext egl_context, | 174 EGLContext egl_context, |
| 175 GLuint texture_id, | 175 GLuint texture_id, |
| 176 gfx::Size /* frame_buffer_size */, | 176 gfx::Size /* frame_buffer_size */, |
| 177 unsigned int buffer_index, | 177 unsigned int buffer_index, |
| 178 size_t /* planes_count */) { | 178 size_t /* planes_count */) { |
| 179 DVLOG(3) << "CreateEGLImage()"; | 179 DVLOG(3) << "CreateEGLImage()"; |
| 180 EGLint attr = EGL_NONE; | 180 EGLint attr = EGL_NONE; |
| 181 EGLImageKHR egl_image = | 181 EGLImageKHR egl_image = |
| 182 eglCreateImageKHR(egl_display, | 182 eglCreateImageKHR(egl_display, |
| 183 egl_context, | 183 egl_context, |
| 184 EGL_GL_TEXTURE_2D_KHR, | 184 EGL_GL_TEXTURE_2D_KHR, |
| 185 reinterpret_cast<EGLClientBuffer>(texture_id), | 185 reinterpret_cast<EGLClientBuffer>(texture_id), |
| 186 &attr); | 186 &attr); |
| 187 if (egl_image == EGL_NO_IMAGE_KHR) { | 187 if (egl_image == EGL_NO_IMAGE_KHR) { |
| 188 LOG(ERROR) << "Unable to create EGL image"; |
| 188 return egl_image; | 189 return egl_image; |
| 189 } | 190 } |
| 190 if (TegraV4L2_UseEglImage(device_fd_, buffer_index, egl_image) != 0) { | 191 if (TegraV4L2_UseEglImage(device_fd_, buffer_index, egl_image) != 0) { |
| 192 LOG(ERROR) << "Unable to use EGL image"; |
| 191 eglDestroyImageKHR(egl_display, egl_image); | 193 eglDestroyImageKHR(egl_display, egl_image); |
| 192 egl_image = EGL_NO_IMAGE_KHR; | 194 egl_image = EGL_NO_IMAGE_KHR; |
| 193 } | 195 } |
| 194 return egl_image; | 196 return egl_image; |
| 195 } | 197 } |
| 196 | 198 |
| 197 EGLBoolean TegraV4L2Device::DestroyEGLImage(EGLDisplay egl_display, | 199 EGLBoolean TegraV4L2Device::DestroyEGLImage(EGLDisplay egl_display, |
| 198 EGLImageKHR egl_image) { | 200 EGLImageKHR egl_image) { |
| 199 return eglDestroyImageKHR(egl_display, egl_image); | 201 return eglDestroyImageKHR(egl_display, egl_image); |
| 200 } | 202 } |
| 201 | 203 |
| 202 GLenum TegraV4L2Device::GetTextureTarget() { return GL_TEXTURE_2D; } | 204 GLenum TegraV4L2Device::GetTextureTarget() { return GL_TEXTURE_2D; } |
| 203 | 205 |
| 204 uint32 TegraV4L2Device::PreferredInputFormat() { | 206 uint32 TegraV4L2Device::PreferredInputFormat() { |
| 205 // TODO(posciak): We should support "dontcare" returns here once we | 207 // TODO(posciak): We should support "dontcare" returns here once we |
| 206 // implement proper handling (fallback, negotiation) for this in users. | 208 // implement proper handling (fallback, negotiation) for this in users. |
| 207 CHECK_EQ(type_, kEncoder); | 209 CHECK_EQ(type_, kEncoder); |
| 208 return V4L2_PIX_FMT_YUV420M; | 210 return V4L2_PIX_FMT_YUV420M; |
| 209 } | 211 } |
| 210 | 212 |
| 211 uint32 TegraV4L2Device::PreferredOutputFormat() { | 213 uint32 TegraV4L2Device::PreferredOutputFormat() { |
| 212 // TODO(posciak): We should support "dontcare" returns here once we | 214 // TODO(posciak): We should support "dontcare" returns here once we |
| 213 // implement proper handling (fallback, negotiation) for this in users. | 215 // implement proper handling (fallback, negotiation) for this in users. |
| 214 CHECK_EQ(type_, kDecoder); | 216 CHECK_EQ(type_, kDecoder); |
| 215 return V4L2_PIX_FMT_NV12M; | 217 return V4L2_PIX_FMT_NV12M; |
| 216 } | 218 } |
| 217 | 219 |
| 218 } // namespace content | 220 } // namespace content |
| OLD | NEW |