| OLD | NEW | 
|    1 // Copyright 2014 The Chromium Authors. All rights reserved. |    1 // Copyright 2014 The Chromium Authors. All rights reserved. | 
|    2 // Use of this source code is governed by a BSD-style license that can be |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "base/file_descriptor_posix.h" |    5 #include "base/file_descriptor_posix.h" | 
|    6 #include "content/common/gpu/media/va_surface.h" |    6 #include "content/common/gpu/media/va_surface.h" | 
|    7 #include "content/common/gpu/media/vaapi_drm_picture.h" |    7 #include "content/common/gpu/media/vaapi_drm_picture.h" | 
|    8 #include "content/common/gpu/media/vaapi_wrapper.h" |    8 #include "content/common/gpu/media/vaapi_wrapper.h" | 
|    9 #include "third_party/libva/va/drm/va_drm.h" |    9 #include "third_party/libva/va/drm/va_drm.h" | 
|   10 #include "third_party/libva/va/va.h" |   10 #include "third_party/libva/va/va.h" | 
|   11 #include "third_party/libva/va/va_drmcommon.h" |  | 
|   12 #include "ui/gfx/gpu_memory_buffer.h" |   11 #include "ui/gfx/gpu_memory_buffer.h" | 
|   13 #include "ui/gl/gl_bindings.h" |   12 #include "ui/gl/gl_bindings.h" | 
|   14 #include "ui/gl/gl_image_ozone_native_pixmap.h" |   13 #include "ui/gl/gl_image_ozone_native_pixmap.h" | 
|   15 #include "ui/gl/scoped_binders.h" |   14 #include "ui/gl/scoped_binders.h" | 
|   16 #include "ui/ozone/public/native_pixmap.h" |   15 #include "ui/ozone/public/native_pixmap.h" | 
|   17 #include "ui/ozone/public/ozone_platform.h" |   16 #include "ui/ozone/public/ozone_platform.h" | 
|   18 #include "ui/ozone/public/surface_factory_ozone.h" |   17 #include "ui/ozone/public/surface_factory_ozone.h" | 
|   19  |   18  | 
|   20 namespace { |   19 namespace { | 
|   21 // We decode video into YUV420, but for usage with GLImages we have to convert |   20 // We decode video into YUV420, but for usage with GLImages we have to convert | 
|   22 // to BGRX_8888. |   21 // to BGRX_8888. | 
|   23 const gfx::BufferFormat kPictureForGLImageFormat = gfx::BufferFormat::BGRX_8888; |   22 const gfx::BufferFormat kPictureForGLImageFormat = gfx::BufferFormat::BGRX_8888; | 
|   24  |   23  | 
|   25 uint32_t BufferFormatToVAFourCC(gfx::BufferFormat fmt) { |  | 
|   26   switch (fmt) { |  | 
|   27     case gfx::BufferFormat::BGRX_8888: |  | 
|   28       return VA_FOURCC_BGRX; |  | 
|   29     case gfx::BufferFormat::UYVY_422: |  | 
|   30       return VA_FOURCC_UYVY; |  | 
|   31     default: |  | 
|   32       NOTREACHED(); |  | 
|   33       return 0; |  | 
|   34   } |  | 
|   35 } |  | 
|   36  |  | 
|   37 uint32_t BufferFormatToVARTFormat(gfx::BufferFormat fmt) { |  | 
|   38   switch (fmt) { |  | 
|   39     case gfx::BufferFormat::UYVY_422: |  | 
|   40       return VA_RT_FORMAT_YUV422; |  | 
|   41     case gfx::BufferFormat::BGRX_8888: |  | 
|   42       return VA_RT_FORMAT_RGB32; |  | 
|   43     default: |  | 
|   44       NOTREACHED(); |  | 
|   45       return 0; |  | 
|   46   } |  | 
|   47 } |  | 
|   48  |  | 
|   49 }  // namespace |   24 }  // namespace | 
|   50  |   25  | 
|   51 namespace content { |   26 namespace content { | 
|   52  |   27  | 
|   53 VaapiDrmPicture::VaapiDrmPicture( |   28 VaapiDrmPicture::VaapiDrmPicture( | 
|   54     VaapiWrapper* vaapi_wrapper, |   29     const scoped_refptr<VaapiWrapper>& vaapi_wrapper, | 
|   55     const base::Callback<bool(void)>& make_context_current, |   30     const base::Callback<bool(void)>& make_context_current, | 
|   56     int32 picture_buffer_id, |   31     int32 picture_buffer_id, | 
|   57     uint32 texture_id, |   32     uint32 texture_id, | 
|   58     const gfx::Size& size) |   33     const gfx::Size& size) | 
|   59     : VaapiPicture(picture_buffer_id, texture_id, size), |   34     : VaapiPicture(picture_buffer_id, texture_id, size), | 
|   60       vaapi_wrapper_(vaapi_wrapper), |   35       vaapi_wrapper_(vaapi_wrapper), | 
|   61       make_context_current_(make_context_current), |   36       make_context_current_(make_context_current) {} | 
|   62       weak_this_factory_(this) { |  | 
|   63 } |  | 
|   64  |   37  | 
|   65 VaapiDrmPicture::~VaapiDrmPicture() { |   38 VaapiDrmPicture::~VaapiDrmPicture() { | 
|   66   if (gl_image_ && make_context_current_.Run()) { |   39   if (gl_image_ && make_context_current_.Run()) { | 
|   67     gl_image_->ReleaseTexImage(GL_TEXTURE_EXTERNAL_OES); |   40     gl_image_->ReleaseTexImage(GL_TEXTURE_EXTERNAL_OES); | 
|   68     gl_image_->Destroy(true); |   41     gl_image_->Destroy(true); | 
|   69  |   42  | 
|   70     DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR)); |   43     DCHECK_EQ(glGetError(), static_cast<GLenum>(GL_NO_ERROR)); | 
|   71   } |   44   } | 
|   72 } |   45 } | 
|   73  |   46  | 
|   74 scoped_refptr<VASurface> VaapiDrmPicture::CreateVASurfaceForPixmap( |  | 
|   75     scoped_refptr<ui::NativePixmap> pixmap, |  | 
|   76     gfx::Size pixmap_size) { |  | 
|   77   // Get the dmabuf of the created buffer. |  | 
|   78   int dmabuf_fd = pixmap->GetDmaBufFd(); |  | 
|   79   if (dmabuf_fd < 0) { |  | 
|   80     LOG(ERROR) << "Failed to get dmabuf from an Ozone NativePixmap"; |  | 
|   81     return nullptr; |  | 
|   82   } |  | 
|   83   int dmabuf_pitch = pixmap->GetDmaBufPitch(); |  | 
|   84  |  | 
|   85   // Create a VASurface out of the created buffer using the dmabuf. |  | 
|   86   VASurfaceAttribExternalBuffers va_attrib_extbuf; |  | 
|   87   memset(&va_attrib_extbuf, 0, sizeof(va_attrib_extbuf)); |  | 
|   88   va_attrib_extbuf.pixel_format = |  | 
|   89       BufferFormatToVAFourCC(pixmap->GetBufferFormat()); |  | 
|   90   va_attrib_extbuf.width = pixmap_size.width(); |  | 
|   91   va_attrib_extbuf.height = pixmap_size.height(); |  | 
|   92   va_attrib_extbuf.data_size = pixmap_size.height() * dmabuf_pitch; |  | 
|   93   va_attrib_extbuf.num_planes = 1; |  | 
|   94   va_attrib_extbuf.pitches[0] = dmabuf_pitch; |  | 
|   95   va_attrib_extbuf.offsets[0] = 0; |  | 
|   96   va_attrib_extbuf.buffers = reinterpret_cast<unsigned long*>(&dmabuf_fd); |  | 
|   97   va_attrib_extbuf.num_buffers = 1; |  | 
|   98   va_attrib_extbuf.flags = 0; |  | 
|   99   va_attrib_extbuf.private_data = NULL; |  | 
|  100  |  | 
|  101   std::vector<VASurfaceAttrib> va_attribs; |  | 
|  102   va_attribs.resize(2); |  | 
|  103  |  | 
|  104   va_attribs[0].type = VASurfaceAttribMemoryType; |  | 
|  105   va_attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE; |  | 
|  106   va_attribs[0].value.type = VAGenericValueTypeInteger; |  | 
|  107   va_attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; |  | 
|  108  |  | 
|  109   va_attribs[1].type = VASurfaceAttribExternalBufferDescriptor; |  | 
|  110   va_attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE; |  | 
|  111   va_attribs[1].value.type = VAGenericValueTypePointer; |  | 
|  112   va_attribs[1].value.value.p = &va_attrib_extbuf; |  | 
|  113  |  | 
|  114   scoped_refptr<VASurface> va_surface = vaapi_wrapper_->CreateUnownedSurface( |  | 
|  115       BufferFormatToVARTFormat(pixmap->GetBufferFormat()), pixmap_size, |  | 
|  116       va_attribs); |  | 
|  117   if (!va_surface) { |  | 
|  118     LOG(ERROR) << "Failed to create VASurface for an Ozone NativePixmap"; |  | 
|  119     return nullptr; |  | 
|  120   } |  | 
|  121  |  | 
|  122   return va_surface; |  | 
|  123 } |  | 
|  124  |  | 
|  125 scoped_refptr<ui::NativePixmap> VaapiDrmPicture::CreateNativePixmap( |  | 
|  126     gfx::Size size, |  | 
|  127     gfx::BufferFormat format) { |  | 
|  128   ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); |  | 
|  129   ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); |  | 
|  130  |  | 
|  131   // Create a buffer from Ozone. |  | 
|  132   return factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size, format, |  | 
|  133                                      gfx::BufferUsage::SCANOUT); |  | 
|  134 } |  | 
|  135  |  | 
|  136 bool VaapiDrmPicture::Initialize() { |   47 bool VaapiDrmPicture::Initialize() { | 
|  137   // We want to create a VASurface and an EGLImage out of the same |   48   // We want to create a VASurface and an EGLImage out of the same | 
|  138   // memory buffer, so we can output decoded pictures to it using |   49   // memory buffer, so we can output decoded pictures to it using | 
|  139   // VAAPI and also use it to paint with GL. |   50   // VAAPI and also use it to paint with GL. | 
|  140   pixmap_ = CreateNativePixmap(size(), kPictureForGLImageFormat); |   51   ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); | 
 |   52   ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); | 
 |   53   pixmap_ = factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size(), | 
 |   54                                         kPictureForGLImageFormat, | 
 |   55                                         gfx::BufferUsage::SCANOUT); | 
