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

Side by Side Diff: media/gpu/android_video_decode_accelerator.cc

Issue 2106133003: [M52] Make AVDA fall back to software decoding if needed. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@2743
Patch Set: Created 4 years, 5 months 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_video_decode_accelerator.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 (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 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/android_video_decode_accelerator.h" 5 #include "media/gpu/android_video_decode_accelerator.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <memory> 9 #include <memory>
10 10
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
108 static inline const base::TimeDelta ErrorPostingDelay() { 108 static inline const base::TimeDelta ErrorPostingDelay() {
109 return base::TimeDelta::FromSeconds(2); 109 return base::TimeDelta::FromSeconds(2);
110 } 110 }
111 111
112 // For RecordFormatChangedMetric. 112 // For RecordFormatChangedMetric.
113 enum FormatChangedValue { 113 enum FormatChangedValue {
114 CodecInitialized = false, 114 CodecInitialized = false,
115 MissingFormatChanged = true 115 MissingFormatChanged = true
116 }; 116 };
117 117
118 // Maximum number of concurrent, incomplete codec creations that we'll allow
119 // before turning off autodection of codec type.
120 enum { kMaxConcurrentCodecAutodetections = 4 };
121
118 static inline void RecordFormatChangedMetric(FormatChangedValue value) { 122 static inline void RecordFormatChangedMetric(FormatChangedValue value) {
119 UMA_HISTOGRAM_BOOLEAN("Media.AVDA.MissingFormatChanged", !!value); 123 UMA_HISTOGRAM_BOOLEAN("Media.AVDA.MissingFormatChanged", !!value);
120 } 124 }
121 125
122 // Handle OnFrameAvailable callbacks safely. Since they occur asynchronously, 126 // Handle OnFrameAvailable callbacks safely. Since they occur asynchronously,
123 // we take care that the AVDA that wants them still exists. A WeakPtr to 127 // we take care that the AVDA that wants them still exists. A WeakPtr to
124 // the AVDA would be preferable, except that OnFrameAvailable callbacks can 128 // the AVDA would be preferable, except that OnFrameAvailable callbacks can
125 // occur off the gpu main thread. We also can't guarantee when the 129 // occur off the gpu main thread. We also can't guarantee when the
126 // SurfaceTexture will quit sending callbacks to coordinate with the 130 // SurfaceTexture will quit sending callbacks to coordinate with the
127 // destruction of the AVDA, so we have a separate object that the cb can own. 131 // destruction of the AVDA, so we have a separate object that the cb can own.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 // buffer to MediaCodec). This is inherently a race, since we don't know if 182 // buffer to MediaCodec). This is inherently a race, since we don't know if
179 // MediaCodec is broken or just slow. Since the MediaCodec API doesn't let 183 // MediaCodec is broken or just slow. Since the MediaCodec API doesn't let
180 // us wait on MediaCodec state changes prior to L, we more or less have to 184 // us wait on MediaCodec state changes prior to L, we more or less have to
181 // time out or keep polling forever in some common cases. 185 // time out or keep polling forever in some common cases.
182 class AVDATimerManager { 186 class AVDATimerManager {
183 public: 187 public:
184 // Make sure that the construction thread is started for |avda_instance|. 188 // Make sure that the construction thread is started for |avda_instance|.
185 bool StartThread(AndroidVideoDecodeAccelerator* avda_instance) { 189 bool StartThread(AndroidVideoDecodeAccelerator* avda_instance) {
186 DCHECK(thread_checker_.CalledOnValidThread()); 190 DCHECK(thread_checker_.CalledOnValidThread());
187 191
188 if (thread_avda_instances_.empty()) { 192 // If we chose not to shut it down due to pending codec constructions, then
193 // the thread might already be started even if there are no avda instances.
194 // Plus, sometimes we just fail to start the thread.
195 if (!construction_thread_.IsRunning()) {
189 if (!construction_thread_.Start()) { 196 if (!construction_thread_.Start()) {
190 LOG(ERROR) << "Failed to start construction thread."; 197 LOG(ERROR) << "Failed to start construction thread.";
191 return false; 198 return false;
192 } 199 }
193 } 200 }
194 201
195 thread_avda_instances_.insert(avda_instance); 202 thread_avda_instances_.insert(avda_instance);
196 return true; 203 return true;
197 } 204 }
198 205
199 // |avda_instance| will no longer need the construction thread. Stop the 206 // |avda_instance| will no longer need the construction thread. Stop the
200 // thread if this is the last instance. 207 // thread if this is the last instance.
201 void StopThread(AndroidVideoDecodeAccelerator* avda_instance) { 208 void StopThread(AndroidVideoDecodeAccelerator* avda_instance) {
202 DCHECK(thread_checker_.CalledOnValidThread()); 209 DCHECK(thread_checker_.CalledOnValidThread());
203 210
204 thread_avda_instances_.erase(avda_instance); 211 thread_avda_instances_.erase(avda_instance);
205 if (thread_avda_instances_.empty()) 212 if (!thread_avda_instances_.empty())
206 construction_thread_.Stop(); 213 return;
214
215 // Don't stop the thread if there are outstanding requests, since they
216 // might be hung. They also might simply be incomplete, and the thread
217 // will stay running until we try to shut it down again.
218 base::AutoLock auto_lock(autodetection_info_.lock_);
219 if (autodetection_info_.outstanding_)
220 return;
221
222 construction_thread_.Stop();
207 } 223 }
208 224
209 // Request periodic callback of |avda_instance|->DoIOTask(). Does nothing if 225 // Request periodic callback of |avda_instance|->DoIOTask(). Does nothing if
210 // the instance is already registered and the timer started. The first request 226 // the instance is already registered and the timer started. The first request
211 // will start the repeating timer on an interval of DecodePollDelay(). 227 // will start the repeating timer on an interval of DecodePollDelay().
212 void StartTimer(AndroidVideoDecodeAccelerator* avda_instance) { 228 void StartTimer(AndroidVideoDecodeAccelerator* avda_instance) {
213 DCHECK(thread_checker_.CalledOnValidThread()); 229 DCHECK(thread_checker_.CalledOnValidThread());
214 230
215 timer_avda_instances_.insert(avda_instance); 231 timer_avda_instances_.insert(avda_instance);
216 232
(...skipping 25 matching lines...) Expand all
242 io_timer_.Stop(); 258 io_timer_.Stop();
243 } 259 }
244 260
245 // Eventually, we should run the timer on this thread. For now, we just keep 261 // Eventually, we should run the timer on this thread. For now, we just keep
246 // it as a convenience for construction. 262 // it as a convenience for construction.
247 scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() { 263 scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() {
248 DCHECK(thread_checker_.CalledOnValidThread()); 264 DCHECK(thread_checker_.CalledOnValidThread());
249 return construction_thread_.task_runner(); 265 return construction_thread_.task_runner();
250 } 266 }
251 267
268 // Called on the main thread when codec autodetection starts. There may be
269 // several calls to this before any call to OnAsyncCodecAutodetectionComplete.
270 void OnAsyncCodecAutodetectionStarted() {
271 base::AutoLock auto_lock(autodetection_info_.lock_);
272 ++autodetection_info_.outstanding_;
273 }
274
275 // Called on any thread when a codec is constructed with autodetection. This
276 // assumes that requests are ordered, so please don't mix sync and async codec
277 // construction here. This may be called on any thread.
278 void OnAsyncCodecAutodetectionComplete() {
279 base::AutoLock auto_lock_l(autodetection_info_.lock_);
280 DCHECK_GT(autodetection_info_.outstanding_, 0);
281 --autodetection_info_.outstanding_;
282 }
283
284 // Return a hint about whether autodetecting the codec type is safe or not.
285 bool IsCodecAutodetectionProbablySafe() {
286 base::AutoLock auto_lock_l(autodetection_info_.lock_);
287
288 return autodetection_info_.outstanding_ < kMaxConcurrentCodecAutodetections;
289 }
290
252 // |avda| would like to use |surface_id|. If it is not busy, then mark it 291 // |avda| would like to use |surface_id|. If it is not busy, then mark it
253 // as busy and return true. If it is busy, then replace any existing waiter, 292 // as busy and return true. If it is busy, then replace any existing waiter,
254 // make |avda| the current waiter, and return false. Any existing waiter 293 // make |avda| the current waiter, and return false. Any existing waiter
255 // is assumed to be on the way out, so we fail its allocation request. 294 // is assumed to be on the way out, so we fail its allocation request.
256 bool AllocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) { 295 bool AllocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) {
257 // Nobody has to wait for no surface. 296 // Nobody has to wait for no surface.
258 if (surface_id == AndroidVideoDecodeAccelerator::Config::kNoSurfaceID) 297 if (surface_id == AndroidVideoDecodeAccelerator::Config::kNoSurfaceID)
259 return true; 298 return true;
260 299
261 auto iter = surface_waiter_map_.find(surface_id); 300 auto iter = surface_waiter_map_.find(surface_id);
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 SurfaceWaiterMap surface_waiter_map_; 386 SurfaceWaiterMap surface_waiter_map_;
348 387
349 // Since we can't delete while iterating when using a set, defer erasure until 388 // Since we can't delete while iterating when using a set, defer erasure until
350 // after iteration complete. 389 // after iteration complete.
351 bool timer_running_ = false; 390 bool timer_running_ = false;
352 std::set<AndroidVideoDecodeAccelerator*> pending_erase_; 391 std::set<AndroidVideoDecodeAccelerator*> pending_erase_;
353 392
354 // Repeating timer responsible for draining pending IO to the codecs. 393 // Repeating timer responsible for draining pending IO to the codecs.
355 base::RepeatingTimer io_timer_; 394 base::RepeatingTimer io_timer_;
356 395
396 // Data for determining if codec creation is hanging.
397 struct {
398 // Lock that protects other members of this struct.
399 base::Lock lock_;
400
401 // Number of currently pending autodetection requests.
402 int outstanding_ = 0;
403 } autodetection_info_;
404
357 base::Thread construction_thread_; 405 base::Thread construction_thread_;
358 406
359 base::ThreadChecker thread_checker_; 407 base::ThreadChecker thread_checker_;
360 408
361 DISALLOW_COPY_AND_ASSIGN(AVDATimerManager); 409 DISALLOW_COPY_AND_ASSIGN(AVDATimerManager);
362 }; 410 };
363 411
364 static base::LazyInstance<AVDATimerManager>::Leaky g_avda_timer = 412 static base::LazyInstance<AVDATimerManager>::Leaky g_avda_timer =
365 LAZY_INSTANCE_INITIALIZER; 413 LAZY_INSTANCE_INITIALIZER;
366 414
(...skipping 670 matching lines...) Expand 10 before | Expand all | Expand 10 after
1037 // Tell the strategy that we're changing codecs. The codec itself could be 1085 // Tell the strategy that we're changing codecs. The codec itself could be
1038 // used normally, since we don't replace it until we're back on the main 1086 // used normally, since we don't replace it until we're back on the main
1039 // thread. However, if we're using an output surface, then the incoming codec 1087 // thread. However, if we're using an output surface, then the incoming codec
1040 // might access that surface while the main thread is drawing. Telling the 1088 // might access that surface while the main thread is drawing. Telling the
1041 // strategy to forget the codec avoids this. 1089 // strategy to forget the codec avoids this.
1042 if (media_codec_) { 1090 if (media_codec_) {
1043 media_codec_.reset(); 1091 media_codec_.reset();
1044 strategy_->CodecChanged(nullptr); 1092 strategy_->CodecChanged(nullptr);
1045 } 1093 }
1046 1094
1095 // Choose whether to autodetect the codec type.
1096 codec_config_->allow_autodetection_ =
1097 g_avda_timer.Pointer()->IsCodecAutodetectionProbablySafe();
1098 codec_config_->notify_completion_ = codec_config_->allow_autodetection_;
1099 if (codec_config_->allow_autodetection_)
1100 g_avda_timer.Pointer()->OnAsyncCodecAutodetectionStarted();
1101
1102 // If we're not trying autodetection, then use the main thread. The original
1103 // might be blocked.
1047 scoped_refptr<base::SingleThreadTaskRunner> task_runner = 1104 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
1048 g_avda_timer.Pointer()->ConstructionTaskRunner(); 1105 codec_config_->allow_autodetection_
1106 ? g_avda_timer.Pointer()->ConstructionTaskRunner()
1107 : base::ThreadTaskRunnerHandle::Get();
1049 CHECK(task_runner); 1108 CHECK(task_runner);
1050 1109
1051 base::PostTaskAndReplyWithResult( 1110 base::PostTaskAndReplyWithResult(
1052 task_runner.get(), FROM_HERE, 1111 task_runner.get(), FROM_HERE,
1053 base::Bind(&AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread, 1112 base::Bind(&AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread,
1054 codec_config_), 1113 codec_config_),
1055 base::Bind(&AndroidVideoDecodeAccelerator::OnCodecConfigured, 1114 base::Bind(&AndroidVideoDecodeAccelerator::OnCodecConfigured,
1056 weak_this_factory_.GetWeakPtr())); 1115 weak_this_factory_.GetWeakPtr()));
1057 } 1116 }
1058 1117
1059 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodecSynchronously() { 1118 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodecSynchronously() {
1060 state_ = WAITING_FOR_CODEC; 1119 state_ = WAITING_FOR_CODEC;
1120
1121 // Decide whether to allow autodetection or not. Since we're on the main
1122 // thread, and this request is unordered with respect to pending async config
1123 // attempts, don't record it. It may break book-keeping, and there's not
1124 // much we can do anyway.
1125 codec_config_->allow_autodetection_ =
1126 g_avda_timer.Pointer()->IsCodecAutodetectionProbablySafe();
1127 codec_config_->notify_completion_ = false;
1128
1061 std::unique_ptr<media::VideoCodecBridge> media_codec = 1129 std::unique_ptr<media::VideoCodecBridge> media_codec =
1062 ConfigureMediaCodecOnAnyThread(codec_config_); 1130 ConfigureMediaCodecOnAnyThread(codec_config_);
1063 OnCodecConfigured(std::move(media_codec)); 1131 OnCodecConfigured(std::move(media_codec));
1064 return !!media_codec_; 1132 return !!media_codec_;
1065 } 1133 }
1066 1134
1067 std::unique_ptr<media::VideoCodecBridge> 1135 std::unique_ptr<media::VideoCodecBridge>
1068 AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread( 1136 AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread(
1069 scoped_refptr<CodecConfig> codec_config) { 1137 scoped_refptr<CodecConfig> codec_config) {
1070 TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec"); 1138 TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec");
1071 1139
1072 jobject media_crypto = codec_config->media_crypto_ 1140 jobject media_crypto = codec_config->media_crypto_
1073 ? codec_config->media_crypto_->obj() 1141 ? codec_config->media_crypto_->obj()
1074 : nullptr; 1142 : nullptr;
1075 1143
1076 // |needs_protected_surface_| implies encrypted stream. 1144 // |needs_protected_surface_| implies encrypted stream.
1077 DCHECK(!codec_config->needs_protected_surface_ || media_crypto); 1145 DCHECK(!codec_config->needs_protected_surface_ || media_crypto);
1078 1146
1079 return std::unique_ptr<media::VideoCodecBridge>( 1147 const bool require_software_codec = !codec_config->allow_autodetection_;
1080 media::VideoCodecBridge::CreateDecoder( 1148
1149 std::unique_ptr<media::VideoCodecBridge> codec(
1150 VideoCodecBridge::CreateDecoder(
1081 codec_config->codec_, codec_config->needs_protected_surface_, 1151 codec_config->codec_, codec_config->needs_protected_surface_,
1082 codec_config->initial_expected_coded_size_, 1152 codec_config->initial_expected_coded_size_,
1083 codec_config->surface_.j_surface().obj(), media_crypto, true)); 1153 codec_config->surface_.j_surface().obj(), media_crypto, true,
1154 require_software_codec));
1155
1156 // If we successfully completed after an autodetect, then let the other
1157 // instances know that we didn't get stuck.
1158 if (codec_config->notify_completion_)
1159 g_avda_timer.Pointer()->OnAsyncCodecAutodetectionComplete();
1160
1161 return codec;
1084 } 1162 }
1085 1163
1086 void AndroidVideoDecodeAccelerator::OnCodecConfigured( 1164 void AndroidVideoDecodeAccelerator::OnCodecConfigured(
1087 std::unique_ptr<media::VideoCodecBridge> media_codec) { 1165 std::unique_ptr<media::VideoCodecBridge> media_codec) {
1088 DCHECK(thread_checker_.CalledOnValidThread()); 1166 DCHECK(thread_checker_.CalledOnValidThread());
1089 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED); 1167 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED);
1090 1168
1091 // Record one instance of the codec being initialized. 1169 // Record one instance of the codec being initialized.
1092 RecordFormatChangedMetric(FormatChangedValue::CodecInitialized); 1170 RecordFormatChangedMetric(FormatChangedValue::CodecInitialized);
1093 1171
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after
1325 DCHECK(thread_checker_.CalledOnValidThread()); 1403 DCHECK(thread_checker_.CalledOnValidThread());
1326 1404
1327 if (!on_destroying_surface_cb_.is_null()) { 1405 if (!on_destroying_surface_cb_.is_null()) {
1328 AVDASurfaceTracker::GetInstance()->UnregisterOnDestroyingSurfaceCallback( 1406 AVDASurfaceTracker::GetInstance()->UnregisterOnDestroyingSurfaceCallback(
1329 on_destroying_surface_cb_); 1407 on_destroying_surface_cb_);
1330 } 1408 }
1331 1409
1332 if (strategy_) 1410 if (strategy_)
1333 strategy_->EndCleanup(); 1411 strategy_->EndCleanup();
1334 1412
1413 AVDATimerManager* manager = g_avda_timer.Pointer();
1414
1335 // We no longer care about |surface_id|, in case we did before. It's okay 1415 // We no longer care about |surface_id|, in case we did before. It's okay
1336 // if we have no surface and/or weren't the owner or a waiter. 1416 // if we have no surface and/or weren't the owner or a waiter.
1337 g_avda_timer.Pointer()->DeallocateSurface(config_.surface_id, this); 1417 manager->DeallocateSurface(config_.surface_id, this);
1338 1418
1339 // Note that async codec construction might still be in progress. In that 1419 // Note that async codec construction might still be in progress. In that
1340 // case, the codec will be deleted when it completes once we invalidate all 1420 // case, the codec will be deleted when it completes once we invalidate all
1341 // our weak refs. 1421 // our weak refs.
1342 weak_this_factory_.InvalidateWeakPtrs(); 1422 weak_this_factory_.InvalidateWeakPtrs();
1343 if (media_codec_) { 1423 if (media_codec_) {
1344 g_avda_timer.Pointer()->StopTimer(this); 1424 manager->StopTimer(this);
1345 media_codec_.reset(); 1425 // If codec construction is broken, then we can't release this codec if it's
1426 // backed by hardware, else it may hang too. Post it to the construction
1427 // thread, and it'll get freed if things start working. If things are
1428 // already working, then it'll be freed soon.
1429 if (media_codec_->IsSoftwareCodec()) {
1430 media_codec_.reset();
1431 } else {
1432 manager->ConstructionTaskRunner()->DeleteSoon(FROM_HERE,
1433 media_codec_.release());
1434 }
1346 } 1435 }
1347 delete this; 1436 delete this;
1348 } 1437 }
1349 1438
1350 bool AndroidVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( 1439 bool AndroidVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread(
1351 const base::WeakPtr<Client>& decode_client, 1440 const base::WeakPtr<Client>& decode_client,
1352 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { 1441 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) {
1353 return false; 1442 return false;
1354 } 1443 }
1355 1444
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after
1663 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) { 1752 if (media::MediaCodecUtil::IsSurfaceViewOutputSupported()) {
1664 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities:: 1753 capabilities.flags |= media::VideoDecodeAccelerator::Capabilities::
1665 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; 1754 SUPPORTS_EXTERNAL_OUTPUT_SURFACE;
1666 } 1755 }
1667 } 1756 }
1668 1757
1669 return capabilities; 1758 return capabilities;
1670 } 1759 }
1671 1760
1672 } // namespace media 1761 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/android_video_decode_accelerator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698