Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 |
| 126 static void delete_codec_helper(std::unique_ptr<VideoCodecBridge> codec) { | |
| 127 // Do nothing with codec. It will be deleted / released on destruction. | |
| 128 } | |
| 129 | |
| 122 // Handle OnFrameAvailable callbacks safely. Since they occur asynchronously, | 130 // Handle OnFrameAvailable callbacks safely. Since they occur asynchronously, |
| 123 // we take care that the AVDA that wants them still exists. A WeakPtr to | 131 // 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 | 132 // the AVDA would be preferable, except that OnFrameAvailable callbacks can |
| 125 // occur off the gpu main thread. We also can't guarantee when the | 133 // occur off the gpu main thread. We also can't guarantee when the |
| 126 // SurfaceTexture will quit sending callbacks to coordinate with the | 134 // 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. | 135 // destruction of the AVDA, so we have a separate object that the cb can own. |
| 128 class AndroidVideoDecodeAccelerator::OnFrameAvailableHandler | 136 class AndroidVideoDecodeAccelerator::OnFrameAvailableHandler |
| 129 : public base::RefCountedThreadSafe<OnFrameAvailableHandler> { | 137 : public base::RefCountedThreadSafe<OnFrameAvailableHandler> { |
| 130 public: | 138 public: |
| 131 // We do not retain ownership of |owner|. It must remain valid until | 139 // We do not retain ownership of |owner|. It must remain valid until |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 178 // buffer to MediaCodec). This is inherently a race, since we don't know if | 186 // 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 | 187 // 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 | 188 // 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. | 189 // time out or keep polling forever in some common cases. |
| 182 class AVDATimerManager { | 190 class AVDATimerManager { |
| 183 public: | 191 public: |
| 184 // Make sure that the construction thread is started for |avda_instance|. | 192 // Make sure that the construction thread is started for |avda_instance|. |
| 185 bool StartThread(AndroidVideoDecodeAccelerator* avda_instance) { | 193 bool StartThread(AndroidVideoDecodeAccelerator* avda_instance) { |
| 186 DCHECK(thread_checker_.CalledOnValidThread()); | 194 DCHECK(thread_checker_.CalledOnValidThread()); |
| 187 | 195 |
| 188 if (thread_avda_instances_.empty()) { | 196 // If we chose not to shut it down due to pending codec constructions, then |
| 197 // the thread might already be started even if there are no avda instances. | |
| 198 // Plus, sometimes we just fail to start the thread. | |
| 199 if (!construction_thread_.IsRunning()) { | |
| 189 if (!construction_thread_.Start()) { | 200 if (!construction_thread_.Start()) { |
| 190 LOG(ERROR) << "Failed to start construction thread."; | 201 LOG(ERROR) << "Failed to start construction thread."; |
| 191 return false; | 202 return false; |
| 192 } | 203 } |
| 193 } | 204 } |
| 194 | 205 |
| 195 thread_avda_instances_.insert(avda_instance); | 206 thread_avda_instances_.insert(avda_instance); |
| 196 return true; | 207 return true; |
| 197 } | 208 } |
| 198 | 209 |
| 199 // |avda_instance| will no longer need the construction thread. Stop the | 210 // |avda_instance| will no longer need the construction thread. Stop the |
| 200 // thread if this is the last instance. | 211 // thread if this is the last instance. |
| 201 void StopThread(AndroidVideoDecodeAccelerator* avda_instance) { | 212 void StopThread(AndroidVideoDecodeAccelerator* avda_instance) { |
| 202 DCHECK(thread_checker_.CalledOnValidThread()); | 213 DCHECK(thread_checker_.CalledOnValidThread()); |
| 203 | 214 |
| 204 thread_avda_instances_.erase(avda_instance); | 215 thread_avda_instances_.erase(avda_instance); |
| 205 if (thread_avda_instances_.empty()) | 216 if (!thread_avda_instances_.empty()) |
| 206 construction_thread_.Stop(); | 217 return; |
| 218 | |
| 219 // Don't stop the thread if there are outstanding requests, since they | |
| 220 // might be hung. They also might simply be incomplete, and the thread | |
| 221 // will stay running until we try to shut it down again. | |
| 222 base::AutoLock _l(autodetection_info_.lock_); | |
| 223 if (autodetection_info_.outstanding_) | |
| 224 return; | |
| 225 | |
| 226 construction_thread_.Stop(); | |
| 207 } | 227 } |
| 208 | 228 |
| 209 // Request periodic callback of |avda_instance|->DoIOTask(). Does nothing if | 229 // Request periodic callback of |avda_instance|->DoIOTask(). Does nothing if |
| 210 // the instance is already registered and the timer started. The first request | 230 // the instance is already registered and the timer started. The first request |
| 211 // will start the repeating timer on an interval of DecodePollDelay(). | 231 // will start the repeating timer on an interval of DecodePollDelay(). |
| 212 void StartTimer(AndroidVideoDecodeAccelerator* avda_instance) { | 232 void StartTimer(AndroidVideoDecodeAccelerator* avda_instance) { |
| 213 DCHECK(thread_checker_.CalledOnValidThread()); | 233 DCHECK(thread_checker_.CalledOnValidThread()); |
| 214 | 234 |
| 215 timer_avda_instances_.insert(avda_instance); | 235 timer_avda_instances_.insert(avda_instance); |
| 216 | 236 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 242 io_timer_.Stop(); | 262 io_timer_.Stop(); |
| 243 } | 263 } |
| 244 | 264 |
| 245 // Eventually, we should run the timer on this thread. For now, we just keep | 265 // Eventually, we should run the timer on this thread. For now, we just keep |
| 246 // it as a convenience for construction. | 266 // it as a convenience for construction. |
| 247 scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() { | 267 scoped_refptr<base::SingleThreadTaskRunner> ConstructionTaskRunner() { |
| 248 DCHECK(thread_checker_.CalledOnValidThread()); | 268 DCHECK(thread_checker_.CalledOnValidThread()); |
| 249 return construction_thread_.task_runner(); | 269 return construction_thread_.task_runner(); |
| 250 } | 270 } |
| 251 | 271 |
| 272 // Called on the main thread when codec autodetection starts. There may be | |
| 273 // several calls to this before any call to OnAnyThread. | |
| 274 void OnAsyncCodecAutodetectionStarted() { | |
| 275 base::AutoLock _l(autodetection_info_.lock_); | |
|
DaleCurtis
2016/06/22 19:13:49
Chose something other than _l :)
liberato (no reviews please)
2016/06/22 20:44:12
done. that's a habit from android native code.
| |
| 276 ++autodetection_info_.outstanding_; | |
| 277 } | |
| 278 | |
| 279 // Called on any thread when a codec is constructed with autodetection. This | |
| 280 // assumes that requests are ordered, so please don't mix sync and async codec | |
| 281 // construction here. This may be called on any thread. | |
| 282 void OnAsyncCodecAutodetectionComplete() { | |
| 283 base::AutoLock _l(autodetection_info_.lock_); | |
| 284 DCHECK(autodetection_info_.outstanding_ > 0); | |
|
DaleCurtis
2016/06/22 19:13:49
DCHECK_GT()
liberato (no reviews please)
2016/06/22 20:44:12
Done.
| |
| 285 --autodetection_info_.outstanding_; | |
| 286 } | |
| 287 | |
| 288 // Return a hint about whether autodetecting the codec type is safe or not. | |
| 289 bool IsCodecAutodetectionProbablySafe() { | |
| 290 base::AutoLock _l(autodetection_info_.lock_); | |
| 291 | |
| 292 return autodetection_info_.outstanding_ < kMaxConcurrentCodecAutodetections; | |
| 293 } | |
| 294 | |
| 252 // |avda| would like to use |surface_id|. If it is not busy, then mark it | 295 // |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, | 296 // 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 | 297 // 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. | 298 // is assumed to be on the way out, so we fail its allocation request. |
| 256 bool AllocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) { | 299 bool AllocateSurface(int surface_id, AndroidVideoDecodeAccelerator* avda) { |
| 257 // Nobody has to wait for no surface. | 300 // Nobody has to wait for no surface. |
| 258 if (surface_id == AndroidVideoDecodeAccelerator::Config::kNoSurfaceID) | 301 if (surface_id == AndroidVideoDecodeAccelerator::Config::kNoSurfaceID) |
| 259 return true; | 302 return true; |
| 260 | 303 |
| 261 auto iter = surface_waiter_map_.find(surface_id); | 304 auto iter = surface_waiter_map_.find(surface_id); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 347 SurfaceWaiterMap surface_waiter_map_; | 390 SurfaceWaiterMap surface_waiter_map_; |
| 348 | 391 |
| 349 // Since we can't delete while iterating when using a set, defer erasure until | 392 // Since we can't delete while iterating when using a set, defer erasure until |
| 350 // after iteration complete. | 393 // after iteration complete. |
| 351 bool timer_running_ = false; | 394 bool timer_running_ = false; |
| 352 std::set<AndroidVideoDecodeAccelerator*> pending_erase_; | 395 std::set<AndroidVideoDecodeAccelerator*> pending_erase_; |
| 353 | 396 |
| 354 // Repeating timer responsible for draining pending IO to the codecs. | 397 // Repeating timer responsible for draining pending IO to the codecs. |
| 355 base::RepeatingTimer io_timer_; | 398 base::RepeatingTimer io_timer_; |
| 356 | 399 |
| 400 // Data for determining if codec creation is hanging. | |
|
DaleCurtis
2016/06/22 19:13:49
Doesn't seem like this is necessary anymore? Can't
liberato (no reviews please)
2016/06/22 20:44:12
unfortunately, not safely. we'd lose the incremen
DaleCurtis
2016/06/22 20:56:49
What do you mean? Just have a bool pending_initial
liberato (no reviews please)
2016/06/22 21:07:58
OnCodecInitialized is weakptr'd in the callback.
DaleCurtis
2016/06/22 21:11:50
Sure, but if you get to destruction with pending_i
liberato (no reviews please)
2016/06/22 21:13:28
wouldn't we get to destruction with pending_initia
DaleCurtis
2016/06/22 21:20:10
Ah, yeah, sorry I didn't think that through.
| |
| 401 struct { | |
| 402 // Lock that protects other members of this struct. | |
| 403 base::Lock lock_; | |
| 404 | |
| 405 // Number of currently pending autodetection requests. | |
| 406 int outstanding_ = 0; | |
| 407 } autodetection_info_; | |
| 408 | |
| 357 base::Thread construction_thread_; | 409 base::Thread construction_thread_; |
| 358 | 410 |
| 359 base::ThreadChecker thread_checker_; | 411 base::ThreadChecker thread_checker_; |
| 360 | 412 |
| 361 DISALLOW_COPY_AND_ASSIGN(AVDATimerManager); | 413 DISALLOW_COPY_AND_ASSIGN(AVDATimerManager); |
| 362 }; | 414 }; |
| 363 | 415 |
| 364 static base::LazyInstance<AVDATimerManager>::Leaky g_avda_timer = | 416 static base::LazyInstance<AVDATimerManager>::Leaky g_avda_timer = |
| 365 LAZY_INSTANCE_INITIALIZER; | 417 LAZY_INSTANCE_INITIALIZER; |
| 366 | 418 |
| (...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1040 // Tell the strategy that we're changing codecs. The codec itself could be | 1092 // Tell the strategy that we're changing codecs. The codec itself could be |
| 1041 // used normally, since we don't replace it until we're back on the main | 1093 // used normally, since we don't replace it until we're back on the main |
| 1042 // thread. However, if we're using an output surface, then the incoming codec | 1094 // thread. However, if we're using an output surface, then the incoming codec |
| 1043 // might access that surface while the main thread is drawing. Telling the | 1095 // might access that surface while the main thread is drawing. Telling the |
| 1044 // strategy to forget the codec avoids this. | 1096 // strategy to forget the codec avoids this. |
| 1045 if (media_codec_) { | 1097 if (media_codec_) { |
| 1046 media_codec_.reset(); | 1098 media_codec_.reset(); |
| 1047 strategy_->CodecChanged(nullptr); | 1099 strategy_->CodecChanged(nullptr); |
| 1048 } | 1100 } |
| 1049 | 1101 |
| 1102 // Choose whether to autodetect the codec type. | |
| 1103 codec_config_->allow_autodetection_ = | |
| 1104 g_avda_timer.Pointer()->IsCodecAutodetectionProbablySafe(); | |
| 1105 codec_config_->notify_completion_ = codec_config_->allow_autodetection_; | |
| 1106 if (codec_config_->allow_autodetection_) | |
| 1107 g_avda_timer.Pointer()->OnAsyncCodecAutodetectionStarted(); | |
| 1108 | |
| 1109 // If we're not trying autodetection, then use the main thread. The original | |
| 1110 // might be blocked. | |
| 1050 scoped_refptr<base::SingleThreadTaskRunner> task_runner = | 1111 scoped_refptr<base::SingleThreadTaskRunner> task_runner = |
| 1051 g_avda_timer.Pointer()->ConstructionTaskRunner(); | 1112 codec_config_->allow_autodetection_ |
| 1113 ? g_avda_timer.Pointer()->ConstructionTaskRunner() | |
| 1114 : base::ThreadTaskRunnerHandle::Get(); | |
| 1052 CHECK(task_runner); | 1115 CHECK(task_runner); |
| 1053 | 1116 |
| 1054 base::PostTaskAndReplyWithResult( | 1117 base::PostTaskAndReplyWithResult( |
| 1055 task_runner.get(), FROM_HERE, | 1118 task_runner.get(), FROM_HERE, |
| 1056 base::Bind(&AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread, | 1119 base::Bind(&AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread, |
| 1057 codec_config_), | 1120 codec_config_), |
| 1058 base::Bind(&AndroidVideoDecodeAccelerator::OnCodecConfigured, | 1121 base::Bind(&AndroidVideoDecodeAccelerator::OnCodecConfigured, |
| 1059 weak_this_factory_.GetWeakPtr())); | 1122 weak_this_factory_.GetWeakPtr())); |
| 1060 } | 1123 } |
| 1061 | 1124 |
| 1062 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodecSynchronously() { | 1125 bool AndroidVideoDecodeAccelerator::ConfigureMediaCodecSynchronously() { |
| 1063 state_ = WAITING_FOR_CODEC; | 1126 state_ = WAITING_FOR_CODEC; |
| 1127 | |
| 1128 // Decide whether to allow autodetection or not. Since we're on the main | |
| 1129 // thread, and this request is unordered with respect to pending async config | |
| 1130 // attempts, don't record it. It may break book-keeping, and there's not | |
| 1131 // much we can do anyway. | |
| 1132 codec_config_->allow_autodetection_ = | |
| 1133 g_avda_timer.Pointer()->IsCodecAutodetectionProbablySafe(); | |
| 1134 codec_config_->notify_completion_ = false; | |
| 1135 | |
| 1064 std::unique_ptr<VideoCodecBridge> media_codec = | 1136 std::unique_ptr<VideoCodecBridge> media_codec = |
| 1065 ConfigureMediaCodecOnAnyThread(codec_config_); | 1137 ConfigureMediaCodecOnAnyThread(codec_config_); |
| 1066 OnCodecConfigured(std::move(media_codec)); | 1138 OnCodecConfigured(std::move(media_codec)); |
| 1067 return !!media_codec_; | 1139 return !!media_codec_; |
| 1068 } | 1140 } |
| 1069 | 1141 |
| 1070 std::unique_ptr<VideoCodecBridge> | 1142 std::unique_ptr<VideoCodecBridge> |
| 1071 AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread( | 1143 AndroidVideoDecodeAccelerator::ConfigureMediaCodecOnAnyThread( |
| 1072 scoped_refptr<CodecConfig> codec_config) { | 1144 scoped_refptr<CodecConfig> codec_config) { |
| 1073 TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec"); | 1145 TRACE_EVENT0("media", "AVDA::ConfigureMediaCodec"); |
| 1074 | 1146 |
| 1075 jobject media_crypto = codec_config->media_crypto_ | 1147 jobject media_crypto = codec_config->media_crypto_ |
| 1076 ? codec_config->media_crypto_->obj() | 1148 ? codec_config->media_crypto_->obj() |
| 1077 : nullptr; | 1149 : nullptr; |
| 1078 | 1150 |
| 1079 // |needs_protected_surface_| implies encrypted stream. | 1151 // |needs_protected_surface_| implies encrypted stream. |
| 1080 DCHECK(!codec_config->needs_protected_surface_ || media_crypto); | 1152 DCHECK(!codec_config->needs_protected_surface_ || media_crypto); |
| 1081 | 1153 |
| 1082 return std::unique_ptr<VideoCodecBridge>(VideoCodecBridge::CreateDecoder( | 1154 const bool require_software = !codec_config->allow_autodetection_; |
| 1155 | |
| 1156 std::unique_ptr<VideoCodecBridge> codec(VideoCodecBridge::CreateDecoder( | |
| 1083 codec_config->codec_, codec_config->needs_protected_surface_, | 1157 codec_config->codec_, codec_config->needs_protected_surface_, |
| 1084 codec_config->initial_expected_coded_size_, | 1158 codec_config->initial_expected_coded_size_, |
| 1085 codec_config->surface_.j_surface().obj(), media_crypto, true)); | 1159 codec_config->surface_.j_surface().obj(), media_crypto, true, |
| 1160 require_software)); | |
| 1161 | |
| 1162 // If we successfully completed after an autodetect, then reset the timer so | |
| 1163 // that other instances know that autodetection is okay. | |
| 1164 if (codec_config->notify_completion_) | |
| 1165 g_avda_timer.Pointer()->OnAsyncCodecAutodetectionComplete(); | |
| 1166 | |
| 1167 return codec; | |
| 1086 } | 1168 } |
| 1087 | 1169 |
| 1088 void AndroidVideoDecodeAccelerator::OnCodecConfigured( | 1170 void AndroidVideoDecodeAccelerator::OnCodecConfigured( |
| 1089 std::unique_ptr<VideoCodecBridge> media_codec) { | 1171 std::unique_ptr<VideoCodecBridge> media_codec) { |
| 1090 DCHECK(thread_checker_.CalledOnValidThread()); | 1172 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1091 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED); | 1173 DCHECK(state_ == WAITING_FOR_CODEC || state_ == SURFACE_DESTROYED); |
| 1092 | 1174 |
| 1093 // Record one instance of the codec being initialized. | 1175 // Record one instance of the codec being initialized. |
| 1094 RecordFormatChangedMetric(FormatChangedValue::CodecInitialized); | 1176 RecordFormatChangedMetric(FormatChangedValue::CodecInitialized); |
| 1095 | 1177 |
| (...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1310 StartCodecDrain(DRAIN_FOR_DESTROY); | 1392 StartCodecDrain(DRAIN_FOR_DESTROY); |
| 1311 } else { | 1393 } else { |
| 1312 ActualDestroy(); | 1394 ActualDestroy(); |
| 1313 } | 1395 } |
| 1314 } | 1396 } |
| 1315 | 1397 |
| 1316 void AndroidVideoDecodeAccelerator::ActualDestroy() { | 1398 void AndroidVideoDecodeAccelerator::ActualDestroy() { |
| 1317 DVLOG(1) << __FUNCTION__; | 1399 DVLOG(1) << __FUNCTION__; |
| 1318 DCHECK(thread_checker_.CalledOnValidThread()); | 1400 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1319 | 1401 |
| 1402 AVDATimerManager* manager = g_avda_timer.Pointer(); | |
| 1403 | |
| 1320 if (!on_destroying_surface_cb_.is_null()) { | 1404 if (!on_destroying_surface_cb_.is_null()) { |
| 1321 AVDASurfaceTracker::GetInstance()->UnregisterOnDestroyingSurfaceCallback( | 1405 AVDASurfaceTracker::GetInstance()->UnregisterOnDestroyingSurfaceCallback( |
| 1322 on_destroying_surface_cb_); | 1406 on_destroying_surface_cb_); |
| 1323 } | 1407 } |
| 1324 | 1408 |
| 1325 // We no longer care about |surface_id|, in case we did before. It's okay | 1409 // We no longer care about |surface_id|, in case we did before. It's okay |
| 1326 // if we have no surface and/or weren't the owner or a waiter. | 1410 // if we have no surface and/or weren't the owner or a waiter. |
| 1327 g_avda_timer.Pointer()->DeallocateSurface(config_.surface_id, this); | 1411 manager->DeallocateSurface(config_.surface_id, this); |
| 1328 | 1412 |
| 1329 // Note that async codec construction might still be in progress. In that | 1413 // Note that async codec construction might still be in progress. In that |
| 1330 // case, the codec will be deleted when it completes once we invalidate all | 1414 // case, the codec will be deleted when it completes once we invalidate all |
| 1331 // our weak refs. | 1415 // our weak refs. |
| 1332 weak_this_factory_.InvalidateWeakPtrs(); | 1416 weak_this_factory_.InvalidateWeakPtrs(); |
| 1333 if (media_codec_) { | 1417 if (media_codec_) { |
| 1334 g_avda_timer.Pointer()->StopTimer(this); | 1418 manager->StopTimer(this); |
| 1335 media_codec_.reset(); | 1419 // If codec construction is broken, then we can't release this codec if it's |
| 1420 // backed by hardware, else it may hang too. Post it to the construction | |
| 1421 // thread, and it'll get freed if things start working. If things are | |
| 1422 // already working, then it'll be freed soon. | |
| 1423 if (media_codec_->IsSoftwareCodec()) { | |
| 1424 media_codec_.reset(); | |
| 1425 } else { | |
| 1426 manager->ConstructionTaskRunner()->PostTask( | |
| 1427 FROM_HERE, | |
| 1428 base::Bind(delete_codec_helper, base::Passed(&media_codec_))); | |
| 1429 } | |
| 1336 } | 1430 } |
| 1337 delete this; | 1431 delete this; |
| 1338 } | 1432 } |
| 1339 | 1433 |
| 1340 bool AndroidVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( | 1434 bool AndroidVideoDecodeAccelerator::TryToSetupDecodeOnSeparateThread( |
| 1341 const base::WeakPtr<Client>& decode_client, | 1435 const base::WeakPtr<Client>& decode_client, |
| 1342 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { | 1436 const scoped_refptr<base::SingleThreadTaskRunner>& decode_task_runner) { |
| 1343 return false; | 1437 return false; |
| 1344 } | 1438 } |
| 1345 | 1439 |
| (...skipping 305 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1651 if (MediaCodecUtil::IsSurfaceViewOutputSupported()) { | 1745 if (MediaCodecUtil::IsSurfaceViewOutputSupported()) { |
| 1652 capabilities.flags |= VideoDecodeAccelerator::Capabilities:: | 1746 capabilities.flags |= VideoDecodeAccelerator::Capabilities:: |
| 1653 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; | 1747 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; |
| 1654 } | 1748 } |
| 1655 } | 1749 } |
| 1656 | 1750 |
| 1657 return capabilities; | 1751 return capabilities; |
| 1658 } | 1752 } |
| 1659 | 1753 |
| 1660 } // namespace media | 1754 } // namespace media |
| OLD | NEW |