From e1d9a4a2c9ed13312a667a62bfbe32b058762ff5 Mon Sep 17 00:00:00 2001 From: perkj Date: Tue, 8 Mar 2016 01:51:43 +0100 Subject: [PATCH] i# Enter a description of the change. Remove implementation in videosource.cc It should have been part of https://codereview.webrtc.org/1770003002/.... TBR=pthatcher@webrtc.org BUG=webrtc:5621 Review URL: https://codereview.webrtc.org/1767373002 . Cr-Commit-Position: refs/heads/master@{#11894} --- webrtc/api/videosource.cc | 432 +------------------------------------- 1 file changed, 1 insertion(+), 431 deletions(-) diff --git a/webrtc/api/videosource.cc b/webrtc/api/videosource.cc index 445b92de52..08e5422aae 100644 --- a/webrtc/api/videosource.cc +++ b/webrtc/api/videosource.cc @@ -8,434 +8,4 @@ * be found in the AUTHORS file in the root of the source tree. */ -#include "webrtc/api/videosource.h" - -#include -#include -#include - -#include "webrtc/api/mediaconstraintsinterface.h" -#include "webrtc/base/arraysize.h" - -using cricket::CaptureState; -using webrtc::MediaConstraintsInterface; -using webrtc::MediaSourceInterface; - -namespace { - -const double kRoundingTruncation = 0.0005; - -// Default resolution. If no constraint is specified, this is the resolution we -// will use. -static const cricket::VideoFormatPod kDefaultFormat = - {640, 480, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}; - -// List of formats used if the camera doesn't support capability enumeration. -static const cricket::VideoFormatPod kVideoFormats[] = { - {1920, 1080, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, - {1280, 720, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, - {960, 720, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, - {640, 360, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, - {640, 480, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, - {320, 240, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, - {320, 180, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY} -}; - -MediaSourceInterface::SourceState -GetReadyState(cricket::CaptureState state) { - switch (state) { - case cricket::CS_STARTING: - return MediaSourceInterface::kInitializing; - case cricket::CS_RUNNING: - return MediaSourceInterface::kLive; - case cricket::CS_FAILED: - case cricket::CS_STOPPED: - return MediaSourceInterface::kEnded; - case cricket::CS_PAUSED: - return MediaSourceInterface::kMuted; - default: - ASSERT(false && "GetReadyState unknown state"); - } - return MediaSourceInterface::kEnded; -} - -void SetUpperLimit(int new_limit, int* original_limit) { - if (*original_limit < 0 || new_limit < *original_limit) - *original_limit = new_limit; -} - -// Updates |format_upper_limit| from |constraint|. -// If constraint.maxFoo is smaller than format_upper_limit.foo, -// set format_upper_limit.foo to constraint.maxFoo. -void SetUpperLimitFromConstraint( - const MediaConstraintsInterface::Constraint& constraint, - cricket::VideoFormat* format_upper_limit) { - if (constraint.key == MediaConstraintsInterface::kMaxWidth) { - int value = rtc::FromString(constraint.value); - SetUpperLimit(value, &(format_upper_limit->width)); - } else if (constraint.key == MediaConstraintsInterface::kMaxHeight) { - int value = rtc::FromString(constraint.value); - SetUpperLimit(value, &(format_upper_limit->height)); - } -} - -// Fills |format_out| with the max width and height allowed by |constraints|. -void FromConstraintsForScreencast( - const MediaConstraintsInterface::Constraints& constraints, - cricket::VideoFormat* format_out) { - typedef MediaConstraintsInterface::Constraints::const_iterator - ConstraintsIterator; - - cricket::VideoFormat upper_limit(-1, -1, 0, 0); - for (ConstraintsIterator constraints_it = constraints.begin(); - constraints_it != constraints.end(); ++constraints_it) - SetUpperLimitFromConstraint(*constraints_it, &upper_limit); - - if (upper_limit.width >= 0) - format_out->width = upper_limit.width; - if (upper_limit.height >= 0) - format_out->height = upper_limit.height; -} - -// Returns true if |constraint| is fulfilled. |format_out| can differ from -// |format_in| if the format is changed by the constraint. Ie - the frame rate -// can be changed by setting maxFrameRate. -bool NewFormatWithConstraints( - const MediaConstraintsInterface::Constraint& constraint, - const cricket::VideoFormat& format_in, - bool mandatory, - cricket::VideoFormat* format_out) { - ASSERT(format_out != NULL); - *format_out = format_in; - - if (constraint.key == MediaConstraintsInterface::kMinWidth) { - int value = rtc::FromString(constraint.value); - return (value <= format_in.width); - } else if (constraint.key == MediaConstraintsInterface::kMaxWidth) { - int value = rtc::FromString(constraint.value); - return (value >= format_in.width); - } else if (constraint.key == MediaConstraintsInterface::kMinHeight) { - int value = rtc::FromString(constraint.value); - return (value <= format_in.height); - } else if (constraint.key == MediaConstraintsInterface::kMaxHeight) { - int value = rtc::FromString(constraint.value); - return (value >= format_in.height); - } else if (constraint.key == MediaConstraintsInterface::kMinFrameRate) { - int value = rtc::FromString(constraint.value); - return (value <= cricket::VideoFormat::IntervalToFps(format_in.interval)); - } else if (constraint.key == MediaConstraintsInterface::kMaxFrameRate) { - int value = rtc::FromString(constraint.value); - if (value == 0) { - if (mandatory) { - // TODO(ronghuawu): Convert the constraint value to float when sub-1fps - // is supported by the capturer. - return false; - } else { - value = 1; - } - } - if (value <= cricket::VideoFormat::IntervalToFps(format_in.interval)) - format_out->interval = cricket::VideoFormat::FpsToInterval(value); - return true; - } else if (constraint.key == MediaConstraintsInterface::kMinAspectRatio) { - double value = rtc::FromString(constraint.value); - // The aspect ratio in |constraint.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. - double ratio = static_cast(format_in.width) / format_in.height; - return (value <= ratio + kRoundingTruncation); - } else if (constraint.key == MediaConstraintsInterface::kMaxAspectRatio) { - double value = rtc::FromString(constraint.value); - double ratio = static_cast(format_in.width) / format_in.height; - // Subtract 0.0005 to avoid rounding problems. Same as above. - const double kRoundingTruncation = 0.0005; - return (value >= ratio - kRoundingTruncation); - } else if (constraint.key == MediaConstraintsInterface::kNoiseReduction) { - // These are actually options, not constraints, so they can be satisfied - // regardless of the format. - return true; - } - LOG(LS_WARNING) << "Found unknown MediaStream constraint. Name:" - << constraint.key << " Value:" << constraint.value; - return false; -} - -// Removes cricket::VideoFormats from |formats| that don't meet |constraint|. -void FilterFormatsByConstraint( - const MediaConstraintsInterface::Constraint& constraint, - bool mandatory, - std::vector* formats) { - std::vector::iterator format_it = - formats->begin(); - while (format_it != formats->end()) { - // Modify the format_it to fulfill the constraint if possible. - // Delete it otherwise. - if (!NewFormatWithConstraints(constraint, (*format_it), - mandatory, &(*format_it))) { - format_it = formats->erase(format_it); - } else { - ++format_it; - } - } -} - -// Returns a vector of cricket::VideoFormat that best match |constraints|. -std::vector FilterFormats( - const MediaConstraintsInterface::Constraints& mandatory, - const MediaConstraintsInterface::Constraints& optional, - const std::vector& supported_formats) { - typedef MediaConstraintsInterface::Constraints::const_iterator - ConstraintsIterator; - std::vector candidates = supported_formats; - - for (ConstraintsIterator constraints_it = mandatory.begin(); - constraints_it != mandatory.end(); ++constraints_it) - FilterFormatsByConstraint(*constraints_it, true, &candidates); - - if (candidates.size() == 0) - return candidates; - - // Ok - all mandatory checked and we still have a candidate. - // Let's try filtering using the optional constraints. - for (ConstraintsIterator constraints_it = optional.begin(); - constraints_it != optional.end(); ++constraints_it) { - std::vector current_candidates = candidates; - FilterFormatsByConstraint(*constraints_it, false, ¤t_candidates); - if (current_candidates.size() > 0) { - candidates = current_candidates; - } - } - - // We have done as good as we can to filter the supported resolutions. - return candidates; -} - -// Find the format that best matches the default video size. -// Constraints are optional and since the performance of a video call -// might be bad due to bitrate limitations, CPU, and camera performance, -// it is better to select a resolution that is as close as possible to our -// default and still meets the contraints. -const cricket::VideoFormat& GetBestCaptureFormat( - const std::vector& formats) { - ASSERT(formats.size() > 0); - - int default_area = kDefaultFormat.width * kDefaultFormat.height; - - std::vector::const_iterator it = formats.begin(); - std::vector::const_iterator best_it = formats.begin(); - int best_diff_area = std::abs(default_area - it->width * it->height); - int64_t best_diff_interval = kDefaultFormat.interval; - for (; it != formats.end(); ++it) { - int diff_area = std::abs(default_area - it->width * it->height); - int64_t diff_interval = std::abs(kDefaultFormat.interval - it->interval); - if (diff_area < best_diff_area || - (diff_area == best_diff_area && diff_interval < best_diff_interval)) { - best_diff_area = diff_area; - best_diff_interval = diff_interval; - best_it = it; - } - } - return *best_it; -} - -// Set |option| to the highest-priority value of |key| in the constraints. -// Return false if the key is mandatory, and the value is invalid. -bool ExtractOption(const MediaConstraintsInterface* all_constraints, - const std::string& key, - rtc::Optional* option) { - size_t mandatory = 0; - bool value; - if (FindConstraint(all_constraints, key, &value, &mandatory)) { - *option = rtc::Optional(value); - return true; - } - - return mandatory == 0; -} - -// Search |all_constraints| for known video options. Apply all options that are -// found with valid values, and return false if any mandatory video option was -// found with an invalid value. -bool ExtractVideoOptions(const MediaConstraintsInterface* all_constraints, - cricket::VideoOptions* options) { - bool all_valid = true; - - all_valid &= ExtractOption(all_constraints, - MediaConstraintsInterface::kNoiseReduction, - &(options->video_noise_reduction)); - - return all_valid; -} - -} // anonymous namespace - -namespace webrtc { - -rtc::scoped_refptr VideoSource::Create( - rtc::Thread* worker_thread, - cricket::VideoCapturer* capturer, - const webrtc::MediaConstraintsInterface* constraints, - bool remote) { - RTC_DCHECK(worker_thread != NULL); - RTC_DCHECK(capturer != NULL); - rtc::scoped_refptr source(new rtc::RefCountedObject( - worker_thread, capturer, remote)); - source->Initialize(constraints); - return source; -} - -rtc::scoped_refptr VideoSource::Create( - rtc::Thread* worker_thread, - cricket::VideoCapturer* capturer, - bool remote) { - return Create(worker_thread, capturer, nullptr, remote); -} - -VideoSource::VideoSource(rtc::Thread* worker_thread, - cricket::VideoCapturer* capturer, - bool remote) - : signaling_thread_(rtc::Thread::Current()), - worker_thread_(worker_thread), - video_capturer_(capturer), - started_(false), - state_(kInitializing), - remote_(remote) { - video_capturer_->SignalStateChange.connect( - this, &VideoSource::OnStateChange); -} - -VideoSource::~VideoSource() { - video_capturer_->SignalStateChange.disconnect(this); - Stop(); -} - -void VideoSource::Initialize( - const webrtc::MediaConstraintsInterface* constraints) { - std::vector formats = - *video_capturer_->GetSupportedFormats(); - if (formats.empty()) { - if (video_capturer_->IsScreencast()) { - // The screen capturer can accept any resolution and we will derive the - // format from the constraints if any. - // Note that this only affects tab capturing, not desktop capturing, - // since the desktop capturer does not respect the VideoFormat passed in. - formats.push_back(cricket::VideoFormat(kDefaultFormat)); - } else { - // The VideoCapturer implementation doesn't support capability - // enumeration. We need to guess what the camera supports. - for (int i = 0; i < arraysize(kVideoFormats); ++i) { - formats.push_back(cricket::VideoFormat(kVideoFormats[i])); - } - } - } - - if (constraints) { - MediaConstraintsInterface::Constraints mandatory_constraints = - constraints->GetMandatory(); - MediaConstraintsInterface::Constraints optional_constraints; - optional_constraints = constraints->GetOptional(); - - if (video_capturer_->IsScreencast()) { - // Use the maxWidth and maxHeight allowed by constraints for screencast. - FromConstraintsForScreencast(mandatory_constraints, &(formats[0])); - } - - formats = FilterFormats(mandatory_constraints, optional_constraints, - formats); - } - - if (formats.size() == 0) { - LOG(LS_WARNING) << "Failed to find a suitable video format."; - SetState(kEnded); - return; - } - - cricket::VideoOptions options; - if (!ExtractVideoOptions(constraints, &options)) { - LOG(LS_WARNING) << "Could not satisfy mandatory options."; - SetState(kEnded); - return; - } - options_.SetAll(options); - options_.is_screencast = rtc::Optional(video_capturer_->IsScreencast()); - - format_ = GetBestCaptureFormat(formats); - // Start the camera with our best guess. - // TODO(perkj): Should we try again with another format it it turns out that - // the camera doesn't produce frames with the correct format? Or will - // cricket::VideCapturer be able to re-scale / crop to the requested - // resolution? - if (!worker_thread_->Invoke( - rtc::Bind(&cricket::VideoCapturer::StartCapturing, - video_capturer_.get(), format_))) { - SetState(kEnded); - return; - } - started_ = true; - // Initialize hasn't succeeded until a successful state change has occurred. -} - -void VideoSource::Stop() { - if (!started_) { - return; - } - started_ = false; - worker_thread_->Invoke( - rtc::Bind(&cricket::VideoCapturer::Stop, - video_capturer_.get())); -} - -void VideoSource::Restart() { - if (started_) { - return; - } - if (!worker_thread_->Invoke( - rtc::Bind(&cricket::VideoCapturer::StartCapturing, - video_capturer_.get(), format_))) { - SetState(kEnded); - return; - } - started_ = true; -} - -void VideoSource::AddOrUpdateSink( - rtc::VideoSinkInterface* sink, - const rtc::VideoSinkWants& wants) { - worker_thread_->Invoke( - rtc::Bind(&cricket::VideoCapturer::AddOrUpdateSink, - video_capturer_.get(), sink, wants)); -} - -void VideoSource::RemoveSink( - rtc::VideoSinkInterface* output) { - worker_thread_->Invoke( - rtc::Bind(&cricket::VideoCapturer::RemoveSink, - video_capturer_.get(), output)); -} - -// OnStateChange listens to the cricket::VideoCapturer::SignalStateChange. -void VideoSource::OnStateChange(cricket::VideoCapturer* capturer, - cricket::CaptureState capture_state) { - if (rtc::Thread::Current() != signaling_thread_) { - invoker_.AsyncInvoke( - signaling_thread_, rtc::Bind(&VideoSource::OnStateChange, this, - capturer, capture_state)); - return; - } - - if (capturer == video_capturer_.get()) { - SetState(GetReadyState(capture_state)); - } -} - -void VideoSource::SetState(SourceState new_state) { - if (state_ != new_state) { - state_ = new_state; - FireOnChanged(); - } -} - -} // namespace webrtc +// TODO(perkj): Remove this file once Chrome build files doesn't depend on it.