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

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

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

Powered by Google App Engine
This is Rietveld 408576698