10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org/* 20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * libjingle 30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Copyright 2012, Google Inc. 40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * Redistribution and use in source and binary forms, with or without 60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * modification, are permitted provided that the following conditions are met: 70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 1. Redistributions of source code must retain the above copyright notice, 90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * this list of conditions and the following disclaimer. 100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 2. Redistributions in binary form must reproduce the above copyright notice, 110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * this list of conditions and the following disclaimer in the documentation 120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * and/or other materials provided with the distribution. 130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 3. The name of the author may not be used to endorse or promote products 140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * derived from this software without specific prior written permission. 150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * 160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org */ 270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 284ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org#include "talk/app/webrtc/videosource.h" 290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <vector> 31ffa7ab2b11aa9043cb2cbfe4e8621798b2420c0eglaznev@webrtc.org#include <cstdlib> 320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/app/webrtc/mediaconstraintsinterface.h" 340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/session/media/channelmanager.h" 350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgusing cricket::CaptureState; 370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgusing webrtc::MediaConstraintsInterface; 380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgusing webrtc::MediaSourceInterface; 390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace { 410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst double kRoundingTruncation = 0.0005; 430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgenum { 450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MSG_VIDEOCAPTURESTATECONNECT, 460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MSG_VIDEOCAPTURESTATEDISCONNECT, 470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MSG_VIDEOCAPTURESTATECHANGE, 480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}; 490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Default resolution. If no constraint is specified, this is the resolution we 510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// will use. 524ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.orgstatic const cricket::VideoFormatPod kDefaultFormat = 530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org {640, 480, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}; 540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// List of formats used if the camera doesn't support capability enumeration. 560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const cricket::VideoFormatPod kVideoFormats[] = { 570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org {1920, 1080, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, 580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org {1280, 720, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, 590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org {960, 720, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, 600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org {640, 360, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, 610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org {640, 480, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, 620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org {320, 240, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, 630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org {320, 180, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY} 640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}; 650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgMediaSourceInterface::SourceState 670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgGetReadyState(cricket::CaptureState state) { 680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org switch (state) { 690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case cricket::CS_STARTING: 700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return MediaSourceInterface::kInitializing; 710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case cricket::CS_RUNNING: 720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return MediaSourceInterface::kLive; 730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case cricket::CS_FAILED: 740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case cricket::CS_NO_DEVICE: 750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case cricket::CS_STOPPED: 760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return MediaSourceInterface::kEnded; 770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case cricket::CS_PAUSED: 780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return MediaSourceInterface::kMuted; 790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org default: 800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(false && "GetReadyState unknown state"); 810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return MediaSourceInterface::kEnded; 830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SetUpperLimit(int new_limit, int* original_limit) { 860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (*original_limit < 0 || new_limit < *original_limit) 870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *original_limit = new_limit; 880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Updates |format_upper_limit| from |constraint|. 910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// If constraint.maxFoo is smaller than format_upper_limit.foo, 920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// set format_upper_limit.foo to constraint.maxFoo. 930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid SetUpperLimitFromConstraint( 940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const MediaConstraintsInterface::Constraint& constraint, 950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org cricket::VideoFormat* format_upper_limit) { 960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (constraint.key == MediaConstraintsInterface::kMaxWidth) { 972a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org int value = rtc::FromString<int>(constraint.value); 980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SetUpperLimit(value, &(format_upper_limit->width)); 990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kMaxHeight) { 1002a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org int value = rtc::FromString<int>(constraint.value); 1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SetUpperLimit(value, &(format_upper_limit->height)); 1020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Fills |format_out| with the max width and height allowed by |constraints|. 1060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid FromConstraintsForScreencast( 1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const MediaConstraintsInterface::Constraints& constraints, 1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org cricket::VideoFormat* format_out) { 1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org typedef MediaConstraintsInterface::Constraints::const_iterator 1100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ConstraintsIterator; 1110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org cricket::VideoFormat upper_limit(-1, -1, 0, 0); 1130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (ConstraintsIterator constraints_it = constraints.begin(); 1140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org constraints_it != constraints.end(); ++constraints_it) 1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SetUpperLimitFromConstraint(*constraints_it, &upper_limit); 1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (upper_limit.width >= 0) 1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org format_out->width = upper_limit.width; 1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (upper_limit.height >= 0) 1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org format_out->height = upper_limit.height; 1210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Returns true if |constraint| is fulfilled. |format_out| can differ from 1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// |format_in| if the format is changed by the constraint. Ie - the frame rate 1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// can be changed by setting maxFrameRate. 1260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool NewFormatWithConstraints( 1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const MediaConstraintsInterface::Constraint& constraint, 1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const cricket::VideoFormat& format_in, 1290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool mandatory, 1300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org cricket::VideoFormat* format_out) { 1310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(format_out != NULL); 1320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *format_out = format_in; 1330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (constraint.key == MediaConstraintsInterface::kMinWidth) { 1352a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org int value = rtc::FromString<int>(constraint.value); 1360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return (value <= format_in.width); 1370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kMaxWidth) { 1382a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org int value = rtc::FromString<int>(constraint.value); 1390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return (value >= format_in.width); 1400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kMinHeight) { 1412a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org int value = rtc::FromString<int>(constraint.value); 1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return (value <= format_in.height); 1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kMaxHeight) { 1442a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org int value = rtc::FromString<int>(constraint.value); 1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return (value >= format_in.height); 1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kMinFrameRate) { 1472a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org int value = rtc::FromString<int>(constraint.value); 1480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return (value <= cricket::VideoFormat::IntervalToFps(format_in.interval)); 1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kMaxFrameRate) { 1502a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org int value = rtc::FromString<int>(constraint.value); 1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (value == 0) { 1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (mandatory) { 1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(ronghuawu): Convert the constraint value to float when sub-1fps 1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // is supported by the capturer. 1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org value = 1; 1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (value <= cricket::VideoFormat::IntervalToFps(format_in.interval)) { 1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org format_out->interval = cricket::VideoFormat::FpsToInterval(value); 1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kMinAspectRatio) { 1672a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org double value = rtc::FromString<double>(constraint.value); 1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The aspect ratio in |constraint.value| has been converted to a string and 1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // back to a double, so it may have a rounding error. 1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // E.g if the value 1/3 is converted to a string, the string will not have 1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // infinite length. 1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // We add a margin of 0.0005 which is high enough to detect the same aspect 1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // ratio but small enough to avoid matching wrong aspect ratios. 1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org double ratio = static_cast<double>(format_in.width) / format_in.height; 1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return (value <= ratio + kRoundingTruncation); 1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kMaxAspectRatio) { 1772a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org double value = rtc::FromString<double>(constraint.value); 1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org double ratio = static_cast<double>(format_in.width) / format_in.height; 1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Subtract 0.0005 to avoid rounding problems. Same as above. 1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const double kRoundingTruncation = 0.0005; 1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return (value >= ratio - kRoundingTruncation); 1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (constraint.key == MediaConstraintsInterface::kNoiseReduction || 1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org constraint.key == MediaConstraintsInterface::kLeakyBucket || 1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org constraint.key == 1853865f242aa057847ca2c3728d24874882ef227eehenrike@webrtc.org MediaConstraintsInterface::kTemporalLayeredScreencast) { 1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // These are actually options, not constraints, so they can be satisfied 1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // regardless of the format. 1880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "Found unknown MediaStream constraint. Name:" 1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << constraint.key << " Value:" << constraint.value; 1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Removes cricket::VideoFormats from |formats| that don't meet |constraint|. 1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid FilterFormatsByConstraint( 1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const MediaConstraintsInterface::Constraint& constraint, 1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool mandatory, 1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<cricket::VideoFormat>* formats) { 2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<cricket::VideoFormat>::iterator format_it = 2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org formats->begin(); 2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org while (format_it != formats->end()) { 2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Modify the format_it to fulfill the constraint if possible. 2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Delete it otherwise. 2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!NewFormatWithConstraints(constraint, (*format_it), 2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org mandatory, &(*format_it))) { 2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org format_it = formats->erase(format_it); 2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ++format_it; 2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Returns a vector of cricket::VideoFormat that best match |constraints|. 2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstd::vector<cricket::VideoFormat> FilterFormats( 2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const MediaConstraintsInterface::Constraints& mandatory, 2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const MediaConstraintsInterface::Constraints& optional, 2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::vector<cricket::VideoFormat>& supported_formats) { 2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org typedef MediaConstraintsInterface::Constraints::const_iterator 2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ConstraintsIterator; 2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<cricket::VideoFormat> candidates = supported_formats; 2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (ConstraintsIterator constraints_it = mandatory.begin(); 2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org constraints_it != mandatory.end(); ++constraints_it) 2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org FilterFormatsByConstraint(*constraints_it, true, &candidates); 2260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (candidates.size() == 0) 2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return candidates; 2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Ok - all mandatory checked and we still have a candidate. 2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Let's try filtering using the optional constraints. 2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (ConstraintsIterator constraints_it = optional.begin(); 2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org constraints_it != optional.end(); ++constraints_it) { 2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<cricket::VideoFormat> current_candidates = candidates; 2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org FilterFormatsByConstraint(*constraints_it, false, ¤t_candidates); 2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (current_candidates.size() > 0) { 2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org candidates = current_candidates; 2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // We have done as good as we can to filter the supported resolutions. 2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return candidates; 2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Find the format that best matches the default video size. 2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Constraints are optional and since the performance of a video call 2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// might be bad due to bitrate limitations, CPU, and camera performance, 2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// it is better to select a resolution that is as close as possible to our 2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// default and still meets the contraints. 2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst cricket::VideoFormat& GetBestCaptureFormat( 2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::vector<cricket::VideoFormat>& formats) { 2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(formats.size() > 0); 2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2544ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org int default_area = kDefaultFormat.width * kDefaultFormat.height; 2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<cricket::VideoFormat>::const_iterator it = formats.begin(); 2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<cricket::VideoFormat>::const_iterator best_it = formats.begin(); 258ffa7ab2b11aa9043cb2cbfe4e8621798b2420c0eglaznev@webrtc.org int best_diff_area = std::abs(default_area - it->width * it->height); 259ffa7ab2b11aa9043cb2cbfe4e8621798b2420c0eglaznev@webrtc.org int64 best_diff_interval = kDefaultFormat.interval; 2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (; it != formats.end(); ++it) { 261ffa7ab2b11aa9043cb2cbfe4e8621798b2420c0eglaznev@webrtc.org int diff_area = std::abs(default_area - it->width * it->height); 262ffa7ab2b11aa9043cb2cbfe4e8621798b2420c0eglaznev@webrtc.org int64 diff_interval = std::abs(kDefaultFormat.interval - it->interval); 263ffa7ab2b11aa9043cb2cbfe4e8621798b2420c0eglaznev@webrtc.org if (diff_area < best_diff_area || 264ffa7ab2b11aa9043cb2cbfe4e8621798b2420c0eglaznev@webrtc.org (diff_area == best_diff_area && diff_interval < best_diff_interval)) { 265ffa7ab2b11aa9043cb2cbfe4e8621798b2420c0eglaznev@webrtc.org best_diff_area = diff_area; 266ffa7ab2b11aa9043cb2cbfe4e8621798b2420c0eglaznev@webrtc.org best_diff_interval = diff_interval; 2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org best_it = it; 2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return *best_it; 2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Set |option| to the highest-priority value of |key| in the constraints. 2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Return false if the key is mandatory, and the value is invalid. 2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ExtractOption(const MediaConstraintsInterface* all_constraints, 2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::string& key, cricket::Settable<bool>* option) { 2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org size_t mandatory = 0; 2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool value; 2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (FindConstraint(all_constraints, key, &value, &mandatory)) { 2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org option->Set(value); 2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return mandatory == 0; 2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Search |all_constraints| for known video options. Apply all options that are 2880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// found with valid values, and return false if any mandatory video option was 2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// found with an invalid value. 2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool ExtractVideoOptions(const MediaConstraintsInterface* all_constraints, 2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org cricket::VideoOptions* options) { 2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool all_valid = true; 2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org all_valid &= ExtractOption(all_constraints, 2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MediaConstraintsInterface::kNoiseReduction, 2960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org &(options->video_noise_reduction)); 2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org all_valid &= ExtractOption(all_constraints, 2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MediaConstraintsInterface::kLeakyBucket, 2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org &(options->video_leaky_bucket)); 3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org all_valid &= ExtractOption(all_constraints, 3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MediaConstraintsInterface::kTemporalLayeredScreencast, 3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org &(options->video_temporal_layer_screencast)); 3030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return all_valid; 3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3074ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.orgclass FrameInputWrapper : public cricket::VideoRenderer { 3084ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org public: 3094ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org explicit FrameInputWrapper(cricket::VideoCapturer* capturer) 3104ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org : capturer_(capturer) { 3114ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org ASSERT(capturer_ != NULL); 3124ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org } 3134ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org 3144ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org virtual ~FrameInputWrapper() {} 3154ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org 3164ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org // VideoRenderer implementation. 3174ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org virtual bool SetSize(int width, int height, int reserved) OVERRIDE { 3184ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org return true; 3194ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org } 3204ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org 3214ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org virtual bool RenderFrame(const cricket::VideoFrame* frame) OVERRIDE { 3224ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org if (!capturer_->IsRunning()) { 3234ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org return true; 3244ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org } 3254ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org 3264ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org // This signal will be made on media engine render thread. The clients 3274ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org // of this signal should have no assumptions on what thread this signal 3284ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org // come from. 3294ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org capturer_->SignalVideoFrame(capturer_, frame); 3304ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org return true; 3314ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org } 3324ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org 3334ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org private: 3344ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org cricket::VideoCapturer* capturer_; 3354ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org int width_; 3364ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org int height_; 3374ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org 3384ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org DISALLOW_COPY_AND_ASSIGN(FrameInputWrapper); 3394ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org}; 3404ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org 3410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} // anonymous namespace 3420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace webrtc { 3440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3452a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgrtc::scoped_refptr<VideoSource> VideoSource::Create( 3460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org cricket::ChannelManager* channel_manager, 3470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org cricket::VideoCapturer* capturer, 3480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const webrtc::MediaConstraintsInterface* constraints) { 3490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(channel_manager != NULL); 3500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(capturer != NULL); 3512a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::scoped_refptr<VideoSource> source( 3522a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org new rtc::RefCountedObject<VideoSource>(channel_manager, 3534ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org capturer)); 3540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org source->Initialize(constraints); 3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return source; 3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3584ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.orgVideoSource::VideoSource(cricket::ChannelManager* channel_manager, 3594ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org cricket::VideoCapturer* capturer) 3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org : channel_manager_(channel_manager), 3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org video_capturer_(capturer), 3620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org state_(kInitializing) { 3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel_manager_->SignalVideoCaptureStateChange.connect( 3644ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org this, &VideoSource::OnStateChange); 3650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3674ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.orgVideoSource::~VideoSource() { 3680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel_manager_->StopVideoCapture(video_capturer_.get(), format_); 3690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel_manager_->SignalVideoCaptureStateChange.disconnect(this); 3700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3724ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.orgvoid VideoSource::Initialize( 3730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const webrtc::MediaConstraintsInterface* constraints) { 3740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<cricket::VideoFormat> formats; 3760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (video_capturer_->GetSupportedFormats() && 3770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org video_capturer_->GetSupportedFormats()->size() > 0) { 3780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org formats = *video_capturer_->GetSupportedFormats(); 3790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (video_capturer_->IsScreencast()) { 3800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The screen capturer can accept any resolution and we will derive the 3810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // format from the constraints if any. 3820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Note that this only affects tab capturing, not desktop capturing, 3830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // since desktop capturer does not respect the VideoFormat passed in. 3844ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org formats.push_back(cricket::VideoFormat(kDefaultFormat)); 3850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 3860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The VideoCapturer implementation doesn't support capability enumeration. 3870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // We need to guess what the camera support. 3880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (int i = 0; i < ARRAY_SIZE(kVideoFormats); ++i) { 3890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org formats.push_back(cricket::VideoFormat(kVideoFormats[i])); 3900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (constraints) { 3940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MediaConstraintsInterface::Constraints mandatory_constraints = 3950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org constraints->GetMandatory(); 3960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MediaConstraintsInterface::Constraints optional_constraints; 3970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org optional_constraints = constraints->GetOptional(); 3980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (video_capturer_->IsScreencast()) { 4000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Use the maxWidth and maxHeight allowed by constraints for screencast. 4010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org FromConstraintsForScreencast(mandatory_constraints, &(formats[0])); 4020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org formats = FilterFormats(mandatory_constraints, optional_constraints, 4050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org formats); 4060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (formats.size() == 0) { 4090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "Failed to find a suitable video format."; 4100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SetState(kEnded); 4110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return; 4120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org cricket::VideoOptions options; 4150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!ExtractVideoOptions(constraints, &options)) { 4160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "Could not satisfy mandatory options."; 4170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SetState(kEnded); 4180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return; 4190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org options_.SetAll(options); 4210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org format_ = GetBestCaptureFormat(formats); 4230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Start the camera with our best guess. 4240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(perkj): Should we try again with another format it it turns out that 4250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // the camera doesn't produce frames with the correct format? Or will 4260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // cricket::VideCapturer be able to re-scale / crop to the requested 4270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // resolution? 4280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!channel_manager_->StartVideoCapture(video_capturer_.get(), format_)) { 4290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SetState(kEnded); 4300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return; 4310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Initialize hasn't succeeded until a successful state change has occurred. 4330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4354ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.orgcricket::VideoRenderer* VideoSource::FrameInput() { 4364ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org // Defer creation of frame_input_ until it's needed, e.g. the local video 4374ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org // sources will never need it. 4384ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org if (!frame_input_) { 4394ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org frame_input_.reset(new FrameInputWrapper(video_capturer_.get())); 4404ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org } 4414ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org return frame_input_.get(); 4424ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org} 4434ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.org 4444ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.orgvoid VideoSource::AddSink(cricket::VideoRenderer* output) { 4450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel_manager_->AddVideoRenderer(video_capturer_.get(), output); 4460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4484ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.orgvoid VideoSource::RemoveSink(cricket::VideoRenderer* output) { 4490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org channel_manager_->RemoveVideoRenderer(video_capturer_.get(), output); 4500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// OnStateChange listens to the ChannelManager::SignalVideoCaptureStateChange. 4530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// This signal is triggered for all video capturers. Not only the one we are 4540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// interested in. 4554ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.orgvoid VideoSource::OnStateChange(cricket::VideoCapturer* capturer, 4560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org cricket::CaptureState capture_state) { 4570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (capturer == video_capturer_.get()) { 4580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SetState(GetReadyState(capture_state)); 4590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4624ba8b9ea10385f43b19d6ed7408f4a09bdc1cbdawu@webrtc.orgvoid VideoSource::SetState(SourceState new_state) { 4630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (VERIFY(state_ != new_state)) { 4640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org state_ = new_state; 4650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org FireOnChanged(); 4660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 4680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} // namespace webrtc 470