[Sync] Fix autofill tests to be autofill profile entities.
[chromium-blink-merge.git] / media / capture / thread_safe_capture_oracle.cc
blob5de1b3b6173eeac946b28f636ed27094b32c9efd
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
3 // found in the LICENSE file.
5 #include "media/capture/thread_safe_capture_oracle.h"
7 #include "base/basictypes.h"
8 #include "base/bind.h"
9 #include "base/logging.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/synchronization/lock.h"
12 #include "base/time/time.h"
13 #include "base/trace_event/trace_event.h"
14 #include "media/base/video_capture_types.h"
15 #include "media/base/video_frame.h"
16 #include "media/base/video_frame_metadata.h"
17 #include "media/base/video_util.h"
18 #include "ui/gfx/geometry/rect.h"
20 namespace media {
22 ThreadSafeCaptureOracle::ThreadSafeCaptureOracle(
23 scoped_ptr<VideoCaptureDevice::Client> client,
24 const VideoCaptureParams& params)
25 : client_(client.Pass()),
26 oracle_(base::TimeDelta::FromMicroseconds(
27 static_cast<int64>(1000000.0 / params.requested_format.frame_rate +
28 0.5 /* to round to nearest int */))),
29 params_(params),
30 resolution_chooser_(params.requested_format.frame_size,
31 params.resolution_change_policy) {}
33 ThreadSafeCaptureOracle::~ThreadSafeCaptureOracle() {}
35 bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture(
36 VideoCaptureOracle::Event event,
37 const gfx::Rect& damage_rect,
38 base::TimeTicks event_time,
39 scoped_refptr<VideoFrame>* storage,
40 CaptureFrameCallback* callback) {
41 // Grab the current time before waiting to acquire the |lock_|.
42 const base::TimeTicks capture_begin_time = base::TimeTicks::Now();
44 base::AutoLock guard(lock_);
46 if (!client_)
47 return false; // Capture is stopped.
49 const gfx::Size visible_size = resolution_chooser_.capture_size();
50 // Always round up the coded size to multiple of 16 pixels.
51 // See http://crbug.com/402151.
52 const gfx::Size coded_size((visible_size.width() + 15) & ~15,
53 (visible_size.height() + 15) & ~15);
55 scoped_ptr<VideoCaptureDevice::Client::Buffer> output_buffer(
56 client_->ReserveOutputBuffer(params_.requested_format.pixel_format,
57 coded_size));
58 // TODO(miu): Use current buffer pool utilization to drive automatic video
59 // resolution changes. http://crbug.com/156767.
60 VLOG(2) << "Current buffer pool utilization is "
61 << (client_->GetBufferPoolUtilization() * 100.0) << '%';
63 const bool should_capture =
64 oracle_.ObserveEventAndDecideCapture(event, damage_rect, event_time);
66 const char* event_name =
67 (event == VideoCaptureOracle::kTimerPoll ? "poll" :
68 (event == VideoCaptureOracle::kCompositorUpdate ? "gpu" :
69 "unknown"));
71 // Consider the various reasons not to initiate a capture.
72 if (should_capture && !output_buffer.get()) {
73 TRACE_EVENT_INSTANT1("gpu.capture",
74 "PipelineLimited",
75 TRACE_EVENT_SCOPE_THREAD,
76 "trigger",
77 event_name);
78 return false;
79 } else if (!should_capture && output_buffer.get()) {
80 if (event == VideoCaptureOracle::kCompositorUpdate) {
81 // This is a normal and acceptable way to drop a frame. We've hit our
82 // capture rate limit: for example, the content is animating at 60fps but
83 // we're capturing at 30fps.
84 TRACE_EVENT_INSTANT1("gpu.capture", "FpsRateLimited",
85 TRACE_EVENT_SCOPE_THREAD,
86 "trigger", event_name);
88 return false;
89 } else if (!should_capture && !output_buffer.get()) {
90 // We decided not to capture, but we wouldn't have been able to if we wanted
91 // to because no output buffer was available.
92 TRACE_EVENT_INSTANT1("gpu.capture", "NearlyPipelineLimited",
93 TRACE_EVENT_SCOPE_THREAD,
94 "trigger", event_name);
95 return false;
97 int frame_number = oracle_.RecordCapture();
98 TRACE_EVENT_ASYNC_BEGIN2("gpu.capture", "Capture", output_buffer.get(),
99 "frame_number", frame_number,
100 "trigger", event_name);
101 // NATIVE_TEXTURE frames wrap a texture mailbox, which we don't have at the
102 // moment. We do not construct those frames.
103 if (params_.requested_format.pixel_format != PIXEL_FORMAT_TEXTURE) {
104 *storage = VideoFrame::WrapExternalData(
105 VideoFrame::I420,
106 coded_size,
107 gfx::Rect(visible_size),
108 visible_size,
109 static_cast<uint8*>(output_buffer->data()),
110 output_buffer->size(),
111 base::TimeDelta());
112 DCHECK(*storage);
114 *callback = base::Bind(&ThreadSafeCaptureOracle::DidCaptureFrame,
115 this,
116 frame_number,
117 base::Passed(&output_buffer),
118 capture_begin_time,
119 oracle_.estimated_frame_duration());
120 return true;
123 gfx::Size ThreadSafeCaptureOracle::GetCaptureSize() const {
124 base::AutoLock guard(lock_);
125 return resolution_chooser_.capture_size();
128 void ThreadSafeCaptureOracle::UpdateCaptureSize(const gfx::Size& source_size) {
129 base::AutoLock guard(lock_);
130 resolution_chooser_.SetSourceSize(source_size);
131 VLOG(1) << "Source size changed to " << source_size.ToString()
132 << " --> Capture size is now "
133 << resolution_chooser_.capture_size().ToString();
136 void ThreadSafeCaptureOracle::Stop() {
137 base::AutoLock guard(lock_);
138 client_.reset();
141 void ThreadSafeCaptureOracle::ReportError(const std::string& reason) {
142 base::AutoLock guard(lock_);
143 if (client_)
144 client_->OnError(reason);
147 void ThreadSafeCaptureOracle::DidCaptureFrame(
148 int frame_number,
149 scoped_ptr<VideoCaptureDevice::Client::Buffer> buffer,
150 base::TimeTicks capture_begin_time,
151 base::TimeDelta estimated_frame_duration,
152 const scoped_refptr<VideoFrame>& frame,
153 base::TimeTicks timestamp,
154 bool success) {
155 base::AutoLock guard(lock_);
156 TRACE_EVENT_ASYNC_END2("gpu.capture", "Capture", buffer.get(),
157 "success", success,
158 "timestamp", timestamp.ToInternalValue());
160 if (oracle_.CompleteCapture(frame_number, success, &timestamp)) {
161 TRACE_EVENT_INSTANT0("gpu.capture", "CaptureSucceeded",
162 TRACE_EVENT_SCOPE_THREAD);
164 if (!client_)
165 return; // Capture is stopped.
167 frame->metadata()->SetDouble(VideoFrameMetadata::FRAME_RATE,
168 params_.requested_format.frame_rate);
169 frame->metadata()->SetTimeTicks(
170 VideoFrameMetadata::CAPTURE_BEGIN_TIME, capture_begin_time);
171 frame->metadata()->SetTimeTicks(
172 VideoFrameMetadata::CAPTURE_END_TIME, base::TimeTicks::Now());
173 frame->metadata()->SetTimeDelta(VideoFrameMetadata::FRAME_DURATION,
174 estimated_frame_duration);
176 frame->AddDestructionObserver(base::Bind(
177 &ThreadSafeCaptureOracle::DidConsumeFrame,
178 this,
179 frame_number,
180 frame->metadata()));
182 client_->OnIncomingCapturedVideoFrame(buffer.Pass(), frame, timestamp);
186 void ThreadSafeCaptureOracle::DidConsumeFrame(
187 int frame_number,
188 const media::VideoFrameMetadata* metadata) {
189 // Note: This function may be called on any thread by the VideoFrame
190 // destructor. |metadata| is still valid for read-access at this point.
191 double utilization = -1.0;
192 if (metadata->GetDouble(media::VideoFrameMetadata::RESOURCE_UTILIZATION,
193 &utilization) &&
194 utilization >= 0.0) {
195 VLOG(2) << "Consumer resource utilization for frame " << frame_number
196 << ": " << utilization;
199 // TODO(miu): Use |utilization| to drive automatic video resolution changes.
200 // http://crbug.com/156767.
203 } // namespace media