Chromium Code Reviews| OLD | NEW |
|---|---|
| 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/renderer/media/media_stream_dependency_factory.h" | |
| 15 #include "content/renderer/media/media_stream_video_track.h" | 14 #include "content/renderer/media/media_stream_video_track.h" |
| 16 #include "content/renderer/media/video_frame_deliverer.h" | 15 #include "content/renderer/media/video_track_adapter.h" |
| 17 #include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h" | |
| 18 | 16 |
| 19 namespace content { | 17 namespace content { |
| 20 | 18 |
| 21 // Constraint keys. Specified by draft-alvestrand-constraints-resolution-00b | 19 // Constraint keys. Specified by draft-alvestrand-constraints-resolution-00b |
| 22 const char MediaStreamVideoSource::kMinAspectRatio[] = "minAspectRatio"; | 20 const char MediaStreamVideoSource::kMinAspectRatio[] = "minAspectRatio"; |
| 23 const char MediaStreamVideoSource::kMaxAspectRatio[] = "maxAspectRatio"; | 21 const char MediaStreamVideoSource::kMaxAspectRatio[] = "maxAspectRatio"; |
| 24 const char MediaStreamVideoSource::kMaxWidth[] = "maxWidth"; | 22 const char MediaStreamVideoSource::kMaxWidth[] = "maxWidth"; |
| 25 const char MediaStreamVideoSource::kMinWidth[] = "minWidth"; | 23 const char MediaStreamVideoSource::kMinWidth[] = "minWidth"; |
| 26 const char MediaStreamVideoSource::kMaxHeight[] = "maxHeight"; | 24 const char MediaStreamVideoSource::kMaxHeight[] = "maxHeight"; |
| 27 const char MediaStreamVideoSource::kMinHeight[] = "minHeight"; | 25 const char MediaStreamVideoSource::kMinHeight[] = "minHeight"; |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 82 return true; | 80 return true; |
| 83 } | 81 } |
| 84 | 82 |
| 85 // Ignore Chrome specific Tab capture constraints. | 83 // Ignore Chrome specific Tab capture constraints. |
| 86 if (constraint_name == kMediaStreamSource || | 84 if (constraint_name == kMediaStreamSource || |
| 87 constraint_name == kMediaStreamSourceId) | 85 constraint_name == kMediaStreamSourceId) |
| 88 return true; | 86 return true; |
| 89 | 87 |
| 90 if (constraint_name == MediaStreamVideoSource::kMinAspectRatio || | 88 if (constraint_name == MediaStreamVideoSource::kMinAspectRatio || |
| 91 constraint_name == MediaStreamVideoSource::kMaxAspectRatio) { | 89 constraint_name == MediaStreamVideoSource::kMaxAspectRatio) { |
| 92 double double_value = 0; | 90 return true; |
| 93 base::StringToDouble(constraint_value, &double_value); | |
| 94 | |
| 95 // The aspect ratio in |constraint.m_value| has been converted to a string | |
| 96 // and back to a double, so it may have a rounding error. | |
| 97 // E.g if the value 1/3 is converted to a string, the string will not have | |
| 98 // infinite length. | |
| 99 // We add a margin of 0.0005 which is high enough to detect the same aspect | |
| 100 // ratio but small enough to avoid matching wrong aspect ratios. | |
| 101 const double kRoundingTruncation = 0.0005; | |
| 102 double ratio = static_cast<double>(format->frame_size.width()) / | |
| 103 format->frame_size.height(); | |
| 104 if (constraint_name == MediaStreamVideoSource::kMinAspectRatio) | |
| 105 return (double_value <= ratio + kRoundingTruncation); | |
| 106 // Subtract 0.0005 to avoid rounding problems. Same as above. | |
| 107 return (double_value >= ratio - kRoundingTruncation); | |
| 108 } | 91 } |
| 109 | 92 |
| 110 int value; | 93 int value; |
| 111 if (!base::StringToInt(constraint_value, &value)) { | 94 if (!base::StringToInt(constraint_value, &value)) { |
| 112 DLOG(WARNING) << "Can't parse MediaStream constraint. Name:" | 95 DLOG(WARNING) << "Can't parse MediaStream constraint. Name:" |
| 113 << constraint_name << " Value:" << constraint_value; | 96 << constraint_name << " Value:" << constraint_value; |
| 114 return false; | 97 return false; |
| 115 } | 98 } |
| 116 if (constraint_name == MediaStreamVideoSource::kMinWidth) { | 99 if (constraint_name == MediaStreamVideoSource::kMinWidth) { |
| 117 return (value <= format->frame_size.width()); | 100 return (value <= format->frame_size.width()); |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 210 int* value) { | 193 int* value) { |
| 211 blink::WebString value_str; | 194 blink::WebString value_str; |
| 212 bool ret = mandatory ? | 195 bool ret = mandatory ? |
| 213 constraints.getMandatoryConstraintValue(name, value_str) : | 196 constraints.getMandatoryConstraintValue(name, value_str) : |
| 214 constraints.getOptionalConstraintValue(name, value_str); | 197 constraints.getOptionalConstraintValue(name, value_str); |
| 215 if (ret) | 198 if (ret) |
| 216 base::StringToInt(value_str.utf8(), value); | 199 base::StringToInt(value_str.utf8(), value); |
| 217 return ret; | 200 return ret; |
| 218 } | 201 } |
| 219 | 202 |
| 203 bool GetConstraintValue(const blink::WebMediaConstraints& constraints, | |
| 204 bool mandatory, const blink::WebString& name, | |
| 205 double* value) { | |
| 206 blink::WebString value_str; | |
| 207 bool ret = mandatory ? | |
| 208 constraints.getMandatoryConstraintValue(name, value_str) : | |
| 209 constraints.getOptionalConstraintValue(name, value_str); | |
| 210 if (ret) | |
| 211 base::StringToDouble(value_str.utf8(), value); | |
| 212 return ret; | |
| 213 } | |
| 214 | |
| 220 // Returns true if |constraint| has mandatory constraints. | 215 // Returns true if |constraint| has mandatory constraints. |
| 221 bool HasMandatoryConstraints(const blink::WebMediaConstraints& constraints) { | 216 bool HasMandatoryConstraints(const blink::WebMediaConstraints& constraints) { |
| 222 blink::WebVector<blink::WebMediaConstraint> mandatory_constraints; | 217 blink::WebVector<blink::WebMediaConstraint> mandatory_constraints; |
| 223 constraints.getMandatoryConstraints(mandatory_constraints); | 218 constraints.getMandatoryConstraints(mandatory_constraints); |
| 224 return !mandatory_constraints.isEmpty(); | 219 return !mandatory_constraints.isEmpty(); |
| 225 } | 220 } |
| 226 | 221 |
| 227 // Retrieve the desired max width and height from |constraints|. | 222 // Retrieve the desired max width and height from |constraints|. If not set, |
| 223 // the |desired_width| and |desired_height| is to | |
| 224 // std::numeric_limits<int>::max(); | |
| 228 void GetDesiredMaxWidthAndHeight(const blink::WebMediaConstraints& constraints, | 225 void GetDesiredMaxWidthAndHeight(const blink::WebMediaConstraints& constraints, |
| 229 int* desired_width, int* desired_height) { | 226 int* desired_width, int* desired_height) { |
| 227 *desired_width = std::numeric_limits<int>::max(); | |
| 228 *desired_height = std::numeric_limits<int>::max();; | |
| 230 bool mandatory = GetConstraintValue(constraints, true, | 229 bool mandatory = GetConstraintValue(constraints, true, |
| 231 MediaStreamVideoSource::kMaxWidth, | 230 MediaStreamVideoSource::kMaxWidth, |
| 232 desired_width); | 231 desired_width); |
| 233 mandatory |= GetConstraintValue(constraints, true, | 232 mandatory |= GetConstraintValue(constraints, true, |
| 234 MediaStreamVideoSource::kMaxHeight, | 233 MediaStreamVideoSource::kMaxHeight, |
| 235 desired_height); | 234 desired_height); |
| 236 if (mandatory) | 235 if (mandatory) |
| 237 return; | 236 return; |
| 238 | 237 |
| 239 GetConstraintValue(constraints, false, MediaStreamVideoSource::kMaxWidth, | 238 GetConstraintValue(constraints, false, MediaStreamVideoSource::kMaxWidth, |
| 240 desired_width); | 239 desired_width); |
| 241 GetConstraintValue(constraints, false, MediaStreamVideoSource::kMaxHeight, | 240 GetConstraintValue(constraints, false, MediaStreamVideoSource::kMaxHeight, |
| 242 desired_height); | 241 desired_height); |
| 243 } | 242 } |
| 244 | 243 |
| 244 void GetDesiredMinAndMaxAspectRatio( | |
| 245 const blink::WebMediaConstraints& constraints, | |
| 246 double* min_aspect_ratio, | |
| 247 double* max_aspect_ratio) { | |
| 248 *min_aspect_ratio = 0; | |
| 249 *max_aspect_ratio = std::numeric_limits<double>::max(); | |
| 250 | |
| 251 bool mandatory = GetConstraintValue(constraints, true, | |
| 252 MediaStreamVideoSource::kMinAspectRatio, | |
| 253 min_aspect_ratio); | |
| 254 mandatory |= GetConstraintValue(constraints, true, | |
| 255 MediaStreamVideoSource::kMaxAspectRatio, | |
| 256 max_aspect_ratio); | |
| 257 if (!mandatory && | |
| 258 !GetConstraintValue(constraints, false, | |
| 259 MediaStreamVideoSource::kMinAspectRatio, | |
| 260 min_aspect_ratio) && | |
| 261 !GetConstraintValue(constraints, false, | |
| 262 MediaStreamVideoSource::kMaxAspectRatio, | |
| 263 max_aspect_ratio)) { | |
| 264 return; | |
| 265 } | |
| 266 // The aspect ratio in |constraint.m_value| has been converted to a string | |
| 267 // and back to a double, so it may have a rounding error. | |
| 268 // E.g if the value 1/3 is converted to a string, the string will not have | |
| 269 // infinite length. | |
| 270 // We add a margin of 0.0005 which is high enough to detect the same aspect | |
| 271 // ratio but small enough to avoid matching wrong aspect ratios. | |
| 272 const double kRoundingTruncation = 0.0005; | |
| 273 if (*min_aspect_ratio != 0) | |
|
mcasas
2014/05/07 14:10:43
|min_aspect_ratio| is a double, so this comparison
perkj_chrome
2014/05/08 11:29:47
Why would it be true? I set it to 0 at line 248?
mcasas
2014/05/09 07:46:24
A float cannot be 0.0 exactly, and the most likely
| |
| 274 *min_aspect_ratio += kRoundingTruncation; | |
| 275 if (*max_aspect_ratio != std::numeric_limits<double>::max()) | |
| 276 *max_aspect_ratio -= kRoundingTruncation; | |
| 277 } | |
| 278 | |
| 245 const media::VideoCaptureFormat& GetBestFormatBasedOnArea( | 279 const media::VideoCaptureFormat& GetBestFormatBasedOnArea( |
| 246 const media::VideoCaptureFormats& formats, | 280 const media::VideoCaptureFormats& formats, |
| 247 int area) { | 281 int area) { |
| 248 media::VideoCaptureFormats::const_iterator it = formats.begin(); | 282 media::VideoCaptureFormats::const_iterator it = formats.begin(); |
| 249 media::VideoCaptureFormats::const_iterator best_it = formats.begin(); | 283 media::VideoCaptureFormats::const_iterator best_it = formats.begin(); |
| 250 int best_diff = std::numeric_limits<int>::max(); | 284 int best_diff = std::numeric_limits<int>::max(); |
| 251 for (; it != formats.end(); ++it) { | 285 for (; it != formats.end(); ++it) { |
| 252 int diff = abs(area - it->frame_size.width() * it->frame_size.height()); | 286 int diff = abs(area - it->frame_size.width() * it->frame_size.height()); |
| 253 if (diff < best_diff) { | 287 if (diff < best_diff) { |
| 254 best_diff = diff; | 288 best_diff = diff; |
| 255 best_it = it; | 289 best_it = it; |
| 256 } | 290 } |
| 257 } | 291 } |
| 258 return *best_it; | 292 return *best_it; |
| 259 } | 293 } |
| 260 | 294 |
| 261 // Find the format that best matches the default video size. | 295 // Find the format that best matches the default video size. |
| 262 // This algorithm is chosen since a resolution must be picked even if no | 296 // This algorithm is chosen since a resolution must be picked even if no |
| 263 // constraints are provided. We don't just select the maximum supported | 297 // constraints are provided. We don't just select the maximum supported |
| 264 // resolution since higher resolutions cost more in terms of complexity and | 298 // resolution since higher resolutions cost more in terms of complexity and |
| 265 // many cameras have lower frame rate and have more noise in the image at | 299 // many cameras have lower frame rate and have more noise in the image at |
| 266 // their maximum supported resolution. | 300 // their maximum supported resolution. |
| 267 void GetBestCaptureFormat( | 301 void GetBestCaptureFormat( |
| 268 const media::VideoCaptureFormats& formats, | 302 const media::VideoCaptureFormats& formats, |
| 269 const blink::WebMediaConstraints& constraints, | 303 const blink::WebMediaConstraints& constraints, |
| 270 media::VideoCaptureFormat* capture_format, | 304 media::VideoCaptureFormat* capture_format) { |
| 271 gfx::Size* max_frame_output_size) { | |
| 272 DCHECK(!formats.empty()); | 305 DCHECK(!formats.empty()); |
| 273 DCHECK(max_frame_output_size); | |
| 274 | 306 |
| 275 int max_width = std::numeric_limits<int>::max(); | 307 int max_width = std::numeric_limits<int>::max(); |
| 276 int max_height = std::numeric_limits<int>::max();; | 308 int max_height = std::numeric_limits<int>::max();; |
| 277 GetDesiredMaxWidthAndHeight(constraints, &max_width, &max_height); | 309 GetDesiredMaxWidthAndHeight(constraints, &max_width, &max_height); |
| 278 | 310 |
| 279 *capture_format = GetBestFormatBasedOnArea( | 311 *capture_format = GetBestFormatBasedOnArea( |
| 280 formats, | 312 formats, |
| 281 std::min(max_width, MediaStreamVideoSource::kDefaultWidth) * | 313 std::min(max_width, MediaStreamVideoSource::kDefaultWidth) * |
| 282 std::min(max_height, MediaStreamVideoSource::kDefaultHeight)); | 314 std::min(max_height, MediaStreamVideoSource::kDefaultHeight)); |
| 283 | |
| 284 max_frame_output_size->set_width(max_width); | |
| 285 max_frame_output_size->set_height(max_height); | |
| 286 } | |
| 287 | |
| 288 // Empty method used for keeping a reference to the original media::VideoFrame | |
| 289 // in MediaStreamVideoSource::FrameDeliverer::DeliverFrameOnIO if cropping is | |
| 290 // needed. The reference to |frame| is kept in the closure that calls this | |
| 291 // method. | |
| 292 void ReleaseOriginalFrame( | |
| 293 const scoped_refptr<media::VideoFrame>& frame) { | |
| 294 } | 315 } |
| 295 | 316 |
| 296 } // anonymous namespace | 317 } // anonymous namespace |
| 297 | 318 |
| 298 // Helper class used for delivering video frames to all registered tracks | |
| 299 // on the IO-thread. | |
| 300 class MediaStreamVideoSource::FrameDeliverer : public VideoFrameDeliverer { | |
| 301 public: | |
| 302 FrameDeliverer( | |
| 303 const scoped_refptr<base::MessageLoopProxy>& io_message_loop) | |
| 304 : VideoFrameDeliverer(io_message_loop) { | |
| 305 } | |
| 306 | |
| 307 // Register |callback| to receive video frames of max size | |
| 308 // |max_frame_output_size| on the IO thread. | |
| 309 // TODO(perkj): Currently |max_frame_output_size| must be the same for all | |
| 310 // |callbacks|. | |
| 311 void AddCallback(void* id, | |
| 312 const VideoCaptureDeliverFrameCB& callback, | |
| 313 const gfx::Size& max_frame_output_size) { | |
| 314 DCHECK(thread_checker().CalledOnValidThread()); | |
| 315 io_message_loop()->PostTask( | |
| 316 FROM_HERE, | |
| 317 base::Bind( | |
| 318 &FrameDeliverer::AddCallbackWithResolutionOnIO, | |
| 319 this, id, callback, max_frame_output_size)); | |
| 320 } | |
| 321 | |
| 322 virtual void DeliverFrameOnIO( | |
| 323 const scoped_refptr<media::VideoFrame>& frame, | |
| 324 const media::VideoCaptureFormat& format) OVERRIDE { | |
| 325 DCHECK(io_message_loop()->BelongsToCurrentThread()); | |
| 326 TRACE_EVENT0("video", "MediaStreamVideoSource::DeliverFrameOnIO"); | |
| 327 if (max_output_size_.IsEmpty()) | |
| 328 return; // Frame received before the output has been decided. | |
| 329 | |
| 330 scoped_refptr<media::VideoFrame> video_frame(frame); | |
| 331 const gfx::Size& visible_size = frame->visible_rect().size(); | |
| 332 if (visible_size.width() > max_output_size_.width() || | |
| 333 visible_size.height() > max_output_size_.height()) { | |
| 334 // If |frame| is not the size that is expected, we need to crop it by | |
| 335 // providing a new |visible_rect|. The new visible rect must be within the | |
| 336 // original |visible_rect|. | |
| 337 gfx::Rect output_rect = frame->visible_rect(); | |
| 338 output_rect.ClampToCenteredSize(max_output_size_); | |
| 339 // TODO(perkj): Allow cropping of textures once http://crbug/362521 is | |
| 340 // fixed. | |
| 341 if (frame->format() != media::VideoFrame::NATIVE_TEXTURE) { | |
| 342 video_frame = media::VideoFrame::WrapVideoFrame( | |
| 343 frame, | |
| 344 output_rect, | |
| 345 output_rect.size(), | |
| 346 base::Bind(&ReleaseOriginalFrame, frame)); | |
| 347 } | |
| 348 } | |
| 349 VideoFrameDeliverer::DeliverFrameOnIO(video_frame, format); | |
| 350 } | |
| 351 | |
| 352 protected: | |
| 353 virtual ~FrameDeliverer() { | |
| 354 } | |
| 355 | |
| 356 void AddCallbackWithResolutionOnIO( | |
| 357 void* id, | |
| 358 const VideoCaptureDeliverFrameCB& callback, | |
| 359 const gfx::Size& max_frame_output_size) { | |
| 360 DCHECK(io_message_loop()->BelongsToCurrentThread()); | |
| 361 // Currently we only support one frame output size. | |
| 362 DCHECK(!max_frame_output_size.IsEmpty() && | |
| 363 (max_output_size_.IsEmpty() || | |
| 364 max_output_size_ == max_frame_output_size)); | |
| 365 max_output_size_ = max_frame_output_size; | |
| 366 VideoFrameDeliverer::AddCallbackOnIO(id, callback); | |
| 367 } | |
| 368 | |
| 369 private: | |
| 370 gfx::Size max_output_size_; | |
| 371 }; | |
| 372 | |
| 373 // static | 319 // static |
| 374 MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource( | 320 MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource( |
| 375 const blink::WebMediaStreamSource& source) { | 321 const blink::WebMediaStreamSource& source) { |
| 376 return static_cast<MediaStreamVideoSource*>(source.extraData()); | 322 return static_cast<MediaStreamVideoSource*>(source.extraData()); |
| 377 } | 323 } |
| 378 | 324 |
| 379 // static | 325 // static |
| 380 bool MediaStreamVideoSource::IsConstraintSupported(const std::string& name) { | 326 bool MediaStreamVideoSource::IsConstraintSupported(const std::string& name) { |
| 381 for (size_t i = 0; i < arraysize(kSupportedConstraints); ++i) { | 327 for (size_t i = 0; i < arraysize(kSupportedConstraints); ++i) { |
| 382 if (kSupportedConstraints[i] == name) | 328 if (kSupportedConstraints[i] == name) |
| 383 return true; | 329 return true; |
| 384 } | 330 } |
| 385 return false; | 331 return false; |
| 386 } | 332 } |
| 387 | 333 |
| 388 MediaStreamVideoSource::MediaStreamVideoSource( | 334 MediaStreamVideoSource::MediaStreamVideoSource( |
| 389 const scoped_refptr<base::MessageLoopProxy>& io_message_loop) | 335 const scoped_refptr<base::MessageLoopProxy>& io_message_loop) |
| 390 : state_(NEW), | 336 : state_(NEW), |
| 391 frame_deliverer_( | 337 track_adapter_( |
| 392 new MediaStreamVideoSource::FrameDeliverer(io_message_loop)), | 338 new VideoTrackAdapter(io_message_loop)), |
|
mcasas
2014/05/07 14:10:43
nit: Fits in one line.
perkj_chrome
2014/05/08 11:29:47
Done.
| |
| 393 weak_factory_(this) { | 339 weak_factory_(this) { |
| 394 } | 340 } |
| 395 | 341 |
| 396 MediaStreamVideoSource::~MediaStreamVideoSource() { | 342 MediaStreamVideoSource::~MediaStreamVideoSource() { |
| 397 DVLOG(3) << "~MediaStreamVideoSource()"; | 343 DVLOG(3) << "~MediaStreamVideoSource()"; |
| 398 } | 344 } |
| 399 | 345 |
| 400 void MediaStreamVideoSource::AddTrack( | 346 void MediaStreamVideoSource::AddTrack( |
| 401 MediaStreamVideoTrack* track, | 347 MediaStreamVideoTrack* track, |
| 402 const VideoCaptureDeliverFrameCB& frame_callback, | 348 const VideoCaptureDeliverFrameCB& frame_callback, |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 442 } | 388 } |
| 443 } | 389 } |
| 444 } | 390 } |
| 445 | 391 |
| 446 void MediaStreamVideoSource::RemoveTrack(MediaStreamVideoTrack* video_track) { | 392 void MediaStreamVideoSource::RemoveTrack(MediaStreamVideoTrack* video_track) { |
| 447 DCHECK(CalledOnValidThread()); | 393 DCHECK(CalledOnValidThread()); |
| 448 std::vector<MediaStreamVideoTrack*>::iterator it = | 394 std::vector<MediaStreamVideoTrack*>::iterator it = |
| 449 std::find(tracks_.begin(), tracks_.end(), video_track); | 395 std::find(tracks_.begin(), tracks_.end(), video_track); |
| 450 DCHECK(it != tracks_.end()); | 396 DCHECK(it != tracks_.end()); |
| 451 tracks_.erase(it); | 397 tracks_.erase(it); |
| 452 // Call |RemoveCallback| here even if adding the track has failed and | 398 |
| 453 // frame_deliverer_->AddCallback has not been called. | 399 // Check if the track is waiting for applying new constraints and remove |
| 454 frame_deliverer_->RemoveCallback(video_track); | 400 // it in that case. |
| 401 for (std::vector<RequestedConstraints>::iterator it = | |
| 402 requested_constraints_.begin(); | |
| 403 it != requested_constraints_.end(); ++it) { | |
| 404 if (it->track == video_track) { | |
| 405 requested_constraints_.erase(it); | |
| 406 break; | |
| 407 } | |
| 408 } | |
| 409 // Call |frame_adapter_->RemoveTrack| here even if adding the track has | |
| 410 // failed and |frame_adapter_->AddCallback| has not been called. | |
| 411 track_adapter_->RemoveTrack(video_track); | |
| 455 | 412 |
| 456 if (tracks_.empty()) | 413 if (tracks_.empty()) |
| 457 StopSource(); | 414 StopSource(); |
| 458 } | 415 } |
| 459 | 416 |
| 460 const scoped_refptr<base::MessageLoopProxy>& | 417 const scoped_refptr<base::MessageLoopProxy>& |
| 461 MediaStreamVideoSource::io_message_loop() const { | 418 MediaStreamVideoSource::io_message_loop() const { |
| 462 return frame_deliverer_->io_message_loop(); | 419 return track_adapter_->io_message_loop(); |
|
mcasas
2014/05/07 14:10:43
I think nobody uses this getter anymore.
perkj_chrome
2014/05/08 11:29:47
no- its used by a few of the classes that inherits
| |
| 463 } | 420 } |
| 464 | 421 |
| 465 void MediaStreamVideoSource::DoStopSource() { | 422 void MediaStreamVideoSource::DoStopSource() { |
| 466 DCHECK(CalledOnValidThread()); | 423 DCHECK(CalledOnValidThread()); |
| 467 DVLOG(3) << "DoStopSource()"; | 424 DVLOG(3) << "DoStopSource()"; |
| 468 if (state_ == ENDED) | 425 if (state_ == ENDED) |
| 469 return; | 426 return; |
| 470 StopSourceImpl(); | 427 StopSourceImpl(); |
| 471 state_ = ENDED; | 428 state_ = ENDED; |
| 472 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); | 429 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); |
| 473 } | 430 } |
| 474 | 431 |
| 475 void MediaStreamVideoSource::OnSupportedFormats( | 432 void MediaStreamVideoSource::OnSupportedFormats( |
| 476 const media::VideoCaptureFormats& formats) { | 433 const media::VideoCaptureFormats& formats) { |
| 477 DCHECK(CalledOnValidThread()); | 434 DCHECK(CalledOnValidThread()); |
| 478 DCHECK_EQ(RETRIEVING_CAPABILITIES, state_); | 435 DCHECK_EQ(RETRIEVING_CAPABILITIES, state_); |
| 479 | 436 |
| 480 supported_formats_ = formats; | 437 supported_formats_ = formats; |
| 481 if (!FindBestFormatWithConstraints(supported_formats_, | 438 if (!FindBestFormatWithConstraints(supported_formats_, |
| 482 ¤t_format_, | 439 ¤t_format_)) { |
| 483 &max_frame_output_size_, | |
| 484 ¤t_constraints_)) { | |
| 485 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); | 440 SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded); |
| 486 // This object can be deleted after calling FinalizeAddTrack. See comment | 441 // This object can be deleted after calling FinalizeAddTrack. See comment |
| 487 // in the header file. | 442 // in the header file. |
| 488 FinalizeAddTrack(); | 443 FinalizeAddTrack(); |
| 489 return; | 444 return; |
| 490 } | 445 } |
| 491 | 446 |
| 492 state_ = STARTING; | 447 state_ = STARTING; |
| 493 DVLOG(3) << "Starting the capturer with" | 448 DVLOG(3) << "Starting the capturer with" |
| 494 << " width = " << current_format_.frame_size.width() | 449 << " width = " << current_format_.frame_size.width() |
| 495 << " height = " << current_format_.frame_size.height() | 450 << " height = " << current_format_.frame_size.height() |
| 496 << " frame rate = " << current_format_.frame_rate; | 451 << " frame rate = " << current_format_.frame_rate; |
| 497 | 452 |
| 498 media::VideoCaptureParams params; | 453 media::VideoCaptureParams params; |
| 499 params.requested_format = current_format_; | 454 params.requested_format = current_format_; |
| 500 StartSourceImpl( | 455 StartSourceImpl( |
| 501 params, | 456 params, |
| 502 base::Bind(&MediaStreamVideoSource::FrameDeliverer::DeliverFrameOnIO, | 457 base::Bind(&VideoTrackAdapter::DeliverFrameOnIO, track_adapter_)); |
| 503 frame_deliverer_)); | |
| 504 } | 458 } |
| 505 | 459 |
| 506 bool MediaStreamVideoSource::FindBestFormatWithConstraints( | 460 bool MediaStreamVideoSource::FindBestFormatWithConstraints( |
| 507 const media::VideoCaptureFormats& formats, | 461 const media::VideoCaptureFormats& formats, |
| 508 media::VideoCaptureFormat* best_format, | 462 media::VideoCaptureFormat* best_format) { |
| 509 gfx::Size* max_frame_output_size, | |
| 510 blink::WebMediaConstraints* resulting_constraints) { | |
| 511 // Find the first constraints that we can fulfill. | 463 // Find the first constraints that we can fulfill. |
| 512 for (std::vector<RequestedConstraints>::iterator request_it = | 464 for (std::vector<RequestedConstraints>::iterator request_it = |
| 513 requested_constraints_.begin(); | 465 requested_constraints_.begin(); |
| 514 request_it != requested_constraints_.end(); ++request_it) { | 466 request_it != requested_constraints_.end(); ++request_it) { |
| 515 const blink::WebMediaConstraints& requested_constraints = | 467 const blink::WebMediaConstraints& requested_constraints = |
| 516 request_it->constraints; | 468 request_it->constraints; |
| 517 | 469 |
| 518 // If the source doesn't support capability enumeration it is still ok if | 470 // If the source doesn't support capability enumeration it is still ok if |
| 519 // no mandatory constraints have been specified. That just means that | 471 // no mandatory constraints have been specified. That just means that |
| 520 // we will start with whatever format is native to the source. | 472 // we will start with whatever format is native to the source. |
| 521 if (formats.empty() && !HasMandatoryConstraints(requested_constraints)) { | 473 if (formats.empty() && !HasMandatoryConstraints(requested_constraints)) { |
| 522 *best_format = media::VideoCaptureFormat(); | 474 *best_format = media::VideoCaptureFormat(); |
| 523 *resulting_constraints = requested_constraints; | |
| 524 *max_frame_output_size = gfx::Size(std::numeric_limits<int>::max(), | |
| 525 std::numeric_limits<int>::max()); | |
| 526 return true; | 475 return true; |
| 527 } | 476 } |
| 528 media::VideoCaptureFormats filtered_formats = | 477 media::VideoCaptureFormats filtered_formats = |
| 529 FilterFormats(requested_constraints, formats); | 478 FilterFormats(requested_constraints, formats); |
| 530 if (filtered_formats.size() > 0) { | 479 if (filtered_formats.size() > 0) { |
| 531 // A request with constraints that can be fulfilled. | 480 // A request with constraints that can be fulfilled. |
| 532 GetBestCaptureFormat(filtered_formats, | 481 GetBestCaptureFormat(filtered_formats, |
| 533 requested_constraints, | 482 requested_constraints, |
| 534 best_format, | 483 best_format); |
| 535 max_frame_output_size); | |
| 536 *resulting_constraints= requested_constraints; | |
| 537 return true; | 484 return true; |
| 538 } | 485 } |
| 539 } | 486 } |
| 540 return false; | 487 return false; |
| 541 } | 488 } |
| 542 | 489 |
| 543 void MediaStreamVideoSource::OnStartDone(bool success) { | 490 void MediaStreamVideoSource::OnStartDone(bool success) { |
| 544 DCHECK(CalledOnValidThread()); | 491 DCHECK(CalledOnValidThread()); |
| 545 DVLOG(3) << "OnStartDone({success =" << success << "})"; | 492 DVLOG(3) << "OnStartDone({success =" << success << "})"; |
| 546 if (success) { | 493 if (success) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 568 it != callbacks.end(); ++it) { | 515 it != callbacks.end(); ++it) { |
| 569 // The track has been added successfully if the source has started and | 516 // The track has been added successfully if the source has started and |
| 570 // there are either no mandatory constraints and the source doesn't expose | 517 // there are either no mandatory constraints and the source doesn't expose |
| 571 // its format capabilities, or the constraints and the format match. | 518 // its format capabilities, or the constraints and the format match. |
| 572 // For example, a remote source doesn't expose its format capabilities. | 519 // For example, a remote source doesn't expose its format capabilities. |
| 573 bool success = | 520 bool success = |
| 574 state_ == STARTED && | 521 state_ == STARTED && |
| 575 ((!current_format_.IsValid() && !HasMandatoryConstraints( | 522 ((!current_format_.IsValid() && !HasMandatoryConstraints( |
| 576 it->constraints)) || | 523 it->constraints)) || |
| 577 !FilterFormats(it->constraints, formats).empty()); | 524 !FilterFormats(it->constraints, formats).empty()); |
| 525 | |
| 578 if (success) { | 526 if (success) { |
| 579 frame_deliverer_->AddCallback(it->track, it->frame_callback, | 527 int max_width = std::numeric_limits<int>::max(); |
| 580 max_frame_output_size_); | 528 int max_height = std::numeric_limits<int>::max(); |
| 529 GetDesiredMaxWidthAndHeight(it->constraints, &max_width, &max_height); | |
|
mcasas
2014/05/07 14:10:43
nit: Inside GetDesiredMaxWidthAndHeight(), |max_wi
perkj_chrome
2014/05/08 11:29:47
done
| |
| 530 double max_aspect_ratio = std::numeric_limits<double>::max(); | |
| 531 double min_aspect_ratio = 0; | |
| 532 GetDesiredMinAndMaxAspectRatio(it->constraints, | |
| 533 &min_aspect_ratio, | |
| 534 &max_aspect_ratio); | |
| 535 track_adapter_->AddTrack(it->track,it->frame_callback, | |
| 536 max_width, max_height, | |
| 537 min_aspect_ratio, max_aspect_ratio); | |
| 581 } | 538 } |
| 539 | |
| 582 DVLOG(3) << "FinalizeAddTrack() success " << success; | 540 DVLOG(3) << "FinalizeAddTrack() success " << success; |
| 541 | |
| 583 if (!it->callback.is_null()) | 542 if (!it->callback.is_null()) |
| 584 it->callback.Run(this, success); | 543 it->callback.Run(this, success); |
| 585 } | 544 } |
| 586 } | 545 } |
| 587 | 546 |
| 588 void MediaStreamVideoSource::SetReadyState( | 547 void MediaStreamVideoSource::SetReadyState( |
| 589 blink::WebMediaStreamSource::ReadyState state) { | 548 blink::WebMediaStreamSource::ReadyState state) { |
| 590 if (!owner().isNull()) { | 549 if (!owner().isNull()) { |
| 591 owner().setReadyState(state); | 550 owner().setReadyState(state); |
| 592 } | 551 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 604 : track(track), | 563 : track(track), |
| 605 frame_callback(frame_callback), | 564 frame_callback(frame_callback), |
| 606 constraints(constraints), | 565 constraints(constraints), |
| 607 callback(callback) { | 566 callback(callback) { |
| 608 } | 567 } |
| 609 | 568 |
| 610 MediaStreamVideoSource::RequestedConstraints::~RequestedConstraints() { | 569 MediaStreamVideoSource::RequestedConstraints::~RequestedConstraints() { |
| 611 } | 570 } |
| 612 | 571 |
| 613 } // namespace content | 572 } // namespace content |
| OLD | NEW |