OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "content/common/gpu/media/vaapi_wrapper.h" | 5 #include "content/common/gpu/media/vaapi_wrapper.h" |
6 | 6 |
7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback_helpers.h" | 10 #include "base/callback_helpers.h" |
11 #include "base/containers/scoped_ptr_hash_map.h" | |
Pawel Osciak
2014/08/25 01:13:23
Unused?
| |
11 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/memory/scoped_vector.h" | |
Pawel Osciak
2014/08/25 01:13:24
Unused?
| |
12 #include "base/numerics/safe_conversions.h" | 14 #include "base/numerics/safe_conversions.h" |
13 // Auto-generated for dlopen libva libraries | 15 // Auto-generated for dlopen libva libraries |
14 #include "content/common/gpu/media/va_stubs.h" | 16 #include "content/common/gpu/media/va_stubs.h" |
15 #include "third_party/libyuv/include/libyuv.h" | 17 #include "third_party/libyuv/include/libyuv.h" |
18 #include "ui/gl/gl_bindings.h" | |
19 #include "ui/gl/gl_image.h" | |
20 #if defined(USE_X11) | |
21 #include "third_party/libva/va/va_x11.h" | |
22 #include "ui/gl/gl_context_glx.h" | |
23 #else | |
24 #include <gbm.h> | |
25 #include "third_party/libva/va/drm/va_drm.h" | |
26 #include "third_party/libva/va/va_drmcommon.h" | |
27 #include "ui/gl/gl_image_egl.h" | |
28 #include "ui/ozone/public/native_pixmap.h" | |
29 #include "ui/ozone/public/ozone_platform.h" | |
30 #include "ui/ozone/public/surface_factory_ozone.h" | |
31 #include <va/va_vpp.h> | |
32 #endif // USE_X11 | |
33 #include "ui/gl/scoped_binders.h" | |
16 | 34 |
17 using content_common_gpu_media::kModuleVa; | 35 using content_common_gpu_media::kModuleVa; |
36 #if defined(USE_X11) | |
37 using content_common_gpu_media::kModuleVa_x11; | |
38 #else | |
39 using content_common_gpu_media::kModuleVa_ozone; | |
40 #endif // USE_X11 | |
18 using content_common_gpu_media::InitializeStubs; | 41 using content_common_gpu_media::InitializeStubs; |
19 using content_common_gpu_media::StubPathMap; | 42 using content_common_gpu_media::StubPathMap; |
20 | 43 |
21 // libva-x11 depends on libva, so dlopen libva-x11 is enough | |
22 static const base::FilePath::CharType kVaLib[] = | |
23 FILE_PATH_LITERAL("libva-x11.so.1"); | |
24 | |
25 #define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \ | 44 #define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \ |
26 do { \ | 45 do { \ |
27 DVLOG(1) << err_msg \ | 46 DVLOG(1) << err_msg \ |
28 << " VA error: " << vaErrorStr(va_error); \ | 47 << " VA error: " << vaErrorStr(va_error); \ |
29 report_error_to_uma_cb_.Run(); \ | 48 report_error_to_uma_cb_.Run(); \ |
30 } while (0) | 49 } while (0) |
31 | 50 |
32 #define VA_LOG_ON_ERROR(va_error, err_msg) \ | 51 #define VA_LOG_ON_ERROR(va_error, err_msg) \ |
33 do { \ | 52 do { \ |
34 if ((va_error) != VA_STATUS_SUCCESS) \ | 53 if ((va_error) != VA_STATUS_SUCCESS) \ |
35 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \ | 54 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \ |
36 } while (0) | 55 } while (0) |
37 | 56 |
38 #define VA_SUCCESS_OR_RETURN(va_error, err_msg, ret) \ | 57 #define VA_SUCCESS_OR_RETURN(va_error, err_msg, ret) \ |
39 do { \ | 58 do { \ |
40 if ((va_error) != VA_STATUS_SUCCESS) { \ | 59 if ((va_error) != VA_STATUS_SUCCESS) { \ |
41 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \ | 60 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \ |
42 return (ret); \ | 61 return (ret); \ |
43 } \ | 62 } \ |
44 } while (0) | 63 } while (0) |
45 | 64 |
46 namespace content { | 65 namespace content { |
47 | 66 |
67 class VaapiWrapper::Backend : public base::RefCounted<VaapiWrapper::Backend> { | |
Pawel Osciak
2014/08/25 01:13:24
Please document all classes that are added.
| |
68 protected: | |
69 virtual ~Backend() { Deinitialize(); } | |
70 | |
71 public: | |
72 virtual VAStatus CreateSurfaces(VASurfaceID* surfaces, | |
73 uint32 num_surfaces, | |
74 const gfx::Size& size) = 0; | |
75 | |
76 virtual linked_ptr<Picture> CreatePicture(int32 picture_buffer_id, | |
77 uint32 texture_id, | |
78 const gfx::Size& size) = 0; | |
79 | |
80 virtual void DestroyPicture(Picture* picture) = 0; | |
81 | |
82 virtual VAStatus PutSurfaceIntoPicture(VADisplay va_display, | |
83 VASurfaceID va_surface_id, | |
84 Picture* picture) = 0; | |
85 | |
86 virtual VADisplay GetDisplay() = 0; | |
87 | |
88 virtual bool Initialize() = 0; | |
89 | |
90 virtual void Deinitialize() {}; | |
Pawel Osciak
2014/08/25 01:13:24
Does this need body?
| |
91 | |
92 static scoped_refptr<Backend> Create( | |
93 gfx::GLContext* gl_context, | |
94 const base::Callback<bool(void)> make_context_current); | |
95 | |
96 private: | |
97 friend class base::RefCounted<VaapiWrapper::Backend>; | |
98 }; | |
99 | |
100 #if defined(USE_X11) | |
101 class VaapiWrapper::TFPPicture : public VaapiWrapper::Picture { | |
102 public: | |
103 TFPPicture(scoped_refptr<Backend> backend, | |
104 int32 picture_buffer_id, | |
105 uint32 texture_id, | |
106 const gfx::Size& size, | |
107 Pixmap x_pixmap, | |
108 GLXPixmap glx_pixmap) | |
109 : Picture(picture_buffer_id, texture_id, size), | |
110 backend_(backend), | |
111 x_pixmap_(x_pixmap), | |
112 glx_pixmap_(glx_pixmap) {} | |
113 virtual ~TFPPicture() { backend_->DestroyPicture(this); } | |
114 | |
115 Pixmap x_pixmap() const { return x_pixmap_; } | |
116 GLXPixmap glx_pixmap() const { return glx_pixmap_; } | |
117 | |
118 private: | |
119 scoped_refptr<Backend> backend_; | |
120 Pixmap x_pixmap_; | |
121 GLXPixmap glx_pixmap_; | |
122 }; | |
123 | |
124 class XFreeDeleter { | |
125 public: | |
126 void operator()(void* x) const { ::XFree(x); } | |
127 }; | |
128 | |
129 class VaapiWrapper::X11Backend : public VaapiWrapper::Backend { | |
130 private: | |
Pawel Osciak
2014/08/25 01:13:24
The proper order of members should start with publ
| |
131 virtual ~X11Backend() {} | |
132 | |
133 bool BindPicture(Picture* picture) { | |
134 TFPPicture* tfp_picture = static_cast<TFPPicture*>(picture); | |
135 | |
136 if (!make_context_current_.Run()) | |
137 return false; | |
138 | |
139 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, | |
140 tfp_picture->texture_id()); | |
141 glXBindTexImageEXT( | |
142 x_display_, tfp_picture->glx_pixmap(), GLX_FRONT_LEFT_EXT, NULL); | |
143 | |
144 return true; | |
145 } | |
146 | |
147 public: | |
148 X11Backend(gfx::GLContextGLX* glx_context, | |
149 const base::Callback<bool(void)> make_context_current) | |
150 : glx_context_(glx_context), | |
151 make_context_current_(make_context_current), | |
152 x_display_(glx_context_->display()), | |
153 va_display_(NULL) {} | |
154 | |
155 virtual VAStatus CreateSurfaces(VASurfaceID* surfaces, | |
156 uint32 num_surfaces, | |
157 const gfx::Size& size) OVERRIDE { | |
158 return vaCreateSurfaces(GetDisplay(), | |
159 VA_RT_FORMAT_YUV420, | |
160 size.width(), | |
161 size.height(), | |
162 surfaces, | |
163 num_surfaces, | |
164 NULL, | |
165 0); | |
166 } | |
167 | |
168 virtual linked_ptr<Picture> CreatePicture(int32 picture_buffer_id, | |
169 uint32 texture_id, | |
170 const gfx::Size& size) OVERRIDE { | |
171 linked_ptr<TFPPicture> tfp_picture; | |
172 | |
173 if (!make_context_current_.Run()) | |
174 return tfp_picture; | |
175 | |
176 XWindowAttributes win_attr; | |
177 int screen = DefaultScreen(x_display_); | |
178 XGetWindowAttributes(x_display_, RootWindow(x_display_, screen), &win_attr); | |
179 // TODO(posciak): pass the depth required by libva, not the RootWindow's | |
180 // depth | |
181 Pixmap x_pixmap = XCreatePixmap(x_display_, | |
182 RootWindow(x_display_, screen), | |
183 size.width(), | |
184 size.height(), | |
185 win_attr.depth); | |
186 if (!x_pixmap) { | |
187 DVLOG(1) << "Failed creating an X Pixmap for TFP"; | |
188 return tfp_picture; | |
189 } | |
190 | |
191 static const int pixmap_attr[] = { | |
192 GLX_TEXTURE_TARGET_EXT, GLX_TEXTURE_2D_EXT, GLX_TEXTURE_FORMAT_EXT, | |
193 GLX_TEXTURE_FORMAT_RGB_EXT, GL_NONE, | |
194 }; | |
195 | |
196 GLXPixmap glx_pixmap = | |
197 glXCreatePixmap(x_display_, fb_config_, x_pixmap, pixmap_attr); | |
198 if (!glx_pixmap) { | |
199 // x_pixmap_ will be freed in the destructor. | |
200 DVLOG(1) << "Failed creating a GLX Pixmap for TFP"; | |
201 XFreePixmap(x_display_, x_pixmap); | |
202 return tfp_picture; | |
203 } | |
204 | |
205 tfp_picture.reset(new TFPPicture(make_scoped_refptr(this), | |
206 picture_buffer_id, | |
207 texture_id, | |
208 size, | |
209 x_pixmap, | |
210 glx_pixmap)); | |
211 | |
212 return tfp_picture; | |
213 } | |
214 | |
215 virtual void DestroyPicture(Picture* picture) OVERRIDE { | |
216 TFPPicture* tfp_picture = static_cast<TFPPicture*>(picture); | |
Pawel Osciak
2014/08/25 01:13:23
Please do not cast to children. I think you can so
| |
217 | |
218 // Unbind surface from texture and deallocate resources. | |
219 if (tfp_picture->glx_pixmap() && make_context_current_.Run()) { | |
220 glXReleaseTexImageEXT( | |
221 x_display_, tfp_picture->glx_pixmap(), GLX_FRONT_LEFT_EXT); | |
222 glXDestroyPixmap(x_display_, tfp_picture->glx_pixmap()); | |
223 } | |
224 | |
225 if (tfp_picture->x_pixmap()) | |
226 XFreePixmap(x_display_, tfp_picture->x_pixmap()); | |
227 XSync(x_display_, False); // Needed to work around buggy vdpau-driver. | |
228 } | |
229 | |
230 virtual VAStatus PutSurfaceIntoPicture(VADisplay va_display, | |
231 VASurfaceID va_surface_id, | |
232 Picture* picture) OVERRIDE { | |
233 TFPPicture* tfp_picture = static_cast<TFPPicture*>(picture); | |
234 const gfx::Size& size = tfp_picture->size(); | |
235 | |
236 if (!BindPicture(picture)) | |
237 return VA_STATUS_ERROR_OPERATION_FAILED; | |
238 | |
239 return vaPutSurface(va_display, | |
240 va_surface_id, | |
241 tfp_picture->x_pixmap(), | |
242 0, | |
243 0, | |
244 size.width(), | |
245 size.height(), | |
246 0, | |
247 0, | |
248 size.width(), | |
249 size.height(), | |
250 NULL, | |
251 0, | |
252 0); | |
253 } | |
254 | |
255 virtual VADisplay GetDisplay() OVERRIDE { | |
256 if (!va_display_) | |
257 va_display_ = vaGetDisplay(x_display_); | |
Pawel Osciak
2014/08/25 01:13:24
Why not just call this once in the constructor?
| |
258 return va_display_; | |
259 } | |
260 | |
261 virtual bool Initialize() OVERRIDE { | |
262 if (!make_context_current_.Run()) { | |
263 DVLOG(1) << "Couldn't make context current"; | |
264 return false; | |
265 } | |
266 | |
267 const int fbconfig_attr[] = { | |
268 GLX_DRAWABLE_TYPE, GLX_PIXMAP_BIT, | |
269 GLX_BIND_TO_TEXTURE_TARGETS_EXT, GLX_TEXTURE_2D_BIT_EXT, | |
270 GLX_BIND_TO_TEXTURE_RGB_EXT, GL_TRUE, | |
271 GLX_Y_INVERTED_EXT, GL_TRUE, | |
272 GL_NONE, | |
273 }; | |
274 | |
275 int num_fbconfigs; | |
276 scoped_ptr<GLXFBConfig, XFreeDeleter> glx_fb_configs(glXChooseFBConfig( | |
277 x_display_, DefaultScreen(x_display_), fbconfig_attr, &num_fbconfigs)); | |
278 | |
279 if (!glx_fb_configs) { | |
280 DVLOG(1) << "Couldn't get glx configs"; | |
281 return false; | |
282 } | |
283 if (!num_fbconfigs) { | |
284 DVLOG(1) << "Couldn't get at least a glx config"; | |
285 return false; | |
286 } | |
287 | |
288 fb_config_ = glx_fb_configs.get()[0]; | |
289 return true; | |
290 } | |
291 | |
292 virtual void Deinitialize() OVERRIDE { va_display_ = NULL; } | |
293 | |
294 private: | |
295 gfx::GLContextGLX* glx_context_; | |
296 base::Callback<bool(void)> make_context_current_; | |
297 | |
298 Display* x_display_; | |
299 GLXFBConfig fb_config_; | |
300 | |
301 VADisplay va_display_; | |
302 }; | |
303 | |
304 #else | |
305 | |
306 class VaapiWrapper::GbmPicture : public VaapiWrapper::Picture { | |
307 public: | |
308 GbmPicture(scoped_refptr<Backend> backend, | |
309 int32 picture_buffer_id, | |
310 uint32 texture_id, | |
311 const gfx::Size& size, | |
312 VASurfaceID va_surface, | |
313 scoped_refptr<ui::NativePixmap> pixmap, | |
314 scoped_refptr<gfx::GLImage> gl_image) | |
315 : Picture(picture_buffer_id, texture_id, size), | |
316 backend_(backend), | |
317 va_surface_(va_surface), | |
318 pixmap_(pixmap), | |
319 gl_image_(gl_image) {} | |
320 virtual ~GbmPicture() { backend_->DestroyPicture(this); } | |
321 | |
322 scoped_refptr<ui::NativePixmap> pixmap() const { return pixmap_; } | |
Pawel Osciak
2014/08/25 01:13:24
Unused?
| |
323 scoped_refptr<gfx::GLImage> gl_image() const { return gl_image_; } | |
324 VASurfaceID va_surface() const { return va_surface_; } | |
325 | |
326 private: | |
327 scoped_refptr<Backend> backend_; | |
328 VASurfaceID va_surface_; | |
329 scoped_refptr<ui::NativePixmap> pixmap_; | |
330 scoped_refptr<gfx::GLImage> gl_image_; | |
331 }; | |
332 | |
333 class VaapiWrapper::GbmBackend : public VaapiWrapper::Backend { | |
334 private: | |
335 virtual ~GbmBackend() {} | |
336 | |
337 public: | |
338 GbmBackend(const base::Callback<bool(void)> make_context_current) | |
339 : make_context_current_(make_context_current), | |
340 va_display_(NULL), | |
341 vpp_config_(VA_INVALID_ID), | |
342 vpp_context_(VA_INVALID_ID), | |
343 vpp_buffer_(VA_INVALID_ID) {} | |
344 | |
345 virtual VAStatus CreateSurfaces(VASurfaceID* surfaces, | |
346 uint32 num_surfaces, | |
347 const gfx::Size& size) OVERRIDE { | |
348 DeinitializeVpp(); | |
349 if (!InitializeVpp(size)) | |
350 return VA_STATUS_ERROR_OPERATION_FAILED; | |
351 | |
352 return vaCreateSurfaces(GetDisplay(), | |
353 VA_RT_FORMAT_YUV420, | |
354 size.width(), | |
355 size.height(), | |
356 surfaces, | |
357 num_surfaces, | |
358 NULL, | |
359 0); | |
360 } | |
361 | |
362 virtual linked_ptr<Picture> CreatePicture(int32 picture_buffer_id, | |
363 uint32 texture_id, | |
364 const gfx::Size& size) OVERRIDE { | |
365 VASurfaceAttrib va_attribs[2]; | |
366 VASurfaceAttribExternalBuffers va_attrib_extbuf; | |
367 | |
368 ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); | |
369 ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); | |
370 | |
371 scoped_refptr<ui::NativePixmap> pixmap = | |
372 factory->CreateNativePixmap(size, ui::SurfaceFactoryOzone::RGBA_8888); | |
373 unsigned long buffer_fd = pixmap->GetDmaBufFd(); | |
374 VASurfaceID va_surface; | |
375 | |
376 va_attrib_extbuf.pixel_format = VA_FOURCC_BGRX; | |
377 va_attrib_extbuf.width = size.width(); | |
378 va_attrib_extbuf.height = size.height(); | |
379 va_attrib_extbuf.data_size = size.height() * size.width() * 4; | |
380 va_attrib_extbuf.num_planes = 1; | |
381 va_attrib_extbuf.pitches[0] = 4 * size.width(); | |
382 va_attrib_extbuf.offsets[0] = 0; | |
383 va_attrib_extbuf.buffers = &buffer_fd; | |
384 va_attrib_extbuf.num_buffers = 1; | |
385 va_attrib_extbuf.flags = 0; | |
386 va_attrib_extbuf.private_data = NULL; | |
387 | |
388 va_attribs[0].type = VASurfaceAttribMemoryType; | |
389 va_attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE; | |
390 va_attribs[0].value.type = VAGenericValueTypeInteger; | |
391 va_attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; | |
392 | |
393 va_attribs[1].type = VASurfaceAttribExternalBufferDescriptor; | |
394 va_attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE; | |
395 va_attribs[1].value.type = VAGenericValueTypePointer; | |
396 va_attribs[1].value.value.p = &va_attrib_extbuf; | |
397 | |
398 VAStatus status = vaCreateSurfaces(GetDisplay(), | |
399 VA_RT_FORMAT_RGB32, | |
400 size.width(), | |
401 size.height(), | |
402 &va_surface, | |
403 1, | |
404 va_attribs, | |
405 2); | |
Pawel Osciak
2014/08/25 01:13:24
arraysize(va_attribs)
| |
406 | |
407 linked_ptr<GbmPicture> gbm_picture; | |
408 | |
409 if (status == VA_STATUS_SUCCESS) { | |
410 if (!make_context_current_.Run()) | |
411 return gbm_picture; | |
412 | |
413 EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; | |
414 gfx::GLImageEGL* gl_image = new gfx::GLImageEGL(size); | |
Pawel Osciak
2014/08/25 01:13:23
Could we have a scoper for this instead?
Where do
| |
415 gl_image->Initialize( | |
416 EGL_NATIVE_PIXMAP_KHR, pixmap->GetEGLClientBuffer(), attrs); | |
417 | |
418 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | |
Pawel Osciak
2014/08/25 01:13:23
Please don't use CHECK. This crashes the process.
| |
419 | |
420 gbm_picture.reset(new GbmPicture(this, | |
421 picture_buffer_id, | |
422 texture_id, | |
423 size, | |
424 va_surface, | |
425 pixmap, | |
426 gl_image)); | |
427 } | |
428 | |
429 return gbm_picture; | |
430 } | |
431 | |
432 virtual void DestroyPicture(Picture* picture) OVERRIDE { | |
433 GbmPicture* gbm_picture = static_cast<GbmPicture*>(picture); | |
434 VASurfaceID va_surface = gbm_picture->va_surface(); | |
435 | |
436 if (!make_context_current_.Run()) | |
437 return; | |
438 | |
439 // ReleaseTexImage on a GLImageEGL does nothing, do deassociate | |
440 // the renderer texture from the image, just set the storage of | |
441 // that texture to NULL | |
442 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, | |
443 gbm_picture->texture_id()); | |
444 glTexImage2D(GL_TEXTURE_2D, | |
445 0, | |
446 GL_RGBA, | |
447 gbm_picture->size().width(), | |
448 gbm_picture->size().height(), | |
449 0, | |
450 GL_RGBA, | |
451 GL_UNSIGNED_BYTE, | |
452 NULL); | |
453 | |
454 gbm_picture->gl_image()->Destroy(true); | |
455 | |
456 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | |
457 | |
458 vaDestroySurfaces(GetDisplay(), &va_surface, 1); | |
459 } | |
460 | |
461 virtual VAStatus PutSurfaceIntoPicture(VADisplay va_display, | |
462 VASurfaceID va_surface_id, | |
463 Picture* picture) OVERRIDE { | |
464 GbmPicture* gbm_picture = static_cast<GbmPicture*>(picture); | |
Pawel Osciak
2014/08/25 01:13:23
We cannot cast to child. But you don't really need
| |
465 VAProcPipelineParameterBuffer* pipeline_param; | |
466 VAStatus status; | |
467 | |
468 status = vaMapBuffer(GetDisplay(), vpp_buffer_, (void**)&pipeline_param); | |
469 if (status != VA_STATUS_SUCCESS) | |
470 return status; | |
471 | |
472 memset(pipeline_param, 0, sizeof *pipeline_param); | |
473 | |
474 pipeline_param->surface = va_surface_id; | |
475 pipeline_param->surface_color_standard = VAProcColorStandardNone; | |
476 | |
477 pipeline_param->output_background_color = 0xff000000; | |
478 pipeline_param->output_color_standard = VAProcColorStandardNone; | |
marcheu
2014/08/29 04:01:09
isn't this going to differ from the X11 path? IIRC
llandwerlin-old
2014/08/29 16:30:55
As far as I can tell the intel driver ignores this
| |
479 | |
480 status = vaUnmapBuffer(GetDisplay(), vpp_buffer_); | |
481 if (status != VA_STATUS_SUCCESS) | |
482 return status; | |
483 | |
484 status = | |
485 vaBeginPicture(GetDisplay(), vpp_context_, gbm_picture->va_surface()); | |
486 if (status != VA_STATUS_SUCCESS) | |
487 return status; | |
488 | |
489 status = vaRenderPicture(GetDisplay(), vpp_context_, &vpp_buffer_, 1); | |
490 if (status != VA_STATUS_SUCCESS) | |
491 return status; | |
492 | |
493 status = vaEndPicture(GetDisplay(), vpp_context_); | |
494 if (status != VA_STATUS_SUCCESS) | |
495 return status; | |
496 | |
497 if (!make_context_current_.Run()) | |
498 return VA_STATUS_ERROR_OPERATION_FAILED; | |
499 | |
500 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, | |
501 gbm_picture->texture_id()); | |
502 gbm_picture->gl_image()->BindTexImage(GL_TEXTURE_2D); | |
503 | |
504 CHECK_EQ(static_cast<int>(glGetError()), GL_NO_ERROR); | |
505 | |
506 return VA_STATUS_SUCCESS; | |
507 } | |
508 | |
509 virtual VADisplay GetDisplay() OVERRIDE { | |
510 if (!va_display_) { | |
511 ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); | |
512 ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); | |
513 gbm_device* device = | |
514 reinterpret_cast<gbm_device*>(factory->GetNativeDisplay()); | |
515 | |
516 va_display_ = vaGetDisplayDRM(gbm_device_get_fd(device)); | |
517 } | |
518 | |
519 return va_display_; | |
520 } | |
521 | |
522 virtual bool Initialize() OVERRIDE { return true; } | |
523 | |
524 virtual void Deinitialize() OVERRIDE { | |
525 DeinitializeVpp(); | |
526 va_display_ = NULL; | |
527 } | |
528 | |
529 private: | |
530 bool InitializeVpp(const gfx::Size& size) { | |
531 VAStatus status; | |
532 | |
533 status = vaCreateConfig(GetDisplay(), | |
534 VAProfileNone, | |
535 VAEntrypointVideoProc, | |
536 NULL, | |
537 0, | |
538 &vpp_config_); | |
539 if (status != VA_STATUS_SUCCESS) { | |
540 DVLOG(1) << "Couldn't create VPP config"; | |
541 return false; | |
542 } | |
543 | |
544 status = vaCreateContext(GetDisplay(), | |
545 vpp_config_, | |
546 size.width(), | |
547 size.height(), | |
548 0, | |
549 NULL, | |
550 0, | |
551 &vpp_context_); | |
552 if (status != VA_STATUS_SUCCESS) { | |
553 DVLOG(1) << "Couldn't create VPP context"; | |
554 DeinitializeVpp(); | |
Pawel Osciak
2014/08/25 01:13:23
Isn't this called anyway on destruction via Deinit
| |
555 return false; | |
556 } | |
557 | |
558 status = vaCreateBuffer(GetDisplay(), | |
559 vpp_context_, | |
560 VAProcPipelineParameterBufferType, | |
561 sizeof(VAProcPipelineParameterBuffer), | |
562 1, | |
563 NULL, | |
564 &vpp_buffer_); | |
565 if (status != VA_STATUS_SUCCESS) { | |
566 DVLOG(1) << "Couldn't create VPP pipeline buffer"; | |
567 DeinitializeVpp(); | |
568 return false; | |
569 } | |
570 | |
571 return true; | |
572 } | |
573 | |
574 bool IsVppInitialized() { return vpp_buffer_ != VA_INVALID_ID; } | |
575 | |
576 void DeinitializeVpp() { | |
577 if (vpp_buffer_ != VA_INVALID_ID) { | |
578 vaDestroyBuffer(GetDisplay(), vpp_buffer_); | |
579 vpp_buffer_ = VA_INVALID_ID; | |
580 } | |
581 if (vpp_context_ != VA_INVALID_ID) { | |
582 vaDestroyContext(GetDisplay(), vpp_context_); | |
583 vpp_context_ = VA_INVALID_ID; | |
584 } | |
585 if (vpp_config_ != VA_INVALID_ID) { | |
586 vaDestroyConfig(GetDisplay(), vpp_config_); | |
587 vpp_config_ = VA_INVALID_ID; | |
588 } | |
589 } | |
590 | |
591 base::Callback<bool(void)> make_context_current_; | |
592 | |
593 VADisplay va_display_; | |
594 | |
595 VAConfigID vpp_config_; | |
596 VAContextID vpp_context_; | |
597 VABufferID vpp_buffer_; | |
598 }; | |
599 #endif // USE_X11 | |
600 | |
601 scoped_refptr<VaapiWrapper::Backend> VaapiWrapper::Backend::Create( | |
602 gfx::GLContext* gl_context, | |
603 const base::Callback<bool(void)> make_context_current) { | |
604 scoped_refptr<Backend> backend; | |
605 | |
606 #if defined(USE_X11) | |
607 backend = new X11Backend(static_cast<gfx::GLContextGLX*>(gl_context), | |
608 make_context_current); | |
609 #else | |
610 backend = new GbmBackend(make_context_current); | |
611 #endif // USE_X11 | |
612 | |
613 if (!backend->Initialize()) | |
614 backend = NULL; | |
615 | |
616 return backend; | |
617 } | |
618 | |
48 // Config attributes common for both encode and decode. | 619 // Config attributes common for both encode and decode. |
49 static const VAConfigAttrib kCommonVAConfigAttribs[] = { | 620 static const VAConfigAttrib kCommonVAConfigAttribs[] = { |
50 {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420}, | 621 {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420}, |
51 }; | 622 }; |
52 | 623 |
53 // Attributes required for encode. | 624 // Attributes required for encode. |
54 static const VAConfigAttrib kEncodeVAConfigAttribs[] = { | 625 static const VAConfigAttrib kEncodeVAConfigAttribs[] = { |
55 {VAConfigAttribRateControl, VA_RC_CBR}, | 626 {VAConfigAttribRateControl, VA_RC_CBR}, |
56 {VAConfigAttribEncPackedHeaders, | 627 {VAConfigAttribEncPackedHeaders, |
57 VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE}, | 628 VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE}, |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
106 : va_surface_id_(va_surface_id), | 677 : va_surface_id_(va_surface_id), |
107 release_cb_(release_cb) { | 678 release_cb_(release_cb) { |
108 DCHECK(!release_cb_.is_null()); | 679 DCHECK(!release_cb_.is_null()); |
109 } | 680 } |
110 | 681 |
111 VASurface::~VASurface() { | 682 VASurface::~VASurface() { |
112 release_cb_.Run(va_surface_id_); | 683 release_cb_.Run(va_surface_id_); |
113 } | 684 } |
114 | 685 |
115 VaapiWrapper::VaapiWrapper() | 686 VaapiWrapper::VaapiWrapper() |
116 : va_display_(NULL), | 687 : va_config_id_(VA_INVALID_ID), va_context_id_(VA_INVALID_ID) { |
117 va_config_id_(VA_INVALID_ID), | |
118 va_context_id_(VA_INVALID_ID) { | |
119 } | 688 } |
120 | 689 |
121 VaapiWrapper::~VaapiWrapper() { | 690 VaapiWrapper::~VaapiWrapper() { |
122 DestroyPendingBuffers(); | 691 DestroyPendingBuffers(); |
123 DestroyCodedBuffers(); | 692 DestroyCodedBuffers(); |
124 DestroySurfaces(); | 693 DestroySurfaces(); |
125 Deinitialize(); | 694 Deinitialize(); |
126 } | 695 } |
127 | 696 |
128 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( | 697 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( |
129 CodecMode mode, | 698 CodecMode mode, |
130 media::VideoCodecProfile profile, | 699 media::VideoCodecProfile profile, |
131 Display* x_display, | 700 gfx::GLContext* gl_context, |
701 const base::Callback<bool(void)>& make_context_current, | |
132 const base::Closure& report_error_to_uma_cb) { | 702 const base::Closure& report_error_to_uma_cb) { |
133 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | 703 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); |
134 | 704 |
135 if (!vaapi_wrapper->Initialize( | 705 if (!vaapi_wrapper->Initialize(mode, |
136 mode, profile, x_display, report_error_to_uma_cb)) | 706 profile, |
707 gl_context, | |
708 make_context_current, | |
709 report_error_to_uma_cb)) | |
137 vaapi_wrapper.reset(); | 710 vaapi_wrapper.reset(); |
138 | 711 |
139 return vaapi_wrapper.Pass(); | 712 return vaapi_wrapper.Pass(); |
140 } | 713 } |
141 | 714 |
142 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { | 715 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { |
143 VADisplayAttribute item = {VADisplayAttribRenderMode, | 716 VADisplayAttribute item = {VADisplayAttribRenderMode, |
144 1, // At least support '_LOCAL_OVERLAY'. | 717 1, // At least support '_LOCAL_OVERLAY'. |
145 -1, // The maximum possible support 'ALL'. | 718 -1, // The maximum possible support 'ALL'. |
146 VA_RENDER_MODE_LOCAL_GPU, | 719 VA_RENDER_MODE_LOCAL_GPU, |
147 VA_DISPLAY_ATTRIB_SETTABLE}; | 720 VA_DISPLAY_ATTRIB_SETTABLE}; |
148 | 721 |
149 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); | 722 VAStatus va_res = vaSetDisplayAttributes(backend_->GetDisplay(), &item, 1); |
150 if (va_res != VA_STATUS_SUCCESS) | 723 if (va_res != VA_STATUS_SUCCESS) |
151 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; | 724 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; |
152 } | 725 } |
153 | 726 |
154 bool VaapiWrapper::Initialize(CodecMode mode, | 727 bool VaapiWrapper::Initialize( |
155 media::VideoCodecProfile profile, | 728 CodecMode mode, |
156 Display* x_display, | 729 media::VideoCodecProfile profile, |
157 const base::Closure& report_error_to_uma_cb) { | 730 gfx::GLContext* gl_context, |
731 const base::Callback<bool(void)>& make_context_current, | |
732 const base::Closure& report_error_to_uma_cb) { | |
158 static bool vaapi_functions_initialized = PostSandboxInitialization(); | 733 static bool vaapi_functions_initialized = PostSandboxInitialization(); |
159 if (!vaapi_functions_initialized) { | 734 if (!vaapi_functions_initialized) { |
160 DVLOG(1) << "Failed to initialize VAAPI libs"; | 735 DVLOG(1) << "Failed to initialize VAAPI libs"; |
161 return false; | 736 return false; |
162 } | 737 } |
163 | 738 |
164 report_error_to_uma_cb_ = report_error_to_uma_cb; | 739 report_error_to_uma_cb_ = report_error_to_uma_cb; |
165 | 740 |
166 base::AutoLock auto_lock(va_lock_); | 741 base::AutoLock auto_lock(va_lock_); |
167 | 742 |
168 va_display_ = vaGetDisplay(x_display); | 743 backend_ = VaapiWrapper::Backend::Create(gl_context, make_context_current); |
Pawel Osciak
2014/08/25 01:13:24
Could we keep va_display_ in VaapiWrapper? We woul
| |
169 if (!vaDisplayIsValid(va_display_)) { | 744 |
745 if (!backend_.get()) { | |
746 DVLOG(1) << "Failed to initialize VAAPI backend"; | |
747 return false; | |
748 } | |
749 | |
750 // va_display_ = backend_->GetDisplay(); | |
751 if (!vaDisplayIsValid(backend_->GetDisplay())) { | |
170 DVLOG(1) << "Could not get a valid VA display"; | 752 DVLOG(1) << "Could not get a valid VA display"; |
171 return false; | 753 return false; |
172 } | 754 } |
173 | 755 |
174 VAStatus va_res = vaInitialize(va_display_, &major_version_, &minor_version_); | 756 VAStatus va_res = |
757 vaInitialize(backend_->GetDisplay(), &major_version_, &minor_version_); | |
175 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); | 758 VA_SUCCESS_OR_RETURN(va_res, "vaInitialize failed", false); |
176 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; | 759 DVLOG(1) << "VAAPI version: " << major_version_ << "." << minor_version_; |
177 | 760 |
178 if (VAAPIVersionLessThan(0, 34)) { | 761 if (VAAPIVersionLessThan(0, 34)) { |
179 DVLOG(1) << "VAAPI version < 0.34 is not supported."; | 762 DVLOG(1) << "VAAPI version < 0.34 is not supported."; |
180 return false; | 763 return false; |
181 } | 764 } |
182 | 765 |
183 // Query the driver for supported profiles. | 766 // Query the driver for supported profiles. |
184 int max_profiles = vaMaxNumProfiles(va_display_); | 767 int max_profiles = vaMaxNumProfiles(backend_->GetDisplay()); |
185 std::vector<VAProfile> supported_profiles( | 768 std::vector<VAProfile> supported_profiles( |
186 base::checked_cast<size_t>(max_profiles)); | 769 base::checked_cast<size_t>(max_profiles)); |
187 | 770 |
188 int num_supported_profiles; | 771 int num_supported_profiles; |
189 va_res = vaQueryConfigProfiles( | 772 va_res = vaQueryConfigProfiles( |
190 va_display_, &supported_profiles[0], &num_supported_profiles); | 773 backend_->GetDisplay(), &supported_profiles[0], &num_supported_profiles); |
191 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false); | 774 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigProfiles failed", false); |
192 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { | 775 if (num_supported_profiles < 0 || num_supported_profiles > max_profiles) { |
193 DVLOG(1) << "vaQueryConfigProfiles returned: " << num_supported_profiles; | 776 DVLOG(1) << "vaQueryConfigProfiles returned: " << num_supported_profiles; |
194 return false; | 777 return false; |
195 } | 778 } |
196 | 779 |
197 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); | 780 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); |
198 | 781 |
199 VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles); | 782 VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles); |
200 if (va_profile == VAProfileNone) { | 783 if (va_profile == VAProfileNone) { |
201 DVLOG(1) << "Unsupported profile"; | 784 DVLOG(1) << "Unsupported profile : " << profile; |
202 return false; | 785 return false; |
203 } | 786 } |
204 | 787 |
205 // Query the driver for supported entrypoints. | 788 // Query the driver for supported entrypoints. |
206 int max_entrypoints = vaMaxNumEntrypoints(va_display_); | 789 int max_entrypoints = vaMaxNumEntrypoints(backend_->GetDisplay()); |
207 std::vector<VAEntrypoint> supported_entrypoints( | 790 std::vector<VAEntrypoint> supported_entrypoints( |
208 base::checked_cast<size_t>(max_entrypoints)); | 791 base::checked_cast<size_t>(max_entrypoints)); |
209 | 792 |
210 int num_supported_entrypoints; | 793 int num_supported_entrypoints; |
211 va_res = vaQueryConfigEntrypoints(va_display_, | 794 va_res = vaQueryConfigEntrypoints(backend_->GetDisplay(), |
212 va_profile, | 795 va_profile, |
213 &supported_entrypoints[0], | 796 &supported_entrypoints[0], |
214 &num_supported_entrypoints); | 797 &num_supported_entrypoints); |
215 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false); | 798 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false); |
216 if (num_supported_entrypoints < 0 || | 799 if (num_supported_entrypoints < 0 || |
217 num_supported_entrypoints > max_entrypoints) { | 800 num_supported_entrypoints > max_entrypoints) { |
218 DVLOG(1) << "vaQueryConfigEntrypoints returned: " | 801 DVLOG(1) << "vaQueryConfigEntrypoints returned: " |
219 << num_supported_entrypoints; | 802 << num_supported_entrypoints; |
220 return false; | 803 return false; |
221 } | 804 } |
(...skipping 18 matching lines...) Expand all Loading... | |
240 required_attribs.insert( | 823 required_attribs.insert( |
241 required_attribs.end(), | 824 required_attribs.end(), |
242 kEncodeVAConfigAttribs, | 825 kEncodeVAConfigAttribs, |
243 kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs)); | 826 kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs)); |
244 } | 827 } |
245 | 828 |
246 std::vector<VAConfigAttrib> attribs = required_attribs; | 829 std::vector<VAConfigAttrib> attribs = required_attribs; |
247 for (size_t i = 0; i < required_attribs.size(); ++i) | 830 for (size_t i = 0; i < required_attribs.size(); ++i) |
248 attribs[i].value = 0; | 831 attribs[i].value = 0; |
249 | 832 |
250 va_res = vaGetConfigAttributes( | 833 va_res = vaGetConfigAttributes(backend_->GetDisplay(), |
251 va_display_, va_profile, entrypoint, &attribs[0], attribs.size()); | 834 va_profile, |
835 entrypoint, | |
836 &attribs[0], | |
837 attribs.size()); | |
252 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); | 838 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); |
253 | 839 |
254 for (size_t i = 0; i < required_attribs.size(); ++i) { | 840 for (size_t i = 0; i < required_attribs.size(); ++i) { |
255 if (attribs[i].type != required_attribs[i].type || | 841 if (attribs[i].type != required_attribs[i].type || |
256 (attribs[i].value & required_attribs[i].value) != | 842 (attribs[i].value & required_attribs[i].value) != |
257 required_attribs[i].value) { | 843 required_attribs[i].value) { |
258 DVLOG(1) << "Unsupported value " << required_attribs[i].value | 844 DVLOG(1) << "Unsupported value " << required_attribs[i].value |
259 << " for attribute type " << required_attribs[i].type; | 845 << " for attribute type " << required_attribs[i].type; |
260 return false; | 846 return false; |
261 } | 847 } |
262 } | 848 } |
263 | 849 |
264 TryToSetVADisplayAttributeToLocalGPU(); | 850 TryToSetVADisplayAttributeToLocalGPU(); |
265 | 851 |
266 va_res = vaCreateConfig(va_display_, | 852 va_res = vaCreateConfig(backend_->GetDisplay(), |
267 va_profile, | 853 va_profile, |
268 entrypoint, | 854 entrypoint, |
269 &required_attribs[0], | 855 &required_attribs[0], |
270 required_attribs.size(), | 856 required_attribs.size(), |
271 &va_config_id_); | 857 &va_config_id_); |
272 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); | 858 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); |
273 | 859 |
274 return true; | 860 return true; |
275 } | 861 } |
276 | 862 |
277 void VaapiWrapper::Deinitialize() { | 863 void VaapiWrapper::Deinitialize() { |
278 base::AutoLock auto_lock(va_lock_); | 864 base::AutoLock auto_lock(va_lock_); |
279 | 865 |
280 if (va_config_id_ != VA_INVALID_ID) { | 866 if (va_config_id_ != VA_INVALID_ID) { |
281 VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_); | 867 VAStatus va_res = vaDestroyConfig(backend_->GetDisplay(), va_config_id_); |
282 VA_LOG_ON_ERROR(va_res, "vaDestroyConfig failed"); | 868 VA_LOG_ON_ERROR(va_res, "vaDestroyConfig failed"); |
283 } | 869 } |
284 | 870 |
285 if (va_display_) { | 871 if (backend_->GetDisplay()) { |
286 VAStatus va_res = vaTerminate(va_display_); | 872 VAStatus va_res = vaTerminate(backend_->GetDisplay()); |
287 VA_LOG_ON_ERROR(va_res, "vaTerminate failed"); | 873 VA_LOG_ON_ERROR(va_res, "vaTerminate failed"); |
288 } | 874 } |
289 | 875 |
290 va_config_id_ = VA_INVALID_ID; | 876 va_config_id_ = VA_INVALID_ID; |
291 va_display_ = NULL; | 877 backend_ = NULL; |
292 } | 878 } |
293 | 879 |
294 bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) { | 880 bool VaapiWrapper::VAAPIVersionLessThan(int major, int minor) { |
295 return (major_version_ < major) || | 881 return (major_version_ < major) || |
296 (major_version_ == major && minor_version_ < minor); | 882 (major_version_ == major && minor_version_ < minor); |
297 } | 883 } |
298 | 884 |
299 bool VaapiWrapper::CreateSurfaces(gfx::Size size, | 885 bool VaapiWrapper::CreateSurfaces(const gfx::Size& size, |
300 size_t num_surfaces, | 886 size_t num_surfaces, |
301 std::vector<VASurfaceID>* va_surfaces) { | 887 std::vector<VASurfaceID>* va_surfaces) { |
302 base::AutoLock auto_lock(va_lock_); | 888 base::AutoLock auto_lock(va_lock_); |
303 DVLOG(2) << "Creating " << num_surfaces << " surfaces"; | 889 DVLOG(2) << "Creating " << num_surfaces << " surfaces"; |
304 | 890 |
305 DCHECK(va_surfaces->empty()); | 891 DCHECK(va_surfaces->empty()); |
306 DCHECK(va_surface_ids_.empty()); | 892 DCHECK(va_surface_ids_.empty()); |
307 va_surface_ids_.resize(num_surfaces); | 893 va_surface_ids_.resize(num_surfaces); |
308 | 894 |
309 // Allocate surfaces in driver. | 895 // Allocate surfaces in driver. |
310 VAStatus va_res = vaCreateSurfaces(va_display_, | 896 VAStatus va_res = backend_->CreateSurfaces( |
311 VA_RT_FORMAT_YUV420, | 897 &va_surface_ids_[0], va_surface_ids_.size(), size); |
312 size.width(), size.height(), | |
313 &va_surface_ids_[0], | |
314 va_surface_ids_.size(), | |
315 NULL, 0); | |
316 | |
317 VA_LOG_ON_ERROR(va_res, "vaCreateSurfaces failed"); | 898 VA_LOG_ON_ERROR(va_res, "vaCreateSurfaces failed"); |
318 if (va_res != VA_STATUS_SUCCESS) { | 899 if (va_res != VA_STATUS_SUCCESS) { |
319 va_surface_ids_.clear(); | 900 va_surface_ids_.clear(); |
320 return false; | 901 return false; |
321 } | 902 } |
322 | 903 |
323 // And create a context associated with them. | 904 // And create a context associated with them. |
324 va_res = vaCreateContext(va_display_, va_config_id_, | 905 va_res = vaCreateContext(backend_->GetDisplay(), |
325 size.width(), size.height(), VA_PROGRESSIVE, | 906 va_config_id_, |
326 &va_surface_ids_[0], va_surface_ids_.size(), | 907 size.width(), |
908 size.height(), | |
909 VA_PROGRESSIVE, | |
910 &va_surface_ids_[0], | |
911 va_surface_ids_.size(), | |
327 &va_context_id_); | 912 &va_context_id_); |
328 | 913 |
329 VA_LOG_ON_ERROR(va_res, "vaCreateContext failed"); | 914 VA_LOG_ON_ERROR(va_res, "vaCreateContext failed"); |
330 if (va_res != VA_STATUS_SUCCESS) { | 915 if (va_res != VA_STATUS_SUCCESS) { |
331 DestroySurfaces(); | 916 DestroySurfaces(); |
332 return false; | 917 return false; |
333 } | 918 } |
334 | 919 |
335 *va_surfaces = va_surface_ids_; | 920 *va_surfaces = va_surface_ids_; |
336 return true; | 921 return true; |
337 } | 922 } |
338 | 923 |
339 void VaapiWrapper::DestroySurfaces() { | 924 void VaapiWrapper::DestroySurfaces() { |
340 base::AutoLock auto_lock(va_lock_); | 925 base::AutoLock auto_lock(va_lock_); |
341 DVLOG(2) << "Destroying " << va_surface_ids_.size() << " surfaces"; | 926 DVLOG(2) << "Destroying " << va_surface_ids_.size() << " surfaces"; |
342 | 927 |
343 if (va_context_id_ != VA_INVALID_ID) { | 928 if (va_context_id_ != VA_INVALID_ID) { |
344 VAStatus va_res = vaDestroyContext(va_display_, va_context_id_); | 929 VAStatus va_res = vaDestroyContext(backend_->GetDisplay(), va_context_id_); |
345 VA_LOG_ON_ERROR(va_res, "vaDestroyContext failed"); | 930 VA_LOG_ON_ERROR(va_res, "vaDestroyContext failed"); |
346 } | 931 } |
347 | 932 |
348 if (!va_surface_ids_.empty()) { | 933 if (!va_surface_ids_.empty()) { |
349 VAStatus va_res = vaDestroySurfaces(va_display_, &va_surface_ids_[0], | 934 VAStatus va_res = vaDestroySurfaces( |
350 va_surface_ids_.size()); | 935 backend_->GetDisplay(), &va_surface_ids_[0], va_surface_ids_.size()); |
351 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces failed"); | 936 VA_LOG_ON_ERROR(va_res, "vaDestroySurfaces failed"); |
352 } | 937 } |
353 | 938 |
354 va_surface_ids_.clear(); | 939 va_surface_ids_.clear(); |
355 va_context_id_ = VA_INVALID_ID; | 940 va_context_id_ = VA_INVALID_ID; |
356 } | 941 } |
357 | 942 |
943 linked_ptr<VaapiWrapper::Picture> VaapiWrapper::CreatePicture( | |
944 int32 picture_buffer_id, | |
945 uint32 texture_id, | |
946 gfx::Size size) { | |
947 return backend_->CreatePicture(picture_buffer_id, texture_id, size); | |
948 } | |
949 | |
358 bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, | 950 bool VaapiWrapper::SubmitBuffer(VABufferType va_buffer_type, |
359 size_t size, | 951 size_t size, |
360 void* buffer) { | 952 void* buffer) { |
361 base::AutoLock auto_lock(va_lock_); | 953 base::AutoLock auto_lock(va_lock_); |
362 | 954 |
363 VABufferID buffer_id; | 955 VABufferID buffer_id; |
364 VAStatus va_res = vaCreateBuffer(va_display_, va_context_id_, | 956 VAStatus va_res = vaCreateBuffer(backend_->GetDisplay(), |
365 va_buffer_type, size, | 957 va_context_id_, |
366 1, buffer, &buffer_id); | 958 va_buffer_type, |
959 size, | |
960 1, | |
961 buffer, | |
962 &buffer_id); | |
367 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false); | 963 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false); |
368 | 964 |
369 switch (va_buffer_type) { | 965 switch (va_buffer_type) { |
370 case VASliceParameterBufferType: | 966 case VASliceParameterBufferType: |
371 case VASliceDataBufferType: | 967 case VASliceDataBufferType: |
372 case VAEncSliceParameterBufferType: | 968 case VAEncSliceParameterBufferType: |
373 pending_slice_bufs_.push_back(buffer_id); | 969 pending_slice_bufs_.push_back(buffer_id); |
374 break; | 970 break; |
375 | 971 |
376 default: | 972 default: |
377 pending_va_bufs_.push_back(buffer_id); | 973 pending_va_bufs_.push_back(buffer_id); |
378 break; | 974 break; |
379 } | 975 } |
380 | 976 |
381 return true; | 977 return true; |
382 } | 978 } |
383 | 979 |
384 bool VaapiWrapper::SubmitVAEncMiscParamBuffer( | 980 bool VaapiWrapper::SubmitVAEncMiscParamBuffer( |
385 VAEncMiscParameterType misc_param_type, | 981 VAEncMiscParameterType misc_param_type, |
386 size_t size, | 982 size_t size, |
387 void* buffer) { | 983 void* buffer) { |
388 base::AutoLock auto_lock(va_lock_); | 984 base::AutoLock auto_lock(va_lock_); |
389 | 985 |
390 VABufferID buffer_id; | 986 VABufferID buffer_id; |
391 VAStatus va_res = vaCreateBuffer(va_display_, | 987 VAStatus va_res = vaCreateBuffer(backend_->GetDisplay(), |
392 va_context_id_, | 988 va_context_id_, |
393 VAEncMiscParameterBufferType, | 989 VAEncMiscParameterBufferType, |
394 sizeof(VAEncMiscParameterBuffer) + size, | 990 sizeof(VAEncMiscParameterBuffer) + size, |
395 1, | 991 1, |
396 NULL, | 992 NULL, |
397 &buffer_id); | 993 &buffer_id); |
398 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false); | 994 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false); |
399 | 995 |
400 void* data_ptr = NULL; | 996 void* data_ptr = NULL; |
401 va_res = vaMapBuffer(va_display_, buffer_id, &data_ptr); | 997 va_res = vaMapBuffer(backend_->GetDisplay(), buffer_id, &data_ptr); |
402 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); | 998 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); |
403 if (va_res != VA_STATUS_SUCCESS) { | 999 if (va_res != VA_STATUS_SUCCESS) { |
404 vaDestroyBuffer(va_display_, buffer_id); | 1000 vaDestroyBuffer(backend_->GetDisplay(), buffer_id); |
405 return false; | 1001 return false; |
406 } | 1002 } |
407 | 1003 |
408 DCHECK(data_ptr); | 1004 DCHECK(data_ptr); |
409 | 1005 |
410 VAEncMiscParameterBuffer* misc_param = | 1006 VAEncMiscParameterBuffer* misc_param = |
411 reinterpret_cast<VAEncMiscParameterBuffer*>(data_ptr); | 1007 reinterpret_cast<VAEncMiscParameterBuffer*>(data_ptr); |
412 misc_param->type = misc_param_type; | 1008 misc_param->type = misc_param_type; |
413 memcpy(misc_param->data, buffer, size); | 1009 memcpy(misc_param->data, buffer, size); |
414 va_res = vaUnmapBuffer(va_display_, buffer_id); | 1010 va_res = vaUnmapBuffer(backend_->GetDisplay(), buffer_id); |
415 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); | 1011 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); |
416 | 1012 |
417 pending_va_bufs_.push_back(buffer_id); | 1013 pending_va_bufs_.push_back(buffer_id); |
418 return true; | 1014 return true; |
419 } | 1015 } |
420 | 1016 |
421 void VaapiWrapper::DestroyPendingBuffers() { | 1017 void VaapiWrapper::DestroyPendingBuffers() { |
422 base::AutoLock auto_lock(va_lock_); | 1018 base::AutoLock auto_lock(va_lock_); |
423 | 1019 |
424 for (size_t i = 0; i < pending_va_bufs_.size(); ++i) { | 1020 for (size_t i = 0; i < pending_va_bufs_.size(); ++i) { |
425 VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_bufs_[i]); | 1021 VAStatus va_res = |
1022 vaDestroyBuffer(backend_->GetDisplay(), pending_va_bufs_[i]); | |
426 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 1023 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
427 } | 1024 } |
428 | 1025 |
429 for (size_t i = 0; i < pending_slice_bufs_.size(); ++i) { | 1026 for (size_t i = 0; i < pending_slice_bufs_.size(); ++i) { |
430 VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_bufs_[i]); | 1027 VAStatus va_res = |
1028 vaDestroyBuffer(backend_->GetDisplay(), pending_slice_bufs_[i]); | |
431 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 1029 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
432 } | 1030 } |
433 | 1031 |
434 pending_va_bufs_.clear(); | 1032 pending_va_bufs_.clear(); |
435 pending_slice_bufs_.clear(); | 1033 pending_slice_bufs_.clear(); |
436 } | 1034 } |
437 | 1035 |
438 bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) { | 1036 bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) { |
439 base::AutoLock auto_lock(va_lock_); | 1037 base::AutoLock auto_lock(va_lock_); |
440 VAStatus va_res = vaCreateBuffer(va_display_, | 1038 VAStatus va_res = vaCreateBuffer(backend_->GetDisplay(), |
441 va_context_id_, | 1039 va_context_id_, |
442 VAEncCodedBufferType, | 1040 VAEncCodedBufferType, |
443 size, | 1041 size, |
444 1, | 1042 1, |
445 NULL, | 1043 NULL, |
446 buffer_id); | 1044 buffer_id); |
447 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a coded buffer", false); | 1045 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a coded buffer", false); |
448 | 1046 |
449 DCHECK(coded_buffers_.insert(*buffer_id).second); | 1047 DCHECK(coded_buffers_.insert(*buffer_id).second); |
450 return true; | 1048 return true; |
451 } | 1049 } |
452 | 1050 |
453 void VaapiWrapper::DestroyCodedBuffers() { | 1051 void VaapiWrapper::DestroyCodedBuffers() { |
454 base::AutoLock auto_lock(va_lock_); | 1052 base::AutoLock auto_lock(va_lock_); |
455 | 1053 |
456 for (std::set<VABufferID>::const_iterator iter = coded_buffers_.begin(); | 1054 for (std::set<VABufferID>::const_iterator iter = coded_buffers_.begin(); |
457 iter != coded_buffers_.end(); | 1055 iter != coded_buffers_.end(); |
458 ++iter) { | 1056 ++iter) { |
459 VAStatus va_res = vaDestroyBuffer(va_display_, *iter); | 1057 VAStatus va_res = vaDestroyBuffer(backend_->GetDisplay(), *iter); |
460 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 1058 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
461 } | 1059 } |
462 | 1060 |
463 coded_buffers_.clear(); | 1061 coded_buffers_.clear(); |
464 } | 1062 } |
465 | 1063 |
466 bool VaapiWrapper::Execute(VASurfaceID va_surface_id) { | 1064 bool VaapiWrapper::Execute(VASurfaceID va_surface_id) { |
467 base::AutoLock auto_lock(va_lock_); | 1065 base::AutoLock auto_lock(va_lock_); |
468 | 1066 |
469 DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size(); | 1067 DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size(); |
470 DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size(); | 1068 DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size(); |
471 DVLOG(4) << "Target VA surface " << va_surface_id; | 1069 DVLOG(4) << "Target VA surface " << va_surface_id; |
472 | 1070 |
473 // Get ready to execute for given surface. | 1071 // Get ready to execute for given surface. |
474 VAStatus va_res = vaBeginPicture(va_display_, va_context_id_, | 1072 VAStatus va_res = |
475 va_surface_id); | 1073 vaBeginPicture(backend_->GetDisplay(), va_context_id_, va_surface_id); |
476 VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false); | 1074 VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false); |
477 | 1075 |
478 if (pending_va_bufs_.size() > 0) { | 1076 if (pending_va_bufs_.size() > 0) { |
479 // Commit parameter and slice buffers. | 1077 // Commit parameter and slice buffers. |
480 va_res = vaRenderPicture(va_display_, | 1078 va_res = vaRenderPicture(backend_->GetDisplay(), |
481 va_context_id_, | 1079 va_context_id_, |
482 &pending_va_bufs_[0], | 1080 &pending_va_bufs_[0], |
483 pending_va_bufs_.size()); | 1081 pending_va_bufs_.size()); |
484 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for va_bufs failed", false); | 1082 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for va_bufs failed", false); |
485 } | 1083 } |
486 | 1084 |
487 if (pending_slice_bufs_.size() > 0) { | 1085 if (pending_slice_bufs_.size() > 0) { |
488 va_res = vaRenderPicture(va_display_, | 1086 va_res = vaRenderPicture(backend_->GetDisplay(), |
489 va_context_id_, | 1087 va_context_id_, |
490 &pending_slice_bufs_[0], | 1088 &pending_slice_bufs_[0], |
491 pending_slice_bufs_.size()); | 1089 pending_slice_bufs_.size()); |
492 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for slices failed", false); | 1090 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for slices failed", false); |
493 } | 1091 } |
494 | 1092 |
495 // Instruct HW codec to start processing committed buffers. | 1093 // Instruct HW codec to start processing committed buffers. |
496 // Does not block and the job is not finished after this returns. | 1094 // Does not block and the job is not finished after this returns. |
497 va_res = vaEndPicture(va_display_, va_context_id_); | 1095 va_res = vaEndPicture(backend_->GetDisplay(), va_context_id_); |
498 VA_SUCCESS_OR_RETURN(va_res, "vaEndPicture failed", false); | 1096 VA_SUCCESS_OR_RETURN(va_res, "vaEndPicture failed", false); |
499 | 1097 |
500 return true; | 1098 return true; |
501 } | 1099 } |
502 | 1100 |
503 bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) { | 1101 bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) { |
504 bool result = Execute(va_surface_id); | 1102 bool result = Execute(va_surface_id); |
505 DestroyPendingBuffers(); | 1103 DestroyPendingBuffers(); |
506 return result; | 1104 return result; |
507 } | 1105 } |
508 | 1106 |
509 bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, | 1107 bool VaapiWrapper::PutSurfaceIntoPicture(VASurfaceID va_surface_id, |
510 Pixmap x_pixmap, | 1108 Picture* picture) { |
511 gfx::Size dest_size) { | |
512 base::AutoLock auto_lock(va_lock_); | 1109 base::AutoLock auto_lock(va_lock_); |
513 | 1110 |
514 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); | 1111 VAStatus va_res = vaSyncSurface(backend_->GetDisplay(), va_surface_id); |
515 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | 1112 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
516 | 1113 |
517 // Put the data into an X Pixmap. | 1114 va_res = backend_->PutSurfaceIntoPicture( |
518 va_res = vaPutSurface(va_display_, | 1115 backend_->GetDisplay(), va_surface_id, picture); |
Pawel Osciak
2014/08/25 01:13:24
We don't need to pass to backend_ its own member.
| |
519 va_surface_id, | |
520 x_pixmap, | |
521 0, 0, dest_size.width(), dest_size.height(), | |
522 0, 0, dest_size.width(), dest_size.height(), | |
523 NULL, 0, 0); | |
524 VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false); | 1116 VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false); |
Pawel Osciak
2014/08/25 01:13:24
s/pixmap/picture/?
| |
1117 | |
525 return true; | 1118 return true; |
526 } | 1119 } |
527 | 1120 |
528 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id, | 1121 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id, |
529 VAImage* image, | 1122 VAImage* image, |
530 void** mem) { | 1123 void** mem) { |
531 base::AutoLock auto_lock(va_lock_); | 1124 base::AutoLock auto_lock(va_lock_); |
532 | 1125 |
533 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); | 1126 VAStatus va_res = vaSyncSurface(backend_->GetDisplay(), va_surface_id); |
534 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | 1127 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
535 | 1128 |
536 // Derive a VAImage from the VASurface | 1129 // Derive a VAImage from the VASurface |
537 va_res = vaDeriveImage(va_display_, va_surface_id, image); | 1130 va_res = vaDeriveImage(backend_->GetDisplay(), va_surface_id, image); |
538 VA_LOG_ON_ERROR(va_res, "vaDeriveImage failed"); | 1131 VA_LOG_ON_ERROR(va_res, "vaDeriveImage failed"); |
539 if (va_res != VA_STATUS_SUCCESS) | 1132 if (va_res != VA_STATUS_SUCCESS) |
540 return false; | 1133 return false; |
541 | 1134 |
542 // Map the VAImage into memory | 1135 // Map the VAImage into memory |
543 va_res = vaMapBuffer(va_display_, image->buf, mem); | 1136 va_res = vaMapBuffer(backend_->GetDisplay(), image->buf, mem); |
544 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); | 1137 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); |
545 if (va_res == VA_STATUS_SUCCESS) | 1138 if (va_res == VA_STATUS_SUCCESS) |
546 return true; | 1139 return true; |
547 | 1140 |
548 va_res = vaDestroyImage(va_display_, image->image_id); | 1141 va_res = vaDestroyImage(backend_->GetDisplay(), image->image_id); |
549 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); | 1142 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); |
550 | 1143 |
551 return false; | 1144 return false; |
552 } | 1145 } |
553 | 1146 |
554 void VaapiWrapper::ReturnVaImageForTesting(VAImage* image) { | 1147 void VaapiWrapper::ReturnVaImageForTesting(VAImage* image) { |
555 base::AutoLock auto_lock(va_lock_); | 1148 base::AutoLock auto_lock(va_lock_); |
556 | 1149 |
557 VAStatus va_res = vaUnmapBuffer(va_display_, image->buf); | 1150 VAStatus va_res = vaUnmapBuffer(backend_->GetDisplay(), image->buf); |
558 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); | 1151 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); |
559 | 1152 |
560 va_res = vaDestroyImage(va_display_, image->image_id); | 1153 va_res = vaDestroyImage(backend_->GetDisplay(), image->image_id); |
561 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); | 1154 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); |
562 } | 1155 } |
563 | 1156 |
564 static void DestroyVAImage(VADisplay va_display, VAImage image) { | 1157 static void DestroyVAImage(VADisplay va_display, VAImage image) { |
565 if (image.image_id != VA_INVALID_ID) | 1158 if (image.image_id != VA_INVALID_ID) |
566 vaDestroyImage(va_display, image.image_id); | 1159 vaDestroyImage(va_display, image.image_id); |
567 } | 1160 } |
568 | 1161 |
569 bool VaapiWrapper::UploadVideoFrameToSurface( | 1162 bool VaapiWrapper::UploadVideoFrameToSurface( |
570 const scoped_refptr<media::VideoFrame>& frame, | 1163 const scoped_refptr<media::VideoFrame>& frame, |
571 VASurfaceID va_surface_id) { | 1164 VASurfaceID va_surface_id) { |
572 base::AutoLock auto_lock(va_lock_); | 1165 base::AutoLock auto_lock(va_lock_); |
573 | 1166 |
574 VAImage image; | 1167 VAImage image; |
575 VAStatus va_res = vaDeriveImage(va_display_, va_surface_id, &image); | 1168 VAStatus va_res = |
1169 vaDeriveImage(backend_->GetDisplay(), va_surface_id, &image); | |
576 VA_SUCCESS_OR_RETURN(va_res, "vaDeriveImage failed", false); | 1170 VA_SUCCESS_OR_RETURN(va_res, "vaDeriveImage failed", false); |
577 base::ScopedClosureRunner vaimage_deleter( | 1171 base::ScopedClosureRunner vaimage_deleter( |
578 base::Bind(&DestroyVAImage, va_display_, image)); | 1172 base::Bind(&DestroyVAImage, backend_->GetDisplay(), image)); |
579 | 1173 |
580 if (image.format.fourcc != VA_FOURCC_NV12) { | 1174 if (image.format.fourcc != VA_FOURCC_NV12) { |
581 DVLOG(1) << "Unsupported image format: " << image.format.fourcc; | 1175 DVLOG(1) << "Unsupported image format: " << image.format.fourcc; |
582 return false; | 1176 return false; |
583 } | 1177 } |
584 | 1178 |
585 if (gfx::Rect(image.width, image.height) < gfx::Rect(frame->coded_size())) { | 1179 if (gfx::Rect(image.width, image.height) < gfx::Rect(frame->coded_size())) { |
586 DVLOG(1) << "Buffer too small to fit the frame."; | 1180 DVLOG(1) << "Buffer too small to fit the frame."; |
587 return false; | 1181 return false; |
588 } | 1182 } |
589 | 1183 |
590 void* image_ptr = NULL; | 1184 void* image_ptr = NULL; |
591 va_res = vaMapBuffer(va_display_, image.buf, &image_ptr); | 1185 va_res = vaMapBuffer(backend_->GetDisplay(), image.buf, &image_ptr); |
592 VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false); | 1186 VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false); |
593 DCHECK(image_ptr); | 1187 DCHECK(image_ptr); |
594 | 1188 |
595 int ret = 0; | 1189 int ret = 0; |
596 { | 1190 { |
597 base::AutoUnlock auto_unlock(va_lock_); | 1191 base::AutoUnlock auto_unlock(va_lock_); |
598 ret = libyuv::I420ToNV12(frame->data(media::VideoFrame::kYPlane), | 1192 ret = libyuv::I420ToNV12(frame->data(media::VideoFrame::kYPlane), |
599 frame->stride(media::VideoFrame::kYPlane), | 1193 frame->stride(media::VideoFrame::kYPlane), |
600 frame->data(media::VideoFrame::kUPlane), | 1194 frame->data(media::VideoFrame::kUPlane), |
601 frame->stride(media::VideoFrame::kUPlane), | 1195 frame->stride(media::VideoFrame::kUPlane), |
602 frame->data(media::VideoFrame::kVPlane), | 1196 frame->data(media::VideoFrame::kVPlane), |
603 frame->stride(media::VideoFrame::kVPlane), | 1197 frame->stride(media::VideoFrame::kVPlane), |
604 static_cast<uint8*>(image_ptr) + image.offsets[0], | 1198 static_cast<uint8*>(image_ptr) + image.offsets[0], |
605 image.pitches[0], | 1199 image.pitches[0], |
606 static_cast<uint8*>(image_ptr) + image.offsets[1], | 1200 static_cast<uint8*>(image_ptr) + image.offsets[1], |
607 image.pitches[1], | 1201 image.pitches[1], |
608 image.width, | 1202 image.width, |
609 image.height); | 1203 image.height); |
610 } | 1204 } |
611 | 1205 |
612 va_res = vaUnmapBuffer(va_display_, image.buf); | 1206 va_res = vaUnmapBuffer(backend_->GetDisplay(), image.buf); |
613 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); | 1207 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); |
614 | 1208 |
615 return ret == 0; | 1209 return ret == 0; |
616 } | 1210 } |
617 | 1211 |
618 bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id, | 1212 bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id, |
619 VASurfaceID sync_surface_id, | 1213 VASurfaceID sync_surface_id, |
620 uint8* target_ptr, | 1214 uint8* target_ptr, |
621 size_t target_size, | 1215 size_t target_size, |
622 size_t* coded_data_size) { | 1216 size_t* coded_data_size) { |
623 base::AutoLock auto_lock(va_lock_); | 1217 base::AutoLock auto_lock(va_lock_); |
624 | 1218 |
625 VAStatus va_res = vaSyncSurface(va_display_, sync_surface_id); | 1219 VAStatus va_res = vaSyncSurface(backend_->GetDisplay(), sync_surface_id); |
626 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | 1220 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
627 | 1221 |
628 VACodedBufferSegment* buffer_segment = NULL; | 1222 VACodedBufferSegment* buffer_segment = NULL; |
629 va_res = vaMapBuffer( | 1223 va_res = vaMapBuffer(backend_->GetDisplay(), |
630 va_display_, buffer_id, reinterpret_cast<void**>(&buffer_segment)); | 1224 buffer_id, |
1225 reinterpret_cast<void**>(&buffer_segment)); | |
631 VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false); | 1226 VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false); |
632 DCHECK(target_ptr); | 1227 DCHECK(target_ptr); |
633 | 1228 |
634 { | 1229 { |
635 base::AutoUnlock auto_unlock(va_lock_); | 1230 base::AutoUnlock auto_unlock(va_lock_); |
636 *coded_data_size = 0; | 1231 *coded_data_size = 0; |
637 | 1232 |
638 while (buffer_segment) { | 1233 while (buffer_segment) { |
639 DCHECK(buffer_segment->buf); | 1234 DCHECK(buffer_segment->buf); |
640 | 1235 |
641 if (buffer_segment->size > target_size) { | 1236 if (buffer_segment->size > target_size) { |
642 DVLOG(1) << "Insufficient output buffer size"; | 1237 DVLOG(1) << "Insufficient output buffer size"; |
643 break; | 1238 break; |
644 } | 1239 } |
645 | 1240 |
646 memcpy(target_ptr, buffer_segment->buf, buffer_segment->size); | 1241 memcpy(target_ptr, buffer_segment->buf, buffer_segment->size); |
647 | 1242 |
648 target_ptr += buffer_segment->size; | 1243 target_ptr += buffer_segment->size; |
649 *coded_data_size += buffer_segment->size; | 1244 *coded_data_size += buffer_segment->size; |
650 target_size -= buffer_segment->size; | 1245 target_size -= buffer_segment->size; |
651 | 1246 |
652 buffer_segment = | 1247 buffer_segment = |
653 reinterpret_cast<VACodedBufferSegment*>(buffer_segment->next); | 1248 reinterpret_cast<VACodedBufferSegment*>(buffer_segment->next); |
654 } | 1249 } |
655 } | 1250 } |
656 | 1251 |
657 va_res = vaUnmapBuffer(va_display_, buffer_id); | 1252 va_res = vaUnmapBuffer(backend_->GetDisplay(), buffer_id); |
658 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); | 1253 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); |
659 | 1254 |
660 va_res = vaDestroyBuffer(va_display_, buffer_id); | 1255 va_res = vaDestroyBuffer(backend_->GetDisplay(), buffer_id); |
661 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); | 1256 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); |
662 | 1257 |
663 DCHECK(coded_buffers_.erase(buffer_id)); | 1258 DCHECK(coded_buffers_.erase(buffer_id)); |
664 | 1259 |
665 return buffer_segment == NULL; | 1260 return buffer_segment == NULL; |
666 } | 1261 } |
667 | 1262 |
668 // static | 1263 // static |
669 bool VaapiWrapper::PostSandboxInitialization() { | 1264 bool VaapiWrapper::PostSandboxInitialization() { |
670 StubPathMap paths; | 1265 StubPathMap paths; |
671 paths[kModuleVa].push_back(kVaLib); | 1266 |
1267 paths[kModuleVa].push_back("libva.so.1"); | |
1268 | |
1269 #ifdef USE_X11 | |
1270 paths[kModuleVa_x11].push_back("libva-x11.so.1"); | |
1271 #else | |
1272 paths[kModuleVa_ozone].push_back("libva-drm.so.1"); | |
1273 #endif | |
672 | 1274 |
673 return InitializeStubs(paths); | 1275 return InitializeStubs(paths); |
674 } | 1276 } |
675 | 1277 |
676 } // namespace content | 1278 } // namespace content |
OLD | NEW |