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"
39bbaf3633c54e3d49aa4c762b8eaa34e09de01c45Stefan Holmer#include "talk/media/webrtc/webrtcmediaengine.h"
4081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström#include "talk/media/webrtc/webrtcvideoencoderfactory.h"
41b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/webrtc/webrtcvideoframe.h"
42b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "talk/media/webrtc/webrtcvoiceengine.h"
43a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/buffer.h"
44a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/logging.h"
45a09a99950ec40aef6421e4ba35eee7196b7a6e68buildbot@webrtc.org#include "webrtc/base/stringutils.h"
46c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen#include "webrtc/base/timeutils.h"
47e4f96501fc5b3e6de0d1ccd262372afcda1f5b4ftommi#include "webrtc/base/trace_event.h"
48b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#include "webrtc/call.h"
4971f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
5081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström#include "webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h"
5198f53510b222f71fdd8b799b2f33737ceeb28c61Henrik Kjellander#include "webrtc/system_wrappers/include/field_trial.h"
52776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org#include "webrtc/video_decoder.h"
53ab990ae43a2b84b103cb3c50bc38502375c13e68pbos@webrtc.org#include "webrtc/video_encoder.h"
54b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
55b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgnamespace cricket {
567fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgnamespace {
5781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
5881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström// Wrap cricket::WebRtcVideoEncoderFactory as a webrtc::VideoEncoderFactory.
5981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmclass EncoderFactoryAdapter : public webrtc::VideoEncoderFactory {
6081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström public:
6181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  // EncoderFactoryAdapter doesn't take ownership of |factory|, which is owned
6281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  // by e.g. PeerConnectionFactory.
6381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  explicit EncoderFactoryAdapter(cricket::WebRtcVideoEncoderFactory* factory)
6481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      : factory_(factory) {}
6581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  virtual ~EncoderFactoryAdapter() {}
6681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
6781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  // Implement webrtc::VideoEncoderFactory.
6881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  webrtc::VideoEncoder* Create() override {
6981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    return factory_->CreateVideoEncoder(webrtc::kVideoCodecVP8);
7081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
7181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
7281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  void Destroy(webrtc::VideoEncoder* encoder) override {
7381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    return factory_->DestroyVideoEncoder(encoder);
7481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
7581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
7681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström private:
7781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  cricket::WebRtcVideoEncoderFactory* const factory_;
7881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström};
7981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
8081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström// An encoder factory that wraps Create requests for simulcastable codec types
8181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström// with a webrtc::SimulcastEncoderAdapter. Non simulcastable codec type
8281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström// requests are just passed through to the contained encoder factory.
8381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmclass WebRtcSimulcastEncoderFactory
8481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    : public cricket::WebRtcVideoEncoderFactory {
8581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström public:
8681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  // WebRtcSimulcastEncoderFactory doesn't take ownership of |factory|, which is
8781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  // owned by e.g. PeerConnectionFactory.
8881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  explicit WebRtcSimulcastEncoderFactory(
8981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      cricket::WebRtcVideoEncoderFactory* factory)
9081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      : factory_(factory) {}
9181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
9281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  static bool UseSimulcastEncoderFactory(
9381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      const std::vector<VideoCodec>& codecs) {
9481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    // If any codec is VP8, use the simulcast factory. If asked to create a
9581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    // non-VP8 codec, we'll just return a contained factory encoder directly.
9681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    for (const auto& codec : codecs) {
9781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      if (codec.type == webrtc::kVideoCodecVP8) {
9881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström        return true;
9981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      }
10081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    }
10181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    return false;
10281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
10381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
10481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  webrtc::VideoEncoder* CreateVideoEncoder(
10581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      webrtc::VideoCodecType type) override {
10691d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_DCHECK(factory_ != NULL);
10781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    // If it's a codec type we can simulcast, create a wrapped encoder.
10881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    if (type == webrtc::kVideoCodecVP8) {
10981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      return new webrtc::SimulcastEncoderAdapter(
11081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström          new EncoderFactoryAdapter(factory_));
11181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    }
11281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    webrtc::VideoEncoder* encoder = factory_->CreateVideoEncoder(type);
11381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    if (encoder) {
11481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      non_simulcast_encoders_.push_back(encoder);
11581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    }
11681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    return encoder;
11781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
11881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
11981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  const std::vector<VideoCodec>& codecs() const override {
12081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    return factory_->codecs();
12181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
12281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
12381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  bool EncoderTypeHasInternalSource(
12481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      webrtc::VideoCodecType type) const override {
12581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    return factory_->EncoderTypeHasInternalSource(type);
12681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
12781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
12881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) override {
12981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    // Check first to see if the encoder wasn't wrapped in a
13081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    // SimulcastEncoderAdapter. In that case, ask the factory to destroy it.
13181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    if (std::remove(non_simulcast_encoders_.begin(),
13281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                    non_simulcast_encoders_.end(),
13381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                    encoder) != non_simulcast_encoders_.end()) {
13481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      factory_->DestroyVideoEncoder(encoder);
13581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      return;
13681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    }
13781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
13881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    // Otherwise, SimulcastEncoderAdapter can be deleted directly, and will call
13981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    // DestroyVideoEncoder on the factory for individual encoder instances.
14081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    delete encoder;
14181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
14281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
14381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström private:
14481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  cricket::WebRtcVideoEncoderFactory* factory_;
14581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  // A list of encoders that were created without being wrapped in a
14681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  // SimulcastEncoderAdapter.
14781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  std::vector<webrtc::VideoEncoder*> non_simulcast_encoders_;
14881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström};
14981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
15081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmbool CodecIsInternallySupported(const std::string& codec_name) {
15181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  if (CodecNamesEq(codec_name, kVp8CodecName)) {
15281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    return true;
15381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
15481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  if (CodecNamesEq(codec_name, kVp9CodecName)) {
1553ed348707e93980fd74246f7a1dfab011f841087asapersson    return true;
15681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
15771f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin  if (CodecNamesEq(codec_name, kH264CodecName)) {
15871f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin    return webrtc::H264Encoder::IsSupported() &&
15971f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin        webrtc::H264Decoder::IsSupported();
16071f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin  }
16181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  return false;
16281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström}
16381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
16481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmvoid AddDefaultFeedbackParams(VideoCodec* codec) {
16581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamCcm, kRtcpFbCcmParamFir));
16681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamNack, kParamValueEmpty));
16781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamNack, kRtcpFbNackParamPli));
16881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamRemb, kParamValueEmpty));
16943edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan  codec->AddFeedbackParam(
17043edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan      FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty));
17181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström}
17281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
17381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmstatic VideoCodec MakeVideoCodecWithDefaultFeedbackParams(int payload_type,
17481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                                                          const char* name) {
17581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  VideoCodec codec(payload_type, name, kDefaultVideoMaxWidth,
17681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                   kDefaultVideoMaxHeight, kDefaultVideoMaxFramerate, 0);
17781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  AddDefaultFeedbackParams(&codec);
17881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  return codec;
17981ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström}
18081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
1817fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgstatic std::string CodecVectorToString(const std::vector<VideoCodec>& codecs) {
1827fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  std::stringstream out;
1837fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  out << '{';
1847fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
1857fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    out << codecs[i].ToString();
1867fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (i != codecs.size() - 1) {
1877fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      out << ", ";
1887fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
1897fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
1907fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  out << '}';
1917fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return out.str();
1927fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
1937fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
1947fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgstatic bool ValidateCodecFormats(const std::vector<VideoCodec>& codecs) {
1957fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  bool has_video = false;
1967fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
1977fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (!codecs[i].ValidateCodecFormat()) {
1987fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      return false;
1997fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
2007fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (codecs[i].GetCodecType() == VideoCodec::CODEC_VIDEO) {
2017fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      has_video = true;
2027fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
2037fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
2047fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (!has_video) {
2057fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    LOG(LS_ERROR) << "Setting codecs without a video codec is invalid: "
2067fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                  << CodecVectorToString(codecs);
2077fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return false;
2087fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
2097fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return true;
2107fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
2117fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
212d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boströmstatic bool ValidateStreamParams(const StreamParams& sp) {
213d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  if (sp.ssrcs.empty()) {
214d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString();
215d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    return false;
216d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  }
217d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström
2180c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  std::vector<uint32_t> primary_ssrcs;
219d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  sp.GetPrimarySsrcs(&primary_ssrcs);
2200c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  std::vector<uint32_t> rtx_ssrcs;
221d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  sp.GetFidSsrcs(primary_ssrcs, &rtx_ssrcs);
222d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  for (uint32_t rtx_ssrc : rtx_ssrcs) {
223d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    bool rtx_ssrc_present = false;
224d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    for (uint32_t sp_ssrc : sp.ssrcs) {
225d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström      if (sp_ssrc == rtx_ssrc) {
226d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström        rtx_ssrc_present = true;
227d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström        break;
228d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström      }
229d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    }
230d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    if (!rtx_ssrc_present) {
231d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström      LOG(LS_ERROR) << "RTX SSRC '" << rtx_ssrc
232d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström                    << "' missing from StreamParams ssrcs: " << sp.ToString();
233d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström      return false;
234d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    }
235d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  }
236d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  if (!rtx_ssrcs.empty() && primary_ssrcs.size() != rtx_ssrcs.size()) {
237d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    LOG(LS_ERROR)
238d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström        << "RTX SSRCs exist, but don't cover all SSRCs (unsupported): "
239d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström        << sp.ToString();
240d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    return false;
241d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  }
242d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström
243d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  return true;
244d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström}
245d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström
24664c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shiehinline const webrtc::RtpExtension* FindHeaderExtension(
24764c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    const std::vector<webrtc::RtpExtension>& extensions,
24864c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    const std::string& name) {
24964c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  for (const auto& kv : extensions) {
25064c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    if (kv.name == name) {
25164c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh      return &kv;
25264c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    }
25364c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  }
25464c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  return NULL;
25564c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh}
25664c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh
25782775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org// Merges two fec configs and logs an error if a conflict arises
258e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin// such that merging in different order would trigger a different output.
25982775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.orgstatic void MergeFecConfig(const webrtc::FecConfig& other,
26082775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org                           webrtc::FecConfig* output) {
26182775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org  if (other.ulpfec_payload_type != -1) {
26282775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    if (output->ulpfec_payload_type != -1 &&
26382775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org        output->ulpfec_payload_type != other.ulpfec_payload_type) {
26482775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org      LOG(LS_WARNING) << "Conflict merging ulpfec_payload_type configs: "
26582775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org                      << output->ulpfec_payload_type << " and "
26682775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org                      << other.ulpfec_payload_type;
26782775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    }
26882775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    output->ulpfec_payload_type = other.ulpfec_payload_type;
26982775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org  }
27082775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org  if (other.red_payload_type != -1) {
27182775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    if (output->red_payload_type != -1 &&
27282775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org        output->red_payload_type != other.red_payload_type) {
27382775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org      LOG(LS_WARNING) << "Conflict merging red_payload_type configs: "
27482775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org                      << output->red_payload_type << " and "
27582775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org                      << other.red_payload_type;
27682775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    }
27782775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    output->red_payload_type = other.red_payload_type;
27882775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org  }
279e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin  if (other.red_rtx_payload_type != -1) {
280e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    if (output->red_rtx_payload_type != -1 &&
281e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin        output->red_rtx_payload_type != other.red_rtx_payload_type) {
282e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin      LOG(LS_WARNING) << "Conflict merging red_rtx_payload_type configs: "
283e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin                      << output->red_rtx_payload_type << " and "
284e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin                      << other.red_rtx_payload_type;
285e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    }
286e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    output->red_rtx_payload_type = other.red_rtx_payload_type;
287e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin  }
28882775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org}
289fdac516510a2bd5d57b0786fbd49e2a6b9aeed2fnoahric
290fdac516510a2bd5d57b0786fbd49e2a6b9aeed2fnoahric// Returns true if the given codec is disallowed from doing simulcast.
291fdac516510a2bd5d57b0786fbd49e2a6b9aeed2fnoahricbool IsCodecBlacklistedForSimulcast(const std::string& codec_name) {
2923ed348707e93980fd74246f7a1dfab011f841087asapersson  return CodecNamesEq(codec_name, kH264CodecName) ||
2933ed348707e93980fd74246f7a1dfab011f841087asapersson         CodecNamesEq(codec_name, kVp9CodecName);
294fdac516510a2bd5d57b0786fbd49e2a6b9aeed2fnoahric}
295fdac516510a2bd5d57b0786fbd49e2a6b9aeed2fnoahric
2961c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Persson// The selected thresholds for QVGA and VGA corresponded to a QP around 10.
2971c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Persson// The change in QP declined above the selected bitrates.
2981c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Perssonstatic int GetMaxDefaultVideoBitrateKbps(int width, int height) {
2991c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Persson  if (width * height <= 320 * 240) {
3001c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Persson    return 600;
3011c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Persson  } else if (width * height <= 640 * 480) {
3021c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Persson    return 1700;
3031c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Persson  } else if (width * height <= 960 * 540) {
3041c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Persson    return 2000;
3051c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Persson  } else {
3061c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Persson    return 2500;
3071c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Persson  }
3081c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Persson}
3097fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}  // namespace
310b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
31181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström// Constants defined in talk/media/webrtc/constants.h
31281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström// TODO(pbos): Move these to a separate constants.cc file.
31381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmconst int kMinVideoBitrate = 30;
31481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmconst int kStartVideoBitrate = 300;
31581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
31681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmconst int kVideoMtu = 1200;
31781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmconst int kVideoRtpBufferSize = 65536;
31881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
319b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// This constant is really an on/off, lower-level configurable NACK history
320b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// duration hasn't been implemented.
321b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const int kNackHistoryMs = 1000;
322b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
323933d88af58b00517570ef78f38852bfd7fb1bb02buildbot@webrtc.orgstatic const int kDefaultQpMax = 56;
324933d88af58b00517570ef78f38852bfd7fb1bb02buildbot@webrtc.org
325b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstatic const int kDefaultRtcpReceiverReportSsrc = 1;
326b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
32781ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boströmstd::vector<VideoCodec> DefaultVideoCodecList() {
32881ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  std::vector<VideoCodec> codecs;
3293ed348707e93980fd74246f7a1dfab011f841087asapersson  codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultVp8PlType,
3303ed348707e93980fd74246f7a1dfab011f841087asapersson                                                           kVp8CodecName));
33181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  if (CodecIsInternallySupported(kVp9CodecName)) {
33281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultVp9PlType,
33381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström                                                             kVp9CodecName));
33481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström    // TODO(andresp): Add rtx codec for vp9 and verify it works.
33581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  }
33671f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin  if (CodecIsInternallySupported(kH264CodecName)) {
33771f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin    codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultH264PlType,
33871f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin                                                             kH264CodecName));
33971f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin  }
34081ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  codecs.push_back(
34181ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström      VideoCodec::CreateRtxCodec(kDefaultRtxVp8PlType, kDefaultVp8PlType));
34281ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  codecs.push_back(VideoCodec(kDefaultRedPlType, kRedCodecName));
34381ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  codecs.push_back(VideoCodec(kDefaultUlpfecType, kUlpfecCodecName));
34481ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström  return codecs;
34581ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström}
34681ea54eaac82b36b7208a02fd37a469d7d0bd9d0Peter Boström
347a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.orgstd::vector<webrtc::VideoStream>
348f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::CreateSimulcastVideoStreams(
349d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    const VideoCodec& codec,
350d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    const VideoOptions& options,
351dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    int max_bitrate_bps,
352d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org    size_t num_streams) {
353a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org  int max_qp = kDefaultQpMax;
354a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org  codec.GetParam(kCodecParamMaxQuantization, &max_qp);
355a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org
356a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org  return GetSimulcastConfig(
357be16f79818d7c21b747189b3e86d8d98add3e6b1pbos      num_streams, codec.width, codec.height, max_bitrate_bps, max_qp,
358a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org      codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate);
359a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org}
360a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org
361f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.orgstd::vector<webrtc::VideoStream>
362f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoStreams(
363a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org    const VideoCodec& codec,
364a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org    const VideoOptions& options,
365dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    int max_bitrate_bps,
366a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org    size_t num_streams) {
367dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  int codec_max_bitrate_kbps;
368dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  if (codec.GetParam(kCodecParamMaxBitrate, &codec_max_bitrate_kbps)) {
369dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    max_bitrate_bps = codec_max_bitrate_kbps * 1000;
370dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  }
371dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  if (num_streams != 1) {
372dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    return CreateSimulcastVideoStreams(codec, options, max_bitrate_bps,
373dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström                                       num_streams);
374dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  }
375dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström
376dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  // For unset max bitrates set default bitrate for non-simulcast.
3771c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Persson  if (max_bitrate_bps <= 0) {
3781c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Persson    max_bitrate_bps =
3791c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Persson        GetMaxDefaultVideoBitrateKbps(codec.width, codec.height) * 1000;
3801c7d48d431e098ba42fa6bd9f1cfe69a703edee5Ã…sa Persson  }
381a85307737cc9ea3e79b86daf96d455fca4ad1bb4buildbot@webrtc.org
382d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  webrtc::VideoStream stream;
383d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.width = codec.width;
384d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.height = codec.height;
385d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.max_framerate =
38682775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org      codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate;
387d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org
388008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  stream.min_bitrate_bps = kMinVideoBitrate * 1000;
389dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate_bps;
390d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org
391933d88af58b00517570ef78f38852bfd7fb1bb02buildbot@webrtc.org  int max_qp = kDefaultQpMax;
392d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  codec.GetParam(kCodecParamMaxQuantization, &max_qp);
393d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  stream.max_qp = max_qp;
394d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  std::vector<webrtc::VideoStream> streams;
395d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  streams.push_back(stream);
396d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org  return streams;
397d41eaeb7cded2b2cda83f53aa320cf18e2d07380buildbot@webrtc.org}
398b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
399f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.orgvoid* WebRtcVideoChannel2::WebRtcVideoSendStream::ConfigureVideoEncoderSettings(
4006f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org    const VideoCodec& codec,
401143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng    const VideoOptions& options,
402143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng    bool is_screencast) {
4032feafdb742226f57588d9c95bc25b2202166688fPeter Boström  // No automatic resizing when using simulcast or screencast.
4042feafdb742226f57588d9c95bc25b2202166688fPeter Boström  bool automatic_resize =
4052feafdb742226f57588d9c95bc25b2202166688fPeter Boström      !is_screencast && parameters_.config.rtp.ssrcs.size() == 1;
406143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng  bool frame_dropping = !is_screencast;
407143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng  bool denoising;
4084cba4eba596706f2238d14f96f4e181f47e5034cpbos  bool codec_default_denoising = false;
409143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng  if (is_screencast) {
410143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng    denoising = false;
411143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng  } else {
4124cba4eba596706f2238d14f96f4e181f47e5034cpbos    // Use codec default if video_noise_reduction is unset.
413102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg    codec_default_denoising = !options.video_noise_reduction;
414102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg    denoising = options.video_noise_reduction.value_or(false);
415143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng  }
416143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng
417e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin  if (CodecNamesEq(codec.name, kVp8CodecName)) {
418f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.org    encoder_settings_.vp8 = webrtc::VideoEncoder::GetDefaultVp8Settings();
419143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng    encoder_settings_.vp8.automaticResizeOn = automatic_resize;
4204cba4eba596706f2238d14f96f4e181f47e5034cpbos    // VP8 denoising is enabled by default.
4214cba4eba596706f2238d14f96f4e181f47e5034cpbos    encoder_settings_.vp8.denoisingOn =
4224cba4eba596706f2238d14f96f4e181f47e5034cpbos        codec_default_denoising ? true : denoising;
423143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng    encoder_settings_.vp8.frameDroppingOn = frame_dropping;
424f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.org    return &encoder_settings_.vp8;
4256f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  }
426e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin  if (CodecNamesEq(codec.name, kVp9CodecName)) {
427f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.org    encoder_settings_.vp9 = webrtc::VideoEncoder::GetDefaultVp9Settings();
4284cba4eba596706f2238d14f96f4e181f47e5034cpbos    // VP9 denoising is disabled by default.
4294cba4eba596706f2238d14f96f4e181f47e5034cpbos    encoder_settings_.vp9.denoisingOn =
4304cba4eba596706f2238d14f96f4e181f47e5034cpbos        codec_default_denoising ? false : denoising;
431143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng    encoder_settings_.vp9.frameDroppingOn = frame_dropping;
432f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.org    return &encoder_settings_.vp9;
433188d3b2245b49f21468840386d81b080176b434bandresp@webrtc.org  }
4346f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org  return NULL;
4356f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org}
4366f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
437afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.orgDefaultUnsignalledSsrcHandler::DefaultUnsignalledSsrcHandler()
438afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    : default_recv_ssrc_(0), default_renderer_(NULL) {}
439afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
440afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.orgUnsignalledSsrcHandler::Action DefaultUnsignalledSsrcHandler::OnUnsignalledSsrc(
441a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org    WebRtcVideoChannel2* channel,
442afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    uint32_t ssrc) {
443afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  if (default_recv_ssrc_ != 0) {  // Already one default stream.
444afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    LOG(LS_WARNING) << "Unknown SSRC, but default receive stream already set.";
445afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    return kDropPacket;
446afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  }
447afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
448afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  StreamParams sp;
449afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  sp.ssrcs.push_back(ssrc);
450afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  LOG(LS_INFO) << "Creating default receive stream for SSRC=" << ssrc << ".";
451a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org  if (!channel->AddRecvStream(sp, true)) {
452afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    LOG(LS_WARNING) << "Could not create default receive stream.";
453afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  }
454afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
455afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  channel->SetRenderer(ssrc, default_renderer_);
456afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  default_recv_ssrc_ = ssrc;
457afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  return kDeliverPacket;
458afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org}
459afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
460afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.orgVideoRenderer* DefaultUnsignalledSsrcHandler::GetDefaultRenderer() const {
461afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  return default_renderer_;
462afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org}
463afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
464afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.orgvoid DefaultUnsignalledSsrcHandler::SetDefaultRenderer(
465afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    VideoMediaChannel* channel,
466afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    VideoRenderer* renderer) {
467afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  default_renderer_ = renderer;
468afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  if (default_recv_ssrc_ != 0) {
469afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    channel->SetRenderer(default_recv_ssrc_, default_renderer_);
470afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  }
471afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org}
472afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org
473709ed67c38d0a942f3bf3e68e337cc27a27bc353Fredrik SolenbergWebRtcVideoEngine2::WebRtcVideoEngine2()
474709ed67c38d0a942f3bf3e68e337cc27a27bc353Fredrik Solenberg    : initialized_(false),
4750a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org      external_decoder_factory_(NULL),
4760a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org      external_encoder_factory_(NULL) {
477b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::WebRtcVideoEngine2()";
4787fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  video_codecs_ = GetSupportedCodecs();
479b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
480b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
481b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoEngine2::~WebRtcVideoEngine2() {
482b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::~WebRtcVideoEngine2";
483b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
484b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
4859a416bd14ee225d8f1a1ada627a1dd7daf275032Fredrik Solenbergvoid WebRtcVideoEngine2::Init() {
486b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "WebRtcVideoEngine2::Init";
487b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  initialized_ = true;
488b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
489b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
490b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2* WebRtcVideoEngine2::CreateChannel(
491709ed67c38d0a942f3bf3e68e337cc27a27bc353Fredrik Solenberg    webrtc::Call* call,
492709ed67c38d0a942f3bf3e68e337cc27a27bc353Fredrik Solenberg    const VideoOptions& options) {
49391d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(initialized_);
494709ed67c38d0a942f3bf3e68e337cc27a27bc353Fredrik Solenberg  LOG(LS_INFO) << "CreateChannel. Options: " << options.ToString();
495b071a19019a0a2173cc139c960d6ef6946a1c581Fredrik Solenberg  return new WebRtcVideoChannel2(call, options, video_codecs_,
496709ed67c38d0a942f3bf3e68e337cc27a27bc353Fredrik Solenberg      external_encoder_factory_, external_decoder_factory_);
497b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
498b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
499b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgconst std::vector<VideoCodec>& WebRtcVideoEngine2::codecs() const {
500b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return video_codecs_;
501b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
502b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
5039d69c3f4d99240c27d997c37950b561605d403bdStefan HolmerRtpCapabilities WebRtcVideoEngine2::GetCapabilities() const {
5049d69c3f4d99240c27d997c37950b561605d403bdStefan Holmer  RtpCapabilities capabilities;
5059d69c3f4d99240c27d997c37950b561605d403bdStefan Holmer  capabilities.header_extensions.push_back(
5069d69c3f4d99240c27d997c37950b561605d403bdStefan Holmer      RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension,
5079d69c3f4d99240c27d997c37950b561605d403bdStefan Holmer                         kRtpTimestampOffsetHeaderExtensionDefaultId));
5089d69c3f4d99240c27d997c37950b561605d403bdStefan Holmer  capabilities.header_extensions.push_back(
5099d69c3f4d99240c27d997c37950b561605d403bdStefan Holmer      RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension,
5109d69c3f4d99240c27d997c37950b561605d403bdStefan Holmer                         kRtpAbsoluteSenderTimeHeaderExtensionDefaultId));
5119d69c3f4d99240c27d997c37950b561605d403bdStefan Holmer  capabilities.header_extensions.push_back(
5129d69c3f4d99240c27d997c37950b561605d403bdStefan Holmer      RtpHeaderExtension(kRtpVideoRotationHeaderExtension,
5139d69c3f4d99240c27d997c37950b561605d403bdStefan Holmer                         kRtpVideoRotationHeaderExtensionDefaultId));
5149d69c3f4d99240c27d997c37950b561605d403bdStefan Holmer  if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe") == "Enabled") {
5159d69c3f4d99240c27d997c37950b561605d403bdStefan Holmer    capabilities.header_extensions.push_back(RtpHeaderExtension(
5169d69c3f4d99240c27d997c37950b561605d403bdStefan Holmer        kRtpTransportSequenceNumberHeaderExtension,
5179d69c3f4d99240c27d997c37950b561605d403bdStefan Holmer        kRtpTransportSequenceNumberHeaderExtensionDefaultId));
5189d69c3f4d99240c27d997c37950b561605d403bdStefan Holmer  }
5199d69c3f4d99240c27d997c37950b561605d403bdStefan Holmer  return capabilities;
520b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
521b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
5220a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.orgvoid WebRtcVideoEngine2::SetExternalDecoderFactory(
5230a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org    WebRtcVideoDecoderFactory* decoder_factory) {
52491d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(!initialized_);
5250a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  external_decoder_factory_ = decoder_factory;
5260a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org}
5270a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org
5280a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.orgvoid WebRtcVideoEngine2::SetExternalEncoderFactory(
5290a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org    WebRtcVideoEncoderFactory* encoder_factory) {
53091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(!initialized_);
531f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org  if (external_encoder_factory_ == encoder_factory)
532f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org    return;
533f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org
534f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org  // No matter what happens we shouldn't hold on to a stale
535f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org  // WebRtcSimulcastEncoderFactory.
536f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org  simulcast_encoder_factory_.reset();
537f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org
538f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org  if (encoder_factory &&
539f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org      WebRtcSimulcastEncoderFactory::UseSimulcastEncoderFactory(
540f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org          encoder_factory->codecs())) {
541f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org    simulcast_encoder_factory_.reset(
542f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org        new WebRtcSimulcastEncoderFactory(encoder_factory));
543f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org    encoder_factory = simulcast_encoder_factory_.get();
544f18fba2f7b3d1fad7b7b38a9a5dc281bef06c50epbos@webrtc.org  }
5450a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org  external_encoder_factory_ = encoder_factory;
5467fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
5477fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  video_codecs_ = GetSupportedCodecs();
5480a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org}
5490a2087a7110e2455ce68f2c85068df5ae447508fpbos@webrtc.org
550b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::EnableTimedRender() {
551b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Figure out whether this can be removed.
552b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
553b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
554b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
555b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// Checks to see whether we comprehend and could receive a particular codec
556b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::FindCodec(const VideoCodec& in) {
557b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Probe encoder factory to figure out that the codec is supported
558b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // if supported by the encoder factory. Add a corresponding test that fails
559b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // with this code (that doesn't ask the factory).
5608fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org  for (size_t j = 0; j < video_codecs_.size(); ++j) {
5618fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    VideoCodec codec(video_codecs_[j].id, video_codecs_[j].name, 0, 0, 0, 0);
5628fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org    if (codec.Matches(in)) {
5638fdeee6abfcb560233b5e769afb1c1c72cc2100dpbos@webrtc.org      return true;
564b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
565b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
566b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return false;
567b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
568b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
569b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// Ignore spammy trace messages, mostly from the stats API when we haven't
570b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org// gotten RTCP info yet from the remote side.
571b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoEngine2::ShouldIgnoreTrace(const std::string& trace) {
572b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  static const char* const kTracesToIgnore[] = {NULL};
573b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (const char* const* p = kTracesToIgnore; *p; ++p) {
574b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (trace.find(*p) == 0) {
575b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return true;
576b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
577b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
578b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return false;
579b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
580b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
5817fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgstd::vector<VideoCodec> WebRtcVideoEngine2::GetSupportedCodecs() const {
58282775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org  std::vector<VideoCodec> supported_codecs = DefaultVideoCodecList();
5837fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
5847fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (external_encoder_factory_ == NULL) {
5857fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return supported_codecs;
5867fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
5877fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
5887fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs =
5897fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      external_encoder_factory_->codecs();
5907fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
5917fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    // Don't add internally-supported codecs twice.
5927fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (CodecIsInternallySupported(codecs[i].name)) {
5937fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      continue;
5947fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
5957fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
596d324546ced76d4e792338af4f7d02a5cd8819f92pkasting@chromium.org    // External video encoders are given payloads 120-127. This also means that
597d324546ced76d4e792338af4f7d02a5cd8819f92pkasting@chromium.org    // we only support up to 8 external payload types.
598d324546ced76d4e792338af4f7d02a5cd8819f92pkasting@chromium.org    const int kExternalVideoPayloadTypeBase = 120;
599d324546ced76d4e792338af4f7d02a5cd8819f92pkasting@chromium.org    size_t payload_type = kExternalVideoPayloadTypeBase + i;
60091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_DCHECK(payload_type < 128);
601d324546ced76d4e792338af4f7d02a5cd8819f92pkasting@chromium.org    VideoCodec codec(static_cast<int>(payload_type),
6027fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                     codecs[i].name,
6037fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                     codecs[i].max_width,
6047fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                     codecs[i].max_height,
6057fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                     codecs[i].max_fps,
6067fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org                     0);
6077fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
6087fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    AddDefaultFeedbackParams(&codec);
6097fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    supported_codecs.push_back(codec);
6107fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
6117fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return supported_codecs;
6127fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
6137fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
614b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoChannel2(
615709ed67c38d0a942f3bf3e68e337cc27a27bc353Fredrik Solenberg    webrtc::Call* call,
616fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org    const VideoOptions& options,
617b071a19019a0a2173cc139c960d6ef6946a1c581Fredrik Solenberg    const std::vector<VideoCodec>& recv_codecs,
6187fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    WebRtcVideoEncoderFactory* external_encoder_factory,
619f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.org    WebRtcVideoDecoderFactory* external_decoder_factory)
620709ed67c38d0a942f3bf3e68e337cc27a27bc353Fredrik Solenberg    : call_(call),
621709ed67c38d0a942f3bf3e68e337cc27a27bc353Fredrik Solenberg      unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_),
6227fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      external_encoder_factory_(external_encoder_factory),
623f1c8b905204bc7a6c74271ead038f5d80d8d3eedpbos@webrtc.org      external_decoder_factory_(external_decoder_factory) {
62491d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(thread_checker_.CalledOnValidThread());
625fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org  SetDefaultOptions();
626fa553ef6053b20f3768d5fe4314e8c993648bf0apbos@webrtc.org  options_.SetAll(options);
627102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg  if (options_.cpu_overuse_detection)
628102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg    signal_cpu_adaptation_ = *options_.cpu_overuse_detection;
629b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  rtcp_receiver_report_ssrc_ = kDefaultRtcpReceiverReportSsrc;
630b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = false;
631b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  default_send_ssrc_ = 0;
632b071a19019a0a2173cc139c960d6ef6946a1c581Fredrik Solenberg  SetRecvCodecs(recv_codecs);
6336f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org}
6346f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
6356f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.orgvoid WebRtcVideoChannel2::SetDefaultOptions() {
636be57983f4bd875c39a229bab5112b32dad004057Karl Wiberg  options_.cpu_overuse_detection = rtc::Optional<bool>(true);
637be57983f4bd875c39a229bab5112b32dad004057Karl Wiberg  options_.dscp = rtc::Optional<bool>(false);
638be57983f4bd875c39a229bab5112b32dad004057Karl Wiberg  options_.suspend_below_min_bitrate = rtc::Optional<bool>(false);
639be57983f4bd875c39a229bab5112b32dad004057Karl Wiberg  options_.screencast_min_bitrate = rtc::Optional<int>(0);
640b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
641b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
642b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::~WebRtcVideoChannel2() {
643dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  for (auto& kv : send_streams_)
644dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    delete kv.second;
645dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  for (auto& kv : receive_streams_)
646dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    delete kv.second;
647b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
648b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
64996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.orgbool WebRtcVideoChannel2::CodecIsExternallySupported(
65096a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    const std::string& name) const {
65196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  if (external_encoder_factory_ == NULL) {
65296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    return false;
65396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  }
65496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org
65596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  const std::vector<WebRtcVideoEncoderFactory::VideoCodec> external_codecs =
65696a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      external_encoder_factory_->codecs();
65796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  for (size_t c = 0; c < external_codecs.size(); ++c) {
658e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    if (CodecNamesEq(name, external_codecs[c].name)) {
65996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      return true;
66096a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    }
66196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  }
66296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  return false;
66396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org}
66496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org
66596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.orgstd::vector<WebRtcVideoChannel2::VideoCodecSettings>
66696a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.orgWebRtcVideoChannel2::FilterSupportedCodecs(
66796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    const std::vector<WebRtcVideoChannel2::VideoCodecSettings>& mapped_codecs)
66896a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    const {
66996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  std::vector<VideoCodecSettings> supported_codecs;
67096a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  for (size_t i = 0; i < mapped_codecs.size(); ++i) {
67196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    const VideoCodecSettings& codec = mapped_codecs[i];
67296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    if (CodecIsInternallySupported(codec.codec.name) ||
67396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org        CodecIsExternallySupported(codec.codec.name)) {
67496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      supported_codecs.push_back(codec);
67596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    }
67696a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  }
67796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  return supported_codecs;
67896a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org}
67996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org
680874ca3af5b163e1b3fd8802171e44ee252557842deadbeefbool WebRtcVideoChannel2::ReceiveCodecsHaveChanged(
681874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    std::vector<VideoCodecSettings> before,
682874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    std::vector<VideoCodecSettings> after) {
683874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  if (before.size() != after.size()) {
684874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    return true;
685874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  }
686874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  // The receive codec order doesn't matter, so we sort the codecs before
687874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  // comparing. This is necessary because currently the
688874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  // only way to change the send codec is to munge SDP, which causes
689874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  // the receive codec list to change order, which causes the streams
690874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  // to be recreates which causes a "blink" of black video.  In order
691874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  // to support munging the SDP in this way without recreating receive
692874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  // streams, we ignore the order of the received codecs so that
693874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  // changing the order doesn't cause this "blink".
694874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  auto comparison =
695874ca3af5b163e1b3fd8802171e44ee252557842deadbeef      [](const VideoCodecSettings& codec1, const VideoCodecSettings& codec2) {
696874ca3af5b163e1b3fd8802171e44ee252557842deadbeef        return codec1.codec.id > codec2.codec.id;
697874ca3af5b163e1b3fd8802171e44ee252557842deadbeef      };
698874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  std::sort(before.begin(), before.end(), comparison);
699874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  std::sort(after.begin(), after.end(), comparison);
700874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  for (size_t i = 0; i < before.size(); ++i) {
701874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    // For the same reason that we sort the codecs, we also ignore the
702874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    // preference.  We don't want a preference change on the receive
703874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    // side to cause recreation of the stream.
704874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    before[i].codec.preference = 0;
705874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    after[i].codec.preference = 0;
706874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    if (before[i] != after[i]) {
707874ca3af5b163e1b3fd8802171e44ee252557842deadbeef      return true;
708874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    }
709874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  }
710874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  return false;
711874ca3af5b163e1b3fd8802171e44ee252557842deadbeef}
712874ca3af5b163e1b3fd8802171e44ee252557842deadbeef
713c2ee2c86f905991a8cd05ee1f35bea105b41e4e0Peter Thatcherbool WebRtcVideoChannel2::SetSendParameters(const VideoSendParameters& params) {
7149f45a45a628100d973111b3aac66dede57454b6aPeter Boström  TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetSendParameters");
7157e4e01a4413fa98644b94ab9d8a9dccc664f39f2solenberg  LOG(LS_INFO) << "SetSendParameters: " << params.ToString();
716c2ee2c86f905991a8cd05ee1f35bea105b41e4e0Peter Thatcher  // TODO(pbos): Refactor this to only recreate the send streams once
717c2ee2c86f905991a8cd05ee1f35bea105b41e4e0Peter Thatcher  // instead of 4 times.
7181387149ad1669365ac05278bf779a407bec08a4edeadbeef  if (!SetSendCodecs(params.codecs) ||
7191387149ad1669365ac05278bf779a407bec08a4edeadbeef      !SetSendRtpHeaderExtensions(params.extensions) ||
7201387149ad1669365ac05278bf779a407bec08a4edeadbeef      !SetMaxSendBandwidth(params.max_bandwidth_bps) ||
7211387149ad1669365ac05278bf779a407bec08a4edeadbeef      !SetOptions(params.options)) {
7221387149ad1669365ac05278bf779a407bec08a4edeadbeef    return false;
7231387149ad1669365ac05278bf779a407bec08a4edeadbeef  }
7241387149ad1669365ac05278bf779a407bec08a4edeadbeef  if (send_params_.rtcp.reduced_size != params.rtcp.reduced_size) {
7251387149ad1669365ac05278bf779a407bec08a4edeadbeef    rtc::CritScope stream_lock(&stream_crit_);
7261387149ad1669365ac05278bf779a407bec08a4edeadbeef    for (auto& kv : send_streams_) {
7271387149ad1669365ac05278bf779a407bec08a4edeadbeef      kv.second->SetSendParameters(params);
7281387149ad1669365ac05278bf779a407bec08a4edeadbeef    }
7291387149ad1669365ac05278bf779a407bec08a4edeadbeef  }
7301387149ad1669365ac05278bf779a407bec08a4edeadbeef  send_params_ = params;
7311387149ad1669365ac05278bf779a407bec08a4edeadbeef  return true;
732c2ee2c86f905991a8cd05ee1f35bea105b41e4e0Peter Thatcher}
733c2ee2c86f905991a8cd05ee1f35bea105b41e4e0Peter Thatcher
734c2ee2c86f905991a8cd05ee1f35bea105b41e4e0Peter Thatcherbool WebRtcVideoChannel2::SetRecvParameters(const VideoRecvParameters& params) {
7359f45a45a628100d973111b3aac66dede57454b6aPeter Boström  TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetRecvParameters");
7367e4e01a4413fa98644b94ab9d8a9dccc664f39f2solenberg  LOG(LS_INFO) << "SetRecvParameters: " << params.ToString();
737c2ee2c86f905991a8cd05ee1f35bea105b41e4e0Peter Thatcher  // TODO(pbos): Refactor this to only recreate the recv streams once
738c2ee2c86f905991a8cd05ee1f35bea105b41e4e0Peter Thatcher  // instead of twice.
7391387149ad1669365ac05278bf779a407bec08a4edeadbeef  if (!SetRecvCodecs(params.codecs) ||
7401387149ad1669365ac05278bf779a407bec08a4edeadbeef      !SetRecvRtpHeaderExtensions(params.extensions)) {
7411387149ad1669365ac05278bf779a407bec08a4edeadbeef    return false;
7421387149ad1669365ac05278bf779a407bec08a4edeadbeef  }
7431387149ad1669365ac05278bf779a407bec08a4edeadbeef  if (recv_params_.rtcp.reduced_size != params.rtcp.reduced_size) {
7441387149ad1669365ac05278bf779a407bec08a4edeadbeef    rtc::CritScope stream_lock(&stream_crit_);
7451387149ad1669365ac05278bf779a407bec08a4edeadbeef    for (auto& kv : receive_streams_) {
7461387149ad1669365ac05278bf779a407bec08a4edeadbeef      kv.second->SetRecvParameters(params);
7471387149ad1669365ac05278bf779a407bec08a4edeadbeef    }
7481387149ad1669365ac05278bf779a407bec08a4edeadbeef  }
7491387149ad1669365ac05278bf779a407bec08a4edeadbeef  recv_params_ = params;
7501387149ad1669365ac05278bf779a407bec08a4edeadbeef  return true;
751c2ee2c86f905991a8cd05ee1f35bea105b41e4e0Peter Thatcher}
752c2ee2c86f905991a8cd05ee1f35bea105b41e4e0Peter Thatcher
753874ca3af5b163e1b3fd8802171e44ee252557842deadbeefstd::string WebRtcVideoChannel2::CodecSettingsVectorToString(
754874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    const std::vector<VideoCodecSettings>& codecs) {
755874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  std::stringstream out;
756874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  out << '{';
757874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  for (size_t i = 0; i < codecs.size(); ++i) {
758874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    out << codecs[i].codec.ToString();
759874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    if (i != codecs.size() - 1) {
760874ca3af5b163e1b3fd8802171e44ee252557842deadbeef      out << ", ";
761874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    }
762874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  }
763874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  out << '}';
764874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  return out.str();
765874ca3af5b163e1b3fd8802171e44ee252557842deadbeef}
766874ca3af5b163e1b3fd8802171e44ee252557842deadbeef
767b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) {
76850fe359eb614e1bbe41124b9c19263019da0395dpbos@webrtc.org  TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetRecvCodecs");
769b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetRecvCodecs: " << CodecVectorToString(codecs);
770b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!ValidateCodecFormats(codecs)) {
771b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
772b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
773b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
774b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const std::vector<VideoCodecSettings> mapped_codecs = MapCodecs(codecs);
775b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (mapped_codecs.empty()) {
77696a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    LOG(LS_ERROR) << "SetRecvCodecs called without any video codecs.";
777b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
778b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
779b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
780874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  std::vector<VideoCodecSettings> supported_codecs =
78196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      FilterSupportedCodecs(mapped_codecs);
78296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org
78396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  if (mapped_codecs.size() != supported_codecs.size()) {
78496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    LOG(LS_ERROR) << "SetRecvCodecs called with unsupported video codecs.";
78596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    return false;
786b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
787b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
788ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström  // Prevent reconfiguration when setting identical receive codecs.
789874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  if (!ReceiveCodecsHaveChanged(recv_codecs_, supported_codecs)) {
790874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    LOG(LS_INFO)
791874ca3af5b163e1b3fd8802171e44ee252557842deadbeef        << "Ignoring call to SetRecvCodecs because codecs haven't changed.";
792874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    return true;
793ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström  }
794ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström
795874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  LOG(LS_INFO) << "Changing recv codecs from "
796874ca3af5b163e1b3fd8802171e44ee252557842deadbeef               << CodecSettingsVectorToString(recv_codecs_) << " to "
797874ca3af5b163e1b3fd8802171e44ee252557842deadbeef               << CodecSettingsVectorToString(supported_codecs);
79896a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  recv_codecs_ = supported_codecs;
799d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
800575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
8010c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (std::map<uint32_t, WebRtcVideoReceiveStream*>::iterator it =
802d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org           receive_streams_.begin();
8030c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström       it != receive_streams_.end(); ++it) {
804d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    it->second->SetRecvCodecs(recv_codecs_);
805d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
806d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
807b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
808b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
809b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
810b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) {
81150fe359eb614e1bbe41124b9c19263019da0395dpbos@webrtc.org  TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetSendCodecs");
812b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetSendCodecs: " << CodecVectorToString(codecs);
813b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!ValidateCodecFormats(codecs)) {
814b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
815b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
816b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
817b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  const std::vector<VideoCodecSettings> supported_codecs =
818b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      FilterSupportedCodecs(MapCodecs(codecs));
819b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
820b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (supported_codecs.empty()) {
8213c3f6460646183914629e5dab8ae5fcede4f0e80Peter Boström    LOG(LS_ERROR) << "No video codecs supported.";
822b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
823b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
824b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
825b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "Using codec: " << supported_codecs.front().codec.ToString();
826b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
827102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg  if (send_codec_ && supported_codecs.front() == *send_codec_) {
828874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    LOG(LS_INFO) << "Ignore call to SetSendCodecs because first supported "
829874ca3af5b163e1b3fd8802171e44ee252557842deadbeef                    "codec hasn't changed.";
830a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    // Using same codec, avoid reconfiguring.
831a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    return true;
832a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  }
833a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
834be57983f4bd875c39a229bab5112b32dad004057Karl Wiberg  send_codec_ = rtc::Optional<WebRtcVideoChannel2::VideoCodecSettings>(
835102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg      supported_codecs.front());
836a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
837575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
838874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  LOG(LS_INFO) << "Change the send codec because SetSendCodecs has a different "
839874ca3af5b163e1b3fd8802171e44ee252557842deadbeef                  "first supported codec.";
840126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström  for (auto& kv : send_streams_) {
84191d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_DCHECK(kv.second != nullptr);
842126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström    kv.second->SetCodec(supported_codecs.front());
843126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström  }
84443edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan  LOG(LS_INFO)
84543edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan      << "SetFeedbackOptions on all the receive streams because the send "
84643edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan         "codec has changed.";
847126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström  for (auto& kv : receive_streams_) {
84891d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_DCHECK(kv.second != nullptr);
84943edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan    kv.second->SetFeedbackParameters(
85043edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan        HasNack(supported_codecs.front().codec),
85143edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan        HasRemb(supported_codecs.front().codec),
85243edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan        HasTransportCc(supported_codecs.front().codec));
853d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
854b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
855e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  // TODO(holmer): Changing the codec parameters shouldn't necessarily mean that
856e59041672283a28bde0b043c0c2bc198272f82e1Stefan Holmer  // we change the min/max of bandwidth estimation. Reevaluate this.
857008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  VideoCodec codec = supported_codecs.front().codec;
858008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  int bitrate_kbps;
859008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  if (codec.GetParam(kCodecParamMinBitrate, &bitrate_kbps) &&
860008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org      bitrate_kbps > 0) {
861008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    bitrate_config_.min_bitrate_bps = bitrate_kbps * 1000;
862008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  } else {
863008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    bitrate_config_.min_bitrate_bps = 0;
864008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  }
865008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  if (codec.GetParam(kCodecParamStartBitrate, &bitrate_kbps) &&
866008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org      bitrate_kbps > 0) {
867008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    bitrate_config_.start_bitrate_bps = bitrate_kbps * 1000;
868008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  } else {
869008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    // Do not reconfigure start bitrate unless it's specified and positive.
870008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    bitrate_config_.start_bitrate_bps = -1;
871008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  }
872008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  if (codec.GetParam(kCodecParamMaxBitrate, &bitrate_kbps) &&
873008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org      bitrate_kbps > 0) {
874008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    bitrate_config_.max_bitrate_bps = bitrate_kbps * 1000;
875008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  } else {
876008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    bitrate_config_.max_bitrate_bps = -1;
877008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  }
878008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  call_->SetBitrateConfig(bitrate_config_);
879008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org
880b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
881b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
882b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
883b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::GetSendCodec(VideoCodec* codec) {
884102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg  if (!send_codec_) {
885b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_VERBOSE) << "GetSendCodec: No send codec set.";
886b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
887b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
888102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg  *codec = send_codec_->codec;
889b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
890b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
891b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
8920c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool WebRtcVideoChannel2::SetSendStreamFormat(uint32_t ssrc,
893b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                                              const VideoFormat& format) {
894b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetSendStreamFormat:" << ssrc << " -> "
895b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << format.ToString();
896575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
897b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send_streams_.find(ssrc) == send_streams_.end()) {
898b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
899b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
900b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return send_streams_[ssrc]->SetVideoFormat(format);
901b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
902b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
903b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSend(bool send) {
904b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SetSend: " << (send ? "true" : "false");
905102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg  if (send && !send_codec_) {
906b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "SetSend(true) called before setting codec.";
907b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
908b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
909b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send) {
910b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    StartAllSendStreams();
911b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  } else {
912b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    StopAllSendStreams();
913b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
914b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  sending_ = send;
915b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
916b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
917b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
9180c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool WebRtcVideoChannel2::SetVideoSend(uint32_t ssrc, bool enable,
9191dd98f321920c1442dd5b3f791ea0fca133c2756solenberg                                       const VideoOptions* options) {
9201dd98f321920c1442dd5b3f791ea0fca133c2756solenberg  // TODO(solenberg): The state change should be fully rolled back if any one of
9211dd98f321920c1442dd5b3f791ea0fca133c2756solenberg  //                  these calls fail.
922dfc8f4ff8731390828884a0a91b99e51f2950275solenberg  if (!MuteStream(ssrc, !enable)) {
9231dd98f321920c1442dd5b3f791ea0fca133c2756solenberg    return false;
9241dd98f321920c1442dd5b3f791ea0fca133c2756solenberg  }
925dfc8f4ff8731390828884a0a91b99e51f2950275solenberg  if (enable && options) {
9261dd98f321920c1442dd5b3f791ea0fca133c2756solenberg    return SetOptions(*options);
9271dd98f321920c1442dd5b3f791ea0fca133c2756solenberg  } else {
9281dd98f321920c1442dd5b3f791ea0fca133c2756solenberg    return true;
9291dd98f321920c1442dd5b3f791ea0fca133c2756solenberg  }
9301dd98f321920c1442dd5b3f791ea0fca133c2756solenberg}
9311dd98f321920c1442dd5b3f791ea0fca133c2756solenberg
932d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boströmbool WebRtcVideoChannel2::ValidateSendSsrcAvailability(
933d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    const StreamParams& sp) const {
934d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  for (uint32_t ssrc: sp.ssrcs) {
935d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    if (send_ssrcs_.find(ssrc) != send_ssrcs_.end()) {
936d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström      LOG(LS_ERROR) << "Send stream with SSRC '" << ssrc << "' already exists.";
937d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström      return false;
938d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    }
939d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  }
940d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  return true;
941d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström}
942d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
943d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boströmbool WebRtcVideoChannel2::ValidateReceiveSsrcAvailability(
944d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    const StreamParams& sp) const {
945d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  for (uint32_t ssrc: sp.ssrcs) {
946d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    if (receive_ssrcs_.find(ssrc) != receive_ssrcs_.end()) {
947d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström      LOG(LS_ERROR) << "Receive stream with SSRC '" << ssrc
948d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström                    << "' already exists.";
949d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström      return false;
950d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    }
951d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  }
952d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  return true;
953d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström}
954d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
955b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) {
956b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "AddSendStream: " << sp.ToString();
957d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  if (!ValidateStreamParams(sp))
958b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
959b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
960575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
961d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
962d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  if (!ValidateSendSsrcAvailability(sp))
963b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
964d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
9650c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (uint32_t used_ssrc : sp.ssrcs)
966d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    send_ssrcs_.insert(used_ssrc);
967b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
968e5269747595864eedd604f153df5d7bcbe1b475asolenberg  webrtc::VideoSendStream::Config config(this);
969e5269747595864eedd604f153df5d7bcbe1b475asolenberg  config.overuse_callback = this;
970e5269747595864eedd604f153df5d7bcbe1b475asolenberg
9711387149ad1669365ac05278bf779a407bec08a4edeadbeef  WebRtcVideoSendStream* stream = new WebRtcVideoSendStream(
9721387149ad1669365ac05278bf779a407bec08a4edeadbeef      call_, sp, config, external_encoder_factory_, options_,
9731387149ad1669365ac05278bf779a407bec08a4edeadbeef      bitrate_config_.max_bitrate_bps, send_codec_, send_rtp_extensions_,
9741387149ad1669365ac05278bf779a407bec08a4edeadbeef      send_params_);
9755301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
9760c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t ssrc = sp.first_ssrc();
97791d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(ssrc != 0);
978b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  send_streams_[ssrc] = stream;
979b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
980b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (rtcp_receiver_report_ssrc_ == kDefaultRtcpReceiverReportSsrc) {
981b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    rtcp_receiver_report_ssrc_ = ssrc;
982874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    LOG(LS_INFO) << "SetLocalSsrc on all the receive streams because we added "
983874ca3af5b163e1b3fd8802171e44ee252557842deadbeef                    "a send stream.";
9843548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström    for (auto& kv : receive_streams_)
9853548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström      kv.second->SetLocalSsrc(ssrc);
986b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
987b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (default_send_ssrc_ == 0) {
988b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    default_send_ssrc_ = ssrc;
989b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
990b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (sending_) {
991b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    stream->Start();
992b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
993b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
994b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
995b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
996b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
9970c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool WebRtcVideoChannel2::RemoveSendStream(uint32_t ssrc) {
998b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "RemoveSendStream: " << ssrc;
999b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1000b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1001b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (default_send_ssrc_ == 0) {
1002b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_ERROR) << "No default send stream active.";
1003b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return false;
1004b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1005b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1006b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_VERBOSE) << "Removing default stream: " << default_send_ssrc_;
1007b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    ssrc = default_send_ssrc_;
1008b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1009b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1010575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  WebRtcVideoSendStream* removed_stream;
1011575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  {
1012575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    rtc::CritScope stream_lock(&stream_crit_);
10130c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    std::map<uint32_t, WebRtcVideoSendStream*>::iterator it =
1014575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org        send_streams_.find(ssrc);
1015575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    if (it == send_streams_.end()) {
1016575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org      return false;
1017575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    }
1018575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org
10190c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    for (uint32_t old_ssrc : it->second->GetSsrcs())
1020d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström      send_ssrcs_.erase(old_ssrc);
1021d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
1022575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    removed_stream = it->second;
1023575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org    send_streams_.erase(it);
1024dfa2815b4f606a58ede5c0214e08a1d5d26d3639Peter Boström
1025dfa2815b4f606a58ede5c0214e08a1d5d26d3639Peter Boström    // Switch receiver report SSRCs, the one in use is no longer valid.
1026dfa2815b4f606a58ede5c0214e08a1d5d26d3639Peter Boström    if (rtcp_receiver_report_ssrc_ == ssrc) {
1027dfa2815b4f606a58ede5c0214e08a1d5d26d3639Peter Boström      rtcp_receiver_report_ssrc_ = send_streams_.empty()
1028dfa2815b4f606a58ede5c0214e08a1d5d26d3639Peter Boström                                       ? kDefaultRtcpReceiverReportSsrc
1029dfa2815b4f606a58ede5c0214e08a1d5d26d3639Peter Boström                                       : send_streams_.begin()->first;
1030dfa2815b4f606a58ede5c0214e08a1d5d26d3639Peter Boström      LOG(LS_INFO) << "SetLocalSsrc on all the receive streams because the "
1031dfa2815b4f606a58ede5c0214e08a1d5d26d3639Peter Boström                      "previous local SSRC was removed.";
1032dfa2815b4f606a58ede5c0214e08a1d5d26d3639Peter Boström
1033dfa2815b4f606a58ede5c0214e08a1d5d26d3639Peter Boström      for (auto& kv : receive_streams_) {
1034dfa2815b4f606a58ede5c0214e08a1d5d26d3639Peter Boström        kv.second->SetLocalSsrc(rtcp_receiver_report_ssrc_);
1035dfa2815b4f606a58ede5c0214e08a1d5d26d3639Peter Boström      }
1036dfa2815b4f606a58ede5c0214e08a1d5d26d3639Peter Boström    }
1037b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1038b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1039575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  delete removed_stream;
1040b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1041b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == default_send_ssrc_) {
1042b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    default_send_ssrc_ = 0;
1043b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1044b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1045b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1046b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1047b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1048d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boströmvoid WebRtcVideoChannel2::DeleteReceiveStream(
1049d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    WebRtcVideoChannel2::WebRtcVideoReceiveStream* stream) {
10500c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (uint32_t old_ssrc : stream->GetSsrcs())
1051d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    receive_ssrcs_.erase(old_ssrc);
1052d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  delete stream;
1053d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström}
1054d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
1055b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp) {
1056a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org  return AddRecvStream(sp, false);
1057a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org}
1058a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org
1059a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.orgbool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp,
1060a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org                                        bool default_stream) {
106191d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(thread_checker_.CalledOnValidThread());
10624b60c73e74d62beff484b7f54d8f3267cb66274fFredrik Solenberg
1063d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  LOG(LS_INFO) << "AddRecvStream" << (default_stream ? " (default stream)" : "")
1064d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström               << ": " << sp.ToString();
1065d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström  if (!ValidateStreamParams(sp))
1066d4362cd3368d5fe542911c375b3a5c9f24b2f29dPeter Boström    return false;
1067b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
10680c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t ssrc = sp.first_ssrc();
106991d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(ssrc != 0);  // TODO(pbos): Is this ever valid?
1070b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1071575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1072d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  // Remove running stream if this was a default stream.
1073d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  auto prev_stream = receive_streams_.find(ssrc);
1074d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  if (prev_stream != receive_streams_.end()) {
1075d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    if (default_stream || !prev_stream->second->IsDefaultStream()) {
1076d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström      LOG(LS_ERROR) << "Receive stream for SSRC '" << ssrc
1077d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström                    << "' already exists.";
1078d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström      return false;
1079a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org    }
1080d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    DeleteReceiveStream(prev_stream->second);
1081d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    receive_streams_.erase(prev_stream);
1082b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1083b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1084d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  if (!ValidateReceiveSsrcAvailability(sp))
1085d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    return false;
1086d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
10870c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (uint32_t used_ssrc : sp.ssrcs)
1088d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström    receive_ssrcs_.insert(used_ssrc);
1089d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
10904fbae2b79134572135d9d5fe35a7d1ccdeea3a4dsolenberg  webrtc::VideoReceiveStream::Config config(this);
1091d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  ConfigureReceiverRtp(&config, sp);
10923bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org
10938fc7fa798f7a36955f1b933980401afad2aff592pbos  // Set up A/V sync group based on sync label.
10948fc7fa798f7a36955f1b933980401afad2aff592pbos  config.sync_group = sp.sync_label;
10953bf3d238c8c4578e444e5a601684db68c79a29capbos@webrtc.org
1096102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg  config.rtp.remb = send_codec_ ? HasRemb(send_codec_->codec) : false;
109743edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan  config.rtp.transport_cc =
109843edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan      send_codec_ ? HasTransportCc(send_codec_->codec) : false;
1099126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström
1100d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  receive_streams_[ssrc] = new WebRtcVideoReceiveStream(
1101709ed67c38d0a942f3bf3e68e337cc27a27bc353Fredrik Solenberg      call_, sp, config, external_decoder_factory_, default_stream,
1102444682acf9804c5fcbddaded9e900ba3cc6921fcqiangchen      recv_codecs_, options_.disable_prerenderer_smoothing.value_or(false));
1103d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1104d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  return true;
1105d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1106d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1107d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::ConfigureReceiverRtp(
1108d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    webrtc::VideoReceiveStream::Config* config,
1109d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const StreamParams& sp) const {
11100c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t ssrc = sp.first_ssrc();
1111d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
1112d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config->rtp.remote_ssrc = ssrc;
1113d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config->rtp.local_ssrc = rtcp_receiver_report_ssrc_;
1114b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1115d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config->rtp.extensions = recv_rtp_extensions_;
11161387149ad1669365ac05278bf779a407bec08a4edeadbeef  config->rtp.rtcp_mode = recv_params_.rtcp.reduced_size
11171387149ad1669365ac05278bf779a407bec08a4edeadbeef                              ? webrtc::RtcpMode::kReducedSize
11181387149ad1669365ac05278bf779a407bec08a4edeadbeef                              : webrtc::RtcpMode::kCompound;
1119257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org
1120b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): This protection is against setting the same local ssrc as
1121b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // remote which is not permitted by the lower-level API. RTCP requires a
1122b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // corresponding sender SSRC. Figure out what to do when we don't have
1123b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // (receive-only) or know a good local SSRC.
1124d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (config->rtp.remote_ssrc == config->rtp.local_ssrc) {
1125d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    if (config->rtp.local_ssrc != kDefaultRtcpReceiverReportSsrc) {
1126d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc;
1127b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    } else {
1128d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc + 1;
1129b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1130b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1131b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1132d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  for (size_t i = 0; i < recv_codecs_.size(); ++i) {
113382775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    MergeFecConfig(recv_codecs_[i].fec, &config->rtp.fec);
1134b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1135b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
113682775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org  for (size_t i = 0; i < recv_codecs_.size(); ++i) {
11370c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström    uint32_t rtx_ssrc;
113882775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    if (recv_codecs_[i].rtx_payload_type != -1 &&
113982775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org        sp.GetFidSsrc(ssrc, &rtx_ssrc)) {
114082775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org      webrtc::VideoReceiveStream::Config::Rtp::Rtx& rtx =
114182775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org          config->rtp.rtx[recv_codecs_[i].codec.id];
114282775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org      rtx.ssrc = rtx_ssrc;
114382775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org      rtx.payload_type = recv_codecs_[i].rtx_payload_type;
114482775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org    }
114582775b13965b4d41299b097c09c30c4ab160cdacandresp@webrtc.org  }
1146b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1147b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
11480c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool WebRtcVideoChannel2::RemoveRecvStream(uint32_t ssrc) {
1149b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "RemoveRecvStream: " << ssrc;
1150b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1151afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    LOG(LS_ERROR) << "RemoveRecvStream with 0 ssrc is not supported.";
1152afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    return false;
1153b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1154b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1155575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
11560c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  std::map<uint32_t, WebRtcVideoReceiveStream*>::iterator stream =
1157b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      receive_streams_.find(ssrc);
1158b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (stream == receive_streams_.end()) {
1159b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Stream not found for ssrc: " << ssrc;
1160b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1161b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1162d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  DeleteReceiveStream(stream->second);
1163b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  receive_streams_.erase(stream);
1164b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1165b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1166b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1167b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
11680c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool WebRtcVideoChannel2::SetRenderer(uint32_t ssrc, VideoRenderer* renderer) {
1169b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetRenderer: ssrc:" << ssrc << " "
1170b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org               << (renderer ? "(ptr)" : "NULL");
1171b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1172afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    default_unsignalled_ssrc_handler_.SetDefaultRenderer(this, renderer);
1173d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    return true;
1174b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1175b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1176575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
11770c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  std::map<uint32_t, WebRtcVideoReceiveStream*>::iterator it =
1178d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      receive_streams_.find(ssrc);
1179d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (it == receive_streams_.end()) {
1180d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    return false;
1181b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1182b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1183b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  it->second->SetRenderer(renderer);
1184b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1185b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1186b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
11870c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool WebRtcVideoChannel2::GetRenderer(uint32_t ssrc, VideoRenderer** renderer) {
1188b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (ssrc == 0) {
1189afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    *renderer = default_unsignalled_ssrc_handler_.GetDefaultRenderer();
1190afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    return *renderer != NULL;
1191b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1192b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1193575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
11940c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  std::map<uint32_t, WebRtcVideoReceiveStream*>::iterator it =
1195d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      receive_streams_.find(ssrc);
1196d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (it == receive_streams_.end()) {
1197b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1198b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1199b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  *renderer = it->second->GetRenderer();
1200b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1201b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1202b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1203058b1f17ac43b1fe69a8c18aaa7999ba88733dfdpbos@webrtc.orgbool WebRtcVideoChannel2::GetStats(VideoMediaInfo* info) {
1204e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info->Clear();
1205e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  FillSenderStats(info);
1206e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  FillReceiverStats(info);
12072b19f0631233488e891d9db0d170b637dc8fc464pbos@webrtc.org  webrtc::Call::Stats stats = call_->GetStats();
12082b19f0631233488e891d9db0d170b637dc8fc464pbos@webrtc.org  FillBandwidthEstimationStats(stats, info);
12092b19f0631233488e891d9db0d170b637dc8fc464pbos@webrtc.org  if (stats.rtt_ms != -1) {
12102b19f0631233488e891d9db0d170b637dc8fc464pbos@webrtc.org    for (size_t i = 0; i < info->senders.size(); ++i) {
12112b19f0631233488e891d9db0d170b637dc8fc464pbos@webrtc.org      info->senders[i].rtt_ms = stats.rtt_ms;
12122b19f0631233488e891d9db0d170b637dc8fc464pbos@webrtc.org    }
12132b19f0631233488e891d9db0d170b637dc8fc464pbos@webrtc.org  }
1214b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1215b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1216b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1217e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgvoid WebRtcVideoChannel2::FillSenderStats(VideoMediaInfo* video_media_info) {
1218575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
12190c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (std::map<uint32_t, WebRtcVideoSendStream*>::iterator it =
1220e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org           send_streams_.begin();
12210c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström       it != send_streams_.end(); ++it) {
1222e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    video_media_info->senders.push_back(it->second->GetVideoSenderInfo());
1223e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
1224e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
1225e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1226e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgvoid WebRtcVideoChannel2::FillReceiverStats(VideoMediaInfo* video_media_info) {
1227575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
12280c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (std::map<uint32_t, WebRtcVideoReceiveStream*>::iterator it =
1229e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org           receive_streams_.begin();
12300c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström       it != receive_streams_.end(); ++it) {
1231e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    video_media_info->receivers.push_back(it->second->GetVideoReceiverInfo());
1232e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
1233e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
1234e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
1235e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgvoid WebRtcVideoChannel2::FillBandwidthEstimationStats(
12362b19f0631233488e891d9db0d170b637dc8fc464pbos@webrtc.org    const webrtc::Call::Stats& stats,
1237e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    VideoMediaInfo* video_media_info) {
12380bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  BandwidthEstimationInfo bwe_info;
12390bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  bwe_info.available_send_bandwidth = stats.send_bandwidth_bps;
12400bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  bwe_info.available_recv_bandwidth = stats.recv_bandwidth_bps;
12410bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  bwe_info.bucket_delay = stats.pacer_delay_ms;
12420bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org
12430bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  // Get send stream bitrate stats.
12440bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
12450c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (std::map<uint32_t, WebRtcVideoSendStream*>::iterator stream =
12460bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org           send_streams_.begin();
12470c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström       stream != send_streams_.end(); ++stream) {
12480bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org    stream->second->FillBandwidthEstimationInfo(&bwe_info);
12490bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  }
12500bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  video_media_info->bw_estimations.push_back(bwe_info);
1251e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
1252e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
12530c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool WebRtcVideoChannel2::SetCapturer(uint32_t ssrc, VideoCapturer* capturer) {
1254b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_INFO) << "SetCapturer: " << ssrc << " -> "
1255b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org               << (capturer != NULL ? "(capturer)" : "NULL");
125691d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(ssrc != 0);
1257e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  {
1258e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    rtc::CritScope stream_lock(&stream_crit_);
1259e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    if (send_streams_.find(ssrc) == send_streams_.end()) {
1260e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström      LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc;
1261e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström      return false;
1262e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    }
1263e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    if (!send_streams_[ssrc]->SetCapturer(capturer)) {
1264e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström      return false;
1265e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    }
126664c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  }
126764c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh
126864c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  if (capturer) {
126964c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    capturer->SetApplyRotation(
127064c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh        !FindHeaderExtension(send_rtp_extensions_,
127164c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh                             kRtpVideoRotationHeaderExtension));
127264c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  }
1273e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  {
1274e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    rtc::CritScope lock(&capturer_crit_);
1275e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    capturers_[ssrc] = capturer;
1276e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  }
127764c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  return true;
1278b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1279b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1280b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SendIntraFrame() {
1281b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1282b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SendIntraFrame().";
1283b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1284b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1285b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1286b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::RequestIntraFrame() {
1287b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1288b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "SendIntraFrame().";
1289b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1290b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1291b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1292b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::OnPacketReceived(
1293d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    rtc::Buffer* packet,
1294d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    const rtc::PacketTime& packet_time) {
129568786d20400f1f3744ad83549325665c18ea9e5bstefan  const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
129668786d20400f1f3744ad83549325665c18ea9e5bstefan                                              packet_time.not_before);
12974e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org  const webrtc::PacketReceiver::DeliveryStatus delivery_result =
129868786d20400f1f3744ad83549325665c18ea9e5bstefan      call_->Receiver()->DeliverPacket(
129968786d20400f1f3744ad83549325665c18ea9e5bstefan          webrtc::MediaType::VIDEO,
130068786d20400f1f3744ad83549325665c18ea9e5bstefan          reinterpret_cast<const uint8_t*>(packet->data()), packet->size(),
130168786d20400f1f3744ad83549325665c18ea9e5bstefan          webrtc_packet_time);
13024e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org  switch (delivery_result) {
13034e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_OK:
13044e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      return;
13054e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_PACKET_ERROR:
13064e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      return;
13074e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org    case webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC:
13084e545cc24478df6dec0f73cb8f5b9e5720fbce59pbos@webrtc.org      break;
1309b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1310b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
13110c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  uint32_t ssrc = 0;
1312eebcab5ce99d3e8641dd92a569916b0d24e29fcakwiberg@webrtc.org  if (!GetRtpSsrc(packet->data(), packet->size(), &ssrc)) {
1313b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1314b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1315b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1316d10a68e7974a29b26d6c926e6f137255f3c173benoahric  int payload_type = 0;
1317d10a68e7974a29b26d6c926e6f137255f3c173benoahric  if (!GetRtpPayloadType(packet->data(), packet->size(), &payload_type)) {
1318d10a68e7974a29b26d6c926e6f137255f3c173benoahric    return;
1319d10a68e7974a29b26d6c926e6f137255f3c173benoahric  }
1320d10a68e7974a29b26d6c926e6f137255f3c173benoahric
1321d10a68e7974a29b26d6c926e6f137255f3c173benoahric  // See if this payload_type is registered as one that usually gets its own
1322d10a68e7974a29b26d6c926e6f137255f3c173benoahric  // SSRC (RTX) or at least is safe to drop either way (ULPFEC). If it is, and
1323d10a68e7974a29b26d6c926e6f137255f3c173benoahric  // it wasn't handled above by DeliverPacket, that means we don't know what
1324d10a68e7974a29b26d6c926e6f137255f3c173benoahric  // stream it associates with, and we shouldn't ever create an implicit channel
1325d10a68e7974a29b26d6c926e6f137255f3c173benoahric  // for these.
1326d10a68e7974a29b26d6c926e6f137255f3c173benoahric  for (auto& codec : recv_codecs_) {
1327d10a68e7974a29b26d6c926e6f137255f3c173benoahric    if (payload_type == codec.rtx_payload_type ||
1328d10a68e7974a29b26d6c926e6f137255f3c173benoahric        payload_type == codec.fec.red_rtx_payload_type ||
1329d10a68e7974a29b26d6c926e6f137255f3c173benoahric        payload_type == codec.fec.ulpfec_payload_type) {
1330d10a68e7974a29b26d6c926e6f137255f3c173benoahric      return;
1331d10a68e7974a29b26d6c926e6f137255f3c173benoahric    }
1332d10a68e7974a29b26d6c926e6f137255f3c173benoahric  }
1333d10a68e7974a29b26d6c926e6f137255f3c173benoahric
1334afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  switch (unsignalled_ssrc_handler_->OnUnsignalledSsrc(this, ssrc)) {
1335afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    case UnsignalledSsrcHandler::kDropPacket:
1336afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org      return;
1337afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    case UnsignalledSsrcHandler::kDeliverPacket:
1338afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org      break;
1339afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org  }
1340b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
134168786d20400f1f3744ad83549325665c18ea9e5bstefan  if (call_->Receiver()->DeliverPacket(
134268786d20400f1f3744ad83549325665c18ea9e5bstefan          webrtc::MediaType::VIDEO,
134368786d20400f1f3744ad83549325665c18ea9e5bstefan          reinterpret_cast<const uint8_t*>(packet->data()), packet->size(),
134468786d20400f1f3744ad83549325665c18ea9e5bstefan          webrtc_packet_time) != webrtc::PacketReceiver::DELIVERY_OK) {
1345afb554f404d68e6f3ca5395216f776169370713dpbos@webrtc.org    LOG(LS_WARNING) << "Failed to deliver RTP packet on re-delivery.";
1346b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1347b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1348b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1349b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1350b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::OnRtcpReceived(
1351d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    rtc::Buffer* packet,
1352d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    const rtc::PacketTime& packet_time) {
135368786d20400f1f3744ad83549325665c18ea9e5bstefan  const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp,
135468786d20400f1f3744ad83549325665c18ea9e5bstefan                                              packet_time.not_before);
13552aff615bd7c7c24a6e7a35163112f169ff4f9246Peter Boström  // TODO(pbos): Check webrtc::PacketReceiver::DELIVERY_OK once we deliver
13562aff615bd7c7c24a6e7a35163112f169ff4f9246Peter Boström  // for both audio and video on the same path. Since BundleFilter doesn't
13572aff615bd7c7c24a6e7a35163112f169ff4f9246Peter Boström  // filter RTCP anymore incoming RTCP packets could've been going to audio (so
13582aff615bd7c7c24a6e7a35163112f169ff4f9246Peter Boström  // logging failures spam the log).
13592aff615bd7c7c24a6e7a35163112f169ff4f9246Peter Boström  call_->Receiver()->DeliverPacket(
13602aff615bd7c7c24a6e7a35163112f169ff4f9246Peter Boström      webrtc::MediaType::VIDEO,
13612aff615bd7c7c24a6e7a35163112f169ff4f9246Peter Boström      reinterpret_cast<const uint8_t*>(packet->data()), packet->size(),
13622aff615bd7c7c24a6e7a35163112f169ff4f9246Peter Boström      webrtc_packet_time);
1363b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1364b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1365b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::OnReadyToSend(bool ready) {
136626c0c41a06d77af54df547169d952a21319dea8cpbos@webrtc.org  LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready.");
1367cd6702282a49448adda470934f4bd9e6181cab22Jelena Marusic  call_->SignalNetworkState(ready ? webrtc::kNetworkUp : webrtc::kNetworkDown);
1368b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1369b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
13700c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmbool WebRtcVideoChannel2::MuteStream(uint32_t ssrc, bool mute) {
1371b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  LOG(LS_VERBOSE) << "MuteStream: " << ssrc << " -> "
1372b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                  << (mute ? "mute" : "unmute");
137391d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(ssrc != 0);
1374575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
1375b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (send_streams_.find(ssrc) == send_streams_.end()) {
1376b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc;
1377b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1378b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1379ef8bb8d9b0bca0b1fd1ddb0a17df665e9dfaf9adpbos@webrtc.org
1380ef8bb8d9b0bca0b1fd1ddb0a17df665e9dfaf9adpbos@webrtc.org  send_streams_[ssrc]->MuteStream(mute);
1381ef8bb8d9b0bca0b1fd1ddb0a17df665e9dfaf9adpbos@webrtc.org  return true;
1382b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1383b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1384b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions(
1385b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
138650fe359eb614e1bbe41124b9c19263019da0395dpbos@webrtc.org  TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetRecvRtpHeaderExtensions");
13877e4e01a4413fa98644b94ab9d8a9dccc664f39f2solenberg  if (!ValidateRtpExtensions(extensions)) {
13883c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    return false;
13897e4e01a4413fa98644b94ab9d8a9dccc664f39f2solenberg  }
13907e4e01a4413fa98644b94ab9d8a9dccc664f39f2solenberg  std::vector<webrtc::RtpExtension> filtered_extensions = FilterRtpExtensions(
13917e4e01a4413fa98644b94ab9d8a9dccc664f39f2solenberg      extensions, webrtc::RtpExtension::IsSupportedForVideo, false);
13927e4e01a4413fa98644b94ab9d8a9dccc664f39f2solenberg  if (recv_rtp_extensions_ == filtered_extensions) {
1393874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    LOG(LS_INFO) << "Ignoring call to SetRecvRtpHeaderExtensions because "
1394874ca3af5b163e1b3fd8802171e44ee252557842deadbeef                    "header extensions haven't changed.";
1395c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org    return true;
1396874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  }
13977e4e01a4413fa98644b94ab9d8a9dccc664f39f2solenberg  recv_rtp_extensions_.swap(filtered_extensions);
1398c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org
1399575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
14000c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (std::map<uint32_t, WebRtcVideoReceiveStream*>::iterator it =
1401d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org           receive_streams_.begin();
14020c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström       it != receive_streams_.end(); ++it) {
1403d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    it->second->SetRtpExtensions(recv_rtp_extensions_);
1404d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1405b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1406b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1407b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1408b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetSendRtpHeaderExtensions(
1409b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const std::vector<RtpHeaderExtension>& extensions) {
141050fe359eb614e1bbe41124b9c19263019da0395dpbos@webrtc.org  TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetSendRtpHeaderExtensions");
14117e4e01a4413fa98644b94ab9d8a9dccc664f39f2solenberg  if (!ValidateRtpExtensions(extensions)) {
14123c10758b3bb9519d5e582c00f454ac30196ac4e7pbos@webrtc.org    return false;
14137e4e01a4413fa98644b94ab9d8a9dccc664f39f2solenberg  }
14147e4e01a4413fa98644b94ab9d8a9dccc664f39f2solenberg  std::vector<webrtc::RtpExtension> filtered_extensions = FilterRtpExtensions(
14157e4e01a4413fa98644b94ab9d8a9dccc664f39f2solenberg      extensions, webrtc::RtpExtension::IsSupportedForVideo, true);
14167e4e01a4413fa98644b94ab9d8a9dccc664f39f2solenberg  if (send_rtp_extensions_ == filtered_extensions) {
14177e4e01a4413fa98644b94ab9d8a9dccc664f39f2solenberg    LOG(LS_INFO) << "Ignoring call to SetRecvRtpHeaderExtensions because "
1418874ca3af5b163e1b3fd8802171e44ee252557842deadbeef                    "header extensions haven't changed.";
1419c37e72e890cb1c769af9006dbd2e582c1a2e2a50pbos@webrtc.org    return true;
1420874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  }
14217e4e01a4413fa98644b94ab9d8a9dccc664f39f2solenberg  send_rtp_extensions_.swap(filtered_extensions);
1422a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
142364c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  const webrtc::RtpExtension* cvo_extension = FindHeaderExtension(
142464c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh      send_rtp_extensions_, kRtpVideoRotationHeaderExtension);
142564c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh
1426575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
14270c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (std::map<uint32_t, WebRtcVideoSendStream*>::iterator it =
1428d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org           send_streams_.begin();
14290c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström       it != send_streams_.end(); ++it) {
1430d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    it->second->SetRtpExtensions(send_rtp_extensions_);
143164c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    it->second->SetApplyRotation(!cvo_extension);
1432d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
1433b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1434b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1435b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1436dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström// Counter-intuitively this method doesn't only set global bitrate caps but also
1437dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström// per-stream codec max bitrates. This is to permit SetMaxSendBitrate (b=AS) to
1438dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström// raise bitrates above the 2000k default bitrate cap.
1439008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.orgbool WebRtcVideoChannel2::SetMaxSendBandwidth(int max_bitrate_bps) {
1440dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  // TODO(pbos): Figure out whether b=AS means max bitrate for this
1441dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  // WebRtcVideoChannel2 (in which case we're good), or per sender (SSRC), in
1442dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  // which case this should not set a Call::BitrateConfig but rather reconfigure
1443dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  // all senders.
1444008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  LOG(LS_INFO) << "SetMaxSendBandwidth: " << max_bitrate_bps << "bps.";
1445dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  if (max_bitrate_bps == bitrate_config_.max_bitrate_bps)
1446dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    return true;
1447dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström
1448b071a19019a0a2173cc139c960d6ef6946a1c581Fredrik Solenberg  if (max_bitrate_bps < 0) {
1449b071a19019a0a2173cc139c960d6ef6946a1c581Fredrik Solenberg    // Option not set.
1450b071a19019a0a2173cc139c960d6ef6946a1c581Fredrik Solenberg    return true;
1451b071a19019a0a2173cc139c960d6ef6946a1c581Fredrik Solenberg  }
1452b071a19019a0a2173cc139c960d6ef6946a1c581Fredrik Solenberg  if (max_bitrate_bps == 0) {
1453008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    // Unsetting max bitrate.
1454008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    max_bitrate_bps = -1;
1455008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  }
1456008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  bitrate_config_.start_bitrate_bps = -1;
1457008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  bitrate_config_.max_bitrate_bps = max_bitrate_bps;
1458008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  if (max_bitrate_bps > 0 &&
1459008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org      bitrate_config_.min_bitrate_bps > max_bitrate_bps) {
1460008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org    bitrate_config_.min_bitrate_bps = max_bitrate_bps;
1461008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  }
1462008731868a09e2fe01da53733a612dc24761f791pbos@webrtc.org  call_->SetBitrateConfig(bitrate_config_);
1463dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  rtc::CritScope stream_lock(&stream_crit_);
1464dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  for (auto& kv : send_streams_)
1465dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    kv.second->SetMaxBitrateBps(max_bitrate_bps);
1466b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1467b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1468b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1469b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SetOptions(const VideoOptions& options) {
147050fe359eb614e1bbe41124b9c19263019da0395dpbos@webrtc.org  TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetOptions");
1471a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  LOG(LS_INFO) << "SetOptions: " << options.ToString();
1472a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  VideoOptions old_options = options_;
1473b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  options_.SetAll(options);
1474a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  if (options_ == old_options) {
1475a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    // No new options to set.
1476a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    return true;
1477a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  }
1478e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  {
1479e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    rtc::CritScope lock(&capturer_crit_);
1480102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg    if (options_.cpu_overuse_detection)
1481102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg      signal_cpu_adaptation_ = *options_.cpu_overuse_detection;
1482e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  }
1483102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg  rtc::DiffServCodePoint dscp =
1484102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg      options_.dscp.value_or(false) ? rtc::DSCP_AF41 : rtc::DSCP_DEFAULT;
1485d819803d4570564a9800a7dd54f4593e6e21a6e7pbos@webrtc.org  MediaChannel::SetDscp(dscp);
1486575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
14870c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (std::map<uint32_t, WebRtcVideoSendStream*>::iterator it =
14885301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org           send_streams_.begin();
14890c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström       it != send_streams_.end(); ++it) {
14905301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    it->second->SetOptions(options_);
14915301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
1492b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1493b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1494b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1495b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::SetInterface(NetworkInterface* iface) {
1496b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  MediaChannel::SetInterface(iface);
1497b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Set the RTP recv/send buffer to a bigger size
1498b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  MediaChannel::SetOption(NetworkInterface::ST_RTP,
1499d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org                          rtc::Socket::OPT_RCVBUF,
1500b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                          kVideoRtpBufferSize);
1501b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1502ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org  // Speculative change to increase the outbound socket buffer size.
1503ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org  // In b/15152257, we are seeing a significant number of packets discarded
1504ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org  // due to lack of socket buffer space, although it's not yet clear what the
1505ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org  // ideal value should be.
1506ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org  MediaChannel::SetOption(NetworkInterface::ST_RTP,
1507ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org                          rtc::Socket::OPT_SNDBUF,
1508ae694effd85d501f15600275dec96522a00c4febbuildbot@webrtc.org                          kVideoRtpBufferSize);
1509b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1510b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1511b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::UpdateAspectRatio(int ratio_w, int ratio_h) {
1512b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // TODO(pbos): Implement.
1513b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1514b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1515d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.orgvoid WebRtcVideoChannel2::OnMessage(rtc::Message* msg) {
1516b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Ignored.
1517b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1518b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
151942684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.orgvoid WebRtcVideoChannel2::OnLoadUpdate(Load load) {
1520e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  // OnLoadUpdate can not take any locks that are held while creating streams
1521e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  // etc. Doing so establishes lock-order inversions between the webrtc process
1522e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  // thread on stream creation and locks such as stream_crit_ while calling out.
1523e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  rtc::CritScope stream_lock(&capturer_crit_);
1524e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  if (!signal_cpu_adaptation_)
1525e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    return;
1526efbde3775b5eed8015d7e2e86ddcea3e6033d321Erik Språng  // Do not adapt resolution for screen content as this will likely result in
1527efbde3775b5eed8015d7e2e86ddcea3e6033d321Erik Språng  // blurry and unreadable text.
1528e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström  for (auto& kv : capturers_) {
1529efbde3775b5eed8015d7e2e86ddcea3e6033d321Erik Språng    if (kv.second != nullptr
1530efbde3775b5eed8015d7e2e86ddcea3e6033d321Erik Språng        && !kv.second->IsScreencast()
1531efbde3775b5eed8015d7e2e86ddcea3e6033d321Erik Språng        && kv.second->video_adapter() != nullptr) {
1532e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström      kv.second->video_adapter()->OnCpuResolutionRequest(
1533e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström          load == kOveruse ? CoordinatedVideoAdapter::DOWNGRADE
1534e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström                           : CoordinatedVideoAdapter::UPGRADE);
1535e7b221f4760af10e29cb4c501e758cc3518f628bPeter Boström    }
153642684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org  }
153742684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org}
153842684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org
15391d8a506405734d0cef9653704b036ca4f1388960stefanbool WebRtcVideoChannel2::SendRtp(const uint8_t* data,
15401d8a506405734d0cef9653704b036ca4f1388960stefan                                  size_t len,
15411d8a506405734d0cef9653704b036ca4f1388960stefan                                  const webrtc::PacketOptions& options) {
1542d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::Buffer packet(data, len, kMaxRtpPacketLen);
1543c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan  rtc::PacketOptions rtc_options;
1544c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan  rtc_options.packet_id = options.packet_id;
1545c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan  return MediaChannel::SendPacket(&packet, rtc_options);
1546b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1547b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1548b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::SendRtcp(const uint8_t* data, size_t len) {
1549d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::Buffer packet(data, len, kMaxRtpPacketLen);
1550c1aeaf0dc37d96f31c92f893f4e30e7a5f7cc2b7stefan  return MediaChannel::SendRtcp(&packet, rtc::PacketOptions());
1551b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1552b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1553b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::StartAllSendStreams() {
1554575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
15550c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (std::map<uint32_t, WebRtcVideoSendStream*>::iterator it =
1556b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           send_streams_.begin();
15570c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström       it != send_streams_.end(); ++it) {
1558b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    it->second->Start();
1559b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1560b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1561b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1562b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::StopAllSendStreams() {
1563575d126a3d4a4bf6d43ea07189ac201f6bfe0798pbos@webrtc.org  rtc::CritScope stream_lock(&stream_crit_);
15640c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström  for (std::map<uint32_t, WebRtcVideoSendStream*>::iterator it =
1565b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org           send_streams_.begin();
15660c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boström       it != send_streams_.end(); ++it) {
1567b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    it->second->Stop();
1568b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1569b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1570b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
15716ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters::
15726ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org    VideoSendStreamParameters(
15736ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        const webrtc::VideoSendStream::Config& config,
15746ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        const VideoOptions& options,
1575dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström        int max_bitrate_bps,
1576be57983f4bd875c39a229bab5112b32dad004057Karl Wiberg        const rtc::Optional<VideoCodecSettings>& codec_settings)
1577dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    : config(config),
1578dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström      options(options),
1579dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström      max_bitrate_bps(max_bitrate_bps),
1580102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg      codec_settings(codec_settings) {}
15816ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
15824d71edef45afa38b3f68b6af0519ac0f21d327dfPeter BoströmWebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder::AllocatedEncoder(
15834d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström    webrtc::VideoEncoder* encoder,
15844d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström    webrtc::VideoCodecType type,
15854d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström    bool external)
15864d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström    : encoder(encoder),
15874d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström      external_encoder(nullptr),
15884d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström      type(type),
15894d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström      external(external) {
15904d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström  if (external) {
15914d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström    external_encoder = encoder;
15924d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström    this->encoder =
15934d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström        new webrtc::VideoEncoderSoftwareFallbackWrapper(type, encoder);
15944d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström  }
15954d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström}
15964d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström
1597b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream(
1598b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    webrtc::Call* call,
15994fbae2b79134572135d9d5fe35a7d1ccdeea3a4dsolenberg    const StreamParams& sp,
16004fbae2b79134572135d9d5fe35a7d1ccdeea3a4dsolenberg    const webrtc::VideoSendStream::Config& config,
16017fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    WebRtcVideoEncoderFactory* external_encoder_factory,
16026ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org    const VideoOptions& options,
1603dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    int max_bitrate_bps,
1604be57983f4bd875c39a229bab5112b32dad004057Karl Wiberg    const rtc::Optional<VideoCodecSettings>& codec_settings,
16051387149ad1669365ac05278bf779a407bec08a4edeadbeef    const std::vector<webrtc::RtpExtension>& rtp_extensions,
16061387149ad1669365ac05278bf779a407bec08a4edeadbeef    // TODO(deadbeef): Don't duplicate information between send_params,
16071387149ad1669365ac05278bf779a407bec08a4edeadbeef    // rtp_extensions, options, etc.
16081387149ad1669365ac05278bf779a407bec08a4edeadbeef    const VideoSendParameters& send_params)
16097c027b64ae53a29bc528b4241cc540694c239304Henrik Kjellander    : ssrcs_(sp.ssrcs),
1610259bd2034c3d3ee7f2dc4d481e9bf896a3a4d6efPeter Boström      ssrc_groups_(sp.ssrc_groups),
16117c027b64ae53a29bc528b4241cc540694c239304Henrik Kjellander      call_(call),
16127fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      external_encoder_factory_(external_encoder_factory),
1613b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      stream_(NULL),
16144fbae2b79134572135d9d5fe35a7d1ccdeea3a4dsolenberg      parameters_(config, options, max_bitrate_bps, codec_settings),
16157fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      allocated_encoder_(NULL, webrtc::kVideoCodecUnknown, false),
1616b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      capturer_(NULL),
1617b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      sending_(false),
16189a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org      muted_(false),
1619c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen      old_adapt_changes_(0),
1620c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen      first_frame_timestamp_ms_(0),
1621c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen      last_frame_timestamp_ms_(0) {
16225301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.rtp.max_packet_size = kVideoMtu;
16235301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
16245301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  sp.GetPrimarySsrcs(&parameters_.config.rtp.ssrcs);
16255301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  sp.GetFidSsrcs(parameters_.config.rtp.ssrcs,
16265301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                 &parameters_.config.rtp.rtx.ssrcs);
16275301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.rtp.c_name = sp.cname;
16285301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.rtp.extensions = rtp_extensions;
16291387149ad1669365ac05278bf779a407bec08a4edeadbeef  parameters_.config.rtp.rtcp_mode = send_params.rtcp.reduced_size
16301387149ad1669365ac05278bf779a407bec08a4edeadbeef                                         ? webrtc::RtcpMode::kReducedSize
16311387149ad1669365ac05278bf779a407bec08a4edeadbeef                                         : webrtc::RtcpMode::kCompound;
16325301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
1633102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg  if (codec_settings) {
1634102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg    SetCodec(*codec_settings);
16355301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
1636b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1637b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1638b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() {
1639b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  DisconnectCapturer();
16405301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (stream_ != NULL) {
16415301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    call_->DestroyVideoSendStream(stream_);
16425301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
16437fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  DestroyVideoEncoder(&allocated_encoder_);
1644b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1645b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
16464765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchezstatic void CreateBlackFrame(webrtc::VideoFrame* video_frame,
1647b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                             int width,
1648b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                             int height) {
1649b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org  video_frame->CreateEmptyFrame(width, height, width, (width + 1) / 2,
1650b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org                                (width + 1) / 2);
1651b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org  memset(video_frame->buffer(webrtc::kYPlane), 16,
1652b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org         video_frame->allocated_size(webrtc::kYPlane));
1653b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org  memset(video_frame->buffer(webrtc::kUPlane), 128,
1654b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org         video_frame->allocated_size(webrtc::kUPlane));
1655b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org  memset(video_frame->buffer(webrtc::kVPlane), 128,
1656b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org         video_frame->allocated_size(webrtc::kVPlane));
1657b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1658b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1659b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame(
1660b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VideoCapturer* capturer,
1661b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoFrame* frame) {
166286196c4f481d7f515e54806988f763169e8b9206pbos@webrtc.org  TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::InputFrame");
16634765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez  webrtc::VideoFrame video_frame(frame->GetVideoFrameBuffer(), 0, 0,
16644765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez                                 frame->GetVideoRotation());
1665d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
16665301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (stream_ == NULL) {
1667ad1f9b61a3107ca27ee023990dc576abc38f05acPeter Boström    // Frame input before send codecs are configured, dropping frame.
16685301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    return;
16695301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
167086196c4f481d7f515e54806988f763169e8b9206pbos@webrtc.org
167186196c4f481d7f515e54806988f763169e8b9206pbos@webrtc.org  // Not sending, abort early to prevent expensive reconfigurations while
167286196c4f481d7f515e54806988f763169e8b9206pbos@webrtc.org  // setting up codecs etc.
167386196c4f481d7f515e54806988f763169e8b9206pbos@webrtc.org  if (!sending_)
167486196c4f481d7f515e54806988f763169e8b9206pbos@webrtc.org    return;
167586196c4f481d7f515e54806988f763169e8b9206pbos@webrtc.org
1676b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (format_.width == 0) {  // Dropping frames.
167791d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg    RTC_DCHECK(format_.height == 0);
1678b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_VERBOSE) << "VideoFormat 0x0 set, Dropping frame.";
1679b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1680b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1681d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org  if (muted_) {
1682d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org    // Create a black frame to transmit instead.
1683afdd5dd372d69be7244a3d90d70de9d5ecd60eb9magjed@webrtc.org    CreateBlackFrame(&video_frame,
1684d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org                     static_cast<int>(frame->GetWidth()),
1685d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org                     static_cast<int>(frame->GetHeight()));
1686d60d79a14594cbc8266e4a50391ddbe64ed491f0pbos@webrtc.org  }
1687c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen
1688c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen  int64_t frame_delta_ms = frame->GetTimeStamp() / rtc::kNumNanosecsPerMillisec;
1689c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen  // frame->GetTimeStamp() is essentially a delta, align to webrtc time
1690c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen  if (first_frame_timestamp_ms_ == 0) {
1691c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen    first_frame_timestamp_ms_ = rtc::Time() - frame_delta_ms;
1692c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen  }
1693c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen
1694c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen  last_frame_timestamp_ms_ = first_frame_timestamp_ms_ + frame_delta_ms;
1695c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen  video_frame.set_render_time_ms(last_frame_timestamp_ms_);
1696b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Reconfigure codec if necessary.
1697c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org  SetDimensions(
1698afdd5dd372d69be7244a3d90d70de9d5ecd60eb9magjed@webrtc.org      video_frame.width(), video_frame.height(), capturer->IsScreencast());
1699c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org
1700af612d5e0769571544952cbe55e675748afa9bddperkj@webrtc.org  stream_->Input()->IncomingCapturedFrame(video_frame);
1701b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1702b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1703b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer(
1704b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    VideoCapturer* capturer) {
1705b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org  TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::SetCapturer");
1706b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (!DisconnectCapturer() && capturer == NULL) {
1707b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1708b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1709b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1710b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  {
1711d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org    rtc::CritScope cs(&lock_);
1712b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
17131cb121dea478a4bb4f88e76cf92719e2853543cfpbos    // Reset timestamps to realign new incoming frames to a webrtc timestamp. A
17141cb121dea478a4bb4f88e76cf92719e2853543cfpbos    // new capturer may have a different timestamp delta than the previous one.
17151cb121dea478a4bb4f88e76cf92719e2853543cfpbos    first_frame_timestamp_ms_ = 0;
17161cb121dea478a4bb4f88e76cf92719e2853543cfpbos
17179359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org    if (capturer == NULL) {
17189359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org      if (stream_ != NULL) {
17199359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org        LOG(LS_VERBOSE) << "Disabling capturer, sending black frame.";
17204765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez        webrtc::VideoFrame black_frame;
17219359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org
1722b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org        CreateBlackFrame(&black_frame, last_dimensions_.width,
1723b4987bfc24e1e755a6c54053d09a58d1e72228bbpbos@webrtc.org                         last_dimensions_.height);
1724c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen
1725c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen        // Force this black frame not to be dropped due to timestamp order
1726c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen        // check. As IncomingCapturedFrame will drop the frame if this frame's
1727c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen        // timestamp is less than or equal to last frame's timestamp, it is
1728c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen        // necessary to give this black frame a larger timestamp than the
1729c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen        // previous one.
1730c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen        last_frame_timestamp_ms_ +=
1731c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen            format_.interval / rtc::kNumNanosecsPerMillisec;
1732c27d89fdc6b33846ff06e8ca8bd03119d05c6530qiangchen        black_frame.set_render_time_ms(last_frame_timestamp_ms_);
1733af612d5e0769571544952cbe55e675748afa9bddperkj@webrtc.org        stream_->Input()->IncomingCapturedFrame(black_frame);
17349359cb3e75c7100dab4c687f60dd28dc613280e4pbos@webrtc.org      }
1735b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1736b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      capturer_ = NULL;
1737b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return true;
1738b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
1739b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1740b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    capturer_ = capturer;
1741b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1742b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // Lock cannot be held while connecting the capturer to prevent lock-order
1743b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // violations.
1744b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  capturer->SignalVideoFrame.connect(this, &WebRtcVideoSendStream::InputFrame);
1745b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1746b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1747b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1748b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoFormat(
1749b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoFormat& format) {
1750b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if ((format.width == 0 || format.height == 0) &&
1751b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      format.width != format.height) {
1752b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_ERROR) << "Can't set VideoFormat, width or height is zero (but not "
1753b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                     "both, 0x0 drops frames).";
1754b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return false;
1755b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1756b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1757d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1758b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (format.width == 0 && format.height == 0) {
1759b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    LOG(LS_INFO)
1760b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        << "0x0 resolution selected. Captured frames will be dropped for ssrc: "
17616ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org        << parameters_.config.rtp.ssrcs[0] << ".";
1762b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  } else {
1763b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    // TODO(pbos): Fix me, this only affects the last stream!
1764bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org    parameters_.encoder_config.streams.back().max_framerate =
1765b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        VideoFormat::IntervalToFps(format.interval);
1766c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org    SetDimensions(format.width, format.height, false);
1767b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1768b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1769b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  format_ = format;
1770b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1771b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1772b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1773ef8bb8d9b0bca0b1fd1ddb0a17df665e9dfaf9adpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::MuteStream(bool mute) {
1774d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1775b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  muted_ = mute;
1776b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1777b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1778b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectCapturer() {
1779963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org  cricket::VideoCapturer* capturer;
1780963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org  {
1781963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org    rtc::CritScope cs(&lock_);
17829a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org    if (capturer_ == NULL)
1783963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org      return false;
17849a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org
17859a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org    if (capturer_->video_adapter() != nullptr)
17869a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org      old_adapt_changes_ += capturer_->video_adapter()->adaptation_changes();
17879a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org
1788963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org    capturer = capturer_;
1789963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org    capturer_ = NULL;
1790b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
1791963b979510f6521fd69576f146235c6a5c0f8264pbos@webrtc.org  capturer->SignalVideoFrame.disconnect(this);
1792b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return true;
1793b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1794b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
17950c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmconst std::vector<uint32_t>&
1796d6f4c25eedcfd502920f1b2a24744badd9da80bePeter BoströmWebRtcVideoChannel2::WebRtcVideoSendStream::GetSsrcs() const {
1797d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  return ssrcs_;
1798d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström}
1799d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
180064c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shiehvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetApplyRotation(
180164c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    bool apply_rotation) {
180264c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  rtc::CritScope cs(&lock_);
180364c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  if (capturer_ == NULL)
180464c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh    return;
180564c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh
180664c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh  capturer_->SetApplyRotation(apply_rotation);
180764c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh}
180864c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh
18095301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetOptions(
18105301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const VideoOptions& options) {
1811d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1812102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg  if (parameters_.codec_settings) {
1813874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    LOG(LS_INFO) << "SetCodecAndOptions because of SetOptions; options="
1814874ca3af5b163e1b3fd8802171e44ee252557842deadbeef                 << options.ToString();
1815102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg    SetCodecAndOptions(*parameters_.codec_settings, options);
18165301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  } else {
18175301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    parameters_.options = options;
18185301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
18195301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org}
18207fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
1821b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec(
18225301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const VideoCodecSettings& codec_settings) {
1823d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1824874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  LOG(LS_INFO) << "SetCodecAndOptions because of SetCodec.";
18255301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  SetCodecAndOptions(codec_settings, parameters_.options);
18265301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org}
18277fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
18287fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgwebrtc::VideoCodecType CodecTypeFromName(const std::string& name) {
1829e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin  if (CodecNamesEq(name, kVp8CodecName)) {
18307fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return webrtc::kVideoCodecVP8;
1831e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin  } else if (CodecNamesEq(name, kVp9CodecName)) {
1832188d3b2245b49f21468840386d81b080176b434bandresp@webrtc.org    return webrtc::kVideoCodecVP9;
1833e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin  } else if (CodecNamesEq(name, kH264CodecName)) {
18347fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return webrtc::kVideoCodecH264;
18357fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
18367fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return webrtc::kVideoCodecUnknown;
18377fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
18387fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
18397fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder
18407fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder(
18417fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    const VideoCodec& codec) {
18427fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  webrtc::VideoCodecType type = CodecTypeFromName(codec.name);
18437fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
18447fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  // Do not re-create encoders of the same type.
18457fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (type == allocated_encoder_.type && allocated_encoder_.encoder != NULL) {
18467fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return allocated_encoder_;
18477fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
18487fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
18497fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (external_encoder_factory_ != NULL) {
18507fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    webrtc::VideoEncoder* encoder =
18517fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org        external_encoder_factory_->CreateVideoEncoder(type);
18527fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    if (encoder != NULL) {
18537fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org      return AllocatedEncoder(encoder, type, true);
18547fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    }
18557fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
18567fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
18577fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (type == webrtc::kVideoCodecVP8) {
18587fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    return AllocatedEncoder(
18597fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org        webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kVp8), type, false);
1860188d3b2245b49f21468840386d81b080176b434bandresp@webrtc.org  } else if (type == webrtc::kVideoCodecVP9) {
1861188d3b2245b49f21468840386d81b080176b434bandresp@webrtc.org    return AllocatedEncoder(
1862188d3b2245b49f21468840386d81b080176b434bandresp@webrtc.org        webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kVp9), type, false);
186371f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin  } else if (type == webrtc::kVideoCodecH264) {
186471f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin    return AllocatedEncoder(
186571f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin        webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kH264), type, false);
18667fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
18677fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
18687fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  // This shouldn't happen, we should not be trying to create something we don't
18697fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  // support.
187091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(false);
18717fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  return AllocatedEncoder(NULL, webrtc::kVideoCodecUnknown, false);
18727fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
18737fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
18747fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::DestroyVideoEncoder(
18757fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    AllocatedEncoder* encoder) {
18767fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (encoder->external) {
18774d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström    external_encoder_factory_->DestroyVideoEncoder(encoder->external_encoder);
18787fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
18794d71edef45afa38b3f68b6af0519ac0f21d327dfPeter Boström  delete encoder->encoder;
18807fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org}
18817fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org
18825301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodecAndOptions(
18835301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const VideoCodecSettings& codec_settings,
18845301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org    const VideoOptions& options) {
1885a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  parameters_.encoder_config =
1886a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org      CreateVideoEncoderConfig(last_dimensions_, codec_settings.codec);
188786196c4f481d7f515e54806988f763169e8b9206pbos@webrtc.org  if (parameters_.encoder_config.streams.empty())
1888b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    return;
1889a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
18905301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  format_ = VideoFormat(codec_settings.codec.width,
18915301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org                        codec_settings.codec.height,
1892b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                        VideoFormat::FpsToInterval(30),
1893b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                        FOURCC_I420);
18946ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
18957fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  AllocatedEncoder new_encoder = CreateVideoEncoder(codec_settings.codec);
18967fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  parameters_.config.encoder_settings.encoder = new_encoder.encoder;
18975301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.encoder_settings.payload_name = codec_settings.codec.name;
18985301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.encoder_settings.payload_type = codec_settings.codec.id;
189947d78cc8ad54baabc9042c2b848ae3afd9b80d2esophiechang  if (new_encoder.external) {
190047d78cc8ad54baabc9042c2b848ae3afd9b80d2esophiechang    webrtc::VideoCodecType type = CodecTypeFromName(codec_settings.codec.name);
190147d78cc8ad54baabc9042c2b848ae3afd9b80d2esophiechang    parameters_.config.encoder_settings.internal_source =
190247d78cc8ad54baabc9042c2b848ae3afd9b80d2esophiechang        external_encoder_factory_->EncoderTypeHasInternalSource(type);
190347d78cc8ad54baabc9042c2b848ae3afd9b80d2esophiechang  }
19045301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  parameters_.config.rtp.fec = codec_settings.fec;
19055301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
19065301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  // Set RTX payload type if RTX is enabled.
19075301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  if (!parameters_.config.rtp.rtx.ssrcs.empty()) {
1908b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org    if (codec_settings.rtx_payload_type == -1) {
1909b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org      LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX "
1910b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org                         "payload type. Ignoring.";
1911b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org      parameters_.config.rtp.rtx.ssrcs.clear();
1912b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org    } else {
1913b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org      parameters_.config.rtp.rtx.payload_type = codec_settings.rtx_payload_type;
1914b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org    }
19155301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org  }
19165301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
191767c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström  parameters_.config.rtp.nack.rtp_history_ms =
191867c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström      HasNack(codec_settings.codec) ? kNackHistoryMs : 0;
19195301b0f1fce9478dfa56476e174332a1d67b053apbos@webrtc.org
1920102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg  RTC_CHECK(options.suspend_below_min_bitrate);
1921102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg  parameters_.config.suspend_below_min_bitrate =
1922102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg      *options.suspend_below_min_bitrate;
19235ff71ab4b369fe3dbfaec5f91cd2e491397eff33pbos@webrtc.org
1924102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg  parameters_.codec_settings =
1925be57983f4bd875c39a229bab5112b32dad004057Karl Wiberg      rtc::Optional<WebRtcVideoChannel2::VideoCodecSettings>(codec_settings);
19266ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org  parameters_.options = options;
1927543e589205af006f6b999a2c5df51d3fb722d925pbos@webrtc.org
1928874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  LOG(LS_INFO)
1929874ca3af5b163e1b3fd8802171e44ee252557842deadbeef      << "RecreateWebRtcStream (send) because of SetCodecAndOptions; options="
1930874ca3af5b163e1b3fd8802171e44ee252557842deadbeef      << options.ToString();
1931b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  RecreateWebRtcStream();
19327fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  if (allocated_encoder_.encoder != new_encoder.encoder) {
19337fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    DestroyVideoEncoder(&allocated_encoder_);
19347fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org    allocated_encoder_ = new_encoder;
19357fe1e03dd6da66401010119734245f114bf06645pbos@webrtc.org  }
1936b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
1937b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
1938d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions(
1939d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const std::vector<webrtc::RtpExtension>& rtp_extensions) {
1940d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope cs(&lock_);
1941d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  parameters_.config.rtp.extensions = rtp_extensions;
1942874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  if (stream_ != nullptr) {
1943874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetRtpExtensions";
19443c3f6460646183914629e5dab8ae5fcede4f0e80Peter Boström    RecreateWebRtcStream();
1945874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  }
1946d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
1947d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
19481387149ad1669365ac05278bf779a407bec08a4edeadbeefvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetSendParameters(
19491387149ad1669365ac05278bf779a407bec08a4edeadbeef    const VideoSendParameters& send_params) {
19501387149ad1669365ac05278bf779a407bec08a4edeadbeef  rtc::CritScope cs(&lock_);
19511387149ad1669365ac05278bf779a407bec08a4edeadbeef  parameters_.config.rtp.rtcp_mode = send_params.rtcp.reduced_size
19521387149ad1669365ac05278bf779a407bec08a4edeadbeef                                         ? webrtc::RtcpMode::kReducedSize
19531387149ad1669365ac05278bf779a407bec08a4edeadbeef                                         : webrtc::RtcpMode::kCompound;
19541387149ad1669365ac05278bf779a407bec08a4edeadbeef  if (stream_ != nullptr) {
19551387149ad1669365ac05278bf779a407bec08a4edeadbeef    LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetSendParameters";
19561387149ad1669365ac05278bf779a407bec08a4edeadbeef    RecreateWebRtcStream();
19571387149ad1669365ac05278bf779a407bec08a4edeadbeef  }
19581387149ad1669365ac05278bf779a407bec08a4edeadbeef}
19591387149ad1669365ac05278bf779a407bec08a4edeadbeef
1960a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.orgwebrtc::VideoEncoderConfig
1961a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig(
1962a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    const Dimensions& dimensions,
1963a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    const VideoCodec& codec) const {
1964a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  webrtc::VideoEncoderConfig encoder_config;
1965a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  if (dimensions.is_screencast) {
1966102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg    RTC_CHECK(parameters_.options.screencast_min_bitrate);
1967a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    encoder_config.min_transmit_bitrate_bps =
1968102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg        *parameters_.options.screencast_min_bitrate * 1000;
1969143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng    encoder_config.content_type =
1970143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng        webrtc::VideoEncoderConfig::ContentType::kScreen;
1971a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  } else {
1972a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    encoder_config.min_transmit_bitrate_bps = 0;
1973143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng    encoder_config.content_type =
1974143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng        webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo;
1975a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  }
1976a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
1977a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  // Restrict dimensions according to codec max.
1978a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  int width = dimensions.width;
1979a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  int height = dimensions.height;
1980a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  if (!dimensions.is_screencast) {
1981a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    if (codec.width < width)
1982a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org      width = codec.width;
1983a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    if (codec.height < height)
1984a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org      height = codec.height;
1985a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  }
1986a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
1987a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  VideoCodec clamped_codec = codec;
1988a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  clamped_codec.width = width;
1989a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  clamped_codec.height = height;
1990a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
1991fdac516510a2bd5d57b0786fbd49e2a6b9aeed2fnoahric  // By default, the stream count for the codec configuration should match the
1992fdac516510a2bd5d57b0786fbd49e2a6b9aeed2fnoahric  // number of negotiated ssrcs. But if the codec is blacklisted for simulcast
1993fdac516510a2bd5d57b0786fbd49e2a6b9aeed2fnoahric  // or a screencast, only configure a single stream.
1994fdac516510a2bd5d57b0786fbd49e2a6b9aeed2fnoahric  size_t stream_count = parameters_.config.rtp.ssrcs.size();
1995fdac516510a2bd5d57b0786fbd49e2a6b9aeed2fnoahric  if (IsCodecBlacklistedForSimulcast(codec.name) || dimensions.is_screencast) {
1996fdac516510a2bd5d57b0786fbd49e2a6b9aeed2fnoahric    stream_count = 1;
1997fdac516510a2bd5d57b0786fbd49e2a6b9aeed2fnoahric  }
1998fdac516510a2bd5d57b0786fbd49e2a6b9aeed2fnoahric
1999fdac516510a2bd5d57b0786fbd49e2a6b9aeed2fnoahric  encoder_config.streams =
2000fdac516510a2bd5d57b0786fbd49e2a6b9aeed2fnoahric      CreateVideoStreams(clamped_codec, parameters_.options,
2001fdac516510a2bd5d57b0786fbd49e2a6b9aeed2fnoahric                         parameters_.max_bitrate_bps, stream_count);
2002a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
2003a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  // Conference mode screencast uses 2 temporal layers split at 100kbit.
2004102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg  if (parameters_.options.conference_mode.value_or(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
203791d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(!parameters_.encoder_config.streams.empty());
2038c4175b9fdf7d23eb58a044ff39e2b096f9091995pbos@webrtc.org
2039102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg  RTC_CHECK(parameters_.codec_settings);
2040102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg  VideoCodecSettings codec_settings = *parameters_.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_);
206391d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_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
2085102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg    if (parameters_.codec_settings)
2086102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg      info.codec_name = parameters_.codec_settings->codec.name;
208777e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org    for (size_t i = 0; i < parameters_.encoder_config.streams.size(); ++i) {
208877e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org      if (i == parameters_.encoder_config.streams.size() - 1) {
208977e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org        info.preferred_bitrate +=
209077e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org            parameters_.encoder_config.streams[i].max_bitrate_bps;
209177e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org      } else {
209277e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org        info.preferred_bitrate +=
209377e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org            parameters_.encoder_config.streams[i].target_bitrate_bps;
209477e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org      }
209577e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org    }
2096e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
209777e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org    if (stream_ == NULL)
209877e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org      return info;
2099c3d2bd28a3e8badc434a5081dd36f4ac41b4e3f2pbos@webrtc.org
210077e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org    stats = stream_->GetStats();
210177e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org
21029a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org    info.adapt_changes = old_adapt_changes_;
21039a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org    info.adapt_reason = CoordinatedVideoAdapter::ADAPTREASON_NONE;
21049a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org
21059a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org    if (capturer_ != NULL) {
21069a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org      if (!capturer_->IsMuted()) {
21079a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org        VideoFormat last_captured_frame_format;
21089a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org        capturer_->GetStats(&info.adapt_frame_drops, &info.effects_frame_drops,
21099a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org                            &info.capturer_frame_time,
21109a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org                            &last_captured_frame_format);
21119a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org        info.input_frame_width = last_captured_frame_format.width;
21129a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org        info.input_frame_height = last_captured_frame_format.height;
21139a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org      }
21149a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org      if (capturer_->video_adapter() != nullptr) {
21159a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org        info.adapt_changes += capturer_->video_adapter()->adaptation_changes();
21169a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org        info.adapt_reason = capturer_->video_adapter()->adapt_reason();
21179a4410e9934578e84cc129b978a29e151d957994pbos@webrtc.org      }
211877e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org    }
211977e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org  }
212017821db19702aca15d0d93cb60515ca70823fad7asapersson
212117821db19702aca15d0d93cb60515ca70823fad7asapersson  // Get bandwidth limitation info from stream_->GetStats().
212217821db19702aca15d0d93cb60515ca70823fad7asapersson  // Input resolution (output from video_adapter) can be further scaled down or
212317821db19702aca15d0d93cb60515ca70823fad7asapersson  // higher video layer(s) can be dropped due to bitrate constraints.
212417821db19702aca15d0d93cb60515ca70823fad7asapersson  // Note, adapt_changes only include changes from the video_adapter.
212517821db19702aca15d0d93cb60515ca70823fad7asapersson  if (stats.bw_limited_resolution)
212617821db19702aca15d0d93cb60515ca70823fad7asapersson    info.adapt_reason |= CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH;
212717821db19702aca15d0d93cb60515ca70823fad7asapersson
2128b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström  info.encoder_implementation_name = stats.encoder_implementation_name;
2129259bd2034c3d3ee7f2dc4d481e9bf896a3a4d6efPeter Boström  info.ssrc_groups = ssrc_groups_;
2130e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_input = stats.input_frame_rate;
2131e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_sent = stats.encode_frame_rate;
21323e6e271ec3253e78ae0eb72156e5236d43f8731dpbos@webrtc.org  info.avg_encode_ms = stats.avg_encode_time_ms;
21333e6e271ec3253e78ae0eb72156e5236d43f8731dpbos@webrtc.org  info.encode_usage_percent = stats.encode_usage_percent;
2134e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
213577e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org  info.nominal_bitrate = stats.media_bitrate_bps;
213677e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org
2137273a414b0ec2e58fdf3b817ad8b1a02f4ce15287pbos@webrtc.org  info.send_frame_width = 0;
2138273a414b0ec2e58fdf3b817ad8b1a02f4ce15287pbos@webrtc.org  info.send_frame_height = 0;
213909c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  for (std::map<uint32_t, webrtc::VideoSendStream::StreamStats>::iterator it =
2140e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org           stats.substreams.begin();
214109c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org       it != stats.substreams.end(); ++it) {
2142e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    // TODO(pbos): Wire up additional stats, such as padding bytes.
214309c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org    webrtc::VideoSendStream::StreamStats stream_stats = it->second;
2144cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org    info.bytes_sent += stream_stats.rtp_stats.transmitted.payload_bytes +
2145cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org                       stream_stats.rtp_stats.transmitted.header_bytes +
2146cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org                       stream_stats.rtp_stats.transmitted.padding_bytes;
2147cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org    info.packets_sent += stream_stats.rtp_stats.transmitted.packets;
2148e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.packets_lost += stream_stats.rtcp_stats.cumulative_lost;
214909c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org    if (stream_stats.width > info.send_frame_width)
215009c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org      info.send_frame_width = stream_stats.width;
215109c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org    if (stream_stats.height > info.send_frame_height)
215209c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org      info.send_frame_height = stream_stats.height;
21531d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    info.firs_rcvd += stream_stats.rtcp_packet_type_counts.fir_packets;
21541d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    info.nacks_rcvd += stream_stats.rtcp_packet_type_counts.nack_packets;
21551d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    info.plis_rcvd += stream_stats.rtcp_packet_type_counts.pli_packets;
2156e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
2157e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
2158e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  if (!stats.substreams.empty()) {
2159e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    // TODO(pbos): Report fraction lost per SSRC.
216009c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org    webrtc::VideoSendStream::StreamStats first_stream_stats =
216109c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org        stats.substreams.begin()->second;
2162e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org    info.fraction_lost =
2163e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org        static_cast<float>(first_stream_stats.rtcp_stats.fraction_lost) /
2164e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org        (1 << 8);
2165e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  }
2166e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
2167e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  return info;
2168e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
2169e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
21700bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::FillBandwidthEstimationInfo(
21710bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org    BandwidthEstimationInfo* bwe_info) {
21720bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  rtc::CritScope cs(&lock_);
21730bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  if (stream_ == NULL) {
21740bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org    return;
21750bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  }
21760bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  webrtc::VideoSendStream::Stats stats = stream_->GetStats();
217709c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  for (std::map<uint32_t, webrtc::VideoSendStream::StreamStats>::iterator it =
21780bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org           stats.substreams.begin();
217909c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org       it != stats.substreams.end(); ++it) {
21800bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org    bwe_info->transmit_bitrate += it->second.total_bitrate_bps;
21810bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org    bwe_info->retransmit_bitrate += it->second.retransmit_bitrate_bps;
21820bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org  }
2183891d48393e5ccd2f5e03d509c544c00a3d88cbbcpbos@webrtc.org  bwe_info->target_enc_bitrate += stats.target_media_bitrate_bps;
218477e11bbe834e3b096db57278d2ad7c76d8c26d66pbos@webrtc.org  bwe_info->actual_enc_bitrate += stats.media_bitrate_bps;
21850bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org}
21860bae1fab4adb9bb8164e53142bf419049eafec38stefan@webrtc.org
2187dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boströmvoid WebRtcVideoChannel2::WebRtcVideoSendStream::SetMaxBitrateBps(
2188dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    int max_bitrate_bps) {
2189dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  rtc::CritScope cs(&lock_);
2190dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  parameters_.max_bitrate_bps = max_bitrate_bps;
2191dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström
2192dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  // No need to reconfigure if the stream hasn't been configured yet.
2193dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  if (parameters_.encoder_config.streams.empty())
2194dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström    return;
2195dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström
2196dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  // Force a stream reconfigure to set the new max bitrate.
2197dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  int width = last_dimensions_.width;
2198dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  last_dimensions_.width = 0;
2199dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström  SetDimensions(width, last_dimensions_.height, last_dimensions_.is_screencast);
2200dfd53fe26b013d0948024a38eec6fbc31c29a094Peter Boström}
220142684be21b255e2b07eb154e6a2807fa2226167epbos@webrtc.org
2202b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() {
2203b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (stream_ != NULL) {
2204b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    call_->DestroyVideoSendStream(stream_);
2205b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
22066ae48c660934784b4df56ab1ac99402ce3745e9fpbos@webrtc.org
2207102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg  RTC_CHECK(parameters_.codec_settings);
2208bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  parameters_.encoder_config.encoder_specific_settings =
2209143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng      ConfigureVideoEncoderSettings(
2210102c6a61bc0b42dc0956d013530fc0213b7e881bkwiberg          parameters_.codec_settings->codec, parameters_.options,
2211143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng          parameters_.encoder_config.content_type ==
2212143cec1cc68b9ba44f3ef4467f1422704f2395f0Erik Språng              webrtc::VideoEncoderConfig::ContentType::kScreen);
2213bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org
2214b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org  webrtc::VideoSendStream::Config config = parameters_.config;
2215b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org  if (!config.rtp.rtx.ssrcs.empty() && config.rtp.rtx.payload_type == -1) {
2216b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org    LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX "
2217b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org                       "payload type the set codec. Ignoring RTX.";
2218b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org    config.rtp.rtx.ssrcs.clear();
2219b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org  }
2220b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org  stream_ = call_->CreateVideoSendStream(config, parameters_.encoder_config);
22216f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
2222bbe0a8517d7f9da7aa779bff77cdbb70df358437pbos@webrtc.org  parameters_.encoder_config.encoder_specific_settings = NULL;
22236f48f1bf68a10669c9bcd81262c1a98ed2a8d462pbos@webrtc.org
2224b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  if (sending_) {
2225b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    stream_->Start();
2226b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
2227b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
2228b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2229d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream(
2230d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    webrtc::Call* call,
2231259bd2034c3d3ee7f2dc4d481e9bf896a3a4d6efPeter Boström    const StreamParams& sp,
22324fbae2b79134572135d9d5fe35a7d1ccdeea3a4dsolenberg    const webrtc::VideoReceiveStream::Config& config,
2233776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org    WebRtcVideoDecoderFactory* external_decoder_factory,
2234a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org    bool default_stream,
2235444682acf9804c5fcbddaded9e900ba3cc6921fcqiangchen    const std::vector<VideoCodecSettings>& recv_codecs,
2236444682acf9804c5fcbddaded9e900ba3cc6921fcqiangchen    bool disable_prerenderer_smoothing)
2237d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    : call_(call),
2238259bd2034c3d3ee7f2dc4d481e9bf896a3a4d6efPeter Boström      ssrcs_(sp.ssrcs),
2239259bd2034c3d3ee7f2dc4d481e9bf896a3a4d6efPeter Boström      ssrc_groups_(sp.ssrc_groups),
2240d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      stream_(NULL),
2241a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org      default_stream_(default_stream),
2242b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      config_(config),
2243776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org      external_decoder_factory_(external_decoder_factory),
2244444682acf9804c5fcbddaded9e900ba3cc6921fcqiangchen      disable_prerenderer_smoothing_(disable_prerenderer_smoothing),
2245b648b9d85c5d07b0866ef45f5be587f71b0849b4pbos@webrtc.org      renderer_(NULL),
2246d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org      last_width_(-1),
2247fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org      last_height_(-1),
2248fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org      first_frame_timestamp_(-1),
2249fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org      estimated_remote_start_ntp_time_ms_(0) {
2250d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config_.renderer = this;
2251d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // SetRecvCodecs will also reset (start) the VideoReceiveStream.
2252874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  LOG(LS_INFO) << "SetRecvCodecs (recv) because we are creating the receive "
2253874ca3af5b163e1b3fd8802171e44ee252557842deadbeef                  "stream for the first time: "
2254874ca3af5b163e1b3fd8802171e44ee252557842deadbeef               << CodecSettingsVectorToString(recv_codecs);
2255d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  SetRecvCodecs(recv_codecs);
2256d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2257d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
22587252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter BoströmWebRtcVideoChannel2::WebRtcVideoReceiveStream::AllocatedDecoder::
22597252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström    AllocatedDecoder(webrtc::VideoDecoder* decoder,
22607252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström                     webrtc::VideoCodecType type,
22617252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström                     bool external)
22627252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström    : decoder(decoder),
22637252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström      external_decoder(nullptr),
22647252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström      type(type),
22657252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström      external(external) {
22667252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström  if (external) {
22677252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström    external_decoder = decoder;
22687252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström    this->decoder =
22697252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström        new webrtc::VideoDecoderSoftwareFallbackWrapper(type, external_decoder);
22707252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström  }
22717252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström}
22727252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström
2273d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::~WebRtcVideoReceiveStream() {
2274d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  call_->DestroyVideoReceiveStream(stream_);
227596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  ClearDecoders(&allocated_decoders_);
2276d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2277d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
22780c4e06b4c6107a1b94f764e279e4fb4161e905b0Peter Boströmconst std::vector<uint32_t>&
2279d6f4c25eedcfd502920f1b2a24744badd9da80bePeter BoströmWebRtcVideoChannel2::WebRtcVideoReceiveStream::GetSsrcs() const {
2280d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström  return ssrcs_;
2281d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström}
2282d6f4c25eedcfd502920f1b2a24744badd9da80bePeter Boström
228396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::AllocatedDecoder
228496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::CreateOrReuseVideoDecoder(
228596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    std::vector<AllocatedDecoder>* old_decoders,
228696a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    const VideoCodec& codec) {
228796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  webrtc::VideoCodecType type = CodecTypeFromName(codec.name);
2288776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
228996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  for (size_t i = 0; i < old_decoders->size(); ++i) {
229096a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    if ((*old_decoders)[i].type == type) {
229196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      AllocatedDecoder decoder = (*old_decoders)[i];
229296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      (*old_decoders)[i] = old_decoders->back();
229396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      old_decoders->pop_back();
229496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      return decoder;
229596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    }
229696a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  }
2297776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
229896a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  if (external_decoder_factory_ != NULL) {
229996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    webrtc::VideoDecoder* decoder =
230096a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org        external_decoder_factory_->CreateVideoDecoder(type);
230196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    if (decoder != NULL) {
230296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org      return AllocatedDecoder(decoder, type, true);
230396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    }
230496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  }
2305776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
230696a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  if (type == webrtc::kVideoCodecVP8) {
230796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    return AllocatedDecoder(
230896a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org        webrtc::VideoDecoder::Create(webrtc::VideoDecoder::kVp8), type, false);
230996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  }
2310d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
2311b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org  if (type == webrtc::kVideoCodecVP9) {
2312b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org    return AllocatedDecoder(
2313b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org        webrtc::VideoDecoder::Create(webrtc::VideoDecoder::kVp9), type, false);
2314b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org  }
2315b9557a9bb7ed5f9aa1e7b3a64de4238572794ae3pbos@webrtc.org
231671f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin  if (type == webrtc::kVideoCodecH264) {
231771f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin    return AllocatedDecoder(
231871f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin        webrtc::VideoDecoder::Create(webrtc::VideoDecoder::kH264), type, false);
231971f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin  }
232071f6f4405c1c5f60097f8d10841378088e78e8b9Zeke Chin
232196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  // This shouldn't happen, we should not be trying to create something we don't
232296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  // support.
232391d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(false);
232496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  return AllocatedDecoder(NULL, webrtc::kVideoCodecUnknown, false);
232596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org}
232696a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org
232796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvCodecs(
232896a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    const std::vector<VideoCodecSettings>& recv_codecs) {
232996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  std::vector<AllocatedDecoder> old_decoders = allocated_decoders_;
233096a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  allocated_decoders_.clear();
233196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  config_.decoders.clear();
233296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  for (size_t i = 0; i < recv_codecs.size(); ++i) {
233396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    AllocatedDecoder allocated_decoder =
233496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org        CreateOrReuseVideoDecoder(&old_decoders, recv_codecs[i].codec);
233596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    allocated_decoders_.push_back(allocated_decoder);
2336d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
233796a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    webrtc::VideoReceiveStream::Decoder decoder;
233896a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    decoder.decoder = allocated_decoder.decoder;
233996a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    decoder.payload_type = recv_codecs[i].codec.id;
234096a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    decoder.payload_name = recv_codecs[i].codec.name;
234196a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    config_.decoders.push_back(decoder);
234296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  }
234396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org
234496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  // TODO(pbos): Reconfigure RTX based on incoming recv_codecs.
234596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  config_.rtp.fec = recv_codecs.front().fec;
2346257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org  config_.rtp.nack.rtp_history_ms =
2347e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin      HasNack(recv_codecs.begin()->codec) ? kNackHistoryMs : 0;
2348257e130a1639febeb3ffc4d42943be3cb58151c7pbos@webrtc.org
2349874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  LOG(LS_INFO) << "RecreateWebRtcStream (recv) because of SetRecvCodecs: "
2350874ca3af5b163e1b3fd8802171e44ee252557842deadbeef               << CodecSettingsVectorToString(recv_codecs);
2351d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  RecreateWebRtcStream();
23529e1b992f74470aecfeb216e26b455982ddc4a6d5Peter Boström  ClearDecoders(&old_decoders);
2353d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2354d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
23553548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boströmvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetLocalSsrc(
23563548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström    uint32_t local_ssrc) {
235791d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  // TODO(pbos): Consider turning this sanity check into a RTC_DCHECK. You
235891d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  // should not be able to create a sender with the same SSRC as a receiver, but
235991d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  // right now this can't be done due to unittests depending on receiving what
236091d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  // they are sending from the same MediaChannel.
2361874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  if (local_ssrc == config_.rtp.remote_ssrc) {
2362874ca3af5b163e1b3fd8802171e44ee252557842deadbeef    LOG(LS_INFO) << "Ignoring call to SetLocalSsrc because parameters are "
2363874ca3af5b163e1b3fd8802171e44ee252557842deadbeef                    "unchanged; local_ssrc=" << local_ssrc;
23643548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström    return;
2365874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  }
23663548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström
23673548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström  config_.rtp.local_ssrc = local_ssrc;
2368874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  LOG(LS_INFO)
2369874ca3af5b163e1b3fd8802171e44ee252557842deadbeef      << "RecreateWebRtcStream (recv) because of SetLocalSsrc; local_ssrc="
2370874ca3af5b163e1b3fd8802171e44ee252557842deadbeef      << local_ssrc;
23713548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström  RecreateWebRtcStream();
23723548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström}
23733548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström
237443edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefanvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetFeedbackParameters(
237543edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan    bool nack_enabled,
237643edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan    bool remb_enabled,
237743edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan    bool transport_cc_enabled) {
237867c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström  int nack_history_ms = nack_enabled ? kNackHistoryMs : 0;
237967c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström  if (config_.rtp.nack.rtp_history_ms == nack_history_ms &&
238043edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan      config_.rtp.remb == remb_enabled &&
238143edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan      config_.rtp.transport_cc == transport_cc_enabled) {
238243edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan    LOG(LS_INFO)
238343edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan        << "Ignoring call to SetFeedbackParameters because parameters are "
238443edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan           "unchanged; nack="
238543edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan        << nack_enabled << ", remb=" << remb_enabled
238643edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan        << ", transport_cc=" << transport_cc_enabled;
2387126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström    return;
238867c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström  }
238967c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström  config_.rtp.remb = remb_enabled;
239067c9df79828991c5aab96b9253ae4e7ba7ed508ePeter Boström  config_.rtp.nack.rtp_history_ms = nack_history_ms;
239143edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan  config_.rtp.transport_cc = transport_cc_enabled;
239243edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan  LOG(LS_INFO)
239343edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan      << "RecreateWebRtcStream (recv) because of SetFeedbackParameters; nack="
239443edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan      << nack_enabled << ", remb=" << remb_enabled
239543edf0ffb91a50e2efa01c7befe4d188a7e30ea2stefan      << ", transport_cc=" << transport_cc_enabled;
2396126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström  RecreateWebRtcStream();
2397126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström}
2398126c03ea02d8a99bfa3d1e6d6fe04516183d31afPeter Boström
2399d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRtpExtensions(
2400d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    const std::vector<webrtc::RtpExtension>& extensions) {
2401d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  config_.rtp.extensions = extensions;
2402874ca3af5b163e1b3fd8802171e44ee252557842deadbeef  LOG(LS_INFO) << "RecreateWebRtcStream (recv) because of SetRtpExtensions";
24033548dd21542c7b3f2c4680c6a6d86b0d719bd008Peter Boström  RecreateWebRtcStream();
2404d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2405d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
24061387149ad1669365ac05278bf779a407bec08a4edeadbeefvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvParameters(
24071387149ad1669365ac05278bf779a407bec08a4edeadbeef    const VideoRecvParameters& recv_params) {
24081387149ad1669365ac05278bf779a407bec08a4edeadbeef  config_.rtp.rtcp_mode = recv_params.rtcp.reduced_size
24091387149ad1669365ac05278bf779a407bec08a4edeadbeef                              ? webrtc::RtcpMode::kReducedSize
24101387149ad1669365ac05278bf779a407bec08a4edeadbeef                              : webrtc::RtcpMode::kCompound;
24111387149ad1669365ac05278bf779a407bec08a4edeadbeef  LOG(LS_INFO) << "RecreateWebRtcStream (recv) because of SetRecvParameters";
24121387149ad1669365ac05278bf779a407bec08a4edeadbeef  RecreateWebRtcStream();
24131387149ad1669365ac05278bf779a407bec08a4edeadbeef}
24141387149ad1669365ac05278bf779a407bec08a4edeadbeef
2415d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::RecreateWebRtcStream() {
2416d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (stream_ != NULL) {
2417d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    call_->DestroyVideoReceiveStream(stream_);
2418d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
2419d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  stream_ = call_->CreateVideoReceiveStream(config_);
2420d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  stream_->Start();
2421d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2422d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
242396a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::ClearDecoders(
242496a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    std::vector<AllocatedDecoder>* allocated_decoders) {
242596a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  for (size_t i = 0; i < allocated_decoders->size(); ++i) {
242696a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org    if ((*allocated_decoders)[i].external) {
2427776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org      external_decoder_factory_->DestroyVideoDecoder(
24287252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström          (*allocated_decoders)[i].external_decoder);
2429776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org    }
24307252a2ba8035c4128917a9558a3e34fc9dbe7c44Peter Boström    delete (*allocated_decoders)[i].decoder;
2431776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org  }
243296a93259b361f4b03080a188d781b0835cf4edafpbos@webrtc.org  allocated_decoders->clear();
2433776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org}
2434776e6f289c7396a1143b8b36b03f88b08ac8cba3pbos@webrtc.org
2435d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::RenderFrame(
24364765070b8d6f024509c717c04d9b708750666927Miguel Casas-Sanchez    const webrtc::VideoFrame& frame,
2437d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    int time_to_render_ms) {
2438d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
2439fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org
2440fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org  if (first_frame_timestamp_ < 0)
2441fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org    first_frame_timestamp_ = frame.timestamp();
2442fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org  int64_t rtp_time_elapsed_since_first_frame =
2443fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org      (timestamp_wraparound_handler_.Unwrap(frame.timestamp()) -
2444fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org       first_frame_timestamp_);
2445fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org  int64_t elapsed_time_ms = rtp_time_elapsed_since_first_frame /
2446fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org                            (cricket::kVideoCodecClockrate / 1000);
2447fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org  if (frame.ntp_time_ms() > 0)
2448fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org    estimated_remote_start_ntp_time_ms_ = frame.ntp_time_ms() - elapsed_time_ms;
2449fc5ad95fecc5ddc7d98dcfbac1c4e75a7814253fmagjed@webrtc.org
2450d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (renderer_ == NULL) {
2451d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    LOG(LS_WARNING) << "VideoReceiveStream not connected to a VideoRenderer.";
2452d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    return;
2453d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
2454d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
2455d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (frame.width() != last_width_ || frame.height() != last_height_) {
2456d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    SetSize(frame.width(), frame.height());
2457d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
2458d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
24592386d6dd92f10a715f131b5ad408b1babc1f35b0magjed@webrtc.org  const WebRtcVideoFrame render_frame(
24602386d6dd92f10a715f131b5ad408b1babc1f35b0magjed@webrtc.org      frame.video_frame_buffer(),
246164c1e8cda5cb4db85c5c296bf2f6a8181af7de9dGuo-wei Shieh      frame.render_time_ms() * rtc::kNumNanosecsPerMillisec, frame.rotation());
2462d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  renderer_->RenderFrame(&render_frame);
2463d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2464d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
24650d852d5c27a759fe7aadc500bd7b3cadfae3deb8pbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoReceiveStream::IsTextureSupported() const {
24660d852d5c27a759fe7aadc500bd7b3cadfae3deb8pbos@webrtc.org  return true;
24670d852d5c27a759fe7aadc500bd7b3cadfae3deb8pbos@webrtc.org}
24680d852d5c27a759fe7aadc500bd7b3cadfae3deb8pbos@webrtc.org
2469444682acf9804c5fcbddaded9e900ba3cc6921fcqiangchenbool WebRtcVideoChannel2::WebRtcVideoReceiveStream::SmoothsRenderedFrames()
2470444682acf9804c5fcbddaded9e900ba3cc6921fcqiangchen    const {
2471444682acf9804c5fcbddaded9e900ba3cc6921fcqiangchen  return disable_prerenderer_smoothing_;
2472444682acf9804c5fcbddaded9e900ba3cc6921fcqiangchen}
2473444682acf9804c5fcbddaded9e900ba3cc6921fcqiangchen
2474a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.orgbool WebRtcVideoChannel2::WebRtcVideoReceiveStream::IsDefaultStream() const {
2475a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org  return default_stream_;
2476a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org}
2477a2a6fe66a39797ea61a04d80ce3afc494d850bfcpbos@webrtc.org
2478d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRenderer(
2479d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    cricket::VideoRenderer* renderer) {
2480d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
2481d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  renderer_ = renderer;
2482d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (renderer_ != NULL && last_width_ != -1) {
2483d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    SetSize(last_width_, last_height_);
2484d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
2485d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2486d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
2487d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgVideoRenderer* WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetRenderer() {
2488d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // TODO(pbos): Remove GetRenderer and all uses of it, it's thread-unsafe by
2489d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  // design.
2490d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
2491d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  return renderer_;
2492d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2493d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
2494d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.orgvoid WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetSize(int width,
2495d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org                                                            int height) {
2496d4e598d57aed714a599444a7eab5e8fdde52a950buildbot@webrtc.org  rtc::CritScope crit(&renderer_lock_);
2497d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  if (!renderer_->SetSize(width, height, 0)) {
2498d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org    LOG(LS_ERROR) << "Could not set renderer size.";
2499d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  }
2500d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  last_width_ = width;
2501d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org  last_height_ = height;
2502d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org}
2503d1ea06b3d5adab352741df5092c56b20f3e1a74fpbos@webrtc.org
2504f42376c60111edba6f29060bf3dd79e75d8dbb97pbosstd::string
2505f42376c60111edba6f29060bf3dd79e75d8dbb97pbosWebRtcVideoChannel2::WebRtcVideoReceiveStream::GetCodecNameFromPayloadType(
2506f42376c60111edba6f29060bf3dd79e75d8dbb97pbos    int payload_type) {
2507f42376c60111edba6f29060bf3dd79e75d8dbb97pbos  for (const webrtc::VideoReceiveStream::Decoder& decoder : config_.decoders) {
2508f42376c60111edba6f29060bf3dd79e75d8dbb97pbos    if (decoder.payload_type == payload_type) {
2509f42376c60111edba6f29060bf3dd79e75d8dbb97pbos      return decoder.payload_name;
2510f42376c60111edba6f29060bf3dd79e75d8dbb97pbos    }
2511f42376c60111edba6f29060bf3dd79e75d8dbb97pbos  }
2512f42376c60111edba6f29060bf3dd79e75d8dbb97pbos  return "";
2513f42376c60111edba6f29060bf3dd79e75d8dbb97pbos}
2514f42376c60111edba6f29060bf3dd79e75d8dbb97pbos
2515e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgVideoReceiverInfo
2516e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.orgWebRtcVideoChannel2::WebRtcVideoReceiveStream::GetVideoReceiverInfo() {
2517e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  VideoReceiverInfo info;
2518259bd2034c3d3ee7f2dc4d481e9bf896a3a4d6efPeter Boström  info.ssrc_groups = ssrc_groups_;
2519e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.add_ssrc(config_.rtp.remote_ssrc);
2520e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  webrtc::VideoReceiveStream::Stats stats = stream_->GetStats();
2521b7d9a97ce41022e984348efb5f28bf6dd6c6b779Peter Boström  info.decoder_implementation_name = stats.decoder_implementation_name;
2522cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org  info.bytes_rcvd = stats.rtp_stats.transmitted.payload_bytes +
2523cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org                    stats.rtp_stats.transmitted.header_bytes +
2524cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org                    stats.rtp_stats.transmitted.padding_bytes;
2525cfd82dfc1156f6610388bec0ebbdeacaf47e9719asapersson@webrtc.org  info.packets_rcvd = stats.rtp_stats.transmitted.packets;
2526393347ff988708df5037ddcd181fe204bd1ab37ePeter Boström  info.packets_lost = stats.rtcp_stats.cumulative_lost;
2527393347ff988708df5037ddcd181fe204bd1ab37ePeter Boström  info.fraction_lost =
2528393347ff988708df5037ddcd181fe204bd1ab37ePeter Boström      static_cast<float>(stats.rtcp_stats.fraction_lost) / (1 << 8);
2529e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
2530e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_rcvd = stats.network_frame_rate;
2531e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_decoded = stats.decode_frame_rate;
2532e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  info.framerate_output = stats.render_frame_rate;
2533e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
25341d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org  {
25351d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    rtc::CritScope frame_cs(&renderer_lock_);
25361d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    info.frame_width = last_width_;
25371d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    info.frame_height = last_height_;
25381d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org    info.capture_start_ntp_time_ms = estimated_remote_start_ntp_time_ms_;
25391d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org  }
25401d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org
254109c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  info.decode_ms = stats.decode_ms;
254209c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  info.max_decode_ms = stats.max_decode_ms;
254309c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  info.current_delay_ms = stats.current_delay_ms;
254409c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  info.target_delay_ms = stats.target_delay_ms;
254509c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  info.jitter_buffer_ms = stats.jitter_buffer_ms;
254609c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  info.min_playout_delay_ms = stats.min_playout_delay_ms;
254709c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org  info.render_delay_ms = stats.render_delay_ms;
254809c77b95bb62566be64da662f0b3b6a838ec6553pbos@webrtc.org
2549f42376c60111edba6f29060bf3dd79e75d8dbb97pbos  info.codec_name = GetCodecNameFromPayloadType(stats.current_payload_type);
2550f42376c60111edba6f29060bf3dd79e75d8dbb97pbos
25511d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org  info.firs_sent = stats.rtcp_packet_type_counts.fir_packets;
25521d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org  info.plis_sent = stats.rtcp_packet_type_counts.pli_packets;
25531d0fa5d352fe12092201fade249905c7e1ff974bpbos@webrtc.org  info.nacks_sent = stats.rtcp_packet_type_counts.nack_packets;
2554e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
2555e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org  return info;
2556e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org}
2557e6f84ae8a602ce78733d20b280ce32198e7ecef5pbos@webrtc.org
2558b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::VideoCodecSettings::VideoCodecSettings()
2559b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    : rtx_payload_type(-1) {}
2560b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2561a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.orgbool WebRtcVideoChannel2::VideoCodecSettings::operator==(
2562a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org    const WebRtcVideoChannel2::VideoCodecSettings& other) const {
2563a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org  return codec == other.codec &&
2564a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org         fec.ulpfec_payload_type == other.fec.ulpfec_payload_type &&
2565a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org         fec.red_payload_type == other.fec.red_payload_type &&
2566e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin         fec.red_rtx_payload_type == other.fec.red_rtx_payload_type &&
2567a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org         rtx_payload_type == other.rtx_payload_type;
2568a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org}
2569a2ef4fe9c331e7668b9e8ff64ce5141a535a5f21pbos@webrtc.org
2570ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boströmbool WebRtcVideoChannel2::VideoCodecSettings::operator!=(
2571ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström    const WebRtcVideoChannel2::VideoCodecSettings& other) const {
2572ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström  return !(*this == other);
2573ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström}
2574ee0b00e8a9cc2d8f4578912a389dee92ac020ee9Peter Boström
2575b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgstd::vector<WebRtcVideoChannel2::VideoCodecSettings>
2576b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.orgWebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) {
257791d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(!codecs.empty());
2578b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2579b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::vector<VideoCodecSettings> video_codecs;
2580b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  std::map<int, bool> payload_used;
2581e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  std::map<int, VideoCodec::CodecType> payload_codec_type;
2582d324546ced76d4e792338af4f7d02a5cd8819f92pkasting@chromium.org  // |rtx_mapping| maps video payload type to rtx payload type.
2583d324546ced76d4e792338af4f7d02a5cd8819f92pkasting@chromium.org  std::map<int, int> rtx_mapping;
2584b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2585b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  webrtc::FecConfig fec_settings;
2586b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2587b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < codecs.size(); ++i) {
2588b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    const VideoCodec& in_codec = codecs[i];
2589b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    int payload_type = in_codec.id;
2590b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2591b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    if (payload_used[payload_type]) {
2592b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      LOG(LS_ERROR) << "Payload type already registered: "
2593b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org                    << in_codec.ToString();
2594b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      return std::vector<VideoCodecSettings>();
2595b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
2596b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    payload_used[payload_type] = true;
2597e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    payload_codec_type[payload_type] = in_codec.GetCodecType();
2598b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2599b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    switch (in_codec.GetCodecType()) {
2600b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_RED: {
2601b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        // RED payload type, should not have duplicates.
260291d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg        RTC_DCHECK(fec_settings.red_payload_type == -1);
2603b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        fec_settings.red_payload_type = in_codec.id;
2604b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        continue;
2605b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
2606b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2607b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_ULPFEC: {
2608b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        // ULPFEC payload type, should not have duplicates.
260991d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg        RTC_DCHECK(fec_settings.ulpfec_payload_type == -1);
2610b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        fec_settings.ulpfec_payload_type = in_codec.id;
2611b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        continue;
2612b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
2613b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2614b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_RTX: {
2615b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        int associated_payload_type;
2616b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        if (!in_codec.GetParam(kCodecParamAssociatedPayloadType,
2617e9facf8bb32a1688f2156009c755caa2904e1ac9pkasting@chromium.org                               &associated_payload_type) ||
2618e9facf8bb32a1688f2156009c755caa2904e1ac9pkasting@chromium.org            !IsValidRtpPayloadType(associated_payload_type)) {
2619e9facf8bb32a1688f2156009c755caa2904e1ac9pkasting@chromium.org          LOG(LS_ERROR)
2620e9facf8bb32a1688f2156009c755caa2904e1ac9pkasting@chromium.org              << "RTX codec with invalid or no associated payload type: "
2621e9facf8bb32a1688f2156009c755caa2904e1ac9pkasting@chromium.org              << in_codec.ToString();
2622b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org          return std::vector<VideoCodecSettings>();
2623b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        }
2624b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        rtx_mapping[associated_payload_type] = in_codec.id;
2625b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        continue;
2626b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      }
2627b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2628b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      case VideoCodec::CODEC_VIDEO:
2629b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org        break;
2630b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
2631b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2632b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    video_codecs.push_back(VideoCodecSettings());
2633b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    video_codecs.back().codec = in_codec;
2634b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
2635b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2636b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // One of these codecs should have been a video codec. Only having FEC
2637b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  // parameters into this code is a logic error.
263891d6edef35e7275879c30ce16ecb8b6dc73c6e4ahenrikg  RTC_DCHECK(!video_codecs.empty());
2639b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2640e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  for (std::map<int, int>::const_iterator it = rtx_mapping.begin();
2641e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org       it != rtx_mapping.end();
2642e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org       ++it) {
2643e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    if (!payload_used[it->first]) {
2644e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org      LOG(LS_ERROR) << "RTX mapped to payload not in codec list.";
2645e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org      return std::vector<VideoCodecSettings>();
2646e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    }
2647e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    if (payload_codec_type[it->first] != VideoCodec::CODEC_VIDEO &&
2648e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin        payload_codec_type[it->first] != VideoCodec::CODEC_RED) {
2649e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin      LOG(LS_ERROR) << "RTX not mapped to regular video codec or RED codec.";
2650e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org      return std::vector<VideoCodecSettings>();
2651e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org    }
2652e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin
2653e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    if (it->first == fec_settings.red_payload_type) {
2654e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin      fec_settings.red_rtx_payload_type = it->second;
2655e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    }
2656e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org  }
2657e322a175f6f38c4ed39296d9724edf005e536a63pbos@webrtc.org
2658b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  for (size_t i = 0; i < video_codecs.size(); ++i) {
2659b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    video_codecs[i].fec = fec_settings;
2660e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin    if (rtx_mapping[video_codecs[i].codec.id] != 0 &&
2661e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin        rtx_mapping[video_codecs[i].codec.id] !=
2662e62202fedf57b74cc263246c0586ee353978caf8Shao Changbin            fec_settings.red_payload_type) {
2663b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org      video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id];
2664b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org    }
2665b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  }
2666b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2667b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org  return video_codecs;
2668b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}
2669b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2670b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org}  // namespace cricket
2671b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org
2672b5a22b14648c53874b4b76368a1a2271d985e875pbos@webrtc.org#endif  // HAVE_WEBRTC_VIDEO
2673