| 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 "content/common/gpu/media/android_video_decode_accelerator.h" | 5 #include "content/common/gpu/media/android_video_decode_accelerator.h" |
| 6 | 6 |
| 7 #include <stddef.h> | 7 #include <stddef.h> |
| 8 | 8 |
| 9 #include "base/android/build_info.h" | 9 #include "base/android/build_info.h" |
| 10 #include "base/auto_reset.h" | 10 #include "base/auto_reset.h" |
| (...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 120 // we take care that the AVDA that wants them still exists. A WeakPtr to | 120 // we take care that the AVDA that wants them still exists. A WeakPtr to |
| 121 // the AVDA would be preferable, except that OnFrameAvailable callbacks can | 121 // the AVDA would be preferable, except that OnFrameAvailable callbacks can |
| 122 // occur off the gpu main thread. We also can't guarantee when the | 122 // occur off the gpu main thread. We also can't guarantee when the |
| 123 // SurfaceTexture will quit sending callbacks to coordinate with the | 123 // SurfaceTexture will quit sending callbacks to coordinate with the |
| 124 // destruction of the AVDA, so we have a separate object that the cb can own. | 124 // destruction of the AVDA, so we have a separate object that the cb can own. |
| 125 class AndroidVideoDecodeAccelerator::OnFrameAvailableHandler | 125 class AndroidVideoDecodeAccelerator::OnFrameAvailableHandler |
| 126 : public base::RefCountedThreadSafe<OnFrameAvailableHandler> { | 126 : public base::RefCountedThreadSafe<OnFrameAvailableHandler> { |
| 127 public: | 127 public: |
| 128 // We do not retain ownership of |owner|. It must remain valid until | 128 // We do not retain ownership of |owner|. It must remain valid until |
| 129 // after ClearOwner() is called. This will register with | 129 // after ClearOwner() is called. This will register with |
| 130 // |surface_texture| to receive OnFrameAvailable callbacks. | 130 // |surface_texture| to receive OnFrameAvailable callbacks. If |
| 131 // |use_separate_thread| is true, then we'll request that the callback happens |
| 132 // on a thread that is dedicated to SurfaceTexture callbacks. |
| 131 OnFrameAvailableHandler( | 133 OnFrameAvailableHandler( |
| 132 AndroidVideoDecodeAccelerator* owner, | 134 AndroidVideoDecodeAccelerator* owner, |
| 133 const scoped_refptr<gfx::SurfaceTexture>& surface_texture) | 135 const scoped_refptr<gfx::SurfaceTexture>& surface_texture, |
| 136 bool use_separate_thread) |
| 134 : owner_(owner) { | 137 : owner_(owner) { |
| 135 // Note that the callback owns a strong ref to us. | 138 // Note that the callback owns a strong ref to us. |
| 136 surface_texture->SetFrameAvailableCallbackOnAnyThread( | 139 base::Closure cb = base::Bind(&OnFrameAvailableHandler::OnFrameAvailable, |
| 137 base::Bind(&OnFrameAvailableHandler::OnFrameAvailable, | 140 scoped_refptr<OnFrameAvailableHandler>(this)); |
| 138 scoped_refptr<OnFrameAvailableHandler>(this))); | 141 |
| 142 if (use_separate_thread) |
| 143 surface_texture->SetFrameAvailableCallbackOnSeparateThread(cb); |
| 144 else |
| 145 surface_texture->SetFrameAvailableCallbackOnAnyThread(cb); |
| 139 } | 146 } |
| 140 | 147 |
| 141 // Forget about our owner, which is required before one deletes it. | 148 // Forget about our owner, which is required before one deletes it. |
| 142 // No further callbacks will happen once this completes. | 149 // No further callbacks will happen once this completes. |
| 143 void ClearOwner() { | 150 void ClearOwner() { |
| 144 base::AutoLock lock(lock_); | 151 base::AutoLock lock(lock_); |
| 145 // No callback can happen until we release the lock. | 152 // No callback can happen until we release the lock. |
| 146 owner_ = nullptr; | 153 owner_ = nullptr; |
| 147 } | 154 } |
| 148 | 155 |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 250 picturebuffers_requested_(false), | 257 picturebuffers_requested_(false), |
| 251 gl_decoder_(decoder), | 258 gl_decoder_(decoder), |
| 252 cdm_registration_id_(0), | 259 cdm_registration_id_(0), |
| 253 pending_input_buf_index_(-1), | 260 pending_input_buf_index_(-1), |
| 254 error_sequence_token_(0), | 261 error_sequence_token_(0), |
| 255 defer_errors_(false), | 262 defer_errors_(false), |
| 256 weak_this_factory_(this) { | 263 weak_this_factory_(this) { |
| 257 if (UseDeferredRenderingStrategy()) { | 264 if (UseDeferredRenderingStrategy()) { |
| 258 // TODO(liberato, watk): Figure out what we want to do about zero copy for | 265 // TODO(liberato, watk): Figure out what we want to do about zero copy for |
| 259 // fullscreen external SurfaceView in WebView. http://crbug.com/582170. | 266 // fullscreen external SurfaceView in WebView. http://crbug.com/582170. |
| 260 DCHECK(!gl_decoder_->GetContextGroup()->mailbox_manager()->UsesSync()); | 267 |
| 268 // Make sure that we're making a copy in sync mode, to verify that our |
| 269 // guess about whether we're in sync mode in NeedsBrowserCopy is correct. |
| 270 // Also make sure that, if we're in sync mode, that we're using a threaded |
| 271 // callback so that it doesn't deadlock with the main thread. |
| 272 DCHECK(!gl_decoder_->GetContextGroup()->mailbox_manager()->UsesSync() || |
| 273 (DeferredStrategyNeedsBrowserCopy() && IsCallbackThreadable())); |
| 274 |
| 261 DVLOG(1) << __FUNCTION__ << ", using deferred rendering strategy."; | 275 DVLOG(1) << __FUNCTION__ << ", using deferred rendering strategy."; |
| 262 strategy_.reset(new AndroidDeferredRenderingBackingStrategy(this)); | 276 strategy_.reset(new AndroidDeferredRenderingBackingStrategy(this)); |
| 263 } else { | 277 } else { |
| 264 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; | 278 DVLOG(1) << __FUNCTION__ << ", using copy back strategy."; |
| 265 strategy_.reset(new AndroidCopyingBackingStrategy(this)); | 279 strategy_.reset(new AndroidCopyingBackingStrategy(this)); |
| 266 } | 280 } |
| 267 } | 281 } |
| 268 | 282 |
| 269 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { | 283 AndroidVideoDecodeAccelerator::~AndroidVideoDecodeAccelerator() { |
| 270 DCHECK(thread_checker_.CalledOnValidThread()); | 284 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 328 if (surface_.IsEmpty()) { | 342 if (surface_.IsEmpty()) { |
| 329 LOG(ERROR) << "Failed to initialize the backing strategy. The returned " | 343 LOG(ERROR) << "Failed to initialize the backing strategy. The returned " |
| 330 "Java surface is empty."; | 344 "Java surface is empty."; |
| 331 return false; | 345 return false; |
| 332 } | 346 } |
| 333 | 347 |
| 334 // TODO(watk,liberato): move this into the strategy. | 348 // TODO(watk,liberato): move this into the strategy. |
| 335 scoped_refptr<gfx::SurfaceTexture> surface_texture = | 349 scoped_refptr<gfx::SurfaceTexture> surface_texture = |
| 336 strategy_->GetSurfaceTexture(); | 350 strategy_->GetSurfaceTexture(); |
| 337 if (surface_texture) { | 351 if (surface_texture) { |
| 352 // The deferred strategy requires threading the callback if we're using |
| 353 // the sync compositor. |
| 354 bool use_separate_thread = |
| 355 gl_decoder_->GetContextGroup()->mailbox_manager()->UsesSync() && |
| 356 UseDeferredRenderingStrategy(); |
| 357 DCHECK(!use_separate_thread || IsCallbackThreadable()); |
| 338 on_frame_available_handler_ = | 358 on_frame_available_handler_ = |
| 339 new OnFrameAvailableHandler(this, surface_texture); | 359 new OnFrameAvailableHandler(this, surface_texture, use_separate_thread); |
| 340 } | 360 } |
| 341 | 361 |
| 342 // For encrypted streams we postpone configuration until MediaCrypto is | 362 // For encrypted streams we postpone configuration until MediaCrypto is |
| 343 // available. | 363 // available. |
| 344 if (is_encrypted_) | 364 if (is_encrypted_) |
| 345 return true; | 365 return true; |
| 346 | 366 |
| 347 return ConfigureMediaCodec(); | 367 return ConfigureMediaCodec(); |
| 348 } | 368 } |
| 349 | 369 |
| (...skipping 745 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1095 } | 1115 } |
| 1096 | 1116 |
| 1097 if (should_be_running) | 1117 if (should_be_running) |
| 1098 g_avda_timer.Pointer()->StartTimer(this); | 1118 g_avda_timer.Pointer()->StartTimer(this); |
| 1099 else | 1119 else |
| 1100 g_avda_timer.Pointer()->StopTimer(this); | 1120 g_avda_timer.Pointer()->StopTimer(this); |
| 1101 } | 1121 } |
| 1102 | 1122 |
| 1103 // static | 1123 // static |
| 1104 bool AndroidVideoDecodeAccelerator::UseDeferredRenderingStrategy() { | 1124 bool AndroidVideoDecodeAccelerator::UseDeferredRenderingStrategy() { |
| 1105 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); | |
| 1106 // TODO(liberato, watk): Figure out what we want to do about zero copy for | 1125 // TODO(liberato, watk): Figure out what we want to do about zero copy for |
| 1107 // fullscreen external SurfaceView in WebView. http://crbug.com/582170. | 1126 // fullscreen external SurfaceView in WebView. http://crbug.com/582170. |
| 1108 return !cmd_line->HasSwitch(switches::kEnableThreadedTextureMailboxes); | 1127 // If we are at API 21, we can use this any time. Otherwise, we cannot use |
| 1128 // it for webview, since we cannot set the callback thread, causing a |
| 1129 // deadlock with the compositor. |
| 1130 return IsCallbackThreadable() || !DeferredStrategyNeedsBrowserCopy(); |
| 1109 } | 1131 } |
| 1110 | 1132 |
| 1111 // static | 1133 // static |
| 1134 bool AndroidVideoDecodeAccelerator::DeferredStrategyNeedsBrowserCopy() { |
| 1135 // If we're using the synchronous mailbox mechanism and the deferred |
| 1136 // rendering strategy, then we need to force a copy before sending to |
| 1137 // the browser compositor. |
| 1138 // The copy is required because SurfaceTexture client textures can't be |
| 1139 // shared across unrelated GL contexts. By deferring the copy until the |
| 1140 // frame is sent to the browser compositor, we can limit the number of |
| 1141 // outstanding copies to be ~2, regardless of how many the pipeline wants |
| 1142 // for better playback. |
| 1143 // In practice, all of that means "WebView requires a copy". |
| 1144 |
| 1145 // We'd really like to check |
| 1146 // gl_decoder_->GetContextGroup()->mailbox_manager()->UsesSync() here, but |
| 1147 // we're called too early in start-up for that to be set properly. |
| 1148 // Instead, we use this switch and verify it later. |
| 1149 const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess(); |
| 1150 return cmd_line->HasSwitch(switches::kEnableThreadedTextureMailboxes); |
| 1151 } |
| 1152 |
| 1153 // static |
| 1154 bool AndroidVideoDecodeAccelerator::IsCallbackThreadable() { |
| 1155 return base::android::BuildInfo::GetInstance()->sdk_int() >= 21; |
| 1156 } |
| 1157 |
| 1158 // static |
| 1112 media::VideoDecodeAccelerator::Capabilities | 1159 media::VideoDecodeAccelerator::Capabilities |
| 1113 AndroidVideoDecodeAccelerator::GetCapabilities() { | 1160 AndroidVideoDecodeAccelerator::GetCapabilities() { |
| 1114 Capabilities capabilities; | 1161 Capabilities capabilities; |
| 1115 SupportedProfiles& profiles = capabilities.supported_profiles; | 1162 SupportedProfiles& profiles = capabilities.supported_profiles; |
| 1116 | 1163 |
| 1117 SupportedProfile profile; | 1164 SupportedProfile profile; |
| 1118 | 1165 |
| 1119 if (media::MediaCodecUtil::IsVp8DecoderAvailable()) { | 1166 if (media::MediaCodecUtil::IsVp8DecoderAvailable()) { |
| 1120 profile.profile = media::VP8PROFILE_ANY; | 1167 profile.profile = media::VP8PROFILE_ANY; |
| 1121 profile.min_resolution.SetSize(0, 0); | 1168 profile.min_resolution.SetSize(0, 0); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1139 // software fallback for H264 on Android anyway. | 1186 // software fallback for H264 on Android anyway. |
| 1140 profile.max_resolution.SetSize(3840, 2160); | 1187 profile.max_resolution.SetSize(3840, 2160); |
| 1141 profiles.push_back(profile); | 1188 profiles.push_back(profile); |
| 1142 } | 1189 } |
| 1143 | 1190 |
| 1144 if (UseDeferredRenderingStrategy()) { | 1191 if (UseDeferredRenderingStrategy()) { |
| 1145 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: | 1192 capabilities.flags = media::VideoDecodeAccelerator::Capabilities:: |
| 1146 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE | | 1193 NEEDS_ALL_PICTURE_BUFFERS_TO_DECODE | |
| 1147 media::VideoDecodeAccelerator::Capabilities:: | 1194 media::VideoDecodeAccelerator::Capabilities:: |
| 1148 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; | 1195 SUPPORTS_EXTERNAL_OUTPUT_SURFACE; |
| 1196 if (DeferredStrategyNeedsBrowserCopy()) |
| 1197 capabilities.flags |= |
| 1198 media::VideoDecodeAccelerator::Capabilities::COPY_REQUIRED; |
| 1149 } | 1199 } |
| 1150 | 1200 |
| 1151 return capabilities; | 1201 return capabilities; |
| 1152 } | 1202 } |
| 1153 | 1203 |
| 1154 } // namespace content | 1204 } // namespace content |
| OLD | NEW |