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

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

Issue 356903002: Revert "Revert 279650 "Add VaapiVideoEncodeAccelerator for HW-accelerate..."" (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 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 | Annotate | Revision Log
OLDNEW
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/logging.h" 11 #include "base/logging.h"
11 #include "base/numerics/safe_conversions.h" 12 #include "base/numerics/safe_conversions.h"
12 // Auto-generated for dlopen libva libraries 13 // Auto-generated for dlopen libva libraries
13 #include "content/common/gpu/media/va_stubs.h" 14 #include "content/common/gpu/media/va_stubs.h"
15 #include "third_party/libyuv/include/libyuv.h"
14 16
15 using content_common_gpu_media::kModuleVa; 17 using content_common_gpu_media::kModuleVa;
16 using content_common_gpu_media::InitializeStubs; 18 using content_common_gpu_media::InitializeStubs;
17 using content_common_gpu_media::StubPathMap; 19 using content_common_gpu_media::StubPathMap;
18 20
19 // libva-x11 depends on libva, so dlopen libva-x11 is enough 21 // libva-x11 depends on libva, so dlopen libva-x11 is enough
20 static const base::FilePath::CharType kVaLib[] = 22 static const base::FilePath::CharType kVaLib[] =
21 FILE_PATH_LITERAL("libva-x11.so.1"); 23 FILE_PATH_LITERAL("libva-x11.so.1");
22 24
23 #define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \ 25 #define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \
(...skipping 12 matching lines...) Expand all
36 #define VA_SUCCESS_OR_RETURN(va_error, err_msg, ret) \ 38 #define VA_SUCCESS_OR_RETURN(va_error, err_msg, ret) \
37 do { \ 39 do { \
38 if ((va_error) != VA_STATUS_SUCCESS) { \ 40 if ((va_error) != VA_STATUS_SUCCESS) { \
39 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \ 41 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \
40 return (ret); \ 42 return (ret); \
41 } \ 43 } \
42 } while (0) 44 } while (0)
43 45
44 namespace content { 46 namespace content {
45 47
48 // Config attributes common for both encode and decode.
49 static const VAConfigAttrib kCommonVAConfigAttribs[] = {
50 {VAConfigAttribRTFormat, VA_RT_FORMAT_YUV420},
51 };
52
53 // Attributes required for encode.
54 static const VAConfigAttrib kEncodeVAConfigAttribs[] = {
55 {VAConfigAttribRateControl, VA_RC_CBR},
56 {VAConfigAttribEncPackedHeaders,
57 VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE},
58 };
59
46 // Maps Profile enum values to VaProfile values. 60 // Maps Profile enum values to VaProfile values.
47 static VAProfile ProfileToVAProfile( 61 static VAProfile ProfileToVAProfile(
48 media::VideoCodecProfile profile, 62 media::VideoCodecProfile profile,
49 const std::vector<VAProfile>& supported_profiles) { 63 const std::vector<VAProfile>& supported_profiles) {
50 64
51 VAProfile va_profile = VAProfileNone; 65 VAProfile va_profile = VAProfileNone;
52 66
53 switch (profile) { 67 switch (profile) {
54 case media::H264PROFILE_BASELINE: 68 case media::H264PROFILE_BASELINE:
55 va_profile = VAProfileH264Baseline; 69 va_profile = VAProfileH264Baseline;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 } 113 }
100 114
101 VaapiWrapper::VaapiWrapper() 115 VaapiWrapper::VaapiWrapper()
102 : va_display_(NULL), 116 : va_display_(NULL),
103 va_config_id_(VA_INVALID_ID), 117 va_config_id_(VA_INVALID_ID),
104 va_context_id_(VA_INVALID_ID) { 118 va_context_id_(VA_INVALID_ID) {
105 } 119 }
106 120
107 VaapiWrapper::~VaapiWrapper() { 121 VaapiWrapper::~VaapiWrapper() {
108 DestroyPendingBuffers(); 122 DestroyPendingBuffers();
123 DestroyCodedBuffers();
109 DestroySurfaces(); 124 DestroySurfaces();
110 Deinitialize(); 125 Deinitialize();
111 } 126 }
112 127
113 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( 128 scoped_ptr<VaapiWrapper> VaapiWrapper::Create(
129 CodecMode mode,
114 media::VideoCodecProfile profile, 130 media::VideoCodecProfile profile,
115 Display* x_display, 131 Display* x_display,
116 const base::Closure& report_error_to_uma_cb) { 132 const base::Closure& report_error_to_uma_cb) {
117 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); 133 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper());
118 134
119 if (!vaapi_wrapper->Initialize(profile, x_display, report_error_to_uma_cb)) 135 if (!vaapi_wrapper->Initialize(
136 mode, profile, x_display, report_error_to_uma_cb))
120 vaapi_wrapper.reset(); 137 vaapi_wrapper.reset();
121 138
122 return vaapi_wrapper.Pass(); 139 return vaapi_wrapper.Pass();
123 } 140 }
124 141
125 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { 142 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() {
126 VADisplayAttribute item = {VADisplayAttribRenderMode, 143 VADisplayAttribute item = {VADisplayAttribRenderMode,
127 1, // At least support '_LOCAL_OVERLAY'. 144 1, // At least support '_LOCAL_OVERLAY'.
128 -1, // The maximum possible support 'ALL'. 145 -1, // The maximum possible support 'ALL'.
129 VA_RENDER_MODE_LOCAL_GPU, 146 VA_RENDER_MODE_LOCAL_GPU,
130 VA_DISPLAY_ATTRIB_SETTABLE}; 147 VA_DISPLAY_ATTRIB_SETTABLE};
131 148
132 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); 149 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1);
133 if (va_res != VA_STATUS_SUCCESS) 150 if (va_res != VA_STATUS_SUCCESS)
134 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; 151 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default.";
135 } 152 }
136 153
137 bool VaapiWrapper::Initialize(media::VideoCodecProfile profile, 154 bool VaapiWrapper::Initialize(CodecMode mode,
155 media::VideoCodecProfile profile,
138 Display* x_display, 156 Display* x_display,
139 const base::Closure& report_error_to_uma_cb) { 157 const base::Closure& report_error_to_uma_cb) {
140 static bool vaapi_functions_initialized = PostSandboxInitialization(); 158 static bool vaapi_functions_initialized = PostSandboxInitialization();
141 if (!vaapi_functions_initialized) { 159 if (!vaapi_functions_initialized) {
142 DVLOG(1) << "Failed to initialize VAAPI libs"; 160 DVLOG(1) << "Failed to initialize VAAPI libs";
143 return false; 161 return false;
144 } 162 }
145 163
146 report_error_to_uma_cb_ = report_error_to_uma_cb; 164 report_error_to_uma_cb_ = report_error_to_uma_cb;
147 165
(...skipping 29 matching lines...) Expand all
177 } 195 }
178 196
179 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); 197 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles));
180 198
181 VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles); 199 VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles);
182 if (va_profile == VAProfileNone) { 200 if (va_profile == VAProfileNone) {
183 DVLOG(1) << "Unsupported profile"; 201 DVLOG(1) << "Unsupported profile";
184 return false; 202 return false;
185 } 203 }
186 204
187 VAConfigAttrib attrib = {VAConfigAttribRTFormat, 0}; 205 // Query the driver for supported entrypoints.
188 const VAEntrypoint kEntrypoint = VAEntrypointVLD; 206 int max_entrypoints = vaMaxNumEntrypoints(va_display_);
189 va_res = vaGetConfigAttributes(va_display_, va_profile, kEntrypoint, 207 std::vector<VAEntrypoint> supported_entrypoints(
190 &attrib, 1); 208 base::checked_cast<size_t>(max_entrypoints));
209
210 int num_supported_entrypoints;
211 va_res = vaQueryConfigEntrypoints(va_display_,
212 va_profile,
213 &supported_entrypoints[0],
214 &num_supported_entrypoints);
215 VA_SUCCESS_OR_RETURN(va_res, "vaQueryConfigEntrypoints failed", false);
216 if (num_supported_entrypoints < 0 ||
217 num_supported_entrypoints > max_entrypoints) {
218 DVLOG(1) << "vaQueryConfigEntrypoints returned: "
219 << num_supported_entrypoints;
220 return false;
221 }
222
223 VAEntrypoint entrypoint =
224 (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD);
225
226 if (std::find(supported_entrypoints.begin(),
227 supported_entrypoints.end(),
228 entrypoint) == supported_entrypoints.end()) {
229 DVLOG(1) << "Unsupported entrypoint";
230 return false;
231 }
232
233 // Query the driver for required attributes.
234 std::vector<VAConfigAttrib> required_attribs;
235 required_attribs.insert(
236 required_attribs.end(),
237 kCommonVAConfigAttribs,
238 kCommonVAConfigAttribs + arraysize(kCommonVAConfigAttribs));
239 if (mode == kEncode) {
240 required_attribs.insert(
241 required_attribs.end(),
242 kEncodeVAConfigAttribs,
243 kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs));
244 }
245
246 std::vector<VAConfigAttrib> attribs = required_attribs;
247 for (size_t i = 0; i < required_attribs.size(); ++i)
248 attribs[i].value = 0;
249
250 va_res = vaGetConfigAttributes(
251 va_display_, va_profile, entrypoint, &attribs[0], attribs.size());
191 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); 252 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false);
192 253
193 if (!(attrib.value & VA_RT_FORMAT_YUV420)) { 254 for (size_t i = 0; i < required_attribs.size(); ++i) {
194 DVLOG(1) << "YUV420 not supported by this VAAPI implementation"; 255 if (attribs[i].type != required_attribs[i].type ||
195 return false; 256 (attribs[i].value & required_attribs[i].value) !=
257 required_attribs[i].value) {
258 DVLOG(1) << "Unsupported value " << required_attribs[i].value
259 << " for attribute type " << required_attribs[i].type;
260 return false;
261 }
196 } 262 }
197 263
198 TryToSetVADisplayAttributeToLocalGPU(); 264 TryToSetVADisplayAttributeToLocalGPU();
199 265
200 va_res = vaCreateConfig(va_display_, va_profile, kEntrypoint, 266 va_res = vaCreateConfig(va_display_,
201 &attrib, 1, &va_config_id_); 267 va_profile,
268 entrypoint,
269 &required_attribs[0],
270 required_attribs.size(),
271 &va_config_id_);
202 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); 272 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false);
203 273
204 return true; 274 return true;
205 } 275 }
206 276
207 void VaapiWrapper::Deinitialize() { 277 void VaapiWrapper::Deinitialize() {
208 base::AutoLock auto_lock(va_lock_); 278 base::AutoLock auto_lock(va_lock_);
209 279
210 if (va_config_id_ != VA_INVALID_ID) { 280 if (va_config_id_ != VA_INVALID_ID) {
211 VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_); 281 VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
292 362
293 VABufferID buffer_id; 363 VABufferID buffer_id;
294 VAStatus va_res = vaCreateBuffer(va_display_, va_context_id_, 364 VAStatus va_res = vaCreateBuffer(va_display_, va_context_id_,
295 va_buffer_type, size, 365 va_buffer_type, size,
296 1, buffer, &buffer_id); 366 1, buffer, &buffer_id);
297 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false); 367 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false);
298 368
299 switch (va_buffer_type) { 369 switch (va_buffer_type) {
300 case VASliceParameterBufferType: 370 case VASliceParameterBufferType:
301 case VASliceDataBufferType: 371 case VASliceDataBufferType:
372 case VAEncSliceParameterBufferType:
302 pending_slice_bufs_.push_back(buffer_id); 373 pending_slice_bufs_.push_back(buffer_id);
303 break; 374 break;
304 375
305 default: 376 default:
306 pending_va_bufs_.push_back(buffer_id); 377 pending_va_bufs_.push_back(buffer_id);
307 break; 378 break;
308 } 379 }
309 380
310 return true; 381 return true;
311 } 382 }
312 383
384 bool VaapiWrapper::SubmitVAEncMiscParamBuffer(
385 VAEncMiscParameterType misc_param_type,
386 size_t size,
387 void* buffer) {
388 base::AutoLock auto_lock(va_lock_);
389
390 VABufferID buffer_id;
391 VAStatus va_res = vaCreateBuffer(va_display_,
392 va_context_id_,
393 VAEncMiscParameterBufferType,
394 sizeof(VAEncMiscParameterBuffer) + size,
395 1,
396 NULL,
397 &buffer_id);
398 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false);
399
400 void* data_ptr = NULL;
401 va_res = vaMapBuffer(va_display_, buffer_id, &data_ptr);
402 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed");
403 if (va_res != VA_STATUS_SUCCESS) {
404 vaDestroyBuffer(va_display_, buffer_id);
405 return false;
406 }
407
408 DCHECK(data_ptr);
409
410 VAEncMiscParameterBuffer* misc_param =
411 reinterpret_cast<VAEncMiscParameterBuffer*>(data_ptr);
412 misc_param->type = misc_param_type;
413 memcpy(misc_param->data, buffer, size);
414 va_res = vaUnmapBuffer(va_display_, buffer_id);
415 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
416
417 pending_va_bufs_.push_back(buffer_id);
418 return true;
419 }
420
313 void VaapiWrapper::DestroyPendingBuffers() { 421 void VaapiWrapper::DestroyPendingBuffers() {
314 base::AutoLock auto_lock(va_lock_); 422 base::AutoLock auto_lock(va_lock_);
315 423
316 for (size_t i = 0; i < pending_va_bufs_.size(); ++i) { 424 for (size_t i = 0; i < pending_va_bufs_.size(); ++i) {
317 VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_bufs_[i]); 425 VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_bufs_[i]);
318 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); 426 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
319 } 427 }
320 428
321 for (size_t i = 0; i < pending_slice_bufs_.size(); ++i) { 429 for (size_t i = 0; i < pending_slice_bufs_.size(); ++i) {
322 VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_bufs_[i]); 430 VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_bufs_[i]);
323 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); 431 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
324 } 432 }
325 433
326 pending_va_bufs_.clear(); 434 pending_va_bufs_.clear();
327 pending_slice_bufs_.clear(); 435 pending_slice_bufs_.clear();
328 } 436 }
329 437
330 bool VaapiWrapper::SubmitDecode(VASurfaceID va_surface_id) { 438 bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) {
439 base::AutoLock auto_lock(va_lock_);
440 VAStatus va_res = vaCreateBuffer(va_display_,
441 va_context_id_,
442 VAEncCodedBufferType,
443 size,
444 1,
445 NULL,
446 buffer_id);
447 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a coded buffer", false);
448
449 DCHECK(coded_buffers_.insert(*buffer_id).second);
450 return true;
451 }
452
453 void VaapiWrapper::DestroyCodedBuffers() {
454 base::AutoLock auto_lock(va_lock_);
455
456 for (std::set<VABufferID>::const_iterator iter = coded_buffers_.begin();
457 iter != coded_buffers_.end();
458 ++iter) {
459 VAStatus va_res = vaDestroyBuffer(va_display_, *iter);
460 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
461 }
462
463 coded_buffers_.clear();
464 }
465
466 bool VaapiWrapper::Execute(VASurfaceID va_surface_id) {
331 base::AutoLock auto_lock(va_lock_); 467 base::AutoLock auto_lock(va_lock_);
332 468
333 DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size(); 469 DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size();
334 DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size(); 470 DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size();
335 DVLOG(4) << "Decoding into VA surface " << va_surface_id; 471 DVLOG(4) << "Target VA surface " << va_surface_id;
336 472
337 // Get ready to decode into surface. 473 // Get ready to execute for given surface.
338 VAStatus va_res = vaBeginPicture(va_display_, va_context_id_, 474 VAStatus va_res = vaBeginPicture(va_display_, va_context_id_,
339 va_surface_id); 475 va_surface_id);
340 VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false); 476 VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false);
341 477
342 // Commit parameter and slice buffers. 478 if (pending_va_bufs_.size() > 0) {
343 va_res = vaRenderPicture(va_display_, va_context_id_, 479 // Commit parameter and slice buffers.
344 &pending_va_bufs_[0], pending_va_bufs_.size()); 480 va_res = vaRenderPicture(va_display_,
345 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for va_bufs failed", false); 481 va_context_id_,
482 &pending_va_bufs_[0],
483 pending_va_bufs_.size());
484 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for va_bufs failed", false);
485 }
346 486
347 va_res = vaRenderPicture(va_display_, va_context_id_, 487 if (pending_slice_bufs_.size() > 0) {
348 &pending_slice_bufs_[0], 488 va_res = vaRenderPicture(va_display_,
349 pending_slice_bufs_.size()); 489 va_context_id_,
350 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for slices failed", false); 490 &pending_slice_bufs_[0],
491 pending_slice_bufs_.size());
492 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for slices failed", false);
493 }
351 494
352 // Instruct HW decoder to start processing committed buffers (decode this 495 // Instruct HW codec to start processing committed buffers.
353 // picture). This does not block until the end of decode. 496 // Does not block and the job is not finished after this returns.
354 va_res = vaEndPicture(va_display_, va_context_id_); 497 va_res = vaEndPicture(va_display_, va_context_id_);
355 VA_SUCCESS_OR_RETURN(va_res, "vaEndPicture failed", false); 498 VA_SUCCESS_OR_RETURN(va_res, "vaEndPicture failed", false);
356 499
357 return true; 500 return true;
358 } 501 }
359 502
360 bool VaapiWrapper::DecodeAndDestroyPendingBuffers(VASurfaceID va_surface_id) { 503 bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) {
361 bool result = SubmitDecode(va_surface_id); 504 bool result = Execute(va_surface_id);
362 DestroyPendingBuffers(); 505 DestroyPendingBuffers();
363 return result; 506 return result;
364 } 507 }
365 508
366 bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, 509 bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id,
367 Pixmap x_pixmap, 510 Pixmap x_pixmap,
368 gfx::Size dest_size) { 511 gfx::Size dest_size) {
369 base::AutoLock auto_lock(va_lock_); 512 base::AutoLock auto_lock(va_lock_);
370 513
371 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); 514 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
372 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); 515 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
373 516
374 // Put the data into an X Pixmap. 517 // Put the data into an X Pixmap.
375 va_res = vaPutSurface(va_display_, 518 va_res = vaPutSurface(va_display_,
376 va_surface_id, 519 va_surface_id,
377 x_pixmap, 520 x_pixmap,
378 0, 0, dest_size.width(), dest_size.height(), 521 0, 0, dest_size.width(), dest_size.height(),
379 0, 0, dest_size.width(), dest_size.height(), 522 0, 0, dest_size.width(), dest_size.height(),
380 NULL, 0, 0); 523 NULL, 0, 0);
381 VA_SUCCESS_OR_RETURN(va_res, "Failed putting decode surface to pixmap", 524 VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false);
382 false);
383 return true; 525 return true;
384 } 526 }
385 527
386 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id, 528 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id,
387 VAImage* image, 529 VAImage* image,
388 void** mem) { 530 void** mem) {
389 base::AutoLock auto_lock(va_lock_); 531 base::AutoLock auto_lock(va_lock_);
390 532
391 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); 533 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
392 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); 534 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
393 535
394 // Derive a VAImage from the VASurface 536 // Derive a VAImage from the VASurface
395 va_res = vaDeriveImage(va_display_, va_surface_id, image); 537 va_res = vaDeriveImage(va_display_, va_surface_id, image);
396 VA_LOG_ON_ERROR(va_res, "vaDeriveImage failed"); 538 VA_LOG_ON_ERROR(va_res, "vaDeriveImage failed");
397 if (va_res != VA_STATUS_SUCCESS) 539 if (va_res != VA_STATUS_SUCCESS)
398 return false; 540 return false;
399 541
400 // Map the VAImage into memory 542 // Map the VAImage into memory
401 va_res = vaMapBuffer(va_display_, image->buf, mem); 543 va_res = vaMapBuffer(va_display_, image->buf, mem);
402 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); 544 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed");
403 if (va_res == VA_STATUS_SUCCESS) 545 if (va_res == VA_STATUS_SUCCESS)
404 return true; 546 return true;
405 547
406 vaDestroyImage(va_display_, image->image_id); 548 va_res = vaDestroyImage(va_display_, image->image_id);
549 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed");
550
407 return false; 551 return false;
408 } 552 }
409 553
410 void VaapiWrapper::ReturnVaImageForTesting(VAImage* image) { 554 void VaapiWrapper::ReturnVaImageForTesting(VAImage* image) {
411 base::AutoLock auto_lock(va_lock_); 555 base::AutoLock auto_lock(va_lock_);
412 556
413 vaUnmapBuffer(va_display_, image->buf); 557 VAStatus va_res = vaUnmapBuffer(va_display_, image->buf);
414 vaDestroyImage(va_display_, image->image_id); 558 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
559
560 va_res = vaDestroyImage(va_display_, image->image_id);
561 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed");
562 }
563
564 static void DestroyVAImage(VADisplay va_display, VAImage image) {
565 if (image.image_id != VA_INVALID_ID)
566 vaDestroyImage(va_display, image.image_id);
567 }
568
569 bool VaapiWrapper::UploadVideoFrameToSurface(
570 const scoped_refptr<media::VideoFrame>& frame,
571 VASurfaceID va_surface_id) {
572 base::AutoLock auto_lock(va_lock_);
573
574 VAImage image;
575 VAStatus va_res = vaDeriveImage(va_display_, va_surface_id, &image);
576 VA_SUCCESS_OR_RETURN(va_res, "vaDeriveImage failed", false);
577 base::ScopedClosureRunner vaimage_deleter(
578 base::Bind(&DestroyVAImage, va_display_, image));
579
580 if (image.format.fourcc != VA_FOURCC_NV12) {
581 DVLOG(1) << "Unsupported image format: " << image.format.fourcc;
582 return false;
583 }
584
585 if (gfx::Rect(image.width, image.height) < gfx::Rect(frame->coded_size())) {
586 DVLOG(1) << "Buffer too small to fit the frame.";
587 return false;
588 }
589
590 void* image_ptr = NULL;
591 va_res = vaMapBuffer(va_display_, image.buf, &image_ptr);
592 VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false);
593 DCHECK(image_ptr);
594
595 int ret = 0;
596 {
597 base::AutoUnlock auto_unlock(va_lock_);
598 ret = libyuv::I420ToNV12(frame->data(media::VideoFrame::kYPlane),
599 frame->stride(media::VideoFrame::kYPlane),
600 frame->data(media::VideoFrame::kUPlane),
601 frame->stride(media::VideoFrame::kUPlane),
602 frame->data(media::VideoFrame::kVPlane),
603 frame->stride(media::VideoFrame::kVPlane),
604 static_cast<uint8*>(image_ptr) + image.offsets[0],
605 image.pitches[0],
606 static_cast<uint8*>(image_ptr) + image.offsets[1],
607 image.pitches[1],
608 image.width,
609 image.height);
610 }
611
612 va_res = vaUnmapBuffer(va_display_, image.buf);
613 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
614
615 return ret == 0;
616 }
617
618 bool VaapiWrapper::DownloadAndDestroyCodedBuffer(VABufferID buffer_id,
619 VASurfaceID sync_surface_id,
620 uint8* target_ptr,
621 size_t target_size,
622 size_t* coded_data_size) {
623 base::AutoLock auto_lock(va_lock_);
624
625 VAStatus va_res = vaSyncSurface(va_display_, sync_surface_id);
626 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
627
628 VACodedBufferSegment* buffer_segment = NULL;
629 va_res = vaMapBuffer(
630 va_display_, buffer_id, reinterpret_cast<void**>(&buffer_segment));
631 VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false);
632 DCHECK(target_ptr);
633
634 {
635 base::AutoUnlock auto_unlock(va_lock_);
636 *coded_data_size = 0;
637
638 while (buffer_segment) {
639 DCHECK(buffer_segment->buf);
640
641 if (buffer_segment->size > target_size) {
642 DVLOG(1) << "Insufficient output buffer size";
643 break;
644 }
645
646 memcpy(target_ptr, buffer_segment->buf, buffer_segment->size);
647
648 target_ptr += buffer_segment->size;
649 *coded_data_size += buffer_segment->size;
650 target_size -= buffer_segment->size;
651
652 buffer_segment =
653 reinterpret_cast<VACodedBufferSegment*>(buffer_segment->next);
654 }
655 }
656
657 va_res = vaUnmapBuffer(va_display_, buffer_id);
658 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed");
659
660 va_res = vaDestroyBuffer(va_display_, buffer_id);
661 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
662
663 DCHECK(coded_buffers_.erase(buffer_id));
664
665 return buffer_segment == NULL;
415 } 666 }
416 667
417 // static 668 // static
418 bool VaapiWrapper::PostSandboxInitialization() { 669 bool VaapiWrapper::PostSandboxInitialization() {
419 StubPathMap paths; 670 StubPathMap paths;
420 paths[kModuleVa].push_back(kVaLib); 671 paths[kModuleVa].push_back(kVaLib);
421 672
422 return InitializeStubs(paths); 673 return InitializeStubs(paths);
423 } 674 }
424 675
425 } // namespace content 676 } // namespace content
OLDNEW
« no previous file with comments | « content/common/gpu/media/vaapi_wrapper.h ('k') | content/common/gpu/media/video_encode_accelerator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698