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

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

Issue 1822983002: Support external buffer import in VDA interface and add a V4L2SVDA impl. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 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
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 5
6 #include <errno.h> 6 #include <errno.h>
7 #include <fcntl.h> 7 #include <fcntl.h>
8 #include <libdrm/drm_fourcc.h> 8 #include <libdrm/drm_fourcc.h>
9 #include <linux/videodev2.h> 9 #include <linux/videodev2.h>
10 #include <poll.h> 10 #include <poll.h>
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
169 } 169 }
170 #endif 170 #endif
171 171
172 device_poll_interrupt_fd_.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC)); 172 device_poll_interrupt_fd_.reset(eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC));
173 if (!device_poll_interrupt_fd_.is_valid()) { 173 if (!device_poll_interrupt_fd_.is_valid()) {
174 return false; 174 return false;
175 } 175 }
176 return true; 176 return true;
177 } 177 }
178 178
179 std::vector<base::ScopedFD> GenericV4L2Device::GetDmabufsForV4L2Buffer(
180 int index,
181 size_t num_planes,
182 enum v4l2_buf_type type) {
183 DCHECK(V4L2_TYPE_IS_MULTIPLANAR(type));
184
185 std::vector<base::ScopedFD> dmabuf_fds;
186 for (size_t i = 0; i < num_planes; ++i) {
187 struct v4l2_exportbuffer expbuf;
188 memset(&expbuf, 0, sizeof(expbuf));
189 expbuf.type = type;
190 expbuf.index = index;
191 expbuf.plane = i;
192 expbuf.flags = O_CLOEXEC;
193 if (Ioctl(VIDIOC_EXPBUF, &expbuf) != 0) {
194 dmabuf_fds.clear();
195 break;
196 }
197
198 dmabuf_fds.push_back(base::ScopedFD(expbuf.fd));
199 }
200
201 return dmabuf_fds;
202 }
203
179 bool GenericV4L2Device::CanCreateEGLImageFrom(uint32_t v4l2_pixfmt) { 204 bool GenericV4L2Device::CanCreateEGLImageFrom(uint32_t v4l2_pixfmt) {
180 static uint32_t kEGLImageDrmFmtsSupported[] = { 205 static uint32_t kEGLImageDrmFmtsSupported[] = {
181 DRM_FORMAT_ARGB8888, 206 DRM_FORMAT_ARGB8888,
182 #if defined(ARCH_CPU_ARMEL) 207 #if defined(ARCH_CPU_ARMEL)
183 DRM_FORMAT_NV12, 208 DRM_FORMAT_NV12,
184 DRM_FORMAT_MT21, 209 DRM_FORMAT_MT21,
185 #endif 210 #endif
186 }; 211 };
187 212
188 return std::find( 213 return std::find(
189 kEGLImageDrmFmtsSupported, 214 kEGLImageDrmFmtsSupported,
190 kEGLImageDrmFmtsSupported + arraysize(kEGLImageDrmFmtsSupported), 215 kEGLImageDrmFmtsSupported + arraysize(kEGLImageDrmFmtsSupported),
191 V4L2PixFmtToDrmFormat(v4l2_pixfmt)) != 216 V4L2PixFmtToDrmFormat(v4l2_pixfmt)) !=
192 kEGLImageDrmFmtsSupported + arraysize(kEGLImageDrmFmtsSupported); 217 kEGLImageDrmFmtsSupported + arraysize(kEGLImageDrmFmtsSupported);
193 } 218 }
194 219
195 EGLImageKHR GenericV4L2Device::CreateEGLImage(EGLDisplay egl_display, 220 EGLImageKHR GenericV4L2Device::CreateEGLImage(
196 EGLContext /* egl_context */, 221 EGLDisplay egl_display,
197 GLuint texture_id, 222 EGLContext /* egl_context */,
198 gfx::Size frame_buffer_size, 223 GLuint texture_id,
199 unsigned int buffer_index, 224 const gfx::Size& size,
200 uint32_t v4l2_pixfmt, 225 unsigned int buffer_index,
201 size_t num_v4l2_planes) { 226 uint32_t v4l2_pixfmt,
227 const std::vector<base::ScopedFD>& dmabuf_fds) {
202 DVLOG(3) << "CreateEGLImage()"; 228 DVLOG(3) << "CreateEGLImage()";
203 if (!CanCreateEGLImageFrom(v4l2_pixfmt)) { 229 if (!CanCreateEGLImageFrom(v4l2_pixfmt)) {
204 LOG(ERROR) << "Unsupported V4L2 pixel format"; 230 LOG(ERROR) << "Unsupported V4L2 pixel format";
205 return EGL_NO_IMAGE_KHR; 231 return EGL_NO_IMAGE_KHR;
206 } 232 }
207 233
208 media::VideoPixelFormat vf_format = V4L2PixFmtToVideoPixelFormat(v4l2_pixfmt); 234 media::VideoPixelFormat vf_format = V4L2PixFmtToVideoPixelFormat(v4l2_pixfmt);
209 // Number of components, as opposed to the number of V4L2 planes, which is 235 // Number of components, as opposed to the number of V4L2 planes, which is
210 // just a buffer count. 236 // just a buffer count.
211 size_t num_planes = media::VideoFrame::NumPlanes(vf_format); 237 size_t num_planes = media::VideoFrame::NumPlanes(vf_format);
212 DCHECK_LE(num_planes, 3u); 238 DCHECK_LE(num_planes, 3u);
213 if (num_planes < num_v4l2_planes) { 239 if (num_planes < dmabuf_fds.size()) {
214 // It's possible for more than one DRM plane to reside in one V4L2 plane, 240 // It's possible for more than one DRM plane to reside in one V4L2 plane,
215 // but not the other way around. We must use all V4L2 planes. 241 // but not the other way around. We must use all V4L2 planes.
216 LOG(ERROR) << "Invalid plane count"; 242 LOG(ERROR) << "Invalid plane count";
217 return EGL_NO_IMAGE_KHR; 243 return EGL_NO_IMAGE_KHR;
218 } 244 }
219 245
220 scoped_ptr<base::ScopedFD[]> dmabuf_fds(new base::ScopedFD[num_v4l2_planes]);
221 // Export dmabuf fds so we can create an EGLImage from them.
222 for (size_t i = 0; i < num_v4l2_planes; ++i) {
223 struct v4l2_exportbuffer expbuf;
224 memset(&expbuf, 0, sizeof(expbuf));
225 expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
226 expbuf.index = buffer_index;
227 expbuf.plane = i;
228 expbuf.flags = O_CLOEXEC;
229 if (Ioctl(VIDIOC_EXPBUF, &expbuf) != 0) {
230 return EGL_NO_IMAGE_KHR;
231 }
232 dmabuf_fds[i].reset(expbuf.fd);
233 }
234
235 std::vector<EGLint> attrs; 246 std::vector<EGLint> attrs;
236 attrs.push_back(EGL_WIDTH); 247 attrs.push_back(EGL_WIDTH);
237 attrs.push_back(frame_buffer_size.width()); 248 attrs.push_back(size.width());
238 attrs.push_back(EGL_HEIGHT); 249 attrs.push_back(EGL_HEIGHT);
239 attrs.push_back(frame_buffer_size.height()); 250 attrs.push_back(size.height());
240 attrs.push_back(EGL_LINUX_DRM_FOURCC_EXT); 251 attrs.push_back(EGL_LINUX_DRM_FOURCC_EXT);
241 attrs.push_back(V4L2PixFmtToDrmFormat(v4l2_pixfmt)); 252 attrs.push_back(V4L2PixFmtToDrmFormat(v4l2_pixfmt));
242 253
243 // For existing formats, if we have less buffers (V4L2 planes) than 254 // For existing formats, if we have less buffers (V4L2 planes) than
244 // components (planes), the remaining planes are stored in the last 255 // components (planes), the remaining planes are stored in the last
245 // V4L2 plane. Use one V4L2 plane per each component until we run out of V4L2 256 // V4L2 plane. Use one V4L2 plane per each component until we run out of V4L2
246 // planes, and use the last V4L2 plane for all remaining components, each 257 // planes, and use the last V4L2 plane for all remaining components, each
247 // with an offset equal to the size of the preceding planes in the same 258 // with an offset equal to the size of the preceding planes in the same
248 // V4L2 plane. 259 // V4L2 plane.
249 size_t v4l2_plane = 0; 260 size_t v4l2_plane = 0;
250 size_t plane_offset = 0; 261 size_t plane_offset = 0;
251 for (size_t plane = 0; plane < num_planes; ++plane) { 262 for (size_t plane = 0; plane < num_planes; ++plane) {
252 attrs.push_back(EGL_DMA_BUF_PLANE0_FD_EXT + plane * 3); 263 attrs.push_back(EGL_DMA_BUF_PLANE0_FD_EXT + plane * 3);
253 attrs.push_back(dmabuf_fds[v4l2_plane].get()); 264 attrs.push_back(dmabuf_fds[v4l2_plane].get());
254 attrs.push_back(EGL_DMA_BUF_PLANE0_OFFSET_EXT + plane * 3); 265 attrs.push_back(EGL_DMA_BUF_PLANE0_OFFSET_EXT + plane * 3);
255 attrs.push_back(plane_offset); 266 attrs.push_back(plane_offset);
256 attrs.push_back(EGL_DMA_BUF_PLANE0_PITCH_EXT + plane * 3); 267 attrs.push_back(EGL_DMA_BUF_PLANE0_PITCH_EXT + plane * 3);
257 attrs.push_back(media::VideoFrame::RowBytes(plane, vf_format, 268 attrs.push_back(
258 frame_buffer_size.width())); 269 media::VideoFrame::RowBytes(plane, vf_format, size.width()));
259 270
260 if (v4l2_plane + 1 < num_v4l2_planes) { 271 if (v4l2_plane + 1 < dmabuf_fds.size()) {
261 ++v4l2_plane; 272 ++v4l2_plane;
kcwu 2016/03/28 02:28:36 reset plane_offset to 0 here?
Pawel Osciak 2016/03/31 05:42:33 Good catch, thanks. Done.
262 } else { 273 } else {
263 plane_offset += media::VideoFrame::PlaneSize( 274 plane_offset +=
264 vf_format, plane, frame_buffer_size).GetArea(); 275 media::VideoFrame::PlaneSize(vf_format, plane, size).GetArea();
265 } 276 }
266 } 277 }
267 278
268 attrs.push_back(EGL_NONE); 279 attrs.push_back(EGL_NONE);
269 280
270 EGLImageKHR egl_image = eglCreateImageKHR( 281 EGLImageKHR egl_image = eglCreateImageKHR(
271 egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, &attrs[0]); 282 egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, &attrs[0]);
272 if (egl_image == EGL_NO_IMAGE_KHR) { 283 if (egl_image == EGL_NO_IMAGE_KHR) {
273 LOG(ERROR) << "Failed creating EGL image: " << ui::GetLastEGLErrorString(); 284 LOG(ERROR) << "Failed creating EGL image: " << ui::GetLastEGLErrorString();
274 return egl_image; 285 return egl_image;
(...skipping 24 matching lines...) Expand all
299 StubPathMap paths; 310 StubPathMap paths;
300 paths[kModuleV4l2].push_back(kV4l2Lib); 311 paths[kModuleV4l2].push_back(kV4l2Lib);
301 312
302 return InitializeStubs(paths); 313 return InitializeStubs(paths);
303 #else 314 #else
304 return true; 315 return true;
305 #endif 316 #endif
306 } 317 }
307 318
308 } // namespace content 319 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/generic_v4l2_device.h ('k') | content/common/gpu/media/gpu_video_decode_accelerator_factory_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698