OLD | NEW |
---|---|
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 <dlfcn.h> | 5 #include <dlfcn.h> |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "content/common/gpu/media/vaapi_wrapper.h" | 9 #include "content/common/gpu/media/vaapi_wrapper.h" |
10 | 10 |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
107 unsigned short desth, | 107 unsigned short desth, |
108 VARectangle *cliprects, | 108 VARectangle *cliprects, |
109 unsigned int number_cliprects, | 109 unsigned int number_cliprects, |
110 unsigned int flags); | 110 unsigned int flags); |
111 typedef VAStatus (*VaapiRenderPicture)(VADisplay dpy, | 111 typedef VAStatus (*VaapiRenderPicture)(VADisplay dpy, |
112 VAContextID context, | 112 VAContextID context, |
113 VABufferID *buffers, | 113 VABufferID *buffers, |
114 int num_buffers); | 114 int num_buffers); |
115 typedef VAStatus (*VaapiSyncSurface)(VADisplay dpy, VASurfaceID render_target); | 115 typedef VAStatus (*VaapiSyncSurface)(VADisplay dpy, VASurfaceID render_target); |
116 typedef VAStatus (*VaapiTerminate)(VADisplay dpy); | 116 typedef VAStatus (*VaapiTerminate)(VADisplay dpy); |
117 typedef VAStatus (*VaapiMapBuffer)(VADisplay dpy, | |
Pawel Osciak
2013/11/29 04:25:13
Please maintain lexicographical order.
chihchung
2013/11/29 14:06:30
Done.
| |
118 VABufferID buf_id, | |
119 void** pbuf); | |
120 typedef VAStatus (*VaapiUnmapBuffer)(VADisplay dpy, VABufferID buf_id); | |
121 typedef VAStatus (*VaapiDeriveImage)(VADisplay dpy, | |
122 VASurfaceID surface, | |
123 VAImage* image); | |
124 typedef VAStatus (*VaapiDestroyImage)(VADisplay dpy, VAImageID image); | |
117 | 125 |
118 #define VAAPI_SYM(name, handle) Vaapi##name VAAPI_##name = NULL | 126 #define VAAPI_SYM(name, handle) Vaapi##name VAAPI_##name = NULL |
119 | 127 |
120 VAAPI_SYM(BeginPicture, vaapi_handle); | 128 VAAPI_SYM(BeginPicture, vaapi_handle); |
121 VAAPI_SYM(CreateBuffer, vaapi_handle); | 129 VAAPI_SYM(CreateBuffer, vaapi_handle); |
122 VAAPI_SYM(CreateConfig, vaapi_handle); | 130 VAAPI_SYM(CreateConfig, vaapi_handle); |
123 VAAPI_SYM(CreateContext, vaapi_handle); | 131 VAAPI_SYM(CreateContext, vaapi_handle); |
124 VAAPI_SYM(CreateSurfaces, vaapi_handle); | 132 VAAPI_SYM(CreateSurfaces, vaapi_handle); |
125 VAAPI_SYM(DestroyBuffer, vaapi_handle); | 133 VAAPI_SYM(DestroyBuffer, vaapi_handle); |
126 VAAPI_SYM(DestroyConfig, vaapi_handle); | 134 VAAPI_SYM(DestroyConfig, vaapi_handle); |
127 VAAPI_SYM(DestroyContext, vaapi_handle); | 135 VAAPI_SYM(DestroyContext, vaapi_handle); |
128 VAAPI_SYM(DestroySurfaces, vaapi_handle); | 136 VAAPI_SYM(DestroySurfaces, vaapi_handle); |
129 VAAPI_SYM(DisplayIsValid, vaapi_handle); | 137 VAAPI_SYM(DisplayIsValid, vaapi_handle); |
130 VAAPI_SYM(EndPicture, vaapi_handle); | 138 VAAPI_SYM(EndPicture, vaapi_handle); |
131 VAAPI_SYM(ErrorStr, vaapi_handle); | 139 VAAPI_SYM(ErrorStr, vaapi_handle); |
132 VAAPI_SYM(GetConfigAttributes, vaapi_handle); | 140 VAAPI_SYM(GetConfigAttributes, vaapi_handle); |
133 VAAPI_SYM(GetDisplay, vaapi_x11_handle); | 141 VAAPI_SYM(GetDisplay, vaapi_x11_handle); |
134 VAAPI_SYM(Initialize, vaapi_handle); | 142 VAAPI_SYM(Initialize, vaapi_handle); |
135 VAAPI_SYM(PutSurface, vaapi_x11_handle); | 143 VAAPI_SYM(PutSurface, vaapi_x11_handle); |
136 VAAPI_SYM(RenderPicture, vaapi_handle); | 144 VAAPI_SYM(RenderPicture, vaapi_handle); |
137 VAAPI_SYM(SyncSurface, vaapi_x11_handle); | 145 VAAPI_SYM(SyncSurface, vaapi_x11_handle); |
138 VAAPI_SYM(Terminate, vaapi_handle); | 146 VAAPI_SYM(Terminate, vaapi_handle); |
147 VAAPI_SYM(MapBuffer, vaapi_handle); | |
148 VAAPI_SYM(UnmapBuffer, vaapi_handle); | |
149 VAAPI_SYM(DeriveImage, vaapi_handle); | |
150 VAAPI_SYM(DestroyImage, vaapi_handle); | |
139 | 151 |
140 #undef VAAPI_SYM | 152 #undef VAAPI_SYM |
141 | 153 |
142 // Maps Profile enum values to VaProfile values. | 154 // Maps Profile enum values to VaProfile values. |
143 static bool ProfileToVAProfile(media::VideoCodecProfile profile, | 155 static bool ProfileToVAProfile(media::VideoCodecProfile profile, |
144 VAProfile* va_profile) { | 156 VAProfile* va_profile) { |
145 switch (profile) { | 157 switch (profile) { |
146 case media::H264PROFILE_BASELINE: | 158 case media::H264PROFILE_BASELINE: |
147 *va_profile = VAProfileH264Baseline; | 159 *va_profile = VAProfileH264Baseline; |
148 break; | 160 break; |
(...skipping 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
426 va_surface_id, | 438 va_surface_id, |
427 x_pixmap, | 439 x_pixmap, |
428 0, 0, dest_size.width(), dest_size.height(), | 440 0, 0, dest_size.width(), dest_size.height(), |
429 0, 0, dest_size.width(), dest_size.height(), | 441 0, 0, dest_size.width(), dest_size.height(), |
430 NULL, 0, 0); | 442 NULL, 0, 0); |
431 VA_SUCCESS_OR_RETURN(va_res, "Failed putting decode surface to pixmap", | 443 VA_SUCCESS_OR_RETURN(va_res, "Failed putting decode surface to pixmap", |
432 false); | 444 false); |
433 return true; | 445 return true; |
434 } | 446 } |
435 | 447 |
448 static scoped_refptr<media::VideoFrame> CopyNV12ToI420(VAImage* image, | |
Pawel Osciak
2013/11/29 04:25:13
To be honest I feel now that all the conversion co
chihchung
2013/11/29 14:06:30
I prefer current code because (1) The linker shoul
Pawel Osciak
2013/12/03 08:52:06
1) We just did an interesting experiment where we
chihchung
2013/12/03 10:57:40
Done.
| |
449 void* mem) { | |
450 DVLOG(1) << "CopyNV12ToI420 width=" << image->width | |
451 << ", height=" << image->height; | |
452 | |
453 const gfx::Size coded_size(image->width, image->height); | |
454 const gfx::Rect visible_rect(image->width, image->height); | |
455 const gfx::Size natural_size(image->width, image->height); | |
456 | |
457 scoped_refptr<media::VideoFrame> frame = | |
458 media::VideoFrame::CreateFrame(media::VideoFrame::I420, | |
Pawel Osciak
2013/11/29 04:25:13
Normally I'd suggest adding a
VideoFrame::WrapVAIm
| |
459 coded_size, | |
460 visible_rect, | |
461 natural_size, | |
462 base::TimeDelta()); | |
463 | |
464 uint8_t* mem_byte_ptr = static_cast<uint8_t*>(mem); | |
465 uint8_t* srcY = mem_byte_ptr + image->offsets[0]; | |
466 uint8_t* srcU = mem_byte_ptr + image->offsets[1]; | |
467 uint8_t* srcV = srcU + 1; | |
468 | |
469 uint8_t* dstY = frame->data(media::VideoFrame::kYPlane); | |
470 uint8_t* dstU = frame->data(media::VideoFrame::kUPlane); | |
471 uint8_t* dstV = frame->data(media::VideoFrame::kVPlane); | |
472 | |
473 for (int i = 0; i < image->height; i++) { | |
474 memcpy(dstY, srcY, image->width); | |
475 srcY += image->pitches[0]; | |
476 dstY += frame->stride(media::VideoFrame::kYPlane); | |
477 | |
478 if ((i & 1) == 1) | |
Pawel Osciak
2013/11/29 04:25:13
It's obvious for us, but maybe add a comment why t
chihchung
2013/11/29 14:06:30
Done.
| |
479 continue; | |
480 for (int j = 0, k = 0; j < image->width; j += 2, k++) { | |
481 dstU[k] = srcU[j]; | |
Pawel Osciak
2013/11/29 04:25:13
Did a quick peek into vagetimage and it looks like
| |
482 dstV[k] = srcV[j]; | |
483 } | |
484 srcU += image->pitches[1]; | |
485 srcV += image->pitches[1]; | |
486 dstU += frame->stride(media::VideoFrame::kUPlane); | |
487 dstV += frame->stride(media::VideoFrame::kVPlane); | |
488 } | |
489 | |
490 return frame; | |
491 } | |
492 | |
493 scoped_refptr<media::VideoFrame> VaapiWrapper::VideoFrameFromVASurface( | |
494 VASurfaceID va_surface_id) { | |
495 base::AutoLock auto_lock(va_lock_); | |
496 | |
497 VAStatus va_res = VAAPI_SyncSurface(va_display_, va_surface_id); | |
498 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", NULL); | |
499 | |
500 VAImage image; | |
501 void* mem = NULL; | |
502 scoped_refptr<media::VideoFrame> result; | |
Pawel Osciak
2013/11/29 04:25:13
s/result/frame or something like that :)
chihchung
2013/11/29 14:06:30
Done.
| |
503 | |
504 // Derive a VAImage from the VASurface | |
505 va_res = VAAPI_DeriveImage(va_display_, va_surface_id, &image); | |
506 VA_LOG_ON_ERROR(va_res, "vaDeriveImage failed"); | |
507 if (va_res == VA_STATUS_SUCCESS) { | |
Pawel Osciak
2013/11/29 04:25:13
Early return from here instead maybe to save on in
chihchung
2013/11/29 14:06:30
Done.
| |
508 // Check if the format is NV12 | |
509 if (image.format.fourcc == VA_FOURCC_NV12) { | |
510 // Map the buffer | |
511 va_res = VAAPI_MapBuffer(va_display_, image.buf, &mem); | |
512 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); | |
513 if (va_res == VA_STATUS_SUCCESS) { | |
514 result = CopyNV12ToI420(&image, mem); | |
515 // Unmap the buffer | |
516 VAAPI_UnmapBuffer(va_display_, image.buf); | |
517 } | |
518 } else { | |
519 LOG(ERROR) << "unexpected image format: " << image.format.fourcc; | |
Pawel Osciak
2013/11/29 04:25:13
Please use DVLOG() instead so as to not pollute th
chihchung
2013/11/29 14:06:30
Done.
| |
520 } | |
521 VAAPI_DestroyImage(va_display_, image.image_id); | |
522 } | |
523 | |
524 return result; | |
525 } | |
526 | |
436 // static | 527 // static |
437 bool VaapiWrapper::PostSandboxInitialization() { | 528 bool VaapiWrapper::PostSandboxInitialization() { |
438 vaapi_handle = dlopen("libva.so.1", RTLD_NOW); | 529 vaapi_handle = dlopen("libva.so.1", RTLD_NOW); |
439 vaapi_x11_handle = dlopen("libva-x11.so.1", RTLD_NOW); | 530 vaapi_x11_handle = dlopen("libva-x11.so.1", RTLD_NOW); |
440 | 531 |
441 if (!vaapi_handle || !vaapi_x11_handle) | 532 if (!vaapi_handle || !vaapi_x11_handle) |
442 return false; | 533 return false; |
443 #define VAAPI_DLSYM_OR_RETURN_ON_ERROR(name, handle) \ | 534 #define VAAPI_DLSYM_OR_RETURN_ON_ERROR(name, handle) \ |
444 do { \ | 535 do { \ |
445 VAAPI_##name = reinterpret_cast<Vaapi##name>(dlsym((handle), "va"#name)); \ | 536 VAAPI_##name = reinterpret_cast<Vaapi##name>(dlsym((handle), "va"#name)); \ |
(...skipping 15 matching lines...) Expand all Loading... | |
461 VAAPI_DLSYM_OR_RETURN_ON_ERROR(DisplayIsValid, vaapi_handle); | 552 VAAPI_DLSYM_OR_RETURN_ON_ERROR(DisplayIsValid, vaapi_handle); |
462 VAAPI_DLSYM_OR_RETURN_ON_ERROR(EndPicture, vaapi_handle); | 553 VAAPI_DLSYM_OR_RETURN_ON_ERROR(EndPicture, vaapi_handle); |
463 VAAPI_DLSYM_OR_RETURN_ON_ERROR(ErrorStr, vaapi_handle); | 554 VAAPI_DLSYM_OR_RETURN_ON_ERROR(ErrorStr, vaapi_handle); |
464 VAAPI_DLSYM_OR_RETURN_ON_ERROR(GetConfigAttributes, vaapi_handle); | 555 VAAPI_DLSYM_OR_RETURN_ON_ERROR(GetConfigAttributes, vaapi_handle); |
465 VAAPI_DLSYM_OR_RETURN_ON_ERROR(GetDisplay, vaapi_x11_handle); | 556 VAAPI_DLSYM_OR_RETURN_ON_ERROR(GetDisplay, vaapi_x11_handle); |
466 VAAPI_DLSYM_OR_RETURN_ON_ERROR(Initialize, vaapi_handle); | 557 VAAPI_DLSYM_OR_RETURN_ON_ERROR(Initialize, vaapi_handle); |
467 VAAPI_DLSYM_OR_RETURN_ON_ERROR(PutSurface, vaapi_x11_handle); | 558 VAAPI_DLSYM_OR_RETURN_ON_ERROR(PutSurface, vaapi_x11_handle); |
468 VAAPI_DLSYM_OR_RETURN_ON_ERROR(RenderPicture, vaapi_handle); | 559 VAAPI_DLSYM_OR_RETURN_ON_ERROR(RenderPicture, vaapi_handle); |
469 VAAPI_DLSYM_OR_RETURN_ON_ERROR(SyncSurface, vaapi_handle); | 560 VAAPI_DLSYM_OR_RETURN_ON_ERROR(SyncSurface, vaapi_handle); |
470 VAAPI_DLSYM_OR_RETURN_ON_ERROR(Terminate, vaapi_handle); | 561 VAAPI_DLSYM_OR_RETURN_ON_ERROR(Terminate, vaapi_handle); |
562 VAAPI_DLSYM_OR_RETURN_ON_ERROR(MapBuffer, vaapi_handle); | |
563 VAAPI_DLSYM_OR_RETURN_ON_ERROR(UnmapBuffer, vaapi_handle); | |
564 VAAPI_DLSYM_OR_RETURN_ON_ERROR(DeriveImage, vaapi_handle); | |
565 VAAPI_DLSYM_OR_RETURN_ON_ERROR(DestroyImage, vaapi_handle); | |
471 #undef VAAPI_DLSYM | 566 #undef VAAPI_DLSYM |
472 | 567 |
473 return true; | 568 return true; |
474 } | 569 } |
475 | 570 |
476 } // namespace content | 571 } // namespace content |
OLD | NEW |