webrtcvideoengine2.cc revision cd6702282a49448adda470934f4bd9e6181cab22
1b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org/*
2b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * libjingle
3b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * Copyright 2014 Google Inc.
4b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *
5b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * Redistribution and use in source and binary forms, with or without
6b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * modification, are permitted provided that the following conditions are met:
7b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *
8b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *  1. Redistributions of source code must retain the above copyright notice,
9b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *     this list of conditions and the following disclaimer.
10b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *  2. Redistributions in binary form must reproduce the above copyright notice,
11b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *     this list of conditions and the following disclaimer in the documentation
12b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *     and/or other materials provided with the distribution.
13b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *  3. The name of the author may not be used to endorse or promote products
14b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *     derived from this software without specific prior written permission.
15b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org *
16b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org */
27b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
28b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#ifdef HAVE_WEBRTC_VIDEO
29b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/webrtc/webrtcvideoengine2.h"
30b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
31c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org#include <algorithm>
323c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org#include <set>
33b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include <string>
34b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
35b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/base/videocapturer.h"
36b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/base/videorenderer.h"
37df9bbbee56f4d9ecef93b3c46964b6f29803f81bbuildbot@webrtc.org#include "talk/media/webrtc/constants.h"
38a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org#include "talk/media/webrtc/simulcast.h"
3981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström#include "talk/media/webrtc/webrtcvideoencoderfactory.h"
40b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/webrtc/webrtcvideoframe.h"
41b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/webrtc/webrtcvoiceengine.h"
42a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/buffer.h"
43a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/logging.h"
44a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/stringutils.h"
45b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "webrtc/call.h"
4671f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
4781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström#include "webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h"
4881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström#include "webrtc/system_wrappers/interface/field_trial.h"
4950fe359eb614e1bbe41124b9c19263019da0395dpbos@webrtc.org#include "webrtc/system_wrappers/interface/trace_event.h"
50776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org#include "webrtc/video_decoder.h"
51ab990ae43a2b84b103cb3c50bc38502375c13e68pbos@webrtc.org#include "webrtc/video_encoder.h"
52b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
53b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#define UNIMPLEMENTED                                                 \
54b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_ERROR) << "Call to unimplemented function " << __FUNCTION__; \
55d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  RTC_NOTREACHED()
56b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
57b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgnamespace cricket {
587fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgnamespace {
5981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
6081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström// Wrap cricket::WebRtcVideoEncoderFactory as a webrtc::VideoEncoderFactory.
6181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmclass EncoderFactoryAdapter : public webrtc::VideoEncoderFactory {
6281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström public:
6381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  // EncoderFactoryAdapter doesn't take ownership of |factory|, which is owned
6481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  // by e.g. PeerConnectionFactory.
6581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  explicit EncoderFactoryAdapter(cricket::WebRtcVideoEncoderFactory* factory)
6681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      : factory_(factory) {}
6781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  virtual ~EncoderFactoryAdapter() {}
6881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
6981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  // Implement webrtc::VideoEncoderFactory.
7081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  webrtc::VideoEncoder* Create() override {
7181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    return factory_->CreateVideoEncoder(webrtc::kVideoCodecVP8);
7281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
7381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
7481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  void Destroy(webrtc::VideoEncoder* encoder) override {
7581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    return factory_->DestroyVideoEncoder(encoder);
7681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
7781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
7881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström private:
7981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  cricket::WebRtcVideoEncoderFactory* const factory_;
8081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström};
8181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
8281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström// An encoder factory that wraps Create requests for simulcastable codec types
8381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström// with a webrtc::SimulcastEncoderAdapter. Non simulcastable codec type
8481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström// requests are just passed through to the contained encoder factory.
8581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmclass WebRtcSimulcastEncoderFactory
8681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    : public cricket::WebRtcVideoEncoderFactory {
8781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström public:
8881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  // WebRtcSimulcastEncoderFactory doesn't take ownership of |factory|, which is
8981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  // owned by e.g. PeerConnectionFactory.
9081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  explicit WebRtcSimulcastEncoderFactory(
9181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      cricket::WebRtcVideoEncoderFactory* factory)
9281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      : factory_(factory) {}
9381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
9481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  static bool UseSimulcastEncoderFactory(
9581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      const std::vector<VideoCodec>& codecs) {
9681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    // If any codec is VP8, use the simulcast factory. If asked to create a
9781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    // non-VP8 codec, we'll just return a contained factory encoder directly.
9881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    for (const auto& codec : codecs) {
9981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      if (codec.type == webrtc::kVideoCodecVP8) {
10081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        return true;
10181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      }
10281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    }
10381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    return false;
10481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
10581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
10681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  webrtc::VideoEncoder* CreateVideoEncoder(
10781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      webrtc::VideoCodecType type) override {
108d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg    DCHECK(factory_ != NULL);
10981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    // If it's a codec type we can simulcast, create a wrapped encoder.
11081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    if (type == webrtc::kVideoCodecVP8) {
11181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      return new webrtc::SimulcastEncoderAdapter(
11281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström          new EncoderFactoryAdapter(factory_));
11381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    }
11481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    webrtc::VideoEncoder* encoder = factory_->CreateVideoEncoder(type);
11581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    if (encoder) {
11681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      non_simulcast_encoders_.push_back(encoder);
11781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    }
11881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    return encoder;
11981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
12081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
12181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  const std::vector<VideoCodec>& codecs() const override {
12281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    return factory_->codecs();
12381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
12481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
12581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  bool EncoderTypeHasInternalSource(
12681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      webrtc::VideoCodecType type) const override {
12781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    return factory_->EncoderTypeHasInternalSource(type);
12881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
12981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
13081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) override {
13181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    // Check first to see if the encoder wasn't wrapped in a
13281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    // SimulcastEncoderAdapter. In that case, ask the factory to destroy it.
13381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    if (std::remove(non_simulcast_encoders_.begin(),
13481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                    non_simulcast_encoders_.end(),
13581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                    encoder) != non_simulcast_encoders_.end()) {
13681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      factory_->DestroyVideoEncoder(encoder);
13781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      return;
13881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    }
13981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
14081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    // Otherwise, SimulcastEncoderAdapter can be deleted directly, and will call
14181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    // DestroyVideoEncoder on the factory for individual encoder instances.
14281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    delete encoder;
14381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
14481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
14581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström private:
14681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  cricket::WebRtcVideoEncoderFactory* factory_;
14781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  // A list of encoders that were created without being wrapped in a
14881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  // SimulcastEncoderAdapter.
14981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  std::vector<webrtc::VideoEncoder*> non_simulcast_encoders_;
15081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström};
15181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
15281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmbool CodecIsInternallySupported(const std::string& codec_name) {
15381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  if (CodecNamesEq(codec_name, kVp8CodecName)) {
15481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    return true;
15581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
15681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  if (CodecNamesEq(codec_name, kVp9CodecName)) {
15781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    const std::string group_name =
15881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        webrtc::field_trial::FindFullName("WebRTC-SupportVP9");
15981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    return group_name == "Enabled" || group_name == "EnabledByFlag";
16081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
16171f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin  if (CodecNamesEq(codec_name, kH264CodecName)) {
16271f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin    return webrtc::H264Encoder::IsSupported() &&
16371f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin        webrtc::H264Decoder::IsSupported();
16471f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin  }
16581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  return false;
16681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström}
16781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
16881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmvoid AddDefaultFeedbackParams(VideoCodec* codec) {
16981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamCcm, kRtcpFbCcmParamFir));
17081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamNack, kParamValueEmpty));
17181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamNack, kRtcpFbNackParamPli));
17281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamRemb, kParamValueEmpty));
17381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström}
17481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
17581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmstatic VideoCodec MakeVideoCodecWithDefaultFeedbackParams(int payload_type,
17681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                                                          const char* name) {
17781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  VideoCodec codec(payload_type, name, kDefaultVideoMaxWidth,
17881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                   kDefaultVideoMaxHeight, kDefaultVideoMaxFramerate, 0);
17981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  AddDefaultFeedbackParams(&codec);
18081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  return codec;
18181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström}
18281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
1837fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgstatic std::string CodecVectorToString(const std::vector<VideoCodec>& codecs) {
1847fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  std::stringstream out;
1857fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  out << '{';
1867fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
1877fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    out << codecs[i].ToString();
1887fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (i != codecs.size() - 1) {
1897fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      out << ", ";
1907fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
1917fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
1927fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  out << '}';
1937fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return out.str();
1947fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
1957fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
1967fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgstatic bool ValidateCodecFormats(const std::vector<VideoCodec>& codecs) {
1977fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  bool has_video = false;
1987fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
1997fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (!codecs[i].ValidateCodecFormat()) {
2007fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      return false;
2017fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
2027fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (codecs[i].GetCodecType() == VideoCodec::CODEC_VIDEO) {
2037fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      has_video = true;
2047fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
2057fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
2067fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (!has_video) {
2077fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    LOG(LS_ERROR) << "Setting codecs without a video codec is invalid: "
2087fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                  << CodecVectorToString(codecs);
2097fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return false;
2107fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
2117fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return true;
2127fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
2137fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
214d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boströmstatic bool ValidateStreamParams(const StreamParams& sp) {
215d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  if (sp.ssrcs.empty()) {
216d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString();
217d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    return false;
218d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  }
219d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström
220d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  std::vector<uint32> primary_ssrcs;
221d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  sp.GetPrimarySsrcs(&primary_ssrcs);
222d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  std::vector<uint32> rtx_ssrcs;
223d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  sp.GetFidSsrcs(primary_ssrcs, &rtx_ssrcs);
224d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  for (uint32_t rtx_ssrc : rtx_ssrcs) {
225d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    bool rtx_ssrc_present = false;
226d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    for (uint32_t sp_ssrc : sp.ssrcs) {
227d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström      if (sp_ssrc == rtx_ssrc) {
228d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström        rtx_ssrc_present = true;
229d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström        break;
230d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström      }
231d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    }
232d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    if (!rtx_ssrc_present) {
233d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström      LOG(LS_ERROR) << "RTX SSRC '" << rtx_ssrc
234d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström                    << "' missing from StreamParams ssrcs: " << sp.ToString();
235d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström      return false;
236d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    }
237d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  }
238d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  if (!rtx_ssrcs.empty() && primary_ssrcs.size() != rtx_ssrcs.size()) {
239d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    LOG(LS_ERROR)
240d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström        << "RTX SSRCs exist, but don't cover all SSRCs (unsupported): "
241d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström        << sp.ToString();
242d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    return false;
243d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  }
244d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström
245d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  return true;
246d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström}
247d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström
2487fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgstatic std::string RtpExtensionsToString(
2497fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
2507fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  std::stringstream out;
2517fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  out << '{';
2527fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  for (size_t i = 0; i < extensions.size(); ++i) {
2537fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    out << "{" << extensions[i].uri << ": " << extensions[i].id << "}";
2547fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (i != extensions.size() - 1) {
2557fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      out << ", ";
2567fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
2577fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
2587fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  out << '}';
2597fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return out.str();
2607fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
2617fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
26264c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shiehinline const webrtc::RtpExtension* FindHeaderExtension(
26364c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    const std::vector<webrtc::RtpExtension>& extensions,
26464c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    const std::string& name) {
26564c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  for (const auto& kv : extensions) {
26664c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    if (kv.name == name) {
26764c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh      return &kv;
26864c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    }
26964c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  }
27064c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  return NULL;
27164c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh}
27264c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh
27382775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org// Merges two fec configs and logs an error if a conflict arises
274e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin// such that merging in different order would trigger a different output.
27582775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.orgstatic void MergeFecConfig(const webrtc::FecConfig& other,
27682775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org                           webrtc::FecConfig* output) {
27782775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org  if (other.ulpfec_payload_type != -1) {
27882775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    if (output->ulpfec_payload_type != -1 &&
27982775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org        output->ulpfec_payload_type != other.ulpfec_payload_type) {
28082775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org      LOG(LS_WARNING) << "Conflict merging ulpfec_payload_type configs: "
28182775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org                      << output->ulpfec_payload_type << " and "
28282775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org                      << other.ulpfec_payload_type;
28382775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    }
28482775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    output->ulpfec_payload_type = other.ulpfec_payload_type;
28582775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org  }
28682775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org  if (other.red_payload_type != -1) {
28782775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    if (output->red_payload_type != -1 &&
28882775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org        output->red_payload_type != other.red_payload_type) {
28982775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org      LOG(LS_WARNING) << "Conflict merging red_payload_type configs: "
29082775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org                      << output->red_payload_type << " and "
29182775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org                      << other.red_payload_type;
29282775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    }
29382775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    output->red_payload_type = other.red_payload_type;
29482775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org  }
295e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin  if (other.red_rtx_payload_type != -1) {
296e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    if (output->red_rtx_payload_type != -1 &&
297e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin        output->red_rtx_payload_type != other.red_rtx_payload_type) {
298e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin      LOG(LS_WARNING) << "Conflict merging red_rtx_payload_type configs: "
299e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin                      << output->red_rtx_payload_type << " and "
300e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin                      << other.red_rtx_payload_type;
301e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    }
302e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    output->red_rtx_payload_type = other.red_rtx_payload_type;
303e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin  }
30482775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org}
3057fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}  // namespace
306b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
30781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström// Constants defined in talk/media/webrtc/constants.h
30881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström// TODO(pbos): Move these to a separate constants.cc file.
30981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmconst int kMinVideoBitrate = 30;
31081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmconst int kStartVideoBitrate = 300;
31181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmconst int kMaxVideoBitrate = 2000;
31281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
31381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmconst int kVideoMtu = 1200;
31481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmconst int kVideoRtpBufferSize = 65536;
31581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
316b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// This constant is really an on/off, lower-level configurable NACK history
317b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// duration hasn't been implemented.
318b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const int kNackHistoryMs = 1000;
319b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
320933d88af58b00517570ef78f38852bfd7fb1bb02buildbot@webrtc.orgstatic const int kDefaultQpMax = 56;
321933d88af58b00517570ef78f38852bfd7fb1bb02buildbot@webrtc.org
322b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const int kDefaultRtcpReceiverReportSsrc = 1;
323b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
324e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmerconst int kMinBandwidthBps = 30000;
325e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmerconst int kStartBandwidthBps = 300000;
326e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmerconst int kMaxBandwidthBps = 2000000;
327e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer
32881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmstd::vector<VideoCodec> DefaultVideoCodecList() {
32981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  std::vector<VideoCodec> codecs;
33081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  if (CodecIsInternallySupported(kVp9CodecName)) {
33181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultVp9PlType,
33281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                                                             kVp9CodecName));
33381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    // TODO(andresp): Add rtx codec for vp9 and verify it works.
33481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
33581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultVp8PlType,
33681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                                                           kVp8CodecName));
33771f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin  if (CodecIsInternallySupported(kH264CodecName)) {
33871f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin    codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultH264PlType,
33971f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin                                                             kH264CodecName));
34071f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin  }
34181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  codecs.push_back(
34281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      VideoCodec::CreateRtxCodec(kDefaultRtxVp8PlType, kDefaultVp8PlType));
34381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  codecs.push_back(VideoCodec(kDefaultRedPlType, kRedCodecName));
34481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  codecs.push_back(VideoCodec(kDefaultUlpfecType, kUlpfecCodecName));
34581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  return codecs;
34681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström}
34781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
348b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic bool FindFirstMatchingCodec(const std::vector<VideoCodec>& codecs,
349b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                   const VideoCodec& requested_codec,
350b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                   VideoCodec* matching_codec) {
351b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
352b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (requested_codec.Matches(codecs[i])) {
353b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      *matching_codec = codecs[i];
354b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return true;
355b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
356b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
357b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return false;
358b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
359b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
3603c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.orgstatic bool ValidateRtpHeaderExtensionIds(
3613c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
3623c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  std::set<int> extensions_used;
3633c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  for (size_t i = 0; i < extensions.size(); ++i) {
36423914fe756903353eae13fffc868d2c84f51f06fPeter Boström    if (extensions[i].id <= 0 || extensions[i].id >= 15 ||
3653c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org        !extensions_used.insert(extensions[i].id).second) {
3663c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org      LOG(LS_ERROR) << "RTP extensions are with incorrect or duplicate ids.";
3673c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org      return false;
3683c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    }
3693c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  }
3703c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  return true;
3713c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org}
3723c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org
373c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.orgstatic bool CompareRtpHeaderExtensionIds(
374c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org    const webrtc::RtpExtension& extension1,
375c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org    const webrtc::RtpExtension& extension2) {
376c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org  // Sorting on ID is sufficient, more than one extension per ID is unsupported.
377c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org  return extension1.id > extension2.id;
378c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org}
379c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org
3803c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.orgstatic std::vector<webrtc::RtpExtension> FilterRtpExtensions(
3813c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
3823c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  std::vector<webrtc::RtpExtension> webrtc_extensions;
3833c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  for (size_t i = 0; i < extensions.size(); ++i) {
3843c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    // Unsupported extensions will be ignored.
38523fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg    if (webrtc::RtpExtension::IsSupportedForVideo(extensions[i].uri)) {
3863c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org      webrtc_extensions.push_back(webrtc::RtpExtension(
3873c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org          extensions[i].uri, extensions[i].id));
3883c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    } else {
3893c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org      LOG(LS_WARNING) << "Unsupported RTP extension: " << extensions[i].uri;
3903c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    }
3913c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  }
392c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org
393c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org  // Sort filtered headers to make sure that they can later be compared
394c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org  // regardless of in which order they were entered.
395c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org  std::sort(webrtc_extensions.begin(), webrtc_extensions.end(),
396c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org            CompareRtpHeaderExtensionIds);
3973c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  return webrtc_extensions;
3983c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org}
3993c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org
400c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.orgstatic bool RtpExtensionsHaveChanged(
401c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org    const std::vector<webrtc::RtpExtension>& before,
402c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org    const std::vector<webrtc::RtpExtension>& after) {
403c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org  if (before.size() != after.size())
404c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org    return true;
405c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org  for (size_t i = 0; i < before.size(); ++i) {
406c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org    if (before[i].id != after[i].id)
407c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org      return true;
408c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org    if (before[i].name != after[i].name)
409c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org      return true;
410c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org  }
411c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org  return false;
412c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org}
413c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org
414a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.orgstd::vector<webrtc::VideoStream>
415f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::CreateSimulcastVideoStreams(
416d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    const VideoCodec& codec,
417d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    const VideoOptions& options,
418dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    int max_bitrate_bps,
419d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    size_t num_streams) {
420a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org  int max_qp = kDefaultQpMax;
421a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org  codec.GetParam(kCodecParamMaxQuantization, &max_qp);
422a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org
423a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org  return GetSimulcastConfig(
424dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström      num_streams, GetSimulcastBitrateMode(options), codec.width, codec.height,
425dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström      max_bitrate_bps, max_qp,
426a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org      codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate);
427a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org}
428a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org
429f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.orgstd::vector<webrtc::VideoStream>
430f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoStreams(
431a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org    const VideoCodec& codec,
432a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org    const VideoOptions& options,
433dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    int max_bitrate_bps,
434a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org    size_t num_streams) {
435dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  int codec_max_bitrate_kbps;
436dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  if (codec.GetParam(kCodecParamMaxBitrate, &codec_max_bitrate_kbps)) {
437dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    max_bitrate_bps = codec_max_bitrate_kbps * 1000;
438dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  }
439dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  if (num_streams != 1) {
440dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    return CreateSimulcastVideoStreams(codec, options, max_bitrate_bps,
441dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström                                       num_streams);
442dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  }
443dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström
444dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  // For unset max bitrates set default bitrate for non-simulcast.
445dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  if (max_bitrate_bps <= 0)
446dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    max_bitrate_bps = kMaxVideoBitrate * 1000;
447a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org
448d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  webrtc::VideoStream stream;
449d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.width = codec.width;
450d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.height = codec.height;
451d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.max_framerate =
45282775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org      codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate;
453d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org
454008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  stream.min_bitrate_bps = kMinVideoBitrate * 1000;
455dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate_bps;
456d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org
457933d88af58b00517570ef78f38852bfd7fb1bb02buildbot@webrtc.org  int max_qp = kDefaultQpMax;
458d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  codec.GetParam(kCodecParamMaxQuantization, &max_qp);
459d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.max_qp = max_qp;
460d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  std::vector<webrtc::VideoStream> streams;
461d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  streams.push_back(stream);
462d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  return streams;
463d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org}
464b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
465f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.orgvoid* WebRtcVideoChannel2::WebRtcVideoSendStream::ConfigureVideoEncoderSettings(
4666f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    const VideoCodec& codec,
467143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng    const VideoOptions& options,
468143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng    bool is_screencast) {
469143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng  // No automatic resizing when using simulcast.
470143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng  bool automatic_resize = !is_screencast && ssrcs_.size() == 1;
471143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng  bool frame_dropping = !is_screencast;
472143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng  bool denoising;
473143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng  if (is_screencast) {
474143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng    denoising = false;
475143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng  } else {
476143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng    options.video_noise_reduction.Get(&denoising);
477143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng  }
478143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng
479e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin  if (CodecNamesEq(codec.name, kVp8CodecName)) {
480f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.org    encoder_settings_.vp8 = webrtc::VideoEncoder::GetDefaultVp8Settings();
481143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng    encoder_settings_.vp8.automaticResizeOn = automatic_resize;
482143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng    encoder_settings_.vp8.denoisingOn = denoising;
483143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng    encoder_settings_.vp8.frameDroppingOn = frame_dropping;
484f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.org    return &encoder_settings_.vp8;
4856f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  }
486e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin  if (CodecNamesEq(codec.name, kVp9CodecName)) {
487f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.org    encoder_settings_.vp9 = webrtc::VideoEncoder::GetDefaultVp9Settings();
488143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng    encoder_settings_.vp9.denoisingOn = denoising;
489143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng    encoder_settings_.vp9.frameDroppingOn = frame_dropping;
490f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.org    return &encoder_settings_.vp9;
491188d3b2245b49f21468840386d81b080176b434bandresp@webrtc.org  }
4926f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  return NULL;
4936f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org}
4946f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
495afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.orgDefaultUnsignalledSsrcHandler::DefaultUnsignalledSsrcHandler()
496afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    : default_recv_ssrc_(0), default_renderer_(NULL) {}
497afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
498afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.orgUnsignalledSsrcHandler::Action DefaultUnsignalledSsrcHandler::OnUnsignalledSsrc(
499a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org    WebRtcVideoChannel2* channel,
500afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    uint32_t ssrc) {
501afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  if (default_recv_ssrc_ != 0) {  // Already one default stream.
502afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    LOG(LS_WARNING) << "Unknown SSRC, but default receive stream already set.";
503afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    return kDropPacket;
504afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  }
505afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
506afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  StreamParams sp;
507afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  sp.ssrcs.push_back(ssrc);
508afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  LOG(LS_INFO) << "Creating default receive stream for SSRC=" << ssrc << ".";
509a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org  if (!channel->AddRecvStream(sp, true)) {
510afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    LOG(LS_WARNING) << "Could not create default receive stream.";
511afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  }
512afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
513afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  channel->SetRenderer(ssrc, default_renderer_);
514afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  default_recv_ssrc_ = ssrc;
515afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  return kDeliverPacket;
516afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org}
517afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
51842684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.orgWebRtcCallFactory::~WebRtcCallFactory() {
51942684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org}
52042684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.orgwebrtc::Call* WebRtcCallFactory::CreateCall(
52142684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org    const webrtc::Call::Config& config) {
52242684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  return webrtc::Call::Create(config);
52342684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org}
52442684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org
525afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.orgVideoRenderer* DefaultUnsignalledSsrcHandler::GetDefaultRenderer() const {
526afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  return default_renderer_;
527afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org}
528afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
529afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.orgvoid DefaultUnsignalledSsrcHandler::SetDefaultRenderer(
530afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    VideoMediaChannel* channel,
531afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    VideoRenderer* renderer) {
532afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  default_renderer_ = renderer;
533afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  if (default_recv_ssrc_ != 0) {
534afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    channel->SetRenderer(default_recv_ssrc_, default_renderer_);
535afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  }
536afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org}
537afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
538f1f0d9a4cd53f4eacbf791cb7317612fa7382a45pbos@webrtc.orgWebRtcVideoEngine2::WebRtcVideoEngine2(WebRtcVoiceEngine* voice_engine)
5399a416bd14ee225d8f1a1ada627a1dd7daf275032Fredrik Solenberg    : voice_engine_(voice_engine),
540b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      initialized_(false),
54142684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org      call_factory_(&default_call_factory_),
5420a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org      external_decoder_factory_(NULL),
5430a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org      external_encoder_factory_(NULL) {
544b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::WebRtcVideoEngine2()";
5457fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  video_codecs_ = GetSupportedCodecs();
546587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  rtp_header_extensions_.push_back(
547587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org      RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension,
548587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org                         kRtpTimestampOffsetHeaderExtensionDefaultId));
549587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  rtp_header_extensions_.push_back(
550587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org      RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
551587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org                         kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
55264c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  rtp_header_extensions_.push_back(
55364c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh      RtpHeaderExtension(kRtpVideoRotationHeaderExtension,
55464c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh                         kRtpVideoRotationHeaderExtensionDefaultId));
555b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
556b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
557b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoEngine2::~WebRtcVideoEngine2() {
558b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::~WebRtcVideoEngine2";
559b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
560b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
56142684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.orgvoid WebRtcVideoEngine2::SetCallFactory(WebRtcCallFactory* call_factory) {
562d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  DCHECK(!initialized_);
56342684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  call_factory_ = call_factory;
56442684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org}
56542684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org
5669a416bd14ee225d8f1a1ada627a1dd7daf275032Fredrik Solenbergvoid WebRtcVideoEngine2::Init() {
567b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::Init";
568b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  initialized_ = true;
569b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
570b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
571b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgint WebRtcVideoEngine2::GetCapabilities() { return VIDEO_RECV | VIDEO_SEND; }
572b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
573b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::SetDefaultEncoderConfig(
574b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoEncoderConfig& config) {
5758fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  const VideoCodec& codec = config.max_codec;
576957e802fe0e6e765425955cc1e3e02f73d1a670bpbos@webrtc.org  bool supports_codec = false;
577957e802fe0e6e765425955cc1e3e02f73d1a670bpbos@webrtc.org  for (size_t i = 0; i < video_codecs_.size(); ++i) {
578e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    if (CodecNamesEq(video_codecs_[i].name, codec.name)) {
5792a72c6506a49b15d5e079eaa28cb80abb445684bpbos@webrtc.org      video_codecs_[i].width = codec.width;
5802a72c6506a49b15d5e079eaa28cb80abb445684bpbos@webrtc.org      video_codecs_[i].height = codec.height;
5812a72c6506a49b15d5e079eaa28cb80abb445684bpbos@webrtc.org      video_codecs_[i].framerate = codec.framerate;
582957e802fe0e6e765425955cc1e3e02f73d1a670bpbos@webrtc.org      supports_codec = true;
583957e802fe0e6e765425955cc1e3e02f73d1a670bpbos@webrtc.org      break;
584957e802fe0e6e765425955cc1e3e02f73d1a670bpbos@webrtc.org    }
585957e802fe0e6e765425955cc1e3e02f73d1a670bpbos@webrtc.org  }
586957e802fe0e6e765425955cc1e3e02f73d1a670bpbos@webrtc.org
587957e802fe0e6e765425955cc1e3e02f73d1a670bpbos@webrtc.org  if (!supports_codec) {
588957e802fe0e6e765425955cc1e3e02f73d1a670bpbos@webrtc.org    LOG(LS_ERROR) << "SetDefaultEncoderConfig, codec not supported: "
5898fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org                  << codec.ToString();
5908fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    return false;
5918fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  }
5928fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org
593b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
594b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
595b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
596b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2* WebRtcVideoEngine2::CreateChannel(
5971ecbe45c7e4c9142896cb2810d699558518f4f28buildbot@webrtc.org    const VideoOptions& options,
598b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VoiceMediaChannel* voice_channel) {
599d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  DCHECK(initialized_);
600b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "CreateChannel: "
601b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org               << (voice_channel != NULL ? "With" : "Without")
602fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org               << " voice channel. Options: " << options.ToString();
6037fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  WebRtcVideoChannel2* channel =
6044b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg      new WebRtcVideoChannel2(call_factory_, voice_engine_,
6054b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg          static_cast<WebRtcVoiceMediaChannel*>(voice_channel), options,
6064b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg          external_encoder_factory_, external_decoder_factory_);
607b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!channel->Init()) {
608b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    delete channel;
609b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return NULL;
610b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
611e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  channel->SetRecvCodecs(video_codecs_);
612b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return channel;
613b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
614b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
615b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgconst std::vector<VideoCodec>& WebRtcVideoEngine2::codecs() const {
616b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return video_codecs_;
617b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
618b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
619b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgconst std::vector<RtpHeaderExtension>&
620b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoEngine2::rtp_header_extensions() const {
621b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return rtp_header_extensions_;
622b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
623b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
624b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoEngine2::SetLogging(int min_sev, const char* filter) {
625b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Set up logging.
626b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetLogging: " << min_sev << '"' << filter << '"';
627b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // if min_sev == -1, we keep the current log level.
628b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (min_sev < 0) {
629d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg    DCHECK(min_sev == -1);
630b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
631b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
632b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
633b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
6340a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.orgvoid WebRtcVideoEngine2::SetExternalDecoderFactory(
6350a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org    WebRtcVideoDecoderFactory* decoder_factory) {
636d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  DCHECK(!initialized_);
6370a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  external_decoder_factory_ = decoder_factory;
6380a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org}
6390a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org
6400a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.orgvoid WebRtcVideoEngine2::SetExternalEncoderFactory(
6410a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org    WebRtcVideoEncoderFactory* encoder_factory) {
642d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  DCHECK(!initialized_);
643f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org  if (external_encoder_factory_ == encoder_factory)
644f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org    return;
645f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org
646f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org  // No matter what happens we shouldn't hold on to a stale
647f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org  // WebRtcSimulcastEncoderFactory.
648f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org  simulcast_encoder_factory_.reset();
649f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org
650f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org  if (encoder_factory &&
651f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org      WebRtcSimulcastEncoderFactory::UseSimulcastEncoderFactory(
652f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org          encoder_factory->codecs())) {
653f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org    simulcast_encoder_factory_.reset(
654f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org        new WebRtcSimulcastEncoderFactory(encoder_factory));
655f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org    encoder_factory = simulcast_encoder_factory_.get();
656f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org  }
6570a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  external_encoder_factory_ = encoder_factory;
6587fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
6597fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  video_codecs_ = GetSupportedCodecs();
6600a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org}
6610a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org
662b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::EnableTimedRender() {
663b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Figure out whether this can be removed.
664b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
665b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
666b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
667b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// Checks to see whether we comprehend and could receive a particular codec
668b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::FindCodec(const VideoCodec& in) {
669b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Probe encoder factory to figure out that the codec is supported
670b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // if supported by the encoder factory. Add a corresponding test that fails
671b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // with this code (that doesn't ask the factory).
6728fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  for (size_t j = 0; j < video_codecs_.size(); ++j) {
6738fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    VideoCodec codec(video_codecs_[j].id, video_codecs_[j].name, 0, 0, 0, 0);
6748fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    if (codec.Matches(in)) {
6758fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org      return true;
676b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
677b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
678b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return false;
679b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
680b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
681b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// Tells whether the |requested| codec can be transmitted or not. If it can be
682b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// transmitted |out| is set with the best settings supported. Aspect ratio will
683b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// be set as close to |current|'s as possible. If not set |requested|'s
684b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// dimensions will be used for aspect ratio matching.
685b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::CanSendCodec(const VideoCodec& requested,
686b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                      const VideoCodec& current,
687b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                      VideoCodec* out) {
688d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  DCHECK(out != NULL);
689b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
690b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (requested.width != requested.height &&
691b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      (requested.height == 0 || requested.width == 0)) {
692b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // 0xn and nx0 are invalid resolutions.
693b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
694b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
695b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
696b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  VideoCodec matching_codec;
697b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!FindFirstMatchingCodec(video_codecs_, requested, &matching_codec)) {
698b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // Codec not supported.
699b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
700b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
701b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
702b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->id = requested.id;
703b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->name = requested.name;
704b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->preference = requested.preference;
705b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->params = requested.params;
706ff689be3c0c59c1be29aaa0697aa0f762566d6c6andresp@webrtc.org  out->framerate = std::min(requested.framerate, matching_codec.framerate);
707b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->params = requested.params;
708b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  out->feedback_params = requested.feedback_params;
7098fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  out->width = requested.width;
7108fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  out->height = requested.height;
7118fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  if (requested.width == 0 && requested.height == 0) {
7128fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    return true;
7138fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  }
7148fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org
7158fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  while (out->width > matching_codec.width) {
7168fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    out->width /= 2;
7178fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    out->height /= 2;
7188fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  }
7198fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org
7208fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  return out->width > 0 && out->height > 0;
721b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
722b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
723b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// Ignore spammy trace messages, mostly from the stats API when we haven't
724b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// gotten RTCP info yet from the remote side.
725b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::ShouldIgnoreTrace(const std::string& trace) {
726b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  static const char* const kTracesToIgnore[] = {NULL};
727b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (const char* const* p = kTracesToIgnore; *p; ++p) {
728b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (trace.find(*p) == 0) {
729b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return true;
730b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
731b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
732b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return false;
733b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
734b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
7357fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgstd::vector<VideoCodec> WebRtcVideoEngine2::GetSupportedCodecs() const {
73682775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org  std::vector<VideoCodec> supported_codecs = DefaultVideoCodecList();
7377fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
7387fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (external_encoder_factory_ == NULL) {
7397fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return supported_codecs;
7407fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
7417fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
7427fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs =
7437fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      external_encoder_factory_->codecs();
7447fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
7457fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    // Don't add internally-supported codecs twice.
7467fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (CodecIsInternallySupported(codecs[i].name)) {
7477fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      continue;
7487fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
7497fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
750d324546ced76d4e792338af4f7d02a5cd8819f92pkasting@chromium.org    // External video encoders are given payloads 120-127. This also means that
751d324546ced76d4e792338af4f7d02a5cd8819f92pkasting@chromium.org    // we only support up to 8 external payload types.
752d324546ced76d4e792338af4f7d02a5cd8819f92pkasting@chromium.org    const int kExternalVideoPayloadTypeBase = 120;
753d324546ced76d4e792338af4f7d02a5cd8819f92pkasting@chromium.org    size_t payload_type = kExternalVideoPayloadTypeBase + i;
754d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg    DCHECK(payload_type < 128);
755d324546ced76d4e792338af4f7d02a5cd8819f92pkasting@chromium.org    VideoCodec codec(static_cast<int>(payload_type),
7567fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                     codecs[i].name,
7577fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                     codecs[i].max_width,
7587fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                     codecs[i].max_height,
7597fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                     codecs[i].max_fps,
7607fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                     0);
7617fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
7627fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    AddDefaultFeedbackParams(&codec);
7637fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    supported_codecs.push_back(codec);
7647fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
7657fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return supported_codecs;
7667fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
7677fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
768b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoChannel2(
76942684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org    WebRtcCallFactory* call_factory,
7703bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org    WebRtcVoiceEngine* voice_engine,
7714b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg    WebRtcVoiceMediaChannel* voice_channel,
772fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org    const VideoOptions& options,
7737fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    WebRtcVideoEncoderFactory* external_encoder_factory,
774f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.org    WebRtcVideoDecoderFactory* external_decoder_factory)
775b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org    : unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_),
7764b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg      voice_channel_(voice_channel),
7774b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg      voice_channel_id_(voice_channel ? voice_channel->voe_channel() : -1),
7787fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      external_encoder_factory_(external_encoder_factory),
779f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.org      external_decoder_factory_(external_decoder_factory) {
7804b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg  DCHECK(thread_checker_.CalledOnValidThread());
781fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org  SetDefaultOptions();
782fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org  options_.SetAll(options);
783e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  options_.cpu_overuse_detection.Get(&signal_cpu_adaptation_);
784b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  webrtc::Call::Config config(this);
78542684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  config.overuse_callback = this;
7863bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org  if (voice_engine != NULL) {
7873bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org    config.voice_engine = voice_engine->voe()->engine();
7883bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org  }
789e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  config.bitrate_config.min_bitrate_bps = kMinBandwidthBps;
790e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  config.bitrate_config.start_bitrate_bps = kStartBandwidthBps;
791e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  config.bitrate_config.max_bitrate_bps = kMaxBandwidthBps;
79242684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  call_.reset(call_factory->CreateCall(config));
7934b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg  if (voice_channel_) {
7944b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg    voice_channel_->SetCall(call_.get());
7954b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg  }
796b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  rtcp_receiver_report_ssrc_ = kDefaultRtcpReceiverReportSsrc;
797b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = false;
798b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  default_send_ssrc_ = 0;
7996f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org}
8006f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
8016f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.orgvoid WebRtcVideoChannel2::SetDefaultOptions() {
802e432800aeb6b695bda14acf2d60c0200803b5218Peter Boström  options_.cpu_overuse_detection.Set(true);
803d819803d4570564a9800a7dd54f4593e6e21a6e7pbos@webrtc.org  options_.dscp.Set(false);
8045ff71ab4b369fe3dbfaec5f91cd2e491397eff33pbos@webrtc.org  options_.suspend_below_min_bitrate.Set(false);
80542684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  options_.video_noise_reduction.Set(true);
806efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org  options_.screencast_min_bitrate.Set(0);
807b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
808b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
809b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::~WebRtcVideoChannel2() {
8104b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg  DetachVoiceChannel();
811dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  for (auto& kv : send_streams_)
812dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    delete kv.second;
813dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  for (auto& kv : receive_streams_)
814dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    delete kv.second;
815b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
816b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
817b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::Init() { return true; }
818b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
8194b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenbergvoid WebRtcVideoChannel2::DetachVoiceChannel() {
8204b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg  DCHECK(thread_checker_.CalledOnValidThread());
8214b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg  if (voice_channel_) {
8224b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg    voice_channel_->SetCall(nullptr);
8234b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg    voice_channel_ = nullptr;
8244b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg  }
8254b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg}
8264b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg
82796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.orgbool WebRtcVideoChannel2::CodecIsExternallySupported(
82896a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    const std::string& name) const {
82996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  if (external_encoder_factory_ == NULL) {
83096a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    return false;
83196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  }
83296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org
83396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  const std::vector<WebRtcVideoEncoderFactory::VideoCodec> external_codecs =
83496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      external_encoder_factory_->codecs();
83596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  for (size_t c = 0; c < external_codecs.size(); ++c) {
836e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    if (CodecNamesEq(name, external_codecs[c].name)) {
83796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      return true;
83896a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    }
83996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  }
84096a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  return false;
84196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org}
84296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org
84396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.orgstd::vector<WebRtcVideoChannel2::VideoCodecSettings>
84496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.orgWebRtcVideoChannel2::FilterSupportedCodecs(
84596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    const std::vector<WebRtcVideoChannel2::VideoCodecSettings>& mapped_codecs)
84696a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    const {
84796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  std::vector<VideoCodecSettings> supported_codecs;
84896a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  for (size_t i = 0; i < mapped_codecs.size(); ++i) {
84996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    const VideoCodecSettings& codec = mapped_codecs[i];
85096a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    if (CodecIsInternallySupported(codec.codec.name) ||
85196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org        CodecIsExternallySupported(codec.codec.name)) {
85296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      supported_codecs.push_back(codec);
85396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    }
85496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  }
85596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  return supported_codecs;
85696a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org}
85796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org
858b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) {
85950fe359eb614e1bbe41124b9c19263019da0395dpbos@webrtc.org  TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetRecvCodecs");
860b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetRecvCodecs: " << CodecVectorToString(codecs);
861b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!ValidateCodecFormats(codecs)) {
862b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
863b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
864b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
865b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const std::vector<VideoCodecSettings> mapped_codecs = MapCodecs(codecs);
866b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (mapped_codecs.empty()) {
86796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    LOG(LS_ERROR) << "SetRecvCodecs called without any video codecs.";
868b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
869b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
870b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
87196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  const std::vector<VideoCodecSettings> supported_codecs =
87296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      FilterSupportedCodecs(mapped_codecs);
87396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org
87496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  if (mapped_codecs.size() != supported_codecs.size()) {
87596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    LOG(LS_ERROR) << "SetRecvCodecs called with unsupported video codecs.";
87696a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    return false;
877b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
878b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
879ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström  // Prevent reconfiguration when setting identical receive codecs.
880ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström  if (recv_codecs_.size() == supported_codecs.size()) {
881ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström    bool reconfigured = false;
882ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström    for (size_t i = 0; i < supported_codecs.size(); ++i) {
883ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström      if (recv_codecs_[i] != supported_codecs[i]) {
884ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström        reconfigured = true;
885ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström        break;
886ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström      }
887ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström    }
888ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström    if (!reconfigured)
889ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström      return true;
890ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström  }
891ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström
89296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  recv_codecs_ = supported_codecs;
893d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
894575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
895d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
896d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org           receive_streams_.begin();
897d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       it != receive_streams_.end();
898d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       ++it) {
899d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    it->second->SetRecvCodecs(recv_codecs_);
900d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
901d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
902b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
903b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
904b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
905b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) {
90650fe359eb614e1bbe41124b9c19263019da0395dpbos@webrtc.org  TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetSendCodecs");
907b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetSendCodecs: " << CodecVectorToString(codecs);
908b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!ValidateCodecFormats(codecs)) {
909b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
910b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
911b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
912b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const std::vector<VideoCodecSettings> supported_codecs =
913b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      FilterSupportedCodecs(MapCodecs(codecs));
914b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
915b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (supported_codecs.empty()) {
9163c3f6460646183914629e5dab8ae5fcede4f0e80Peter Boström    LOG(LS_ERROR) << "No video codecs supported.";
917b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
918b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
919b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
920b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "Using codec: " << supported_codecs.front().codec.ToString();
921b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
922a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  VideoCodecSettings old_codec;
923a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  if (send_codec_.Get(&old_codec) && supported_codecs.front() == old_codec) {
924a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    // Using same codec, avoid reconfiguring.
925a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    return true;
926a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  }
927a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
928a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  send_codec_.Set(supported_codecs.front());
929a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
930575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
931126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström  for (auto& kv : send_streams_) {
932126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström    DCHECK(kv.second != nullptr);
933126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström    kv.second->SetCodec(supported_codecs.front());
934126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström  }
935126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström  for (auto& kv : receive_streams_) {
936126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström    DCHECK(kv.second != nullptr);
93767c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström    kv.second->SetNackAndRemb(HasNack(supported_codecs.front().codec),
93867c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström                              HasRemb(supported_codecs.front().codec));
939d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
940b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
941e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  // TODO(holmer): Changing the codec parameters shouldn't necessarily mean that
942e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  // we change the min/max of bandwidth estimation. Reevaluate this.
943008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  VideoCodec codec = supported_codecs.front().codec;
944008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  int bitrate_kbps;
945008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  if (codec.GetParam(kCodecParamMinBitrate, &bitrate_kbps) &&
946008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org      bitrate_kbps > 0) {
947008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    bitrate_config_.min_bitrate_bps = bitrate_kbps * 1000;
948008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  } else {
949008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    bitrate_config_.min_bitrate_bps = 0;
950008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  }
951008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  if (codec.GetParam(kCodecParamStartBitrate, &bitrate_kbps) &&
952008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org      bitrate_kbps > 0) {
953008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    bitrate_config_.start_bitrate_bps = bitrate_kbps * 1000;
954008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  } else {
955008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    // Do not reconfigure start bitrate unless it's specified and positive.
956008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    bitrate_config_.start_bitrate_bps = -1;
957008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  }
958008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  if (codec.GetParam(kCodecParamMaxBitrate, &bitrate_kbps) &&
959008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org      bitrate_kbps > 0) {
960008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    bitrate_config_.max_bitrate_bps = bitrate_kbps * 1000;
961008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  } else {
962008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    bitrate_config_.max_bitrate_bps = -1;
963008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  }
964008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  call_->SetBitrateConfig(bitrate_config_);
965008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org
966b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
967b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
968b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
969b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::GetSendCodec(VideoCodec* codec) {
970b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  VideoCodecSettings codec_settings;
971b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!send_codec_.Get(&codec_settings)) {
972b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_VERBOSE) << "GetSendCodec: No send codec set.";
973b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
974b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
975b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  *codec = codec_settings.codec;
976b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
977b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
978b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
979b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSendStreamFormat(uint32 ssrc,
980b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                              const VideoFormat& format) {
981b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetSendStreamFormat:" << ssrc << " -> "
982b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << format.ToString();
983575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
984b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send_streams_.find(ssrc) == send_streams_.end()) {
985b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
986b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
987b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return send_streams_[ssrc]->SetVideoFormat(format);
988b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
989b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
990b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRender(bool render) {
991b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement. Or refactor away as it shouldn't be needed.
992b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetRender: " << (render ? "true" : "false");
993b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
994b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
995b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
996b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSend(bool send) {
997b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetSend: " << (send ? "true" : "false");
998b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send && !send_codec_.IsSet()) {
999b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "SetSend(true) called before setting codec.";
1000b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1001b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1002b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send) {
1003b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    StartAllSendStreams();
1004b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  } else {
1005b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    StopAllSendStreams();
1006b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1007b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = send;
1008b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1009b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1010b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1011d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boströmbool WebRtcVideoChannel2::ValidateSendSsrcAvailability(
1012d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    const StreamParams& sp) const {
1013d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  for (uint32_t ssrc: sp.ssrcs) {
1014d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    if (send_ssrcs_.find(ssrc) != send_ssrcs_.end()) {
1015d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström      LOG(LS_ERROR) << "Send stream with SSRC '" << ssrc << "' already exists.";
1016d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström      return false;
1017d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    }
1018d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  }
1019d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  return true;
1020d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström}
1021d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
1022d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boströmbool WebRtcVideoChannel2::ValidateReceiveSsrcAvailability(
1023d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    const StreamParams& sp) const {
1024d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  for (uint32_t ssrc: sp.ssrcs) {
1025d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    if (receive_ssrcs_.find(ssrc) != receive_ssrcs_.end()) {
1026d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström      LOG(LS_ERROR) << "Receive stream with SSRC '" << ssrc
1027d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström                    << "' already exists.";
1028d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström      return false;
1029d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    }
1030d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  }
1031d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  return true;
1032d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström}
1033d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
1034b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) {
1035b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
1036d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  if (!ValidateStreamParams(sp))
1037b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1038b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1039575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1040d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
1041d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  if (!ValidateSendSsrcAvailability(sp))
1042b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1043d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
1044d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  for (uint32 used_ssrc : sp.ssrcs)
1045d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    send_ssrcs_.insert(used_ssrc);
1046b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1047b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  WebRtcVideoSendStream* stream =
10486ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org      new WebRtcVideoSendStream(call_.get(),
10497fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                                external_encoder_factory_,
10506ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org                                options_,
1051dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström                                bitrate_config_.max_bitrate_bps,
10525301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                                send_codec_,
10535301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                                sp,
10545301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                                send_rtp_extensions_);
10555301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
1056d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  uint32 ssrc = sp.first_ssrc();
1057d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  DCHECK(ssrc != 0);
1058b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  send_streams_[ssrc] = stream;
1059b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1060b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (rtcp_receiver_report_ssrc_ == kDefaultRtcpReceiverReportSsrc) {
1061b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    rtcp_receiver_report_ssrc_ = ssrc;
10623548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström    for (auto& kv : receive_streams_)
10633548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström      kv.second->SetLocalSsrc(ssrc);
1064b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1065b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (default_send_ssrc_ == 0) {
1066b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    default_send_ssrc_ = ssrc;
1067b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1068b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (sending_) {
1069b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    stream->Start();
1070b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1071b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1072b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1073b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1074b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1075b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::RemoveSendStream(uint32 ssrc) {
1076b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
1077b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1078b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1079b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (default_send_ssrc_ == 0) {
1080b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_ERROR) << "No default send stream active.";
1081b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return false;
1082b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1083b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1084b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_VERBOSE) << "Removing default stream: " << default_send_ssrc_;
1085b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    ssrc = default_send_ssrc_;
1086b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1087b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1088575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  WebRtcVideoSendStream* removed_stream;
1089575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  {
1090575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    rtc::CritScope stream_lock(&stream_crit_);
1091575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1092575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org        send_streams_.find(ssrc);
1093575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    if (it == send_streams_.end()) {
1094575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org      return false;
1095575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    }
1096575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org
1097d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    for (uint32 old_ssrc : it->second->GetSsrcs())
1098d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström      send_ssrcs_.erase(old_ssrc);
1099d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
1100575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    removed_stream = it->second;
1101575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    send_streams_.erase(it);
1102b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1103b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1104575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  delete removed_stream;
1105b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1106b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == default_send_ssrc_) {
1107b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    default_send_ssrc_ = 0;
1108b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1109b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1110b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1111b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1112b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1113d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boströmvoid WebRtcVideoChannel2::DeleteReceiveStream(
1114d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    WebRtcVideoChannel2::WebRtcVideoReceiveStream* stream) {
1115d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  for (uint32 old_ssrc : stream->GetSsrcs())
1116d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    receive_ssrcs_.erase(old_ssrc);
1117d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  delete stream;
1118d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström}
1119d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
1120b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp) {
1121a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org  return AddRecvStream(sp, false);
1122a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org}
1123a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org
1124a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.orgbool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp,
1125a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org                                        bool default_stream) {
11264b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg  DCHECK(thread_checker_.CalledOnValidThread());
11274b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg
1128d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  LOG(LS_INFO) << "AddRecvStream" << (default_stream ? " (default stream)" : "")
1129d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström               << ": " << sp.ToString();
1130d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  if (!ValidateStreamParams(sp))
1131d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    return false;
1132b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1133b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  uint32 ssrc = sp.first_ssrc();
1134d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  DCHECK(ssrc != 0);  // TODO(pbos): Is this ever valid?
1135b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1136575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1137d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  // Remove running stream if this was a default stream.
1138d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  auto prev_stream = receive_streams_.find(ssrc);
1139d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  if (prev_stream != receive_streams_.end()) {
1140d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    if (default_stream || !prev_stream->second->IsDefaultStream()) {
1141d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström      LOG(LS_ERROR) << "Receive stream for SSRC '" << ssrc
1142d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström                    << "' already exists.";
1143d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström      return false;
1144a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org    }
1145d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    DeleteReceiveStream(prev_stream->second);
1146d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    receive_streams_.erase(prev_stream);
1147b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1148b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1149d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  if (!ValidateReceiveSsrcAvailability(sp))
1150d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    return false;
1151d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
1152d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  for (uint32 used_ssrc : sp.ssrcs)
1153d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    receive_ssrcs_.insert(used_ssrc);
1154d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
1155bd249bc711b3c9efd142eb8de3df489282fe693epbos@webrtc.org  webrtc::VideoReceiveStream::Config config;
1156d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  ConfigureReceiverRtp(&config, sp);
11573bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org
11588fc7fa798f7a36955f1b933980401afad2aff592pbos  // Set up A/V sync group based on sync label.
11598fc7fa798f7a36955f1b933980401afad2aff592pbos  config.sync_group = sp.sync_label;
11603bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org
1161126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström  config.rtp.remb = false;
1162126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström  VideoCodecSettings send_codec;
1163126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström  if (send_codec_.Get(&send_codec)) {
1164126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström    config.rtp.remb = HasRemb(send_codec.codec);
1165126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström  }
1166126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström
1167d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  receive_streams_[ssrc] = new WebRtcVideoReceiveStream(
1168259bd2034c3d3ee7f2dc4d481e9bf896a3a4d6efPeter Boström      call_.get(), sp, external_decoder_factory_, default_stream, config,
1169d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström      recv_codecs_);
1170d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1171d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  return true;
1172d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1173d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1174d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::ConfigureReceiverRtp(
1175d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    webrtc::VideoReceiveStream::Config* config,
1176d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const StreamParams& sp) const {
1177d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  uint32 ssrc = sp.first_ssrc();
1178d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1179d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config->rtp.remote_ssrc = ssrc;
1180d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config->rtp.local_ssrc = rtcp_receiver_report_ssrc_;
1181b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1182d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config->rtp.extensions = recv_rtp_extensions_;
1183257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org
1184b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): This protection is against setting the same local ssrc as
1185b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // remote which is not permitted by the lower-level API. RTCP requires a
1186b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // corresponding sender SSRC. Figure out what to do when we don't have
1187b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // (receive-only) or know a good local SSRC.
1188d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (config->rtp.remote_ssrc == config->rtp.local_ssrc) {
1189d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    if (config->rtp.local_ssrc != kDefaultRtcpReceiverReportSsrc) {
1190d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc;
1191b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    } else {
1192d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc + 1;
1193b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1194b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1195b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1196d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (size_t i = 0; i < recv_codecs_.size(); ++i) {
119782775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    MergeFecConfig(recv_codecs_[i].fec, &config->rtp.fec);
1198b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1199b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
120082775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org  for (size_t i = 0; i < recv_codecs_.size(); ++i) {
120182775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    uint32 rtx_ssrc;
120282775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    if (recv_codecs_[i].rtx_payload_type != -1 &&
120382775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org        sp.GetFidSsrc(ssrc, &rtx_ssrc)) {
120482775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org      webrtc::VideoReceiveStream::Config::Rtp::Rtx& rtx =
120582775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org          config->rtp.rtx[recv_codecs_[i].codec.id];
120682775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org      rtx.ssrc = rtx_ssrc;
120782775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org      rtx.payload_type = recv_codecs_[i].rtx_payload_type;
120882775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    }
120982775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org  }
1210b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1211b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1212b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::RemoveRecvStream(uint32 ssrc) {
1213b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
1214b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1215afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    LOG(LS_ERROR) << "RemoveRecvStream with 0 ssrc is not supported.";
1216afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    return false;
1217b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1218b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1219575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1220d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  std::map<uint32, WebRtcVideoReceiveStream*>::iterator stream =
1221b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      receive_streams_.find(ssrc);
1222b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (stream == receive_streams_.end()) {
1223b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Stream not found for ssrc: " << ssrc;
1224b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1225b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1226d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  DeleteReceiveStream(stream->second);
1227b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  receive_streams_.erase(stream);
1228b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1229b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1230b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1231b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1232b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRenderer(uint32 ssrc, VideoRenderer* renderer) {
1233b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetRenderer: ssrc:" << ssrc << " "
1234b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org               << (renderer ? "(ptr)" : "NULL");
1235b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1236afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    default_unsignalled_ssrc_handler_.SetDefaultRenderer(this, renderer);
1237d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    return true;
1238b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1239b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1240575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1241d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1242d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      receive_streams_.find(ssrc);
1243d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (it == receive_streams_.end()) {
1244d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    return false;
1245b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1246b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1247b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  it->second->SetRenderer(renderer);
1248b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1249b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1250b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1251b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::GetRenderer(uint32 ssrc, VideoRenderer** renderer) {
1252b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1253afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    *renderer = default_unsignalled_ssrc_handler_.GetDefaultRenderer();
1254afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    return *renderer != NULL;
1255b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1256b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1257575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1258d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1259d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      receive_streams_.find(ssrc);
1260d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (it == receive_streams_.end()) {
1261b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1262b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1263b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  *renderer = it->second->GetRenderer();
1264b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1265b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1266b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1267058b1f17ac43b1fe69a8c18aaa7999ba88733dfdpbos@webrtc.orgbool WebRtcVideoChannel2::GetStats(VideoMediaInfo* info) {
1268e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info->Clear();
1269e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  FillSenderStats(info);
1270e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  FillReceiverStats(info);
12712b19f0631233488e891d9db0d170b637dc8fc464pbos@webrtc.org  webrtc::Call::Stats stats = call_->GetStats();
12722b19f0631233488e891d9db0d170b637dc8fc464pbos@webrtc.org  FillBandwidthEstimationStats(stats, info);
12732b19f0631233488e891d9db0d170b637dc8fc464pbos@webrtc.org  if (stats.rtt_ms != -1) {
12742b19f0631233488e891d9db0d170b637dc8fc464pbos@webrtc.org    for (size_t i = 0; i < info->senders.size(); ++i) {
12752b19f0631233488e891d9db0d170b637dc8fc464pbos@webrtc.org      info->senders[i].rtt_ms = stats.rtt_ms;
12762b19f0631233488e891d9db0d170b637dc8fc464pbos@webrtc.org    }
12772b19f0631233488e891d9db0d170b637dc8fc464pbos@webrtc.org  }
1278b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1279b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1280b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1281e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgvoid WebRtcVideoChannel2::FillSenderStats(VideoMediaInfo* video_media_info) {
1282575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1283e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1284e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org           send_streams_.begin();
1285e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org       it != send_streams_.end();
1286e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org       ++it) {
1287e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    video_media_info->senders.push_back(it->second->GetVideoSenderInfo());
1288e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
1289e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
1290e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1291e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgvoid WebRtcVideoChannel2::FillReceiverStats(VideoMediaInfo* video_media_info) {
1292575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1293e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1294e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org           receive_streams_.begin();
1295e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org       it != receive_streams_.end();
1296e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org       ++it) {
1297e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    video_media_info->receivers.push_back(it->second->GetVideoReceiverInfo());
1298e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
1299e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
1300e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1301e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgvoid WebRtcVideoChannel2::FillBandwidthEstimationStats(
13022b19f0631233488e891d9db0d170b637dc8fc464pbos@webrtc.org    const webrtc::Call::Stats& stats,
1303e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    VideoMediaInfo* video_media_info) {
13040bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  BandwidthEstimationInfo bwe_info;
13050bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  bwe_info.available_send_bandwidth = stats.send_bandwidth_bps;
13060bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  bwe_info.available_recv_bandwidth = stats.recv_bandwidth_bps;
13070bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  bwe_info.bucket_delay = stats.pacer_delay_ms;
13080bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org
13090bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  // Get send stream bitrate stats.
13100bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
13110bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator stream =
13120bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org           send_streams_.begin();
13130bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org       stream != send_streams_.end();
13140bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org       ++stream) {
13150bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org    stream->second->FillBandwidthEstimationInfo(&bwe_info);
13160bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  }
13170bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  video_media_info->bw_estimations.push_back(bwe_info);
1318e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
1319e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1320b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetCapturer(uint32 ssrc, VideoCapturer* capturer) {
1321b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetCapturer: " << ssrc << " -> "
1322b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org               << (capturer != NULL ? "(capturer)" : "NULL");
1323d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  DCHECK(ssrc != 0);
1324e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  {
1325e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    rtc::CritScope stream_lock(&stream_crit_);
1326e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    if (send_streams_.find(ssrc) == send_streams_.end()) {
1327e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström      LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc;
1328e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström      return false;
1329e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    }
1330e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    if (!send_streams_[ssrc]->SetCapturer(capturer)) {
1331e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström      return false;
1332e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    }
133364c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  }
133464c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh
133564c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  if (capturer) {
133664c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    capturer->SetApplyRotation(
133764c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh        !FindHeaderExtension(send_rtp_extensions_,
133864c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh                             kRtpVideoRotationHeaderExtension));
133964c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  }
1340e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  {
1341e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    rtc::CritScope lock(&capturer_crit_);
1342e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    capturers_[ssrc] = capturer;
1343e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  }
134464c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  return true;
1345b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1346b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1347b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SendIntraFrame() {
1348b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1349b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SendIntraFrame().";
1350b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1351b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1352b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1353b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::RequestIntraFrame() {
1354b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1355b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SendIntraFrame().";
1356b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1357b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1358b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1359b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::OnPacketReceived(
1360d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    rtc::Buffer* packet,
1361d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    const rtc::PacketTime& packet_time) {
13624e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org  const webrtc::PacketReceiver::DeliveryStatus delivery_result =
136323fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg      call_->Receiver()->DeliverPacket(webrtc::MediaType::VIDEO,
1364eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org          reinterpret_cast<const uint8_t*>(packet->data()), packet->size());
13654e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org  switch (delivery_result) {
13664e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_OK:
13674e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      return;
13684e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_PACKET_ERROR:
13694e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      return;
13704e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC:
13714e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      break;
1372b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1373b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1374b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  uint32 ssrc = 0;
1375eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org  if (!GetRtpSsrc(packet->data(), packet->size(), &ssrc)) {
1376b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1377b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1378b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1379d10a68e7974a29b26d6c926e6f137255f3c173benoahric  int payload_type = 0;
1380d10a68e7974a29b26d6c926e6f137255f3c173benoahric  if (!GetRtpPayloadType(packet->data(), packet->size(), &payload_type)) {
1381d10a68e7974a29b26d6c926e6f137255f3c173benoahric    return;
1382d10a68e7974a29b26d6c926e6f137255f3c173benoahric  }
1383d10a68e7974a29b26d6c926e6f137255f3c173benoahric
1384d10a68e7974a29b26d6c926e6f137255f3c173benoahric  // See if this payload_type is registered as one that usually gets its own
1385d10a68e7974a29b26d6c926e6f137255f3c173benoahric  // SSRC (RTX) or at least is safe to drop either way (ULPFEC). If it is, and
1386d10a68e7974a29b26d6c926e6f137255f3c173benoahric  // it wasn't handled above by DeliverPacket, that means we don't know what
1387d10a68e7974a29b26d6c926e6f137255f3c173benoahric  // stream it associates with, and we shouldn't ever create an implicit channel
1388d10a68e7974a29b26d6c926e6f137255f3c173benoahric  // for these.
1389d10a68e7974a29b26d6c926e6f137255f3c173benoahric  for (auto& codec : recv_codecs_) {
1390d10a68e7974a29b26d6c926e6f137255f3c173benoahric    if (payload_type == codec.rtx_payload_type ||
1391d10a68e7974a29b26d6c926e6f137255f3c173benoahric        payload_type == codec.fec.red_rtx_payload_type ||
1392d10a68e7974a29b26d6c926e6f137255f3c173benoahric        payload_type == codec.fec.ulpfec_payload_type) {
1393d10a68e7974a29b26d6c926e6f137255f3c173benoahric      return;
1394d10a68e7974a29b26d6c926e6f137255f3c173benoahric    }
1395d10a68e7974a29b26d6c926e6f137255f3c173benoahric  }
1396d10a68e7974a29b26d6c926e6f137255f3c173benoahric
1397afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  switch (unsignalled_ssrc_handler_->OnUnsignalledSsrc(this, ssrc)) {
1398afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    case UnsignalledSsrcHandler::kDropPacket:
1399afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org      return;
1400afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    case UnsignalledSsrcHandler::kDeliverPacket:
1401afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org      break;
1402afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  }
1403b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
140423fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg  if (call_->Receiver()->DeliverPacket(webrtc::MediaType::VIDEO,
1405eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org          reinterpret_cast<const uint8_t*>(packet->data()), packet->size()) !=
14061e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org      webrtc::PacketReceiver::DELIVERY_OK) {
1407afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    LOG(LS_WARNING) << "Failed to deliver RTP packet on re-delivery.";
1408b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1409b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1410b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1411b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1412b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::OnRtcpReceived(
1413d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    rtc::Buffer* packet,
1414d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    const rtc::PacketTime& packet_time) {
141523fba1ffa0079f70744a83bcf4e85501dc226013Fredrik Solenberg  if (call_->Receiver()->DeliverPacket(webrtc::MediaType::VIDEO,
1416eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org          reinterpret_cast<const uint8_t*>(packet->data()), packet->size()) !=
14171e019d10b8bcd96e8cf6b3d3df2730449fbed939pbos@webrtc.org      webrtc::PacketReceiver::DELIVERY_OK) {
1418b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_WARNING) << "Failed to deliver RTCP packet.";
1419b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1420b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1421b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1422b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::OnReadyToSend(bool ready) {
142326c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org  LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
1424cd6702282a49448adda470934f4bd9e6181cab22Jelena Marusic  call_->SignalNetworkState(ready ? webrtc::kNetworkUp : webrtc::kNetworkDown);
1425b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1426b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1427b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::MuteStream(uint32 ssrc, bool mute) {
1428b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "MuteStream: " << ssrc << " -> "
1429b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << (mute ? "mute" : "unmute");
1430d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  DCHECK(ssrc != 0);
1431575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1432b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send_streams_.find(ssrc) == send_streams_.end()) {
1433b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc;
1434b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1435b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1436ef8bb8d9b0bca0b1fd1ddb0a17df665e9dfaf9adpbos@webrtc.org
1437ef8bb8d9b0bca0b1fd1ddb0a17df665e9dfaf9adpbos@webrtc.org  send_streams_[ssrc]->MuteStream(mute);
1438ef8bb8d9b0bca0b1fd1ddb0a17df665e9dfaf9adpbos@webrtc.org  return true;
1439b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1440b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1441b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions(
1442b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
144350fe359eb614e1bbe41124b9c19263019da0395dpbos@webrtc.org  TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetRecvRtpHeaderExtensions");
1444587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  LOG(LS_INFO) << "SetRecvRtpHeaderExtensions: "
1445587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org               << RtpExtensionsToString(extensions);
14463c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  if (!ValidateRtpHeaderExtensionIds(extensions))
14473c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    return false;
1448d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1449c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org  std::vector<webrtc::RtpExtension> filtered_extensions =
1450c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org      FilterRtpExtensions(extensions);
1451c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org  if (!RtpExtensionsHaveChanged(recv_rtp_extensions_, filtered_extensions))
1452c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org    return true;
1453c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org
1454c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org  recv_rtp_extensions_ = filtered_extensions;
1455c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org
1456575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1457d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (std::map<uint32, WebRtcVideoReceiveStream*>::iterator it =
1458d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org           receive_streams_.begin();
1459d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       it != receive_streams_.end();
1460d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       ++it) {
1461d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    it->second->SetRtpExtensions(recv_rtp_extensions_);
1462d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1463b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1464b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1465b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1466b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSendRtpHeaderExtensions(
1467b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
146850fe359eb614e1bbe41124b9c19263019da0395dpbos@webrtc.org  TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetSendRtpHeaderExtensions");
1469587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org  LOG(LS_INFO) << "SetSendRtpHeaderExtensions: "
1470587ef60056ff0e301a95a9eb8231fb0cae6b69b1pbos@webrtc.org               << RtpExtensionsToString(extensions);
14713c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org  if (!ValidateRtpHeaderExtensionIds(extensions))
14723c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    return false;
14733c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org
1474c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org  std::vector<webrtc::RtpExtension> filtered_extensions =
1475c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org      FilterRtpExtensions(extensions);
1476c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org  if (!RtpExtensionsHaveChanged(send_rtp_extensions_, filtered_extensions))
1477c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org    return true;
1478c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org
1479c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org  send_rtp_extensions_ = filtered_extensions;
1480a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
148164c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  const webrtc::RtpExtension* cvo_extension = FindHeaderExtension(
148264c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh      send_rtp_extensions_, kRtpVideoRotationHeaderExtension);
148364c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh
1484575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1485d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1486d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org           send_streams_.begin();
1487d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       it != send_streams_.end();
1488d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org       ++it) {
1489d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    it->second->SetRtpExtensions(send_rtp_extensions_);
149064c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    it->second->SetApplyRotation(!cvo_extension);
1491d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1492b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1493b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1494b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1495dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström// Counter-intuitively this method doesn't only set global bitrate caps but also
1496dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström// per-stream codec max bitrates. This is to permit SetMaxSendBitrate (b=AS) to
1497dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström// raise bitrates above the 2000k default bitrate cap.
1498008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.orgbool WebRtcVideoChannel2::SetMaxSendBandwidth(int max_bitrate_bps) {
1499dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  // TODO(pbos): Figure out whether b=AS means max bitrate for this
1500dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  // WebRtcVideoChannel2 (in which case we're good), or per sender (SSRC), in
1501dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  // which case this should not set a Call::BitrateConfig but rather reconfigure
1502dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  // all senders.
1503008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  LOG(LS_INFO) << "SetMaxSendBandwidth: " << max_bitrate_bps << "bps.";
1504dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  if (max_bitrate_bps == bitrate_config_.max_bitrate_bps)
1505dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    return true;
1506dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström
1507008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  if (max_bitrate_bps <= 0) {
1508008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    // Unsetting max bitrate.
1509008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    max_bitrate_bps = -1;
1510008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  }
1511008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  bitrate_config_.start_bitrate_bps = -1;
1512008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  bitrate_config_.max_bitrate_bps = max_bitrate_bps;
1513008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  if (max_bitrate_bps > 0 &&
1514008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org      bitrate_config_.min_bitrate_bps > max_bitrate_bps) {
1515008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    bitrate_config_.min_bitrate_bps = max_bitrate_bps;
1516008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  }
1517008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  call_->SetBitrateConfig(bitrate_config_);
1518dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  rtc::CritScope stream_lock(&stream_crit_);
1519dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  for (auto& kv : send_streams_)
1520dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    kv.second->SetMaxBitrateBps(max_bitrate_bps);
1521b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1522b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1523b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1524b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetOptions(const VideoOptions& options) {
152550fe359eb614e1bbe41124b9c19263019da0395dpbos@webrtc.org  TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetOptions");
1526a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  LOG(LS_INFO) << "SetOptions: " << options.ToString();
1527a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  VideoOptions old_options = options_;
1528b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  options_.SetAll(options);
1529a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  if (options_ == old_options) {
1530a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    // No new options to set.
1531a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    return true;
1532a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  }
1533e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  {
1534e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    rtc::CritScope lock(&capturer_crit_);
1535e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    options_.cpu_overuse_detection.Get(&signal_cpu_adaptation_);
1536e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  }
1537d819803d4570564a9800a7dd54f4593e6e21a6e7pbos@webrtc.org  rtc::DiffServCodePoint dscp = options_.dscp.GetWithDefaultIfUnset(false)
1538d819803d4570564a9800a7dd54f4593e6e21a6e7pbos@webrtc.org                                    ? rtc::DSCP_AF41
1539d819803d4570564a9800a7dd54f4593e6e21a6e7pbos@webrtc.org                                    : rtc::DSCP_DEFAULT;
1540d819803d4570564a9800a7dd54f4593e6e21a6e7pbos@webrtc.org  MediaChannel::SetDscp(dscp);
1541575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
15425301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
15435301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org           send_streams_.begin();
15445301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org       it != send_streams_.end();
15455301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org       ++it) {
15465301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    it->second->SetOptions(options_);
15475301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
1548b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1549b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1550b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1551b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::SetInterface(NetworkInterface* iface) {
1552b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  MediaChannel::SetInterface(iface);
1553b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Set the RTP recv/send buffer to a bigger size
1554b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  MediaChannel::SetOption(NetworkInterface::ST_RTP,
1555d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org                          rtc::Socket::OPT_RCVBUF,
1556b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                          kVideoRtpBufferSize);
1557b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1558ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org  // Speculative change to increase the outbound socket buffer size.
1559ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org  // In b/15152257, we are seeing a significant number of packets discarded
1560ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org  // due to lack of socket buffer space, although it's not yet clear what the
1561ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org  // ideal value should be.
1562ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org  MediaChannel::SetOption(NetworkInterface::ST_RTP,
1563ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org                          rtc::Socket::OPT_SNDBUF,
1564ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org                          kVideoRtpBufferSize);
1565b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1566b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1567b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::UpdateAspectRatio(int ratio_w, int ratio_h) {
1568b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1569b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1570b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1571d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.orgvoid WebRtcVideoChannel2::OnMessage(rtc::Message* msg) {
1572b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Ignored.
1573b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1574b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
157542684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.orgvoid WebRtcVideoChannel2::OnLoadUpdate(Load load) {
1576e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  // OnLoadUpdate can not take any locks that are held while creating streams
1577e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  // etc. Doing so establishes lock-order inversions between the webrtc process
1578e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  // thread on stream creation and locks such as stream_crit_ while calling out.
1579e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  rtc::CritScope stream_lock(&capturer_crit_);
1580e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  if (!signal_cpu_adaptation_)
1581e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    return;
1582efbde3775b5eed8015d7e2e86ddcea3e6033d321Erik SprĂ¥ng  // Do not adapt resolution for screen content as this will likely result in
1583efbde3775b5eed8015d7e2e86ddcea3e6033d321Erik SprĂ¥ng  // blurry and unreadable text.
1584e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  for (auto& kv : capturers_) {
1585efbde3775b5eed8015d7e2e86ddcea3e6033d321Erik SprĂ¥ng    if (kv.second != nullptr
1586efbde3775b5eed8015d7e2e86ddcea3e6033d321Erik SprĂ¥ng        && !kv.second->IsScreencast()
1587efbde3775b5eed8015d7e2e86ddcea3e6033d321Erik SprĂ¥ng        && kv.second->video_adapter() != nullptr) {
1588e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström      kv.second->video_adapter()->OnCpuResolutionRequest(
1589e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström          load == kOveruse ? CoordinatedVideoAdapter::DOWNGRADE
1590e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström                           : CoordinatedVideoAdapter::UPGRADE);
1591e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    }
159242684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  }
159342684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org}
159442684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org
1595b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SendRtp(const uint8_t* data, size_t len) {
1596d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::Buffer packet(data, len, kMaxRtpPacketLen);
1597b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return MediaChannel::SendPacket(&packet);
1598b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1599b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1600b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SendRtcp(const uint8_t* data, size_t len) {
1601d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::Buffer packet(data, len, kMaxRtpPacketLen);
1602b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return MediaChannel::SendRtcp(&packet);
1603b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1604b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1605b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::StartAllSendStreams() {
1606575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1607b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1608b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           send_streams_.begin();
1609b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != send_streams_.end();
1610b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
1611b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    it->second->Start();
1612b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1613b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1614b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1615b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::StopAllSendStreams() {
1616575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1617b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (std::map<uint32, WebRtcVideoSendStream*>::iterator it =
1618b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           send_streams_.begin();
1619b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       it != send_streams_.end();
1620b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org       ++it) {
1621b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    it->second->Stop();
1622b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1623b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1624b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
16256ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters::
16266ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org    VideoSendStreamParameters(
16276ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        const webrtc::VideoSendStream::Config& config,
16286ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        const VideoOptions& options,
1629dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström        int max_bitrate_bps,
16305301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org        const Settable<VideoCodecSettings>& codec_settings)
1631dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    : config(config),
1632dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström      options(options),
1633dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström      max_bitrate_bps(max_bitrate_bps),
1634dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström      codec_settings(codec_settings) {
16356ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org}
16366ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
16374d71edef45afa38b3f68b6af0519ac0f21d327dfPeter BoströmWebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder::AllocatedEncoder(
16384d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström    webrtc::VideoEncoder* encoder,
16394d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström    webrtc::VideoCodecType type,
16404d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström    bool external)
16414d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström    : encoder(encoder),
16424d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström      external_encoder(nullptr),
16434d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström      type(type),
16444d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström      external(external) {
16454d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström  if (external) {
16464d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström    external_encoder = encoder;
16474d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström    this->encoder =
16484d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström        new webrtc::VideoEncoderSoftwareFallbackWrapper(type, encoder);
16494d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström  }
16504d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström}
16514d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström
1652b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream(
1653b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    webrtc::Call* call,
16547fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    WebRtcVideoEncoderFactory* external_encoder_factory,
16556ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org    const VideoOptions& options,
1656dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    int max_bitrate_bps,
16575301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const Settable<VideoCodecSettings>& codec_settings,
16585301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const StreamParams& sp,
16595301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const std::vector<webrtc::RtpExtension>& rtp_extensions)
16607c027b64ae53a29bc528b4241cc540694c239304Henrik Kjellander    : ssrcs_(sp.ssrcs),
1661259bd2034c3d3ee7f2dc4d481e9bf896a3a4d6efPeter Boström      ssrc_groups_(sp.ssrc_groups),
16627c027b64ae53a29bc528b4241cc540694c239304Henrik Kjellander      call_(call),
16637fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      external_encoder_factory_(external_encoder_factory),
1664b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      stream_(NULL),
1665dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström      parameters_(webrtc::VideoSendStream::Config(),
1666dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström                  options,
1667dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström                  max_bitrate_bps,
1668dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström                  codec_settings),
16697fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      allocated_encoder_(NULL, webrtc::kVideoCodecUnknown, false),
1670b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      capturer_(NULL),
1671b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      sending_(false),
16729a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org      muted_(false),
16739a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org      old_adapt_changes_(0) {
16745301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.rtp.max_packet_size = kVideoMtu;
16755301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
16765301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  sp.GetPrimarySsrcs(&parameters_.config.rtp.ssrcs);
16775301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  sp.GetFidSsrcs(parameters_.config.rtp.ssrcs,
16785301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                 &parameters_.config.rtp.rtx.ssrcs);
16795301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.rtp.c_name = sp.cname;
16805301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.rtp.extensions = rtp_extensions;
16815301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
16825301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  VideoCodecSettings params;
16835301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (codec_settings.Get(&params)) {
16845301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    SetCodec(params);
16855301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
1686b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1687b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1688b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() {
1689b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  DisconnectCapturer();
16905301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (stream_ != NULL) {
16915301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    call_->DestroyVideoSendStream(stream_);
16925301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
16937fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  DestroyVideoEncoder(&allocated_encoder_);
1694b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1695b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
16964765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchezstatic void CreateBlackFrame(webrtc::VideoFrame* video_frame,
1697b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                             int width,
1698b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                             int height) {
1699b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org  video_frame->CreateEmptyFrame(width, height, width, (width + 1) / 2,
1700b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org                                (width + 1) / 2);
1701b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org  memset(video_frame->buffer(webrtc::kYPlane), 16,
1702b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org         video_frame->allocated_size(webrtc::kYPlane));
1703b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org  memset(video_frame->buffer(webrtc::kUPlane), 128,
1704b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org         video_frame->allocated_size(webrtc::kUPlane));
1705b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org  memset(video_frame->buffer(webrtc::kVPlane), 128,
1706b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org         video_frame->allocated_size(webrtc::kVPlane));
1707b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1708b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1709b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame(
1710b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VideoCapturer* capturer,
1711b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoFrame* frame) {
171286196c4f481d7f515e54806988f763169e8b9206pbos@webrtc.org  TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::InputFrame");
17134765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez  webrtc::VideoFrame video_frame(frame->GetVideoFrameBuffer(), 0, 0,
17144765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez                                 frame->GetVideoRotation());
1715d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
17165301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (stream_ == NULL) {
1717ad1f9b61a3107ca27ee023990dc576abc38f05acPeter Boström    // Frame input before send codecs are configured, dropping frame.
17185301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    return;
17195301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
172086196c4f481d7f515e54806988f763169e8b9206pbos@webrtc.org
172186196c4f481d7f515e54806988f763169e8b9206pbos@webrtc.org  // Not sending, abort early to prevent expensive reconfigurations while
172286196c4f481d7f515e54806988f763169e8b9206pbos@webrtc.org  // setting up codecs etc.
172386196c4f481d7f515e54806988f763169e8b9206pbos@webrtc.org  if (!sending_)
172486196c4f481d7f515e54806988f763169e8b9206pbos@webrtc.org    return;
172586196c4f481d7f515e54806988f763169e8b9206pbos@webrtc.org
1726b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (format_.width == 0) {  // Dropping frames.
1727d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg    DCHECK(format_.height == 0);
1728b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_VERBOSE) << "VideoFormat 0x0 set, Dropping frame.";
1729b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1730b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1731d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org  if (muted_) {
1732d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org    // Create a black frame to transmit instead.
1733afdd5dd372d69be7244a3d90d70de9d5ecd60eb9magjed@webrtc.org    CreateBlackFrame(&video_frame,
1734d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org                     static_cast<int>(frame->GetWidth()),
1735d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org                     static_cast<int>(frame->GetHeight()));
1736d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org  }
1737b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Reconfigure codec if necessary.
1738c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org  SetDimensions(
1739afdd5dd372d69be7244a3d90d70de9d5ecd60eb9magjed@webrtc.org      video_frame.width(), video_frame.height(), capturer->IsScreencast());
1740c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org
1741e433c0ef31297d78336d99cc18cf063b1a486cf2Alex Glaznev  LOG(LS_VERBOSE) << "IncomingCapturedFrame: " << video_frame.width() << "x"
1742e433c0ef31297d78336d99cc18cf063b1a486cf2Alex Glaznev                  << video_frame.height() << " -> (codec) "
1743e433c0ef31297d78336d99cc18cf063b1a486cf2Alex Glaznev                  << parameters_.encoder_config.streams.back().width << "x"
1744e433c0ef31297d78336d99cc18cf063b1a486cf2Alex Glaznev                  << parameters_.encoder_config.streams.back().height;
1745af612d5e0769571544952cbe55e675748afa9bddperkj@webrtc.org  stream_->Input()->IncomingCapturedFrame(video_frame);
1746b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1747b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1748b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer(
1749b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VideoCapturer* capturer) {
1750b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org  TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::SetCapturer");
1751b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!DisconnectCapturer() && capturer == NULL) {
1752b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1753b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1754b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1755b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  {
1756d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    rtc::CritScope cs(&lock_);
1757b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
17589359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org    if (capturer == NULL) {
17599359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org      if (stream_ != NULL) {
17609359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        LOG(LS_VERBOSE) << "Disabling capturer, sending black frame.";
17614765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez        webrtc::VideoFrame black_frame;
17629359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org
1763b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org        CreateBlackFrame(&black_frame, last_dimensions_.width,
1764b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org                         last_dimensions_.height);
1765af612d5e0769571544952cbe55e675748afa9bddperkj@webrtc.org        stream_->Input()->IncomingCapturedFrame(black_frame);
17669359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org      }
1767b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1768b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      capturer_ = NULL;
1769b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return true;
1770b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1771b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1772b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    capturer_ = capturer;
1773b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1774b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Lock cannot be held while connecting the capturer to prevent lock-order
1775b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // violations.
1776b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  capturer->SignalVideoFrame.connect(this, &WebRtcVideoSendStream::InputFrame);
1777b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1778b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1779b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1780b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoFormat(
1781b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoFormat& format) {
1782b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if ((format.width == 0 || format.height == 0) &&
1783b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      format.width != format.height) {
1784b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Can't set VideoFormat, width or height is zero (but not "
1785b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     "both, 0x0 drops frames).";
1786b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1787b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1788b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1789d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1790b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (format.width == 0 && format.height == 0) {
1791b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_INFO)
1792b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        << "0x0 resolution selected. Captured frames will be dropped for ssrc: "
17936ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        << parameters_.config.rtp.ssrcs[0] << ".";
1794b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  } else {
1795b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // TODO(pbos): Fix me, this only affects the last stream!
1796bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org    parameters_.encoder_config.streams.back().max_framerate =
1797b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        VideoFormat::IntervalToFps(format.interval);
1798c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    SetDimensions(format.width, format.height, false);
1799b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1800b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1801b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  format_ = format;
1802b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1803b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1804b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1805ef8bb8d9b0bca0b1fd1ddb0a17df665e9dfaf9adpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::MuteStream(bool mute) {
1806d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1807b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  muted_ = mute;
1808b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1809b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1810b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectCapturer() {
1811963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org  cricket::VideoCapturer* capturer;
1812963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org  {
1813963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org    rtc::CritScope cs(&lock_);
18149a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org    if (capturer_ == NULL)
1815963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org      return false;
18169a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org
18179a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org    if (capturer_->video_adapter() != nullptr)
18189a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org      old_adapt_changes_ += capturer_->video_adapter()->adaptation_changes();
18199a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org
1820963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org    capturer = capturer_;
1821963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org    capturer_ = NULL;
1822b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1823963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org  capturer->SignalVideoFrame.disconnect(this);
1824b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1825b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1826b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1827d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boströmconst std::vector<uint32>&
1828d6f4c25eedcfd502920f1b2a24744badd9da80bePeter BoströmWebRtcVideoChannel2::WebRtcVideoSendStream::GetSsrcs() const {
1829d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  return ssrcs_;
1830d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström}
1831d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
183264c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shiehvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetApplyRotation(
183364c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    bool apply_rotation) {
183464c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  rtc::CritScope cs(&lock_);
183564c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  if (capturer_ == NULL)
183664c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    return;
183764c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh
183864c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  capturer_->SetApplyRotation(apply_rotation);
183964c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh}
184064c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh
18415301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetOptions(
18425301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const VideoOptions& options) {
1843d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
18445301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  VideoCodecSettings codec_settings;
18455301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (parameters_.codec_settings.Get(&codec_settings)) {
18465301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    SetCodecAndOptions(codec_settings, options);
18475301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  } else {
18485301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    parameters_.options = options;
18495301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
18505301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org}
18517fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
1852b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec(
18535301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const VideoCodecSettings& codec_settings) {
1854d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
18555301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  SetCodecAndOptions(codec_settings, parameters_.options);
18565301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org}
18577fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
18587fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgwebrtc::VideoCodecType CodecTypeFromName(const std::string& name) {
1859e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin  if (CodecNamesEq(name, kVp8CodecName)) {
18607fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return webrtc::kVideoCodecVP8;
1861e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin  } else if (CodecNamesEq(name, kVp9CodecName)) {
1862188d3b2245b49f21468840386d81b080176b434bandresp@webrtc.org    return webrtc::kVideoCodecVP9;
1863e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin  } else if (CodecNamesEq(name, kH264CodecName)) {
18647fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return webrtc::kVideoCodecH264;
18657fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
18667fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return webrtc::kVideoCodecUnknown;
18677fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
18687fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
18697fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder
18707fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder(
18717fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    const VideoCodec& codec) {
18727fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  webrtc::VideoCodecType type = CodecTypeFromName(codec.name);
18737fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
18747fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  // Do not re-create encoders of the same type.
18757fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (type == allocated_encoder_.type && allocated_encoder_.encoder != NULL) {
18767fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return allocated_encoder_;
18777fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
18787fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
18797fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (external_encoder_factory_ != NULL) {
18807fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    webrtc::VideoEncoder* encoder =
18817fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org        external_encoder_factory_->CreateVideoEncoder(type);
18827fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (encoder != NULL) {
18837fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      return AllocatedEncoder(encoder, type, true);
18847fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
18857fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
18867fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
18877fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (type == webrtc::kVideoCodecVP8) {
18887fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return AllocatedEncoder(
18897fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org        webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kVp8), type, false);
1890188d3b2245b49f21468840386d81b080176b434bandresp@webrtc.org  } else if (type == webrtc::kVideoCodecVP9) {
1891188d3b2245b49f21468840386d81b080176b434bandresp@webrtc.org    return AllocatedEncoder(
1892188d3b2245b49f21468840386d81b080176b434bandresp@webrtc.org        webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kVp9), type, false);
189371f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin  } else if (type == webrtc::kVideoCodecH264) {
189471f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin    return AllocatedEncoder(
189571f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin        webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kH264), type, false);
18967fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
18977fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
18987fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  // This shouldn't happen, we should not be trying to create something we don't
18997fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  // support.
1900d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  DCHECK(false);
19017fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return AllocatedEncoder(NULL, webrtc::kVideoCodecUnknown, false);
19027fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
19037fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
19047fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::DestroyVideoEncoder(
19057fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    AllocatedEncoder* encoder) {
19067fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (encoder->external) {
19074d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström    external_encoder_factory_->DestroyVideoEncoder(encoder->external_encoder);
19087fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
19094d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström  delete encoder->encoder;
19107fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
19117fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
19125301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodecAndOptions(
19135301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const VideoCodecSettings& codec_settings,
19145301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const VideoOptions& options) {
1915a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  parameters_.encoder_config =
1916a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org      CreateVideoEncoderConfig(last_dimensions_, codec_settings.codec);
191786196c4f481d7f515e54806988f763169e8b9206pbos@webrtc.org  if (parameters_.encoder_config.streams.empty())
1918b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1919a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
19205301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  format_ = VideoFormat(codec_settings.codec.width,
19215301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                        codec_settings.codec.height,
1922b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                        VideoFormat::FpsToInterval(30),
1923b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                        FOURCC_I420);
19246ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
19257fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  AllocatedEncoder new_encoder = CreateVideoEncoder(codec_settings.codec);
19267fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  parameters_.config.encoder_settings.encoder = new_encoder.encoder;
19275301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.encoder_settings.payload_name = codec_settings.codec.name;
19285301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.encoder_settings.payload_type = codec_settings.codec.id;
19295301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.rtp.fec = codec_settings.fec;
19305301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
19315301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  // Set RTX payload type if RTX is enabled.
19325301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (!parameters_.config.rtp.rtx.ssrcs.empty()) {
1933b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org    if (codec_settings.rtx_payload_type == -1) {
1934b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org      LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX "
1935b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org                         "payload type. Ignoring.";
1936b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org      parameters_.config.rtp.rtx.ssrcs.clear();
1937b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org    } else {
1938b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org      parameters_.config.rtp.rtx.payload_type = codec_settings.rtx_payload_type;
1939b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org    }
19405301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
19415301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
194267c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström  parameters_.config.rtp.nack.rtp_history_ms =
194367c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström      HasNack(codec_settings.codec) ? kNackHistoryMs : 0;
19445301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
19455ff71ab4b369fe3dbfaec5f91cd2e491397eff33pbos@webrtc.org  options.suspend_below_min_bitrate.Get(
19465ff71ab4b369fe3dbfaec5f91cd2e491397eff33pbos@webrtc.org      &parameters_.config.suspend_below_min_bitrate);
19475ff71ab4b369fe3dbfaec5f91cd2e491397eff33pbos@webrtc.org
19485301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.codec_settings.Set(codec_settings);
19496ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  parameters_.options = options;
1950543e589205af006f6b999a2c5df51d3fb722d925pbos@webrtc.org
1951b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  RecreateWebRtcStream();
19527fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (allocated_encoder_.encoder != new_encoder.encoder) {
19537fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    DestroyVideoEncoder(&allocated_encoder_);
19547fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    allocated_encoder_ = new_encoder;
19557fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
1956b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1957b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1958d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions(
1959d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const std::vector<webrtc::RtpExtension>& rtp_extensions) {
1960d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1961d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  parameters_.config.rtp.extensions = rtp_extensions;
19623c3f6460646183914629e5dab8ae5fcede4f0e80Peter Boström  if (stream_ != nullptr)
19633c3f6460646183914629e5dab8ae5fcede4f0e80Peter Boström    RecreateWebRtcStream();
1964d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1965d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1966a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.orgwebrtc::VideoEncoderConfig
1967a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig(
1968a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    const Dimensions& dimensions,
1969a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    const VideoCodec& codec) const {
1970a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  webrtc::VideoEncoderConfig encoder_config;
1971a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  if (dimensions.is_screencast) {
1972a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    int screencast_min_bitrate_kbps;
1973a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    parameters_.options.screencast_min_bitrate.Get(
1974a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org        &screencast_min_bitrate_kbps);
1975a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    encoder_config.min_transmit_bitrate_bps =
1976a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org        screencast_min_bitrate_kbps * 1000;
1977143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng    encoder_config.content_type =
1978143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng        webrtc::VideoEncoderConfig::ContentType::kScreen;
1979a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  } else {
1980a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    encoder_config.min_transmit_bitrate_bps = 0;
1981143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng    encoder_config.content_type =
1982143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng        webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo;
1983a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  }
1984a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
1985a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  // Restrict dimensions according to codec max.
1986a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  int width = dimensions.width;
1987a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  int height = dimensions.height;
1988a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  if (!dimensions.is_screencast) {
1989a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    if (codec.width < width)
1990a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org      width = codec.width;
1991a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    if (codec.height < height)
1992a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org      height = codec.height;
1993a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  }
1994a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
1995a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  VideoCodec clamped_codec = codec;
1996a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  clamped_codec.width = width;
1997a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  clamped_codec.height = height;
1998a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
1999f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.org  encoder_config.streams = CreateVideoStreams(
2000dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström      clamped_codec, parameters_.options, parameters_.max_bitrate_bps,
2001143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng      dimensions.is_screencast ? 1 : parameters_.config.rtp.ssrcs.size());
2002a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
2003a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  // Conference mode screencast uses 2 temporal layers split at 100kbit.
2004a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  if (parameters_.options.conference_mode.GetWithDefaultIfUnset(false) &&
2005a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org      dimensions.is_screencast && encoder_config.streams.size() == 1) {
200646d4d29a751c559b6f01b311a1e4aa14a2586a46sprang@webrtc.org    ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault();
200746d4d29a751c559b6f01b311a1e4aa14a2586a46sprang@webrtc.org
200846d4d29a751c559b6f01b311a1e4aa14a2586a46sprang@webrtc.org    // For screenshare in conference mode, tl0 and tl1 bitrates are piggybacked
200946d4d29a751c559b6f01b311a1e4aa14a2586a46sprang@webrtc.org    // on the VideoCodec struct as target and max bitrates, respectively.
201046d4d29a751c559b6f01b311a1e4aa14a2586a46sprang@webrtc.org    // See eg. webrtc::VP8EncoderImpl::SetRates().
201146d4d29a751c559b6f01b311a1e4aa14a2586a46sprang@webrtc.org    encoder_config.streams[0].target_bitrate_bps =
201246d4d29a751c559b6f01b311a1e4aa14a2586a46sprang@webrtc.org        config.tl0_bitrate_kbps * 1000;
201346d4d29a751c559b6f01b311a1e4aa14a2586a46sprang@webrtc.org    encoder_config.streams[0].max_bitrate_bps = config.tl1_bitrate_kbps * 1000;
2014a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    encoder_config.streams[0].temporal_layer_thresholds_bps.clear();
2015a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    encoder_config.streams[0].temporal_layer_thresholds_bps.push_back(
201646d4d29a751c559b6f01b311a1e4aa14a2586a46sprang@webrtc.org        config.tl0_bitrate_kbps * 1000);
2017a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  }
2018a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  return encoder_config;
2019a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org}
2020a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
2021c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions(
2022c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    int width,
2023c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    int height,
2024efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org    bool is_screencast) {
2025efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org  if (last_dimensions_.width == width && last_dimensions_.height == height &&
2026efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org      last_dimensions_.is_screencast == is_screencast) {
2027efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org    // Configured using the same parameters, do not reconfigure.
2028efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org    return;
2029efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org  }
2030a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  LOG(LS_INFO) << "SetDimensions: " << width << "x" << height
2031a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org               << (is_screencast ? " (screencast)" : " (not screencast)");
2032efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org
2033efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org  last_dimensions_.width = width;
2034efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org  last_dimensions_.height = height;
2035efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org  last_dimensions_.is_screencast = is_screencast;
2036efc82c2c734171faba9e400ff60a114e7af2ebccpbos@webrtc.org
2037d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  DCHECK(!parameters_.encoder_config.streams.empty());
2038c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org
2039c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org  VideoCodecSettings codec_settings;
2040c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org  parameters_.codec_settings.Get(&codec_settings);
2041c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org
2042a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  webrtc::VideoEncoderConfig encoder_config =
2043a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org      CreateVideoEncoderConfig(last_dimensions_, codec_settings.codec);
2044a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
2045143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng  encoder_config.encoder_specific_settings = ConfigureVideoEncoderSettings(
2046143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng      codec_settings.codec, parameters_.options, is_screencast);
20476f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
2048bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  bool stream_reconfigured = stream_->ReconfigureVideoEncoder(encoder_config);
2049bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org
2050bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  encoder_config.encoder_specific_settings = NULL;
20516f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
20526f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  if (!stream_reconfigured) {
2053b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_WARNING) << "Failed to reconfigure video encoder for dimensions: "
2054b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                    << width << "x" << height;
2055b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
2056b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
2057cddd17c0f89cfaa9d2f21118ae90b45dae3b4aeepbos@webrtc.org
2058bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  parameters_.encoder_config = encoder_config;
2059b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
2060b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2061b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::Start() {
2062d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
2063d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  DCHECK(stream_ != NULL);
2064b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  stream_->Start();
2065b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = true;
2066b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
2067b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2068b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::Stop() {
2069d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
20705301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (stream_ != NULL) {
20715301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    stream_->Stop();
20725301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
2073b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = false;
2074b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
2075b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2076e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgVideoSenderInfo
2077e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() {
2078e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  VideoSenderInfo info;
207977e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org  webrtc::VideoSendStream::Stats stats;
208077e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org  {
208177e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org    rtc::CritScope cs(&lock_);
208277e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org    for (uint32_t ssrc : parameters_.config.rtp.ssrcs)
208377e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org      info.add_ssrc(ssrc);
208477e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org
208574d9ed7d853677d297807021436467a4f97584acPeter Boström    VideoCodecSettings codec_settings;
208674d9ed7d853677d297807021436467a4f97584acPeter Boström    if (parameters_.codec_settings.Get(&codec_settings))
208774d9ed7d853677d297807021436467a4f97584acPeter Boström      info.codec_name = codec_settings.codec.name;
208877e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org    for (size_t i = 0; i < parameters_.encoder_config.streams.size(); ++i) {
208977e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org      if (i == parameters_.encoder_config.streams.size() - 1) {
209077e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org        info.preferred_bitrate +=
209177e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org            parameters_.encoder_config.streams[i].max_bitrate_bps;
209277e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org      } else {
209377e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org        info.preferred_bitrate +=
209477e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org            parameters_.encoder_config.streams[i].target_bitrate_bps;
209577e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org      }
209677e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org    }
2097e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
209877e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org    if (stream_ == NULL)
209977e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org      return info;
2100c3d2bd28a3e8badc434a5081dd36f4ac41b4e3f2pbos@webrtc.org
210177e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org    stats = stream_->GetStats();
210277e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org
21039a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org    info.adapt_changes = old_adapt_changes_;
21049a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org    info.adapt_reason = CoordinatedVideoAdapter::ADAPTREASON_NONE;
21059a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org
21069a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org    if (capturer_ != NULL) {
21079a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org      if (!capturer_->IsMuted()) {
21089a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org        VideoFormat last_captured_frame_format;
21099a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org        capturer_->GetStats(&info.adapt_frame_drops, &info.effects_frame_drops,
21109a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org                            &info.capturer_frame_time,
21119a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org                            &last_captured_frame_format);
21129a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org        info.input_frame_width = last_captured_frame_format.width;
21139a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org        info.input_frame_height = last_captured_frame_format.height;
21149a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org      }
21159a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org      if (capturer_->video_adapter() != nullptr) {
21169a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org        info.adapt_changes += capturer_->video_adapter()->adaptation_changes();
21179a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org        info.adapt_reason = capturer_->video_adapter()->adapt_reason();
21189a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org      }
211977e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org    }
212077e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org  }
2121259bd2034c3d3ee7f2dc4d481e9bf896a3a4d6efPeter Boström  info.ssrc_groups = ssrc_groups_;
2122e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_input = stats.input_frame_rate;
2123e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_sent = stats.encode_frame_rate;
21243e6e271ec3253e78ae0eb72156e5236d43f8731dpbos@webrtc.org  info.avg_encode_ms = stats.avg_encode_time_ms;
21253e6e271ec3253e78ae0eb72156e5236d43f8731dpbos@webrtc.org  info.encode_usage_percent = stats.encode_usage_percent;
2126e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
212777e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org  info.nominal_bitrate = stats.media_bitrate_bps;
212877e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org
2129273a414b0ec2e58fdf3b817ad8b1a02f4ce15287pbos@webrtc.org  info.send_frame_width = 0;
2130273a414b0ec2e58fdf3b817ad8b1a02f4ce15287pbos@webrtc.org  info.send_frame_height = 0;
213109c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  for (std::map<uint32_t, webrtc::VideoSendStream::StreamStats>::iterator it =
2132e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org           stats.substreams.begin();
213309c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org       it != stats.substreams.end(); ++it) {
2134e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    // TODO(pbos): Wire up additional stats, such as padding bytes.
213509c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org    webrtc::VideoSendStream::StreamStats stream_stats = it->second;
2136cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org    info.bytes_sent += stream_stats.rtp_stats.transmitted.payload_bytes +
2137cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org                       stream_stats.rtp_stats.transmitted.header_bytes +
2138cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org                       stream_stats.rtp_stats.transmitted.padding_bytes;
2139cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org    info.packets_sent += stream_stats.rtp_stats.transmitted.packets;
2140e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.packets_lost += stream_stats.rtcp_stats.cumulative_lost;
214109c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org    if (stream_stats.width > info.send_frame_width)
214209c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org      info.send_frame_width = stream_stats.width;
214309c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org    if (stream_stats.height > info.send_frame_height)
214409c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org      info.send_frame_height = stream_stats.height;
21451d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    info.firs_rcvd += stream_stats.rtcp_packet_type_counts.fir_packets;
21461d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    info.nacks_rcvd += stream_stats.rtcp_packet_type_counts.nack_packets;
21471d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    info.plis_rcvd += stream_stats.rtcp_packet_type_counts.pli_packets;
2148e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
2149e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
2150e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  if (!stats.substreams.empty()) {
2151e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    // TODO(pbos): Report fraction lost per SSRC.
215209c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org    webrtc::VideoSendStream::StreamStats first_stream_stats =
215309c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org        stats.substreams.begin()->second;
2154e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.fraction_lost =
2155e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org        static_cast<float>(first_stream_stats.rtcp_stats.fraction_lost) /
2156e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org        (1 << 8);
2157e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
2158e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
2159e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  return info;
2160e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
2161e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
21620bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::FillBandwidthEstimationInfo(
21630bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org    BandwidthEstimationInfo* bwe_info) {
21640bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  rtc::CritScope cs(&lock_);
21650bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  if (stream_ == NULL) {
21660bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org    return;
21670bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  }
21680bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  webrtc::VideoSendStream::Stats stats = stream_->GetStats();
216909c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  for (std::map<uint32_t, webrtc::VideoSendStream::StreamStats>::iterator it =
21700bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org           stats.substreams.begin();
217109c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org       it != stats.substreams.end(); ++it) {
21720bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org    bwe_info->transmit_bitrate += it->second.total_bitrate_bps;
21730bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org    bwe_info->retransmit_bitrate += it->second.retransmit_bitrate_bps;
21740bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  }
2175891d48393e5ccd2f5e03d509c544c00a3d88cbbcpbos@webrtc.org  bwe_info->target_enc_bitrate += stats.target_media_bitrate_bps;
217677e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org  bwe_info->actual_enc_bitrate += stats.media_bitrate_bps;
21770bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org}
21780bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org
2179dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boströmvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetMaxBitrateBps(
2180dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    int max_bitrate_bps) {
2181dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  rtc::CritScope cs(&lock_);
2182dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  parameters_.max_bitrate_bps = max_bitrate_bps;
2183dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström
2184dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  // No need to reconfigure if the stream hasn't been configured yet.
2185dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  if (parameters_.encoder_config.streams.empty())
2186dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    return;
2187dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström
2188dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  // Force a stream reconfigure to set the new max bitrate.
2189dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  int width = last_dimensions_.width;
2190dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  last_dimensions_.width = 0;
2191dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  SetDimensions(width, last_dimensions_.height, last_dimensions_.is_screencast);
2192dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström}
219342684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org
2194b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
2195b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (stream_ != NULL) {
2196b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    call_->DestroyVideoSendStream(stream_);
2197b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
21986ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
21996f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  VideoCodecSettings codec_settings;
22006f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  parameters_.codec_settings.Get(&codec_settings);
2201bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  parameters_.encoder_config.encoder_specific_settings =
2202143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng      ConfigureVideoEncoderSettings(
2203143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng          codec_settings.codec, parameters_.options,
2204143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng          parameters_.encoder_config.content_type ==
2205143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik SprĂ¥ng              webrtc::VideoEncoderConfig::ContentType::kScreen);
2206bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org
2207b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org  webrtc::VideoSendStream::Config config = parameters_.config;
2208b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org  if (!config.rtp.rtx.ssrcs.empty() && config.rtp.rtx.payload_type == -1) {
2209b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org    LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX "
2210b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org                       "payload type the set codec. Ignoring RTX.";
2211b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org    config.rtp.rtx.ssrcs.clear();
2212b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org  }
2213b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org  stream_ = call_->CreateVideoSendStream(config, parameters_.encoder_config);
22146f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
2215bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  parameters_.encoder_config.encoder_specific_settings = NULL;
22166f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
2217b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (sending_) {
2218b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    stream_->Start();
2219b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
2220b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
2221b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2222d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream(
2223d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    webrtc::Call* call,
2224259bd2034c3d3ee7f2dc4d481e9bf896a3a4d6efPeter Boström    const StreamParams& sp,
2225776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org    WebRtcVideoDecoderFactory* external_decoder_factory,
2226a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org    bool default_stream,
2227d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const webrtc::VideoReceiveStream::Config& config,
2228d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const std::vector<VideoCodecSettings>& recv_codecs)
2229d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    : call_(call),
2230259bd2034c3d3ee7f2dc4d481e9bf896a3a4d6efPeter Boström      ssrcs_(sp.ssrcs),
2231259bd2034c3d3ee7f2dc4d481e9bf896a3a4d6efPeter Boström      ssrc_groups_(sp.ssrc_groups),
2232d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      stream_(NULL),
2233a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org      default_stream_(default_stream),
2234b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      config_(config),
2235776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org      external_decoder_factory_(external_decoder_factory),
2236b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      renderer_(NULL),
2237d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      last_width_(-1),
2238fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org      last_height_(-1),
2239fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org      first_frame_timestamp_(-1),
2240fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org      estimated_remote_start_ntp_time_ms_(0) {
2241d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config_.renderer = this;
2242d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // SetRecvCodecs will also reset (start) the VideoReceiveStream.
2243d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  SetRecvCodecs(recv_codecs);
2244d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2245d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
22467252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter BoströmWebRtcVideoChannel2::WebRtcVideoReceiveStream::AllocatedDecoder::
22477252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström    AllocatedDecoder(webrtc::VideoDecoder* decoder,
22487252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström                     webrtc::VideoCodecType type,
22497252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström                     bool external)
22507252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström    : decoder(decoder),
22517252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström      external_decoder(nullptr),
22527252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström      type(type),
22537252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström      external(external) {
22547252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström  if (external) {
22557252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström    external_decoder = decoder;
22567252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström    this->decoder =
22577252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström        new webrtc::VideoDecoderSoftwareFallbackWrapper(type, external_decoder);
22587252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström  }
22597252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström}
22607252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström
2261d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::~WebRtcVideoReceiveStream() {
2262d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  call_->DestroyVideoReceiveStream(stream_);
226396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  ClearDecoders(&allocated_decoders_);
2264d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2265d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
2266d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boströmconst std::vector<uint32>&
2267d6f4c25eedcfd502920f1b2a24744badd9da80bePeter BoströmWebRtcVideoChannel2::WebRtcVideoReceiveStream::GetSsrcs() const {
2268d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  return ssrcs_;
2269d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström}
2270d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
227196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::AllocatedDecoder
227296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::CreateOrReuseVideoDecoder(
227396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    std::vector<AllocatedDecoder>* old_decoders,
227496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    const VideoCodec& codec) {
227596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  webrtc::VideoCodecType type = CodecTypeFromName(codec.name);
2276776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
227796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  for (size_t i = 0; i < old_decoders->size(); ++i) {
227896a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    if ((*old_decoders)[i].type == type) {
227996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      AllocatedDecoder decoder = (*old_decoders)[i];
228096a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      (*old_decoders)[i] = old_decoders->back();
228196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      old_decoders->pop_back();
228296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      return decoder;
228396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    }
228496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  }
2285776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
228696a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  if (external_decoder_factory_ != NULL) {
228796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    webrtc::VideoDecoder* decoder =
228896a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org        external_decoder_factory_->CreateVideoDecoder(type);
228996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    if (decoder != NULL) {
229096a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      return AllocatedDecoder(decoder, type, true);
229196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    }
229296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  }
2293776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
229496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  if (type == webrtc::kVideoCodecVP8) {
229596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    return AllocatedDecoder(
229696a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org        webrtc::VideoDecoder::Create(webrtc::VideoDecoder::kVp8), type, false);
229796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  }
2298d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
2299b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org  if (type == webrtc::kVideoCodecVP9) {
2300b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org    return AllocatedDecoder(
2301b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org        webrtc::VideoDecoder::Create(webrtc::VideoDecoder::kVp9), type, false);
2302b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org  }
2303b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org
230471f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin  if (type == webrtc::kVideoCodecH264) {
230571f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin    return AllocatedDecoder(
230671f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin        webrtc::VideoDecoder::Create(webrtc::VideoDecoder::kH264), type, false);
230771f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin  }
230871f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin
230996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  // This shouldn't happen, we should not be trying to create something we don't
231096a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  // support.
2311d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  DCHECK(false);
231296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  return AllocatedDecoder(NULL, webrtc::kVideoCodecUnknown, false);
231396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org}
231496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org
231596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvCodecs(
231696a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    const std::vector<VideoCodecSettings>& recv_codecs) {
231796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  std::vector<AllocatedDecoder> old_decoders = allocated_decoders_;
231896a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  allocated_decoders_.clear();
231996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  config_.decoders.clear();
232096a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  for (size_t i = 0; i < recv_codecs.size(); ++i) {
232196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    AllocatedDecoder allocated_decoder =
232296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org        CreateOrReuseVideoDecoder(&old_decoders, recv_codecs[i].codec);
232396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    allocated_decoders_.push_back(allocated_decoder);
2324d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
232596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    webrtc::VideoReceiveStream::Decoder decoder;
232696a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    decoder.decoder = allocated_decoder.decoder;
232796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    decoder.payload_type = recv_codecs[i].codec.id;
232896a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    decoder.payload_name = recv_codecs[i].codec.name;
232996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    config_.decoders.push_back(decoder);
233096a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  }
233196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org
233296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  // TODO(pbos): Reconfigure RTX based on incoming recv_codecs.
233396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  config_.rtp.fec = recv_codecs.front().fec;
2334257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org  config_.rtp.nack.rtp_history_ms =
2335e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin      HasNack(recv_codecs.begin()->codec) ? kNackHistoryMs : 0;
2336257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org
233796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  ClearDecoders(&old_decoders);
2338d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  RecreateWebRtcStream();
2339d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2340d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
23413548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boströmvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetLocalSsrc(
23423548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström    uint32_t local_ssrc) {
23433548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström  // TODO(pbos): Consider turning this sanity check into a DCHECK. You should
23443548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström  // not be able to create a sender with the same SSRC as a receiver, but right
23453548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström  // now this can't be done due to unittests depending on receiving what they
23463548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström  // are sending from the same MediaChannel.
23473548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström  if (local_ssrc == config_.rtp.remote_ssrc)
23483548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström    return;
23493548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström
23503548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström  config_.rtp.local_ssrc = local_ssrc;
23513548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström  RecreateWebRtcStream();
23523548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström}
23533548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström
235467c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boströmvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetNackAndRemb(
235567c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström    bool nack_enabled, bool remb_enabled) {
235667c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström  int nack_history_ms = nack_enabled ? kNackHistoryMs : 0;
235767c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström  if (config_.rtp.nack.rtp_history_ms == nack_history_ms &&
235867c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström      config_.rtp.remb == remb_enabled) {
2359126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström    return;
236067c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström  }
236167c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström  config_.rtp.remb = remb_enabled;
236267c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström  config_.rtp.nack.rtp_history_ms = nack_history_ms;
2363126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström  RecreateWebRtcStream();
2364126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström}
2365126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström
2366d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRtpExtensions(
2367d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const std::vector<webrtc::RtpExtension>& extensions) {
2368d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config_.rtp.extensions = extensions;
23693548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström  RecreateWebRtcStream();
2370d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2371d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
2372d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::RecreateWebRtcStream() {
2373d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (stream_ != NULL) {
2374d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    call_->DestroyVideoReceiveStream(stream_);
2375d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
2376d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  stream_ = call_->CreateVideoReceiveStream(config_);
2377d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  stream_->Start();
2378d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2379d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
238096a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::ClearDecoders(
238196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    std::vector<AllocatedDecoder>* allocated_decoders) {
238296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  for (size_t i = 0; i < allocated_decoders->size(); ++i) {
238396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    if ((*allocated_decoders)[i].external) {
2384776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org      external_decoder_factory_->DestroyVideoDecoder(
23857252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström          (*allocated_decoders)[i].external_decoder);
2386776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org    }
23877252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström    delete (*allocated_decoders)[i].decoder;
2388776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  }
238996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  allocated_decoders->clear();
2390776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org}
2391776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
2392d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::RenderFrame(
23934765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez    const webrtc::VideoFrame& frame,
2394d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    int time_to_render_ms) {
2395d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
2396fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org
2397fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org  if (first_frame_timestamp_ < 0)
2398fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org    first_frame_timestamp_ = frame.timestamp();
2399fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org  int64_t rtp_time_elapsed_since_first_frame =
2400fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org      (timestamp_wraparound_handler_.Unwrap(frame.timestamp()) -
2401fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org       first_frame_timestamp_);
2402fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org  int64_t elapsed_time_ms = rtp_time_elapsed_since_first_frame /
2403fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org                            (cricket::kVideoCodecClockrate / 1000);
2404fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org  if (frame.ntp_time_ms() > 0)
2405fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org    estimated_remote_start_ntp_time_ms_ = frame.ntp_time_ms() - elapsed_time_ms;
2406fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org
2407d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (renderer_ == NULL) {
2408d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    LOG(LS_WARNING) << "VideoReceiveStream not connected to a VideoRenderer.";
2409d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    return;
2410d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
2411d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
2412d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (frame.width() != last_width_ || frame.height() != last_height_) {
2413d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    SetSize(frame.width(), frame.height());
2414d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
2415d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
24162386d6dd92f10a715f131b5ad408b1babc1f35b0magjed@webrtc.org  const WebRtcVideoFrame render_frame(
24172386d6dd92f10a715f131b5ad408b1babc1f35b0magjed@webrtc.org      frame.video_frame_buffer(),
24182386d6dd92f10a715f131b5ad408b1babc1f35b0magjed@webrtc.org      elapsed_time_ms * rtc::kNumNanosecsPerMillisec,
241964c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh      frame.render_time_ms() * rtc::kNumNanosecsPerMillisec, frame.rotation());
2420d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  renderer_->RenderFrame(&render_frame);
2421d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2422d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
24230d852d5c27a759fe7aadc500bd7b3cadfae3deb8pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoReceiveStream::IsTextureSupported() const {
24240d852d5c27a759fe7aadc500bd7b3cadfae3deb8pbos@webrtc.org  return true;
24250d852d5c27a759fe7aadc500bd7b3cadfae3deb8pbos@webrtc.org}
24260d852d5c27a759fe7aadc500bd7b3cadfae3deb8pbos@webrtc.org
2427a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoReceiveStream::IsDefaultStream() const {
2428a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org  return default_stream_;
2429a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org}
2430a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org
2431d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRenderer(
2432d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    cricket::VideoRenderer* renderer) {
2433d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
2434d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  renderer_ = renderer;
2435d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (renderer_ != NULL && last_width_ != -1) {
2436d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    SetSize(last_width_, last_height_);
2437d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
2438d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2439d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
2440d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgVideoRenderer* WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetRenderer() {
2441d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // TODO(pbos): Remove GetRenderer and all uses of it, it's thread-unsafe by
2442d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // design.
2443d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
2444d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  return renderer_;
2445d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2446d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
2447d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetSize(int width,
2448d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org                                                            int height) {
2449d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
2450d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (!renderer_->SetSize(width, height, 0)) {
2451d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    LOG(LS_ERROR) << "Could not set renderer size.";
2452d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
2453d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  last_width_ = width;
2454d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  last_height_ = height;
2455d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2456d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
2457e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgVideoReceiverInfo
2458e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::GetVideoReceiverInfo() {
2459e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  VideoReceiverInfo info;
2460259bd2034c3d3ee7f2dc4d481e9bf896a3a4d6efPeter Boström  info.ssrc_groups = ssrc_groups_;
2461e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.add_ssrc(config_.rtp.remote_ssrc);
2462e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  webrtc::VideoReceiveStream::Stats stats = stream_->GetStats();
2463cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org  info.bytes_rcvd = stats.rtp_stats.transmitted.payload_bytes +
2464cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org                    stats.rtp_stats.transmitted.header_bytes +
2465cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org                    stats.rtp_stats.transmitted.padding_bytes;
2466cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org  info.packets_rcvd = stats.rtp_stats.transmitted.packets;
2467393347ff988708df5037ddcd181fe204bd1ab37ePeter Boström  info.packets_lost = stats.rtcp_stats.cumulative_lost;
2468393347ff988708df5037ddcd181fe204bd1ab37ePeter Boström  info.fraction_lost =
2469393347ff988708df5037ddcd181fe204bd1ab37ePeter Boström      static_cast<float>(stats.rtcp_stats.fraction_lost) / (1 << 8);
2470e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
2471e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_rcvd = stats.network_frame_rate;
2472e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_decoded = stats.decode_frame_rate;
2473e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_output = stats.render_frame_rate;
2474e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
24751d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org  {
24761d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    rtc::CritScope frame_cs(&renderer_lock_);
24771d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    info.frame_width = last_width_;
24781d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    info.frame_height = last_height_;
24791d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    info.capture_start_ntp_time_ms = estimated_remote_start_ntp_time_ms_;
24801d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org  }
24811d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org
248209c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  info.decode_ms = stats.decode_ms;
248309c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  info.max_decode_ms = stats.max_decode_ms;
248409c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  info.current_delay_ms = stats.current_delay_ms;
248509c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  info.target_delay_ms = stats.target_delay_ms;
248609c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  info.jitter_buffer_ms = stats.jitter_buffer_ms;
248709c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  info.min_playout_delay_ms = stats.min_playout_delay_ms;
248809c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  info.render_delay_ms = stats.render_delay_ms;
248909c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org
24901d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org  info.firs_sent = stats.rtcp_packet_type_counts.fir_packets;
24911d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org  info.plis_sent = stats.rtcp_packet_type_counts.pli_packets;
24921d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org  info.nacks_sent = stats.rtcp_packet_type_counts.nack_packets;
2493e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
2494e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  return info;
2495e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
2496e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
2497b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::VideoCodecSettings::VideoCodecSettings()
2498b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    : rtx_payload_type(-1) {}
2499b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2500a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.orgbool WebRtcVideoChannel2::VideoCodecSettings::operator==(
2501a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    const WebRtcVideoChannel2::VideoCodecSettings& other) const {
2502a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  return codec == other.codec &&
2503a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org         fec.ulpfec_payload_type == other.fec.ulpfec_payload_type &&
2504a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org         fec.red_payload_type == other.fec.red_payload_type &&
2505e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin         fec.red_rtx_payload_type == other.fec.red_rtx_payload_type &&
2506a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org         rtx_payload_type == other.rtx_payload_type;
2507a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org}
2508a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
2509ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boströmbool WebRtcVideoChannel2::VideoCodecSettings::operator!=(
2510ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström    const WebRtcVideoChannel2::VideoCodecSettings& other) const {
2511ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström  return !(*this == other);
2512ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström}
2513ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström
2514b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstd::vector<WebRtcVideoChannel2::VideoCodecSettings>
2515b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) {
2516d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  DCHECK(!codecs.empty());
2517b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2518b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::vector<VideoCodecSettings> video_codecs;
2519b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::map<int, bool> payload_used;
2520e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  std::map<int, VideoCodec::CodecType> payload_codec_type;
2521d324546ced76d4e792338af4f7d02a5cd8819f92pkasting@chromium.org  // |rtx_mapping| maps video payload type to rtx payload type.
2522d324546ced76d4e792338af4f7d02a5cd8819f92pkasting@chromium.org  std::map<int, int> rtx_mapping;
2523b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2524b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  webrtc::FecConfig fec_settings;
2525b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2526b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
2527b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoCodec& in_codec = codecs[i];
2528b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    int payload_type = in_codec.id;
2529b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2530b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (payload_used[payload_type]) {
2531b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_ERROR) << "Payload type already registered: "
2532b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                    << in_codec.ToString();
2533b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return std::vector<VideoCodecSettings>();
2534b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
2535b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    payload_used[payload_type] = true;
2536e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    payload_codec_type[payload_type] = in_codec.GetCodecType();
2537b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2538b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    switch (in_codec.GetCodecType()) {
2539b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_RED: {
2540b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        // RED payload type, should not have duplicates.
2541d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg        DCHECK(fec_settings.red_payload_type == -1);
2542b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        fec_settings.red_payload_type = in_codec.id;
2543b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        continue;
2544b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
2545b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2546b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_ULPFEC: {
2547b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        // ULPFEC payload type, should not have duplicates.
2548d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg        DCHECK(fec_settings.ulpfec_payload_type == -1);
2549b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        fec_settings.ulpfec_payload_type = in_codec.id;
2550b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        continue;
2551b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
2552b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2553b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_RTX: {
2554b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        int associated_payload_type;
2555b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        if (!in_codec.GetParam(kCodecParamAssociatedPayloadType,
2556e9facf8bb32a1688f2156009c755caa2904e1ac9pkasting@chromium.org                               &associated_payload_type) ||
2557e9facf8bb32a1688f2156009c755caa2904e1ac9pkasting@chromium.org            !IsValidRtpPayloadType(associated_payload_type)) {
2558e9facf8bb32a1688f2156009c755caa2904e1ac9pkasting@chromium.org          LOG(LS_ERROR)
2559e9facf8bb32a1688f2156009c755caa2904e1ac9pkasting@chromium.org              << "RTX codec with invalid or no associated payload type: "
2560e9facf8bb32a1688f2156009c755caa2904e1ac9pkasting@chromium.org              << in_codec.ToString();
2561b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org          return std::vector<VideoCodecSettings>();
2562b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        }
2563b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        rtx_mapping[associated_payload_type] = in_codec.id;
2564b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        continue;
2565b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
2566b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2567b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_VIDEO:
2568b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        break;
2569b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
2570b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2571b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    video_codecs.push_back(VideoCodecSettings());
2572b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    video_codecs.back().codec = in_codec;
2573b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
2574b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2575b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // One of these codecs should have been a video codec. Only having FEC
2576b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // parameters into this code is a logic error.
2577d3ddc1b69e9cdfd7c6d38ab02b8d8ab891d30fd1Fredrik Solenberg  DCHECK(!video_codecs.empty());
2578b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2579e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  for (std::map<int, int>::const_iterator it = rtx_mapping.begin();
2580e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org       it != rtx_mapping.end();
2581e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org       ++it) {
2582e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    if (!payload_used[it->first]) {
2583e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org      LOG(LS_ERROR) << "RTX mapped to payload not in codec list.";
2584e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org      return std::vector<VideoCodecSettings>();
2585e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    }
2586e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    if (payload_codec_type[it->first] != VideoCodec::CODEC_VIDEO &&
2587e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin        payload_codec_type[it->first] != VideoCodec::CODEC_RED) {
2588e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin      LOG(LS_ERROR) << "RTX not mapped to regular video codec or RED codec.";
2589e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org      return std::vector<VideoCodecSettings>();
2590e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    }
2591e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin
2592e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    if (it->first == fec_settings.red_payload_type) {
2593e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin      fec_settings.red_rtx_payload_type = it->second;
2594e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    }
2595e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  }
2596e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org
2597b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < video_codecs.size(); ++i) {
2598b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    video_codecs[i].fec = fec_settings;
2599e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    if (rtx_mapping[video_codecs[i].codec.id] != 0 &&
2600e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin        rtx_mapping[video_codecs[i].codec.id] !=
2601e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin            fec_settings.red_payload_type) {
2602b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id];
2603b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
2604b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
2605b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2606b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return video_codecs;
2607b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
2608b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2609b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}  // namespace cricket
2610b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2611b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#endif  // HAVE_WEBRTC_VIDEO
2612