Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(167)

Side by Side Diff: content/common/gpu/media/tegra_v4l2_device.cc

Issue 1882373004: Migrate content/common/gpu/media code to media/gpu (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Squash and rebase Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include <dlfcn.h>
6 #include <fcntl.h>
7 #include <linux/videodev2.h>
8
9 #include "base/lazy_instance.h"
10 #include "base/posix/eintr_wrapper.h"
11 #include "base/trace_event/trace_event.h"
12 #include "content/common/gpu/media/tegra_v4l2_device.h"
13 #include "ui/gl/gl_bindings.h"
14
15 namespace content {
16
17 namespace {
18 const char kDecoderDevice[] = "/dev/tegra_avpchannel";
19 const char kEncoderDevice[] = "/dev/nvhost-msenc";
20 }
21
22 typedef int32_t (*TegraV4L2Open)(const char* name, int32_t flags);
23 typedef int32_t (*TegraV4L2Close)(int32_t fd);
24 typedef int32_t (*TegraV4L2Ioctl)(int32_t fd, unsigned long cmd, ...);
25 typedef int32_t (*TegraV4L2Poll)(int32_t fd,
26 bool poll_device,
27 bool* event_pending);
28 typedef int32_t (*TegraV4L2SetDevicePollInterrupt)(int32_t fd);
29 typedef int32_t (*TegraV4L2ClearDevicePollInterrupt)(int32_t fd);
30 typedef void* (*TegraV4L2Mmap)(void* addr,
31 size_t length,
32 int prot,
33 int flags,
34 int fd,
35 unsigned int offset);
36 typedef int32_t (*TegraV4L2Munmap)(void* addr, size_t length);
37 typedef int32_t (*TegraV4L2UseEglImage)(int fd,
38 unsigned int buffer_index,
39 void* egl_image);
40
41 #define TEGRAV4L2_SYM(name) TegraV4L2##name TegraV4L2_##name = NULL
42
43 TEGRAV4L2_SYM(Open);
44 TEGRAV4L2_SYM(Close);
45 TEGRAV4L2_SYM(Ioctl);
46 TEGRAV4L2_SYM(Poll);
47 TEGRAV4L2_SYM(SetDevicePollInterrupt);
48 TEGRAV4L2_SYM(ClearDevicePollInterrupt);
49 TEGRAV4L2_SYM(Mmap);
50 TEGRAV4L2_SYM(Munmap);
51 TEGRAV4L2_SYM(UseEglImage);
52
53 #undef TEGRAV4L2_SYM
54
55 class TegraFunctionSymbolFinder {
56 public:
57 TegraFunctionSymbolFinder() : initialized_(false) {
58 if (!dlopen("/usr/lib/libtegrav4l2.so",
59 RTLD_NOW | RTLD_GLOBAL | RTLD_NODELETE)) {
60 DLOG(ERROR) << "Failed to load libtegrav4l2.so";
61 return;
62 }
63 #define TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(name) \
64 do { \
65 TegraV4L2_##name = reinterpret_cast<TegraV4L2##name>( \
66 dlsym(RTLD_DEFAULT, "TegraV4L2_" #name)); \
67 if (TegraV4L2_##name == NULL) { \
68 LOG(ERROR) << "Failed to dlsym TegraV4L2_" #name; \
69 return; \
70 } \
71 } while (0)
72
73 TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(Open);
74 TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(Close);
75 TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(Ioctl);
76 TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(Poll);
77 TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(SetDevicePollInterrupt);
78 TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(ClearDevicePollInterrupt);
79 TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(Mmap);
80 TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(Munmap);
81 TEGRAV4L2_DLSYM_OR_RETURN_ON_ERROR(UseEglImage);
82 #undef TEGRAV4L2_DLSYM
83 initialized_ = true;
84 }
85
86 bool initialized() { return initialized_; }
87
88 private:
89 bool initialized_;
90 };
91
92 base::LazyInstance<TegraFunctionSymbolFinder> g_tegra_function_symbol_finder_ =
93 LAZY_INSTANCE_INITIALIZER;
94
95 TegraV4L2Device::TegraV4L2Device(Type type)
96 : V4L2Device(type),
97 device_fd_(-1) {
98 }
99
100 TegraV4L2Device::~TegraV4L2Device() {
101 if (device_fd_ != -1) {
102 TegraV4L2_Close(device_fd_);
103 device_fd_ = -1;
104 }
105 }
106
107 int TegraV4L2Device::Ioctl(int flags, void* arg) {
108 return HANDLE_EINTR(TegraV4L2_Ioctl(device_fd_, flags, arg));
109 }
110
111 bool TegraV4L2Device::Poll(bool poll_device, bool* event_pending) {
112 if (HANDLE_EINTR(TegraV4L2_Poll(device_fd_, poll_device, event_pending)) ==
113 -1) {
114 LOG(ERROR) << "TegraV4L2Poll returned -1 ";
115 return false;
116 }
117 return true;
118 }
119
120 void* TegraV4L2Device::Mmap(void* addr,
121 unsigned int len,
122 int prot,
123 int flags,
124 unsigned int offset) {
125 return TegraV4L2_Mmap(addr, len, prot, flags, device_fd_, offset);
126 }
127
128 void TegraV4L2Device::Munmap(void* addr, unsigned int len) {
129 TegraV4L2_Munmap(addr, len);
130 }
131
132 bool TegraV4L2Device::SetDevicePollInterrupt() {
133 if (HANDLE_EINTR(TegraV4L2_SetDevicePollInterrupt(device_fd_)) == -1) {
134 LOG(ERROR) << "Error in calling TegraV4L2SetDevicePollInterrupt";
135 return false;
136 }
137 return true;
138 }
139
140 bool TegraV4L2Device::ClearDevicePollInterrupt() {
141 if (HANDLE_EINTR(TegraV4L2_ClearDevicePollInterrupt(device_fd_)) == -1) {
142 LOG(ERROR) << "Error in calling TegraV4L2ClearDevicePollInterrupt";
143 return false;
144 }
145 return true;
146 }
147
148 bool TegraV4L2Device::Initialize() {
149 const char* device_path = NULL;
150 switch (type_) {
151 case kDecoder:
152 device_path = kDecoderDevice;
153 break;
154 case kEncoder:
155 device_path = kEncoderDevice;
156 break;
157 default:
158 DVLOG(1) << "Device type " << type_ << " not supported on this platform";
159 return false;
160 }
161
162 if (!g_tegra_function_symbol_finder_.Get().initialized()) {
163 DLOG(ERROR) << "Unable to initialize functions";
164 return false;
165 }
166 device_fd_ = HANDLE_EINTR(
167 TegraV4L2_Open(device_path, O_RDWR | O_NONBLOCK | O_CLOEXEC));
168 if (device_fd_ == -1) {
169 DLOG(ERROR) << "Unable to open device " << device_path;
170 return false;
171 }
172 return true;
173 }
174
175 std::vector<base::ScopedFD> TegraV4L2Device::GetDmabufsForV4L2Buffer(
176 int /* index */,
177 size_t num_planes,
178 enum v4l2_buf_type /* type */) {
179 std::vector<base::ScopedFD> dmabuf_fds;
180 // Tegra does not actually provide dmabuf fds currently. Fill the vector with
181 // invalid descriptors to prevent the caller from failing on an empty vector
182 // being returned. TegraV4L2Device::CreateEGLImage() will ignore the invalid
183 // descriptors and create images based on V4L2 index passed to it.
184 dmabuf_fds.resize(num_planes);
185 return dmabuf_fds;
186 }
187
188 bool TegraV4L2Device::CanCreateEGLImageFrom(uint32_t v4l2_pixfmt) {
189 return v4l2_pixfmt == V4L2_PIX_FMT_NV12M;
190 }
191
192 EGLImageKHR TegraV4L2Device::CreateEGLImage(
193 EGLDisplay egl_display,
194 EGLContext egl_context,
195 GLuint texture_id,
196 const gfx::Size& /* size */,
197 unsigned int buffer_index,
198 uint32_t v4l2_pixfmt,
199 const std::vector<base::ScopedFD>& /* dmabuf_fds */) {
200 DVLOG(3) << "CreateEGLImage()";
201 if (!CanCreateEGLImageFrom(v4l2_pixfmt)) {
202 LOG(ERROR) << "Unsupported V4L2 pixel format";
203 return EGL_NO_IMAGE_KHR;
204 }
205
206 EGLint attr = EGL_NONE;
207 EGLImageKHR egl_image =
208 eglCreateImageKHR(egl_display,
209 egl_context,
210 EGL_GL_TEXTURE_2D_KHR,
211 reinterpret_cast<EGLClientBuffer>(texture_id),
212 &attr);
213 if (egl_image == EGL_NO_IMAGE_KHR) {
214 LOG(ERROR) << "Unable to create EGL image";
215 return egl_image;
216 }
217 if (TegraV4L2_UseEglImage(device_fd_, buffer_index, egl_image) != 0) {
218 LOG(ERROR) << "Unable to use EGL image";
219 eglDestroyImageKHR(egl_display, egl_image);
220 egl_image = EGL_NO_IMAGE_KHR;
221 }
222 return egl_image;
223 }
224
225 EGLBoolean TegraV4L2Device::DestroyEGLImage(EGLDisplay egl_display,
226 EGLImageKHR egl_image) {
227 return eglDestroyImageKHR(egl_display, egl_image);
228 }
229
230 GLenum TegraV4L2Device::GetTextureTarget() { return GL_TEXTURE_2D; }
231
232 uint32_t TegraV4L2Device::PreferredInputFormat() {
233 // TODO(posciak): We should support "dontcare" returns here once we
234 // implement proper handling (fallback, negotiation) for this in users.
235 CHECK_EQ(type_, kEncoder);
236 return V4L2_PIX_FMT_YUV420M;
237 }
238
239 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698