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 "media/gpu/vaapi_wrapper.h" | 5 #include "media/gpu/vaapi_wrapper.h" |
6 | 6 |
7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
8 #include <string.h> | 8 #include <string.h> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 }; | 111 }; |
112 | 112 |
113 // Attributes required for encode. | 113 // Attributes required for encode. |
114 static const VAConfigAttrib kEncodeVAConfigAttribs[] = { | 114 static const VAConfigAttrib kEncodeVAConfigAttribs[] = { |
115 {VAConfigAttribRateControl, VA_RC_CBR}, | 115 {VAConfigAttribRateControl, VA_RC_CBR}, |
116 {VAConfigAttribEncPackedHeaders, | 116 {VAConfigAttribEncPackedHeaders, |
117 VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE}, | 117 VA_ENC_PACKED_HEADER_SEQUENCE | VA_ENC_PACKED_HEADER_PICTURE}, |
118 }; | 118 }; |
119 | 119 |
120 struct ProfileMap { | 120 struct ProfileMap { |
121 media::VideoCodecProfile profile; | 121 VideoCodecProfile profile; |
122 VAProfile va_profile; | 122 VAProfile va_profile; |
123 }; | 123 }; |
124 | 124 |
125 // A map between VideoCodecProfile and VAProfile. | 125 // A map between VideoCodecProfile and VAProfile. |
126 static const ProfileMap kProfileMap[] = { | 126 static const ProfileMap kProfileMap[] = { |
127 {media::H264PROFILE_BASELINE, VAProfileH264Baseline}, | 127 {H264PROFILE_BASELINE, VAProfileH264Baseline}, |
128 {media::H264PROFILE_MAIN, VAProfileH264Main}, | 128 {H264PROFILE_MAIN, VAProfileH264Main}, |
129 // TODO(posciak): See if we can/want support other variants of | 129 // TODO(posciak): See if we can/want support other variants of |
130 // media::H264PROFILE_HIGH*. | 130 // H264PROFILE_HIGH*. |
131 {media::H264PROFILE_HIGH, VAProfileH264High}, | 131 {H264PROFILE_HIGH, VAProfileH264High}, |
132 {media::VP8PROFILE_ANY, VAProfileVP8Version0_3}, | 132 {VP8PROFILE_ANY, VAProfileVP8Version0_3}, |
133 // TODO(servolk): Need to add VP9 profiles 1,2,3 here after rolling | 133 // TODO(servolk): Need to add VP9 profiles 1,2,3 here after rolling |
134 // third_party/libva to 1.7. crbug.com/598118 | 134 // third_party/libva to 1.7. crbug.com/598118 |
135 {media::VP9PROFILE_PROFILE0, VAProfileVP9Profile0}, | 135 {VP9PROFILE_PROFILE0, VAProfileVP9Profile0}, |
136 }; | 136 }; |
137 | 137 |
138 static std::vector<VAConfigAttrib> GetRequiredAttribs( | 138 static std::vector<VAConfigAttrib> GetRequiredAttribs( |
139 VaapiWrapper::CodecMode mode) { | 139 VaapiWrapper::CodecMode mode) { |
140 std::vector<VAConfigAttrib> required_attribs; | 140 std::vector<VAConfigAttrib> required_attribs; |
141 required_attribs.insert( | 141 required_attribs.insert( |
142 required_attribs.end(), kCommonVAConfigAttribs, | 142 required_attribs.end(), kCommonVAConfigAttribs, |
143 kCommonVAConfigAttribs + arraysize(kCommonVAConfigAttribs)); | 143 kCommonVAConfigAttribs + arraysize(kCommonVAConfigAttribs)); |
144 if (mode == VaapiWrapper::kEncode) { | 144 if (mode == VaapiWrapper::kEncode) { |
145 required_attribs.insert( | 145 required_attribs.insert( |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
198 if (vaapi_wrapper->Initialize(mode, va_profile)) | 198 if (vaapi_wrapper->Initialize(mode, va_profile)) |
199 return vaapi_wrapper; | 199 return vaapi_wrapper; |
200 } | 200 } |
201 LOG(ERROR) << "Failed to create VaapiWrapper for va_profile: " << va_profile; | 201 LOG(ERROR) << "Failed to create VaapiWrapper for va_profile: " << va_profile; |
202 return nullptr; | 202 return nullptr; |
203 } | 203 } |
204 | 204 |
205 // static | 205 // static |
206 scoped_refptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec( | 206 scoped_refptr<VaapiWrapper> VaapiWrapper::CreateForVideoCodec( |
207 CodecMode mode, | 207 CodecMode mode, |
208 media::VideoCodecProfile profile, | 208 VideoCodecProfile profile, |
209 const base::Closure& report_error_to_uma_cb) { | 209 const base::Closure& report_error_to_uma_cb) { |
210 VAProfile va_profile = ProfileToVAProfile(profile, mode); | 210 VAProfile va_profile = ProfileToVAProfile(profile, mode); |
211 scoped_refptr<VaapiWrapper> vaapi_wrapper = | 211 scoped_refptr<VaapiWrapper> vaapi_wrapper = |
212 Create(mode, va_profile, report_error_to_uma_cb); | 212 Create(mode, va_profile, report_error_to_uma_cb); |
213 return vaapi_wrapper; | 213 return vaapi_wrapper; |
214 } | 214 } |
215 | 215 |
216 // static | 216 // static |
217 media::VideoEncodeAccelerator::SupportedProfiles | 217 VideoEncodeAccelerator::SupportedProfiles |
218 VaapiWrapper::GetSupportedEncodeProfiles() { | 218 VaapiWrapper::GetSupportedEncodeProfiles() { |
219 media::VideoEncodeAccelerator::SupportedProfiles profiles; | 219 VideoEncodeAccelerator::SupportedProfiles profiles; |
220 std::vector<ProfileInfo> encode_profile_infos = | 220 std::vector<ProfileInfo> encode_profile_infos = |
221 profile_infos_.Get().GetSupportedProfileInfosForCodecMode(kEncode); | 221 profile_infos_.Get().GetSupportedProfileInfosForCodecMode(kEncode); |
222 | 222 |
223 for (size_t i = 0; i < arraysize(kProfileMap); ++i) { | 223 for (size_t i = 0; i < arraysize(kProfileMap); ++i) { |
224 VAProfile va_profile = ProfileToVAProfile(kProfileMap[i].profile, kEncode); | 224 VAProfile va_profile = ProfileToVAProfile(kProfileMap[i].profile, kEncode); |
225 if (va_profile == VAProfileNone) | 225 if (va_profile == VAProfileNone) |
226 continue; | 226 continue; |
227 for (const auto& profile_info : encode_profile_infos) { | 227 for (const auto& profile_info : encode_profile_infos) { |
228 if (profile_info.va_profile == va_profile) { | 228 if (profile_info.va_profile == va_profile) { |
229 media::VideoEncodeAccelerator::SupportedProfile profile; | 229 VideoEncodeAccelerator::SupportedProfile profile; |
230 profile.profile = kProfileMap[i].profile; | 230 profile.profile = kProfileMap[i].profile; |
231 profile.max_resolution = profile_info.max_resolution; | 231 profile.max_resolution = profile_info.max_resolution; |
232 profile.max_framerate_numerator = kMaxEncoderFramerate; | 232 profile.max_framerate_numerator = kMaxEncoderFramerate; |
233 profile.max_framerate_denominator = 1; | 233 profile.max_framerate_denominator = 1; |
234 profiles.push_back(profile); | 234 profiles.push_back(profile); |
235 break; | 235 break; |
236 } | 236 } |
237 } | 237 } |
238 } | 238 } |
239 return profiles; | 239 return profiles; |
240 } | 240 } |
241 | 241 |
242 // static | 242 // static |
243 media::VideoDecodeAccelerator::SupportedProfiles | 243 VideoDecodeAccelerator::SupportedProfiles |
244 VaapiWrapper::GetSupportedDecodeProfiles() { | 244 VaapiWrapper::GetSupportedDecodeProfiles() { |
245 media::VideoDecodeAccelerator::SupportedProfiles profiles; | 245 VideoDecodeAccelerator::SupportedProfiles profiles; |
246 std::vector<ProfileInfo> decode_profile_infos = | 246 std::vector<ProfileInfo> decode_profile_infos = |
247 profile_infos_.Get().GetSupportedProfileInfosForCodecMode(kDecode); | 247 profile_infos_.Get().GetSupportedProfileInfosForCodecMode(kDecode); |
248 | 248 |
249 for (size_t i = 0; i < arraysize(kProfileMap); ++i) { | 249 for (size_t i = 0; i < arraysize(kProfileMap); ++i) { |
250 VAProfile va_profile = ProfileToVAProfile(kProfileMap[i].profile, kDecode); | 250 VAProfile va_profile = ProfileToVAProfile(kProfileMap[i].profile, kDecode); |
251 if (va_profile == VAProfileNone) | 251 if (va_profile == VAProfileNone) |
252 continue; | 252 continue; |
253 for (const auto& profile_info : decode_profile_infos) { | 253 for (const auto& profile_info : decode_profile_infos) { |
254 if (profile_info.va_profile == va_profile) { | 254 if (profile_info.va_profile == va_profile) { |
255 media::VideoDecodeAccelerator::SupportedProfile profile; | 255 VideoDecodeAccelerator::SupportedProfile profile; |
256 profile.profile = kProfileMap[i].profile; | 256 profile.profile = kProfileMap[i].profile; |
257 profile.max_resolution = profile_info.max_resolution; | 257 profile.max_resolution = profile_info.max_resolution; |
258 profile.min_resolution.SetSize(16, 16); | 258 profile.min_resolution.SetSize(16, 16); |
259 profiles.push_back(profile); | 259 profiles.push_back(profile); |
260 break; | 260 break; |
261 } | 261 } |
262 } | 262 } |
263 } | 263 } |
264 return profiles; | 264 return profiles; |
265 } | 265 } |
(...skipping 11 matching lines...) Expand all Loading... |
277 -1, // The maximum possible support 'ALL'. | 277 -1, // The maximum possible support 'ALL'. |
278 VA_RENDER_MODE_LOCAL_GPU, | 278 VA_RENDER_MODE_LOCAL_GPU, |
279 VA_DISPLAY_ATTRIB_SETTABLE}; | 279 VA_DISPLAY_ATTRIB_SETTABLE}; |
280 | 280 |
281 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); | 281 VAStatus va_res = vaSetDisplayAttributes(va_display_, &item, 1); |
282 if (va_res != VA_STATUS_SUCCESS) | 282 if (va_res != VA_STATUS_SUCCESS) |
283 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; | 283 DVLOG(2) << "vaSetDisplayAttributes unsupported, ignoring by default."; |
284 } | 284 } |
285 | 285 |
286 // static | 286 // static |
287 VAProfile VaapiWrapper::ProfileToVAProfile(media::VideoCodecProfile profile, | 287 VAProfile VaapiWrapper::ProfileToVAProfile(VideoCodecProfile profile, |
288 CodecMode mode) { | 288 CodecMode mode) { |
289 VAProfile va_profile = VAProfileNone; | 289 VAProfile va_profile = VAProfileNone; |
290 for (size_t i = 0; i < arraysize(kProfileMap); ++i) { | 290 for (size_t i = 0; i < arraysize(kProfileMap); ++i) { |
291 if (kProfileMap[i].profile == profile) { | 291 if (kProfileMap[i].profile == profile) { |
292 va_profile = kProfileMap[i].va_profile; | 292 va_profile = kProfileMap[i].va_profile; |
293 break; | 293 break; |
294 } | 294 } |
295 } | 295 } |
296 if (!profile_infos_.Get().IsProfileSupported(mode, va_profile) && | 296 if (!profile_infos_.Get().IsProfileSupported(mode, va_profile) && |
297 va_profile == VAProfileH264Baseline) { | 297 va_profile == VAProfileH264Baseline) { |
298 // crbug.com/345569: media::ProfileIDToVideoCodecProfile() currently strips | 298 // crbug.com/345569: ProfileIDToVideoCodecProfile() currently strips |
299 // the information whether the profile is constrained or not, so we have no | 299 // the information whether the profile is constrained or not, so we have no |
300 // way to know here. Try for baseline first, but if it is not supported, | 300 // way to know here. Try for baseline first, but if it is not supported, |
301 // try constrained baseline and hope this is what it actually is | 301 // try constrained baseline and hope this is what it actually is |
302 // (which in practice is true for a great majority of cases). | 302 // (which in practice is true for a great majority of cases). |
303 if (profile_infos_.Get().IsProfileSupported( | 303 if (profile_infos_.Get().IsProfileSupported( |
304 mode, VAProfileH264ConstrainedBaseline)) { | 304 mode, VAProfileH264ConstrainedBaseline)) { |
305 va_profile = VAProfileH264ConstrainedBaseline; | 305 va_profile = VAProfileH264ConstrainedBaseline; |
306 DVLOG(1) << "Fall back to constrained baseline profile."; | 306 DVLOG(1) << "Fall back to constrained baseline profile."; |
307 } | 307 } |
308 } | 308 } |
(...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
923 va_res = vaDestroyImage(va_display_, image->image_id); | 923 va_res = vaDestroyImage(va_display_, image->image_id); |
924 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); | 924 VA_LOG_ON_ERROR(va_res, "vaDestroyImage failed"); |
925 } | 925 } |
926 | 926 |
927 static void DestroyVAImage(VADisplay va_display, VAImage image) { | 927 static void DestroyVAImage(VADisplay va_display, VAImage image) { |
928 if (image.image_id != VA_INVALID_ID) | 928 if (image.image_id != VA_INVALID_ID) |
929 vaDestroyImage(va_display, image.image_id); | 929 vaDestroyImage(va_display, image.image_id); |
930 } | 930 } |
931 | 931 |
932 bool VaapiWrapper::UploadVideoFrameToSurface( | 932 bool VaapiWrapper::UploadVideoFrameToSurface( |
933 const scoped_refptr<media::VideoFrame>& frame, | 933 const scoped_refptr<VideoFrame>& frame, |
934 VASurfaceID va_surface_id) { | 934 VASurfaceID va_surface_id) { |
935 base::AutoLock auto_lock(*va_lock_); | 935 base::AutoLock auto_lock(*va_lock_); |
936 | 936 |
937 VAImage image; | 937 VAImage image; |
938 VAStatus va_res = vaDeriveImage(va_display_, va_surface_id, &image); | 938 VAStatus va_res = vaDeriveImage(va_display_, va_surface_id, &image); |
939 VA_SUCCESS_OR_RETURN(va_res, "vaDeriveImage failed", false); | 939 VA_SUCCESS_OR_RETURN(va_res, "vaDeriveImage failed", false); |
940 base::ScopedClosureRunner vaimage_deleter( | 940 base::ScopedClosureRunner vaimage_deleter( |
941 base::Bind(&DestroyVAImage, va_display_, image)); | 941 base::Bind(&DestroyVAImage, va_display_, image)); |
942 | 942 |
943 if (image.format.fourcc != VA_FOURCC_NV12) { | 943 if (image.format.fourcc != VA_FOURCC_NV12) { |
944 LOG(ERROR) << "Unsupported image format: " << image.format.fourcc; | 944 LOG(ERROR) << "Unsupported image format: " << image.format.fourcc; |
945 return false; | 945 return false; |
946 } | 946 } |
947 | 947 |
948 if (gfx::Rect(image.width, image.height) < gfx::Rect(frame->coded_size())) { | 948 if (gfx::Rect(image.width, image.height) < gfx::Rect(frame->coded_size())) { |
949 LOG(ERROR) << "Buffer too small to fit the frame."; | 949 LOG(ERROR) << "Buffer too small to fit the frame."; |
950 return false; | 950 return false; |
951 } | 951 } |
952 | 952 |
953 void* image_ptr = NULL; | 953 void* image_ptr = NULL; |
954 va_res = vaMapBuffer(va_display_, image.buf, &image_ptr); | 954 va_res = vaMapBuffer(va_display_, image.buf, &image_ptr); |
955 VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false); | 955 VA_SUCCESS_OR_RETURN(va_res, "vaMapBuffer failed", false); |
956 DCHECK(image_ptr); | 956 DCHECK(image_ptr); |
957 | 957 |
958 int ret = 0; | 958 int ret = 0; |
959 { | 959 { |
960 base::AutoUnlock auto_unlock(*va_lock_); | 960 base::AutoUnlock auto_unlock(*va_lock_); |
961 ret = libyuv::I420ToNV12( | 961 ret = libyuv::I420ToNV12( |
962 frame->data(media::VideoFrame::kYPlane), | 962 frame->data(VideoFrame::kYPlane), frame->stride(VideoFrame::kYPlane), |
963 frame->stride(media::VideoFrame::kYPlane), | 963 frame->data(VideoFrame::kUPlane), frame->stride(VideoFrame::kUPlane), |
964 frame->data(media::VideoFrame::kUPlane), | 964 frame->data(VideoFrame::kVPlane), frame->stride(VideoFrame::kVPlane), |
965 frame->stride(media::VideoFrame::kUPlane), | |
966 frame->data(media::VideoFrame::kVPlane), | |
967 frame->stride(media::VideoFrame::kVPlane), | |
968 static_cast<uint8_t*>(image_ptr) + image.offsets[0], image.pitches[0], | 965 static_cast<uint8_t*>(image_ptr) + image.offsets[0], image.pitches[0], |
969 static_cast<uint8_t*>(image_ptr) + image.offsets[1], image.pitches[1], | 966 static_cast<uint8_t*>(image_ptr) + image.offsets[1], image.pitches[1], |
970 image.width, image.height); | 967 image.width, image.height); |
971 } | 968 } |
972 | 969 |
973 va_res = vaUnmapBuffer(va_display_, image.buf); | 970 va_res = vaUnmapBuffer(va_display_, image.buf); |
974 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); | 971 VA_LOG_ON_ERROR(va_res, "vaUnmapBuffer failed"); |
975 | 972 |
976 return ret == 0; | 973 return ret == 0; |
977 } | 974 } |
(...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1241 drm_fd_.reset(HANDLE_EINTR(dup(fd))); | 1238 drm_fd_.reset(HANDLE_EINTR(dup(fd))); |
1242 } | 1239 } |
1243 #endif // USE_OZONE | 1240 #endif // USE_OZONE |
1244 | 1241 |
1245 bool VaapiWrapper::VADisplayState::VAAPIVersionLessThan(int major, int minor) { | 1242 bool VaapiWrapper::VADisplayState::VAAPIVersionLessThan(int major, int minor) { |
1246 return (major_version_ < major) || | 1243 return (major_version_ < major) || |
1247 (major_version_ == major && minor_version_ < minor); | 1244 (major_version_ == major && minor_version_ < minor); |
1248 } | 1245 } |
1249 | 1246 |
1250 } // namespace media | 1247 } // namespace media |
OLD | NEW |