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)) |
kcwu
2016/10/07 11:19:04
Why removed the DLOG ? It may silently fallback to
Pawel Osciak
2016/10/11 06:13:45
It is now the normal flow to try TegraV4L2Device f
| |
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 if (device_fd_ != -1) { |
100 TegraV4L2_Close(device_fd_); | 97 TegraV4L2_Close(device_fd_); |
101 device_fd_ = -1; | 98 device_fd_ = -1; |
102 } | 99 } |
103 } | 100 } |
104 | 101 |
105 int TegraV4L2Device::Ioctl(int flags, void* arg) { | 102 int TegraV4L2Device::Ioctl(int flags, void* arg) { |
106 return HANDLE_EINTR(TegraV4L2_Ioctl(device_fd_, flags, arg)); | 103 return HANDLE_EINTR(TegraV4L2_Ioctl(device_fd_, flags, arg)); |
(...skipping 30 matching lines...) Expand all Loading... | |
137 | 134 |
138 bool TegraV4L2Device::ClearDevicePollInterrupt() { | 135 bool TegraV4L2Device::ClearDevicePollInterrupt() { |
139 if (HANDLE_EINTR(TegraV4L2_ClearDevicePollInterrupt(device_fd_)) == -1) { | 136 if (HANDLE_EINTR(TegraV4L2_ClearDevicePollInterrupt(device_fd_)) == -1) { |
140 LOG(ERROR) << "Error in calling TegraV4L2ClearDevicePollInterrupt"; | 137 LOG(ERROR) << "Error in calling TegraV4L2ClearDevicePollInterrupt"; |
141 return false; | 138 return false; |
142 } | 139 } |
143 return true; | 140 return true; |
144 } | 141 } |
145 | 142 |
146 bool TegraV4L2Device::Initialize() { | 143 bool TegraV4L2Device::Initialize() { |
147 const char* device_path = NULL; | 144 return g_tegra_function_symbol_finder_.Get().initialized(); |
148 switch (type_) { | 145 } |
149 case kDecoder: | 146 |
147 bool TegraV4L2Device::Open(Type type, uint32_t /* v4l2_pixfmt */) { | |
148 return OpenInternal(type); | |
149 } | |
150 | |
151 bool TegraV4L2Device::OpenInternal(Type type) { | |
152 const char* device_path = nullptr; | |
kcwu
2016/10/07 11:19:04
DCHECK_EQ(device_fd_, -1);
Pawel Osciak
2016/10/11 06:13:45
Done.
| |
153 | |
154 switch (type) { | |
155 case Type::kDecoder: | |
150 device_path = kDecoderDevice; | 156 device_path = kDecoderDevice; |
151 break; | 157 break; |
152 case kEncoder: | 158 case Type::kEncoder: |
153 device_path = kEncoderDevice; | 159 device_path = kEncoderDevice; |
154 break; | 160 break; |
155 default: | 161 default: |
156 DVLOG(1) << "Device type " << type_ << " not supported on this platform"; | 162 DVLOG(1) << "Device type " << static_cast<int>(type) |
163 << " not supported on this platform"; | |
157 return false; | 164 return false; |
158 } | 165 } |
159 | 166 |
160 if (!g_tegra_function_symbol_finder_.Get().initialized()) { | |
161 DLOG(ERROR) << "Unable to initialize functions"; | |
162 return false; | |
163 } | |
164 device_fd_ = HANDLE_EINTR( | 167 device_fd_ = HANDLE_EINTR( |
165 TegraV4L2_Open(device_path, O_RDWR | O_NONBLOCK | O_CLOEXEC)); | 168 TegraV4L2_Open(device_path, O_RDWR | O_NONBLOCK | O_CLOEXEC)); |
166 if (device_fd_ == -1) { | 169 if (device_fd_ == -1) { |
167 DLOG(ERROR) << "Unable to open device " << device_path; | 170 DLOG(ERROR) << "Unable to open device " << device_path; |
168 return false; | 171 return false; |
169 } | 172 } |
170 return true; | 173 return true; |
171 } | 174 } |
172 | 175 |
173 std::vector<base::ScopedFD> TegraV4L2Device::GetDmabufsForV4L2Buffer( | 176 std::vector<base::ScopedFD> TegraV4L2Device::GetDmabufsForV4L2Buffer( |
174 int /* index */, | 177 int /* index */, |
175 size_t num_planes, | 178 size_t num_planes, |
176 enum v4l2_buf_type /* type */) { | 179 enum v4l2_buf_type /* buf_type */) { |
177 std::vector<base::ScopedFD> dmabuf_fds; | 180 std::vector<base::ScopedFD> dmabuf_fds; |
178 // Tegra does not actually provide dmabuf fds currently. Fill the vector with | 181 // 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 | 182 // invalid descriptors to prevent the caller from failing on an empty vector |
180 // being returned. TegraV4L2Device::CreateEGLImage() will ignore the invalid | 183 // being returned. TegraV4L2Device::CreateEGLImage() will ignore the invalid |
181 // descriptors and create images based on V4L2 index passed to it. | 184 // descriptors and create images based on V4L2 index passed to it. |
182 dmabuf_fds.resize(num_planes); | 185 dmabuf_fds.resize(num_planes); |
183 return dmabuf_fds; | 186 return dmabuf_fds; |
184 } | 187 } |
185 | 188 |
186 bool TegraV4L2Device::CanCreateEGLImageFrom(uint32_t v4l2_pixfmt) { | 189 bool TegraV4L2Device::CanCreateEGLImageFrom(uint32_t v4l2_pixfmt) { |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
219 | 222 |
220 EGLBoolean TegraV4L2Device::DestroyEGLImage(EGLDisplay egl_display, | 223 EGLBoolean TegraV4L2Device::DestroyEGLImage(EGLDisplay egl_display, |
221 EGLImageKHR egl_image) { | 224 EGLImageKHR egl_image) { |
222 return eglDestroyImageKHR(egl_display, egl_image); | 225 return eglDestroyImageKHR(egl_display, egl_image); |
223 } | 226 } |
224 | 227 |
225 GLenum TegraV4L2Device::GetTextureTarget() { | 228 GLenum TegraV4L2Device::GetTextureTarget() { |
226 return GL_TEXTURE_2D; | 229 return GL_TEXTURE_2D; |
227 } | 230 } |
228 | 231 |
229 uint32_t TegraV4L2Device::PreferredInputFormat() { | 232 uint32_t TegraV4L2Device::PreferredInputFormat(Type type) { |
230 // TODO(posciak): We should support "dontcare" returns here once we | 233 if (type == Type::kEncoder) |
231 // implement proper handling (fallback, negotiation) for this in users. | 234 return V4L2_PIX_FMT_YUV420M; |
232 CHECK_EQ(type_, kEncoder); | 235 |
233 return V4L2_PIX_FMT_YUV420M; | 236 return 0; |
237 } | |
238 | |
239 std::vector<uint32_t> TegraV4L2Device::GetSupportedImageProcessorPixelformats( | |
240 v4l2_buf_type /* buf_type */) { | |
241 return std::vector<uint32_t>(); | |
242 } | |
243 | |
244 VideoDecodeAccelerator::SupportedProfiles | |
245 TegraV4L2Device::GetSupportedDecodeProfiles(const size_t num_formats, | |
246 const uint32_t pixelformats[]) { | |
247 if (!OpenInternal(Type::kDecoder)) | |
248 return VideoDecodeAccelerator::SupportedProfiles(); | |
249 | |
250 return EnumerateSupportedDecodeProfiles(num_formats, pixelformats); | |
kcwu
2016/10/07 11:19:04
don't forget to close, otherwise fd leak.
Pawel Osciak
2016/10/11 06:13:45
Done.
| |
251 } | |
252 | |
253 VideoEncodeAccelerator::SupportedProfiles | |
254 TegraV4L2Device::GetSupportedEncodeProfiles() { | |
255 if (!OpenInternal(Type::kEncoder)) | |
256 return VideoEncodeAccelerator::SupportedProfiles(); | |
257 | |
258 return EnumerateSupportedEncodeProfiles(); | |
kcwu
2016/10/07 11:19:04
don't forget to close, otherwise fd leak.
Pawel Osciak
2016/10/11 06:13:45
Done.
| |
259 } | |
260 | |
261 bool TegraV4L2Device::IsImageProcessingSupported() { | |
262 return false; | |
263 } | |
264 | |
265 bool TegraV4L2Device::IsJpegDecodingSupported() { | |
266 return false; | |
234 } | 267 } |
235 | 268 |
236 } // namespace media | 269 } // namespace media |
OLD | NEW |