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/lazy_instance.h" | 9 #include "base/lazy_instance.h" |
10 #include "base/posix/eintr_wrapper.h" | 10 #include "base/posix/eintr_wrapper.h" |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
49 TEGRAV4L2_SYM(Mmap); | 49 TEGRAV4L2_SYM(Mmap); |
50 TEGRAV4L2_SYM(Munmap); | 50 TEGRAV4L2_SYM(Munmap); |
51 TEGRAV4L2_SYM(UseEglImage); | 51 TEGRAV4L2_SYM(UseEglImage); |
52 | 52 |
53 #undef TEGRAV4L2_SYM | 53 #undef TEGRAV4L2_SYM |
54 | 54 |
55 class TegraFunctionSymbolFinder { | 55 class TegraFunctionSymbolFinder { |
56 public: | 56 public: |
57 TegraFunctionSymbolFinder() : initialized_(false) { | 57 TegraFunctionSymbolFinder() : initialized_(false) { |
58 if (!dlopen("/usr/lib/libtegrav4l2.so", | 58 if (!dlopen("/usr/lib/libtegrav4l2.so", |
59 RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE)) { | 59 RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE)) |
60 DLOG(ERROR) << "Failed to load libtegrav4l2.so"; | |
61 return; | 60 return; |
62 } | |
63 #define TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(name) \ | 61 #define TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(name) \ |
64 do { \ | 62 do { \ |
65 TegraV4L2_##name = reinterpret_cast<TegraV4L2##name>( \ | 63 TegraV4L2_##name = reinterpret_cast<TegraV4L2##name>( \ |
66 dlsym(RTLD_DEFAULT, "TegraV4L2_" #name)); \ | 64 dlsym(RTLD_DEFAULT, "TegraV4L2_" #name)); \ |
67 if (TegraV4L2_##name == NULL) { \ | 65 if (TegraV4L2_##name == NULL) { \ |
68 LOG(ERROR) << "Failed to dlsym TegraV4L2_" #name; \ | 66 LOG(ERROR) << "Failed to dlsym TegraV4L2_" #name; \ |
69 return; \ | 67 return; \ |
70 } \ | 68 } \ |
71 } while (0) | 69 } while (0) |
72 | 70 |
(...skipping 12 matching lines...) Expand all Loading... |
85 | 83 |
86 bool initialized() { return initialized_; } | 84 bool initialized() { return initialized_; } |
87 | 85 |
88 private: | 86 private: |
89 bool initialized_; | 87 bool initialized_; |
90 }; | 88 }; |
91 | 89 |
92 base::LazyInstance<TegraFunctionSymbolFinder> g_tegra_function_symbol_finder_ = | 90 base::LazyInstance<TegraFunctionSymbolFinder> g_tegra_function_symbol_finder_ = |
93 LAZY_INSTANCE_INITIALIZER; | 91 LAZY_INSTANCE_INITIALIZER; |
94 | 92 |
95 TegraV4L2Device::TegraV4L2Device(Type type) | 93 TegraV4L2Device::TegraV4L2Device() {} |
96 : V4L2Device(type), device_fd_(-1) {} | |
97 | 94 |
98 TegraV4L2Device::~TegraV4L2Device() { | 95 TegraV4L2Device::~TegraV4L2Device() { |
99 if (device_fd_ != -1) { | 96 Close(); |
100 TegraV4L2_Close(device_fd_); | |
101 device_fd_ = -1; | |
102 } | |
103 } | 97 } |
104 | 98 |
105 int TegraV4L2Device::Ioctl(int flags, void* arg) { | 99 int TegraV4L2Device::Ioctl(int flags, void* arg) { |
106 return HANDLE_EINTR(TegraV4L2_Ioctl(device_fd_, flags, arg)); | 100 return HANDLE_EINTR(TegraV4L2_Ioctl(device_fd_, flags, arg)); |
107 } | 101 } |
108 | 102 |
109 bool TegraV4L2Device::Poll(bool poll_device, bool* event_pending) { | 103 bool TegraV4L2Device::Poll(bool poll_device, bool* event_pending) { |
110 if (HANDLE_EINTR(TegraV4L2_Poll(device_fd_, poll_device, event_pending)) == | 104 if (HANDLE_EINTR(TegraV4L2_Poll(device_fd_, poll_device, event_pending)) == |
111 -1) { | 105 -1) { |
112 LOG(ERROR) << "TegraV4L2Poll returned -1 "; | 106 LOG(ERROR) << "TegraV4L2Poll returned -1 "; |
(...skipping 24 matching lines...) Expand all Loading... |
137 | 131 |
138 bool TegraV4L2Device::ClearDevicePollInterrupt() { | 132 bool TegraV4L2Device::ClearDevicePollInterrupt() { |
139 if (HANDLE_EINTR(TegraV4L2_ClearDevicePollInterrupt(device_fd_)) == -1) { | 133 if (HANDLE_EINTR(TegraV4L2_ClearDevicePollInterrupt(device_fd_)) == -1) { |
140 LOG(ERROR) << "Error in calling TegraV4L2ClearDevicePollInterrupt"; | 134 LOG(ERROR) << "Error in calling TegraV4L2ClearDevicePollInterrupt"; |
141 return false; | 135 return false; |
142 } | 136 } |
143 return true; | 137 return true; |
144 } | 138 } |
145 | 139 |
146 bool TegraV4L2Device::Initialize() { | 140 bool TegraV4L2Device::Initialize() { |
147 const char* device_path = NULL; | 141 return g_tegra_function_symbol_finder_.Get().initialized(); |
148 switch (type_) { | 142 } |
149 case kDecoder: | 143 |
| 144 bool TegraV4L2Device::Open(Type type, uint32_t /* v4l2_pixfmt */) { |
| 145 return OpenInternal(type); |
| 146 } |
| 147 |
| 148 bool TegraV4L2Device::OpenInternal(Type type) { |
| 149 const char* device_path = nullptr; |
| 150 |
| 151 switch (type) { |
| 152 case Type::kDecoder: |
150 device_path = kDecoderDevice; | 153 device_path = kDecoderDevice; |
151 break; | 154 break; |
152 case kEncoder: | 155 case Type::kEncoder: |
153 device_path = kEncoderDevice; | 156 device_path = kEncoderDevice; |
154 break; | 157 break; |
155 default: | 158 default: |
156 DVLOG(1) << "Device type " << type_ << " not supported on this platform"; | 159 DVLOG(1) << "Device type " << static_cast<int>(type) |
| 160 << " not supported on this platform"; |
157 return false; | 161 return false; |
158 } | 162 } |
159 | 163 |
160 if (!g_tegra_function_symbol_finder_.Get().initialized()) { | 164 DCHECK_EQ(device_fd_, -1); |
161 DLOG(ERROR) << "Unable to initialize functions"; | |
162 return false; | |
163 } | |
164 device_fd_ = HANDLE_EINTR( | 165 device_fd_ = HANDLE_EINTR( |
165 TegraV4L2_Open(device_path, O_RDWR | O_NONBLOCK | O_CLOEXEC)); | 166 TegraV4L2_Open(device_path, O_RDWR | O_NONBLOCK | O_CLOEXEC)); |
166 if (device_fd_ == -1) { | 167 if (device_fd_ == -1) { |
167 DLOG(ERROR) << "Unable to open device " << device_path; | 168 DLOG(ERROR) << "Unable to open device " << device_path; |
168 return false; | 169 return false; |
169 } | 170 } |
170 return true; | 171 return true; |
171 } | 172 } |
172 | 173 |
| 174 void TegraV4L2Device::Close() { |
| 175 if (device_fd_ != -1) { |
| 176 TegraV4L2_Close(device_fd_); |
| 177 device_fd_ = -1; |
| 178 } |
| 179 } |
| 180 |
173 std::vector<base::ScopedFD> TegraV4L2Device::GetDmabufsForV4L2Buffer( | 181 std::vector<base::ScopedFD> TegraV4L2Device::GetDmabufsForV4L2Buffer( |
174 int /* index */, | 182 int /* index */, |
175 size_t num_planes, | 183 size_t num_planes, |
176 enum v4l2_buf_type /* type */) { | 184 enum v4l2_buf_type /* buf_type */) { |
177 std::vector<base::ScopedFD> dmabuf_fds; | 185 std::vector<base::ScopedFD> dmabuf_fds; |
178 // Tegra does not actually provide dmabuf fds currently. Fill the vector with | 186 // Tegra does not actually provide dmabuf fds currently. Fill the vector with |
179 // invalid descriptors to prevent the caller from failing on an empty vector | 187 // invalid descriptors to prevent the caller from failing on an empty vector |
180 // being returned. TegraV4L2Device::CreateEGLImage() will ignore the invalid | 188 // being returned. TegraV4L2Device::CreateEGLImage() will ignore the invalid |
181 // descriptors and create images based on V4L2 index passed to it. | 189 // descriptors and create images based on V4L2 index passed to it. |
182 dmabuf_fds.resize(num_planes); | 190 dmabuf_fds.resize(num_planes); |
183 return dmabuf_fds; | 191 return dmabuf_fds; |
184 } | 192 } |
185 | 193 |
186 bool TegraV4L2Device::CanCreateEGLImageFrom(uint32_t v4l2_pixfmt) { | 194 bool TegraV4L2Device::CanCreateEGLImageFrom(uint32_t v4l2_pixfmt) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 | 227 |
220 EGLBoolean TegraV4L2Device::DestroyEGLImage(EGLDisplay egl_display, | 228 EGLBoolean TegraV4L2Device::DestroyEGLImage(EGLDisplay egl_display, |
221 EGLImageKHR egl_image) { | 229 EGLImageKHR egl_image) { |
222 return eglDestroyImageKHR(egl_display, egl_image); | 230 return eglDestroyImageKHR(egl_display, egl_image); |
223 } | 231 } |
224 | 232 |
225 GLenum TegraV4L2Device::GetTextureTarget() { | 233 GLenum TegraV4L2Device::GetTextureTarget() { |
226 return GL_TEXTURE_2D; | 234 return GL_TEXTURE_2D; |
227 } | 235 } |
228 | 236 |
229 uint32_t TegraV4L2Device::PreferredInputFormat() { | 237 uint32_t TegraV4L2Device::PreferredInputFormat(Type type) { |
230 // TODO(posciak): We should support "dontcare" returns here once we | 238 if (type == Type::kEncoder) |
231 // implement proper handling (fallback, negotiation) for this in users. | 239 return V4L2_PIX_FMT_YUV420M; |
232 CHECK_EQ(type_, kEncoder); | 240 |
233 return V4L2_PIX_FMT_YUV420M; | 241 return 0; |
| 242 } |
| 243 |
| 244 std::vector<uint32_t> TegraV4L2Device::GetSupportedImageProcessorPixelformats( |
| 245 v4l2_buf_type /* buf_type */) { |
| 246 return std::vector<uint32_t>(); |
| 247 } |
| 248 |
| 249 VideoDecodeAccelerator::SupportedProfiles |
| 250 TegraV4L2Device::GetSupportedDecodeProfiles(const size_t num_formats, |
| 251 const uint32_t pixelformats[]) { |
| 252 if (!OpenInternal(Type::kDecoder)) |
| 253 return VideoDecodeAccelerator::SupportedProfiles(); |
| 254 |
| 255 const auto& profiles = |
| 256 EnumerateSupportedDecodeProfiles(num_formats, pixelformats); |
| 257 |
| 258 Close(); |
| 259 return profiles; |
| 260 } |
| 261 |
| 262 VideoEncodeAccelerator::SupportedProfiles |
| 263 TegraV4L2Device::GetSupportedEncodeProfiles() { |
| 264 if (!OpenInternal(Type::kEncoder)) |
| 265 return VideoEncodeAccelerator::SupportedProfiles(); |
| 266 |
| 267 const auto& profiles = EnumerateSupportedEncodeProfiles(); |
| 268 |
| 269 Close(); |
| 270 return profiles; |
| 271 } |
| 272 |
| 273 bool TegraV4L2Device::IsImageProcessingSupported() { |
| 274 return false; |
| 275 } |
| 276 |
| 277 bool TegraV4L2Device::IsJpegDecodingSupported() { |
| 278 return false; |
234 } | 279 } |
235 | 280 |
236 } // namespace media | 281 } // namespace media |
OLD | NEW |