#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "content/child/child_process.h"
-#include "content/renderer/media/media_stream_dependency_factory.h"
+#include "content/renderer/media/media_stream_constraints_util.h"
#include "content/renderer/media/media_stream_video_track.h"
-#include "content/renderer/media/video_frame_deliverer.h"
-#include "content/renderer/media/webrtc/webrtc_video_capturer_adapter.h"
+#include "content/renderer/media/video_track_adapter.h"
+#include "media/base/bind_to_current_loop.h"
namespace content {
const int MediaStreamVideoSource::kDefaultFrameRate = 30;
namespace {
-// Constraints keys for http://dev.w3.org/2011/webrtc/editor/getusermedia.html
-const char kSourceId[] = "sourceId";
// Google-specific key prefix. Constraints with this prefix are ignored if they
// are unknown.
const char kGooglePrefix[] = "goog";
-// MediaStreamVideoSource supports cropping of video frames but only up to
-// kMaxCropFactor. Ie - if a constraint is set to maxHeight 360, an original
-// input frame height of max 360 * kMaxCropFactor pixels is accepted.
-const int kMaxCropFactor = 2;
+// Returns true if |constraint| has mandatory constraints.
+bool HasMandatoryConstraints(const blink::WebMediaConstraints& constraints) {
+ blink::WebVector<blink::WebMediaConstraint> mandatory_constraints;
+ constraints.getMandatoryConstraints(mandatory_constraints);
+ return !mandatory_constraints.isEmpty();
+}
-// Returns true if |constraint| is fulfilled. |format| can be changed
-// changed by a constraint. Ie - the frame rate can be changed by setting
-// maxFrameRate.
+// Retrieve the desired max width and height from |constraints|. If not set,
+// the |desired_width| and |desired_height| are set to
+// std::numeric_limits<int>::max();
+// If either max width or height is set as a mandatory constraint, the optional
+// constraints are not checked.
+void GetDesiredMaxWidthAndHeight(const blink::WebMediaConstraints& constraints,
+ int* desired_width, int* desired_height) {
+ *desired_width = std::numeric_limits<int>::max();
+ *desired_height = std::numeric_limits<int>::max();
+
+ bool mandatory = GetMandatoryConstraintValueAsInteger(
+ constraints,
+ MediaStreamVideoSource::kMaxWidth,
+ desired_width);
+ mandatory |= GetMandatoryConstraintValueAsInteger(
+ constraints,
+ MediaStreamVideoSource::kMaxHeight,
+ desired_height);
+ if (mandatory)
+ return;
+
+ GetOptionalConstraintValueAsInteger(constraints,
+ MediaStreamVideoSource::kMaxWidth,
+ desired_width);
+ GetOptionalConstraintValueAsInteger(constraints,
+ MediaStreamVideoSource::kMaxHeight,
+ desired_height);
+}
+
+// Retrieve the desired max and min aspect ratio from |constraints|. If not set,
+// the |min_aspect_ratio| is set to 0 and |max_aspect_ratio| is set to
+// std::numeric_limits<double>::max();
+// If either min or max aspect ratio is set as a mandatory constraint, the
+// optional constraints are not checked.
+void GetDesiredMinAndMaxAspectRatio(
+ const blink::WebMediaConstraints& constraints,
+ double* min_aspect_ratio,
+ double* max_aspect_ratio) {
+ *min_aspect_ratio = 0;
+ *max_aspect_ratio = std::numeric_limits<double>::max();
+
+ bool mandatory = GetMandatoryConstraintValueAsDouble(
+ constraints,
+ MediaStreamVideoSource::kMinAspectRatio,
+ min_aspect_ratio);
+ mandatory |= GetMandatoryConstraintValueAsDouble(
+ constraints,
+ MediaStreamVideoSource::kMaxAspectRatio,
+ max_aspect_ratio);
+ if (mandatory)
+ return;
+
+ GetOptionalConstraintValueAsDouble(
+ constraints,
+ MediaStreamVideoSource::kMinAspectRatio,
+ min_aspect_ratio);
+ GetOptionalConstraintValueAsDouble(
+ constraints,
+ MediaStreamVideoSource::kMaxAspectRatio,
+ max_aspect_ratio);
+}
+
+// Returns true if |constraint| is fulfilled. |format| can be changed by a
+// constraint, e.g. the frame rate can be changed by setting maxFrameRate.
bool UpdateFormatForConstraint(
const blink::WebMediaConstraint& constraint,
bool mandatory,
return true;
}
- if (constraint_name == kSourceId) {
+ if (constraint_name == MediaStreamSource::kSourceId) {
// This is a constraint that doesn't affect the format.
return true;
}
if (constraint_name == MediaStreamVideoSource::kMinAspectRatio ||
constraint_name == MediaStreamVideoSource::kMaxAspectRatio) {
- double double_value = 0;
- base::StringToDouble(constraint_value, &double_value);
-
- // The aspect ratio in |constraint.m_value| has been converted to a string
- // and back to a double, so it may have a rounding error.
- // E.g if the value 1/3 is converted to a string, the string will not have
- // infinite length.
- // We add a margin of 0.0005 which is high enough to detect the same aspect
- // ratio but small enough to avoid matching wrong aspect ratios.
- const double kRoundingTruncation = 0.0005;
- double ratio = static_cast<double>(format->frame_size.width()) /
- format->frame_size.height();
- if (constraint_name == MediaStreamVideoSource::kMinAspectRatio)
- return (double_value <= ratio + kRoundingTruncation);
- // Subtract 0.0005 to avoid rounding problems. Same as above.
- return (double_value >= ratio - kRoundingTruncation);
+ // These constraints are handled by cropping if the camera outputs the wrong
+ // aspect ratio.
+ double value;
+ return base::StringToDouble(constraint_value, &value);
}
- int value;
- if (!base::StringToInt(constraint_value, &value)) {
+ double value = 0.0;
+ if (!base::StringToDouble(constraint_value, &value)) {
DLOG(WARNING) << "Can't parse MediaStream constraint. Name:"
<< constraint_name << " Value:" << constraint_value;
return false;
}
+
if (constraint_name == MediaStreamVideoSource::kMinWidth) {
return (value <= format->frame_size.width());
} else if (constraint_name == MediaStreamVideoSource::kMaxWidth) {
- return (value * kMaxCropFactor >= format->frame_size.width());
+ return value > 0.0;
} else if (constraint_name == MediaStreamVideoSource::kMinHeight) {
return (value <= format->frame_size.height());
} else if (constraint_name == MediaStreamVideoSource::kMaxHeight) {
- return (value * kMaxCropFactor >= format->frame_size.height());
+ return value > 0.0;
} else if (constraint_name == MediaStreamVideoSource::kMinFrameRate) {
- return (value <= format->frame_rate);
+ return (value > 0.0) && (value <= format->frame_rate);
} else if (constraint_name == MediaStreamVideoSource::kMaxFrameRate) {
- if (value == 0) {
+ if (value <= 0.0) {
// The frame rate is set by constraint.
// Don't allow 0 as frame rate if it is a mandatory constraint.
// Set the frame rate to 1 if it is not mandatory.
if (mandatory) {
return false;
} else {
- value = 1;
+ value = 1.0;
}
}
format->frame_rate =
// Returns the media::VideoCaptureFormats that matches |constraints|.
media::VideoCaptureFormats FilterFormats(
const blink::WebMediaConstraints& constraints,
- const media::VideoCaptureFormats& supported_formats) {
+ const media::VideoCaptureFormats& supported_formats,
+ blink::WebString* unsatisfied_constraint) {
if (constraints.isNull()) {
return supported_formats;
}
+ double max_aspect_ratio;
+ double min_aspect_ratio;
+ GetDesiredMinAndMaxAspectRatio(constraints,
+ &min_aspect_ratio,
+ &max_aspect_ratio);
+
+ if (min_aspect_ratio > max_aspect_ratio || max_aspect_ratio < 0.05f) {
+ DLOG(WARNING) << "Wrong requested aspect ratio.";
+ return media::VideoCaptureFormats();
+ }
+
+ int min_width = 0;
+ GetMandatoryConstraintValueAsInteger(constraints,
+ MediaStreamVideoSource::kMinWidth,
+ &min_width);
+ int min_height = 0;
+ GetMandatoryConstraintValueAsInteger(constraints,
+ MediaStreamVideoSource::kMinHeight,
+ &min_height);
+ int max_width;
+ int max_height;
+ GetDesiredMaxWidthAndHeight(constraints, &max_width, &max_height);
+
+ if (min_width > max_width || min_height > max_height)
+ return media::VideoCaptureFormats();
+
+ double min_frame_rate = 0.0f;
+ double max_frame_rate = 0.0f;
+ if (GetConstraintValueAsDouble(constraints,
+ MediaStreamVideoSource::kMaxFrameRate,
+ &max_frame_rate) &&
+ GetConstraintValueAsDouble(constraints,
+ MediaStreamVideoSource::kMinFrameRate,
+ &min_frame_rate)) {
+ if (min_frame_rate > max_frame_rate) {
+ DLOG(WARNING) << "Wrong requested frame rate.";
+ return media::VideoCaptureFormats();
+ }
+ }
+
blink::WebVector<blink::WebMediaConstraint> mandatory;
blink::WebVector<blink::WebMediaConstraint> optional;
constraints.getMandatoryConstraints(mandatory);
constraints.getOptionalConstraints(optional);
-
media::VideoCaptureFormats candidates = supported_formats;
-
- for (size_t i = 0; i < mandatory.size(); ++i)
+ for (size_t i = 0; i < mandatory.size(); ++i) {
FilterFormatsByConstraint(mandatory[i], true, &candidates);
+ if (candidates.empty()) {
+ *unsatisfied_constraint = mandatory[i].m_name;
+ return candidates;
+ }
+ }
if (candidates.empty())
return candidates;
return candidates;
}
-bool GetConstraintValue(const blink::WebMediaConstraints& constraints,
- bool mandatory, const blink::WebString& name,
- int* value) {
- blink::WebString value_str;
- bool ret = mandatory ?
- constraints.getMandatoryConstraintValue(name, value_str) :
- constraints.getOptionalConstraintValue(name, value_str);
- if (ret)
- base::StringToInt(value_str.utf8(), value);
- return ret;
-}
-
-// Returns true if |constraint| has mandatory constraints.
-bool HasMandatoryConstraints(const blink::WebMediaConstraints& constraints) {
- blink::WebVector<blink::WebMediaConstraint> mandatory_constraints;
- constraints.getMandatoryConstraints(mandatory_constraints);
- return !mandatory_constraints.isEmpty();
-}
-
-// Retrieve the desired max width and height from |constraints|.
-void GetDesiredMaxWidthAndHeight(const blink::WebMediaConstraints& constraints,
- int* desired_width, int* desired_height) {
- bool mandatory = GetConstraintValue(constraints, true,
- MediaStreamVideoSource::kMaxWidth,
- desired_width);
- mandatory |= GetConstraintValue(constraints, true,
- MediaStreamVideoSource::kMaxHeight,
- desired_height);
- if (mandatory)
- return;
-
- GetConstraintValue(constraints, false, MediaStreamVideoSource::kMaxWidth,
- desired_width);
- GetConstraintValue(constraints, false, MediaStreamVideoSource::kMaxHeight,
- desired_height);
-}
-
const media::VideoCaptureFormat& GetBestFormatBasedOnArea(
const media::VideoCaptureFormats& formats,
int area) {
void GetBestCaptureFormat(
const media::VideoCaptureFormats& formats,
const blink::WebMediaConstraints& constraints,
- media::VideoCaptureFormat* capture_format,
- gfx::Size* max_frame_output_size) {
+ media::VideoCaptureFormat* capture_format) {
DCHECK(!formats.empty());
- DCHECK(max_frame_output_size);
- int max_width = std::numeric_limits<int>::max();
- int max_height = std::numeric_limits<int>::max();;
+ int max_width;
+ int max_height;
GetDesiredMaxWidthAndHeight(constraints, &max_width, &max_height);
*capture_format = GetBestFormatBasedOnArea(
formats,
std::min(max_width, MediaStreamVideoSource::kDefaultWidth) *
std::min(max_height, MediaStreamVideoSource::kDefaultHeight));
-
- max_frame_output_size->set_width(max_width);
- max_frame_output_size->set_height(max_height);
-}
-
-// Empty method used for keeping a reference to the original media::VideoFrame
-// in MediaStreamVideoSource::FrameDeliverer::DeliverFrameOnIO if cropping is
-// needed. The reference to |frame| is kept in the closure that calls this
-// method.
-void ReleaseOriginalFrame(
- const scoped_refptr<media::VideoFrame>& frame) {
}
} // anonymous namespace
-// Helper class used for delivering video frames to all registered tracks
-// on the IO-thread.
-class MediaStreamVideoSource::FrameDeliverer : public VideoFrameDeliverer {
- public:
- FrameDeliverer(
- const scoped_refptr<base::MessageLoopProxy>& io_message_loop)
- : VideoFrameDeliverer(io_message_loop) {
- }
-
- // Register |callback| to receive video frames of max size
- // |max_frame_output_size| on the IO thread.
- // TODO(perkj): Currently |max_frame_output_size| must be the same for all
- // |callbacks|.
- void AddCallback(void* id,
- const VideoCaptureDeliverFrameCB& callback,
- const gfx::Size& max_frame_output_size) {
- DCHECK(thread_checker().CalledOnValidThread());
- io_message_loop()->PostTask(
- FROM_HERE,
- base::Bind(
- &FrameDeliverer::AddCallbackWithResolutionOnIO,
- this, id, callback, max_frame_output_size));
- }
-
- virtual void DeliverFrameOnIO(
- const scoped_refptr<media::VideoFrame>& frame,
- const media::VideoCaptureFormat& format) OVERRIDE {
- DCHECK(io_message_loop()->BelongsToCurrentThread());
- TRACE_EVENT0("video", "MediaStreamVideoSource::DeliverFrameOnIO");
- if (max_output_size_.IsEmpty())
- return; // Frame received before the output has been decided.
-
- scoped_refptr<media::VideoFrame> video_frame(frame);
- const gfx::Size& visible_size = frame->visible_rect().size();
- if (visible_size.width() > max_output_size_.width() ||
- visible_size.height() > max_output_size_.height()) {
- // If |frame| is not the size that is expected, we need to crop it by
- // providing a new |visible_rect|. The new visible rect must be within the
- // original |visible_rect|.
- gfx::Rect output_rect = frame->visible_rect();
- output_rect.ClampToCenteredSize(max_output_size_);
- // TODO(perkj): Allow cropping of textures once http://crbug/362521 is
- // fixed.
- if (frame->format() != media::VideoFrame::NATIVE_TEXTURE) {
- video_frame = media::VideoFrame::WrapVideoFrame(
- frame,
- output_rect,
- output_rect.size(),
- base::Bind(&ReleaseOriginalFrame, frame));
- }
- }
- VideoFrameDeliverer::DeliverFrameOnIO(video_frame, format);
- }
-
- protected:
- virtual ~FrameDeliverer() {
- }
-
- void AddCallbackWithResolutionOnIO(
- void* id,
- const VideoCaptureDeliverFrameCB& callback,
- const gfx::Size& max_frame_output_size) {
- DCHECK(io_message_loop()->BelongsToCurrentThread());
- // Currently we only support one frame output size.
- DCHECK(!max_frame_output_size.IsEmpty() &&
- (max_output_size_.IsEmpty() ||
- max_output_size_ == max_frame_output_size));
- max_output_size_ = max_frame_output_size;
- VideoFrameDeliverer::AddCallbackOnIO(id, callback);
- }
-
- private:
- gfx::Size max_output_size_;
-};
-
// static
MediaStreamVideoSource* MediaStreamVideoSource::GetVideoSource(
const blink::WebMediaStreamSource& source) {
MediaStreamVideoSource::MediaStreamVideoSource()
: state_(NEW),
- frame_deliverer_(
- new MediaStreamVideoSource::FrameDeliverer(
- ChildProcess::current()->io_message_loop_proxy())),
+ muted_state_(false),
+ track_adapter_(new VideoTrackAdapter(
+ ChildProcess::current()->io_message_loop_proxy())),
weak_factory_(this) {
}
MediaStreamVideoSource::~MediaStreamVideoSource() {
- DVLOG(3) << "~MediaStreamVideoSource()";
+ DCHECK(CalledOnValidThread());
}
void MediaStreamVideoSource::AddTrack(
const blink::WebMediaConstraints& constraints,
const ConstraintsCallback& callback) {
DCHECK(CalledOnValidThread());
+ DCHECK(!constraints.isNull());
DCHECK(std::find(tracks_.begin(), tracks_.end(),
track) == tracks_.end());
tracks_.push_back(track);
// Tab capture and Screen capture needs the maximum requested height
// and width to decide on the resolution.
int max_requested_width = 0;
- GetConstraintValue(constraints, true, kMaxWidth, &max_requested_width);
+ GetMandatoryConstraintValueAsInteger(constraints, kMaxWidth,
+ &max_requested_width);
int max_requested_height = 0;
- GetConstraintValue(constraints, true, kMaxHeight, &max_requested_height);
+ GetMandatoryConstraintValueAsInteger(constraints, kMaxHeight,
+ &max_requested_height);
+
+ double max_requested_frame_rate;
+ if (!GetConstraintValueAsDouble(constraints, kMaxFrameRate,
+ &max_requested_frame_rate)) {
+ max_requested_frame_rate = kDefaultFrameRate;
+ }
state_ = RETRIEVING_CAPABILITIES;
GetCurrentSupportedFormats(
max_requested_width,
max_requested_height,
+ max_requested_frame_rate,
base::Bind(&MediaStreamVideoSource::OnSupportedFormats,
weak_factory_.GetWeakPtr()));
std::find(tracks_.begin(), tracks_.end(), video_track);
DCHECK(it != tracks_.end());
tracks_.erase(it);
- // Call |RemoveCallback| here even if adding the track has failed and
- // frame_deliverer_->AddCallback has not been called.
- frame_deliverer_->RemoveCallback(video_track);
+
+ // Check if |video_track| is waiting for applying new constraints and remove
+ // the request in that case.
+ for (std::vector<RequestedConstraints>::iterator it =
+ requested_constraints_.begin();
+ it != requested_constraints_.end(); ++it) {
+ if (it->track == video_track) {
+ requested_constraints_.erase(it);
+ break;
+ }
+ }
+ // Call |frame_adapter_->RemoveTrack| here even if adding the track has
+ // failed and |frame_adapter_->AddCallback| has not been called.
+ track_adapter_->RemoveTrack(video_track);
if (tracks_.empty())
StopSource();
const scoped_refptr<base::MessageLoopProxy>&
MediaStreamVideoSource::io_message_loop() const {
- return frame_deliverer_->io_message_loop();
+ DCHECK(CalledOnValidThread());
+ return track_adapter_->io_message_loop();
}
void MediaStreamVideoSource::DoStopSource() {
supported_formats_ = formats;
if (!FindBestFormatWithConstraints(supported_formats_,
- ¤t_format_,
- &max_frame_output_size_,
- ¤t_constraints_)) {
+ ¤t_format_)) {
SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
// This object can be deleted after calling FinalizeAddTrack. See comment
// in the header file.
DVLOG(3) << "Starting the capturer with"
<< " width = " << current_format_.frame_size.width()
<< " height = " << current_format_.frame_size.height()
- << " frame rate = " << current_format_.frame_rate;
+ << " frame rate = " << current_format_.frame_rate
+ << " pixel format = "
+ << media::VideoCaptureFormat::PixelFormatToString(
+ current_format_.pixel_format);
media::VideoCaptureParams params;
params.requested_format = current_format_;
StartSourceImpl(
params,
- base::Bind(&MediaStreamVideoSource::FrameDeliverer::DeliverFrameOnIO,
- frame_deliverer_));
+ base::Bind(&VideoTrackAdapter::DeliverFrameOnIO, track_adapter_));
}
bool MediaStreamVideoSource::FindBestFormatWithConstraints(
const media::VideoCaptureFormats& formats,
- media::VideoCaptureFormat* best_format,
- gfx::Size* max_frame_output_size,
- blink::WebMediaConstraints* resulting_constraints) {
+ media::VideoCaptureFormat* best_format) {
+ DCHECK(CalledOnValidThread());
// Find the first constraints that we can fulfill.
for (std::vector<RequestedConstraints>::iterator request_it =
requested_constraints_.begin();
// we will start with whatever format is native to the source.
if (formats.empty() && !HasMandatoryConstraints(requested_constraints)) {
*best_format = media::VideoCaptureFormat();
- *resulting_constraints = requested_constraints;
- *max_frame_output_size = gfx::Size(std::numeric_limits<int>::max(),
- std::numeric_limits<int>::max());
return true;
}
+ blink::WebString unsatisfied_constraint;
media::VideoCaptureFormats filtered_formats =
- FilterFormats(requested_constraints, formats);
+ FilterFormats(requested_constraints, formats, &unsatisfied_constraint);
if (filtered_formats.size() > 0) {
// A request with constraints that can be fulfilled.
GetBestCaptureFormat(filtered_formats,
requested_constraints,
- best_format,
- max_frame_output_size);
- *resulting_constraints= requested_constraints;
+ best_format);
return true;
}
}
return false;
}
-void MediaStreamVideoSource::OnStartDone(bool success) {
+void MediaStreamVideoSource::OnStartDone(MediaStreamRequestResult result) {
DCHECK(CalledOnValidThread());
- DVLOG(3) << "OnStartDone({success =" << success << "})";
- if (success) {
+ DVLOG(3) << "OnStartDone({result =" << result << "})";
+ if (result == MEDIA_DEVICE_OK) {
DCHECK_EQ(STARTING, state_);
state_ = STARTED;
SetReadyState(blink::WebMediaStreamSource::ReadyStateLive);
} else {
- state_ = ENDED;
- SetReadyState(blink::WebMediaStreamSource::ReadyStateEnded);
- StopSourceImpl();
+ StopSource();
}
// This object can be deleted after calling FinalizeAddTrack. See comment in
}
void MediaStreamVideoSource::FinalizeAddTrack() {
+ DCHECK(CalledOnValidThread());
media::VideoCaptureFormats formats;
formats.push_back(current_format_);
callbacks.swap(requested_constraints_);
for (std::vector<RequestedConstraints>::iterator it = callbacks.begin();
it != callbacks.end(); ++it) {
- // The track has been added successfully if the source has started and
- // there are either no mandatory constraints and the source doesn't expose
- // its format capabilities, or the constraints and the format match.
- // For example, a remote source doesn't expose its format capabilities.
- bool success =
- state_ == STARTED &&
- ((!current_format_.IsValid() && !HasMandatoryConstraints(
- it->constraints)) ||
- !FilterFormats(it->constraints, formats).empty());
- if (success) {
- frame_deliverer_->AddCallback(it->track, it->frame_callback,
- max_frame_output_size_);
+ MediaStreamRequestResult result = MEDIA_DEVICE_OK;
+ blink::WebString unsatisfied_constraint;
+
+ if (HasMandatoryConstraints(it->constraints) &&
+ FilterFormats(it->constraints, formats,
+ &unsatisfied_constraint).empty())
+ result = MEDIA_DEVICE_CONSTRAINT_NOT_SATISFIED;
+
+ if (state_ != STARTED && result == MEDIA_DEVICE_OK)
+ result = MEDIA_DEVICE_TRACK_START_FAILURE;
+
+ if (result == MEDIA_DEVICE_OK) {
+ int max_width;
+ int max_height;
+ GetDesiredMaxWidthAndHeight(it->constraints, &max_width, &max_height);
+ double max_aspect_ratio;
+ double min_aspect_ratio;
+ GetDesiredMinAndMaxAspectRatio(it->constraints,
+ &min_aspect_ratio,
+ &max_aspect_ratio);
+ double max_frame_rate = 0.0f;
+ GetConstraintValueAsDouble(it->constraints,
+ kMaxFrameRate, &max_frame_rate);
+
+ VideoTrackAdapter::OnMutedCallback on_mute_callback =
+ media::BindToCurrentLoop(base::Bind(
+ &MediaStreamVideoSource::SetMutedState,
+ weak_factory_.GetWeakPtr()));
+ track_adapter_->AddTrack(it->track, it->frame_callback,
+ max_width, max_height,
+ min_aspect_ratio, max_aspect_ratio,
+ max_frame_rate, current_format_.frame_rate,
+ on_mute_callback);
+ }
+
+ DVLOG(3) << "FinalizeAddTrack() result " << result;
+
+ if (!it->callback.is_null()) {
+ it->callback.Run(this, result, unsatisfied_constraint);
}
- DVLOG(3) << "FinalizeAddTrack() success " << success;
- if (!it->callback.is_null())
- it->callback.Run(this, success);
}
}
void MediaStreamVideoSource::SetReadyState(
blink::WebMediaStreamSource::ReadyState state) {
+ DVLOG(3) << "MediaStreamVideoSource::SetReadyState state " << state;
+ DCHECK(CalledOnValidThread());
if (!owner().isNull()) {
owner().setReadyState(state);
}
}
}
+void MediaStreamVideoSource::SetMutedState(bool muted_state) {
+ DVLOG(3) << "MediaStreamVideoSource::SetMutedState state=" << muted_state;
+ DCHECK(CalledOnValidThread());
+ // WebMediaStreamSource doesn't have a muted state, the tracks do.
+ for (std::vector<MediaStreamVideoTrack*>::iterator it = tracks_.begin();
+ it != tracks_.end(); ++it) {
+ (*it)->SetMutedState(muted_state);
+ }
+}
+
MediaStreamVideoSource::RequestedConstraints::RequestedConstraints(
MediaStreamVideoTrack* track,
const VideoCaptureDeliverFrameCB& frame_callback,