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

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

Powered by Google App Engine
This is Rietveld 408576698