| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/android/media_codec_video_decoder.h" | 5 #include "media/gpu/android/media_codec_video_decoder.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include <memory> | 9 #include <memory> |
| 10 | 10 |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 53 } while (0) | 53 } while (0) |
| 54 | 54 |
| 55 namespace media { | 55 namespace media { |
| 56 | 56 |
| 57 namespace { | 57 namespace { |
| 58 | 58 |
| 59 // Max number of bitstreams notified to the client with | 59 // Max number of bitstreams notified to the client with |
| 60 // NotifyEndOfBitstreamBuffer() before getting output from the bitstream. | 60 // NotifyEndOfBitstreamBuffer() before getting output from the bitstream. |
| 61 enum { kMaxBitstreamsNotifiedInAdvance = 32 }; | 61 enum { kMaxBitstreamsNotifiedInAdvance = 32 }; |
| 62 | 62 |
| 63 // MediaCodec is only guaranteed to support baseline, but some devices may | |
| 64 // support others. Advertise support for all H264 profiles and let the | |
| 65 // MediaCodec fail when decoding if it's not actually supported. It's assumed | |
| 66 // that consumers won't have software fallback for H264 on Android anyway. | |
| 67 constexpr VideoCodecProfile kSupportedH264Profiles[] = { | |
| 68 H264PROFILE_BASELINE, | |
| 69 H264PROFILE_MAIN, | |
| 70 H264PROFILE_EXTENDED, | |
| 71 H264PROFILE_HIGH, | |
| 72 H264PROFILE_HIGH10PROFILE, | |
| 73 H264PROFILE_HIGH422PROFILE, | |
| 74 H264PROFILE_HIGH444PREDICTIVEPROFILE, | |
| 75 H264PROFILE_SCALABLEBASELINE, | |
| 76 H264PROFILE_SCALABLEHIGH, | |
| 77 H264PROFILE_STEREOHIGH, | |
| 78 H264PROFILE_MULTIVIEWHIGH}; | |
| 79 | |
| 80 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | |
| 81 constexpr VideoCodecProfile kSupportedHevcProfiles[] = {HEVCPROFILE_MAIN, | |
| 82 HEVCPROFILE_MAIN10}; | |
| 83 #endif | |
| 84 | |
| 85 // Because MediaCodec is thread-hostile (must be poked on a single thread) and | 63 // Because MediaCodec is thread-hostile (must be poked on a single thread) and |
| 86 // has no callback mechanism (b/11990118), we must drive it by polling for | 64 // has no callback mechanism (b/11990118), we must drive it by polling for |
| 87 // complete frames (and available input buffers, when the codec is fully | 65 // complete frames (and available input buffers, when the codec is fully |
| 88 // saturated). This function defines the polling delay. The value used is an | 66 // saturated). This function defines the polling delay. The value used is an |
| 89 // arbitrary choice that trades off CPU utilization (spinning) against latency. | 67 // arbitrary choice that trades off CPU utilization (spinning) against latency. |
| 90 // Mirrors android_video_encode_accelerator.cc:EncodePollDelay(). | 68 // Mirrors android_video_encode_accelerator.cc:EncodePollDelay(). |
| 91 // | 69 // |
| 92 // An alternative to this polling scheme could be to dedicate a new thread | 70 // An alternative to this polling scheme could be to dedicate a new thread |
| 93 // (instead of using the ChildThread) to run the MediaCodec, and make that | 71 // (instead of using the ChildThread) to run the MediaCodec, and make that |
| 94 // thread use the timeout-based flavor of MediaCodec's dequeue methods when it | 72 // thread use the timeout-based flavor of MediaCodec's dequeue methods when it |
| (...skipping 12 matching lines...) Expand all Loading... |
| 107 // On low end devices (< KitKat is always low-end due to buggy MediaCodec), | 85 // On low end devices (< KitKat is always low-end due to buggy MediaCodec), |
| 108 // defer the surface creation until the codec is actually used if we know no | 86 // defer the surface creation until the codec is actually used if we know no |
| 109 // software fallback exists. | 87 // software fallback exists. |
| 110 bool ShouldDeferSurfaceCreation(int surface_id, VideoCodec codec) { | 88 bool ShouldDeferSurfaceCreation(int surface_id, VideoCodec codec) { |
| 111 return surface_id == SurfaceManager::kNoSurfaceID && codec == kCodecH264 && | 89 return surface_id == SurfaceManager::kNoSurfaceID && codec == kCodecH264 && |
| 112 AVDACodecAllocator::Instance()->IsAnyRegisteredAVDA() && | 90 AVDACodecAllocator::Instance()->IsAnyRegisteredAVDA() && |
| 113 (base::android::BuildInfo::GetInstance()->sdk_int() <= 18 || | 91 (base::android::BuildInfo::GetInstance()->sdk_int() <= 18 || |
| 114 base::SysInfo::IsLowEndDevice()); | 92 base::SysInfo::IsLowEndDevice()); |
| 115 } | 93 } |
| 116 | 94 |
| 95 // Don't use MediaCodecs internal software decoders when we have more secure and |
| 96 // up to date versions in the renderer process. |
| 97 bool IsMediaCodecSoftwareDecodingForbidden(const VideoDecoderConfig& config) { |
| 98 return !config.is_encrypted() && |
| 99 (config.codec() == kCodecVP8 || _config.codec() == kCodecVP9); |
| 100 } |
| 101 |
| 102 bool ConfigSupported(const VideoDecoderConfig& config) { |
| 103 const auto codec = config.codec(); |
| 104 |
| 105 // Only use MediaCodec for VP8 or VP9 if it's likely backed by hardware or if |
| 106 // the stream is encrypted. |
| 107 if (IsMediaCodecSoftwareDecodingForbidden(config) && |
| 108 VideoCodecBridge::IsKnownUnaccelerated(codec, MEDIA_CODEC_DECODER)) { |
| 109 DVLOG(1) << "Config not supported: " << GetCodecName(codec) |
| 110 << " is not hardware accelerated"; |
| 111 return false; |
| 112 } |
| 113 |
| 114 // Don't support larger than 4k because it won't perform well on many devices. |
| 115 const auto size = config.coded_size(); |
| 116 if (size.width() > 3840 || size.height() > 2160) |
| 117 return false; |
| 118 |
| 119 switch (codec) { |
| 120 case kCodecVP8: |
| 121 case kCodecVP9: { |
| 122 if ((codec == kCodecVP8 && !MediaCodecUtil::IsVp8DecoderAvailable()) || |
| 123 (codec == kCodecVP9 && !MediaCodecUtil::IsVp9DecoderAvailable())) { |
| 124 return false; |
| 125 } |
| 126 |
| 127 // There's no fallback for encrypted content so we support all sizes. |
| 128 if (config.is_encrypted()) |
| 129 return true; |
| 130 |
| 131 // Below 360p there's little to no power benefit to using MediaCodec over |
| 132 // libvpx so we prefer to use our newer version of libvpx, sandboxed in |
| 133 // the renderer. |
| 134 if (size.width() < 480 || size.height() < 360) |
| 135 return false; |
| 136 |
| 137 return true; |
| 138 } |
| 139 case kCodecH264: |
| 140 return true; |
| 141 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) |
| 142 case kCodecHEVC: |
| 143 return true; |
| 144 #endif |
| 145 default: |
| 146 return false; |
| 147 } |
| 148 } |
| 149 |
| 117 } // namespace | 150 } // namespace |
| 118 | 151 |
| 119 // MCVDManager manages shared resources for a number of MCVD instances. | 152 // MCVDManager manages shared resources for a number of MCVD instances. |
| 120 // Its responsibilities include: | 153 // Its responsibilities include: |
| 121 // - Starting and stopping a shared "construction" thread for instantiating and | 154 // - Starting and stopping a shared "construction" thread for instantiating and |
| 122 // releasing MediaCodecs. | 155 // releasing MediaCodecs. |
| 123 // - Detecting when a task has hung on the construction thread so MCVDs can | 156 // - Detecting when a task has hung on the construction thread so MCVDs can |
| 124 // stop using it. | 157 // stop using it. |
| 125 // - Running a RepeatingTimer so that MCVDs can get a regular callback to | 158 // - Running a RepeatingTimer so that MCVDs can get a regular callback to |
| 126 // DoIOTask(). | 159 // DoIOTask(). |
| (...skipping 1057 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1184 } else { | 1217 } else { |
| 1185 most_recent_work_ = now; | 1218 most_recent_work_ = now; |
| 1186 } | 1219 } |
| 1187 | 1220 |
| 1188 if (should_be_running) | 1221 if (should_be_running) |
| 1189 g_mcvd_manager.Get().StartTimer(this); | 1222 g_mcvd_manager.Get().StartTimer(this); |
| 1190 else | 1223 else |
| 1191 g_mcvd_manager.Get().StopTimer(this); | 1224 g_mcvd_manager.Get().StopTimer(this); |
| 1192 } | 1225 } |
| 1193 | 1226 |
| 1194 // static | |
| 1195 VideoDecodeAccelerator::Capabilities MediaCodecVideoDecoder::GetCapabilities( | |
| 1196 const gpu::GpuPreferences& gpu_preferences) { | |
| 1197 Capabilities capabilities; | |
| 1198 SupportedProfiles& profiles = capabilities.supported_profiles; | |
| 1199 | |
| 1200 if (MediaCodecUtil::IsVp8DecoderAvailable()) { | |
| 1201 SupportedProfile profile; | |
| 1202 profile.profile = VP8PROFILE_ANY; | |
| 1203 // Since there is little to no power benefit below 360p, don't advertise | |
| 1204 // support for it. Let libvpx decode it, and save a MediaCodec instance. | |
| 1205 // Note that we allow it anyway for encrypted content, since we push a | |
| 1206 // separate profile for that. | |
| 1207 profile.min_resolution.SetSize(480, 360); | |
| 1208 profile.max_resolution.SetSize(3840, 2160); | |
| 1209 // If we know MediaCodec will just create a software codec, prefer our | |
| 1210 // internal software decoder instead. It's more up to date and secured | |
| 1211 // within the renderer sandbox. However if the content is encrypted, we | |
| 1212 // must use MediaCodec anyways since MediaDrm offers no way to decrypt | |
| 1213 // the buffers and let us use our internal software decoders. | |
| 1214 profile.encrypted_only = | |
| 1215 VideoCodecBridge::IsKnownUnaccelerated(kCodecVP8, MEDIA_CODEC_DECODER); | |
| 1216 profiles.push_back(profile); | |
| 1217 | |
| 1218 // Always allow encrypted content, even at low resolutions. | |
| 1219 profile.min_resolution.SetSize(0, 0); | |
| 1220 profile.encrypted_only = true; | |
| 1221 profiles.push_back(profile); | |
| 1222 } | |
| 1223 | |
| 1224 if (MediaCodecUtil::IsVp9DecoderAvailable()) { | |
| 1225 const VideoCodecProfile profile_types[] = { | |
| 1226 VP9PROFILE_PROFILE0, VP9PROFILE_PROFILE1, VP9PROFILE_PROFILE2, | |
| 1227 VP9PROFILE_PROFILE3, VIDEO_CODEC_PROFILE_UNKNOWN}; | |
| 1228 const bool is_known_unaccelerated = | |
| 1229 VideoCodecBridge::IsKnownUnaccelerated(kCodecVP9, MEDIA_CODEC_DECODER); | |
| 1230 for (int i = 0; profile_types[i] != VIDEO_CODEC_PROFILE_UNKNOWN; i++) { | |
| 1231 SupportedProfile profile; | |
| 1232 // Limit to 360p, like we do for vp8. See above. | |
| 1233 profile.min_resolution.SetSize(480, 360); | |
| 1234 profile.max_resolution.SetSize(3840, 2160); | |
| 1235 // If we know MediaCodec will just create a software codec, prefer our | |
| 1236 // internal software decoder instead. It's more up to date and secured | |
| 1237 // within the renderer sandbox. However if the content is encrypted, we | |
| 1238 // must use MediaCodec anyways since MediaDrm offers no way to decrypt | |
| 1239 // the buffers and let us use our internal software decoders. | |
| 1240 profile.encrypted_only = is_known_unaccelerated; | |
| 1241 profile.profile = profile_types[i]; | |
| 1242 profiles.push_back(profile); | |
| 1243 | |
| 1244 // Always allow encrypted content. | |
| 1245 profile.min_resolution.SetSize(0, 0); | |
| 1246 profile.encrypted_only = true; | |
| 1247 profiles.push_back(profile); | |
| 1248 } | |
| 1249 } | |
| 1250 | |
| 1251 for (const auto& supported_profile : kSupportedH264Profiles) { | |
| 1252 SupportedProfile profile; | |
| 1253 profile.profile = supported_profile; | |
| 1254 profile.min_resolution.SetSize(0, 0); | |
| 1255 // Advertise support for 4k and let the MediaCodec fail when decoding if it | |
| 1256 // doesn't support the resolution. It's assumed that consumers won't have | |
| 1257 // software fallback for H264 on Android anyway. | |
| 1258 profile.max_resolution.SetSize(3840, 2160); | |
| 1259 profiles.push_back(profile); | |
| 1260 } | |
| 1261 | |
| 1262 capabilities.flags = | |
| 1263 VideoDecodeAccelerator::Capabilities::SUPPORTS_DEFERRED_INITIALIZATION; | |
| 1264 capabilities.flags |= | |
| 1265 VideoDecodeAccelerator::Capabilities::NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE; | |
| 1266 | |
| 1267 // If we're using threaded texture mailboxes the COPY_REQUIRED flag must be | |
| 1268 // set on the video frames (http://crbug.com/582170), and SurfaceView output | |
| 1269 // is disabled (http://crbug.com/582170). | |
| 1270 if (gpu_preferences.enable_threaded_texture_mailboxes) { | |
| 1271 capabilities.flags |= | |
| 1272 VideoDecodeAccelerator::Capabilities::REQUIRES_TEXTURE_COPY; | |
| 1273 } else if (MediaCodecUtil::IsSurfaceViewOutputSupported()) { | |
| 1274 capabilities.flags |= | |
| 1275 VideoDecodeAccelerator::Capabilities::SUPPORTS_EXTERNAL_OUTPUT_SURFACE; | |
| 1276 } | |
| 1277 | |
| 1278 #if BUILDFLAG(ENABLE_HEVC_DEMUXING) | |
| 1279 for (const auto& supported_profile : kSupportedHevcProfiles) { | |
| 1280 SupportedProfile profile; | |
| 1281 profile.profile = supported_profile; | |
| 1282 profile.min_resolution.SetSize(0, 0); | |
| 1283 profile.max_resolution.SetSize(3840, 2160); | |
| 1284 profiles.push_back(profile); | |
| 1285 } | |
| 1286 #endif | |
| 1287 | |
| 1288 return capabilities; | |
| 1289 } | |
| 1290 | |
| 1291 bool MediaCodecVideoDecoder::IsMediaCodecSoftwareDecodingForbidden() const { | |
| 1292 // Prevent MediaCodec from using its internal software decoders when we have | |
| 1293 // more secure and up to date versions in the renderer process. | |
| 1294 return !config_.is_encrypted && (codec_config_->codec_ == kCodecVP8 || | |
| 1295 codec_config_->codec_ == kCodecVP9); | |
| 1296 } | |
| 1297 | 1227 |
| 1298 bool MediaCodecVideoDecoder::UpdateSurface() { | 1228 bool MediaCodecVideoDecoder::UpdateSurface() { |
| 1299 DCHECK(pending_surface_id_); | 1229 DCHECK(pending_surface_id_); |
| 1300 DCHECK_NE(config_.surface_id, pending_surface_id_.value()); | 1230 DCHECK_NE(config_.surface_id, pending_surface_id_.value()); |
| 1301 DCHECK(config_.surface_id == SurfaceManager::kNoSurfaceID || | 1231 DCHECK(config_.surface_id == SurfaceManager::kNoSurfaceID || |
| 1302 pending_surface_id_.value() == SurfaceManager::kNoSurfaceID); | 1232 pending_surface_id_.value() == SurfaceManager::kNoSurfaceID); |
| 1303 | 1233 |
| 1304 const int previous_surface_id = config_.surface_id; | 1234 const int previous_surface_id = config_.surface_id; |
| 1305 const int new_surface_id = pending_surface_id_.value(); | 1235 const int new_surface_id = pending_surface_id_.value(); |
| 1306 pending_surface_id_.reset(); | 1236 pending_surface_id_.reset(); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1350 AVDACodecAllocator::Instance()->DeallocateSurface(this, new_surface_id); | 1280 AVDACodecAllocator::Instance()->DeallocateSurface(this, new_surface_id); |
| 1351 } | 1281 } |
| 1352 | 1282 |
| 1353 // Regardless of whether we succeeded, we no longer own the previous surface. | 1283 // Regardless of whether we succeeded, we no longer own the previous surface. |
| 1354 AVDACodecAllocator::Instance()->DeallocateSurface(this, previous_surface_id); | 1284 AVDACodecAllocator::Instance()->DeallocateSurface(this, previous_surface_id); |
| 1355 | 1285 |
| 1356 return success; | 1286 return success; |
| 1357 } | 1287 } |
| 1358 | 1288 |
| 1359 } // namespace media | 1289 } // namespace media |
| OLD | NEW |