Chromium Code Reviews| 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 |