|  141   if (!pixmap_) { |   56   if (!pixmap_) { | 
|  142     LOG(ERROR) << "Failed creating an Ozone NativePixmap"; |   57     LOG(ERROR) << "Failed creating an Ozone NativePixmap"; | 
|  143     return false; |   58     return false; | 
|  144   } |   59   } | 
|  145  |   60  | 
|  146   va_surface_ = CreateVASurfaceForPixmap(pixmap_, size()); |   61   va_surface_ = vaapi_wrapper_->CreateVASurfaceForPixmap(pixmap_); | 
|  147   if (!va_surface_) { |   62   if (!va_surface_) { | 
|  148     LOG(ERROR) << "Failed creating VASurface for NativePixmap"; |   63     LOG(ERROR) << "Failed creating VASurface for NativePixmap"; | 
|  149     return false; |   64     return false; | 
|  150   } |   65   } | 
|  151  |   66  | 
|  152   // Weak pointers can only bind to methods without return values, |   67   pixmap_->SetProcessingCallback( | 
|  153   // hence we cannot bind ProcessPixmap here. Instead we use a |   68       base::Bind(&VaapiWrapper::ProcessPixmap, vaapi_wrapper_)); | 
|  154   // static function to solve this problem. |  | 
|  155   pixmap_->SetProcessingCallback(base::Bind(&VaapiDrmPicture::CallProcessPixmap, |  | 
|  156                                             weak_this_factory_.GetWeakPtr())); |  | 
|  157  |   69  | 
|  158   if (!make_context_current_.Run()) |   70   if (!make_context_current_.Run()) | 
|  159     return false; |   71     return false; | 
|  160  |   72  | 
|  161   gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_EXTERNAL_OES, |   73   gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_EXTERNAL_OES, | 
|  162                                           texture_id()); |   74                                           texture_id()); | 
|  163   scoped_refptr<gfx::GLImageOzoneNativePixmap> image( |   75   scoped_refptr<gfx::GLImageOzoneNativePixmap> image( | 
|  164       new gfx::GLImageOzoneNativePixmap(size(), GL_BGRA_EXT)); |   76       new gfx::GLImageOzoneNativePixmap(size(), GL_BGRA_EXT)); | 
|  165   if (!image->Initialize(pixmap_.get(), pixmap_->GetBufferFormat())) { |   77   if (!image->Initialize(pixmap_.get(), pixmap_->GetBufferFormat())) { | 
|  166     LOG(ERROR) << "Failed to create GLImage"; |   78     LOG(ERROR) << "Failed to create GLImage"; | 
|  167     return false; |   79     return false; | 
|  168   } |   80   } | 
|  169   gl_image_ = image; |   81   gl_image_ = image; | 
|  170   if (!gl_image_->BindTexImage(GL_TEXTURE_EXTERNAL_OES)) { |   82   if (!gl_image_->BindTexImage(GL_TEXTURE_EXTERNAL_OES)) { | 
|  171     LOG(ERROR) << "Failed to bind texture to GLImage"; |   83     LOG(ERROR) << "Failed to bind texture to GLImage"; | 
|  172     return false; |   84     return false; | 
|  173   } |   85   } | 
|  174  |   86  | 
|  175   return true; |   87   return true; | 
|  176 } |   88 } | 
|  177  |   89  | 
|  178 bool VaapiDrmPicture::DownloadFromSurface( |   90 bool VaapiDrmPicture::DownloadFromSurface( | 
|  179     const scoped_refptr<VASurface>& va_surface) { |   91     const scoped_refptr<VASurface>& va_surface) { | 
|  180   return vaapi_wrapper_->BlitSurface(va_surface, va_surface_); |   92   return vaapi_wrapper_->BlitSurface(va_surface, va_surface_); | 
|  181 } |   93 } | 
|  182  |   94  | 
|  183 // static |  | 
|  184 scoped_refptr<ui::NativePixmap> VaapiDrmPicture::CallProcessPixmap( |  | 
|  185     base::WeakPtr<VaapiDrmPicture> weak_ptr, |  | 
|  186     gfx::Size target_size, |  | 
|  187     gfx::BufferFormat target_format) { |  | 
|  188   if (!weak_ptr.get()) { |  | 
|  189     LOG(ERROR) << "Failed processing NativePixmap as processing " |  | 
|  190                   "unit(VaapiDrmPicture) is deleted"; |  | 
|  191     return nullptr; |  | 
|  192   } |  | 
|  193   return weak_ptr->ProcessPixmap(target_size, target_format); |  | 
|  194 } |  | 
|  195  |  | 
|  196 scoped_refptr<ui::NativePixmap> VaapiDrmPicture::ProcessPixmap( |  | 
|  197     gfx::Size target_size, |  | 
|  198     gfx::BufferFormat target_format) { |  | 
|  199   if (!processed_va_surface_.get() || |  | 
|  200       processed_va_surface_->size() != target_size || |  | 
|  201       processed_va_surface_->format() != |  | 
|  202           BufferFormatToVARTFormat(target_format)) { |  | 
|  203     processed_pixmap_ = CreateNativePixmap(target_size, target_format); |  | 
|  204     if (!processed_pixmap_) { |  | 
|  205       LOG(ERROR) << "Failed creating an Ozone NativePixmap for processing"; |  | 
|  206       processed_va_surface_ = nullptr; |  | 
|  207       return nullptr; |  | 
|  208     } |  | 
|  209     processed_va_surface_ = |  | 
|  210         CreateVASurfaceForPixmap(processed_pixmap_, target_size); |  | 
|  211     if (!processed_va_surface_) { |  | 
|  212       LOG(ERROR) << "Failed creating VA Surface for pixmap"; |  | 
|  213       processed_pixmap_ = nullptr; |  | 
|  214       return nullptr; |  | 
|  215     } |  | 
|  216   } |  | 
|  217  |  | 
|  218   DCHECK(processed_pixmap_); |  | 
|  219   bool vpp_result = |  | 
|  220       vaapi_wrapper_->BlitSurface(va_surface_, processed_va_surface_); |  | 
|  221   if (!vpp_result) { |  | 
|  222     LOG(ERROR) << "Failed scaling NativePixmap"; |  | 
|  223     processed_pixmap_ = nullptr; |  | 
|  224     processed_va_surface_ = nullptr; |  | 
|  225     return nullptr; |  | 
|  226   } |  | 
|  227  |  | 
|  228   return processed_pixmap_; |  | 
|  229 } |  | 
|  230  |  | 
|  231 scoped_refptr<gl::GLImage> VaapiDrmPicture::GetImageToBind() { |   95 scoped_refptr<gl::GLImage> VaapiDrmPicture::GetImageToBind() { | 
|  232   return gl_image_; |   96   return gl_image_; | 
|  233 } |   97 } | 
|  234  |   98  | 
|  235 bool VaapiDrmPicture::AllowOverlay() const { |   99 bool VaapiDrmPicture::AllowOverlay() const { | 
|  236   return true; |  100   return true; | 
|  237 } |  101 } | 
|  238  |  102  | 
|  239 }  // namespace |  103 }  // namespace | 
| OLD | NEW |