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

Side by Side Diff: media/gpu/android/media_codec_video_decoder.cc

Issue 2548923002: media: Convert GetSupportedProfiles to IsConfigSupported in MCVD (Closed)
Patch Set: put the 4k upper limit back Created 4 years 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
« no previous file with comments | « media/gpu/android/media_codec_video_decoder.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
OLDNEW
« no previous file with comments | « media/gpu/android/media_codec_video_decoder.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698