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 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 105 | 105 |
| 106 constexpr base::TimeDelta NoWaitTimeOut = base::TimeDelta::FromMicroseconds(0); | 106 constexpr base::TimeDelta NoWaitTimeOut = base::TimeDelta::FromMicroseconds(0); |
| 107 | 107 |
| 108 constexpr base::TimeDelta IdleTimerTimeOut = base::TimeDelta::FromSeconds(1); | 108 constexpr base::TimeDelta IdleTimerTimeOut = base::TimeDelta::FromSeconds(1); |
| 109 | 109 |
| 110 // On low end devices (< KitKat is always low-end due to buggy MediaCodec), | 110 // On low end devices (< KitKat is always low-end due to buggy MediaCodec), |
| 111 // defer the surface creation until the codec is actually used if we know no | 111 // defer the surface creation until the codec is actually used if we know no |
| 112 // software fallback exists. | 112 // software fallback exists. |
| 113 bool ShouldDeferSurfaceCreation( | 113 bool ShouldDeferSurfaceCreation( |
| 114 AVDACodecAllocator* codec_allocator, | 114 AVDACodecAllocator* codec_allocator, |
| 115 int surface_id, | 115 const OverlayInfo& overlay_info, |
| 116 base::Optional<base::UnguessableToken> overlay_routing_token, | |
| 117 VideoCodec codec, | 116 VideoCodec codec, |
| 118 const AndroidVideoDecodeAccelerator::PlatformConfig& platform_config) { | 117 const AndroidVideoDecodeAccelerator::PlatformConfig& platform_config) { |
| 119 if (platform_config.force_deferred_surface_creation) | 118 if (platform_config.force_deferred_surface_creation) |
| 120 return true; | 119 return true; |
| 121 | 120 |
| 122 // TODO(liberato): We might still want to defer if we've got a routing | 121 // TODO(liberato): We might still want to defer if we've got a routing |
| 123 // token. It depends on whether we want to use it right away or not. | 122 // token. It depends on whether we want to use it right away or not. |
| 124 if (surface_id != SurfaceManager::kNoSurfaceID || overlay_routing_token) | 123 if ((overlay_info.surface_id && |
| 124 *overlay_info.surface_id != SurfaceManager::kNoSurfaceID) || | |
| 125 (overlay_info.routing_token && *overlay_info.routing_token)) { | |
| 125 return false; | 126 return false; |
| 127 } | |
| 126 | 128 |
| 127 return codec == kCodecH264 && codec_allocator->IsAnyRegisteredAVDA() && | 129 return codec == kCodecH264 && codec_allocator->IsAnyRegisteredAVDA() && |
| 128 platform_config.sdk_int <= 18; | 130 platform_config.sdk_int <= 18; |
| 129 } | 131 } |
| 130 | 132 |
| 131 std::unique_ptr<AndroidOverlay> CreateContentVideoViewOverlay( | 133 std::unique_ptr<AndroidOverlay> CreateContentVideoViewOverlay( |
| 132 int32_t surface_id, | 134 int32_t surface_id, |
| 133 AndroidOverlayConfig config) { | 135 AndroidOverlayConfig config) { |
| 134 return base::MakeUnique<ContentVideoViewOverlay>(surface_id, | 136 return base::MakeUnique<ContentVideoViewOverlay>(surface_id, |
| 135 std::move(config)); | 137 std::move(config)); |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 351 // SetSurface() can't be called before Initialize(), so we pick up our first | 353 // SetSurface() can't be called before Initialize(), so we pick up our first |
| 352 // surface ID from the codec configuration. | 354 // surface ID from the codec configuration. |
| 353 DCHECK(!pending_surface_id_); | 355 DCHECK(!pending_surface_id_); |
| 354 | 356 |
| 355 // We signaled that we support deferred initialization, so see if the client | 357 // We signaled that we support deferred initialization, so see if the client |
| 356 // does also. | 358 // does also. |
| 357 deferred_initialization_pending_ = config.is_deferred_initialization_allowed; | 359 deferred_initialization_pending_ = config.is_deferred_initialization_allowed; |
| 358 | 360 |
| 359 // If we're low on resources, we may decide to defer creation of the surface | 361 // If we're low on resources, we may decide to defer creation of the surface |
| 360 // until the codec is actually used. | 362 // until the codec is actually used. |
| 361 if (ShouldDeferSurfaceCreation(codec_allocator_, config_.surface_id, | 363 if (ShouldDeferSurfaceCreation(codec_allocator_, config_.overlay_info, |
| 362 config_.overlay_routing_token, | |
| 363 codec_config_->codec, platform_config_)) { | 364 codec_config_->codec, platform_config_)) { |
| 364 // We should never be here if a SurfaceView is required. | 365 // We should never be here if a SurfaceView is required. |
| 365 // TODO(liberato): This really isn't true with AndroidOverlay. | 366 // TODO(liberato): This really isn't true with AndroidOverlay. |
| 366 DCHECK_EQ(config_.surface_id, SurfaceManager::kNoSurfaceID); | 367 DCHECK(!config_.overlay_info.surface_id || |
|
tguilbert
2017/05/24 19:14:54
NIT: How do you feel about adding syntactic sugar
liberato (no reviews please)
2017/05/24 21:21:07
i think that it's a good idea. Done.
| |
| 368 *config_.overlay_info.surface_id == SurfaceManager::kNoSurfaceID); | |
| 367 defer_surface_creation_ = true; | 369 defer_surface_creation_ = true; |
| 368 } | 370 } |
| 369 | 371 |
| 370 if (!codec_allocator_->StartThread(this)) { | 372 if (!codec_allocator_->StartThread(this)) { |
| 371 LOG(ERROR) << "Unable to start thread"; | 373 LOG(ERROR) << "Unable to start thread"; |
| 372 return false; | 374 return false; |
| 373 } | 375 } |
| 374 | 376 |
| 375 // For encrypted media, start by initializing the CDM. Otherwise, start with | 377 // For encrypted media, start by initializing the CDM. Otherwise, start with |
| 376 // the surface. | 378 // the surface. |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 408 // | 410 // |
| 409 // Also note that we might choose to defer surface creation for the sync path, | 411 // Also note that we might choose to defer surface creation for the sync path, |
| 410 // which won't get here. We'll exit above, successfully, during init, and | 412 // which won't get here. We'll exit above, successfully, during init, and |
| 411 // will fall through to the below when Decode calls us back. That's okay. | 413 // will fall through to the below when Decode calls us back. That's okay. |
| 412 // We only handle this case specially since |surface_chooser_| is allowed to | 414 // We only handle this case specially since |surface_chooser_| is allowed to |
| 413 // post callbacks to us. Here, we guarantee that the sync case is actually | 415 // post callbacks to us. Here, we guarantee that the sync case is actually |
| 414 // resolved synchronously. The only exception will be if we need to defer | 416 // resolved synchronously. The only exception will be if we need to defer |
| 415 // surface creation for other reasons, in which case the sync path with just | 417 // surface creation for other reasons, in which case the sync path with just |
| 416 // signal success optimistically. | 418 // signal success optimistically. |
| 417 if (during_initialize_ && !deferred_initialization_pending_) { | 419 if (during_initialize_ && !deferred_initialization_pending_) { |
| 418 DCHECK_EQ(config_.surface_id, SurfaceManager::kNoSurfaceID); | 420 DCHECK(!config_.overlay_info.surface_id || |
| 419 DCHECK(!config_.overlay_routing_token); | 421 *config_.overlay_info.surface_id == SurfaceManager::kNoSurfaceID); |
| 422 DCHECK(!config_.overlay_info.routing_token || | |
| 423 !(*config_.overlay_info.routing_token)); | |
| 420 OnSurfaceTransition(nullptr); | 424 OnSurfaceTransition(nullptr); |
| 421 return; | 425 return; |
| 422 } | 426 } |
| 423 | 427 |
| 424 // If we have a surface, then notify |surface_chooser_| about it. | 428 // If we have a surface, then notify |surface_chooser_| about it. If we were |
| 429 // told not to use an overlay (kNoSurfaceID or a null routing token), then we | |
| 430 // leave the factory blank. | |
| 425 AndroidOverlayFactoryCB factory; | 431 AndroidOverlayFactoryCB factory; |
| 426 if (config_.surface_id != SurfaceManager::kNoSurfaceID) | 432 if (config_.overlay_info.surface_id && |
| 427 factory = base::Bind(&CreateContentVideoViewOverlay, config_.surface_id); | 433 *config_.overlay_info.surface_id != SurfaceManager::kNoSurfaceID) { |
| 428 else if (config_.overlay_routing_token && overlay_factory_cb_) | 434 factory = base::Bind(&CreateContentVideoViewOverlay, |
| 429 factory = base::Bind(overlay_factory_cb_, *config_.overlay_routing_token); | 435 *config_.overlay_info.surface_id); |
| 436 } else if (config_.overlay_info.routing_token && | |
| 437 *config_.overlay_info.routing_token && overlay_factory_cb_) { | |
|
tguilbert
2017/05/24 19:14:54
NIT: Same/Similar comment as above for "overlay_in
liberato (no reviews please)
2017/05/24 21:21:07
Done.
| |
| 438 factory = | |
| 439 base::Bind(overlay_factory_cb_, **config_.overlay_info.routing_token); | |
| 440 } | |
| 430 | 441 |
| 431 // Notify |surface_chooser_| that we've started. This guarantees that we'll | 442 // Notify |surface_chooser_| that we've started. This guarantees that we'll |
| 432 // get a callback. It might not be a synchronous callback, but we're not in | 443 // get a callback. It might not be a synchronous callback, but we're not in |
| 433 // the synchronous case. It will be soon, though. For pre-M, we rely on the | 444 // the synchronous case. It will be soon, though. For pre-M, we rely on the |
| 434 // fact that |surface_chooser_| won't tell us to use a SurfaceTexture while | 445 // fact that |surface_chooser_| won't tell us to use a SurfaceTexture while |
| 435 // waiting for an overlay to become ready, for example. | 446 // waiting for an overlay to become ready, for example. |
| 436 surface_chooser_->Initialize( | 447 surface_chooser_->Initialize( |
| 437 base::Bind(&AndroidVideoDecodeAccelerator::OnSurfaceTransition, | 448 base::Bind(&AndroidVideoDecodeAccelerator::OnSurfaceTransition, |
| 438 weak_this_factory_.GetWeakPtr()), | 449 weak_this_factory_.GetWeakPtr()), |
| 439 base::Bind(&AndroidVideoDecodeAccelerator::OnSurfaceTransition, | 450 base::Bind(&AndroidVideoDecodeAccelerator::OnSurfaceTransition, |
| (...skipping 802 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1242 weak_this_factory_.GetWeakPtr(), bitstream_buffer_id)); | 1253 weak_this_factory_.GetWeakPtr(), bitstream_buffer_id)); |
| 1243 } | 1254 } |
| 1244 } | 1255 } |
| 1245 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", 0); | 1256 TRACE_COUNTER1("media", "AVDA::PendingBitstreamBufferCount", 0); |
| 1246 bitstreams_notified_in_advance_.clear(); | 1257 bitstreams_notified_in_advance_.clear(); |
| 1247 | 1258 |
| 1248 picture_buffer_manager_.ReleaseCodecBuffers(output_picture_buffers_); | 1259 picture_buffer_manager_.ReleaseCodecBuffers(output_picture_buffers_); |
| 1249 StartCodecDrain(DRAIN_FOR_RESET); | 1260 StartCodecDrain(DRAIN_FOR_RESET); |
| 1250 } | 1261 } |
| 1251 | 1262 |
| 1252 void AndroidVideoDecodeAccelerator::SetSurface( | 1263 void AndroidVideoDecodeAccelerator::SetOverlayInfo( |
| 1253 int32_t surface_id, | 1264 const OverlayInfo& overlay_info) { |
| 1254 const base::Optional<base::UnguessableToken>& routing_token) { | |
| 1255 DVLOG(1) << __func__; | 1265 DVLOG(1) << __func__; |
| 1256 DCHECK(thread_checker_.CalledOnValidThread()); | 1266 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1257 | 1267 |
| 1258 // It's possible that we'll receive a SetSurface before initializing the | 1268 // It's possible that we'll receive a SetSurface before initializing the |
| 1259 // surface chooser. For example, if we defer surface creation, then we'll | 1269 // surface chooser. For example, if we defer surface creation, then we'll |
| 1260 // signal success to WMPI before initializing it. WMPI is free to change the | 1270 // signal success to WMPI before initializing it. WMPI is free to change the |
| 1261 // surface. In this case, just pretend that |surface_id| is the initial one. | 1271 // surface. In this case, just pretend that |surface_id| is the initial one. |
| 1262 if (state_ == BEFORE_OVERLAY_INIT) { | 1272 if (state_ == BEFORE_OVERLAY_INIT) { |
| 1263 config_.surface_id = surface_id; | 1273 config_.overlay_info |= overlay_info; |
| 1264 config_.overlay_routing_token = routing_token; | |
| 1265 return; | 1274 return; |
| 1266 } | 1275 } |
| 1267 | 1276 |
| 1277 int32_t surface_id = SurfaceManager::kNoSurfaceID; | |
| 1278 OverlayInfo::RoutingToken routing_token; | |
| 1279 | |
| 1280 if (overlay_info.surface_id) | |
| 1281 surface_id = *overlay_info.surface_id; | |
| 1282 else if (overlay_info.routing_token) | |
| 1283 routing_token = *overlay_info.routing_token; | |
| 1284 else | |
| 1285 return; | |
| 1286 | |
| 1268 AndroidOverlayFactoryCB factory; | 1287 AndroidOverlayFactoryCB factory; |
| 1269 if (routing_token && overlay_factory_cb_) { | 1288 if (routing_token && overlay_factory_cb_) { |
| 1270 factory = base::Bind(overlay_factory_cb_, *routing_token); | 1289 factory = base::Bind(overlay_factory_cb_, *routing_token); |
| 1271 } else if (surface_id != SurfaceManager::kNoSurfaceID) { | 1290 } else if (surface_id != SurfaceManager::kNoSurfaceID) { |
| 1272 factory = base::Bind(&CreateContentVideoViewOverlay, surface_id); | 1291 factory = base::Bind(&CreateContentVideoViewOverlay, surface_id); |
| 1273 } | 1292 } |
| 1274 | 1293 |
| 1275 surface_chooser_->ReplaceOverlayFactory(std::move(factory)); | 1294 surface_chooser_->ReplaceOverlayFactory(std::move(factory)); |
| 1276 } | 1295 } |
| 1277 | 1296 |
| (...skipping 414 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1692 codec_allocator_->ReleaseMediaCodec(std::move(media_codec_), | 1711 codec_allocator_->ReleaseMediaCodec(std::move(media_codec_), |
| 1693 codec_config_->surface_bundle); | 1712 codec_config_->surface_bundle); |
| 1694 } | 1713 } |
| 1695 | 1714 |
| 1696 void AndroidVideoDecodeAccelerator::ReleaseCodecAndBundle() { | 1715 void AndroidVideoDecodeAccelerator::ReleaseCodecAndBundle() { |
| 1697 ReleaseCodec(); | 1716 ReleaseCodec(); |
| 1698 codec_config_->surface_bundle = nullptr; | 1717 codec_config_->surface_bundle = nullptr; |
| 1699 } | 1718 } |
| 1700 | 1719 |
| 1701 } // namespace media | 1720 } // namespace media |
| OLD | NEW |