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

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

Issue 357903003: Revert 279958 "Revert "Revert 279650 "Add VaapiVideoEncodeAccele..." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 6 years, 6 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"
11 #include "base/logging.h" 10 #include "base/logging.h"
12 #include "base/numerics/safe_conversions.h" 11 #include "base/numerics/safe_conversions.h"
13 // Auto-generated for dlopen libva libraries 12 // Auto-generated for dlopen libva libraries
14 #include "content/common/gpu/media/va_stubs.h" 13 #include "content/common/gpu/media/va_stubs.h"
15 #include "third_party/libyuv/include/libyuv.h"
16 14
17 using content_common_gpu_media::kModuleVa; 15 using content_common_gpu_media::kModuleVa;
18 using content_common_gpu_media::InitializeStubs; 16 using content_common_gpu_media::InitializeStubs;
19 using content_common_gpu_media::StubPathMap; 17 using content_common_gpu_media::StubPathMap;
20 18
21 // libva-x11 depends on libva, so dlopen libva-x11 is enough 19 // libva-x11 depends on libva, so dlopen libva-x11 is enough
22 static const base::FilePath::CharType kVaLib[] = 20 static const base::FilePath::CharType kVaLib[] =
23 FILE_PATH_LITERAL("libva-x11.so.1"); 21 FILE_PATH_LITERAL("libva-x11.so.1");
24 22
25 #define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \ 23 #define LOG_VA_ERROR_AND_REPORT(va_error, err_msg) \
(...skipping 12 matching lines...) Expand all
38 #define VA_SUCCESS_OR_RETURN(va_error, err_msg, ret) \ 36 #define VA_SUCCESS_OR_RETURN(va_error, err_msg, ret) \
39 do { \ 37 do { \
40 if ((va_error) != VA_STATUS_SUCCESS) { \ 38 if ((va_error) != VA_STATUS_SUCCESS) { \
41 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \ 39 LOG_VA_ERROR_AND_REPORT(va_error, err_msg); \
42 return (ret); \ 40 return (ret); \
43 } \ 41 } \
44 } while (0) 42 } while (0)
45 43
46 namespace content { 44 namespace content {
47 45
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
60 // Maps Profile enum values to VaProfile values. 46 // Maps Profile enum values to VaProfile values.
61 static VAProfile ProfileToVAProfile( 47 static VAProfile ProfileToVAProfile(
62 media::VideoCodecProfile profile, 48 media::VideoCodecProfile profile,
63 const std::vector<VAProfile>& supported_profiles) { 49 const std::vector<VAProfile>& supported_profiles) {
64 50
65 VAProfile va_profile = VAProfileNone; 51 VAProfile va_profile = VAProfileNone;
66 52
67 switch (profile) { 53 switch (profile) {
68 case media::H264PROFILE_BASELINE: 54 case media::H264PROFILE_BASELINE:
69 va_profile = VAProfileH264Baseline; 55 va_profile = VAProfileH264Baseline;
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 } 99 }
114 100
115 VaapiWrapper::VaapiWrapper() 101 VaapiWrapper::VaapiWrapper()
116 : va_display_(NULL), 102 : va_display_(NULL),
117 va_config_id_(VA_INVALID_ID), 103 va_config_id_(VA_INVALID_ID),
118 va_context_id_(VA_INVALID_ID) { 104 va_context_id_(VA_INVALID_ID) {
119 } 105 }
120 106
121 VaapiWrapper::~VaapiWrapper() { 107 VaapiWrapper::~VaapiWrapper() {
122 DestroyPendingBuffers(); 108 DestroyPendingBuffers();
123 DestroyCodedBuffers();
124 DestroySurfaces(); 109 DestroySurfaces();
125 Deinitialize(); 110 Deinitialize();
126 } 111 }
127 112
128 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( 113 scoped_ptr<VaapiWrapper> VaapiWrapper::Create(
129 CodecMode mode,
130 media::VideoCodecProfile profile, 114 media::VideoCodecProfile profile,
131 Display* x_display, 115 Display* x_display,
132 const base::Closure& report_error_to_uma_cb) { 116 const base::Closure& report_error_to_uma_cb) {
133 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); 117 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper());
134 118
135 if (!vaapi_wrapper->Initialize( 119 if (!vaapi_wrapper->Initialize(profile, x_display, report_error_to_uma_cb))
136 mode, profile, x_display, report_error_to_uma_cb))
137 vaapi_wrapper.reset(); 120 vaapi_wrapper.reset();
138 121
139 return vaapi_wrapper.Pass(); 122 return vaapi_wrapper.Pass();
140 } 123 }
141 124
142 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() { 125 void VaapiWrapper::TryToSetVADisplayAttributeToLocalGPU() {
143 VADisplayAttribute item = {VADisplayAttribRenderMode, 126 VADisplayAttribute item = {VADisplayAttribRenderMode,
144 1, // At least support '_LOCAL_OVERLAY'. 127 1, // At least support '_LOCAL_OVERLAY'.
145 -1, // The maximum possible support 'ALL'. 128 -1, // The maximum possible support 'ALL'.
146 VA_RENDER_MODE_LOCAL_GPU, 129 VA_RENDER_MODE_LOCAL_GPU,
147 VA_DISPLAY_ATTRIB_SETTABLE}; 130 VA_DISPLAY_ATTRIB_SETTABLE};
148 131
149 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); 132 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1);
150 if (va_res != VA_STATUS_SUCCESS) 133 if (va_res != VA_STATUS_SUCCESS)
151 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; 134 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default.";
152 } 135 }
153 136
154 bool VaapiWrapper::Initialize(CodecMode mode, 137 bool VaapiWrapper::Initialize(media::VideoCodecProfile profile,
155 media::VideoCodecProfile profile,
156 Display* x_display, 138 Display* x_display,
157 const base::Closure& report_error_to_uma_cb) { 139 const base::Closure& report_error_to_uma_cb) {
158 static bool vaapi_functions_initialized = PostSandboxInitialization(); 140 static bool vaapi_functions_initialized = PostSandboxInitialization();
159 if (!vaapi_functions_initialized) { 141 if (!vaapi_functions_initialized) {
160 DVLOG(1) << "Failed to initialize VAAPI libs"; 142 DVLOG(1) << "Failed to initialize VAAPI libs";
161 return false; 143 return false;
162 } 144 }
163 145
164 report_error_to_uma_cb_ = report_error_to_uma_cb; 146 report_error_to_uma_cb_ = report_error_to_uma_cb;
165 147
(...skipping 29 matching lines...) Expand all
195 } 177 }
196 178
197 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles)); 179 supported_profiles.resize(base::checked_cast<size_t>(num_supported_profiles));
198 180
199 VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles); 181 VAProfile va_profile = ProfileToVAProfile(profile, supported_profiles);
200 if (va_profile == VAProfileNone) { 182 if (va_profile == VAProfileNone) {
201 DVLOG(1) << "Unsupported profile"; 183 DVLOG(1) << "Unsupported profile";
202 return false; 184 return false;
203 } 185 }
204 186
205 // Query the driver for supported entrypoints. 187 VAConfigAttrib attrib = {VAConfigAttribRTFormat, 0};
206 int max_entrypoints = vaMaxNumEntrypoints(va_display_); 188 const VAEntrypoint kEntrypoint = VAEntrypointVLD;
207 std::vector<VAEntrypoint> supported_entrypoints( 189 va_res = vaGetConfigAttributes(va_display_, va_profile, kEntrypoint,
208 base::checked_cast<size_t>(max_entrypoints)); 190 &attrib, 1);
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());
252 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false); 191 VA_SUCCESS_OR_RETURN(va_res, "vaGetConfigAttributes failed", false);
253 192
254 for (size_t i = 0; i < required_attribs.size(); ++i) { 193 if (!(attrib.value & VA_RT_FORMAT_YUV420)) {
255 if (attribs[i].type != required_attribs[i].type || 194 DVLOG(1) << "YUV420 not supported by this VAAPI implementation";
256 (attribs[i].value & required_attribs[i].value) != 195 return false;
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 }
262 } 196 }
263 197
264 TryToSetVADisplayAttributeToLocalGPU(); 198 TryToSetVADisplayAttributeToLocalGPU();
265 199
266 va_res = vaCreateConfig(va_display_, 200 va_res = vaCreateConfig(va_display_, va_profile, kEntrypoint,
267 va_profile, 201 &attrib, 1, &va_config_id_);
268 entrypoint,
269 &required_attribs[0],
270 required_attribs.size(),
271 &va_config_id_);
272 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false); 202 VA_SUCCESS_OR_RETURN(va_res, "vaCreateConfig failed", false);
273 203
274 return true; 204 return true;
275 } 205 }
276 206
277 void VaapiWrapper::Deinitialize() { 207 void VaapiWrapper::Deinitialize() {
278 base::AutoLock auto_lock(va_lock_); 208 base::AutoLock auto_lock(va_lock_);
279 209
280 if (va_config_id_ != VA_INVALID_ID) { 210 if (va_config_id_ != VA_INVALID_ID) {
281 VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_); 211 VAStatus va_res = vaDestroyConfig(va_display_, va_config_id_);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
362 292
363 VABufferID buffer_id; 293 VABufferID buffer_id;
364 VAStatus va_res = vaCreateBuffer(va_display_, va_context_id_, 294 VAStatus va_res = vaCreateBuffer(va_display_, va_context_id_,
365 va_buffer_type, size, 295 va_buffer_type, size,
366 1, buffer, &buffer_id); 296 1, buffer, &buffer_id);
367 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false); 297 VA_SUCCESS_OR_RETURN(va_res, "Failed to create a VA buffer", false);
368 298
369 switch (va_buffer_type) { 299 switch (va_buffer_type) {
370 case VASliceParameterBufferType: 300 case VASliceParameterBufferType:
371 case VASliceDataBufferType: 301 case VASliceDataBufferType:
372 case VAEncSliceParameterBufferType:
373 pending_slice_bufs_.push_back(buffer_id); 302 pending_slice_bufs_.push_back(buffer_id);
374 break; 303 break;
375 304
376 default: 305 default:
377 pending_va_bufs_.push_back(buffer_id); 306 pending_va_bufs_.push_back(buffer_id);
378 break; 307 break;
379 } 308 }
380 309
381 return true; 310 return true;
382 } 311 }
383 312
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
421 void VaapiWrapper::DestroyPendingBuffers() { 313 void VaapiWrapper::DestroyPendingBuffers() {
422 base::AutoLock auto_lock(va_lock_); 314 base::AutoLock auto_lock(va_lock_);
423 315
424 for (size_t i = 0; i < pending_va_bufs_.size(); ++i) { 316 for (size_t i = 0; i < pending_va_bufs_.size(); ++i) {
425 VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_bufs_[i]); 317 VAStatus va_res = vaDestroyBuffer(va_display_, pending_va_bufs_[i]);
426 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); 318 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
427 } 319 }
428 320
429 for (size_t i = 0; i < pending_slice_bufs_.size(); ++i) { 321 for (size_t i = 0; i < pending_slice_bufs_.size(); ++i) {
430 VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_bufs_[i]); 322 VAStatus va_res = vaDestroyBuffer(va_display_, pending_slice_bufs_[i]);
431 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed"); 323 VA_LOG_ON_ERROR(va_res, "vaDestroyBuffer failed");
432 } 324 }
433 325
434 pending_va_bufs_.clear(); 326 pending_va_bufs_.clear();
435 pending_slice_bufs_.clear(); 327 pending_slice_bufs_.clear();
436 } 328 }
437 329
438 bool VaapiWrapper::CreateCodedBuffer(size_t size, VABufferID* buffer_id) { 330 bool VaapiWrapper::SubmitDecode(VASurfaceID va_surface_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) {
467 base::AutoLock auto_lock(va_lock_); 331 base::AutoLock auto_lock(va_lock_);
468 332
469 DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size(); 333 DVLOG(4) << "Pending VA bufs to commit: " << pending_va_bufs_.size();
470 DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size(); 334 DVLOG(4) << "Pending slice bufs to commit: " << pending_slice_bufs_.size();
471 DVLOG(4) << "Target VA surface " << va_surface_id; 335 DVLOG(4) << "Decoding into VA surface " << va_surface_id;
472 336
473 // Get ready to execute for given surface. 337 // Get ready to decode into surface.
474 VAStatus va_res = vaBeginPicture(va_display_, va_context_id_, 338 VAStatus va_res = vaBeginPicture(va_display_, va_context_id_,
475 va_surface_id); 339 va_surface_id);
476 VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false); 340 VA_SUCCESS_OR_RETURN(va_res, "vaBeginPicture failed", false);
477 341
478 if (pending_va_bufs_.size() > 0) { 342 // Commit parameter and slice buffers.
479 // Commit parameter and slice buffers. 343 va_res = vaRenderPicture(va_display_, va_context_id_,
480 va_res = vaRenderPicture(va_display_, 344 &pending_va_bufs_[0], pending_va_bufs_.size());
481 va_context_id_, 345 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for va_bufs failed", false);
482 &pending_va_bufs_[0],
483 pending_va_bufs_.size());
484 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for va_bufs failed", false);
485 }
486 346
487 if (pending_slice_bufs_.size() > 0) { 347 va_res = vaRenderPicture(va_display_, va_context_id_,
488 va_res = vaRenderPicture(va_display_, 348 &pending_slice_bufs_[0],
489 va_context_id_, 349 pending_slice_bufs_.size());
490 &pending_slice_bufs_[0], 350 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for slices failed", false);
491 pending_slice_bufs_.size());
492 VA_SUCCESS_OR_RETURN(va_res, "vaRenderPicture for slices failed", false);
493 }
494 351
495 // Instruct HW codec to start processing committed buffers. 352 // Instruct HW decoder to start processing committed buffers (decode this
496 // Does not block and the job is not finished after this returns. 353 // picture). This does not block until the end of decode.
497 va_res = vaEndPicture(va_display_, va_context_id_); 354 va_res = vaEndPicture(va_display_, va_context_id_);
498 VA_SUCCESS_OR_RETURN(va_res, "vaEndPicture failed", false); 355 VA_SUCCESS_OR_RETURN(va_res, "vaEndPicture failed", false);
499 356
500 return true; 357 return true;
501 } 358 }
502 359
503 bool VaapiWrapper::ExecuteAndDestroyPendingBuffers(VASurfaceID va_surface_id) { 360 bool VaapiWrapper::DecodeAndDestroyPendingBuffers(VASurfaceID va_surface_id) {
504 bool result = Execute(va_surface_id); 361 bool result = SubmitDecode(va_surface_id);
505 DestroyPendingBuffers(); 362 DestroyPendingBuffers();
506 return result; 363 return result;
507 } 364 }
508 365
509 bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id, 366 bool VaapiWrapper::PutSurfaceIntoPixmap(VASurfaceID va_surface_id,
510 Pixmap x_pixmap, 367 Pixmap x_pixmap,
511 gfx::Size dest_size) { 368 gfx::Size dest_size) {
512 base::AutoLock auto_lock(va_lock_); 369 base::AutoLock auto_lock(va_lock_);
513 370
514 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); 371 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
515 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); 372 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
516 373
517 // Put the data into an X Pixmap. 374 // Put the data into an X Pixmap.
518 va_res = vaPutSurface(va_display_, 375 va_res = vaPutSurface(va_display_,
519 va_surface_id, 376 va_surface_id,
520 x_pixmap, 377 x_pixmap,
521 0, 0, dest_size.width(), dest_size.height(), 378 0, 0, dest_size.width(), dest_size.height(),
522 0, 0, dest_size.width(), dest_size.height(), 379 0, 0, dest_size.width(), dest_size.height(),
523 NULL, 0, 0); 380 NULL, 0, 0);
524 VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false); 381 VA_SUCCESS_OR_RETURN(va_res, "Failed putting decode surface to pixmap",
382 false);
525 return true; 383 return true;
526 } 384 }
527 385
528 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id, 386 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id,
529 VAImage* image, 387 VAImage* image,
530 void** mem) { 388 void** mem) {
531 base::AutoLock auto_lock(va_lock_); 389 base::AutoLock auto_lock(va_lock_);
532 390
533 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); 391 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id);
534 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); 392 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false);
535 393
536 // Derive a VAImage from the VASurface 394 // Derive a VAImage from the VASurface
537 va_res = vaDeriveImage(va_display_, va_surface_id, image); 395 va_res = vaDeriveImage(va_display_, va_surface_id, image);
538 VA_LOG_ON_ERROR(va_res, "vaDeriveImage failed"); 396 VA_LOG_ON_ERROR(va_res, "vaDeriveImage failed");
539 if (va_res != VA_STATUS_SUCCESS) 397 if (va_res != VA_STATUS_SUCCESS)
540 return false; 398 return false;
541 399
542 // Map the VAImage into memory 400 // Map the VAImage into memory
543 va_res = vaMapBuffer(va_display_, image->buf, mem); 401 va_res = vaMapBuffer(va_display_, image->buf, mem);
544 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); 402 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed");
545 if (va_res == VA_STATUS_SUCCESS) 403 if (va_res == VA_STATUS_SUCCESS)
546 return true; 404 return true;
547 405
548 va_res = vaDestroyImage(va_display_, image->image_id); 406 vaDestroyImage(va_display_, image->image_id);
549 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed");
550
551 return false; 407 return false;
552 } 408 }
553 409
554 void VaapiWrapper::ReturnVaImageForTesting(VAImage* image) { 410 void VaapiWrapper::ReturnVaImageForTesting(VAImage* image) {
555 base::AutoLock auto_lock(va_lock_); 411 base::AutoLock auto_lock(va_lock_);
556 412
557 VAStatus va_res = vaUnmapBuffer(va_display_, image->buf); 413 vaUnmapBuffer(va_display_, image->buf);
558 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); 414 vaDestroyImage(va_display_, image->image_id);
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;
666 } 415 }
667 416
668 // static 417 // static
669 bool VaapiWrapper::PostSandboxInitialization() { 418 bool VaapiWrapper::PostSandboxInitialization() {
670 StubPathMap paths; 419 StubPathMap paths;
671 paths[kModuleVa].push_back(kVaLib); 420 paths[kModuleVa].push_back(kVaLib);
672 421
673 return InitializeStubs(paths); 422 return InitializeStubs(paths);
674 } 423 }
675 424
676 } // namespace content 425 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698