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

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

Issue 809883004: Revert hardware decoder changes causing ChromeOS HW test crash. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 11 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 <fcntl.h> 6 #include <fcntl.h>
7 #include <libdrm/drm_fourcc.h> 7 #include <libdrm/drm_fourcc.h>
8 #include <linux/videodev2.h> 8 #include <linux/videodev2.h>
9 #include <poll.h> 9 #include <poll.h>
10 #include <sys/eventfd.h> 10 #include <sys/eventfd.h>
11 #include <sys/ioctl.h> 11 #include <sys/ioctl.h>
12 #include <sys/mman.h> 12 #include <sys/mman.h>
13 13
14 #include "base/debug/trace_event.h" 14 #include "base/debug/trace_event.h"
15 #include "base/files/scoped_file.h" 15 #include "base/files/scoped_file.h"
16 #include "base/posix/eintr_wrapper.h" 16 #include "base/posix/eintr_wrapper.h"
17 #include "content/common/gpu/media/generic_v4l2_video_device.h" 17 #include "content/common/gpu/media/generic_v4l2_video_device.h"
18 #include "ui/gl/egl_util.h"
19 #include "ui/gl/gl_bindings.h" 18 #include "ui/gl/gl_bindings.h"
20 19
21 namespace content { 20 namespace content {
22 21
23 namespace { 22 namespace {
24 const char kDecoderDevice[] = "/dev/video-dec"; 23 const char kDecoderDevice[] = "/dev/video-dec";
25 const char kEncoderDevice[] = "/dev/video-enc"; 24 const char kEncoderDevice[] = "/dev/video-enc";
26 const char kImageProcessorDevice[] = "/dev/gsc1"; 25 const char kImageProcessorDevice[] = "/dev/gsc1";
27 } 26 }
28 27
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 return false; 130 return false;
132 } 131 }
133 132
134 device_poll_interrupt_fd_ = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC); 133 device_poll_interrupt_fd_ = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
135 if (device_poll_interrupt_fd_ == -1) { 134 if (device_poll_interrupt_fd_ == -1) {
136 return false; 135 return false;
137 } 136 }
138 return true; 137 return true;
139 } 138 }
140 139
141 bool GenericV4L2Device::CanCreateEGLImageFrom(uint32_t v4l2_pixfmt) { 140 EGLImageKHR GenericV4L2Device::CreateEGLImage(EGLDisplay egl_display,
142 static uint32_t kEGLImageDrmFmtsSupported[] = { 141 EGLContext /* egl_context */,
143 DRM_FORMAT_ARGB8888, 142 GLuint texture_id,
144 #if defined(ARCH_CPU_ARMEL) 143 gfx::Size frame_buffer_size,
145 DRM_FORMAT_NV12, 144 unsigned int buffer_index,
146 #endif 145 size_t planes_count) {
147 }; 146 DVLOG(3) << "CreateEGLImage()";
148 147
149 return std::find( 148 scoped_ptr<base::ScopedFD[]> dmabuf_fds(new base::ScopedFD[planes_count]);
150 kEGLImageDrmFmtsSupported, 149 for (size_t i = 0; i < planes_count; ++i) {
151 kEGLImageDrmFmtsSupported + arraysize(kEGLImageDrmFmtsSupported), 150 // Export the DMABUF fd so we can export it as a texture.
152 V4L2PixFmtToDrmFormat(v4l2_pixfmt)) !=
153 kEGLImageDrmFmtsSupported + arraysize(kEGLImageDrmFmtsSupported);
154 }
155
156 EGLImageKHR GenericV4L2Device::CreateEGLImage(EGLDisplay egl_display,
157 EGLContext /* egl_context */,
158 GLuint texture_id,
159 gfx::Size frame_buffer_size,
160 unsigned int buffer_index,
161 uint32_t v4l2_pixfmt,
162 size_t num_v4l2_planes) {
163 DVLOG(3) << "CreateEGLImage()";
164 if (!CanCreateEGLImageFrom(v4l2_pixfmt)) {
165 LOG(ERROR) << "Unsupported V4L2 pixel format";
166 return EGL_NO_IMAGE_KHR;
167 }
168
169 media::VideoFrame::Format vf_format =
170 V4L2PixFmtToVideoFrameFormat(v4l2_pixfmt);
171 // Number of components, as opposed to the number of V4L2 planes, which is
172 // just a buffer count.
173 size_t num_planes = media::VideoFrame::NumPlanes(vf_format);
174 DCHECK_LE(num_planes, 3u);
175 if (num_planes < num_v4l2_planes) {
176 // It's possible for more than one DRM plane to reside in one V4L2 plane,
177 // but not the other way around. We must use all V4L2 planes.
178 LOG(ERROR) << "Invalid plane count";
179 return EGL_NO_IMAGE_KHR;
180 }
181
182 scoped_ptr<base::ScopedFD[]> dmabuf_fds(new base::ScopedFD[num_v4l2_planes]);
183 // Export dmabuf fds so we can create an EGLImage from them.
184 for (size_t i = 0; i < num_v4l2_planes; ++i) {
185 struct v4l2_exportbuffer expbuf; 151 struct v4l2_exportbuffer expbuf;
186 memset(&expbuf, 0, sizeof(expbuf)); 152 memset(&expbuf, 0, sizeof(expbuf));
187 expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 153 expbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
188 expbuf.index = buffer_index; 154 expbuf.index = buffer_index;
189 expbuf.plane = i; 155 expbuf.plane = i;
190 expbuf.flags = O_CLOEXEC; 156 expbuf.flags = O_CLOEXEC;
191 if (Ioctl(VIDIOC_EXPBUF, &expbuf) != 0) { 157 if (Ioctl(VIDIOC_EXPBUF, &expbuf) != 0) {
192 return EGL_NO_IMAGE_KHR; 158 return EGL_NO_IMAGE_KHR;
193 } 159 }
194 dmabuf_fds[i].reset(expbuf.fd); 160 dmabuf_fds[i].reset(expbuf.fd);
195 } 161 }
196 162 DCHECK_EQ(planes_count, 2u);
197 std::vector<EGLint> attrs; 163 EGLint attrs[] = {
198 attrs.push_back(EGL_WIDTH); 164 EGL_WIDTH, 0, EGL_HEIGHT, 0,
199 attrs.push_back(frame_buffer_size.width()); 165 EGL_LINUX_DRM_FOURCC_EXT, 0, EGL_DMA_BUF_PLANE0_FD_EXT, 0,
200 attrs.push_back(EGL_HEIGHT); 166 EGL_DMA_BUF_PLANE0_OFFSET_EXT, 0, EGL_DMA_BUF_PLANE0_PITCH_EXT, 0,
201 attrs.push_back(frame_buffer_size.height()); 167 EGL_DMA_BUF_PLANE1_FD_EXT, 0, EGL_DMA_BUF_PLANE1_OFFSET_EXT, 0,
202 attrs.push_back(EGL_LINUX_DRM_FOURCC_EXT); 168 EGL_DMA_BUF_PLANE1_PITCH_EXT, 0, EGL_NONE, };
203 attrs.push_back(V4L2PixFmtToDrmFormat(v4l2_pixfmt)); 169 attrs[1] = frame_buffer_size.width();
204 170 attrs[3] = frame_buffer_size.height();
205 // For existing formats, if we have less buffers (V4L2 planes) than 171 attrs[5] = DRM_FORMAT_NV12;
206 // components (planes), the remaining planes are stored in the last 172 attrs[7] = dmabuf_fds[0].get();
207 // V4L2 plane. Use one V4L2 plane per each component until we run out of V4L2 173 attrs[9] = 0;
208 // planes, and use the last V4L2 plane for all remaining components, each 174 attrs[11] = frame_buffer_size.width();
209 // with an offset equal to the size of the preceding planes in the same 175 attrs[13] = dmabuf_fds[1].get();
210 // V4L2 plane. 176 attrs[15] = 0;
211 size_t v4l2_plane = 0; 177 attrs[17] = frame_buffer_size.width();
212 size_t plane_offset = 0;
213 for (size_t plane = 0; plane < num_planes; ++plane) {
214 attrs.push_back(EGL_DMA_BUF_PLANE0_FD_EXT + plane * 3);
215 attrs.push_back(dmabuf_fds[v4l2_plane].get());
216 attrs.push_back(EGL_DMA_BUF_PLANE0_OFFSET_EXT + plane * 3);
217 attrs.push_back(plane_offset);
218 attrs.push_back(EGL_DMA_BUF_PLANE0_PITCH_EXT + plane * 3);
219 attrs.push_back(media::VideoFrame::RowBytes(plane, vf_format,
220 frame_buffer_size.width()));
221
222 if (v4l2_plane + 1 < num_v4l2_planes) {
223 ++v4l2_plane;
224 } else {
225 plane_offset += media::VideoFrame::PlaneAllocationSize(
226 vf_format, plane, frame_buffer_size);
227 }
228 }
229
230 attrs.push_back(EGL_NONE);
231 178
232 EGLImageKHR egl_image = eglCreateImageKHR( 179 EGLImageKHR egl_image = eglCreateImageKHR(
233 egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, &attrs[0]); 180 egl_display, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, NULL, attrs);
234 if (egl_image == EGL_NO_IMAGE_KHR) { 181 if (egl_image == EGL_NO_IMAGE_KHR) {
235 LOG(ERROR) << "Failed creating EGL image: " << ui::GetLastEGLErrorString();
236 return egl_image; 182 return egl_image;
237 } 183 }
238 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id); 184 glBindTexture(GL_TEXTURE_EXTERNAL_OES, texture_id);
239 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_image); 185 glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, egl_image);
240 186
241 return egl_image; 187 return egl_image;
242 } 188 }
243 189
244 EGLBoolean GenericV4L2Device::DestroyEGLImage(EGLDisplay egl_display, 190 EGLBoolean GenericV4L2Device::DestroyEGLImage(EGLDisplay egl_display,
245 EGLImageKHR egl_image) { 191 EGLImageKHR egl_image) {
246 return eglDestroyImageKHR(egl_display, egl_image); 192 return eglDestroyImageKHR(egl_display, egl_image);
247 } 193 }
248 194
249 GLenum GenericV4L2Device::GetTextureTarget() { return GL_TEXTURE_EXTERNAL_OES; } 195 GLenum GenericV4L2Device::GetTextureTarget() { return GL_TEXTURE_EXTERNAL_OES; }
250 196
251 uint32 GenericV4L2Device::PreferredInputFormat() { 197 uint32 GenericV4L2Device::PreferredInputFormat() {
252 // TODO(posciak): We should support "dontcare" returns here once we 198 // TODO(posciak): We should support "dontcare" returns here once we
253 // implement proper handling (fallback, negotiation) for this in users. 199 // implement proper handling (fallback, negotiation) for this in users.
254 CHECK_EQ(type_, kEncoder); 200 CHECK_EQ(type_, kEncoder);
255 return V4L2_PIX_FMT_NV12M; 201 return V4L2_PIX_FMT_NV12M;
256 } 202 }
257 203
204 uint32 GenericV4L2Device::PreferredOutputFormat() {
205 // TODO(posciak): We should support "dontcare" returns here once we
206 // implement proper handling (fallback, negotiation) for this in users.
207 CHECK_EQ(type_, kDecoder);
208 return V4L2_PIX_FMT_NV12M;
209 }
210
258 } // namespace content 211 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/generic_v4l2_video_device.h ('k') | content/common/gpu/media/tegra_v4l2_video_device.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698