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

Side by Side Diff: content/browser/media/capture/content_video_capture_device_core.cc

Issue 258663003: Use texture-backed VideoFrame pipeline for Aura desktop capturing. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased at trunk (r267290 changed ReleaseMailboxCB). Created 6 years, 7 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 | Annotate | Revision Log
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 "content/browser/media/capture/content_video_capture_device_core.h" 5 #include "content/browser/media/capture/content_video_capture_device_core.h"
6 6
7 #include "base/basictypes.h" 7 #include "base/basictypes.h"
8 #include "base/bind.h" 8 #include "base/bind.h"
9 #include "base/callback_forward.h" 9 #include "base/callback_forward.h"
10 #include "base/callback_helpers.h" 10 #include "base/callback_helpers.h"
(...skipping 30 matching lines...) Expand all
41 } // namespace 41 } // namespace
42 42
43 ThreadSafeCaptureOracle::ThreadSafeCaptureOracle( 43 ThreadSafeCaptureOracle::ThreadSafeCaptureOracle(
44 scoped_ptr<media::VideoCaptureDevice::Client> client, 44 scoped_ptr<media::VideoCaptureDevice::Client> client,
45 scoped_ptr<VideoCaptureOracle> oracle, 45 scoped_ptr<VideoCaptureOracle> oracle,
46 const media::VideoCaptureParams& params) 46 const media::VideoCaptureParams& params)
47 : client_(client.Pass()), 47 : client_(client.Pass()),
48 oracle_(oracle.Pass()), 48 oracle_(oracle.Pass()),
49 params_(params), 49 params_(params),
50 capture_size_updated_(false) { 50 capture_size_updated_(false) {
51 // Frame dimensions must each be an even integer since the client wants (or 51 switch (params_.requested_format.pixel_format) {
52 // will convert to) YUV420. 52 case media::PIXEL_FORMAT_I420:
53 capture_size_ = gfx::Size( 53 video_frame_format_ = media::VideoFrame::I420;
54 MakeEven(params.requested_format.frame_size.width()), 54 break;
55 MakeEven(params.requested_format.frame_size.height())); 55 case media::PIXEL_FORMAT_TEXTURE:
56 frame_rate_ = params.requested_format.frame_rate; 56 video_frame_format_ = media::VideoFrame::NATIVE_TEXTURE;
57 break;
58 default:
59 LOG(FATAL) << "Unexpected pixel_format "
60 << params_.requested_format.pixel_format;
61 }
57 } 62 }
58 63
59 ThreadSafeCaptureOracle::~ThreadSafeCaptureOracle() {} 64 ThreadSafeCaptureOracle::~ThreadSafeCaptureOracle() {}
60 65
61 bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture( 66 bool ThreadSafeCaptureOracle::ObserveEventAndDecideCapture(
62 VideoCaptureOracle::Event event, 67 VideoCaptureOracle::Event event,
63 base::TimeTicks event_time, 68 base::TimeTicks event_time,
64 scoped_refptr<media::VideoFrame>* storage, 69 scoped_refptr<media::VideoFrame>* storage,
65 CaptureFrameCallback* callback) { 70 CaptureFrameCallback* callback) {
66 base::AutoLock guard(lock_); 71 base::AutoLock guard(lock_);
67 72
68 if (!client_) 73 if (!client_)
69 return false; // Capture is stopped. 74 return false; // Capture is stopped.
70 75
71 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> output_buffer = 76 scoped_refptr<media::VideoCaptureDevice::Client::Buffer> output_buffer =
72 client_->ReserveOutputBuffer(media::VideoFrame::I420, capture_size_); 77 client_->ReserveOutputBuffer(video_frame_format_,
78 params_.requested_format.frame_size);
73 const bool should_capture = 79 const bool should_capture =
74 oracle_->ObserveEventAndDecideCapture(event, event_time); 80 oracle_->ObserveEventAndDecideCapture(event, event_time);
75 const bool content_is_dirty = 81 const bool content_is_dirty =
76 (event == VideoCaptureOracle::kCompositorUpdate || 82 (event == VideoCaptureOracle::kCompositorUpdate ||
77 event == VideoCaptureOracle::kSoftwarePaint); 83 event == VideoCaptureOracle::kSoftwarePaint);
78 const char* event_name = 84 const char* event_name =
79 (event == VideoCaptureOracle::kTimerPoll ? "poll" : 85 (event == VideoCaptureOracle::kTimerPoll ? "poll" :
80 (event == VideoCaptureOracle::kCompositorUpdate ? "gpu" : 86 (event == VideoCaptureOracle::kCompositorUpdate ? "gpu" :
81 "paint")); 87 "paint"));
82 88
(...skipping 20 matching lines...) Expand all
103 // to because no output buffer was available. 109 // to because no output buffer was available.
104 TRACE_EVENT_INSTANT1("mirroring", "NearlyEncodeLimited", 110 TRACE_EVENT_INSTANT1("mirroring", "NearlyEncodeLimited",
105 TRACE_EVENT_SCOPE_THREAD, 111 TRACE_EVENT_SCOPE_THREAD,
106 "trigger", event_name); 112 "trigger", event_name);
107 return false; 113 return false;
108 } 114 }
109 int frame_number = oracle_->RecordCapture(); 115 int frame_number = oracle_->RecordCapture();
110 TRACE_EVENT_ASYNC_BEGIN2("mirroring", "Capture", output_buffer.get(), 116 TRACE_EVENT_ASYNC_BEGIN2("mirroring", "Capture", output_buffer.get(),
111 "frame_number", frame_number, 117 "frame_number", frame_number,
112 "trigger", event_name); 118 "trigger", event_name);
113 *storage = media::VideoFrame::WrapExternalPackedMemory( 119 // NATIVE_TEXTURE frames wrap a texture mailbox, which we don't have at the
114 media::VideoFrame::I420, 120 // moment. We do not construct those frames.
115 capture_size_, 121 if (video_frame_format_ != media::VideoFrame::NATIVE_TEXTURE) {
116 gfx::Rect(capture_size_), 122 *storage = media::VideoFrame::WrapExternalPackedMemory(
117 capture_size_, 123 video_frame_format_,
118 static_cast<uint8*>(output_buffer->data()), 124 params_.requested_format.frame_size,
119 output_buffer->size(), 125 gfx::Rect(params_.requested_format.frame_size),
120 base::SharedMemory::NULLHandle(), 126 params_.requested_format.frame_size,
121 base::TimeDelta(), 127 static_cast<uint8*>(output_buffer->data()),
122 base::Closure()); 128 output_buffer->size(),
129 base::SharedMemory::NULLHandle(),
130 base::TimeDelta(),
131 base::Closure());
132 }
123 *callback = base::Bind(&ThreadSafeCaptureOracle::DidCaptureFrame, 133 *callback = base::Bind(&ThreadSafeCaptureOracle::DidCaptureFrame,
124 this, 134 this,
125 output_buffer, 135 frame_number,
126 *storage, 136 output_buffer);
127 frame_number);
128 return true; 137 return true;
129 } 138 }
130 139
131 gfx::Size ThreadSafeCaptureOracle::GetCaptureSize() const { 140 gfx::Size ThreadSafeCaptureOracle::GetCaptureSize() const {
132 base::AutoLock guard(lock_); 141 base::AutoLock guard(lock_);
133 return capture_size_; 142 return params_.requested_format.frame_size;
134 } 143 }
135 144
136 void ThreadSafeCaptureOracle::UpdateCaptureSize(const gfx::Size& source_size) { 145 void ThreadSafeCaptureOracle::UpdateCaptureSize(const gfx::Size& source_size) {
137 base::AutoLock guard(lock_); 146 base::AutoLock guard(lock_);
138 147
139 // If this is the first call to UpdateCaptureSize(), or the receiver supports 148 // If this is the first call to UpdateCaptureSize(), or the receiver supports
140 // variable resolution, then determine the capture size by treating the 149 // variable resolution, then determine the capture size by treating the
141 // requested width and height as maxima. 150 // requested width and height as maxima.
142 if (!capture_size_updated_ || params_.allow_resolution_change) { 151 if (!capture_size_updated_ || params_.allow_resolution_change) {
143 // The capture resolution should not exceed the source frame size. 152 // The capture resolution should not exceed the source frame size.
144 // In other words it should downscale the image but not upscale it. 153 // In other words it should downscale the image but not upscale it.
145 if (source_size.width() > params_.requested_format.frame_size.width() || 154 if (source_size.width() > params_.requested_format.frame_size.width() ||
146 source_size.height() > params_.requested_format.frame_size.height()) { 155 source_size.height() > params_.requested_format.frame_size.height()) {
147 gfx::Rect capture_rect = media::ComputeLetterboxRegion( 156 gfx::Rect capture_rect = media::ComputeLetterboxRegion(
148 gfx::Rect(params_.requested_format.frame_size), source_size); 157 gfx::Rect(params_.requested_format.frame_size), source_size);
149 capture_size_ = gfx::Size(MakeEven(capture_rect.width()), 158 params_.requested_format.frame_size.SetSize(
150 MakeEven(capture_rect.height())); 159 MakeEven(capture_rect.width()), MakeEven(capture_rect.height()));
151 } else { 160 } else {
152 capture_size_ = gfx::Size(MakeEven(source_size.width()), 161 params_.requested_format.frame_size.SetSize(
153 MakeEven(source_size.height())); 162 MakeEven(source_size.width()), MakeEven(source_size.height()));
154 } 163 }
155 capture_size_updated_ = true; 164 capture_size_updated_ = true;
156 } 165 }
157 } 166 }
158 167
159 void ThreadSafeCaptureOracle::Stop() { 168 void ThreadSafeCaptureOracle::Stop() {
160 base::AutoLock guard(lock_); 169 base::AutoLock guard(lock_);
161 client_.reset(); 170 client_.reset();
162 } 171 }
163 172
164 void ThreadSafeCaptureOracle::ReportError(const std::string& reason) { 173 void ThreadSafeCaptureOracle::ReportError(const std::string& reason) {
165 base::AutoLock guard(lock_); 174 base::AutoLock guard(lock_);
166 if (client_) 175 if (client_)
167 client_->OnError(reason); 176 client_->OnError(reason);
168 } 177 }
169 178
170 void ThreadSafeCaptureOracle::DidCaptureFrame( 179 void ThreadSafeCaptureOracle::DidCaptureFrame(
180 int frame_number,
171 const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer, 181 const scoped_refptr<media::VideoCaptureDevice::Client::Buffer>& buffer,
172 const scoped_refptr<media::VideoFrame>& frame, 182 const scoped_refptr<media::VideoFrame>& frame,
173 int frame_number,
174 base::TimeTicks timestamp, 183 base::TimeTicks timestamp,
175 bool success) { 184 bool success) {
176 base::AutoLock guard(lock_); 185 base::AutoLock guard(lock_);
177 TRACE_EVENT_ASYNC_END2("mirroring", "Capture", buffer.get(), 186 TRACE_EVENT_ASYNC_END2("mirroring", "Capture", buffer.get(),
178 "success", success, 187 "success", success,
179 "timestamp", timestamp.ToInternalValue()); 188 "timestamp", timestamp.ToInternalValue());
180 189
181 if (!client_) 190 if (!client_)
182 return; // Capture is stopped. 191 return; // Capture is stopped.
183 192
184 if (success) { 193 if (success) {
185 if (oracle_->CompleteCapture(frame_number, timestamp)) { 194 if (oracle_->CompleteCapture(frame_number, timestamp)) {
186 client_->OnIncomingCapturedVideoFrame( 195 media::VideoCaptureFormat format = params_.requested_format;
187 buffer, 196 format.frame_size = frame->coded_size();
188 media::VideoCaptureFormat( 197 client_->OnIncomingCapturedVideoFrame(buffer, format, frame, timestamp);
189 capture_size_, frame_rate_, media::PIXEL_FORMAT_I420),
190 frame,
191 timestamp);
192 } 198 }
193 } 199 }
194 } 200 }
195 201
196 void ContentVideoCaptureDeviceCore::AllocateAndStart( 202 void ContentVideoCaptureDeviceCore::AllocateAndStart(
197 const media::VideoCaptureParams& params, 203 const media::VideoCaptureParams& params,
198 scoped_ptr<media::VideoCaptureDevice::Client> client) { 204 scoped_ptr<media::VideoCaptureDevice::Client> client) {
199 DCHECK(thread_checker_.CalledOnValidThread()); 205 DCHECK(thread_checker_.CalledOnValidThread());
200 206
201 if (state_ != kIdle) { 207 if (state_ != kIdle) {
202 DVLOG(1) << "Allocate() invoked when not in state Idle."; 208 DVLOG(1) << "Allocate() invoked when not in state Idle.";
203 return; 209 return;
204 } 210 }
205 211
206 if (params.requested_format.frame_rate <= 0) { 212 if (params.requested_format.frame_rate <= 0) {
207 std::string error_msg = base::StringPrintf( 213 std::string error_msg = base::StringPrintf(
208 "invalid frame_rate: %d", params.requested_format.frame_rate); 214 "invalid frame_rate: %d", params.requested_format.frame_rate);
209 DVLOG(1) << error_msg; 215 DVLOG(1) << error_msg;
210 client->OnError(error_msg); 216 client->OnError(error_msg);
211 return; 217 return;
212 } 218 }
213 219
214 if (params.requested_format.frame_size.width() < kMinFrameWidth || 220 if (params.requested_format.pixel_format != media::PIXEL_FORMAT_I420 &&
215 params.requested_format.frame_size.height() < kMinFrameHeight) { 221 params.requested_format.pixel_format != media::PIXEL_FORMAT_TEXTURE) {
216 std::string error_msg = 222 std::string error_msg = base::StringPrintf(
217 "invalid frame size: " + params.requested_format.frame_size.ToString(); 223 "unsupported format: %d", params.requested_format.pixel_format);
218 DVLOG(1) << error_msg; 224 DVLOG(1) << error_msg;
219 client->OnError(error_msg); 225 client->OnError(error_msg);
220 return; 226 return;
221 } 227 }
222 228
229 media::VideoCaptureParams new_params = params;
230 // Frame dimensions must each be an even integer since the client wants (or
231 // will convert to) YUV420.
232 new_params.requested_format.frame_size.SetSize(
233 MakeEven(params.requested_format.frame_size.width()),
234 MakeEven(params.requested_format.frame_size.height()));
235
223 base::TimeDelta capture_period = base::TimeDelta::FromMicroseconds( 236 base::TimeDelta capture_period = base::TimeDelta::FromMicroseconds(
224 1000000.0 / params.requested_format.frame_rate + 0.5); 237 1000000.0 / params.requested_format.frame_rate + 0.5);
225 238
226 scoped_ptr<VideoCaptureOracle> oracle( 239 scoped_ptr<VideoCaptureOracle> oracle(
227 new VideoCaptureOracle(capture_period, 240 new VideoCaptureOracle(capture_period,
228 kAcceleratedSubscriberIsSupported)); 241 kAcceleratedSubscriberIsSupported));
229 oracle_proxy_ = 242 oracle_proxy_ =
230 new ThreadSafeCaptureOracle(client.Pass(), oracle.Pass(), params); 243 new ThreadSafeCaptureOracle(client.Pass(), oracle.Pass(), new_params);
231 244
232 // Starts the capture machine asynchronously. 245 // Starts the capture machine asynchronously.
233 BrowserThread::PostTaskAndReplyWithResult( 246 BrowserThread::PostTaskAndReplyWithResult(
234 BrowserThread::UI, FROM_HERE, 247 BrowserThread::UI,
248 FROM_HERE,
235 base::Bind(&VideoCaptureMachine::Start, 249 base::Bind(&VideoCaptureMachine::Start,
236 base::Unretained(capture_machine_.get()), 250 base::Unretained(capture_machine_.get()),
237 oracle_proxy_), 251 oracle_proxy_,
238 base::Bind(&ContentVideoCaptureDeviceCore::CaptureStarted, 252 new_params),
239 AsWeakPtr())); 253 base::Bind(&ContentVideoCaptureDeviceCore::CaptureStarted, AsWeakPtr()));
240 254
241 TransitionStateTo(kCapturing); 255 TransitionStateTo(kCapturing);
242 } 256 }
243 257
244 void ContentVideoCaptureDeviceCore::StopAndDeAllocate() { 258 void ContentVideoCaptureDeviceCore::StopAndDeAllocate() {
245 DCHECK(thread_checker_.CalledOnValidThread()); 259 DCHECK(thread_checker_.CalledOnValidThread());
246 260
247 if (state_ != kCapturing) 261 if (state_ != kCapturing)
248 return; 262 return;
249 263
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 return; 324 return;
311 325
312 if (oracle_proxy_) 326 if (oracle_proxy_)
313 oracle_proxy_->ReportError(reason); 327 oracle_proxy_->ReportError(reason);
314 328
315 StopAndDeAllocate(); 329 StopAndDeAllocate();
316 TransitionStateTo(kError); 330 TransitionStateTo(kError);
317 } 331 }
318 332
319 } // namespace content 333 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698