Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2014 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "content/common/gpu/media/vaapi_picture_provider_drm.h" | |
| 6 #include "third_party/libva/va/drm/va_drm.h" | |
| 7 #include "third_party/libva/va/va_drmcommon.h" | |
| 8 #include "third_party/libva/va/va_vpp.h" | |
| 9 #include "ui/gl/gl_bindings.h" | |
| 10 #include "ui/gl/gl_image.h" | |
| 11 #include "ui/gl/gl_image_egl.h" | |
| 12 #include "ui/gl/scoped_binders.h" | |
| 13 #include "ui/ozone/public/native_pixmap.h" | |
| 14 #include "ui/ozone/public/ozone_platform.h" | |
| 15 #include "ui/ozone/public/surface_factory_ozone.h" | |
| 16 | |
| 17 namespace content { | |
| 18 | |
| 19 #define LOG_VA_ERROR_AND_RETURN(input, err_msg) \ | |
| 20 do { \ | |
| 21 VAStatus va_status = input; \ | |
| 22 if (va_status != VA_STATUS_SUCCESS) { \ | |
| 23 DVLOG(1) << err_msg << " : " << vaErrorStr(va_status); \ | |
| 24 return false; \ | |
| 25 } \ | |
| 26 } while (0) | |
| 27 | |
| 28 class DrmPicture : public VaapiPictureProvider::Picture { | |
| 29 public: | |
| 30 DrmPicture(DrmVaapiPictureProvider* provider, | |
| 31 VADisplay va_display, | |
| 32 const base::Callback<bool(void)> make_context_current, | |
| 33 int32 picture_buffer_id, | |
| 34 uint32 texture_id, | |
| 35 const gfx::Size& size) | |
| 36 : Picture(picture_buffer_id, texture_id, size), | |
| 37 provider_(provider), | |
| 38 va_display_(va_display), | |
| 39 make_context_current_(make_context_current), | |
| 40 va_surface_(VA_INVALID_SURFACE) {} | |
| 41 | |
| 42 virtual ~DrmPicture() { | |
| 43 if (gl_image_ && make_context_current_.Run()) { | |
| 44 // ReleaseTexImage on a GLImageEGL does nothing, to deassociate | |
| 45 // the renderer's texture from the image, just set the storage | |
| 46 // of that texture to NULL | |
| 47 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id()); | |
| 48 glTexImage2D(GL_TEXTURE_2D, | |
| 49 0, | |
| 50 GL_RGBA, | |
| 51 size().width(), | |
| 52 size().height(), | |
| 53 0, | |
| 54 GL_RGBA, | |
| 55 GL_UNSIGNED_BYTE, | |
| 56 NULL); | |
| 57 | |
| 58 gl_image_->Destroy(true); | |
| 59 | |
| 60 CHECK_EQ(glGetError(), GL_NO_ERROR); | |
|
Pawel Osciak
2014/10/08 08:17:22
I think this is not critical enough to crash the p
llandwerlin-old
2014/10/08 09:31:18
Acknowledged.
| |
| 61 } | |
| 62 | |
| 63 if (va_surface_ != VA_INVALID_SURFACE) | |
| 64 vaDestroySurfaces(va_display_, &va_surface_, 1); | |
| 65 } | |
| 66 | |
| 67 bool Initialize() { | |
| 68 VASurfaceAttrib va_attribs[2]; | |
| 69 VASurfaceAttribExternalBuffers va_attrib_extbuf; | |
| 70 | |
| 71 ui::OzonePlatform* platform = ui::OzonePlatform::GetInstance(); | |
| 72 ui::SurfaceFactoryOzone* factory = platform->GetSurfaceFactoryOzone(); | |
| 73 | |
| 74 pixmap_ = | |
| 75 factory->CreateNativePixmap(size(), ui::SurfaceFactoryOzone::RGBA_8888); | |
|
Pawel Osciak
2014/10/08 08:17:22
Check for NULL?
llandwerlin-old
2014/10/08 09:31:18
Acknowledged.
| |
| 76 unsigned long buffer_fd = pixmap_->GetDmaBufFd(); | |
|
Pawel Osciak
2014/10/08 08:17:22
fd is an int... We should also check for -1.
llandwerlin-old
2014/10/08 09:31:18
Acknowledged.
| |
| 77 | |
| 78 va_attrib_extbuf.pixel_format = VA_FOURCC_BGRX; | |
| 79 va_attrib_extbuf.width = size().width(); | |
| 80 va_attrib_extbuf.height = size().height(); | |
| 81 va_attrib_extbuf.data_size = size().height() * pixmap_->GetStride(); | |
| 82 va_attrib_extbuf.num_planes = 1; | |
| 83 va_attrib_extbuf.pitches[0] = pixmap_->GetStride(); | |
| 84 va_attrib_extbuf.offsets[0] = 0; | |
| 85 va_attrib_extbuf.buffers = &buffer_fd; | |
| 86 va_attrib_extbuf.num_buffers = 1; | |
| 87 va_attrib_extbuf.flags = 0; | |
| 88 va_attrib_extbuf.private_data = NULL; | |
| 89 | |
| 90 va_attribs[0].type = VASurfaceAttribMemoryType; | |
| 91 va_attribs[0].flags = VA_SURFACE_ATTRIB_SETTABLE; | |
| 92 va_attribs[0].value.type = VAGenericValueTypeInteger; | |
| 93 va_attribs[0].value.value.i = VA_SURFACE_ATTRIB_MEM_TYPE_DRM_PRIME; | |
| 94 | |
| 95 va_attribs[1].type = VASurfaceAttribExternalBufferDescriptor; | |
| 96 va_attribs[1].flags = VA_SURFACE_ATTRIB_SETTABLE; | |
| 97 va_attribs[1].value.type = VAGenericValueTypePointer; | |
| 98 va_attribs[1].value.value.p = &va_attrib_extbuf; | |
| 99 | |
| 100 LOG_VA_ERROR_AND_RETURN(vaCreateSurfaces(va_display_, | |
| 101 VA_RT_FORMAT_RGB32, | |
| 102 size().width(), | |
| 103 size().height(), | |
| 104 &va_surface_, | |
| 105 1, | |
| 106 va_attribs, | |
| 107 arraysize(va_attribs)), | |
| 108 "Couldn't create surface"); | |
| 109 | |
| 110 if (!make_context_current_.Run()) | |
| 111 return false; | |
| 112 | |
| 113 gl_image_ = new gfx::GLImageEGL(size()); | |
| 114 EGLint attrs[] = {EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE}; | |
| 115 if (!gl_image_->Initialize( | |
| 116 EGL_NATIVE_PIXMAP_KHR, pixmap_->GetEGLClientBuffer(), attrs)) | |
| 117 return false; | |
| 118 | |
| 119 return true; | |
| 120 } | |
| 121 | |
| 122 virtual bool PutSurface(VASurfaceID va_surface_id) OVERRIDE { | |
| 123 if (!provider_->PutSurfaceIntoPicture(va_surface_id, va_surface_, size())) | |
| 124 return false; | |
| 125 | |
| 126 if (!make_context_current_.Run()) | |
| 127 return false; | |
| 128 | |
| 129 gfx::ScopedTextureBinder texture_binder(GL_TEXTURE_2D, texture_id()); | |
| 130 return gl_image_->BindTexImage(GL_TEXTURE_2D); | |
| 131 } | |
| 132 | |
| 133 private: | |
| 134 DrmVaapiPictureProvider* provider_; | |
| 135 VADisplay va_display_; | |
| 136 base::Callback<bool(void)> make_context_current_; | |
| 137 VASurfaceID va_surface_; | |
| 138 scoped_refptr<ui::NativePixmap> pixmap_; | |
| 139 scoped_refptr<gfx::GLImageEGL> gl_image_; | |
| 140 }; | |
| 141 | |
| 142 DrmVaapiPictureProvider::DrmVaapiPictureProvider( | |
| 143 VADisplay va_display, | |
| 144 const base::Callback<bool(void)> make_context_current) | |
| 145 : make_context_current_(make_context_current), | |
| 146 va_display_(va_display), | |
| 147 vpp_config_(VA_INVALID_ID), | |
| 148 vpp_context_(VA_INVALID_ID), | |
| 149 vpp_buffer_(VA_INVALID_ID) { | |
| 150 } | |
| 151 | |
| 152 DrmVaapiPictureProvider::~DrmVaapiPictureProvider() { | |
| 153 DeinitializeVpp(); | |
| 154 } | |
| 155 | |
| 156 scoped_ptr<VaapiPictureProvider::Picture> | |
| 157 DrmVaapiPictureProvider::CreatePicture(int32 picture_buffer_id, | |
| 158 uint32 texture_id, | |
| 159 const gfx::Size& size) { | |
| 160 DrmPicture* drm_picture = new DrmPicture(this, | |
|
Pawel Osciak
2014/10/08 08:17:22
Could we create a scoped_ptr directly here?
scoped
llandwerlin-old
2014/10/08 09:31:18
The problem is that I can't access the Initialize
Pawel Osciak
2014/10/26 13:06:46
Could you pass fb_config_ to the constructor of TF
llandwerlin-old
2014/10/29 13:52:47
Acknowledged.
| |
| 161 va_display_, | |
| 162 make_context_current_, | |
| 163 picture_buffer_id, | |
| 164 texture_id, | |
| 165 size); | |
| 166 scoped_ptr<VaapiPictureProvider::Picture> picture(drm_picture); | |
|
Pawel Osciak
2014/10/08 08:17:22
Do we need the qualifier here if we are child of V
llandwerlin-old
2014/10/08 09:31:18
I'll check, thanks.
llandwerlin-old
2014/10/13 16:53:00
Yep, we do...
| |
| 167 | |
| 168 if (!drm_picture->Initialize()) | |
| 169 picture.reset(); | |
| 170 | |
| 171 return picture.Pass(); | |
| 172 } | |
| 173 | |
| 174 bool DrmVaapiPictureProvider::PutSurfaceIntoPicture( | |
| 175 VASurfaceID va_surface_id_src, | |
| 176 VASurfaceID va_surface_id_dest, | |
| 177 const gfx::Size& dest_size) { | |
| 178 VAProcPipelineParameterBuffer* pipeline_param; | |
| 179 VARectangle input_region, output_region; | |
| 180 | |
| 181 LOG_VA_ERROR_AND_RETURN( | |
| 182 vaMapBuffer(va_display_, vpp_buffer_, (void**)&pipeline_param), | |
| 183 "Couldn't map buffer"); | |
| 184 | |
| 185 memset(pipeline_param, 0, sizeof *pipeline_param); | |
| 186 | |
| 187 input_region.x = input_region.y = 0; | |
| 188 input_region.width = coded_picture_size_.width(); | |
| 189 input_region.height = coded_picture_size_.height(); | |
| 190 pipeline_param->surface_region = &input_region; | |
| 191 pipeline_param->surface = va_surface_id_src; | |
| 192 pipeline_param->surface_color_standard = VAProcColorStandardNone; | |
| 193 | |
| 194 output_region.x = output_region.y = 0; | |
| 195 output_region.width = dest_size.width(); | |
| 196 output_region.height = dest_size.height(); | |
| 197 pipeline_param->output_region = &output_region; | |
| 198 pipeline_param->output_background_color = 0xff000000; | |
| 199 pipeline_param->output_color_standard = VAProcColorStandardNone; | |
| 200 | |
| 201 LOG_VA_ERROR_AND_RETURN(vaUnmapBuffer(va_display_, vpp_buffer_), | |
| 202 "Couldn't unmap buffer"); | |
| 203 | |
| 204 LOG_VA_ERROR_AND_RETURN( | |
| 205 vaBeginPicture(va_display_, vpp_context_, va_surface_id_dest), | |
| 206 "Couldn't begin picture"); | |
| 207 | |
| 208 LOG_VA_ERROR_AND_RETURN( | |
| 209 vaRenderPicture(va_display_, vpp_context_, &vpp_buffer_, 1), | |
| 210 "Couldn't render picture"); | |
| 211 | |
| 212 LOG_VA_ERROR_AND_RETURN(vaEndPicture(va_display_, vpp_context_), | |
| 213 "Couldn't end picture"); | |
| 214 return true; | |
| 215 } | |
| 216 | |
| 217 bool DrmVaapiPictureProvider::SetCodedSurfacesSize(const gfx::Size& size) { | |
|
Pawel Osciak
2014/10/08 08:17:22
I realized, could we just do this on PutSurfaceInt
llandwerlin-old
2014/10/08 09:31:18
Acknowledged.
| |
| 218 DeinitializeVpp(); | |
| 219 return InitializeVpp(size); | |
| 220 } | |
| 221 | |
| 222 bool DrmVaapiPictureProvider::Initialize() { | |
| 223 return true; | |
| 224 } | |
| 225 | |
| 226 bool DrmVaapiPictureProvider::InitializeVpp(const gfx::Size& size) { | |
| 227 LOG_VA_ERROR_AND_RETURN(vaCreateConfig(va_display_, | |
| 228 VAProfileNone, | |
| 229 VAEntrypointVideoProc, | |
| 230 NULL, | |
| 231 0, | |
| 232 &vpp_config_), | |
| 233 "Couldn't create config"); | |
| 234 | |
| 235 LOG_VA_ERROR_AND_RETURN(vaCreateContext(va_display_, | |
| 236 vpp_config_, | |
| 237 size.width(), | |
| 238 size.height(), | |
| 239 0, | |
| 240 NULL, | |
| 241 0, | |
| 242 &vpp_context_), | |
| 243 "Couldn't create context"); | |
| 244 | |
| 245 LOG_VA_ERROR_AND_RETURN(vaCreateBuffer(va_display_, | |
| 246 vpp_context_, | |
| 247 VAProcPipelineParameterBufferType, | |
| 248 sizeof(VAProcPipelineParameterBuffer), | |
| 249 1, | |
| 250 NULL, | |
| 251 &vpp_buffer_), | |
| 252 "Couldn't create buffer"); | |
| 253 | |
| 254 coded_picture_size_ = size; | |
| 255 | |
| 256 return true; | |
| 257 } | |
| 258 | |
| 259 void DrmVaapiPictureProvider::DeinitializeVpp() { | |
| 260 if (vpp_buffer_ != VA_INVALID_ID) { | |
| 261 vaDestroyBuffer(va_display_, vpp_buffer_); | |
| 262 vpp_buffer_ = VA_INVALID_ID; | |
| 263 } | |
| 264 if (vpp_context_ != VA_INVALID_ID) { | |
| 265 vaDestroyContext(va_display_, vpp_context_); | |
| 266 vpp_context_ = VA_INVALID_ID; | |
| 267 } | |
| 268 if (vpp_config_ != VA_INVALID_ID) { | |
| 269 vaDestroyConfig(va_display_, vpp_config_); | |
| 270 vpp_config_ = VA_INVALID_ID; | |
| 271 } | |
| 272 } | |
| 273 | |
| 274 } // namespace | |
| OLD | NEW |