videosource.cc revision d4e598d57aed714a599444a7eab5e8fdde52a950
128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org/* 228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * libjingle 328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * Copyright 2012, Google Inc. 428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without 628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * modification, are permitted provided that the following conditions are met: 728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * this list of conditions and the following disclaimer. 1028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 1128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * this list of conditions and the following disclaimer in the documentation 1228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * and/or other materials provided with the distribution. 1328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 3. The name of the author may not be used to endorse or promote products 1428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * derived from this software without specific prior written permission. 1528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * 1628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 1728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 1828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 1928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 2228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 2328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 2428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 2528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org */ 2728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 28967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org#include "talk/app/webrtc/videosource.h" 2928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include <vector> 3128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/app/webrtc/mediaconstraintsinterface.h" 3328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org#include "talk/session/media/channelmanager.h" 3428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgusing cricket::CaptureState; 3628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgusing webrtc::MediaConstraintsInterface; 3728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgusing webrtc::MediaSourceInterface; 3828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 3928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgnamespace { 4028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 4128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgconst double kRoundingTruncation = 0.0005; 4228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 4328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgenum { 4428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org MSG_VIDEOCAPTURESTATECONNECT, 4528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org MSG_VIDEOCAPTURESTATEDISCONNECT, 4628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org MSG_VIDEOCAPTURESTATECHANGE, 4728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 4828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 4928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Default resolution. If no constraint is specified, this is the resolution we 5028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// will use. 51967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.orgstatic const cricket::VideoFormatPod kDefaultFormat = 5228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org {640, 480, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}; 5328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 5428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// List of formats used if the camera doesn't support capability enumeration. 5528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstatic const cricket::VideoFormatPod kVideoFormats[] = { 5628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org {1920, 1080, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, 5728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org {1280, 720, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, 5828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org {960, 720, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, 5928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org {640, 360, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, 6028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org {640, 480, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, 6128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org {320, 240, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, 6228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org {320, 180, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY} 6328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org}; 6428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 6528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgMediaSourceInterface::SourceState 6628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgGetReadyState(cricket::CaptureState state) { 6728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org switch (state) { 6828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case cricket::CS_STARTING: 6928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return MediaSourceInterface::kInitializing; 7028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case cricket::CS_RUNNING: 7128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return MediaSourceInterface::kLive; 7228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case cricket::CS_FAILED: 7328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case cricket::CS_NO_DEVICE: 7428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case cricket::CS_STOPPED: 7528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return MediaSourceInterface::kEnded; 7628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org case cricket::CS_PAUSED: 7728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return MediaSourceInterface::kMuted; 7828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org default: 7928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ASSERT(false && "GetReadyState unknown state"); 8028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 8128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return MediaSourceInterface::kEnded; 8228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 8328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 8428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SetUpperLimit(int new_limit, int* original_limit) { 8528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (*original_limit < 0 || new_limit < *original_limit) 8628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org *original_limit = new_limit; 8728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 8828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 8928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Updates |format_upper_limit| from |constraint|. 9028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// If constraint.maxFoo is smaller than format_upper_limit.foo, 9128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// set format_upper_limit.foo to constraint.maxFoo. 9228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid SetUpperLimitFromConstraint( 9328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const MediaConstraintsInterface::Constraint& constraint, 9428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cricket::VideoFormat* format_upper_limit) { 9528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (constraint.key == MediaConstraintsInterface::kMaxWidth) { 96d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org int value = rtc::FromString<int>(constraint.value); 9728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetUpperLimit(value, &(format_upper_limit->width)); 9828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kMaxHeight) { 99d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org int value = rtc::FromString<int>(constraint.value); 10028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetUpperLimit(value, &(format_upper_limit->height)); 10128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 10228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 10328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 10428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Fills |format_out| with the max width and height allowed by |constraints|. 10528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid FromConstraintsForScreencast( 10628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const MediaConstraintsInterface::Constraints& constraints, 10728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cricket::VideoFormat* format_out) { 10828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org typedef MediaConstraintsInterface::Constraints::const_iterator 10928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ConstraintsIterator; 11028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 11128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cricket::VideoFormat upper_limit(-1, -1, 0, 0); 11228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (ConstraintsIterator constraints_it = constraints.begin(); 11328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org constraints_it != constraints.end(); ++constraints_it) 11428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetUpperLimitFromConstraint(*constraints_it, &upper_limit); 11528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 11628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (upper_limit.width >= 0) 11728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format_out->width = upper_limit.width; 11828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (upper_limit.height >= 0) 11928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format_out->height = upper_limit.height; 12028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 12128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 12228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Returns true if |constraint| is fulfilled. |format_out| can differ from 12328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// |format_in| if the format is changed by the constraint. Ie - the frame rate 12428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// can be changed by setting maxFrameRate. 12528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool NewFormatWithConstraints( 12628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const MediaConstraintsInterface::Constraint& constraint, 12728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const cricket::VideoFormat& format_in, 12828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool mandatory, 12928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cricket::VideoFormat* format_out) { 13028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ASSERT(format_out != NULL); 13128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org *format_out = format_in; 13228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 13328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (constraint.key == MediaConstraintsInterface::kMinWidth) { 134d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org int value = rtc::FromString<int>(constraint.value); 13528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return (value <= format_in.width); 13628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kMaxWidth) { 137d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org int value = rtc::FromString<int>(constraint.value); 13828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return (value >= format_in.width); 13928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kMinHeight) { 140d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org int value = rtc::FromString<int>(constraint.value); 14128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return (value <= format_in.height); 14228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kMaxHeight) { 143d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org int value = rtc::FromString<int>(constraint.value); 14428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return (value >= format_in.height); 14528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kMinFrameRate) { 146d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org int value = rtc::FromString<int>(constraint.value); 14728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return (value <= cricket::VideoFormat::IntervalToFps(format_in.interval)); 14828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kMaxFrameRate) { 149d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org int value = rtc::FromString<int>(constraint.value); 15028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (value == 0) { 15128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (mandatory) { 15228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(ronghuawu): Convert the constraint value to float when sub-1fps 15328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // is supported by the capturer. 15428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 15528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 15628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org value = 1; 15728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 15828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 15928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (value <= cricket::VideoFormat::IntervalToFps(format_in.interval)) { 16028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format_out->interval = cricket::VideoFormat::FpsToInterval(value); 16128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 16228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 16328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 16428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 16528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kMinAspectRatio) { 166d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org double value = rtc::FromString<double>(constraint.value); 16728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // The aspect ratio in |constraint.value| has been converted to a string and 16828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // back to a double, so it may have a rounding error. 16928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // E.g if the value 1/3 is converted to a string, the string will not have 17028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // infinite length. 17128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // We add a margin of 0.0005 which is high enough to detect the same aspect 17228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // ratio but small enough to avoid matching wrong aspect ratios. 17328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org double ratio = static_cast<double>(format_in.width) / format_in.height; 17428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return (value <= ratio + kRoundingTruncation); 17528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kMaxAspectRatio) { 176d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org double value = rtc::FromString<double>(constraint.value); 17728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org double ratio = static_cast<double>(format_in.width) / format_in.height; 17828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Subtract 0.0005 to avoid rounding problems. Same as above. 17928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const double kRoundingTruncation = 0.0005; 18028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return (value >= ratio - kRoundingTruncation); 18128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kNoiseReduction || 18228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org constraint.key == MediaConstraintsInterface::kLeakyBucket || 18328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org constraint.key == 184b0ecc1c6fb107b9032611870eeae8afde3e0a5d2henrike@webrtc.org MediaConstraintsInterface::kTemporalLayeredScreencast) { 18528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // These are actually options, not constraints, so they can be satisfied 18628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // regardless of the format. 18728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 18828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 18928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_WARNING) << "Found unknown MediaStream constraint. Name:" 19028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org << constraint.key << " Value:" << constraint.value; 19128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return false; 19228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 19328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 19428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Removes cricket::VideoFormats from |formats| that don't meet |constraint|. 19528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgvoid FilterFormatsByConstraint( 19628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const MediaConstraintsInterface::Constraint& constraint, 19728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool mandatory, 19828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<cricket::VideoFormat>* formats) { 19928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<cricket::VideoFormat>::iterator format_it = 20028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org formats->begin(); 20128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org while (format_it != formats->end()) { 20228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Modify the format_it to fulfill the constraint if possible. 20328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Delete it otherwise. 20428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!NewFormatWithConstraints(constraint, (*format_it), 20528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org mandatory, &(*format_it))) { 20628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format_it = formats->erase(format_it); 20728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 20828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ++format_it; 20928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 21028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 21128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 21228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 21328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Returns a vector of cricket::VideoFormat that best match |constraints|. 21428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgstd::vector<cricket::VideoFormat> FilterFormats( 21528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const MediaConstraintsInterface::Constraints& mandatory, 21628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const MediaConstraintsInterface::Constraints& optional, 21728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const std::vector<cricket::VideoFormat>& supported_formats) { 21828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org typedef MediaConstraintsInterface::Constraints::const_iterator 21928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ConstraintsIterator; 22028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<cricket::VideoFormat> candidates = supported_formats; 22128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 22228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (ConstraintsIterator constraints_it = mandatory.begin(); 22328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org constraints_it != mandatory.end(); ++constraints_it) 22428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org FilterFormatsByConstraint(*constraints_it, true, &candidates); 22528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 22628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (candidates.size() == 0) 22728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return candidates; 22828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 22928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Ok - all mandatory checked and we still have a candidate. 23028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Let's try filtering using the optional constraints. 23128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (ConstraintsIterator constraints_it = optional.begin(); 23228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org constraints_it != optional.end(); ++constraints_it) { 23328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<cricket::VideoFormat> current_candidates = candidates; 23428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org FilterFormatsByConstraint(*constraints_it, false, ¤t_candidates); 23528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (current_candidates.size() > 0) { 23628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org candidates = current_candidates; 23728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 23828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 23928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 24028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // We have done as good as we can to filter the supported resolutions. 24128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return candidates; 24228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 24328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 24428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Find the format that best matches the default video size. 24528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Constraints are optional and since the performance of a video call 24628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// might be bad due to bitrate limitations, CPU, and camera performance, 24728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// it is better to select a resolution that is as close as possible to our 24828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// default and still meets the contraints. 24928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgconst cricket::VideoFormat& GetBestCaptureFormat( 25028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const std::vector<cricket::VideoFormat>& formats) { 25128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ASSERT(formats.size() > 0); 25228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 253967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org int default_area = kDefaultFormat.width * kDefaultFormat.height; 25428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 25528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<cricket::VideoFormat>::const_iterator it = formats.begin(); 25628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<cricket::VideoFormat>::const_iterator best_it = formats.begin(); 25728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int best_diff = abs(default_area - it->width* it->height); 25828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (; it != formats.end(); ++it) { 25928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org int diff = abs(default_area - it->width* it->height); 26028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (diff < best_diff) { 26128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org best_diff = diff; 26228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org best_it = it; 26328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 26428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 26528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return *best_it; 26628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 26728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 26828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Set |option| to the highest-priority value of |key| in the constraints. 26928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Return false if the key is mandatory, and the value is invalid. 27028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool ExtractOption(const MediaConstraintsInterface* all_constraints, 27128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const std::string& key, cricket::Settable<bool>* option) { 27228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org size_t mandatory = 0; 27328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool value; 27428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (FindConstraint(all_constraints, key, &value, &mandatory)) { 27528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org option->Set(value); 27628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return true; 27728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 27828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 27928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return mandatory == 0; 28028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 28128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 28228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// Search |all_constraints| for known video options. Apply all options that are 28328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// found with valid values, and return false if any mandatory video option was 28428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// found with an invalid value. 28528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgbool ExtractVideoOptions(const MediaConstraintsInterface* all_constraints, 28628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cricket::VideoOptions* options) { 28728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org bool all_valid = true; 28828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 28928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org all_valid &= ExtractOption(all_constraints, 29028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org MediaConstraintsInterface::kNoiseReduction, 29128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org &(options->video_noise_reduction)); 29228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org all_valid &= ExtractOption(all_constraints, 29328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org MediaConstraintsInterface::kLeakyBucket, 29428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org &(options->video_leaky_bucket)); 29528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org all_valid &= ExtractOption(all_constraints, 29628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org MediaConstraintsInterface::kTemporalLayeredScreencast, 29728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org &(options->video_temporal_layer_screencast)); 29828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 29928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return all_valid; 30028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 30128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 302967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.orgclass FrameInputWrapper : public cricket::VideoRenderer { 303967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org public: 304967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org explicit FrameInputWrapper(cricket::VideoCapturer* capturer) 305967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org : capturer_(capturer) { 306967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org ASSERT(capturer_ != NULL); 307967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org } 308967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org 309967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org virtual ~FrameInputWrapper() {} 310967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org 311967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org // VideoRenderer implementation. 312967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org virtual bool SetSize(int width, int height, int reserved) OVERRIDE { 313967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org return true; 314967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org } 315967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org 316967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org virtual bool RenderFrame(const cricket::VideoFrame* frame) OVERRIDE { 317967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org if (!capturer_->IsRunning()) { 318967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org return true; 319967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org } 320967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org 321967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org // This signal will be made on media engine render thread. The clients 322967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org // of this signal should have no assumptions on what thread this signal 323967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org // come from. 324967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org capturer_->SignalVideoFrame(capturer_, frame); 325967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org return true; 326967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org } 327967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org 328967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org private: 329967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org cricket::VideoCapturer* capturer_; 330967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org int width_; 331967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org int height_; 332967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org 333967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org DISALLOW_COPY_AND_ASSIGN(FrameInputWrapper); 334967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org}; 335967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org 33628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} // anonymous namespace 33728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 33828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.orgnamespace webrtc { 33928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 340d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.orgrtc::scoped_refptr<VideoSource> VideoSource::Create( 34128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cricket::ChannelManager* channel_manager, 34228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cricket::VideoCapturer* capturer, 34328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const webrtc::MediaConstraintsInterface* constraints) { 34428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ASSERT(channel_manager != NULL); 34528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org ASSERT(capturer != NULL); 346d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org rtc::scoped_refptr<VideoSource> source( 347d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org new rtc::RefCountedObject<VideoSource>(channel_manager, 348967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org capturer)); 34928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org source->Initialize(constraints); 35028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return source; 35128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 35228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 353967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.orgVideoSource::VideoSource(cricket::ChannelManager* channel_manager, 354967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org cricket::VideoCapturer* capturer) 35528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org : channel_manager_(channel_manager), 35628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org video_capturer_(capturer), 35728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org state_(kInitializing) { 35828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org channel_manager_->SignalVideoCaptureStateChange.connect( 359967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org this, &VideoSource::OnStateChange); 36028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 36128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 362967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.orgVideoSource::~VideoSource() { 36328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org channel_manager_->StopVideoCapture(video_capturer_.get(), format_); 36428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org channel_manager_->SignalVideoCaptureStateChange.disconnect(this); 36528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 36628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 367967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.orgvoid VideoSource::Initialize( 36828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org const webrtc::MediaConstraintsInterface* constraints) { 36928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 37028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org std::vector<cricket::VideoFormat> formats; 37128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (video_capturer_->GetSupportedFormats() && 37228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org video_capturer_->GetSupportedFormats()->size() > 0) { 37328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org formats = *video_capturer_->GetSupportedFormats(); 37428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else if (video_capturer_->IsScreencast()) { 37528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // The screen capturer can accept any resolution and we will derive the 37628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // format from the constraints if any. 37728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Note that this only affects tab capturing, not desktop capturing, 37828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // since desktop capturer does not respect the VideoFormat passed in. 379967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org formats.push_back(cricket::VideoFormat(kDefaultFormat)); 38028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } else { 38128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // The VideoCapturer implementation doesn't support capability enumeration. 38228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // We need to guess what the camera support. 38328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org for (int i = 0; i < ARRAY_SIZE(kVideoFormats); ++i) { 38428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org formats.push_back(cricket::VideoFormat(kVideoFormats[i])); 38528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 38628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 38728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 38828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (constraints) { 38928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org MediaConstraintsInterface::Constraints mandatory_constraints = 39028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org constraints->GetMandatory(); 39128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org MediaConstraintsInterface::Constraints optional_constraints; 39228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org optional_constraints = constraints->GetOptional(); 39328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 39428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (video_capturer_->IsScreencast()) { 39528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Use the maxWidth and maxHeight allowed by constraints for screencast. 39628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org FromConstraintsForScreencast(mandatory_constraints, &(formats[0])); 39728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 39828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 39928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org formats = FilterFormats(mandatory_constraints, optional_constraints, 40028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org formats); 40128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 40228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 40328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (formats.size() == 0) { 40428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_WARNING) << "Failed to find a suitable video format."; 40528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetState(kEnded); 40628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return; 40728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 40828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 40928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cricket::VideoOptions options; 41028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!ExtractVideoOptions(constraints, &options)) { 41128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org LOG(LS_WARNING) << "Could not satisfy mandatory options."; 41228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetState(kEnded); 41328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return; 41428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 41528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org options_.SetAll(options); 41628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 41728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org format_ = GetBestCaptureFormat(formats); 41828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Start the camera with our best guess. 41928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // TODO(perkj): Should we try again with another format it it turns out that 42028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // the camera doesn't produce frames with the correct format? Or will 42128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // cricket::VideCapturer be able to re-scale / crop to the requested 42228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // resolution? 42328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (!channel_manager_->StartVideoCapture(video_capturer_.get(), format_)) { 42428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetState(kEnded); 42528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org return; 42628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 42728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org // Initialize hasn't succeeded until a successful state change has occurred. 42828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 42928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 430967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.orgcricket::VideoRenderer* VideoSource::FrameInput() { 431967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org // Defer creation of frame_input_ until it's needed, e.g. the local video 432967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org // sources will never need it. 433967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org if (!frame_input_) { 434967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org frame_input_.reset(new FrameInputWrapper(video_capturer_.get())); 435967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org } 436967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org return frame_input_.get(); 437967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org} 438967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.org 439967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.orgvoid VideoSource::AddSink(cricket::VideoRenderer* output) { 44028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org channel_manager_->AddVideoRenderer(video_capturer_.get(), output); 44128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 44228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 443967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.orgvoid VideoSource::RemoveSink(cricket::VideoRenderer* output) { 44428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org channel_manager_->RemoveVideoRenderer(video_capturer_.get(), output); 44528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 44628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 44728e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// OnStateChange listens to the ChannelManager::SignalVideoCaptureStateChange. 44828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// This signal is triggered for all video capturers. Not only the one we are 44928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org// interested in. 450967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.orgvoid VideoSource::OnStateChange(cricket::VideoCapturer* capturer, 45128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org cricket::CaptureState capture_state) { 45228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (capturer == video_capturer_.get()) { 45328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org SetState(GetReadyState(capture_state)); 45428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 45528e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 45628e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 457967bfff54d00f176a554bf9f955f14dde99f7bb9wu@webrtc.orgvoid VideoSource::SetState(SourceState new_state) { 45828e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org if (VERIFY(state_ != new_state)) { 45928e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org state_ = new_state; 46028e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org FireOnChanged(); 46128e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org } 46228e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} 46328e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org 46428e20752806a492f5a6a5d343c02f9556f39b1cdhenrike@webrtc.org} // namespace webrtc 465