[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 1 | // Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
[email protected] | cc3cfaa | 2013-03-18 09:05:52 | [diff] [blame] | 5 | #include "cc/layers/video_frame_provider_client_impl.h" |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 6 | |
primiano | c06e238 | 2015-01-28 04:21:49 | [diff] [blame] | 7 | #include "base/trace_event/trace_event.h" |
[email protected] | 681ccff | 2013-03-18 06:13:52 | [diff] [blame] | 8 | #include "cc/base/math_util.h" |
[email protected] | cc3cfaa | 2013-03-18 09:05:52 | [diff] [blame] | 9 | #include "cc/layers/video_layer_impl.h" |
[email protected] | b7cfc63 | 2013-04-10 04:44:49 | [diff] [blame] | 10 | #include "media/base/video_frame.h" |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 11 | |
| 12 | namespace cc { |
| 13 | |
| 14 | // static |
| 15 | scoped_refptr<VideoFrameProviderClientImpl> |
sunnyps | 7d073dc | 2015-04-16 23:29:12 | [diff] [blame] | 16 | VideoFrameProviderClientImpl::Create(VideoFrameProvider* provider, |
| 17 | VideoFrameControllerClient* client) { |
kylechar | 973a041 | 2017-09-26 18:40:29 | [diff] [blame] | 18 | return base::WrapRefCounted( |
| 19 | new VideoFrameProviderClientImpl(provider, client)); |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 20 | } |
| 21 | |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 22 | VideoFrameProviderClientImpl::VideoFrameProviderClientImpl( |
sunnyps | 7d073dc | 2015-04-16 23:29:12 | [diff] [blame] | 23 | VideoFrameProvider* provider, |
| 24 | VideoFrameControllerClient* client) |
| 25 | : provider_(provider), |
| 26 | client_(client), |
| 27 | active_video_layer_(nullptr), |
dalecurtis | f28f0e5 | 2015-05-01 07:08:25 | [diff] [blame] | 28 | stopped_(false), |
dalecurtis | e8024c4 | 2015-05-29 21:22:35 | [diff] [blame] | 29 | rendering_(false), |
| 30 | needs_put_current_frame_(false) { |
dalecurtis | e1edb31 | 2016-06-22 02:33:21 | [diff] [blame] | 31 | // |provider_| may be null if destructed before the layer. |
| 32 | if (provider_) { |
| 33 | // This only happens during a commit on the compositor thread while the main |
| 34 | // thread is blocked. That makes this a thread-safe call to set the video |
| 35 | // frame provider client that does not require a lock. The same is true of |
| 36 | // the call to Stop(). |
| 37 | provider_->SetVideoFrameProviderClient(this); |
| 38 | } |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 39 | } |
| 40 | |
sunnyps | a528172 | 2015-03-27 02:39:48 | [diff] [blame] | 41 | VideoFrameProviderClientImpl::~VideoFrameProviderClientImpl() { |
| 42 | DCHECK(thread_checker_.CalledOnValidThread()); |
| 43 | DCHECK(stopped_); |
| 44 | } |
| 45 | |
| 46 | VideoLayerImpl* VideoFrameProviderClientImpl::ActiveVideoLayer() const { |
| 47 | DCHECK(thread_checker_.CalledOnValidThread()); |
| 48 | return active_video_layer_; |
| 49 | } |
| 50 | |
dongseong.hwang | ee88f0aa | 2015-02-10 19:39:59 | [diff] [blame] | 51 | void VideoFrameProviderClientImpl::SetActiveVideoLayer( |
| 52 | VideoLayerImpl* video_layer) { |
| 53 | DCHECK(thread_checker_.CalledOnValidThread()); |
| 54 | DCHECK(video_layer); |
| 55 | active_video_layer_ = video_layer; |
| 56 | } |
| 57 | |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 58 | void VideoFrameProviderClientImpl::Stop() { |
dongseong.hwang | ee88f0aa | 2015-02-10 19:39:59 | [diff] [blame] | 59 | DCHECK(thread_checker_.CalledOnValidThread()); |
qiangchen | 867223f | 2017-02-14 17:47:12 | [diff] [blame] | 60 | active_video_layer_ = nullptr; |
sunnyps | a528172 | 2015-03-27 02:39:48 | [diff] [blame] | 61 | // It's called when the main thread is blocked, so lock isn't needed. |
| 62 | if (provider_) { |
| 63 | provider_->SetVideoFrameProviderClient(nullptr); |
| 64 | provider_ = nullptr; |
| 65 | } |
dalecurtis | f28f0e5 | 2015-05-01 07:08:25 | [diff] [blame] | 66 | if (rendering_) |
| 67 | StopRendering(); |
sunnyps | a528172 | 2015-03-27 02:39:48 | [diff] [blame] | 68 | stopped_ = true; |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 69 | } |
| 70 | |
sunnyps | a528172 | 2015-03-27 02:39:48 | [diff] [blame] | 71 | bool VideoFrameProviderClientImpl::Stopped() const { |
dongseong.hwang | ee88f0aa | 2015-02-10 19:39:59 | [diff] [blame] | 72 | DCHECK(thread_checker_.CalledOnValidThread()); |
sunnyps | a528172 | 2015-03-27 02:39:48 | [diff] [blame] | 73 | return stopped_; |
dongseong.hwang | ee88f0aa | 2015-02-10 19:39:59 | [diff] [blame] | 74 | } |
| 75 | |
[email protected] | af2cd32 | 2013-03-22 16:56:18 | [diff] [blame] | 76 | scoped_refptr<media::VideoFrame> |
| 77 | VideoFrameProviderClientImpl::AcquireLockAndCurrentFrame() { |
dongseong.hwang | ee88f0aa | 2015-02-10 19:39:59 | [diff] [blame] | 78 | DCHECK(thread_checker_.CalledOnValidThread()); |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 79 | provider_lock_.Acquire(); // Balanced by call to ReleaseLock(). |
| 80 | if (!provider_) |
kulkarni.a | 4015690f1 | 2014-10-10 13:50:06 | [diff] [blame] | 81 | return nullptr; |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 82 | |
| 83 | return provider_->GetCurrentFrame(); |
| 84 | } |
| 85 | |
Bartosz Fabianowski | 85a82381 | 2015-04-16 10:27:51 | [diff] [blame] | 86 | void VideoFrameProviderClientImpl::PutCurrentFrame() { |
dongseong.hwang | ee88f0aa | 2015-02-10 19:39:59 | [diff] [blame] | 87 | DCHECK(thread_checker_.CalledOnValidThread()); |
Bartosz Fabianowski | 85a82381 | 2015-04-16 10:27:51 | [diff] [blame] | 88 | provider_->PutCurrentFrame(); |
dalecurtis | e8024c4 | 2015-05-29 21:22:35 | [diff] [blame] | 89 | needs_put_current_frame_ = false; |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 90 | } |
| 91 | |
| 92 | void VideoFrameProviderClientImpl::ReleaseLock() { |
dongseong.hwang | ee88f0aa | 2015-02-10 19:39:59 | [diff] [blame] | 93 | DCHECK(thread_checker_.CalledOnValidThread()); |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 94 | provider_lock_.Release(); |
| 95 | } |
| 96 | |
hendrikw | e19cc6a | 2015-05-18 23:14:14 | [diff] [blame] | 97 | bool VideoFrameProviderClientImpl::HasCurrentFrame() { |
| 98 | base::AutoLock locker(provider_lock_); |
| 99 | return provider_ && provider_->HasCurrentFrame(); |
| 100 | } |
| 101 | |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 102 | void VideoFrameProviderClientImpl::StopUsingProvider() { |
dalecurtis | 6d37d33 | 2015-06-16 20:26:37 | [diff] [blame] | 103 | { |
| 104 | // Block the provider from shutting down until this client is done |
| 105 | // using the frame. |
| 106 | base::AutoLock locker(provider_lock_); |
| 107 | provider_ = nullptr; |
| 108 | } |
dalecurtis | f28f0e5 | 2015-05-01 07:08:25 | [diff] [blame] | 109 | if (rendering_) |
| 110 | StopRendering(); |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 111 | } |
| 112 | |
Bartosz Fabianowski | 85a82381 | 2015-04-16 10:27:51 | [diff] [blame] | 113 | void VideoFrameProviderClientImpl::StartRendering() { |
dalecurtis | f28f0e5 | 2015-05-01 07:08:25 | [diff] [blame] | 114 | DCHECK(thread_checker_.CalledOnValidThread()); |
| 115 | TRACE_EVENT0("cc", "VideoFrameProviderClientImpl::StartRendering"); |
| 116 | DCHECK(!rendering_); |
| 117 | DCHECK(!stopped_); |
dalecurtis | f28f0e5 | 2015-05-01 07:08:25 | [diff] [blame] | 118 | rendering_ = true; |
sunnyps | c052ba99 | 2015-05-05 00:42:29 | [diff] [blame] | 119 | client_->AddVideoFrameController(this); |
Bartosz Fabianowski | 85a82381 | 2015-04-16 10:27:51 | [diff] [blame] | 120 | } |
| 121 | |
| 122 | void VideoFrameProviderClientImpl::StopRendering() { |
dalecurtis | f28f0e5 | 2015-05-01 07:08:25 | [diff] [blame] | 123 | DCHECK(thread_checker_.CalledOnValidThread()); |
| 124 | TRACE_EVENT0("cc", "VideoFrameProviderClientImpl::StopRendering"); |
| 125 | DCHECK(rendering_); |
| 126 | DCHECK(!stopped_); |
| 127 | client_->RemoveVideoFrameController(this); |
| 128 | rendering_ = false; |
qiangchen | 867223f | 2017-02-14 17:47:12 | [diff] [blame] | 129 | if (active_video_layer_) |
| 130 | active_video_layer_->SetNeedsRedraw(); |
Bartosz Fabianowski | 85a82381 | 2015-04-16 10:27:51 | [diff] [blame] | 131 | } |
| 132 | |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 133 | void VideoFrameProviderClientImpl::DidReceiveFrame() { |
[email protected] | 9469d78 | 2014-04-18 01:23:56 | [diff] [blame] | 134 | TRACE_EVENT1("cc", |
| 135 | "VideoFrameProviderClientImpl::DidReceiveFrame", |
| 136 | "active_video_layer", |
| 137 | !!active_video_layer_); |
dongseong.hwang | ee88f0aa | 2015-02-10 19:39:59 | [diff] [blame] | 138 | DCHECK(thread_checker_.CalledOnValidThread()); |
dalecurtis | e8024c4 | 2015-05-29 21:22:35 | [diff] [blame] | 139 | needs_put_current_frame_ = true; |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 140 | if (active_video_layer_) |
[email protected] | 4af49d54 | 2013-03-15 22:18:47 | [diff] [blame] | 141 | active_video_layer_->SetNeedsRedraw(); |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 142 | } |
| 143 | |
Fady Samuel | c296f5fb | 2017-07-21 04:02:19 | [diff] [blame] | 144 | void VideoFrameProviderClientImpl::OnBeginFrame( |
| 145 | const viz::BeginFrameArgs& args) { |
sunnyps | 7d073dc | 2015-04-16 23:29:12 | [diff] [blame] | 146 | DCHECK(thread_checker_.CalledOnValidThread()); |
dalecurtis | f28f0e5 | 2015-05-01 07:08:25 | [diff] [blame] | 147 | DCHECK(rendering_); |
| 148 | DCHECK(!stopped_); |
| 149 | |
| 150 | TRACE_EVENT0("cc", "VideoFrameProviderClientImpl::OnBeginFrame"); |
dalecurtis | 6d37d33 | 2015-06-16 20:26:37 | [diff] [blame] | 151 | { |
| 152 | base::AutoLock locker(provider_lock_); |
dalecurtis | f28f0e5 | 2015-05-01 07:08:25 | [diff] [blame] | 153 | |
dalecurtis | 6d37d33 | 2015-06-16 20:26:37 | [diff] [blame] | 154 | // We use frame_time + interval here because that is the estimated time at |
| 155 | // which a frame returned during this phase will end up being displayed. |
| 156 | if (!provider_ || |
| 157 | !provider_->UpdateCurrentFrame(args.frame_time + args.interval, |
| 158 | args.frame_time + 2 * args.interval)) { |
| 159 | return; |
| 160 | } |
dalecurtis | f28f0e5 | 2015-05-01 07:08:25 | [diff] [blame] | 161 | } |
| 162 | |
dalecurtis | 6d37d33 | 2015-06-16 20:26:37 | [diff] [blame] | 163 | // Warning: Do not hold |provider_lock_| while calling this function, it may |
| 164 | // lead to a reentrant call to HasCurrentFrame() above. |
dalecurtis | f28f0e5 | 2015-05-01 07:08:25 | [diff] [blame] | 165 | DidReceiveFrame(); |
sunnyps | 7d073dc | 2015-04-16 23:29:12 | [diff] [blame] | 166 | } |
| 167 | |
dalecurtis | e8024c4 | 2015-05-29 21:22:35 | [diff] [blame] | 168 | void VideoFrameProviderClientImpl::DidDrawFrame() { |
| 169 | DCHECK(thread_checker_.CalledOnValidThread()); |
| 170 | { |
| 171 | base::AutoLock locker(provider_lock_); |
| 172 | if (provider_ && needs_put_current_frame_) |
| 173 | provider_->PutCurrentFrame(); |
| 174 | } |
| 175 | needs_put_current_frame_ = false; |
| 176 | } |
| 177 | |
[email protected] | f14f516 | 2018-08-08 17:09:26 | [diff] [blame] | 178 | bool VideoFrameProviderClientImpl::IsDrivingFrameUpdates() const { |
| 179 | // We drive frame updates any time we're rendering, even if we're off-screen. |
| 180 | return rendering_; |
| 181 | } |
| 182 | |
[email protected] | 48871fc | 2013-01-23 07:36:51 | [diff] [blame] | 183 | } // namespace cc |