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

Side by Side Diff: media/capture/content/thread_safe_capture_oracle.cc

Issue 1864813002: Tab/Desktop Capture: Use requests instead of timer-based refreshing. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@video_refresh_from_sinks
Patch Set: Addressed comments from PS2, and sampling decision logic change w.r.t. recent animation. Created 4 years, 8 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
OLDNEW
1 // Copyright 2014 The Chromium Authors. All rights reserved. 1 // Copyright 2014 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/capture/content/thread_safe_capture_oracle.h" 5 #include "media/capture/content/thread_safe_capture_oracle.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <utility> 8 #include <utility>
9 9
10 #include "base/bind.h" 10 #include "base/bind.h"
11 #include "base/bits.h" 11 #include "base/bits.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h" 13 #include "base/memory/scoped_ptr.h"
14 #include "base/numerics/safe_conversions.h"
14 #include "base/synchronization/lock.h" 15 #include "base/synchronization/lock.h"
15 #include "base/time/time.h" 16 #include "base/time/time.h"
16 #include "base/trace_event/trace_event.h" 17 #include "base/trace_event/trace_event.h"
17 #include "media/base/video_capture_types.h" 18 #include "media/base/video_capture_types.h"
18 #include "media/base/video_frame.h" 19 #include "media/base/video_frame.h"
19 #include "media/base/video_frame_metadata.h" 20 #include "media/base/video_frame_metadata.h"
20 #include "media/base/video_util.h" 21 #include "media/base/video_util.h"
21 #include "ui/gfx/geometry/rect.h" 22 #include "ui/gfx/geometry/rect.h"
22 23
23 namespace media { 24 namespace media {
(...skipping 26 matching lines...) Expand all
50 51
51 bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture( 52 bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture(
52 VideoCaptureOracle::Event event, 53 VideoCaptureOracle::Event event,
53 const gfx::Rect& damage_rect, 54 const gfx::Rect& damage_rect,
54 base::TimeTicks event_time, 55 base::TimeTicks event_time,
55 scoped_refptr<VideoFrame>* storage, 56 scoped_refptr<VideoFrame>* storage,
56 CaptureFrameCallback* callback) { 57 CaptureFrameCallback* callback) {
57 // Grab the current time before waiting to acquire the |lock_|. 58 // Grab the current time before waiting to acquire the |lock_|.
58 const base::TimeTicks capture_begin_time = base::TimeTicks::Now(); 59 const base::TimeTicks capture_begin_time = base::TimeTicks::Now();
59 60
60 base::AutoLock guard(lock_); 61 gfx::Size visible_size;
62 gfx::Size coded_size;
63 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> output_buffer;
64 double attenuated_utilization;
65 int frame_number;
66 base::TimeDelta estimated_frame_duration;
67 {
68 base::AutoLock guard(lock_);
61 69
62 if (!client_) 70 if (!client_)
63 return false; // Capture is stopped. 71 return false; // Capture is stopped.
64 72
65 const bool should_capture = 73 if (!oracle_.ObserveEventAndDecideCapture(event, damage_rect, event_time)) {
66 oracle_.ObserveEventAndDecideCapture(event, damage_rect, event_time);
67 const gfx::Size visible_size = oracle_.capture_size();
68 // TODO(miu): Clients should request exact padding, instead of this
69 // memory-wasting hack to make frames that are compatible with all HW
70 // encoders. http://crbug.com/555911
71 const gfx::Size coded_size(base::bits::Align(visible_size.width(), 16),
72 base::bits::Align(visible_size.height(), 16));
73
74 scoped_ptr<media::VideoCaptureDevice::Client::Buffer> output_buffer(
75 client_->ReserveOutputBuffer(coded_size,
76 params_.requested_format.pixel_format,
77 params_.requested_format.pixel_storage));
78 // Get the current buffer pool utilization and attenuate it: The utilization
79 // reported to the oracle is in terms of a maximum sustainable amount (not the
80 // absolute maximum).
81 const double attenuated_utilization =
82 client_->GetBufferPoolUtilization() *
83 (100.0 / kTargetMaxPoolUtilizationPercent);
84
85 const char* event_name =
86 (event == VideoCaptureOracle::kTimerPoll
87 ? "poll"
88 : (event == VideoCaptureOracle::kCompositorUpdate ? "gpu"
89 : "unknown"));
90
91 // Consider the various reasons not to initiate a capture.
92 if (should_capture && !output_buffer.get()) {
93 TRACE_EVENT_INSTANT1("gpu.capture", "PipelineLimited",
94 TRACE_EVENT_SCOPE_THREAD, "trigger", event_name);
95 oracle_.RecordWillNotCapture(attenuated_utilization);
96 return false;
97 } else if (!should_capture && output_buffer.get()) {
98 if (event == VideoCaptureOracle::kCompositorUpdate) {
99 // This is a normal and acceptable way to drop a frame. We've hit our 74 // This is a normal and acceptable way to drop a frame. We've hit our
100 // capture rate limit: for example, the content is animating at 60fps but 75 // capture rate limit: for example, the content is animating at 60fps but
101 // we're capturing at 30fps. 76 // we're capturing at 30fps.
102 TRACE_EVENT_INSTANT1("gpu.capture", "FpsRateLimited", 77 TRACE_EVENT_INSTANT1("gpu.capture", "FpsRateLimited",
103 TRACE_EVENT_SCOPE_THREAD, "trigger", event_name); 78 TRACE_EVENT_SCOPE_THREAD, "trigger",
79 VideoCaptureOracle::EventAsString(event));
80 return false;
104 } 81 }
105 return false; 82
106 } else if (!should_capture && !output_buffer.get()) { 83 visible_size = oracle_.capture_size();
107 // We decided not to capture, but we wouldn't have been able to if we wanted 84 // TODO(miu): Clients should request exact padding, instead of this
108 // to because no output buffer was available. 85 // memory-wasting hack to make frames that are compatible with all HW
109 TRACE_EVENT_INSTANT1("gpu.capture", "NearlyPipelineLimited", 86 // encoders. http://crbug.com/555911
110 TRACE_EVENT_SCOPE_THREAD, "trigger", event_name); 87 coded_size.SetSize(base::bits::Align(visible_size.width(), 16),
111 return false; 88 base::bits::Align(visible_size.height(), 16));
89
90 if (event == VideoCaptureOracle::kPassiveRefreshRequest) {
91 output_buffer = client_->ResurrectLastOutputBuffer(
92 coded_size, params_.requested_format.pixel_format,
93 params_.requested_format.pixel_storage);
94 if (!output_buffer) {
95 TRACE_EVENT_INSTANT0("gpu.capture", "ResurrectionFailed",
96 TRACE_EVENT_SCOPE_THREAD);
97 return false;
98 }
99 } else {
100 output_buffer = client_->ReserveOutputBuffer(
101 coded_size, params_.requested_format.pixel_format,
102 params_.requested_format.pixel_storage);
103 }
104
105 // Get the current buffer pool utilization and attenuate it: The utilization
106 // reported to the oracle is in terms of a maximum sustainable amount (not
107 // the absolute maximum).
108 attenuated_utilization = client_->GetBufferPoolUtilization() *
109 (100.0 / kTargetMaxPoolUtilizationPercent);
110
111 if (!output_buffer) {
112 TRACE_EVENT_INSTANT2(
113 "gpu.capture", "PipelineLimited", TRACE_EVENT_SCOPE_THREAD, "trigger",
114 VideoCaptureOracle::EventAsString(event), "atten_util_percent",
115 base::saturated_cast<int>(attenuated_utilization * 100.0 + 0.5));
116 oracle_.RecordWillNotCapture(attenuated_utilization);
117 return false;
118 }
119
120 frame_number = oracle_.RecordCapture(attenuated_utilization);
121 estimated_frame_duration = oracle_.estimated_frame_duration();
122 } // End of critical section.
123
124 if (attenuated_utilization >= 1.0) {
125 TRACE_EVENT_INSTANT2(
126 "gpu.capture", "NearlyPipelineLimited", TRACE_EVENT_SCOPE_THREAD,
127 "trigger", VideoCaptureOracle::EventAsString(event),
128 "atten_util_percent",
129 base::saturated_cast<int>(attenuated_utilization * 100.0 + 0.5));
112 } 130 }
113 131
114 const int frame_number = oracle_.RecordCapture(attenuated_utilization);
115 TRACE_EVENT_ASYNC_BEGIN2("gpu.capture", "Capture", output_buffer.get(), 132 TRACE_EVENT_ASYNC_BEGIN2("gpu.capture", "Capture", output_buffer.get(),
116 "frame_number", frame_number, "trigger", event_name); 133 "frame_number", frame_number, "trigger",
134 VideoCaptureOracle::EventAsString(event));
117 135
118 DCHECK_EQ(media::PIXEL_STORAGE_CPU, params_.requested_format.pixel_storage); 136 DCHECK_EQ(media::PIXEL_STORAGE_CPU, params_.requested_format.pixel_storage);
119 *storage = VideoFrame::WrapExternalSharedMemory( 137 *storage = VideoFrame::WrapExternalSharedMemory(
120 params_.requested_format.pixel_format, coded_size, 138 params_.requested_format.pixel_format, coded_size,
121 gfx::Rect(visible_size), visible_size, 139 gfx::Rect(visible_size), visible_size,
122 static_cast<uint8_t*>(output_buffer->data()), 140 static_cast<uint8_t*>(output_buffer->data()),
123 output_buffer->mapped_size(), base::SharedMemory::NULLHandle(), 0u, 141 output_buffer->mapped_size(), base::SharedMemory::NULLHandle(), 0u,
124 base::TimeDelta()); 142 base::TimeDelta());
125 if (!(*storage)) 143 if (!(*storage))
126 return false; 144 return false;
127 *callback = 145 *callback = base::Bind(&ThreadSafeCaptureOracle::DidCaptureFrame, this,
128 base::Bind(&ThreadSafeCaptureOracle::DidCaptureFrame, this, frame_number, 146 frame_number, base::Passed(&output_buffer),
129 base::Passed(&output_buffer), capture_begin_time, 147 capture_begin_time, estimated_frame_duration);
130 oracle_.estimated_frame_duration()); 148
131 return true; 149 return true;
132 } 150 }
133 151
152 bool ThreadSafeCaptureOracle::AttemptPassiveRefresh() {
153 const base::TimeTicks refresh_time = base::TimeTicks::Now();
154
155 scoped_refptr<VideoFrame> frame;
156 CaptureFrameCallback capture_callback;
157 if (!ObserveEventAndDecideCapture(VideoCaptureOracle::kPassiveRefreshRequest,
158 gfx::Rect(), refresh_time, &frame,
159 &capture_callback)) {
160 return false;
161 }
162
Irfan 2016/04/06 23:00:21 probably add a comment explaining why the capture
163 capture_callback.Run(frame, refresh_time, true);
164 return true;
165 }
166
134 gfx::Size ThreadSafeCaptureOracle::GetCaptureSize() const { 167 gfx::Size ThreadSafeCaptureOracle::GetCaptureSize() const {
135 base::AutoLock guard(lock_); 168 base::AutoLock guard(lock_);
136 return oracle_.capture_size(); 169 return oracle_.capture_size();
137 } 170 }
138 171
139 void ThreadSafeCaptureOracle::UpdateCaptureSize(const gfx::Size& source_size) { 172 void ThreadSafeCaptureOracle::UpdateCaptureSize(const gfx::Size& source_size) {
140 base::AutoLock guard(lock_); 173 base::AutoLock guard(lock_);
141 VLOG(1) << "Source size changed to " << source_size.ToString(); 174 VLOG(1) << "Source size changed to " << source_size.ToString();
142 oracle_.SetSourceSize(source_size); 175 oracle_.SetSourceSize(source_size);
143 } 176 }
(...skipping 12 matching lines...) Expand all
156 } 189 }
157 190
158 void ThreadSafeCaptureOracle::DidCaptureFrame( 191 void ThreadSafeCaptureOracle::DidCaptureFrame(
159 int frame_number, 192 int frame_number,
160 scoped_ptr<VideoCaptureDevice::Client::Buffer> buffer, 193 scoped_ptr<VideoCaptureDevice::Client::Buffer> buffer,
161 base::TimeTicks capture_begin_time, 194 base::TimeTicks capture_begin_time,
162 base::TimeDelta estimated_frame_duration, 195 base::TimeDelta estimated_frame_duration,
163 const scoped_refptr<VideoFrame>& frame, 196 const scoped_refptr<VideoFrame>& frame,
164 base::TimeTicks timestamp, 197 base::TimeTicks timestamp,
165 bool success) { 198 bool success) {
166 base::AutoLock guard(lock_);
167 TRACE_EVENT_ASYNC_END2("gpu.capture", "Capture", buffer.get(), "success", 199 TRACE_EVENT_ASYNC_END2("gpu.capture", "Capture", buffer.get(), "success",
168 success, "timestamp", timestamp.ToInternalValue()); 200 success, "timestamp", timestamp.ToInternalValue());
169 201
202 base::AutoLock guard(lock_);
203
170 if (oracle_.CompleteCapture(frame_number, success, &timestamp)) { 204 if (oracle_.CompleteCapture(frame_number, success, &timestamp)) {
171 TRACE_EVENT_INSTANT0("gpu.capture", "CaptureSucceeded", 205 TRACE_EVENT_INSTANT0("gpu.capture", "CaptureSucceeded",
172 TRACE_EVENT_SCOPE_THREAD); 206 TRACE_EVENT_SCOPE_THREAD);
173 207
174 if (!client_) 208 if (!client_)
175 return; // Capture is stopped. 209 return; // Capture is stopped.
176 210
177 frame->metadata()->SetDouble(VideoFrameMetadata::FRAME_RATE, 211 frame->metadata()->SetDouble(VideoFrameMetadata::FRAME_RATE,
178 params_.requested_format.frame_rate); 212 params_.requested_format.frame_rate);
179 frame->metadata()->SetTimeTicks(VideoFrameMetadata::CAPTURE_BEGIN_TIME, 213 frame->metadata()->SetTimeTicks(VideoFrameMetadata::CAPTURE_BEGIN_TIME,
(...skipping 18 matching lines...) Expand all
198 // destructor. |metadata| is still valid for read-access at this point. 232 // destructor. |metadata| is still valid for read-access at this point.
199 double utilization = -1.0; 233 double utilization = -1.0;
200 if (metadata->GetDouble(media::VideoFrameMetadata::RESOURCE_UTILIZATION, 234 if (metadata->GetDouble(media::VideoFrameMetadata::RESOURCE_UTILIZATION,
201 &utilization)) { 235 &utilization)) {
202 base::AutoLock guard(lock_); 236 base::AutoLock guard(lock_);
203 oracle_.RecordConsumerFeedback(frame_number, utilization); 237 oracle_.RecordConsumerFeedback(frame_number, utilization);
204 } 238 }
205 } 239 }
206 240
207 } // namespace media 241 } // namespace media
OLDNEW
« no previous file with comments | « media/capture/content/thread_safe_capture_oracle.h ('k') | media/capture/content/video_capture_oracle.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698