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, &current_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