Chromium Code Reviews| 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 "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/callback_helpers.h" |
| (...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 92 if (mode == VaapiWrapper::kEncode) { | 92 if (mode == VaapiWrapper::kEncode) { |
| 93 required_attribs.insert( | 93 required_attribs.insert( |
| 94 required_attribs.end(), | 94 required_attribs.end(), |
| 95 kEncodeVAConfigAttribs, | 95 kEncodeVAConfigAttribs, |
| 96 kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs)); | 96 kEncodeVAConfigAttribs + arraysize(kEncodeVAConfigAttribs)); |
| 97 } | 97 } |
| 98 return required_attribs; | 98 return required_attribs; |
| 99 } | 99 } |
| 100 | 100 |
| 101 // Maps Profile enum values to VaProfile values. | 101 // Maps Profile enum values to VaProfile values. |
| 102 static VAProfile ProfileToVAProfile( | 102 static VAProfile ProfileToVAProfile(media::VideoCodecProfile profile) { |
| 103 media::VideoCodecProfile profile, | |
| 104 const std::vector<VAProfile>& supported_profiles) { | |
| 105 | |
| 106 VAProfile va_profile = VAProfileNone; | 103 VAProfile va_profile = VAProfileNone; |
| 107 for (size_t i = 0; i < arraysize(kProfileMap); i++) { | 104 for (size_t i = 0; i < arraysize(kProfileMap); i++) { |
| 108 if (kProfileMap[i].profile == profile) { | 105 if (kProfileMap[i].profile == profile) { |
| 109 va_profile = kProfileMap[i].va_profile; | 106 va_profile = kProfileMap[i].va_profile; |
| 110 break; | 107 break; |
| 111 } | 108 } |
| 112 } | 109 } |
| 110 return va_profile; | |
| 111 } | |
| 113 | 112 |
| 113 // crbug.com/345569: media::ProfileIDToVideoCodecProfile() currently strips | |
| 114 // the information whether the profile is constrained or not, so we have no | |
| 115 // way to know here. Try for baseline first, but if it is not supported, | |
| 116 // try constrained baseline and hope this is what it actually is | |
| 117 // (which in practice is true for a great majority of cases). | |
| 118 static VAProfile FallbackVaProfileIfNecessary( | |
| 119 VAProfile va_profile, | |
| 120 const std::vector<VAProfile>& supported_profiles) { | |
| 114 bool supported = std::find(supported_profiles.begin(), | 121 bool supported = std::find(supported_profiles.begin(), |
| 115 supported_profiles.end(), | 122 supported_profiles.end(), |
| 116 va_profile) != supported_profiles.end(); | 123 va_profile) != supported_profiles.end(); |
| 117 | 124 |
| 118 if (!supported && va_profile == VAProfileH264Baseline) { | 125 if (!supported && va_profile == VAProfileH264Baseline) { |
| 119 // crbug.com/345569: media::ProfileIDToVideoCodecProfile() currently strips | |
| 120 // the information whether the profile is constrained or not, so we have no | |
| 121 // way to know here. Try for baseline first, but if it is not supported, | |
| 122 // try constrained baseline and hope this is what it actually is | |
| 123 // (which in practice is true for a great majority of cases). | |
| 124 if (std::find(supported_profiles.begin(), | 126 if (std::find(supported_profiles.begin(), |
| 125 supported_profiles.end(), | 127 supported_profiles.end(), |
| 126 VAProfileH264ConstrainedBaseline) != | 128 VAProfileH264ConstrainedBaseline) != |
| 127 supported_profiles.end()) { | 129 supported_profiles.end()) { |
| 128 va_profile = VAProfileH264ConstrainedBaseline; | 130 va_profile = VAProfileH264ConstrainedBaseline; |
| 129 DVLOG(1) << "Falling back to constrained baseline profile."; | 131 DVLOG(1) << "Falling back to constrained baseline profile."; |
| 130 } | 132 } |
| 131 } | 133 } |
| 132 | 134 |
| 133 return va_profile; | 135 return va_profile; |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 157 VaapiWrapper::~VaapiWrapper() { | 159 VaapiWrapper::~VaapiWrapper() { |
| 158 DestroyPendingBuffers(); | 160 DestroyPendingBuffers(); |
| 159 DestroyCodedBuffers(); | 161 DestroyCodedBuffers(); |
| 160 DestroySurfaces(); | 162 DestroySurfaces(); |
| 161 DeinitializeVpp(); | 163 DeinitializeVpp(); |
| 162 Deinitialize(); | 164 Deinitialize(); |
| 163 } | 165 } |
| 164 | 166 |
| 165 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( | 167 scoped_ptr<VaapiWrapper> VaapiWrapper::Create( |
| 166 CodecMode mode, | 168 CodecMode mode, |
| 167 media::VideoCodecProfile profile, | 169 VAProfile va_profile, |
| 168 const base::Closure& report_error_to_uma_cb) { | 170 const base::Closure& report_error_to_uma_cb) { |
| 169 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); | 171 scoped_ptr<VaapiWrapper> vaapi_wrapper(new VaapiWrapper()); |
| 170 | 172 |
| 171 if (!vaapi_wrapper->Initialize(mode, profile, report_error_to_uma_cb)) | 173 if (!vaapi_wrapper->Initialize(mode, va_profile, report_error_to_uma_cb)) |
| 172 vaapi_wrapper.reset(); | 174 return nullptr; |
| 173 | 175 |
| 174 return vaapi_wrapper.Pass(); | 176 return vaapi_wrapper.Pass(); |
| 175 } | 177 } |
| 176 | 178 |
| 179 scoped_ptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec( | |
| 180 CodecMode mode, | |
| 181 media::VideoCodecProfile profile, | |
| 182 const base::Closure& report_error_to_uma_cb) { | |
| 183 VAProfile va_profile = ProfileToVAProfile(profile); | |
| 184 return Create(mode, va_profile, report_error_to_uma_cb); | |
| 185 } | |
| 186 | |
| 177 std::vector<media::VideoCodecProfile> VaapiWrapper::GetSupportedEncodeProfiles( | 187 std::vector<media::VideoCodecProfile> VaapiWrapper::GetSupportedEncodeProfiles( |
| 178 const base::Closure& report_error_to_uma_cb) { | 188 const base::Closure& report_error_to_uma_cb) { |
| 179 std::vector<media::VideoCodecProfile> supported_profiles; | 189 std::vector<media::VideoCodecProfile> supported_profiles; |
| 180 | 190 |
| 181 scoped_ptr<VaapiWrapper> wrapper(new VaapiWrapper()); | 191 scoped_ptr<VaapiWrapper> wrapper(new VaapiWrapper()); |
| 182 if (!wrapper->VaInitialize(report_error_to_uma_cb)) { | 192 if (!wrapper->VaInitialize(report_error_to_uma_cb)) { |
| 183 return supported_profiles; | 193 return supported_profiles; |
| 184 } | 194 } |
| 185 | 195 |
| 186 std::vector<VAProfile> va_profiles; | 196 std::vector<VAProfile> va_profiles; |
| 187 if (!wrapper->GetSupportedVaProfiles(&va_profiles)) | 197 if (!wrapper->GetSupportedVaProfiles(&va_profiles)) |
| 188 return supported_profiles; | 198 return supported_profiles; |
| 189 | 199 |
| 190 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(kEncode); | 200 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(kEncode); |
| 191 for (size_t i = 0; i < arraysize(kProfileMap); i++) { | 201 for (size_t i = 0; i < arraysize(kProfileMap); i++) { |
| 192 VAProfile va_profile = | 202 VAProfile va_profile = ProfileToVAProfile(kProfileMap[i].profile); |
| 193 ProfileToVAProfile(kProfileMap[i].profile, va_profiles); | 203 va_profile = FallbackVaProfileIfNecessary(va_profile, va_profiles); |
| 194 if (va_profile != VAProfileNone && | 204 if (va_profile != VAProfileNone && |
| 195 wrapper->IsEntrypointSupported(va_profile, VAEntrypointEncSlice) && | 205 wrapper->IsEntrypointSupported(va_profile, VAEntrypointEncSlice) && |
| 196 wrapper->AreAttribsSupported( | 206 wrapper->AreAttribsSupported( |
| 197 va_profile, VAEntrypointEncSlice, required_attribs)) { | 207 va_profile, VAEntrypointEncSlice, required_attribs)) { |
| 198 supported_profiles.push_back(kProfileMap[i].profile); | 208 supported_profiles.push_back(kProfileMap[i].profile); |
| 199 } | 209 } |
| 200 } | 210 } |
| 201 return supported_profiles; | 211 return supported_profiles; |
| 202 } | 212 } |
| 203 | 213 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 332 required_attribs[i].value) { | 342 required_attribs[i].value) { |
| 333 DVLOG(1) << "Unsupported value " << required_attribs[i].value | 343 DVLOG(1) << "Unsupported value " << required_attribs[i].value |
| 334 << " for attribute type " << required_attribs[i].type; | 344 << " for attribute type " << required_attribs[i].type; |
| 335 return false; | 345 return false; |
| 336 } | 346 } |
| 337 } | 347 } |
| 338 return true; | 348 return true; |
| 339 } | 349 } |
| 340 | 350 |
| 341 bool VaapiWrapper::Initialize(CodecMode mode, | 351 bool VaapiWrapper::Initialize(CodecMode mode, |
| 342 media::VideoCodecProfile profile, | 352 VAProfile va_profile, |
| 343 const base::Closure& report_error_to_uma_cb) { | 353 const base::Closure& report_error_to_uma_cb) { |
| 344 if (!VaInitialize(report_error_to_uma_cb)) | 354 if (!VaInitialize(report_error_to_uma_cb)) |
| 345 return false; | 355 return nullptr; |
|
wuchengli
2015/01/21 13:19:58
false
kcwu
2015/01/23 07:51:33
Done.
| |
| 346 std::vector<VAProfile> supported_va_profiles; | 356 std::vector<VAProfile> supported_va_profiles; |
| 347 if (!GetSupportedVaProfiles(&supported_va_profiles)) | 357 if (!GetSupportedVaProfiles(&supported_va_profiles)) |
| 348 return false; | 358 return nullptr; |
|
wuchengli
2015/01/21 13:19:58
false
kcwu
2015/01/23 07:51:33
Done.
| |
| 349 VAProfile va_profile = ProfileToVAProfile(profile, supported_va_profiles); | 359 va_profile = FallbackVaProfileIfNecessary(va_profile, supported_va_profiles); |
| 350 if (va_profile == VAProfileNone) { | 360 if (va_profile == VAProfileNone) { |
| 351 DVLOG(1) << "Unsupported profile"; | 361 DVLOG(1) << "Unsupported profile"; |
| 352 return false; | 362 return false; |
| 353 } | 363 } |
| 354 VAEntrypoint entrypoint = | 364 VAEntrypoint entrypoint = |
| 355 (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD); | 365 (mode == kEncode ? VAEntrypointEncSlice : VAEntrypointVLD); |
| 356 if (!IsEntrypointSupported(va_profile, entrypoint)) | 366 if (!IsEntrypointSupported(va_profile, entrypoint)) |
| 357 return false; | 367 return false; |
| 358 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); | 368 std::vector<VAConfigAttrib> required_attribs = GetRequiredAttribs(mode); |
| 359 if (!AreAttribsSupported(va_profile, entrypoint, required_attribs)) | 369 if (!AreAttribsSupported(va_profile, entrypoint, required_attribs)) |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 658 va_surface_id, | 668 va_surface_id, |
| 659 x_pixmap, | 669 x_pixmap, |
| 660 0, 0, dest_size.width(), dest_size.height(), | 670 0, 0, dest_size.width(), dest_size.height(), |
| 661 0, 0, dest_size.width(), dest_size.height(), | 671 0, 0, dest_size.width(), dest_size.height(), |
| 662 NULL, 0, 0); | 672 NULL, 0, 0); |
| 663 VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false); | 673 VA_SUCCESS_OR_RETURN(va_res, "Failed putting surface to pixmap", false); |
| 664 return true; | 674 return true; |
| 665 } | 675 } |
| 666 #endif // USE_X11 | 676 #endif // USE_X11 |
| 667 | 677 |
| 668 bool VaapiWrapper::GetVaImageForTesting(VASurfaceID va_surface_id, | 678 bool VaapiWrapper::GetDerivedVaImage(VASurfaceID va_surface_id, |
| 669 VAImage* image, | 679 VAImage* image, |
| 670 void** mem) { | 680 void** mem) { |
| 671 base::AutoLock auto_lock(va_lock_); | 681 base::AutoLock auto_lock(va_lock_); |
| 672 | 682 |
| 673 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); | 683 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); |
| 674 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | 684 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); |
| 675 | 685 |
| 676 // Derive a VAImage from the VASurface | 686 // Derive a VAImage from the VASurface |
| 677 va_res = vaDeriveImage(va_display_, va_surface_id, image); | 687 va_res = vaDeriveImage(va_display_, va_surface_id, image); |
| 678 VA_LOG_ON_ERROR(va_res, "vaDeriveImage failed"); | 688 VA_LOG_ON_ERROR(va_res, "vaDeriveImage failed"); |
| 679 if (va_res != VA_STATUS_SUCCESS) | 689 if (va_res != VA_STATUS_SUCCESS) |
| 680 return false; | 690 return false; |
| 681 | 691 |
| 682 // Map the VAImage into memory | 692 // Map the VAImage into memory |
| 683 va_res = vaMapBuffer(va_display_, image->buf, mem); | 693 va_res = vaMapBuffer(va_display_, image->buf, mem); |
| 684 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); | 694 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); |
| 685 if (va_res == VA_STATUS_SUCCESS) | 695 if (va_res == VA_STATUS_SUCCESS) |
| 686 return true; | 696 return true; |
| 687 | 697 |
| 688 va_res = vaDestroyImage(va_display_, image->image_id); | 698 va_res = vaDestroyImage(va_display_, image->image_id); |
| 689 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); | 699 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); |
| 690 | 700 |
| 691 return false; | 701 return false; |
| 692 } | 702 } |
| 693 | 703 |
| 694 void VaapiWrapper::ReturnVaImageForTesting(VAImage* image) { | 704 bool VaapiWrapper::GetVaImage(VASurfaceID va_surface_id, |
| 705 VAImageFormat* format, | |
| 706 const gfx::Size& size, | |
| 707 VAImage* image, | |
| 708 void** mem) { | |
| 709 base::AutoLock auto_lock(va_lock_); | |
| 710 | |
| 711 VAStatus va_res = vaSyncSurface(va_display_, va_surface_id); | |
| 712 VA_SUCCESS_OR_RETURN(va_res, "Failed syncing surface", false); | |
| 713 | |
| 714 va_res = | |
| 715 vaCreateImage(va_display_, format, size.width(), size.height(), image); | |
| 716 VA_SUCCESS_OR_RETURN(va_res, "vaCreateImage failed", false); | |
| 717 | |
| 718 va_res = vaGetImage(va_display_, va_surface_id, 0, 0, size.width(), | |
| 719 size.height(), image->image_id); | |
| 720 VA_LOG_ON_ERROR(va_res, "vaGetImage failed"); | |
| 721 | |
| 722 if (va_res == VA_STATUS_SUCCESS) { | |
| 723 // Map the VAImage into memory | |
| 724 va_res = vaMapBuffer(va_display_, image->buf, mem); | |
| 725 VA_LOG_ON_ERROR(va_res, "vaMapBuffer failed"); | |
| 726 } | |
| 727 | |
| 728 if (va_res != VA_STATUS_SUCCESS) { | |
| 729 va_res = vaDestroyImage(va_display_, image->image_id); | |
| 730 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); | |
| 731 return false; | |
| 732 } | |
| 733 | |
| 734 return true; | |
| 735 } | |
| 736 | |
| 737 void VaapiWrapper::ReturnVaImage(VAImage* image) { | |
| 695 base::AutoLock auto_lock(va_lock_); | 738 base::AutoLock auto_lock(va_lock_); |
| 696 | 739 |
| 697 VAStatus va_res = vaUnmapBuffer(va_display_, image->buf); | 740 VAStatus va_res = vaUnmapBuffer(va_display_, image->buf); |
| 698 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); | 741 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); |
| 699 | 742 |
| 700 va_res = vaDestroyImage(va_display_, image->image_id); | 743 va_res = vaDestroyImage(va_display_, image->image_id); |
| 701 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); | 744 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); |
| 702 } | 745 } |
| 703 | 746 |
| 704 static void DestroyVAImage(VADisplay va_display, VAImage image) { | 747 static void DestroyVAImage(VADisplay va_display, VAImage image) { |
| (...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 906 #if defined(USE_X11) | 949 #if defined(USE_X11) |
| 907 paths[kModuleVa_x11].push_back("libva-x11.so.1"); | 950 paths[kModuleVa_x11].push_back("libva-x11.so.1"); |
| 908 #elif defined(USE_OZONE) | 951 #elif defined(USE_OZONE) |
| 909 paths[kModuleVa_drm].push_back("libva-drm.so.1"); | 952 paths[kModuleVa_drm].push_back("libva-drm.so.1"); |
| 910 #endif | 953 #endif |
| 911 | 954 |
| 912 return InitializeStubs(paths); | 955 return InitializeStubs(paths); |
| 913 } | 956 } |
| 914 | 957 |
| 915 } // namespace content | 958 } // namespace content |
| OLD | NEW |