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

Side by Side Diff: content/renderer/media/media_stream_video_source.cc

Issue 246433006: Change MediaStreamVideoSource to output different resolutions to different tracks depending on the … (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Rebased 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/renderer/media/media_stream_video_source.h" 5 #include "content/renderer/media/media_stream_video_source.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <limits> 8 #include <limits>
9 #include <string> 9 #include <string>
10 10
11 #include "base/debug/trace_event.h" 11 #include "base/debug/trace_event.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
14 #include "content/child/child_process.h" 14 #include "content/child/child_process.h"
15 #include "content/renderer/media/media_stream_constraints_util.h" 15 #include "content/renderer/media/media_stream_constraints_util.h"
16 #include "content/renderer/media/media_stream_video_track.h" 16 #include "content/renderer/media/media_stream_video_track.h"
17 #include "content/renderer/media/video_frame_deliverer.h" 17 #include "content/renderer/media/video_track_adapter.h"
18 18
19 namespace content { 19 namespace content {
20 20
21 // Constraint keys. Specified by draft-alvestrand-constraints-resolution-00b 21 // Constraint keys. Specified by draft-alvestrand-constraints-resolution-00b
22 const char MediaStreamVideoSource::kMinAspectRatio[] = "minAspectRatio"; 22 const char MediaStreamVideoSource::kMinAspectRatio[] = "minAspectRatio";
23 const char MediaStreamVideoSource::kMaxAspectRatio[] = "maxAspectRatio"; 23 const char MediaStreamVideoSource::kMaxAspectRatio[] = "maxAspectRatio";
24 const char MediaStreamVideoSource::kMaxWidth[] = "maxWidth"; 24 const char MediaStreamVideoSource::kMaxWidth[] = "maxWidth";
25 const char MediaStreamVideoSource::kMinWidth[] = "minWidth"; 25 const char MediaStreamVideoSource::kMinWidth[] = "minWidth";
26 const char MediaStreamVideoSource::kMaxHeight[] = "maxHeight"; 26 const char MediaStreamVideoSource::kMaxHeight[] = "maxHeight";
27 const char MediaStreamVideoSource::kMinHeight[] = "minHeight"; 27 const char MediaStreamVideoSource::kMinHeight[] = "minHeight";
(...skipping 19 matching lines...) Expand all
47 47
48 // Google-specific key prefix. Constraints with this prefix are ignored if they 48 // Google-specific key prefix. Constraints with this prefix are ignored if they
49 // are unknown. 49 // are unknown.
50 const char kGooglePrefix[] = "goog"; 50 const char kGooglePrefix[] = "goog";
51 51
52 // MediaStreamVideoSource supports cropping of video frames but only up to 52 // MediaStreamVideoSource supports cropping of video frames but only up to
53 // kMaxCropFactor. Ie - if a constraint is set to maxHeight 360, an original 53 // kMaxCropFactor. Ie - if a constraint is set to maxHeight 360, an original
54 // input frame height of max 360 * kMaxCropFactor pixels is accepted. 54 // input frame height of max 360 * kMaxCropFactor pixels is accepted.
55 const int kMaxCropFactor = 2; 55 const int kMaxCropFactor = 2;
56 56
57 // Returns true if |constraint| has mandatory constraints.
58 bool HasMandatoryConstraints(const blink::WebMediaConstraints& constraints) {
59 blink::WebVector<blink::WebMediaConstraint> mandatory_constraints;
60 constraints.getMandatoryConstraints(mandatory_constraints);
61 return !mandatory_constraints.isEmpty();
62 }
63
64 // Retrieve the desired max width and height from |constraints|. If not set,
65 // the |desired_width| and |desired_height| are set to
66 // std::numeric_limits<int>::max();
67 // If either max width or height is set as a mandatory constraint, the optional
68 // constraints are not checked.
69 void GetDesiredMaxWidthAndHeight(const blink::WebMediaConstraints& constraints,
70 int* desired_width, int* desired_height) {
71 *desired_width = std::numeric_limits<int>::max();
72 *desired_height = std::numeric_limits<int>::max();
73
74 bool mandatory = GetMandatoryConstraintValueAsInteger(
75 constraints,
76 MediaStreamVideoSource::kMaxWidth,
77 desired_width);
78 mandatory |= GetMandatoryConstraintValueAsInteger(
79 constraints,
80 MediaStreamVideoSource::kMaxHeight,
81 desired_height);
82 if (mandatory)
83 return;
84
85 GetOptionalConstraintValueAsInteger(constraints,
86 MediaStreamVideoSource::kMaxWidth,
87 desired_width);
88 GetOptionalConstraintValueAsInteger(constraints,
89 MediaStreamVideoSource::kMaxHeight,
90 desired_height);
91 }
92
93 // Retrieve the desired max and min aspect ratio from |constraints|. If not set,
94 // the |min_aspect_ratio| is set to 0 and |max_aspect_ratio| is set to
95 // std::numeric_limits<double>::max();
96 // If either min or max aspect ratio is set as a mandatory constraint, the
97 // optional constraints are not checked.
98 void GetDesiredMinAndMaxAspectRatio(
99 const blink::WebMediaConstraints& constraints,
100 double* min_aspect_ratio,
101 double* max_aspect_ratio) {
102 *min_aspect_ratio = 0;
103 *max_aspect_ratio = std::numeric_limits<double>::max();
104
105 bool mandatory = GetMandatoryConstraintValueAsDouble(
106 constraints,
107 MediaStreamVideoSource::kMinAspectRatio,
108 min_aspect_ratio);
109 mandatory |= GetMandatoryConstraintValueAsDouble(
110 constraints,
111 MediaStreamVideoSource::kMaxAspectRatio,
112 max_aspect_ratio);
113 if (mandatory)
114 return;
115
116 GetOptionalConstraintValueAsDouble(
117 constraints,
118 MediaStreamVideoSource::kMinAspectRatio,
119 min_aspect_ratio);
120 GetOptionalConstraintValueAsDouble(
121 constraints,
122 MediaStreamVideoSource::kMaxAspectRatio,
123 max_aspect_ratio);
124 }
125
57 // Returns true if |constraint| is fulfilled. |format| can be changed 126 // Returns true if |constraint| is fulfilled. |format| can be changed
58 // changed by a constraint. Ie - the frame rate can be changed by setting 127 // changed by a constraint. Ie - the frame rate can be changed by setting
59 // maxFrameRate. 128 // maxFrameRate.
60 bool UpdateFormatForConstraint( 129 bool UpdateFormatForConstraint(
61 const blink::WebMediaConstraint& constraint, 130 const blink::WebMediaConstraint& constraint,
62 bool mandatory, 131 bool mandatory,
63 media::VideoCaptureFormat* format) { 132 media::VideoCaptureFormat* format) {
64 DCHECK(format != NULL); 133 DCHECK(format != NULL);
65 134
66 if (!format->IsValid()) 135 if (!format->IsValid())
(...skipping 13 matching lines...) Expand all
80 return true; 149 return true;
81 } 150 }
82 151
83 // Ignore Chrome specific Tab capture constraints. 152 // Ignore Chrome specific Tab capture constraints.
84 if (constraint_name == kMediaStreamSource || 153 if (constraint_name == kMediaStreamSource ||
85 constraint_name == kMediaStreamSourceId) 154 constraint_name == kMediaStreamSourceId)
86 return true; 155 return true;
87 156
88 if (constraint_name == MediaStreamVideoSource::kMinAspectRatio || 157 if (constraint_name == MediaStreamVideoSource::kMinAspectRatio ||
89 constraint_name == MediaStreamVideoSource::kMaxAspectRatio) { 158 constraint_name == MediaStreamVideoSource::kMaxAspectRatio) {
90 double double_value = 0; 159 // These constraints are handled by cropping if the camera outputs the wrong
91 base::StringToDouble(constraint_value, &double_value); 160 // aspect ratio.
92 161 double value;
93 // The aspect ratio in |constraint.m_value| has been converted to a string 162 return base::StringToDouble(constraint_value, &value);
94 // and back to a double, so it may have a rounding error.
95 // E.g if the value 1/3 is converted to a string, the string will not have
96 // infinite length.
97 // We add a margin of 0.0005 which is high enough to detect the same aspect
98 // ratio but small enough to avoid matching wrong aspect ratios.
99 const double kRoundingTruncation = 0.0005;
100 double ratio = static_cast<double>(format->frame_size.width()) /
101 format->frame_size.height();
102 if (constraint_name == MediaStreamVideoSource::kMinAspectRatio)
103 return (double_value <= ratio + kRoundingTruncation);
104 // Subtract 0.0005 to avoid rounding problems. Same as above.
105 return (double_value >= ratio - kRoundingTruncation);
106 } 163 }
107 164
108 int value; 165 int value;
109 if (!base::StringToInt(constraint_value, &value)) { 166 if (!base::StringToInt(constraint_value, &value)) {
110 DLOG(WARNING) << "Can't parse MediaStream constraint. Name:" 167 DLOG(WARNING) << "Can't parse MediaStream constraint. Name:"
111 << constraint_name << " Value:" << constraint_value; 168 << constraint_name << " Value:" << constraint_value;
112 return false; 169 return false;
113 } 170 }
114 if (constraint_name == MediaStreamVideoSource::kMinWidth) { 171 if (constraint_name == MediaStreamVideoSource::kMinWidth) {
115 return (value <= format->frame_size.width()); 172 return (value <= format->frame_size.width());
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
165 } 222 }
166 223
167 // Returns the media::VideoCaptureFormats that matches |constraints|. 224 // Returns the media::VideoCaptureFormats that matches |constraints|.
168 media::VideoCaptureFormats FilterFormats( 225 media::VideoCaptureFormats FilterFormats(
169 const blink::WebMediaConstraints& constraints, 226 const blink::WebMediaConstraints& constraints,
170 const media::VideoCaptureFormats& supported_formats) { 227 const media::VideoCaptureFormats& supported_formats) {
171 if (constraints.isNull()) { 228 if (constraints.isNull()) {
172 return supported_formats; 229 return supported_formats;
173 } 230 }
174 231
232 double max_aspect_ratio;
233 double min_aspect_ratio;
234 GetDesiredMinAndMaxAspectRatio(constraints,
235 &min_aspect_ratio,
236 &max_aspect_ratio);
237
238 if (min_aspect_ratio > max_aspect_ratio || max_aspect_ratio < 0.05f) {
239 DLOG(WARNING) << "Wrong requested aspect ratio.";
240 return media::VideoCaptureFormats();
241 }
242
243 int min_width = 0;
244 GetMandatoryConstraintValueAsInteger(constraints,
245 MediaStreamVideoSource::kMinWidth,
246 &min_width);
247 int min_height = 0;
248 GetMandatoryConstraintValueAsInteger(constraints,
249 MediaStreamVideoSource::kMinHeight,
250 &min_height);
251 int max_width;
252 int max_height;
253 GetDesiredMaxWidthAndHeight(constraints, &max_width, &max_height);
254
255 if (min_width > max_width || min_height > max_height)
256 return media::VideoCaptureFormats();
257
175 blink::WebVector<blink::WebMediaConstraint> mandatory; 258 blink::WebVector<blink::WebMediaConstraint> mandatory;
176 blink::WebVector<blink::WebMediaConstraint> optional; 259 blink::WebVector<blink::WebMediaConstraint> optional;
177 constraints.getMandatoryConstraints(mandatory); 260 constraints.getMandatoryConstraints(mandatory);
178 constraints.getOptionalConstraints(optional); 261 constraints.getOptionalConstraints(optional);
179
180 media::VideoCaptureFormats candidates = supported_formats; 262 media::VideoCaptureFormats candidates = supported_formats;
181
182 for (size_t i = 0; i < mandatory.size(); ++i) 263 for (size_t i = 0; i < mandatory.size(); ++i)
183 FilterFormatsByConstraint(mandatory[i], true, &candidates); 264 FilterFormatsByConstraint(mandatory[i], true, &candidates);
184 265
185 if (candidates.empty()) 266 if (candidates.empty())
186 return candidates; 267 return candidates;
187 268
188 // Ok - all mandatory checked and we still have candidates. 269 // Ok - all mandatory checked and we still have candidates.
189 // Let's try filtering using the optional constraints. The optional 270 // Let's try filtering using the optional constraints. The optional
190 // constraints must be filtered in the order they occur in |optional|. 271 // constraints must be filtered in the order they occur in |optional|.
191 // But if a constraint produce zero candidates, the constraint is ignored and 272 // But if a constraint produce zero candidates, the constraint is ignored and
192 // the next constraint is tested. 273 // the next constraint is tested.
193 // http://dev.w3.org/2011/webrtc/editor/getusermedia.html#idl-def-Constraints 274 // http://dev.w3.org/2011/webrtc/editor/getusermedia.html#idl-def-Constraints
194 for (size_t i = 0; i < optional.size(); ++i) { 275 for (size_t i = 0; i < optional.size(); ++i) {
195 media::VideoCaptureFormats current_candidates = candidates; 276 media::VideoCaptureFormats current_candidates = candidates;
196 FilterFormatsByConstraint(optional[i], false, &current_candidates); 277 FilterFormatsByConstraint(optional[i], false, &current_candidates);
197 if (!current_candidates.empty()) { 278 if (!current_candidates.empty()) {
198 candidates = current_candidates; 279 candidates = current_candidates;
199 } 280 }
200 } 281 }
201 282
202 // We have done as good as we can to filter the supported resolutions. 283 // We have done as good as we can to filter the supported resolutions.
203 return candidates; 284 return candidates;
204 } 285 }
205 286
206 // Returns true if |constraint| has mandatory constraints.
207 bool HasMandatoryConstraints(const blink::WebMediaConstraints& constraints) {
208 blink::WebVector<blink::WebMediaConstraint> mandatory_constraints;
209 constraints.getMandatoryConstraints(mandatory_constraints);
210 return !mandatory_constraints.isEmpty();
211 }
212
213 // Retrieve the desired max width and height from |constraints|.
214 void GetDesiredMaxWidthAndHeight(const blink::WebMediaConstraints& constraints,
215 int* desired_width, int* desired_height) {
216 bool mandatory = GetMandatoryConstraintValueAsInteger(
217 constraints, MediaStreamVideoSource::kMaxWidth, desired_width);
218 mandatory |= GetMandatoryConstraintValueAsInteger(
219 constraints, MediaStreamVideoSource::kMaxHeight, desired_height);
220 // Skip the optional constraints if any of the mandatory constraint is
221 // specified.
222 if (mandatory)
223 return;
224
225 GetOptionalConstraintValueAsInteger(constraints,
226 MediaStreamVideoSource::kMaxWidth,
227 desired_width);
228 GetOptionalConstraintValueAsInteger(constraints,
229 MediaStreamVideoSource::kMaxHeight,
230 desired_height);
231 }
232
233 const media::VideoCaptureFormat& GetBestFormatBasedOnArea( 287 const media::VideoCaptureFormat& GetBestFormatBasedOnArea(
234 const media::VideoCaptureFormats& formats, 288 const media::VideoCaptureFormats& formats,
235 int area) { 289 int area) {
236 media::VideoCaptureFormats::const_iterator it = formats.begin(); 290 media::VideoCaptureFormats::const_iterator it = formats.begin();
237 media::VideoCaptureFormats::const_iterator best_it = formats.begin(); 291 media::VideoCaptureFormats::const_iterator best_it = formats.begin();
238 int best_diff = std::numeric_limits<int>::max(); 292 int best_diff = std::numeric_limits<int>::max();
239 for (; it != formats.end(); ++it) { 293 for (; it != formats.end(); ++it) {
240 int diff = abs(area - it->frame_size.width() * it->frame_size.height()); 294 int diff = abs(area - it->frame_size.width() * it->frame_size.height());
241 if (diff < best_diff) { 295 if (diff < best_diff) {
242 best_diff = diff; 296 best_diff = diff;
243 best_it = it; 297 best_it = it;
244 } 298 }
245 } 299 }
246 return *best_it; 300 return *best_it;
247 } 301 }
248 302
249 // Find the format that best matches the default video size. 303 // Find the format that best matches the default video size.
250 // This algorithm is chosen since a resolution must be picked even if no 304 // This algorithm is chosen since a resolution must be picked even if no
251 // constraints are provided. We don't just select the maximum supported 305 // constraints are provided. We don't just select the maximum supported
252 // resolution since higher resolutions cost more in terms of complexity and 306 // resolution since higher resolutions cost more in terms of complexity and
253 // many cameras have lower frame rate and have more noise in the image at 307 // many cameras have lower frame rate and have more noise in the image at
254 // their maximum supported resolution. 308 // their maximum supported resolution.
255 void GetBestCaptureFormat( 309 void GetBestCaptureFormat(
256 const media::VideoCaptureFormats& formats, 310 const media::VideoCaptureFormats& formats,
257 const blink::WebMediaConstraints& constraints, 311 const blink::WebMediaConstraints& constraints,
258 media::VideoCaptureFormat* capture_format, 312 media::VideoCaptureFormat* capture_format) {
259 gfx::Size* max_frame_output_size) {
260 DCHECK(!formats.empty()); 313 DCHECK(!formats.empty());
261 DCHECK(max_frame_output_size);
262 314
263 int max_width = std::numeric_limits<int>::max(); 315 int max_width;
264 int max_height = std::numeric_limits<int>::max();; 316 int max_height;
265 GetDesiredMaxWidthAndHeight(constraints, &max_width, &max_height); 317 GetDesiredMaxWidthAndHeight(constraints, &max_width, &max_height);
266 318
267 *capture_format = GetBestFormatBasedOnArea( 319 *capture_format = GetBestFormatBasedOnArea(
268 formats, 320 formats,
269 std::min(max_width, MediaStreamVideoSource::kDefaultWidth) * 321 std::min(max_width, MediaStreamVideoSource::kDefaultWidth) *
270 std::min(max_height, MediaStreamVideoSource::kDefaultHeight)); 322 std::min(max_height, MediaStreamVideoSource::kDefaultHeight));
271
272 max_frame_output_size->set_width(max_width);
273 max_frame_output_size->set_height(max_height);
274 }
275
276 // Empty method used for keeping a reference to the original media::VideoFrame
277 // in MediaStreamVideoSource::FrameDeliverer::DeliverFrameOnIO if cropping is
278 // needed. The reference to |frame| is kept in the closure that calls this
279 // method.
280 void ReleaseOriginalFrame(
281 const scoped_refptr<media::VideoFrame>& frame) {
282 } 323 }
283 324
284 } // anonymous namespace 325 } // anonymous namespace
285 326
286 // Helper class used for delivering video frames to all registered tracks
287 // on the IO-thread.
288 class MediaStreamVideoSource::FrameDeliverer : public VideoFrameDeliverer {
289 public:
290 FrameDeliverer(
291 const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
292 : VideoFrameDeliverer(io_message_loop) {
293 }
294
295 // Register |callback| to receive video frames of max size
296 // |max_frame_output_size| on the IO thread.
297 // TODO(perkj): Currently |max_frame_output_size| must be the same for all
298 // |callbacks|.
299 void AddCallback(void* id,
300 const VideoCaptureDeliverFrameCB& callback,
301 const gfx::Size& max_frame_output_size) {
302 DCHECK(thread_checker().CalledOnValidThread());
303 io_message_loop()->PostTask(
304 FROM_HERE,
305 base::Bind(
306 &FrameDeliverer::AddCallbackWithResolutionOnIO,
307 this, id, callback, max_frame_output_size));
308 }
309
310 virtual void DeliverFrameOnIO(
311 const scoped_refptr<media::VideoFrame>& frame,
312 const media::VideoCaptureFormat& format) OVERRIDE {
313 DCHECK(io_message_loop()->BelongsToCurrentThread());
314 TRACE_EVENT0("video", "MediaStreamVideoSource::DeliverFrameOnIO");
315 if (max_output_size_.IsEmpty())
316 return; // Frame received before the output has been decided.
317
318 scoped_refptr<media::VideoFrame> video_frame(frame);
319 const gfx::Size& visible_size = frame->visible_rect().size();
320 if (visible_size.width() > max_output_size_.width() ||
321 visible_size.height() > max_output_size_.height()) {
322 // If |frame| is not the size that is expected, we need to crop it by
323 // providing a new |visible_rect|. The new visible rect must be within the
324 // original |visible_rect|.
325 gfx::Rect output_rect = frame->visible_rect();
326 output_rect.ClampToCenteredSize(max_output_size_);
327 // TODO(perkj): Allow cropping of textures once http://crbug/362521 is
328 // fixed.
329 if (frame->format() != media::VideoFrame::NATIVE_TEXTURE) {
330 video_frame = media::VideoFrame::WrapVideoFrame(
331 frame,
332 output_rect,
333 output_rect.size(),
334 base::Bind(&ReleaseOriginalFrame, frame));
335 }
336 }
337 VideoFrameDeliverer::DeliverFrameOnIO(video_frame, format);
338 }
339
340 protected:
341 virtual ~FrameDeliverer() {
342 }
343
344 void AddCallbackWithResolutionOnIO(
345 void* id,
346 const VideoCaptureDeliverFrameCB& callback,
347 const gfx::Size& max_frame_output_size) {
348 DCHECK(io_message_loop()->BelongsToCurrentThread());
349 // Currently we only support one frame output size.
350 DCHECK(!max_frame_output_size.IsEmpty() &&
351 (max_output_size_.IsEmpty() ||
352 max_output_size_ == max_frame_output_size));
353 max_output_size_ = max_frame_output_size;
354 VideoFrameDeliverer::AddCallbackOnIO(id, callback);
355 }
356
357 private:
358 gfx::Size max_output_size_;
359 };
360
361 // static 327 // static
362 MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource( 328 MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource(
363 const blink::WebMediaStreamSource& source) { 329 const blink::WebMediaStreamSource& source) {
364 return static_cast<MediaStreamVideoSource*>(source.extraData()); 330 return static_cast<MediaStreamVideoSource*>(source.extraData());
365 } 331 }
366 332
367 // static 333 // static
368 bool MediaStreamVideoSource::IsConstraintSupported(const std::string& name) { 334 bool MediaStreamVideoSource::IsConstraintSupported(const std::string& name) {
369 for (size_t i = 0; i < arraysize(kSupportedConstraints); ++i) { 335 for (size_t i = 0; i < arraysize(kSupportedConstraints); ++i) {
370 if (kSupportedConstraints[i] == name) 336 if (kSupportedConstraints[i] == name)
371 return true; 337 return true;
372 } 338 }
373 return false; 339 return false;
374 } 340 }
375 341
376 MediaStreamVideoSource::MediaStreamVideoSource() 342 MediaStreamVideoSource::MediaStreamVideoSource()
377 : state_(NEW), 343 : state_(NEW),
378 frame_deliverer_( 344 track_adapter_(new VideoTrackAdapter(
379 new MediaStreamVideoSource::FrameDeliverer( 345 ChildProcess::current()->io_message_loop_proxy())),
380 ChildProcess::current()->io_message_loop_proxy())),
381 weak_factory_(this) { 346 weak_factory_(this) {
382 } 347 }
383 348
384 MediaStreamVideoSource::~MediaStreamVideoSource() { 349 MediaStreamVideoSource::~MediaStreamVideoSource() {
385 DVLOG(3) << "~MediaStreamVideoSource()"; 350 DVLOG(3) << "~MediaStreamVideoSource()";
386 } 351 }
387 352
388 void MediaStreamVideoSource::AddTrack( 353 void MediaStreamVideoSource::AddTrack(
389 MediaStreamVideoTrack* track, 354 MediaStreamVideoTrack* track,
390 const VideoCaptureDeliverFrameCB& frame_callback, 355 const VideoCaptureDeliverFrameCB& frame_callback,
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
433 } 398 }
434 } 399 }
435 } 400 }
436 401
437 void MediaStreamVideoSource::RemoveTrack(MediaStreamVideoTrack* video_track) { 402 void MediaStreamVideoSource::RemoveTrack(MediaStreamVideoTrack* video_track) {
438 DCHECK(CalledOnValidThread()); 403 DCHECK(CalledOnValidThread());
439 std::vector<MediaStreamVideoTrack*>::iterator it = 404 std::vector<MediaStreamVideoTrack*>::iterator it =
440 std::find(tracks_.begin(), tracks_.end(), video_track); 405 std::find(tracks_.begin(), tracks_.end(), video_track);
441 DCHECK(it != tracks_.end()); 406 DCHECK(it != tracks_.end());
442 tracks_.erase(it); 407 tracks_.erase(it);
443 // Call |RemoveCallback| here even if adding the track has failed and 408
444 // frame_deliverer_->AddCallback has not been called. 409 // Check if |video_track| is waiting for applying new constraints and remove
445 frame_deliverer_->RemoveCallback(video_track); 410 // the request in that case.
411 for (std::vector<RequestedConstraints>::iterator it =
412 requested_constraints_.begin();
413 it != requested_constraints_.end(); ++it) {
414 if (it->track == video_track) {
415 requested_constraints_.erase(it);
416 break;
417 }
418 }
419 // Call |frame_adapter_->RemoveTrack| here even if adding the track has
420 // failed and |frame_adapter_->AddCallback| has not been called.
421 track_adapter_->RemoveTrack(video_track);
446 422
447 if (tracks_.empty()) 423 if (tracks_.empty())
448 StopSource(); 424 StopSource();
449 } 425 }
450 426
451 const scoped_refptr<base::MessageLoopProxy>& 427 const scoped_refptr<base::MessageLoopProxy>&
452 MediaStreamVideoSource::io_message_loop() const { 428 MediaStreamVideoSource::io_message_loop() const {
453 return frame_deliverer_->io_message_loop(); 429 DCHECK(CalledOnValidThread());
430 return track_adapter_->io_message_loop();
454 } 431 }
455 432
456 void MediaStreamVideoSource::DoStopSource() { 433 void MediaStreamVideoSource::DoStopSource() {
457 DCHECK(CalledOnValidThread()); 434 DCHECK(CalledOnValidThread());
458 DVLOG(3) << "DoStopSource()"; 435 DVLOG(3) << "DoStopSource()";
459 if (state_ == ENDED) 436 if (state_ == ENDED)
460 return; 437 return;
461 StopSourceImpl(); 438 StopSourceImpl();
462 state_ = ENDED; 439 state_ = ENDED;
463 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); 440 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
464 } 441 }
465 442
466 void MediaStreamVideoSource::OnSupportedFormats( 443 void MediaStreamVideoSource::OnSupportedFormats(
467 const media::VideoCaptureFormats& formats) { 444 const media::VideoCaptureFormats& formats) {
468 DCHECK(CalledOnValidThread()); 445 DCHECK(CalledOnValidThread());
469 DCHECK_EQ(RETRIEVING_CAPABILITIES, state_); 446 DCHECK_EQ(RETRIEVING_CAPABILITIES, state_);
470 447
471 supported_formats_ = formats; 448 supported_formats_ = formats;
472 if (!FindBestFormatWithConstraints(supported_formats_, 449 if (!FindBestFormatWithConstraints(supported_formats_,
473 &current_format_, 450 &current_format_)) {
474 &max_frame_output_size_,
475 &current_constraints_)) {
476 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); 451 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
477 // This object can be deleted after calling FinalizeAddTrack. See comment 452 // This object can be deleted after calling FinalizeAddTrack. See comment
478 // in the header file. 453 // in the header file.
479 FinalizeAddTrack(); 454 FinalizeAddTrack();
480 return; 455 return;
481 } 456 }
482 457
483 state_ = STARTING; 458 state_ = STARTING;
484 DVLOG(3) << "Starting the capturer with" 459 DVLOG(3) << "Starting the capturer with"
485 << " width = " << current_format_.frame_size.width() 460 << " width = " << current_format_.frame_size.width()
486 << " height = " << current_format_.frame_size.height() 461 << " height = " << current_format_.frame_size.height()
487 << " frame rate = " << current_format_.frame_rate; 462 << " frame rate = " << current_format_.frame_rate;
488 463
489 media::VideoCaptureParams params; 464 media::VideoCaptureParams params;
490 params.requested_format = current_format_; 465 params.requested_format = current_format_;
491 StartSourceImpl( 466 StartSourceImpl(
492 params, 467 params,
493 base::Bind(&MediaStreamVideoSource::FrameDeliverer::DeliverFrameOnIO, 468 base::Bind(&VideoTrackAdapter::DeliverFrameOnIO, track_adapter_));
494 frame_deliverer_));
495 } 469 }
496 470
497 bool MediaStreamVideoSource::FindBestFormatWithConstraints( 471 bool MediaStreamVideoSource::FindBestFormatWithConstraints(
498 const media::VideoCaptureFormats& formats, 472 const media::VideoCaptureFormats& formats,
499 media::VideoCaptureFormat* best_format, 473 media::VideoCaptureFormat* best_format) {
500 gfx::Size* max_frame_output_size,
501 blink::WebMediaConstraints* resulting_constraints) {
502 // Find the first constraints that we can fulfill. 474 // Find the first constraints that we can fulfill.
503 for (std::vector<RequestedConstraints>::iterator request_it = 475 for (std::vector<RequestedConstraints>::iterator request_it =
504 requested_constraints_.begin(); 476 requested_constraints_.begin();
505 request_it != requested_constraints_.end(); ++request_it) { 477 request_it != requested_constraints_.end(); ++request_it) {
506 const blink::WebMediaConstraints& requested_constraints = 478 const blink::WebMediaConstraints& requested_constraints =
507 request_it->constraints; 479 request_it->constraints;
508 480
509 // If the source doesn't support capability enumeration it is still ok if 481 // If the source doesn't support capability enumeration it is still ok if
510 // no mandatory constraints have been specified. That just means that 482 // no mandatory constraints have been specified. That just means that
511 // we will start with whatever format is native to the source. 483 // we will start with whatever format is native to the source.
512 if (formats.empty() && !HasMandatoryConstraints(requested_constraints)) { 484 if (formats.empty() && !HasMandatoryConstraints(requested_constraints)) {
513 *best_format = media::VideoCaptureFormat(); 485 *best_format = media::VideoCaptureFormat();
514 *resulting_constraints = requested_constraints;
515 *max_frame_output_size = gfx::Size(std::numeric_limits<int>::max(),
516 std::numeric_limits<int>::max());
517 return true; 486 return true;
518 } 487 }
519 media::VideoCaptureFormats filtered_formats = 488 media::VideoCaptureFormats filtered_formats =
520 FilterFormats(requested_constraints, formats); 489 FilterFormats(requested_constraints, formats);
521 if (filtered_formats.size() > 0) { 490 if (filtered_formats.size() > 0) {
522 // A request with constraints that can be fulfilled. 491 // A request with constraints that can be fulfilled.
523 GetBestCaptureFormat(filtered_formats, 492 GetBestCaptureFormat(filtered_formats,
524 requested_constraints, 493 requested_constraints,
525 best_format, 494 best_format);
526 max_frame_output_size);
527 *resulting_constraints= requested_constraints;
528 return true; 495 return true;
529 } 496 }
530 } 497 }
531 return false; 498 return false;
532 } 499 }
533 500
534 void MediaStreamVideoSource::OnStartDone(bool success) { 501 void MediaStreamVideoSource::OnStartDone(bool success) {
535 DCHECK(CalledOnValidThread()); 502 DCHECK(CalledOnValidThread());
536 DVLOG(3) << "OnStartDone({success =" << success << "})"; 503 DVLOG(3) << "OnStartDone({success =" << success << "})";
537 if (success) { 504 if (success) {
(...skipping 21 matching lines...) Expand all
559 it != callbacks.end(); ++it) { 526 it != callbacks.end(); ++it) {
560 // The track has been added successfully if the source has started and 527 // The track has been added successfully if the source has started and
561 // there are either no mandatory constraints and the source doesn't expose 528 // there are either no mandatory constraints and the source doesn't expose
562 // its format capabilities, or the constraints and the format match. 529 // its format capabilities, or the constraints and the format match.
563 // For example, a remote source doesn't expose its format capabilities. 530 // For example, a remote source doesn't expose its format capabilities.
564 bool success = 531 bool success =
565 state_ == STARTED && 532 state_ == STARTED &&
566 ((!current_format_.IsValid() && !HasMandatoryConstraints( 533 ((!current_format_.IsValid() && !HasMandatoryConstraints(
567 it->constraints)) || 534 it->constraints)) ||
568 !FilterFormats(it->constraints, formats).empty()); 535 !FilterFormats(it->constraints, formats).empty());
536
569 if (success) { 537 if (success) {
570 frame_deliverer_->AddCallback(it->track, it->frame_callback, 538 int max_width;
571 max_frame_output_size_); 539 int max_height;
540 GetDesiredMaxWidthAndHeight(it->constraints, &max_width, &max_height);
541 double max_aspect_ratio;
542 double min_aspect_ratio;
543 GetDesiredMinAndMaxAspectRatio(it->constraints,
544 &min_aspect_ratio,
545 &max_aspect_ratio);
546 track_adapter_->AddTrack(it->track,it->frame_callback,
547 max_width, max_height,
548 min_aspect_ratio, max_aspect_ratio);
572 } 549 }
550
573 DVLOG(3) << "FinalizeAddTrack() success " << success; 551 DVLOG(3) << "FinalizeAddTrack() success " << success;
552
574 if (!it->callback.is_null()) 553 if (!it->callback.is_null())
575 it->callback.Run(this, success); 554 it->callback.Run(this, success);
576 } 555 }
577 } 556 }
578 557
579 void MediaStreamVideoSource::SetReadyState( 558 void MediaStreamVideoSource::SetReadyState(
580 blink::WebMediaStreamSource::ReadyState state) { 559 blink::WebMediaStreamSource::ReadyState state) {
581 if (!owner().isNull()) { 560 if (!owner().isNull()) {
582 owner().setReadyState(state); 561 owner().setReadyState(state);
583 } 562 }
(...skipping 11 matching lines...) Expand all
595 : track(track), 574 : track(track),
596 frame_callback(frame_callback), 575 frame_callback(frame_callback),
597 constraints(constraints), 576 constraints(constraints),
598 callback(callback) { 577 callback(callback) {
599 } 578 }
600 579
601 MediaStreamVideoSource::RequestedConstraints::~RequestedConstraints() { 580 MediaStreamVideoSource::RequestedConstraints::~RequestedConstraints() {
602 } 581 }
603 582
604 } // namespace content 583 } // namespace content
OLDNEW
« no previous file with comments | « content/renderer/media/media_stream_video_source.h ('k') | content/renderer/media/media_stream_video_source_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698