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

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

Issue 490233002: VaapiVideoAccelerator: make Vaapi accelerator work with ozone (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Missing modifications in video accelerators Created 6 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698