| OLD | NEW | 
 | (Empty) | 
|     1 /* |  | 
|     2  * libjingle |  | 
|     3  * Copyright 2014 Google Inc. |  | 
|     4  * |  | 
|     5  * Redistribution and use in source and binary forms, with or without |  | 
|     6  * modification, are permitted provided that the following conditions are met: |  | 
|     7  * |  | 
|     8  *  1. Redistributions of source code must retain the above copyright notice, |  | 
|     9  *     this list of conditions and the following disclaimer. |  | 
|    10  *  2. Redistributions in binary form must reproduce the above copyright notice, |  | 
|    11  *     this list of conditions and the following disclaimer in the documentation |  | 
|    12  *     and/or other materials provided with the distribution. |  | 
|    13  *  3. The name of the author may not be used to endorse or promote products |  | 
|    14  *     derived from this software without specific prior written permission. |  | 
|    15  * |  | 
|    16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED |  | 
|    17  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |  | 
|    18  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |  | 
|    19  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |  | 
|    20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |  | 
|    21  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |  | 
|    22  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |  | 
|    23  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR |  | 
|    24  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |  | 
|    25  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |  | 
|    26  */ |  | 
|    27  |  | 
|    28 #ifdef HAVE_WEBRTC_VIDEO |  | 
|    29 #include "talk/media/webrtc/webrtcvideoengine2.h" |  | 
|    30  |  | 
|    31 #include <algorithm> |  | 
|    32 #include <set> |  | 
|    33 #include <string> |  | 
|    34  |  | 
|    35 #include "talk/media/base/videocapturer.h" |  | 
|    36 #include "talk/media/base/videorenderer.h" |  | 
|    37 #include "talk/media/webrtc/constants.h" |  | 
|    38 #include "talk/media/webrtc/simulcast.h" |  | 
|    39 #include "talk/media/webrtc/webrtcmediaengine.h" |  | 
|    40 #include "talk/media/webrtc/webrtcvideoencoderfactory.h" |  | 
|    41 #include "talk/media/webrtc/webrtcvideoframe.h" |  | 
|    42 #include "talk/media/webrtc/webrtcvoiceengine.h" |  | 
|    43 #include "webrtc/base/buffer.h" |  | 
|    44 #include "webrtc/base/logging.h" |  | 
|    45 #include "webrtc/base/stringutils.h" |  | 
|    46 #include "webrtc/base/timeutils.h" |  | 
|    47 #include "webrtc/base/trace_event.h" |  | 
|    48 #include "webrtc/call.h" |  | 
|    49 #include "webrtc/modules/video_coding/codecs/h264/include/h264.h" |  | 
|    50 #include "webrtc/modules/video_coding/codecs/vp8/simulcast_encoder_adapter.h" |  | 
|    51 #include "webrtc/system_wrappers/include/field_trial.h" |  | 
|    52 #include "webrtc/video_decoder.h" |  | 
|    53 #include "webrtc/video_encoder.h" |  | 
|    54  |  | 
|    55 namespace cricket { |  | 
|    56 namespace { |  | 
|    57  |  | 
|    58 // Wrap cricket::WebRtcVideoEncoderFactory as a webrtc::VideoEncoderFactory. |  | 
|    59 class EncoderFactoryAdapter : public webrtc::VideoEncoderFactory { |  | 
|    60  public: |  | 
|    61   // EncoderFactoryAdapter doesn't take ownership of |factory|, which is owned |  | 
|    62   // by e.g. PeerConnectionFactory. |  | 
|    63   explicit EncoderFactoryAdapter(cricket::WebRtcVideoEncoderFactory* factory) |  | 
|    64       : factory_(factory) {} |  | 
|    65   virtual ~EncoderFactoryAdapter() {} |  | 
|    66  |  | 
|    67   // Implement webrtc::VideoEncoderFactory. |  | 
|    68   webrtc::VideoEncoder* Create() override { |  | 
|    69     return factory_->CreateVideoEncoder(webrtc::kVideoCodecVP8); |  | 
|    70   } |  | 
|    71  |  | 
|    72   void Destroy(webrtc::VideoEncoder* encoder) override { |  | 
|    73     return factory_->DestroyVideoEncoder(encoder); |  | 
|    74   } |  | 
|    75  |  | 
|    76  private: |  | 
|    77   cricket::WebRtcVideoEncoderFactory* const factory_; |  | 
|    78 }; |  | 
|    79  |  | 
|    80 // An encoder factory that wraps Create requests for simulcastable codec types |  | 
|    81 // with a webrtc::SimulcastEncoderAdapter. Non simulcastable codec type |  | 
|    82 // requests are just passed through to the contained encoder factory. |  | 
|    83 class WebRtcSimulcastEncoderFactory |  | 
|    84     : public cricket::WebRtcVideoEncoderFactory { |  | 
|    85  public: |  | 
|    86   // WebRtcSimulcastEncoderFactory doesn't take ownership of |factory|, which is |  | 
|    87   // owned by e.g. PeerConnectionFactory. |  | 
|    88   explicit WebRtcSimulcastEncoderFactory( |  | 
|    89       cricket::WebRtcVideoEncoderFactory* factory) |  | 
|    90       : factory_(factory) {} |  | 
|    91  |  | 
|    92   static bool UseSimulcastEncoderFactory( |  | 
|    93       const std::vector<VideoCodec>& codecs) { |  | 
|    94     // If any codec is VP8, use the simulcast factory. If asked to create a |  | 
|    95     // non-VP8 codec, we'll just return a contained factory encoder directly. |  | 
|    96     for (const auto& codec : codecs) { |  | 
|    97       if (codec.type == webrtc::kVideoCodecVP8) { |  | 
|    98         return true; |  | 
|    99       } |  | 
|   100     } |  | 
|   101     return false; |  | 
|   102   } |  | 
|   103  |  | 
|   104   webrtc::VideoEncoder* CreateVideoEncoder( |  | 
|   105       webrtc::VideoCodecType type) override { |  | 
|   106     RTC_DCHECK(factory_ != NULL); |  | 
|   107     // If it's a codec type we can simulcast, create a wrapped encoder. |  | 
|   108     if (type == webrtc::kVideoCodecVP8) { |  | 
|   109       return new webrtc::SimulcastEncoderAdapter( |  | 
|   110           new EncoderFactoryAdapter(factory_)); |  | 
|   111     } |  | 
|   112     webrtc::VideoEncoder* encoder = factory_->CreateVideoEncoder(type); |  | 
|   113     if (encoder) { |  | 
|   114       non_simulcast_encoders_.push_back(encoder); |  | 
|   115     } |  | 
|   116     return encoder; |  | 
|   117   } |  | 
|   118  |  | 
|   119   const std::vector<VideoCodec>& codecs() const override { |  | 
|   120     return factory_->codecs(); |  | 
|   121   } |  | 
|   122  |  | 
|   123   bool EncoderTypeHasInternalSource( |  | 
|   124       webrtc::VideoCodecType type) const override { |  | 
|   125     return factory_->EncoderTypeHasInternalSource(type); |  | 
|   126   } |  | 
|   127  |  | 
|   128   void DestroyVideoEncoder(webrtc::VideoEncoder* encoder) override { |  | 
|   129     // Check first to see if the encoder wasn't wrapped in a |  | 
|   130     // SimulcastEncoderAdapter. In that case, ask the factory to destroy it. |  | 
|   131     if (std::remove(non_simulcast_encoders_.begin(), |  | 
|   132                     non_simulcast_encoders_.end(), |  | 
|   133                     encoder) != non_simulcast_encoders_.end()) { |  | 
|   134       factory_->DestroyVideoEncoder(encoder); |  | 
|   135       return; |  | 
|   136     } |  | 
|   137  |  | 
|   138     // Otherwise, SimulcastEncoderAdapter can be deleted directly, and will call |  | 
|   139     // DestroyVideoEncoder on the factory for individual encoder instances. |  | 
|   140     delete encoder; |  | 
|   141   } |  | 
|   142  |  | 
|   143  private: |  | 
|   144   cricket::WebRtcVideoEncoderFactory* factory_; |  | 
|   145   // A list of encoders that were created without being wrapped in a |  | 
|   146   // SimulcastEncoderAdapter. |  | 
|   147   std::vector<webrtc::VideoEncoder*> non_simulcast_encoders_; |  | 
|   148 }; |  | 
|   149  |  | 
|   150 bool CodecIsInternallySupported(const std::string& codec_name) { |  | 
|   151   if (CodecNamesEq(codec_name, kVp8CodecName)) { |  | 
|   152     return true; |  | 
|   153   } |  | 
|   154   if (CodecNamesEq(codec_name, kVp9CodecName)) { |  | 
|   155     return true; |  | 
|   156   } |  | 
|   157   if (CodecNamesEq(codec_name, kH264CodecName)) { |  | 
|   158     return webrtc::H264Encoder::IsSupported() && |  | 
|   159         webrtc::H264Decoder::IsSupported(); |  | 
|   160   } |  | 
|   161   return false; |  | 
|   162 } |  | 
|   163  |  | 
|   164 void AddDefaultFeedbackParams(VideoCodec* codec) { |  | 
|   165   codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamCcm, kRtcpFbCcmParamFir)); |  | 
|   166   codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamNack, kParamValueEmpty)); |  | 
|   167   codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamNack, kRtcpFbNackParamPli)); |  | 
|   168   codec->AddFeedbackParam(FeedbackParam(kRtcpFbParamRemb, kParamValueEmpty)); |  | 
|   169   codec->AddFeedbackParam( |  | 
|   170       FeedbackParam(kRtcpFbParamTransportCc, kParamValueEmpty)); |  | 
|   171 } |  | 
|   172  |  | 
|   173 static VideoCodec MakeVideoCodecWithDefaultFeedbackParams(int payload_type, |  | 
|   174                                                           const char* name) { |  | 
|   175   VideoCodec codec(payload_type, name, kDefaultVideoMaxWidth, |  | 
|   176                    kDefaultVideoMaxHeight, kDefaultVideoMaxFramerate, 0); |  | 
|   177   AddDefaultFeedbackParams(&codec); |  | 
|   178   return codec; |  | 
|   179 } |  | 
|   180  |  | 
|   181 static std::string CodecVectorToString(const std::vector<VideoCodec>& codecs) { |  | 
|   182   std::stringstream out; |  | 
|   183   out << '{'; |  | 
|   184   for (size_t i = 0; i < codecs.size(); ++i) { |  | 
|   185     out << codecs[i].ToString(); |  | 
|   186     if (i != codecs.size() - 1) { |  | 
|   187       out << ", "; |  | 
|   188     } |  | 
|   189   } |  | 
|   190   out << '}'; |  | 
|   191   return out.str(); |  | 
|   192 } |  | 
|   193  |  | 
|   194 static bool ValidateCodecFormats(const std::vector<VideoCodec>& codecs) { |  | 
|   195   bool has_video = false; |  | 
|   196   for (size_t i = 0; i < codecs.size(); ++i) { |  | 
|   197     if (!codecs[i].ValidateCodecFormat()) { |  | 
|   198       return false; |  | 
|   199     } |  | 
|   200     if (codecs[i].GetCodecType() == VideoCodec::CODEC_VIDEO) { |  | 
|   201       has_video = true; |  | 
|   202     } |  | 
|   203   } |  | 
|   204   if (!has_video) { |  | 
|   205     LOG(LS_ERROR) << "Setting codecs without a video codec is invalid: " |  | 
|   206                   << CodecVectorToString(codecs); |  | 
|   207     return false; |  | 
|   208   } |  | 
|   209   return true; |  | 
|   210 } |  | 
|   211  |  | 
|   212 static bool ValidateStreamParams(const StreamParams& sp) { |  | 
|   213   if (sp.ssrcs.empty()) { |  | 
|   214     LOG(LS_ERROR) << "No SSRCs in stream parameters: " << sp.ToString(); |  | 
|   215     return false; |  | 
|   216   } |  | 
|   217  |  | 
|   218   std::vector<uint32_t> primary_ssrcs; |  | 
|   219   sp.GetPrimarySsrcs(&primary_ssrcs); |  | 
|   220   std::vector<uint32_t> rtx_ssrcs; |  | 
|   221   sp.GetFidSsrcs(primary_ssrcs, &rtx_ssrcs); |  | 
|   222   for (uint32_t rtx_ssrc : rtx_ssrcs) { |  | 
|   223     bool rtx_ssrc_present = false; |  | 
|   224     for (uint32_t sp_ssrc : sp.ssrcs) { |  | 
|   225       if (sp_ssrc == rtx_ssrc) { |  | 
|   226         rtx_ssrc_present = true; |  | 
|   227         break; |  | 
|   228       } |  | 
|   229     } |  | 
|   230     if (!rtx_ssrc_present) { |  | 
|   231       LOG(LS_ERROR) << "RTX SSRC '" << rtx_ssrc |  | 
|   232                     << "' missing from StreamParams ssrcs: " << sp.ToString(); |  | 
|   233       return false; |  | 
|   234     } |  | 
|   235   } |  | 
|   236   if (!rtx_ssrcs.empty() && primary_ssrcs.size() != rtx_ssrcs.size()) { |  | 
|   237     LOG(LS_ERROR) |  | 
|   238         << "RTX SSRCs exist, but don't cover all SSRCs (unsupported): " |  | 
|   239         << sp.ToString(); |  | 
|   240     return false; |  | 
|   241   } |  | 
|   242  |  | 
|   243   return true; |  | 
|   244 } |  | 
|   245  |  | 
|   246 inline const webrtc::RtpExtension* FindHeaderExtension( |  | 
|   247     const std::vector<webrtc::RtpExtension>& extensions, |  | 
|   248     const std::string& name) { |  | 
|   249   for (const auto& kv : extensions) { |  | 
|   250     if (kv.name == name) { |  | 
|   251       return &kv; |  | 
|   252     } |  | 
|   253   } |  | 
|   254   return NULL; |  | 
|   255 } |  | 
|   256  |  | 
|   257 // Merges two fec configs and logs an error if a conflict arises |  | 
|   258 // such that merging in different order would trigger a different output. |  | 
|   259 static void MergeFecConfig(const webrtc::FecConfig& other, |  | 
|   260                            webrtc::FecConfig* output) { |  | 
|   261   if (other.ulpfec_payload_type != -1) { |  | 
|   262     if (output->ulpfec_payload_type != -1 && |  | 
|   263         output->ulpfec_payload_type != other.ulpfec_payload_type) { |  | 
|   264       LOG(LS_WARNING) << "Conflict merging ulpfec_payload_type configs: " |  | 
|   265                       << output->ulpfec_payload_type << " and " |  | 
|   266                       << other.ulpfec_payload_type; |  | 
|   267     } |  | 
|   268     output->ulpfec_payload_type = other.ulpfec_payload_type; |  | 
|   269   } |  | 
|   270   if (other.red_payload_type != -1) { |  | 
|   271     if (output->red_payload_type != -1 && |  | 
|   272         output->red_payload_type != other.red_payload_type) { |  | 
|   273       LOG(LS_WARNING) << "Conflict merging red_payload_type configs: " |  | 
|   274                       << output->red_payload_type << " and " |  | 
|   275                       << other.red_payload_type; |  | 
|   276     } |  | 
|   277     output->red_payload_type = other.red_payload_type; |  | 
|   278   } |  | 
|   279   if (other.red_rtx_payload_type != -1) { |  | 
|   280     if (output->red_rtx_payload_type != -1 && |  | 
|   281         output->red_rtx_payload_type != other.red_rtx_payload_type) { |  | 
|   282       LOG(LS_WARNING) << "Conflict merging red_rtx_payload_type configs: " |  | 
|   283                       << output->red_rtx_payload_type << " and " |  | 
|   284                       << other.red_rtx_payload_type; |  | 
|   285     } |  | 
|   286     output->red_rtx_payload_type = other.red_rtx_payload_type; |  | 
|   287   } |  | 
|   288 } |  | 
|   289  |  | 
|   290 // Returns true if the given codec is disallowed from doing simulcast. |  | 
|   291 bool IsCodecBlacklistedForSimulcast(const std::string& codec_name) { |  | 
|   292   return CodecNamesEq(codec_name, kH264CodecName) || |  | 
|   293          CodecNamesEq(codec_name, kVp9CodecName); |  | 
|   294 } |  | 
|   295  |  | 
|   296 // The selected thresholds for QVGA and VGA corresponded to a QP around 10. |  | 
|   297 // The change in QP declined above the selected bitrates. |  | 
|   298 static int GetMaxDefaultVideoBitrateKbps(int width, int height) { |  | 
|   299   if (width * height <= 320 * 240) { |  | 
|   300     return 600; |  | 
|   301   } else if (width * height <= 640 * 480) { |  | 
|   302     return 1700; |  | 
|   303   } else if (width * height <= 960 * 540) { |  | 
|   304     return 2000; |  | 
|   305   } else { |  | 
|   306     return 2500; |  | 
|   307   } |  | 
|   308 } |  | 
|   309 }  // namespace |  | 
|   310  |  | 
|   311 // Constants defined in talk/media/webrtc/constants.h |  | 
|   312 // TODO(pbos): Move these to a separate constants.cc file. |  | 
|   313 const int kMinVideoBitrate = 30; |  | 
|   314 const int kStartVideoBitrate = 300; |  | 
|   315  |  | 
|   316 const int kVideoMtu = 1200; |  | 
|   317 const int kVideoRtpBufferSize = 65536; |  | 
|   318  |  | 
|   319 // This constant is really an on/off, lower-level configurable NACK history |  | 
|   320 // duration hasn't been implemented. |  | 
|   321 static const int kNackHistoryMs = 1000; |  | 
|   322  |  | 
|   323 static const int kDefaultQpMax = 56; |  | 
|   324  |  | 
|   325 static const int kDefaultRtcpReceiverReportSsrc = 1; |  | 
|   326  |  | 
|   327 std::vector<VideoCodec> DefaultVideoCodecList() { |  | 
|   328   std::vector<VideoCodec> codecs; |  | 
|   329   codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultVp8PlType, |  | 
|   330                                                            kVp8CodecName)); |  | 
|   331   if (CodecIsInternallySupported(kVp9CodecName)) { |  | 
|   332     codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultVp9PlType, |  | 
|   333                                                              kVp9CodecName)); |  | 
|   334     // TODO(andresp): Add rtx codec for vp9 and verify it works. |  | 
|   335   } |  | 
|   336   if (CodecIsInternallySupported(kH264CodecName)) { |  | 
|   337     codecs.push_back(MakeVideoCodecWithDefaultFeedbackParams(kDefaultH264PlType, |  | 
|   338                                                              kH264CodecName)); |  | 
|   339   } |  | 
|   340   codecs.push_back( |  | 
|   341       VideoCodec::CreateRtxCodec(kDefaultRtxVp8PlType, kDefaultVp8PlType)); |  | 
|   342   codecs.push_back(VideoCodec(kDefaultRedPlType, kRedCodecName)); |  | 
|   343   codecs.push_back(VideoCodec(kDefaultUlpfecType, kUlpfecCodecName)); |  | 
|   344   return codecs; |  | 
|   345 } |  | 
|   346  |  | 
|   347 std::vector<webrtc::VideoStream> |  | 
|   348 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateSimulcastVideoStreams( |  | 
|   349     const VideoCodec& codec, |  | 
|   350     const VideoOptions& options, |  | 
|   351     int max_bitrate_bps, |  | 
|   352     size_t num_streams) { |  | 
|   353   int max_qp = kDefaultQpMax; |  | 
|   354   codec.GetParam(kCodecParamMaxQuantization, &max_qp); |  | 
|   355  |  | 
|   356   return GetSimulcastConfig( |  | 
|   357       num_streams, codec.width, codec.height, max_bitrate_bps, max_qp, |  | 
|   358       codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate); |  | 
|   359 } |  | 
|   360  |  | 
|   361 std::vector<webrtc::VideoStream> |  | 
|   362 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoStreams( |  | 
|   363     const VideoCodec& codec, |  | 
|   364     const VideoOptions& options, |  | 
|   365     int max_bitrate_bps, |  | 
|   366     size_t num_streams) { |  | 
|   367   int codec_max_bitrate_kbps; |  | 
|   368   if (codec.GetParam(kCodecParamMaxBitrate, &codec_max_bitrate_kbps)) { |  | 
|   369     max_bitrate_bps = codec_max_bitrate_kbps * 1000; |  | 
|   370   } |  | 
|   371   if (num_streams != 1) { |  | 
|   372     return CreateSimulcastVideoStreams(codec, options, max_bitrate_bps, |  | 
|   373                                        num_streams); |  | 
|   374   } |  | 
|   375  |  | 
|   376   // For unset max bitrates set default bitrate for non-simulcast. |  | 
|   377   if (max_bitrate_bps <= 0) { |  | 
|   378     max_bitrate_bps = |  | 
|   379         GetMaxDefaultVideoBitrateKbps(codec.width, codec.height) * 1000; |  | 
|   380   } |  | 
|   381  |  | 
|   382   webrtc::VideoStream stream; |  | 
|   383   stream.width = codec.width; |  | 
|   384   stream.height = codec.height; |  | 
|   385   stream.max_framerate = |  | 
|   386       codec.framerate != 0 ? codec.framerate : kDefaultVideoMaxFramerate; |  | 
|   387  |  | 
|   388   stream.min_bitrate_bps = kMinVideoBitrate * 1000; |  | 
|   389   stream.target_bitrate_bps = stream.max_bitrate_bps = max_bitrate_bps; |  | 
|   390  |  | 
|   391   int max_qp = kDefaultQpMax; |  | 
|   392   codec.GetParam(kCodecParamMaxQuantization, &max_qp); |  | 
|   393   stream.max_qp = max_qp; |  | 
|   394   std::vector<webrtc::VideoStream> streams; |  | 
|   395   streams.push_back(stream); |  | 
|   396   return streams; |  | 
|   397 } |  | 
|   398  |  | 
|   399 void* WebRtcVideoChannel2::WebRtcVideoSendStream::ConfigureVideoEncoderSettings( |  | 
|   400     const VideoCodec& codec, |  | 
|   401     const VideoOptions& options, |  | 
|   402     bool is_screencast) { |  | 
|   403   // No automatic resizing when using simulcast or screencast. |  | 
|   404   bool automatic_resize = |  | 
|   405       !is_screencast && parameters_.config.rtp.ssrcs.size() == 1; |  | 
|   406   bool frame_dropping = !is_screencast; |  | 
|   407   bool denoising; |  | 
|   408   bool codec_default_denoising = false; |  | 
|   409   if (is_screencast) { |  | 
|   410     denoising = false; |  | 
|   411   } else { |  | 
|   412     // Use codec default if video_noise_reduction is unset. |  | 
|   413     codec_default_denoising = !options.video_noise_reduction; |  | 
|   414     denoising = options.video_noise_reduction.value_or(false); |  | 
|   415   } |  | 
|   416  |  | 
|   417   if (CodecNamesEq(codec.name, kVp8CodecName)) { |  | 
|   418     encoder_settings_.vp8 = webrtc::VideoEncoder::GetDefaultVp8Settings(); |  | 
|   419     encoder_settings_.vp8.automaticResizeOn = automatic_resize; |  | 
|   420     // VP8 denoising is enabled by default. |  | 
|   421     encoder_settings_.vp8.denoisingOn = |  | 
|   422         codec_default_denoising ? true : denoising; |  | 
|   423     encoder_settings_.vp8.frameDroppingOn = frame_dropping; |  | 
|   424     return &encoder_settings_.vp8; |  | 
|   425   } |  | 
|   426   if (CodecNamesEq(codec.name, kVp9CodecName)) { |  | 
|   427     encoder_settings_.vp9 = webrtc::VideoEncoder::GetDefaultVp9Settings(); |  | 
|   428     // VP9 denoising is disabled by default. |  | 
|   429     encoder_settings_.vp9.denoisingOn = |  | 
|   430         codec_default_denoising ? false : denoising; |  | 
|   431     encoder_settings_.vp9.frameDroppingOn = frame_dropping; |  | 
|   432     return &encoder_settings_.vp9; |  | 
|   433   } |  | 
|   434   return NULL; |  | 
|   435 } |  | 
|   436  |  | 
|   437 DefaultUnsignalledSsrcHandler::DefaultUnsignalledSsrcHandler() |  | 
|   438     : default_recv_ssrc_(0), default_renderer_(NULL) {} |  | 
|   439  |  | 
|   440 UnsignalledSsrcHandler::Action DefaultUnsignalledSsrcHandler::OnUnsignalledSsrc( |  | 
|   441     WebRtcVideoChannel2* channel, |  | 
|   442     uint32_t ssrc) { |  | 
|   443   if (default_recv_ssrc_ != 0) {  // Already one default stream. |  | 
|   444     LOG(LS_WARNING) << "Unknown SSRC, but default receive stream already set."; |  | 
|   445     return kDropPacket; |  | 
|   446   } |  | 
|   447  |  | 
|   448   StreamParams sp; |  | 
|   449   sp.ssrcs.push_back(ssrc); |  | 
|   450   LOG(LS_INFO) << "Creating default receive stream for SSRC=" << ssrc << "."; |  | 
|   451   if (!channel->AddRecvStream(sp, true)) { |  | 
|   452     LOG(LS_WARNING) << "Could not create default receive stream."; |  | 
|   453   } |  | 
|   454  |  | 
|   455   channel->SetRenderer(ssrc, default_renderer_); |  | 
|   456   default_recv_ssrc_ = ssrc; |  | 
|   457   return kDeliverPacket; |  | 
|   458 } |  | 
|   459  |  | 
|   460 VideoRenderer* DefaultUnsignalledSsrcHandler::GetDefaultRenderer() const { |  | 
|   461   return default_renderer_; |  | 
|   462 } |  | 
|   463  |  | 
|   464 void DefaultUnsignalledSsrcHandler::SetDefaultRenderer( |  | 
|   465     VideoMediaChannel* channel, |  | 
|   466     VideoRenderer* renderer) { |  | 
|   467   default_renderer_ = renderer; |  | 
|   468   if (default_recv_ssrc_ != 0) { |  | 
|   469     channel->SetRenderer(default_recv_ssrc_, default_renderer_); |  | 
|   470   } |  | 
|   471 } |  | 
|   472  |  | 
|   473 WebRtcVideoEngine2::WebRtcVideoEngine2() |  | 
|   474     : initialized_(false), |  | 
|   475       external_decoder_factory_(NULL), |  | 
|   476       external_encoder_factory_(NULL) { |  | 
|   477   LOG(LS_INFO) << "WebRtcVideoEngine2::WebRtcVideoEngine2()"; |  | 
|   478   video_codecs_ = GetSupportedCodecs(); |  | 
|   479 } |  | 
|   480  |  | 
|   481 WebRtcVideoEngine2::~WebRtcVideoEngine2() { |  | 
|   482   LOG(LS_INFO) << "WebRtcVideoEngine2::~WebRtcVideoEngine2"; |  | 
|   483 } |  | 
|   484  |  | 
|   485 void WebRtcVideoEngine2::Init() { |  | 
|   486   LOG(LS_INFO) << "WebRtcVideoEngine2::Init"; |  | 
|   487   initialized_ = true; |  | 
|   488 } |  | 
|   489  |  | 
|   490 WebRtcVideoChannel2* WebRtcVideoEngine2::CreateChannel( |  | 
|   491     webrtc::Call* call, |  | 
|   492     const VideoOptions& options) { |  | 
|   493   RTC_DCHECK(initialized_); |  | 
|   494   LOG(LS_INFO) << "CreateChannel. Options: " << options.ToString(); |  | 
|   495   return new WebRtcVideoChannel2(call, options, video_codecs_, |  | 
|   496       external_encoder_factory_, external_decoder_factory_); |  | 
|   497 } |  | 
|   498  |  | 
|   499 const std::vector<VideoCodec>& WebRtcVideoEngine2::codecs() const { |  | 
|   500   return video_codecs_; |  | 
|   501 } |  | 
|   502  |  | 
|   503 RtpCapabilities WebRtcVideoEngine2::GetCapabilities() const { |  | 
|   504   RtpCapabilities capabilities; |  | 
|   505   capabilities.header_extensions.push_back( |  | 
|   506       RtpHeaderExtension(kRtpTimestampOffsetHeaderExtension, |  | 
|   507                          kRtpTimestampOffsetHeaderExtensionDefaultId)); |  | 
|   508   capabilities.header_extensions.push_back( |  | 
|   509       RtpHeaderExtension(kRtpAbsoluteSenderTimeHeaderExtension, |  | 
|   510                          kRtpAbsoluteSenderTimeHeaderExtensionDefaultId)); |  | 
|   511   capabilities.header_extensions.push_back( |  | 
|   512       RtpHeaderExtension(kRtpVideoRotationHeaderExtension, |  | 
|   513                          kRtpVideoRotationHeaderExtensionDefaultId)); |  | 
|   514   if (webrtc::field_trial::FindFullName("WebRTC-SendSideBwe") == "Enabled") { |  | 
|   515     capabilities.header_extensions.push_back(RtpHeaderExtension( |  | 
|   516         kRtpTransportSequenceNumberHeaderExtension, |  | 
|   517         kRtpTransportSequenceNumberHeaderExtensionDefaultId)); |  | 
|   518   } |  | 
|   519   return capabilities; |  | 
|   520 } |  | 
|   521  |  | 
|   522 void WebRtcVideoEngine2::SetExternalDecoderFactory( |  | 
|   523     WebRtcVideoDecoderFactory* decoder_factory) { |  | 
|   524   RTC_DCHECK(!initialized_); |  | 
|   525   external_decoder_factory_ = decoder_factory; |  | 
|   526 } |  | 
|   527  |  | 
|   528 void WebRtcVideoEngine2::SetExternalEncoderFactory( |  | 
|   529     WebRtcVideoEncoderFactory* encoder_factory) { |  | 
|   530   RTC_DCHECK(!initialized_); |  | 
|   531   if (external_encoder_factory_ == encoder_factory) |  | 
|   532     return; |  | 
|   533  |  | 
|   534   // No matter what happens we shouldn't hold on to a stale |  | 
|   535   // WebRtcSimulcastEncoderFactory. |  | 
|   536   simulcast_encoder_factory_.reset(); |  | 
|   537  |  | 
|   538   if (encoder_factory && |  | 
|   539       WebRtcSimulcastEncoderFactory::UseSimulcastEncoderFactory( |  | 
|   540           encoder_factory->codecs())) { |  | 
|   541     simulcast_encoder_factory_.reset( |  | 
|   542         new WebRtcSimulcastEncoderFactory(encoder_factory)); |  | 
|   543     encoder_factory = simulcast_encoder_factory_.get(); |  | 
|   544   } |  | 
|   545   external_encoder_factory_ = encoder_factory; |  | 
|   546  |  | 
|   547   video_codecs_ = GetSupportedCodecs(); |  | 
|   548 } |  | 
|   549  |  | 
|   550 bool WebRtcVideoEngine2::EnableTimedRender() { |  | 
|   551   // TODO(pbos): Figure out whether this can be removed. |  | 
|   552   return true; |  | 
|   553 } |  | 
|   554  |  | 
|   555 // Checks to see whether we comprehend and could receive a particular codec |  | 
|   556 bool WebRtcVideoEngine2::FindCodec(const VideoCodec& in) { |  | 
|   557   // TODO(pbos): Probe encoder factory to figure out that the codec is supported |  | 
|   558   // if supported by the encoder factory. Add a corresponding test that fails |  | 
|   559   // with this code (that doesn't ask the factory). |  | 
|   560   for (size_t j = 0; j < video_codecs_.size(); ++j) { |  | 
|   561     VideoCodec codec(video_codecs_[j].id, video_codecs_[j].name, 0, 0, 0, 0); |  | 
|   562     if (codec.Matches(in)) { |  | 
|   563       return true; |  | 
|   564     } |  | 
|   565   } |  | 
|   566   return false; |  | 
|   567 } |  | 
|   568  |  | 
|   569 // Ignore spammy trace messages, mostly from the stats API when we haven't |  | 
|   570 // gotten RTCP info yet from the remote side. |  | 
|   571 bool WebRtcVideoEngine2::ShouldIgnoreTrace(const std::string& trace) { |  | 
|   572   static const char* const kTracesToIgnore[] = {NULL}; |  | 
|   573   for (const char* const* p = kTracesToIgnore; *p; ++p) { |  | 
|   574     if (trace.find(*p) == 0) { |  | 
|   575       return true; |  | 
|   576     } |  | 
|   577   } |  | 
|   578   return false; |  | 
|   579 } |  | 
|   580  |  | 
|   581 std::vector<VideoCodec> WebRtcVideoEngine2::GetSupportedCodecs() const { |  | 
|   582   std::vector<VideoCodec> supported_codecs = DefaultVideoCodecList(); |  | 
|   583  |  | 
|   584   if (external_encoder_factory_ == NULL) { |  | 
|   585     return supported_codecs; |  | 
|   586   } |  | 
|   587  |  | 
|   588   const std::vector<WebRtcVideoEncoderFactory::VideoCodec>& codecs = |  | 
|   589       external_encoder_factory_->codecs(); |  | 
|   590   for (size_t i = 0; i < codecs.size(); ++i) { |  | 
|   591     // Don't add internally-supported codecs twice. |  | 
|   592     if (CodecIsInternallySupported(codecs[i].name)) { |  | 
|   593       continue; |  | 
|   594     } |  | 
|   595  |  | 
|   596     // External video encoders are given payloads 120-127. This also means that |  | 
|   597     // we only support up to 8 external payload types. |  | 
|   598     const int kExternalVideoPayloadTypeBase = 120; |  | 
|   599     size_t payload_type = kExternalVideoPayloadTypeBase + i; |  | 
|   600     RTC_DCHECK(payload_type < 128); |  | 
|   601     VideoCodec codec(static_cast<int>(payload_type), |  | 
|   602                      codecs[i].name, |  | 
|   603                      codecs[i].max_width, |  | 
|   604                      codecs[i].max_height, |  | 
|   605                      codecs[i].max_fps, |  | 
|   606                      0); |  | 
|   607  |  | 
|   608     AddDefaultFeedbackParams(&codec); |  | 
|   609     supported_codecs.push_back(codec); |  | 
|   610   } |  | 
|   611   return supported_codecs; |  | 
|   612 } |  | 
|   613  |  | 
|   614 WebRtcVideoChannel2::WebRtcVideoChannel2( |  | 
|   615     webrtc::Call* call, |  | 
|   616     const VideoOptions& options, |  | 
|   617     const std::vector<VideoCodec>& recv_codecs, |  | 
|   618     WebRtcVideoEncoderFactory* external_encoder_factory, |  | 
|   619     WebRtcVideoDecoderFactory* external_decoder_factory) |  | 
|   620     : call_(call), |  | 
|   621       unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_), |  | 
|   622       external_encoder_factory_(external_encoder_factory), |  | 
|   623       external_decoder_factory_(external_decoder_factory) { |  | 
|   624   RTC_DCHECK(thread_checker_.CalledOnValidThread()); |  | 
|   625   SetDefaultOptions(); |  | 
|   626   options_.SetAll(options); |  | 
|   627   if (options_.cpu_overuse_detection) |  | 
|   628     signal_cpu_adaptation_ = *options_.cpu_overuse_detection; |  | 
|   629   rtcp_receiver_report_ssrc_ = kDefaultRtcpReceiverReportSsrc; |  | 
|   630   sending_ = false; |  | 
|   631   default_send_ssrc_ = 0; |  | 
|   632   SetRecvCodecs(recv_codecs); |  | 
|   633 } |  | 
|   634  |  | 
|   635 void WebRtcVideoChannel2::SetDefaultOptions() { |  | 
|   636   options_.cpu_overuse_detection = rtc::Optional<bool>(true); |  | 
|   637   options_.dscp = rtc::Optional<bool>(false); |  | 
|   638   options_.suspend_below_min_bitrate = rtc::Optional<bool>(false); |  | 
|   639   options_.screencast_min_bitrate = rtc::Optional<int>(0); |  | 
|   640 } |  | 
|   641  |  | 
|   642 WebRtcVideoChannel2::~WebRtcVideoChannel2() { |  | 
|   643   for (auto& kv : send_streams_) |  | 
|   644     delete kv.second; |  | 
|   645   for (auto& kv : receive_streams_) |  | 
|   646     delete kv.second; |  | 
|   647 } |  | 
|   648  |  | 
|   649 bool WebRtcVideoChannel2::CodecIsExternallySupported( |  | 
|   650     const std::string& name) const { |  | 
|   651   if (external_encoder_factory_ == NULL) { |  | 
|   652     return false; |  | 
|   653   } |  | 
|   654  |  | 
|   655   const std::vector<WebRtcVideoEncoderFactory::VideoCodec> external_codecs = |  | 
|   656       external_encoder_factory_->codecs(); |  | 
|   657   for (size_t c = 0; c < external_codecs.size(); ++c) { |  | 
|   658     if (CodecNamesEq(name, external_codecs[c].name)) { |  | 
|   659       return true; |  | 
|   660     } |  | 
|   661   } |  | 
|   662   return false; |  | 
|   663 } |  | 
|   664  |  | 
|   665 std::vector<WebRtcVideoChannel2::VideoCodecSettings> |  | 
|   666 WebRtcVideoChannel2::FilterSupportedCodecs( |  | 
|   667     const std::vector<WebRtcVideoChannel2::VideoCodecSettings>& mapped_codecs) |  | 
|   668     const { |  | 
|   669   std::vector<VideoCodecSettings> supported_codecs; |  | 
|   670   for (size_t i = 0; i < mapped_codecs.size(); ++i) { |  | 
|   671     const VideoCodecSettings& codec = mapped_codecs[i]; |  | 
|   672     if (CodecIsInternallySupported(codec.codec.name) || |  | 
|   673         CodecIsExternallySupported(codec.codec.name)) { |  | 
|   674       supported_codecs.push_back(codec); |  | 
|   675     } |  | 
|   676   } |  | 
|   677   return supported_codecs; |  | 
|   678 } |  | 
|   679  |  | 
|   680 bool WebRtcVideoChannel2::ReceiveCodecsHaveChanged( |  | 
|   681     std::vector<VideoCodecSettings> before, |  | 
|   682     std::vector<VideoCodecSettings> after) { |  | 
|   683   if (before.size() != after.size()) { |  | 
|   684     return true; |  | 
|   685   } |  | 
|   686   // The receive codec order doesn't matter, so we sort the codecs before |  | 
|   687   // comparing. This is necessary because currently the |  | 
|   688   // only way to change the send codec is to munge SDP, which causes |  | 
|   689   // the receive codec list to change order, which causes the streams |  | 
|   690   // to be recreates which causes a "blink" of black video.  In order |  | 
|   691   // to support munging the SDP in this way without recreating receive |  | 
|   692   // streams, we ignore the order of the received codecs so that |  | 
|   693   // changing the order doesn't cause this "blink". |  | 
|   694   auto comparison = |  | 
|   695       [](const VideoCodecSettings& codec1, const VideoCodecSettings& codec2) { |  | 
|   696         return codec1.codec.id > codec2.codec.id; |  | 
|   697       }; |  | 
|   698   std::sort(before.begin(), before.end(), comparison); |  | 
|   699   std::sort(after.begin(), after.end(), comparison); |  | 
|   700   for (size_t i = 0; i < before.size(); ++i) { |  | 
|   701     // For the same reason that we sort the codecs, we also ignore the |  | 
|   702     // preference.  We don't want a preference change on the receive |  | 
|   703     // side to cause recreation of the stream. |  | 
|   704     before[i].codec.preference = 0; |  | 
|   705     after[i].codec.preference = 0; |  | 
|   706     if (before[i] != after[i]) { |  | 
|   707       return true; |  | 
|   708     } |  | 
|   709   } |  | 
|   710   return false; |  | 
|   711 } |  | 
|   712  |  | 
|   713 bool WebRtcVideoChannel2::SetSendParameters(const VideoSendParameters& params) { |  | 
|   714   TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetSendParameters"); |  | 
|   715   LOG(LS_INFO) << "SetSendParameters: " << params.ToString(); |  | 
|   716   // TODO(pbos): Refactor this to only recreate the send streams once |  | 
|   717   // instead of 4 times. |  | 
|   718   if (!SetSendCodecs(params.codecs) || |  | 
|   719       !SetSendRtpHeaderExtensions(params.extensions) || |  | 
|   720       !SetMaxSendBandwidth(params.max_bandwidth_bps) || |  | 
|   721       !SetOptions(params.options)) { |  | 
|   722     return false; |  | 
|   723   } |  | 
|   724   if (send_params_.rtcp.reduced_size != params.rtcp.reduced_size) { |  | 
|   725     rtc::CritScope stream_lock(&stream_crit_); |  | 
|   726     for (auto& kv : send_streams_) { |  | 
|   727       kv.second->SetSendParameters(params); |  | 
|   728     } |  | 
|   729   } |  | 
|   730   send_params_ = params; |  | 
|   731   return true; |  | 
|   732 } |  | 
|   733  |  | 
|   734 bool WebRtcVideoChannel2::SetRecvParameters(const VideoRecvParameters& params) { |  | 
|   735   TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetRecvParameters"); |  | 
|   736   LOG(LS_INFO) << "SetRecvParameters: " << params.ToString(); |  | 
|   737   // TODO(pbos): Refactor this to only recreate the recv streams once |  | 
|   738   // instead of twice. |  | 
|   739   if (!SetRecvCodecs(params.codecs) || |  | 
|   740       !SetRecvRtpHeaderExtensions(params.extensions)) { |  | 
|   741     return false; |  | 
|   742   } |  | 
|   743   if (recv_params_.rtcp.reduced_size != params.rtcp.reduced_size) { |  | 
|   744     rtc::CritScope stream_lock(&stream_crit_); |  | 
|   745     for (auto& kv : receive_streams_) { |  | 
|   746       kv.second->SetRecvParameters(params); |  | 
|   747     } |  | 
|   748   } |  | 
|   749   recv_params_ = params; |  | 
|   750   return true; |  | 
|   751 } |  | 
|   752  |  | 
|   753 std::string WebRtcVideoChannel2::CodecSettingsVectorToString( |  | 
|   754     const std::vector<VideoCodecSettings>& codecs) { |  | 
|   755   std::stringstream out; |  | 
|   756   out << '{'; |  | 
|   757   for (size_t i = 0; i < codecs.size(); ++i) { |  | 
|   758     out << codecs[i].codec.ToString(); |  | 
|   759     if (i != codecs.size() - 1) { |  | 
|   760       out << ", "; |  | 
|   761     } |  | 
|   762   } |  | 
|   763   out << '}'; |  | 
|   764   return out.str(); |  | 
|   765 } |  | 
|   766  |  | 
|   767 bool WebRtcVideoChannel2::SetRecvCodecs(const std::vector<VideoCodec>& codecs) { |  | 
|   768   TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetRecvCodecs"); |  | 
|   769   LOG(LS_INFO) << "SetRecvCodecs: " << CodecVectorToString(codecs); |  | 
|   770   if (!ValidateCodecFormats(codecs)) { |  | 
|   771     return false; |  | 
|   772   } |  | 
|   773  |  | 
|   774   const std::vector<VideoCodecSettings> mapped_codecs = MapCodecs(codecs); |  | 
|   775   if (mapped_codecs.empty()) { |  | 
|   776     LOG(LS_ERROR) << "SetRecvCodecs called without any video codecs."; |  | 
|   777     return false; |  | 
|   778   } |  | 
|   779  |  | 
|   780   std::vector<VideoCodecSettings> supported_codecs = |  | 
|   781       FilterSupportedCodecs(mapped_codecs); |  | 
|   782  |  | 
|   783   if (mapped_codecs.size() != supported_codecs.size()) { |  | 
|   784     LOG(LS_ERROR) << "SetRecvCodecs called with unsupported video codecs."; |  | 
|   785     return false; |  | 
|   786   } |  | 
|   787  |  | 
|   788   // Prevent reconfiguration when setting identical receive codecs. |  | 
|   789   if (!ReceiveCodecsHaveChanged(recv_codecs_, supported_codecs)) { |  | 
|   790     LOG(LS_INFO) |  | 
|   791         << "Ignoring call to SetRecvCodecs because codecs haven't changed."; |  | 
|   792     return true; |  | 
|   793   } |  | 
|   794  |  | 
|   795   LOG(LS_INFO) << "Changing recv codecs from " |  | 
|   796                << CodecSettingsVectorToString(recv_codecs_) << " to " |  | 
|   797                << CodecSettingsVectorToString(supported_codecs); |  | 
|   798   recv_codecs_ = supported_codecs; |  | 
|   799  |  | 
|   800   rtc::CritScope stream_lock(&stream_crit_); |  | 
|   801   for (std::map<uint32_t, WebRtcVideoReceiveStream*>::iterator it = |  | 
|   802            receive_streams_.begin(); |  | 
|   803        it != receive_streams_.end(); ++it) { |  | 
|   804     it->second->SetRecvCodecs(recv_codecs_); |  | 
|   805   } |  | 
|   806  |  | 
|   807   return true; |  | 
|   808 } |  | 
|   809  |  | 
|   810 bool WebRtcVideoChannel2::SetSendCodecs(const std::vector<VideoCodec>& codecs) { |  | 
|   811   TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetSendCodecs"); |  | 
|   812   LOG(LS_INFO) << "SetSendCodecs: " << CodecVectorToString(codecs); |  | 
|   813   if (!ValidateCodecFormats(codecs)) { |  | 
|   814     return false; |  | 
|   815   } |  | 
|   816  |  | 
|   817   const std::vector<VideoCodecSettings> supported_codecs = |  | 
|   818       FilterSupportedCodecs(MapCodecs(codecs)); |  | 
|   819  |  | 
|   820   if (supported_codecs.empty()) { |  | 
|   821     LOG(LS_ERROR) << "No video codecs supported."; |  | 
|   822     return false; |  | 
|   823   } |  | 
|   824  |  | 
|   825   LOG(LS_INFO) << "Using codec: " << supported_codecs.front().codec.ToString(); |  | 
|   826  |  | 
|   827   if (send_codec_ && supported_codecs.front() == *send_codec_) { |  | 
|   828     LOG(LS_INFO) << "Ignore call to SetSendCodecs because first supported " |  | 
|   829                     "codec hasn't changed."; |  | 
|   830     // Using same codec, avoid reconfiguring. |  | 
|   831     return true; |  | 
|   832   } |  | 
|   833  |  | 
|   834   send_codec_ = rtc::Optional<WebRtcVideoChannel2::VideoCodecSettings>( |  | 
|   835       supported_codecs.front()); |  | 
|   836  |  | 
|   837   rtc::CritScope stream_lock(&stream_crit_); |  | 
|   838   LOG(LS_INFO) << "Change the send codec because SetSendCodecs has a different " |  | 
|   839                   "first supported codec."; |  | 
|   840   for (auto& kv : send_streams_) { |  | 
|   841     RTC_DCHECK(kv.second != nullptr); |  | 
|   842     kv.second->SetCodec(supported_codecs.front()); |  | 
|   843   } |  | 
|   844   LOG(LS_INFO) |  | 
|   845       << "SetFeedbackOptions on all the receive streams because the send " |  | 
|   846          "codec has changed."; |  | 
|   847   for (auto& kv : receive_streams_) { |  | 
|   848     RTC_DCHECK(kv.second != nullptr); |  | 
|   849     kv.second->SetFeedbackParameters( |  | 
|   850         HasNack(supported_codecs.front().codec), |  | 
|   851         HasRemb(supported_codecs.front().codec), |  | 
|   852         HasTransportCc(supported_codecs.front().codec)); |  | 
|   853   } |  | 
|   854  |  | 
|   855   // TODO(holmer): Changing the codec parameters shouldn't necessarily mean that |  | 
|   856   // we change the min/max of bandwidth estimation. Reevaluate this. |  | 
|   857   VideoCodec codec = supported_codecs.front().codec; |  | 
|   858   int bitrate_kbps; |  | 
|   859   if (codec.GetParam(kCodecParamMinBitrate, &bitrate_kbps) && |  | 
|   860       bitrate_kbps > 0) { |  | 
|   861     bitrate_config_.min_bitrate_bps = bitrate_kbps * 1000; |  | 
|   862   } else { |  | 
|   863     bitrate_config_.min_bitrate_bps = 0; |  | 
|   864   } |  | 
|   865   if (codec.GetParam(kCodecParamStartBitrate, &bitrate_kbps) && |  | 
|   866       bitrate_kbps > 0) { |  | 
|   867     bitrate_config_.start_bitrate_bps = bitrate_kbps * 1000; |  | 
|   868   } else { |  | 
|   869     // Do not reconfigure start bitrate unless it's specified and positive. |  | 
|   870     bitrate_config_.start_bitrate_bps = -1; |  | 
|   871   } |  | 
|   872   if (codec.GetParam(kCodecParamMaxBitrate, &bitrate_kbps) && |  | 
|   873       bitrate_kbps > 0) { |  | 
|   874     bitrate_config_.max_bitrate_bps = bitrate_kbps * 1000; |  | 
|   875   } else { |  | 
|   876     bitrate_config_.max_bitrate_bps = -1; |  | 
|   877   } |  | 
|   878   call_->SetBitrateConfig(bitrate_config_); |  | 
|   879  |  | 
|   880   return true; |  | 
|   881 } |  | 
|   882  |  | 
|   883 bool WebRtcVideoChannel2::GetSendCodec(VideoCodec* codec) { |  | 
|   884   if (!send_codec_) { |  | 
|   885     LOG(LS_VERBOSE) << "GetSendCodec: No send codec set."; |  | 
|   886     return false; |  | 
|   887   } |  | 
|   888   *codec = send_codec_->codec; |  | 
|   889   return true; |  | 
|   890 } |  | 
|   891  |  | 
|   892 bool WebRtcVideoChannel2::SetSendStreamFormat(uint32_t ssrc, |  | 
|   893                                               const VideoFormat& format) { |  | 
|   894   LOG(LS_VERBOSE) << "SetSendStreamFormat:" << ssrc << " -> " |  | 
|   895                   << format.ToString(); |  | 
|   896   rtc::CritScope stream_lock(&stream_crit_); |  | 
|   897   if (send_streams_.find(ssrc) == send_streams_.end()) { |  | 
|   898     return false; |  | 
|   899   } |  | 
|   900   return send_streams_[ssrc]->SetVideoFormat(format); |  | 
|   901 } |  | 
|   902  |  | 
|   903 bool WebRtcVideoChannel2::SetSend(bool send) { |  | 
|   904   LOG(LS_VERBOSE) << "SetSend: " << (send ? "true" : "false"); |  | 
|   905   if (send && !send_codec_) { |  | 
|   906     LOG(LS_ERROR) << "SetSend(true) called before setting codec."; |  | 
|   907     return false; |  | 
|   908   } |  | 
|   909   if (send) { |  | 
|   910     StartAllSendStreams(); |  | 
|   911   } else { |  | 
|   912     StopAllSendStreams(); |  | 
|   913   } |  | 
|   914   sending_ = send; |  | 
|   915   return true; |  | 
|   916 } |  | 
|   917  |  | 
|   918 bool WebRtcVideoChannel2::SetVideoSend(uint32_t ssrc, bool enable, |  | 
|   919                                        const VideoOptions* options) { |  | 
|   920   // TODO(solenberg): The state change should be fully rolled back if any one of |  | 
|   921   //                  these calls fail. |  | 
|   922   if (!MuteStream(ssrc, !enable)) { |  | 
|   923     return false; |  | 
|   924   } |  | 
|   925   if (enable && options) { |  | 
|   926     return SetOptions(*options); |  | 
|   927   } else { |  | 
|   928     return true; |  | 
|   929   } |  | 
|   930 } |  | 
|   931  |  | 
|   932 bool WebRtcVideoChannel2::ValidateSendSsrcAvailability( |  | 
|   933     const StreamParams& sp) const { |  | 
|   934   for (uint32_t ssrc: sp.ssrcs) { |  | 
|   935     if (send_ssrcs_.find(ssrc) != send_ssrcs_.end()) { |  | 
|   936       LOG(LS_ERROR) << "Send stream with SSRC '" << ssrc << "' already exists."; |  | 
|   937       return false; |  | 
|   938     } |  | 
|   939   } |  | 
|   940   return true; |  | 
|   941 } |  | 
|   942  |  | 
|   943 bool WebRtcVideoChannel2::ValidateReceiveSsrcAvailability( |  | 
|   944     const StreamParams& sp) const { |  | 
|   945   for (uint32_t ssrc: sp.ssrcs) { |  | 
|   946     if (receive_ssrcs_.find(ssrc) != receive_ssrcs_.end()) { |  | 
|   947       LOG(LS_ERROR) << "Receive stream with SSRC '" << ssrc |  | 
|   948                     << "' already exists."; |  | 
|   949       return false; |  | 
|   950     } |  | 
|   951   } |  | 
|   952   return true; |  | 
|   953 } |  | 
|   954  |  | 
|   955 bool WebRtcVideoChannel2::AddSendStream(const StreamParams& sp) { |  | 
|   956   LOG(LS_INFO) << "AddSendStream: " << sp.ToString(); |  | 
|   957   if (!ValidateStreamParams(sp)) |  | 
|   958     return false; |  | 
|   959  |  | 
|   960   rtc::CritScope stream_lock(&stream_crit_); |  | 
|   961  |  | 
|   962   if (!ValidateSendSsrcAvailability(sp)) |  | 
|   963     return false; |  | 
|   964  |  | 
|   965   for (uint32_t used_ssrc : sp.ssrcs) |  | 
|   966     send_ssrcs_.insert(used_ssrc); |  | 
|   967  |  | 
|   968   webrtc::VideoSendStream::Config config(this); |  | 
|   969   config.overuse_callback = this; |  | 
|   970  |  | 
|   971   WebRtcVideoSendStream* stream = new WebRtcVideoSendStream( |  | 
|   972       call_, sp, config, external_encoder_factory_, options_, |  | 
|   973       bitrate_config_.max_bitrate_bps, send_codec_, send_rtp_extensions_, |  | 
|   974       send_params_); |  | 
|   975  |  | 
|   976   uint32_t ssrc = sp.first_ssrc(); |  | 
|   977   RTC_DCHECK(ssrc != 0); |  | 
|   978   send_streams_[ssrc] = stream; |  | 
|   979  |  | 
|   980   if (rtcp_receiver_report_ssrc_ == kDefaultRtcpReceiverReportSsrc) { |  | 
|   981     rtcp_receiver_report_ssrc_ = ssrc; |  | 
|   982     LOG(LS_INFO) << "SetLocalSsrc on all the receive streams because we added " |  | 
|   983                     "a send stream."; |  | 
|   984     for (auto& kv : receive_streams_) |  | 
|   985       kv.second->SetLocalSsrc(ssrc); |  | 
|   986   } |  | 
|   987   if (default_send_ssrc_ == 0) { |  | 
|   988     default_send_ssrc_ = ssrc; |  | 
|   989   } |  | 
|   990   if (sending_) { |  | 
|   991     stream->Start(); |  | 
|   992   } |  | 
|   993  |  | 
|   994   return true; |  | 
|   995 } |  | 
|   996  |  | 
|   997 bool WebRtcVideoChannel2::RemoveSendStream(uint32_t ssrc) { |  | 
|   998   LOG(LS_INFO) << "RemoveSendStream: " << ssrc; |  | 
|   999  |  | 
|  1000   if (ssrc == 0) { |  | 
|  1001     if (default_send_ssrc_ == 0) { |  | 
|  1002       LOG(LS_ERROR) << "No default send stream active."; |  | 
|  1003       return false; |  | 
|  1004     } |  | 
|  1005  |  | 
|  1006     LOG(LS_VERBOSE) << "Removing default stream: " << default_send_ssrc_; |  | 
|  1007     ssrc = default_send_ssrc_; |  | 
|  1008   } |  | 
|  1009  |  | 
|  1010   WebRtcVideoSendStream* removed_stream; |  | 
|  1011   { |  | 
|  1012     rtc::CritScope stream_lock(&stream_crit_); |  | 
|  1013     std::map<uint32_t, WebRtcVideoSendStream*>::iterator it = |  | 
|  1014         send_streams_.find(ssrc); |  | 
|  1015     if (it == send_streams_.end()) { |  | 
|  1016       return false; |  | 
|  1017     } |  | 
|  1018  |  | 
|  1019     for (uint32_t old_ssrc : it->second->GetSsrcs()) |  | 
|  1020       send_ssrcs_.erase(old_ssrc); |  | 
|  1021  |  | 
|  1022     removed_stream = it->second; |  | 
|  1023     send_streams_.erase(it); |  | 
|  1024  |  | 
|  1025     // Switch receiver report SSRCs, the one in use is no longer valid. |  | 
|  1026     if (rtcp_receiver_report_ssrc_ == ssrc) { |  | 
|  1027       rtcp_receiver_report_ssrc_ = send_streams_.empty() |  | 
|  1028                                        ? kDefaultRtcpReceiverReportSsrc |  | 
|  1029                                        : send_streams_.begin()->first; |  | 
|  1030       LOG(LS_INFO) << "SetLocalSsrc on all the receive streams because the " |  | 
|  1031                       "previous local SSRC was removed."; |  | 
|  1032  |  | 
|  1033       for (auto& kv : receive_streams_) { |  | 
|  1034         kv.second->SetLocalSsrc(rtcp_receiver_report_ssrc_); |  | 
|  1035       } |  | 
|  1036     } |  | 
|  1037   } |  | 
|  1038  |  | 
|  1039   delete removed_stream; |  | 
|  1040  |  | 
|  1041   if (ssrc == default_send_ssrc_) { |  | 
|  1042     default_send_ssrc_ = 0; |  | 
|  1043   } |  | 
|  1044  |  | 
|  1045   return true; |  | 
|  1046 } |  | 
|  1047  |  | 
|  1048 void WebRtcVideoChannel2::DeleteReceiveStream( |  | 
|  1049     WebRtcVideoChannel2::WebRtcVideoReceiveStream* stream) { |  | 
|  1050   for (uint32_t old_ssrc : stream->GetSsrcs()) |  | 
|  1051     receive_ssrcs_.erase(old_ssrc); |  | 
|  1052   delete stream; |  | 
|  1053 } |  | 
|  1054  |  | 
|  1055 bool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp) { |  | 
|  1056   return AddRecvStream(sp, false); |  | 
|  1057 } |  | 
|  1058  |  | 
|  1059 bool WebRtcVideoChannel2::AddRecvStream(const StreamParams& sp, |  | 
|  1060                                         bool default_stream) { |  | 
|  1061   RTC_DCHECK(thread_checker_.CalledOnValidThread()); |  | 
|  1062  |  | 
|  1063   LOG(LS_INFO) << "AddRecvStream" << (default_stream ? " (default stream)" : "") |  | 
|  1064                << ": " << sp.ToString(); |  | 
|  1065   if (!ValidateStreamParams(sp)) |  | 
|  1066     return false; |  | 
|  1067  |  | 
|  1068   uint32_t ssrc = sp.first_ssrc(); |  | 
|  1069   RTC_DCHECK(ssrc != 0);  // TODO(pbos): Is this ever valid? |  | 
|  1070  |  | 
|  1071   rtc::CritScope stream_lock(&stream_crit_); |  | 
|  1072   // Remove running stream if this was a default stream. |  | 
|  1073   auto prev_stream = receive_streams_.find(ssrc); |  | 
|  1074   if (prev_stream != receive_streams_.end()) { |  | 
|  1075     if (default_stream || !prev_stream->second->IsDefaultStream()) { |  | 
|  1076       LOG(LS_ERROR) << "Receive stream for SSRC '" << ssrc |  | 
|  1077                     << "' already exists."; |  | 
|  1078       return false; |  | 
|  1079     } |  | 
|  1080     DeleteReceiveStream(prev_stream->second); |  | 
|  1081     receive_streams_.erase(prev_stream); |  | 
|  1082   } |  | 
|  1083  |  | 
|  1084   if (!ValidateReceiveSsrcAvailability(sp)) |  | 
|  1085     return false; |  | 
|  1086  |  | 
|  1087   for (uint32_t used_ssrc : sp.ssrcs) |  | 
|  1088     receive_ssrcs_.insert(used_ssrc); |  | 
|  1089  |  | 
|  1090   webrtc::VideoReceiveStream::Config config(this); |  | 
|  1091   ConfigureReceiverRtp(&config, sp); |  | 
|  1092  |  | 
|  1093   // Set up A/V sync group based on sync label. |  | 
|  1094   config.sync_group = sp.sync_label; |  | 
|  1095  |  | 
|  1096   config.rtp.remb = send_codec_ ? HasRemb(send_codec_->codec) : false; |  | 
|  1097   config.rtp.transport_cc = |  | 
|  1098       send_codec_ ? HasTransportCc(send_codec_->codec) : false; |  | 
|  1099  |  | 
|  1100   receive_streams_[ssrc] = new WebRtcVideoReceiveStream( |  | 
|  1101       call_, sp, config, external_decoder_factory_, default_stream, |  | 
|  1102       recv_codecs_, options_.disable_prerenderer_smoothing.value_or(false)); |  | 
|  1103  |  | 
|  1104   return true; |  | 
|  1105 } |  | 
|  1106  |  | 
|  1107 void WebRtcVideoChannel2::ConfigureReceiverRtp( |  | 
|  1108     webrtc::VideoReceiveStream::Config* config, |  | 
|  1109     const StreamParams& sp) const { |  | 
|  1110   uint32_t ssrc = sp.first_ssrc(); |  | 
|  1111  |  | 
|  1112   config->rtp.remote_ssrc = ssrc; |  | 
|  1113   config->rtp.local_ssrc = rtcp_receiver_report_ssrc_; |  | 
|  1114  |  | 
|  1115   config->rtp.extensions = recv_rtp_extensions_; |  | 
|  1116   config->rtp.rtcp_mode = recv_params_.rtcp.reduced_size |  | 
|  1117                               ? webrtc::RtcpMode::kReducedSize |  | 
|  1118                               : webrtc::RtcpMode::kCompound; |  | 
|  1119  |  | 
|  1120   // TODO(pbos): This protection is against setting the same local ssrc as |  | 
|  1121   // remote which is not permitted by the lower-level API. RTCP requires a |  | 
|  1122   // corresponding sender SSRC. Figure out what to do when we don't have |  | 
|  1123   // (receive-only) or know a good local SSRC. |  | 
|  1124   if (config->rtp.remote_ssrc == config->rtp.local_ssrc) { |  | 
|  1125     if (config->rtp.local_ssrc != kDefaultRtcpReceiverReportSsrc) { |  | 
|  1126       config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc; |  | 
|  1127     } else { |  | 
|  1128       config->rtp.local_ssrc = kDefaultRtcpReceiverReportSsrc + 1; |  | 
|  1129     } |  | 
|  1130   } |  | 
|  1131  |  | 
|  1132   for (size_t i = 0; i < recv_codecs_.size(); ++i) { |  | 
|  1133     MergeFecConfig(recv_codecs_[i].fec, &config->rtp.fec); |  | 
|  1134   } |  | 
|  1135  |  | 
|  1136   for (size_t i = 0; i < recv_codecs_.size(); ++i) { |  | 
|  1137     uint32_t rtx_ssrc; |  | 
|  1138     if (recv_codecs_[i].rtx_payload_type != -1 && |  | 
|  1139         sp.GetFidSsrc(ssrc, &rtx_ssrc)) { |  | 
|  1140       webrtc::VideoReceiveStream::Config::Rtp::Rtx& rtx = |  | 
|  1141           config->rtp.rtx[recv_codecs_[i].codec.id]; |  | 
|  1142       rtx.ssrc = rtx_ssrc; |  | 
|  1143       rtx.payload_type = recv_codecs_[i].rtx_payload_type; |  | 
|  1144     } |  | 
|  1145   } |  | 
|  1146 } |  | 
|  1147  |  | 
|  1148 bool WebRtcVideoChannel2::RemoveRecvStream(uint32_t ssrc) { |  | 
|  1149   LOG(LS_INFO) << "RemoveRecvStream: " << ssrc; |  | 
|  1150   if (ssrc == 0) { |  | 
|  1151     LOG(LS_ERROR) << "RemoveRecvStream with 0 ssrc is not supported."; |  | 
|  1152     return false; |  | 
|  1153   } |  | 
|  1154  |  | 
|  1155   rtc::CritScope stream_lock(&stream_crit_); |  | 
|  1156   std::map<uint32_t, WebRtcVideoReceiveStream*>::iterator stream = |  | 
|  1157       receive_streams_.find(ssrc); |  | 
|  1158   if (stream == receive_streams_.end()) { |  | 
|  1159     LOG(LS_ERROR) << "Stream not found for ssrc: " << ssrc; |  | 
|  1160     return false; |  | 
|  1161   } |  | 
|  1162   DeleteReceiveStream(stream->second); |  | 
|  1163   receive_streams_.erase(stream); |  | 
|  1164  |  | 
|  1165   return true; |  | 
|  1166 } |  | 
|  1167  |  | 
|  1168 bool WebRtcVideoChannel2::SetRenderer(uint32_t ssrc, VideoRenderer* renderer) { |  | 
|  1169   LOG(LS_INFO) << "SetRenderer: ssrc:" << ssrc << " " |  | 
|  1170                << (renderer ? "(ptr)" : "NULL"); |  | 
|  1171   if (ssrc == 0) { |  | 
|  1172     default_unsignalled_ssrc_handler_.SetDefaultRenderer(this, renderer); |  | 
|  1173     return true; |  | 
|  1174   } |  | 
|  1175  |  | 
|  1176   rtc::CritScope stream_lock(&stream_crit_); |  | 
|  1177   std::map<uint32_t, WebRtcVideoReceiveStream*>::iterator it = |  | 
|  1178       receive_streams_.find(ssrc); |  | 
|  1179   if (it == receive_streams_.end()) { |  | 
|  1180     return false; |  | 
|  1181   } |  | 
|  1182  |  | 
|  1183   it->second->SetRenderer(renderer); |  | 
|  1184   return true; |  | 
|  1185 } |  | 
|  1186  |  | 
|  1187 bool WebRtcVideoChannel2::GetRenderer(uint32_t ssrc, VideoRenderer** renderer) { |  | 
|  1188   if (ssrc == 0) { |  | 
|  1189     *renderer = default_unsignalled_ssrc_handler_.GetDefaultRenderer(); |  | 
|  1190     return *renderer != NULL; |  | 
|  1191   } |  | 
|  1192  |  | 
|  1193   rtc::CritScope stream_lock(&stream_crit_); |  | 
|  1194   std::map<uint32_t, WebRtcVideoReceiveStream*>::iterator it = |  | 
|  1195       receive_streams_.find(ssrc); |  | 
|  1196   if (it == receive_streams_.end()) { |  | 
|  1197     return false; |  | 
|  1198   } |  | 
|  1199   *renderer = it->second->GetRenderer(); |  | 
|  1200   return true; |  | 
|  1201 } |  | 
|  1202  |  | 
|  1203 bool WebRtcVideoChannel2::GetStats(VideoMediaInfo* info) { |  | 
|  1204   info->Clear(); |  | 
|  1205   FillSenderStats(info); |  | 
|  1206   FillReceiverStats(info); |  | 
|  1207   webrtc::Call::Stats stats = call_->GetStats(); |  | 
|  1208   FillBandwidthEstimationStats(stats, info); |  | 
|  1209   if (stats.rtt_ms != -1) { |  | 
|  1210     for (size_t i = 0; i < info->senders.size(); ++i) { |  | 
|  1211       info->senders[i].rtt_ms = stats.rtt_ms; |  | 
|  1212     } |  | 
|  1213   } |  | 
|  1214   return true; |  | 
|  1215 } |  | 
|  1216  |  | 
|  1217 void WebRtcVideoChannel2::FillSenderStats(VideoMediaInfo* video_media_info) { |  | 
|  1218   rtc::CritScope stream_lock(&stream_crit_); |  | 
|  1219   for (std::map<uint32_t, WebRtcVideoSendStream*>::iterator it = |  | 
|  1220            send_streams_.begin(); |  | 
|  1221        it != send_streams_.end(); ++it) { |  | 
|  1222     video_media_info->senders.push_back(it->second->GetVideoSenderInfo()); |  | 
|  1223   } |  | 
|  1224 } |  | 
|  1225  |  | 
|  1226 void WebRtcVideoChannel2::FillReceiverStats(VideoMediaInfo* video_media_info) { |  | 
|  1227   rtc::CritScope stream_lock(&stream_crit_); |  | 
|  1228   for (std::map<uint32_t, WebRtcVideoReceiveStream*>::iterator it = |  | 
|  1229            receive_streams_.begin(); |  | 
|  1230        it != receive_streams_.end(); ++it) { |  | 
|  1231     video_media_info->receivers.push_back(it->second->GetVideoReceiverInfo()); |  | 
|  1232   } |  | 
|  1233 } |  | 
|  1234  |  | 
|  1235 void WebRtcVideoChannel2::FillBandwidthEstimationStats( |  | 
|  1236     const webrtc::Call::Stats& stats, |  | 
|  1237     VideoMediaInfo* video_media_info) { |  | 
|  1238   BandwidthEstimationInfo bwe_info; |  | 
|  1239   bwe_info.available_send_bandwidth = stats.send_bandwidth_bps; |  | 
|  1240   bwe_info.available_recv_bandwidth = stats.recv_bandwidth_bps; |  | 
|  1241   bwe_info.bucket_delay = stats.pacer_delay_ms; |  | 
|  1242  |  | 
|  1243   // Get send stream bitrate stats. |  | 
|  1244   rtc::CritScope stream_lock(&stream_crit_); |  | 
|  1245   for (std::map<uint32_t, WebRtcVideoSendStream*>::iterator stream = |  | 
|  1246            send_streams_.begin(); |  | 
|  1247        stream != send_streams_.end(); ++stream) { |  | 
|  1248     stream->second->FillBandwidthEstimationInfo(&bwe_info); |  | 
|  1249   } |  | 
|  1250   video_media_info->bw_estimations.push_back(bwe_info); |  | 
|  1251 } |  | 
|  1252  |  | 
|  1253 bool WebRtcVideoChannel2::SetCapturer(uint32_t ssrc, VideoCapturer* capturer) { |  | 
|  1254   LOG(LS_INFO) << "SetCapturer: " << ssrc << " -> " |  | 
|  1255                << (capturer != NULL ? "(capturer)" : "NULL"); |  | 
|  1256   RTC_DCHECK(ssrc != 0); |  | 
|  1257   { |  | 
|  1258     rtc::CritScope stream_lock(&stream_crit_); |  | 
|  1259     if (send_streams_.find(ssrc) == send_streams_.end()) { |  | 
|  1260       LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc; |  | 
|  1261       return false; |  | 
|  1262     } |  | 
|  1263     if (!send_streams_[ssrc]->SetCapturer(capturer)) { |  | 
|  1264       return false; |  | 
|  1265     } |  | 
|  1266   } |  | 
|  1267  |  | 
|  1268   if (capturer) { |  | 
|  1269     capturer->SetApplyRotation( |  | 
|  1270         !FindHeaderExtension(send_rtp_extensions_, |  | 
|  1271                              kRtpVideoRotationHeaderExtension)); |  | 
|  1272   } |  | 
|  1273   { |  | 
|  1274     rtc::CritScope lock(&capturer_crit_); |  | 
|  1275     capturers_[ssrc] = capturer; |  | 
|  1276   } |  | 
|  1277   return true; |  | 
|  1278 } |  | 
|  1279  |  | 
|  1280 bool WebRtcVideoChannel2::SendIntraFrame() { |  | 
|  1281   // TODO(pbos): Implement. |  | 
|  1282   LOG(LS_VERBOSE) << "SendIntraFrame()."; |  | 
|  1283   return true; |  | 
|  1284 } |  | 
|  1285  |  | 
|  1286 bool WebRtcVideoChannel2::RequestIntraFrame() { |  | 
|  1287   // TODO(pbos): Implement. |  | 
|  1288   LOG(LS_VERBOSE) << "SendIntraFrame()."; |  | 
|  1289   return true; |  | 
|  1290 } |  | 
|  1291  |  | 
|  1292 void WebRtcVideoChannel2::OnPacketReceived( |  | 
|  1293     rtc::Buffer* packet, |  | 
|  1294     const rtc::PacketTime& packet_time) { |  | 
|  1295   const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp, |  | 
|  1296                                               packet_time.not_before); |  | 
|  1297   const webrtc::PacketReceiver::DeliveryStatus delivery_result = |  | 
|  1298       call_->Receiver()->DeliverPacket( |  | 
|  1299           webrtc::MediaType::VIDEO, |  | 
|  1300           reinterpret_cast<const uint8_t*>(packet->data()), packet->size(), |  | 
|  1301           webrtc_packet_time); |  | 
|  1302   switch (delivery_result) { |  | 
|  1303     case webrtc::PacketReceiver::DELIVERY_OK: |  | 
|  1304       return; |  | 
|  1305     case webrtc::PacketReceiver::DELIVERY_PACKET_ERROR: |  | 
|  1306       return; |  | 
|  1307     case webrtc::PacketReceiver::DELIVERY_UNKNOWN_SSRC: |  | 
|  1308       break; |  | 
|  1309   } |  | 
|  1310  |  | 
|  1311   uint32_t ssrc = 0; |  | 
|  1312   if (!GetRtpSsrc(packet->data(), packet->size(), &ssrc)) { |  | 
|  1313     return; |  | 
|  1314   } |  | 
|  1315  |  | 
|  1316   int payload_type = 0; |  | 
|  1317   if (!GetRtpPayloadType(packet->data(), packet->size(), &payload_type)) { |  | 
|  1318     return; |  | 
|  1319   } |  | 
|  1320  |  | 
|  1321   // See if this payload_type is registered as one that usually gets its own |  | 
|  1322   // SSRC (RTX) or at least is safe to drop either way (ULPFEC). If it is, and |  | 
|  1323   // it wasn't handled above by DeliverPacket, that means we don't know what |  | 
|  1324   // stream it associates with, and we shouldn't ever create an implicit channel |  | 
|  1325   // for these. |  | 
|  1326   for (auto& codec : recv_codecs_) { |  | 
|  1327     if (payload_type == codec.rtx_payload_type || |  | 
|  1328         payload_type == codec.fec.red_rtx_payload_type || |  | 
|  1329         payload_type == codec.fec.ulpfec_payload_type) { |  | 
|  1330       return; |  | 
|  1331     } |  | 
|  1332   } |  | 
|  1333  |  | 
|  1334   switch (unsignalled_ssrc_handler_->OnUnsignalledSsrc(this, ssrc)) { |  | 
|  1335     case UnsignalledSsrcHandler::kDropPacket: |  | 
|  1336       return; |  | 
|  1337     case UnsignalledSsrcHandler::kDeliverPacket: |  | 
|  1338       break; |  | 
|  1339   } |  | 
|  1340  |  | 
|  1341   if (call_->Receiver()->DeliverPacket( |  | 
|  1342           webrtc::MediaType::VIDEO, |  | 
|  1343           reinterpret_cast<const uint8_t*>(packet->data()), packet->size(), |  | 
|  1344           webrtc_packet_time) != webrtc::PacketReceiver::DELIVERY_OK) { |  | 
|  1345     LOG(LS_WARNING) << "Failed to deliver RTP packet on re-delivery."; |  | 
|  1346     return; |  | 
|  1347   } |  | 
|  1348 } |  | 
|  1349  |  | 
|  1350 void WebRtcVideoChannel2::OnRtcpReceived( |  | 
|  1351     rtc::Buffer* packet, |  | 
|  1352     const rtc::PacketTime& packet_time) { |  | 
|  1353   const webrtc::PacketTime webrtc_packet_time(packet_time.timestamp, |  | 
|  1354                                               packet_time.not_before); |  | 
|  1355   // TODO(pbos): Check webrtc::PacketReceiver::DELIVERY_OK once we deliver |  | 
|  1356   // for both audio and video on the same path. Since BundleFilter doesn't |  | 
|  1357   // filter RTCP anymore incoming RTCP packets could've been going to audio (so |  | 
|  1358   // logging failures spam the log). |  | 
|  1359   call_->Receiver()->DeliverPacket( |  | 
|  1360       webrtc::MediaType::VIDEO, |  | 
|  1361       reinterpret_cast<const uint8_t*>(packet->data()), packet->size(), |  | 
|  1362       webrtc_packet_time); |  | 
|  1363 } |  | 
|  1364  |  | 
|  1365 void WebRtcVideoChannel2::OnReadyToSend(bool ready) { |  | 
|  1366   LOG(LS_VERBOSE) << "OnReadyToSend: " << (ready ? "Ready." : "Not ready."); |  | 
|  1367   call_->SignalNetworkState(ready ? webrtc::kNetworkUp : webrtc::kNetworkDown); |  | 
|  1368 } |  | 
|  1369  |  | 
|  1370 bool WebRtcVideoChannel2::MuteStream(uint32_t ssrc, bool mute) { |  | 
|  1371   LOG(LS_VERBOSE) << "MuteStream: " << ssrc << " -> " |  | 
|  1372                   << (mute ? "mute" : "unmute"); |  | 
|  1373   RTC_DCHECK(ssrc != 0); |  | 
|  1374   rtc::CritScope stream_lock(&stream_crit_); |  | 
|  1375   if (send_streams_.find(ssrc) == send_streams_.end()) { |  | 
|  1376     LOG(LS_ERROR) << "No sending stream on ssrc " << ssrc; |  | 
|  1377     return false; |  | 
|  1378   } |  | 
|  1379  |  | 
|  1380   send_streams_[ssrc]->MuteStream(mute); |  | 
|  1381   return true; |  | 
|  1382 } |  | 
|  1383  |  | 
|  1384 bool WebRtcVideoChannel2::SetRecvRtpHeaderExtensions( |  | 
|  1385     const std::vector<RtpHeaderExtension>& extensions) { |  | 
|  1386   TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetRecvRtpHeaderExtensions"); |  | 
|  1387   if (!ValidateRtpExtensions(extensions)) { |  | 
|  1388     return false; |  | 
|  1389   } |  | 
|  1390   std::vector<webrtc::RtpExtension> filtered_extensions = FilterRtpExtensions( |  | 
|  1391       extensions, webrtc::RtpExtension::IsSupportedForVideo, false); |  | 
|  1392   if (recv_rtp_extensions_ == filtered_extensions) { |  | 
|  1393     LOG(LS_INFO) << "Ignoring call to SetRecvRtpHeaderExtensions because " |  | 
|  1394                     "header extensions haven't changed."; |  | 
|  1395     return true; |  | 
|  1396   } |  | 
|  1397   recv_rtp_extensions_.swap(filtered_extensions); |  | 
|  1398  |  | 
|  1399   rtc::CritScope stream_lock(&stream_crit_); |  | 
|  1400   for (std::map<uint32_t, WebRtcVideoReceiveStream*>::iterator it = |  | 
|  1401            receive_streams_.begin(); |  | 
|  1402        it != receive_streams_.end(); ++it) { |  | 
|  1403     it->second->SetRtpExtensions(recv_rtp_extensions_); |  | 
|  1404   } |  | 
|  1405   return true; |  | 
|  1406 } |  | 
|  1407  |  | 
|  1408 bool WebRtcVideoChannel2::SetSendRtpHeaderExtensions( |  | 
|  1409     const std::vector<RtpHeaderExtension>& extensions) { |  | 
|  1410   TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetSendRtpHeaderExtensions"); |  | 
|  1411   if (!ValidateRtpExtensions(extensions)) { |  | 
|  1412     return false; |  | 
|  1413   } |  | 
|  1414   std::vector<webrtc::RtpExtension> filtered_extensions = FilterRtpExtensions( |  | 
|  1415       extensions, webrtc::RtpExtension::IsSupportedForVideo, true); |  | 
|  1416   if (send_rtp_extensions_ == filtered_extensions) { |  | 
|  1417     LOG(LS_INFO) << "Ignoring call to SetRecvRtpHeaderExtensions because " |  | 
|  1418                     "header extensions haven't changed."; |  | 
|  1419     return true; |  | 
|  1420   } |  | 
|  1421   send_rtp_extensions_.swap(filtered_extensions); |  | 
|  1422  |  | 
|  1423   const webrtc::RtpExtension* cvo_extension = FindHeaderExtension( |  | 
|  1424       send_rtp_extensions_, kRtpVideoRotationHeaderExtension); |  | 
|  1425  |  | 
|  1426   rtc::CritScope stream_lock(&stream_crit_); |  | 
|  1427   for (std::map<uint32_t, WebRtcVideoSendStream*>::iterator it = |  | 
|  1428            send_streams_.begin(); |  | 
|  1429        it != send_streams_.end(); ++it) { |  | 
|  1430     it->second->SetRtpExtensions(send_rtp_extensions_); |  | 
|  1431     it->second->SetApplyRotation(!cvo_extension); |  | 
|  1432   } |  | 
|  1433   return true; |  | 
|  1434 } |  | 
|  1435  |  | 
|  1436 // Counter-intuitively this method doesn't only set global bitrate caps but also |  | 
|  1437 // per-stream codec max bitrates. This is to permit SetMaxSendBitrate (b=AS) to |  | 
|  1438 // raise bitrates above the 2000k default bitrate cap. |  | 
|  1439 bool WebRtcVideoChannel2::SetMaxSendBandwidth(int max_bitrate_bps) { |  | 
|  1440   // TODO(pbos): Figure out whether b=AS means max bitrate for this |  | 
|  1441   // WebRtcVideoChannel2 (in which case we're good), or per sender (SSRC), in |  | 
|  1442   // which case this should not set a Call::BitrateConfig but rather reconfigure |  | 
|  1443   // all senders. |  | 
|  1444   LOG(LS_INFO) << "SetMaxSendBandwidth: " << max_bitrate_bps << "bps."; |  | 
|  1445   if (max_bitrate_bps == bitrate_config_.max_bitrate_bps) |  | 
|  1446     return true; |  | 
|  1447  |  | 
|  1448   if (max_bitrate_bps < 0) { |  | 
|  1449     // Option not set. |  | 
|  1450     return true; |  | 
|  1451   } |  | 
|  1452   if (max_bitrate_bps == 0) { |  | 
|  1453     // Unsetting max bitrate. |  | 
|  1454     max_bitrate_bps = -1; |  | 
|  1455   } |  | 
|  1456   bitrate_config_.start_bitrate_bps = -1; |  | 
|  1457   bitrate_config_.max_bitrate_bps = max_bitrate_bps; |  | 
|  1458   if (max_bitrate_bps > 0 && |  | 
|  1459       bitrate_config_.min_bitrate_bps > max_bitrate_bps) { |  | 
|  1460     bitrate_config_.min_bitrate_bps = max_bitrate_bps; |  | 
|  1461   } |  | 
|  1462   call_->SetBitrateConfig(bitrate_config_); |  | 
|  1463   rtc::CritScope stream_lock(&stream_crit_); |  | 
|  1464   for (auto& kv : send_streams_) |  | 
|  1465     kv.second->SetMaxBitrateBps(max_bitrate_bps); |  | 
|  1466   return true; |  | 
|  1467 } |  | 
|  1468  |  | 
|  1469 bool WebRtcVideoChannel2::SetOptions(const VideoOptions& options) { |  | 
|  1470   TRACE_EVENT0("webrtc", "WebRtcVideoChannel2::SetOptions"); |  | 
|  1471   LOG(LS_INFO) << "SetOptions: " << options.ToString(); |  | 
|  1472   VideoOptions old_options = options_; |  | 
|  1473   options_.SetAll(options); |  | 
|  1474   if (options_ == old_options) { |  | 
|  1475     // No new options to set. |  | 
|  1476     return true; |  | 
|  1477   } |  | 
|  1478   { |  | 
|  1479     rtc::CritScope lock(&capturer_crit_); |  | 
|  1480     if (options_.cpu_overuse_detection) |  | 
|  1481       signal_cpu_adaptation_ = *options_.cpu_overuse_detection; |  | 
|  1482   } |  | 
|  1483   rtc::DiffServCodePoint dscp = |  | 
|  1484       options_.dscp.value_or(false) ? rtc::DSCP_AF41 : rtc::DSCP_DEFAULT; |  | 
|  1485   MediaChannel::SetDscp(dscp); |  | 
|  1486   rtc::CritScope stream_lock(&stream_crit_); |  | 
|  1487   for (std::map<uint32_t, WebRtcVideoSendStream*>::iterator it = |  | 
|  1488            send_streams_.begin(); |  | 
|  1489        it != send_streams_.end(); ++it) { |  | 
|  1490     it->second->SetOptions(options_); |  | 
|  1491   } |  | 
|  1492   return true; |  | 
|  1493 } |  | 
|  1494  |  | 
|  1495 void WebRtcVideoChannel2::SetInterface(NetworkInterface* iface) { |  | 
|  1496   MediaChannel::SetInterface(iface); |  | 
|  1497   // Set the RTP recv/send buffer to a bigger size |  | 
|  1498   MediaChannel::SetOption(NetworkInterface::ST_RTP, |  | 
|  1499                           rtc::Socket::OPT_RCVBUF, |  | 
|  1500                           kVideoRtpBufferSize); |  | 
|  1501  |  | 
|  1502   // Speculative change to increase the outbound socket buffer size. |  | 
|  1503   // In b/15152257, we are seeing a significant number of packets discarded |  | 
|  1504   // due to lack of socket buffer space, although it's not yet clear what the |  | 
|  1505   // ideal value should be. |  | 
|  1506   MediaChannel::SetOption(NetworkInterface::ST_RTP, |  | 
|  1507                           rtc::Socket::OPT_SNDBUF, |  | 
|  1508                           kVideoRtpBufferSize); |  | 
|  1509 } |  | 
|  1510  |  | 
|  1511 void WebRtcVideoChannel2::UpdateAspectRatio(int ratio_w, int ratio_h) { |  | 
|  1512   // TODO(pbos): Implement. |  | 
|  1513 } |  | 
|  1514  |  | 
|  1515 void WebRtcVideoChannel2::OnMessage(rtc::Message* msg) { |  | 
|  1516   // Ignored. |  | 
|  1517 } |  | 
|  1518  |  | 
|  1519 void WebRtcVideoChannel2::OnLoadUpdate(Load load) { |  | 
|  1520   // OnLoadUpdate can not take any locks that are held while creating streams |  | 
|  1521   // etc. Doing so establishes lock-order inversions between the webrtc process |  | 
|  1522   // thread on stream creation and locks such as stream_crit_ while calling out. |  | 
|  1523   rtc::CritScope stream_lock(&capturer_crit_); |  | 
|  1524   if (!signal_cpu_adaptation_) |  | 
|  1525     return; |  | 
|  1526   // Do not adapt resolution for screen content as this will likely result in |  | 
|  1527   // blurry and unreadable text. |  | 
|  1528   for (auto& kv : capturers_) { |  | 
|  1529     if (kv.second != nullptr |  | 
|  1530         && !kv.second->IsScreencast() |  | 
|  1531         && kv.second->video_adapter() != nullptr) { |  | 
|  1532       kv.second->video_adapter()->OnCpuResolutionRequest( |  | 
|  1533           load == kOveruse ? CoordinatedVideoAdapter::DOWNGRADE |  | 
|  1534                            : CoordinatedVideoAdapter::UPGRADE); |  | 
|  1535     } |  | 
|  1536   } |  | 
|  1537 } |  | 
|  1538  |  | 
|  1539 bool WebRtcVideoChannel2::SendRtp(const uint8_t* data, |  | 
|  1540                                   size_t len, |  | 
|  1541                                   const webrtc::PacketOptions& options) { |  | 
|  1542   rtc::Buffer packet(data, len, kMaxRtpPacketLen); |  | 
|  1543   rtc::PacketOptions rtc_options; |  | 
|  1544   rtc_options.packet_id = options.packet_id; |  | 
|  1545   return MediaChannel::SendPacket(&packet, rtc_options); |  | 
|  1546 } |  | 
|  1547  |  | 
|  1548 bool WebRtcVideoChannel2::SendRtcp(const uint8_t* data, size_t len) { |  | 
|  1549   rtc::Buffer packet(data, len, kMaxRtpPacketLen); |  | 
|  1550   return MediaChannel::SendRtcp(&packet, rtc::PacketOptions()); |  | 
|  1551 } |  | 
|  1552  |  | 
|  1553 void WebRtcVideoChannel2::StartAllSendStreams() { |  | 
|  1554   rtc::CritScope stream_lock(&stream_crit_); |  | 
|  1555   for (std::map<uint32_t, WebRtcVideoSendStream*>::iterator it = |  | 
|  1556            send_streams_.begin(); |  | 
|  1557        it != send_streams_.end(); ++it) { |  | 
|  1558     it->second->Start(); |  | 
|  1559   } |  | 
|  1560 } |  | 
|  1561  |  | 
|  1562 void WebRtcVideoChannel2::StopAllSendStreams() { |  | 
|  1563   rtc::CritScope stream_lock(&stream_crit_); |  | 
|  1564   for (std::map<uint32_t, WebRtcVideoSendStream*>::iterator it = |  | 
|  1565            send_streams_.begin(); |  | 
|  1566        it != send_streams_.end(); ++it) { |  | 
|  1567     it->second->Stop(); |  | 
|  1568   } |  | 
|  1569 } |  | 
|  1570  |  | 
|  1571 WebRtcVideoChannel2::WebRtcVideoSendStream::VideoSendStreamParameters:: |  | 
|  1572     VideoSendStreamParameters( |  | 
|  1573         const webrtc::VideoSendStream::Config& config, |  | 
|  1574         const VideoOptions& options, |  | 
|  1575         int max_bitrate_bps, |  | 
|  1576         const rtc::Optional<VideoCodecSettings>& codec_settings) |  | 
|  1577     : config(config), |  | 
|  1578       options(options), |  | 
|  1579       max_bitrate_bps(max_bitrate_bps), |  | 
|  1580       codec_settings(codec_settings) {} |  | 
|  1581  |  | 
|  1582 WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder::AllocatedEncoder( |  | 
|  1583     webrtc::VideoEncoder* encoder, |  | 
|  1584     webrtc::VideoCodecType type, |  | 
|  1585     bool external) |  | 
|  1586     : encoder(encoder), |  | 
|  1587       external_encoder(nullptr), |  | 
|  1588       type(type), |  | 
|  1589       external(external) { |  | 
|  1590   if (external) { |  | 
|  1591     external_encoder = encoder; |  | 
|  1592     this->encoder = |  | 
|  1593         new webrtc::VideoEncoderSoftwareFallbackWrapper(type, encoder); |  | 
|  1594   } |  | 
|  1595 } |  | 
|  1596  |  | 
|  1597 WebRtcVideoChannel2::WebRtcVideoSendStream::WebRtcVideoSendStream( |  | 
|  1598     webrtc::Call* call, |  | 
|  1599     const StreamParams& sp, |  | 
|  1600     const webrtc::VideoSendStream::Config& config, |  | 
|  1601     WebRtcVideoEncoderFactory* external_encoder_factory, |  | 
|  1602     const VideoOptions& options, |  | 
|  1603     int max_bitrate_bps, |  | 
|  1604     const rtc::Optional<VideoCodecSettings>& codec_settings, |  | 
|  1605     const std::vector<webrtc::RtpExtension>& rtp_extensions, |  | 
|  1606     // TODO(deadbeef): Don't duplicate information between send_params, |  | 
|  1607     // rtp_extensions, options, etc. |  | 
|  1608     const VideoSendParameters& send_params) |  | 
|  1609     : ssrcs_(sp.ssrcs), |  | 
|  1610       ssrc_groups_(sp.ssrc_groups), |  | 
|  1611       call_(call), |  | 
|  1612       external_encoder_factory_(external_encoder_factory), |  | 
|  1613       stream_(NULL), |  | 
|  1614       parameters_(config, options, max_bitrate_bps, codec_settings), |  | 
|  1615       allocated_encoder_(NULL, webrtc::kVideoCodecUnknown, false), |  | 
|  1616       capturer_(NULL), |  | 
|  1617       sending_(false), |  | 
|  1618       muted_(false), |  | 
|  1619       old_adapt_changes_(0), |  | 
|  1620       first_frame_timestamp_ms_(0), |  | 
|  1621       last_frame_timestamp_ms_(0) { |  | 
|  1622   parameters_.config.rtp.max_packet_size = kVideoMtu; |  | 
|  1623  |  | 
|  1624   sp.GetPrimarySsrcs(¶meters_.config.rtp.ssrcs); |  | 
|  1625   sp.GetFidSsrcs(parameters_.config.rtp.ssrcs, |  | 
|  1626                  ¶meters_.config.rtp.rtx.ssrcs); |  | 
|  1627   parameters_.config.rtp.c_name = sp.cname; |  | 
|  1628   parameters_.config.rtp.extensions = rtp_extensions; |  | 
|  1629   parameters_.config.rtp.rtcp_mode = send_params.rtcp.reduced_size |  | 
|  1630                                          ? webrtc::RtcpMode::kReducedSize |  | 
|  1631                                          : webrtc::RtcpMode::kCompound; |  | 
|  1632  |  | 
|  1633   if (codec_settings) { |  | 
|  1634     SetCodec(*codec_settings); |  | 
|  1635   } |  | 
|  1636 } |  | 
|  1637  |  | 
|  1638 WebRtcVideoChannel2::WebRtcVideoSendStream::~WebRtcVideoSendStream() { |  | 
|  1639   DisconnectCapturer(); |  | 
|  1640   if (stream_ != NULL) { |  | 
|  1641     call_->DestroyVideoSendStream(stream_); |  | 
|  1642   } |  | 
|  1643   DestroyVideoEncoder(&allocated_encoder_); |  | 
|  1644 } |  | 
|  1645  |  | 
|  1646 static void CreateBlackFrame(webrtc::VideoFrame* video_frame, |  | 
|  1647                              int width, |  | 
|  1648                              int height) { |  | 
|  1649   video_frame->CreateEmptyFrame(width, height, width, (width + 1) / 2, |  | 
|  1650                                 (width + 1) / 2); |  | 
|  1651   memset(video_frame->buffer(webrtc::kYPlane), 16, |  | 
|  1652          video_frame->allocated_size(webrtc::kYPlane)); |  | 
|  1653   memset(video_frame->buffer(webrtc::kUPlane), 128, |  | 
|  1654          video_frame->allocated_size(webrtc::kUPlane)); |  | 
|  1655   memset(video_frame->buffer(webrtc::kVPlane), 128, |  | 
|  1656          video_frame->allocated_size(webrtc::kVPlane)); |  | 
|  1657 } |  | 
|  1658  |  | 
|  1659 void WebRtcVideoChannel2::WebRtcVideoSendStream::InputFrame( |  | 
|  1660     VideoCapturer* capturer, |  | 
|  1661     const VideoFrame* frame) { |  | 
|  1662   TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::InputFrame"); |  | 
|  1663   webrtc::VideoFrame video_frame(frame->GetVideoFrameBuffer(), 0, 0, |  | 
|  1664                                  frame->GetVideoRotation()); |  | 
|  1665   rtc::CritScope cs(&lock_); |  | 
|  1666   if (stream_ == NULL) { |  | 
|  1667     // Frame input before send codecs are configured, dropping frame. |  | 
|  1668     return; |  | 
|  1669   } |  | 
|  1670  |  | 
|  1671   // Not sending, abort early to prevent expensive reconfigurations while |  | 
|  1672   // setting up codecs etc. |  | 
|  1673   if (!sending_) |  | 
|  1674     return; |  | 
|  1675  |  | 
|  1676   if (format_.width == 0) {  // Dropping frames. |  | 
|  1677     RTC_DCHECK(format_.height == 0); |  | 
|  1678     LOG(LS_VERBOSE) << "VideoFormat 0x0 set, Dropping frame."; |  | 
|  1679     return; |  | 
|  1680   } |  | 
|  1681   if (muted_) { |  | 
|  1682     // Create a black frame to transmit instead. |  | 
|  1683     CreateBlackFrame(&video_frame, |  | 
|  1684                      static_cast<int>(frame->GetWidth()), |  | 
|  1685                      static_cast<int>(frame->GetHeight())); |  | 
|  1686   } |  | 
|  1687  |  | 
|  1688   int64_t frame_delta_ms = frame->GetTimeStamp() / rtc::kNumNanosecsPerMillisec; |  | 
|  1689   // frame->GetTimeStamp() is essentially a delta, align to webrtc time |  | 
|  1690   if (first_frame_timestamp_ms_ == 0) { |  | 
|  1691     first_frame_timestamp_ms_ = rtc::Time() - frame_delta_ms; |  | 
|  1692   } |  | 
|  1693  |  | 
|  1694   last_frame_timestamp_ms_ = first_frame_timestamp_ms_ + frame_delta_ms; |  | 
|  1695   video_frame.set_render_time_ms(last_frame_timestamp_ms_); |  | 
|  1696   // Reconfigure codec if necessary. |  | 
|  1697   SetDimensions( |  | 
|  1698       video_frame.width(), video_frame.height(), capturer->IsScreencast()); |  | 
|  1699  |  | 
|  1700   stream_->Input()->IncomingCapturedFrame(video_frame); |  | 
|  1701 } |  | 
|  1702  |  | 
|  1703 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetCapturer( |  | 
|  1704     VideoCapturer* capturer) { |  | 
|  1705   TRACE_EVENT0("webrtc", "WebRtcVideoSendStream::SetCapturer"); |  | 
|  1706   if (!DisconnectCapturer() && capturer == NULL) { |  | 
|  1707     return false; |  | 
|  1708   } |  | 
|  1709  |  | 
|  1710   { |  | 
|  1711     rtc::CritScope cs(&lock_); |  | 
|  1712  |  | 
|  1713     // Reset timestamps to realign new incoming frames to a webrtc timestamp. A |  | 
|  1714     // new capturer may have a different timestamp delta than the previous one. |  | 
|  1715     first_frame_timestamp_ms_ = 0; |  | 
|  1716  |  | 
|  1717     if (capturer == NULL) { |  | 
|  1718       if (stream_ != NULL) { |  | 
|  1719         LOG(LS_VERBOSE) << "Disabling capturer, sending black frame."; |  | 
|  1720         webrtc::VideoFrame black_frame; |  | 
|  1721  |  | 
|  1722         CreateBlackFrame(&black_frame, last_dimensions_.width, |  | 
|  1723                          last_dimensions_.height); |  | 
|  1724  |  | 
|  1725         // Force this black frame not to be dropped due to timestamp order |  | 
|  1726         // check. As IncomingCapturedFrame will drop the frame if this frame's |  | 
|  1727         // timestamp is less than or equal to last frame's timestamp, it is |  | 
|  1728         // necessary to give this black frame a larger timestamp than the |  | 
|  1729         // previous one. |  | 
|  1730         last_frame_timestamp_ms_ += |  | 
|  1731             format_.interval / rtc::kNumNanosecsPerMillisec; |  | 
|  1732         black_frame.set_render_time_ms(last_frame_timestamp_ms_); |  | 
|  1733         stream_->Input()->IncomingCapturedFrame(black_frame); |  | 
|  1734       } |  | 
|  1735  |  | 
|  1736       capturer_ = NULL; |  | 
|  1737       return true; |  | 
|  1738     } |  | 
|  1739  |  | 
|  1740     capturer_ = capturer; |  | 
|  1741   } |  | 
|  1742   // Lock cannot be held while connecting the capturer to prevent lock-order |  | 
|  1743   // violations. |  | 
|  1744   capturer->SignalVideoFrame.connect(this, &WebRtcVideoSendStream::InputFrame); |  | 
|  1745   return true; |  | 
|  1746 } |  | 
|  1747  |  | 
|  1748 bool WebRtcVideoChannel2::WebRtcVideoSendStream::SetVideoFormat( |  | 
|  1749     const VideoFormat& format) { |  | 
|  1750   if ((format.width == 0 || format.height == 0) && |  | 
|  1751       format.width != format.height) { |  | 
|  1752     LOG(LS_ERROR) << "Can't set VideoFormat, width or height is zero (but not " |  | 
|  1753                      "both, 0x0 drops frames)."; |  | 
|  1754     return false; |  | 
|  1755   } |  | 
|  1756  |  | 
|  1757   rtc::CritScope cs(&lock_); |  | 
|  1758   if (format.width == 0 && format.height == 0) { |  | 
|  1759     LOG(LS_INFO) |  | 
|  1760         << "0x0 resolution selected. Captured frames will be dropped for ssrc: " |  | 
|  1761         << parameters_.config.rtp.ssrcs[0] << "."; |  | 
|  1762   } else { |  | 
|  1763     // TODO(pbos): Fix me, this only affects the last stream! |  | 
|  1764     parameters_.encoder_config.streams.back().max_framerate = |  | 
|  1765         VideoFormat::IntervalToFps(format.interval); |  | 
|  1766     SetDimensions(format.width, format.height, false); |  | 
|  1767   } |  | 
|  1768  |  | 
|  1769   format_ = format; |  | 
|  1770   return true; |  | 
|  1771 } |  | 
|  1772  |  | 
|  1773 void WebRtcVideoChannel2::WebRtcVideoSendStream::MuteStream(bool mute) { |  | 
|  1774   rtc::CritScope cs(&lock_); |  | 
|  1775   muted_ = mute; |  | 
|  1776 } |  | 
|  1777  |  | 
|  1778 bool WebRtcVideoChannel2::WebRtcVideoSendStream::DisconnectCapturer() { |  | 
|  1779   cricket::VideoCapturer* capturer; |  | 
|  1780   { |  | 
|  1781     rtc::CritScope cs(&lock_); |  | 
|  1782     if (capturer_ == NULL) |  | 
|  1783       return false; |  | 
|  1784  |  | 
|  1785     if (capturer_->video_adapter() != nullptr) |  | 
|  1786       old_adapt_changes_ += capturer_->video_adapter()->adaptation_changes(); |  | 
|  1787  |  | 
|  1788     capturer = capturer_; |  | 
|  1789     capturer_ = NULL; |  | 
|  1790   } |  | 
|  1791   capturer->SignalVideoFrame.disconnect(this); |  | 
|  1792   return true; |  | 
|  1793 } |  | 
|  1794  |  | 
|  1795 const std::vector<uint32_t>& |  | 
|  1796 WebRtcVideoChannel2::WebRtcVideoSendStream::GetSsrcs() const { |  | 
|  1797   return ssrcs_; |  | 
|  1798 } |  | 
|  1799  |  | 
|  1800 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetApplyRotation( |  | 
|  1801     bool apply_rotation) { |  | 
|  1802   rtc::CritScope cs(&lock_); |  | 
|  1803   if (capturer_ == NULL) |  | 
|  1804     return; |  | 
|  1805  |  | 
|  1806   capturer_->SetApplyRotation(apply_rotation); |  | 
|  1807 } |  | 
|  1808  |  | 
|  1809 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetOptions( |  | 
|  1810     const VideoOptions& options) { |  | 
|  1811   rtc::CritScope cs(&lock_); |  | 
|  1812   if (parameters_.codec_settings) { |  | 
|  1813     LOG(LS_INFO) << "SetCodecAndOptions because of SetOptions; options=" |  | 
|  1814                  << options.ToString(); |  | 
|  1815     SetCodecAndOptions(*parameters_.codec_settings, options); |  | 
|  1816   } else { |  | 
|  1817     parameters_.options = options; |  | 
|  1818   } |  | 
|  1819 } |  | 
|  1820  |  | 
|  1821 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodec( |  | 
|  1822     const VideoCodecSettings& codec_settings) { |  | 
|  1823   rtc::CritScope cs(&lock_); |  | 
|  1824   LOG(LS_INFO) << "SetCodecAndOptions because of SetCodec."; |  | 
|  1825   SetCodecAndOptions(codec_settings, parameters_.options); |  | 
|  1826 } |  | 
|  1827  |  | 
|  1828 webrtc::VideoCodecType CodecTypeFromName(const std::string& name) { |  | 
|  1829   if (CodecNamesEq(name, kVp8CodecName)) { |  | 
|  1830     return webrtc::kVideoCodecVP8; |  | 
|  1831   } else if (CodecNamesEq(name, kVp9CodecName)) { |  | 
|  1832     return webrtc::kVideoCodecVP9; |  | 
|  1833   } else if (CodecNamesEq(name, kH264CodecName)) { |  | 
|  1834     return webrtc::kVideoCodecH264; |  | 
|  1835   } |  | 
|  1836   return webrtc::kVideoCodecUnknown; |  | 
|  1837 } |  | 
|  1838  |  | 
|  1839 WebRtcVideoChannel2::WebRtcVideoSendStream::AllocatedEncoder |  | 
|  1840 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoder( |  | 
|  1841     const VideoCodec& codec) { |  | 
|  1842   webrtc::VideoCodecType type = CodecTypeFromName(codec.name); |  | 
|  1843  |  | 
|  1844   // Do not re-create encoders of the same type. |  | 
|  1845   if (type == allocated_encoder_.type && allocated_encoder_.encoder != NULL) { |  | 
|  1846     return allocated_encoder_; |  | 
|  1847   } |  | 
|  1848  |  | 
|  1849   if (external_encoder_factory_ != NULL) { |  | 
|  1850     webrtc::VideoEncoder* encoder = |  | 
|  1851         external_encoder_factory_->CreateVideoEncoder(type); |  | 
|  1852     if (encoder != NULL) { |  | 
|  1853       return AllocatedEncoder(encoder, type, true); |  | 
|  1854     } |  | 
|  1855   } |  | 
|  1856  |  | 
|  1857   if (type == webrtc::kVideoCodecVP8) { |  | 
|  1858     return AllocatedEncoder( |  | 
|  1859         webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kVp8), type, false); |  | 
|  1860   } else if (type == webrtc::kVideoCodecVP9) { |  | 
|  1861     return AllocatedEncoder( |  | 
|  1862         webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kVp9), type, false); |  | 
|  1863   } else if (type == webrtc::kVideoCodecH264) { |  | 
|  1864     return AllocatedEncoder( |  | 
|  1865         webrtc::VideoEncoder::Create(webrtc::VideoEncoder::kH264), type, false); |  | 
|  1866   } |  | 
|  1867  |  | 
|  1868   // This shouldn't happen, we should not be trying to create something we don't |  | 
|  1869   // support. |  | 
|  1870   RTC_DCHECK(false); |  | 
|  1871   return AllocatedEncoder(NULL, webrtc::kVideoCodecUnknown, false); |  | 
|  1872 } |  | 
|  1873  |  | 
|  1874 void WebRtcVideoChannel2::WebRtcVideoSendStream::DestroyVideoEncoder( |  | 
|  1875     AllocatedEncoder* encoder) { |  | 
|  1876   if (encoder->external) { |  | 
|  1877     external_encoder_factory_->DestroyVideoEncoder(encoder->external_encoder); |  | 
|  1878   } |  | 
|  1879   delete encoder->encoder; |  | 
|  1880 } |  | 
|  1881  |  | 
|  1882 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetCodecAndOptions( |  | 
|  1883     const VideoCodecSettings& codec_settings, |  | 
|  1884     const VideoOptions& options) { |  | 
|  1885   parameters_.encoder_config = |  | 
|  1886       CreateVideoEncoderConfig(last_dimensions_, codec_settings.codec); |  | 
|  1887   if (parameters_.encoder_config.streams.empty()) |  | 
|  1888     return; |  | 
|  1889  |  | 
|  1890   format_ = VideoFormat(codec_settings.codec.width, |  | 
|  1891                         codec_settings.codec.height, |  | 
|  1892                         VideoFormat::FpsToInterval(30), |  | 
|  1893                         FOURCC_I420); |  | 
|  1894  |  | 
|  1895   AllocatedEncoder new_encoder = CreateVideoEncoder(codec_settings.codec); |  | 
|  1896   parameters_.config.encoder_settings.encoder = new_encoder.encoder; |  | 
|  1897   parameters_.config.encoder_settings.payload_name = codec_settings.codec.name; |  | 
|  1898   parameters_.config.encoder_settings.payload_type = codec_settings.codec.id; |  | 
|  1899   if (new_encoder.external) { |  | 
|  1900     webrtc::VideoCodecType type = CodecTypeFromName(codec_settings.codec.name); |  | 
|  1901     parameters_.config.encoder_settings.internal_source = |  | 
|  1902         external_encoder_factory_->EncoderTypeHasInternalSource(type); |  | 
|  1903   } |  | 
|  1904   parameters_.config.rtp.fec = codec_settings.fec; |  | 
|  1905  |  | 
|  1906   // Set RTX payload type if RTX is enabled. |  | 
|  1907   if (!parameters_.config.rtp.rtx.ssrcs.empty()) { |  | 
|  1908     if (codec_settings.rtx_payload_type == -1) { |  | 
|  1909       LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX " |  | 
|  1910                          "payload type. Ignoring."; |  | 
|  1911       parameters_.config.rtp.rtx.ssrcs.clear(); |  | 
|  1912     } else { |  | 
|  1913       parameters_.config.rtp.rtx.payload_type = codec_settings.rtx_payload_type; |  | 
|  1914     } |  | 
|  1915   } |  | 
|  1916  |  | 
|  1917   parameters_.config.rtp.nack.rtp_history_ms = |  | 
|  1918       HasNack(codec_settings.codec) ? kNackHistoryMs : 0; |  | 
|  1919  |  | 
|  1920   RTC_CHECK(options.suspend_below_min_bitrate); |  | 
|  1921   parameters_.config.suspend_below_min_bitrate = |  | 
|  1922       *options.suspend_below_min_bitrate; |  | 
|  1923  |  | 
|  1924   parameters_.codec_settings = |  | 
|  1925       rtc::Optional<WebRtcVideoChannel2::VideoCodecSettings>(codec_settings); |  | 
|  1926   parameters_.options = options; |  | 
|  1927  |  | 
|  1928   LOG(LS_INFO) |  | 
|  1929       << "RecreateWebRtcStream (send) because of SetCodecAndOptions; options=" |  | 
|  1930       << options.ToString(); |  | 
|  1931   RecreateWebRtcStream(); |  | 
|  1932   if (allocated_encoder_.encoder != new_encoder.encoder) { |  | 
|  1933     DestroyVideoEncoder(&allocated_encoder_); |  | 
|  1934     allocated_encoder_ = new_encoder; |  | 
|  1935   } |  | 
|  1936 } |  | 
|  1937  |  | 
|  1938 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetRtpExtensions( |  | 
|  1939     const std::vector<webrtc::RtpExtension>& rtp_extensions) { |  | 
|  1940   rtc::CritScope cs(&lock_); |  | 
|  1941   parameters_.config.rtp.extensions = rtp_extensions; |  | 
|  1942   if (stream_ != nullptr) { |  | 
|  1943     LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetRtpExtensions"; |  | 
|  1944     RecreateWebRtcStream(); |  | 
|  1945   } |  | 
|  1946 } |  | 
|  1947  |  | 
|  1948 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetSendParameters( |  | 
|  1949     const VideoSendParameters& send_params) { |  | 
|  1950   rtc::CritScope cs(&lock_); |  | 
|  1951   parameters_.config.rtp.rtcp_mode = send_params.rtcp.reduced_size |  | 
|  1952                                          ? webrtc::RtcpMode::kReducedSize |  | 
|  1953                                          : webrtc::RtcpMode::kCompound; |  | 
|  1954   if (stream_ != nullptr) { |  | 
|  1955     LOG(LS_INFO) << "RecreateWebRtcStream (send) because of SetSendParameters"; |  | 
|  1956     RecreateWebRtcStream(); |  | 
|  1957   } |  | 
|  1958 } |  | 
|  1959  |  | 
|  1960 webrtc::VideoEncoderConfig |  | 
|  1961 WebRtcVideoChannel2::WebRtcVideoSendStream::CreateVideoEncoderConfig( |  | 
|  1962     const Dimensions& dimensions, |  | 
|  1963     const VideoCodec& codec) const { |  | 
|  1964   webrtc::VideoEncoderConfig encoder_config; |  | 
|  1965   if (dimensions.is_screencast) { |  | 
|  1966     RTC_CHECK(parameters_.options.screencast_min_bitrate); |  | 
|  1967     encoder_config.min_transmit_bitrate_bps = |  | 
|  1968         *parameters_.options.screencast_min_bitrate * 1000; |  | 
|  1969     encoder_config.content_type = |  | 
|  1970         webrtc::VideoEncoderConfig::ContentType::kScreen; |  | 
|  1971   } else { |  | 
|  1972     encoder_config.min_transmit_bitrate_bps = 0; |  | 
|  1973     encoder_config.content_type = |  | 
|  1974         webrtc::VideoEncoderConfig::ContentType::kRealtimeVideo; |  | 
|  1975   } |  | 
|  1976  |  | 
|  1977   // Restrict dimensions according to codec max. |  | 
|  1978   int width = dimensions.width; |  | 
|  1979   int height = dimensions.height; |  | 
|  1980   if (!dimensions.is_screencast) { |  | 
|  1981     if (codec.width < width) |  | 
|  1982       width = codec.width; |  | 
|  1983     if (codec.height < height) |  | 
|  1984       height = codec.height; |  | 
|  1985   } |  | 
|  1986  |  | 
|  1987   VideoCodec clamped_codec = codec; |  | 
|  1988   clamped_codec.width = width; |  | 
|  1989   clamped_codec.height = height; |  | 
|  1990  |  | 
|  1991   // By default, the stream count for the codec configuration should match the |  | 
|  1992   // number of negotiated ssrcs. But if the codec is blacklisted for simulcast |  | 
|  1993   // or a screencast, only configure a single stream. |  | 
|  1994   size_t stream_count = parameters_.config.rtp.ssrcs.size(); |  | 
|  1995   if (IsCodecBlacklistedForSimulcast(codec.name) || dimensions.is_screencast) { |  | 
|  1996     stream_count = 1; |  | 
|  1997   } |  | 
|  1998  |  | 
|  1999   encoder_config.streams = |  | 
|  2000       CreateVideoStreams(clamped_codec, parameters_.options, |  | 
|  2001                          parameters_.max_bitrate_bps, stream_count); |  | 
|  2002  |  | 
|  2003   // Conference mode screencast uses 2 temporal layers split at 100kbit. |  | 
|  2004   if (parameters_.options.conference_mode.value_or(false) && |  | 
|  2005       dimensions.is_screencast && encoder_config.streams.size() == 1) { |  | 
|  2006     ScreenshareLayerConfig config = ScreenshareLayerConfig::GetDefault(); |  | 
|  2007  |  | 
|  2008     // For screenshare in conference mode, tl0 and tl1 bitrates are piggybacked |  | 
|  2009     // on the VideoCodec struct as target and max bitrates, respectively. |  | 
|  2010     // See eg. webrtc::VP8EncoderImpl::SetRates(). |  | 
|  2011     encoder_config.streams[0].target_bitrate_bps = |  | 
|  2012         config.tl0_bitrate_kbps * 1000; |  | 
|  2013     encoder_config.streams[0].max_bitrate_bps = config.tl1_bitrate_kbps * 1000; |  | 
|  2014     encoder_config.streams[0].temporal_layer_thresholds_bps.clear(); |  | 
|  2015     encoder_config.streams[0].temporal_layer_thresholds_bps.push_back( |  | 
|  2016         config.tl0_bitrate_kbps * 1000); |  | 
|  2017   } |  | 
|  2018   return encoder_config; |  | 
|  2019 } |  | 
|  2020  |  | 
|  2021 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetDimensions( |  | 
|  2022     int width, |  | 
|  2023     int height, |  | 
|  2024     bool is_screencast) { |  | 
|  2025   if (last_dimensions_.width == width && last_dimensions_.height == height && |  | 
|  2026       last_dimensions_.is_screencast == is_screencast) { |  | 
|  2027     // Configured using the same parameters, do not reconfigure. |  | 
|  2028     return; |  | 
|  2029   } |  | 
|  2030   LOG(LS_INFO) << "SetDimensions: " << width << "x" << height |  | 
|  2031                << (is_screencast ? " (screencast)" : " (not screencast)"); |  | 
|  2032  |  | 
|  2033   last_dimensions_.width = width; |  | 
|  2034   last_dimensions_.height = height; |  | 
|  2035   last_dimensions_.is_screencast = is_screencast; |  | 
|  2036  |  | 
|  2037   RTC_DCHECK(!parameters_.encoder_config.streams.empty()); |  | 
|  2038  |  | 
|  2039   RTC_CHECK(parameters_.codec_settings); |  | 
|  2040   VideoCodecSettings codec_settings = *parameters_.codec_settings; |  | 
|  2041  |  | 
|  2042   webrtc::VideoEncoderConfig encoder_config = |  | 
|  2043       CreateVideoEncoderConfig(last_dimensions_, codec_settings.codec); |  | 
|  2044  |  | 
|  2045   encoder_config.encoder_specific_settings = ConfigureVideoEncoderSettings( |  | 
|  2046       codec_settings.codec, parameters_.options, is_screencast); |  | 
|  2047  |  | 
|  2048   bool stream_reconfigured = stream_->ReconfigureVideoEncoder(encoder_config); |  | 
|  2049  |  | 
|  2050   encoder_config.encoder_specific_settings = NULL; |  | 
|  2051  |  | 
|  2052   if (!stream_reconfigured) { |  | 
|  2053     LOG(LS_WARNING) << "Failed to reconfigure video encoder for dimensions: " |  | 
|  2054                     << width << "x" << height; |  | 
|  2055     return; |  | 
|  2056   } |  | 
|  2057  |  | 
|  2058   parameters_.encoder_config = encoder_config; |  | 
|  2059 } |  | 
|  2060  |  | 
|  2061 void WebRtcVideoChannel2::WebRtcVideoSendStream::Start() { |  | 
|  2062   rtc::CritScope cs(&lock_); |  | 
|  2063   RTC_DCHECK(stream_ != NULL); |  | 
|  2064   stream_->Start(); |  | 
|  2065   sending_ = true; |  | 
|  2066 } |  | 
|  2067  |  | 
|  2068 void WebRtcVideoChannel2::WebRtcVideoSendStream::Stop() { |  | 
|  2069   rtc::CritScope cs(&lock_); |  | 
|  2070   if (stream_ != NULL) { |  | 
|  2071     stream_->Stop(); |  | 
|  2072   } |  | 
|  2073   sending_ = false; |  | 
|  2074 } |  | 
|  2075  |  | 
|  2076 VideoSenderInfo |  | 
|  2077 WebRtcVideoChannel2::WebRtcVideoSendStream::GetVideoSenderInfo() { |  | 
|  2078   VideoSenderInfo info; |  | 
|  2079   webrtc::VideoSendStream::Stats stats; |  | 
|  2080   { |  | 
|  2081     rtc::CritScope cs(&lock_); |  | 
|  2082     for (uint32_t ssrc : parameters_.config.rtp.ssrcs) |  | 
|  2083       info.add_ssrc(ssrc); |  | 
|  2084  |  | 
|  2085     if (parameters_.codec_settings) |  | 
|  2086       info.codec_name = parameters_.codec_settings->codec.name; |  | 
|  2087     for (size_t i = 0; i < parameters_.encoder_config.streams.size(); ++i) { |  | 
|  2088       if (i == parameters_.encoder_config.streams.size() - 1) { |  | 
|  2089         info.preferred_bitrate += |  | 
|  2090             parameters_.encoder_config.streams[i].max_bitrate_bps; |  | 
|  2091       } else { |  | 
|  2092         info.preferred_bitrate += |  | 
|  2093             parameters_.encoder_config.streams[i].target_bitrate_bps; |  | 
|  2094       } |  | 
|  2095     } |  | 
|  2096  |  | 
|  2097     if (stream_ == NULL) |  | 
|  2098       return info; |  | 
|  2099  |  | 
|  2100     stats = stream_->GetStats(); |  | 
|  2101  |  | 
|  2102     info.adapt_changes = old_adapt_changes_; |  | 
|  2103     info.adapt_reason = CoordinatedVideoAdapter::ADAPTREASON_NONE; |  | 
|  2104  |  | 
|  2105     if (capturer_ != NULL) { |  | 
|  2106       if (!capturer_->IsMuted()) { |  | 
|  2107         VideoFormat last_captured_frame_format; |  | 
|  2108         capturer_->GetStats(&info.adapt_frame_drops, &info.effects_frame_drops, |  | 
|  2109                             &info.capturer_frame_time, |  | 
|  2110                             &last_captured_frame_format); |  | 
|  2111         info.input_frame_width = last_captured_frame_format.width; |  | 
|  2112         info.input_frame_height = last_captured_frame_format.height; |  | 
|  2113       } |  | 
|  2114       if (capturer_->video_adapter() != nullptr) { |  | 
|  2115         info.adapt_changes += capturer_->video_adapter()->adaptation_changes(); |  | 
|  2116         info.adapt_reason = capturer_->video_adapter()->adapt_reason(); |  | 
|  2117       } |  | 
|  2118     } |  | 
|  2119   } |  | 
|  2120  |  | 
|  2121   // Get bandwidth limitation info from stream_->GetStats(). |  | 
|  2122   // Input resolution (output from video_adapter) can be further scaled down or |  | 
|  2123   // higher video layer(s) can be dropped due to bitrate constraints. |  | 
|  2124   // Note, adapt_changes only include changes from the video_adapter. |  | 
|  2125   if (stats.bw_limited_resolution) |  | 
|  2126     info.adapt_reason |= CoordinatedVideoAdapter::ADAPTREASON_BANDWIDTH; |  | 
|  2127  |  | 
|  2128   info.encoder_implementation_name = stats.encoder_implementation_name; |  | 
|  2129   info.ssrc_groups = ssrc_groups_; |  | 
|  2130   info.framerate_input = stats.input_frame_rate; |  | 
|  2131   info.framerate_sent = stats.encode_frame_rate; |  | 
|  2132   info.avg_encode_ms = stats.avg_encode_time_ms; |  | 
|  2133   info.encode_usage_percent = stats.encode_usage_percent; |  | 
|  2134  |  | 
|  2135   info.nominal_bitrate = stats.media_bitrate_bps; |  | 
|  2136  |  | 
|  2137   info.send_frame_width = 0; |  | 
|  2138   info.send_frame_height = 0; |  | 
|  2139   for (std::map<uint32_t, webrtc::VideoSendStream::StreamStats>::iterator it = |  | 
|  2140            stats.substreams.begin(); |  | 
|  2141        it != stats.substreams.end(); ++it) { |  | 
|  2142     // TODO(pbos): Wire up additional stats, such as padding bytes. |  | 
|  2143     webrtc::VideoSendStream::StreamStats stream_stats = it->second; |  | 
|  2144     info.bytes_sent += stream_stats.rtp_stats.transmitted.payload_bytes + |  | 
|  2145                        stream_stats.rtp_stats.transmitted.header_bytes + |  | 
|  2146                        stream_stats.rtp_stats.transmitted.padding_bytes; |  | 
|  2147     info.packets_sent += stream_stats.rtp_stats.transmitted.packets; |  | 
|  2148     info.packets_lost += stream_stats.rtcp_stats.cumulative_lost; |  | 
|  2149     if (stream_stats.width > info.send_frame_width) |  | 
|  2150       info.send_frame_width = stream_stats.width; |  | 
|  2151     if (stream_stats.height > info.send_frame_height) |  | 
|  2152       info.send_frame_height = stream_stats.height; |  | 
|  2153     info.firs_rcvd += stream_stats.rtcp_packet_type_counts.fir_packets; |  | 
|  2154     info.nacks_rcvd += stream_stats.rtcp_packet_type_counts.nack_packets; |  | 
|  2155     info.plis_rcvd += stream_stats.rtcp_packet_type_counts.pli_packets; |  | 
|  2156   } |  | 
|  2157  |  | 
|  2158   if (!stats.substreams.empty()) { |  | 
|  2159     // TODO(pbos): Report fraction lost per SSRC. |  | 
|  2160     webrtc::VideoSendStream::StreamStats first_stream_stats = |  | 
|  2161         stats.substreams.begin()->second; |  | 
|  2162     info.fraction_lost = |  | 
|  2163         static_cast<float>(first_stream_stats.rtcp_stats.fraction_lost) / |  | 
|  2164         (1 << 8); |  | 
|  2165   } |  | 
|  2166  |  | 
|  2167   return info; |  | 
|  2168 } |  | 
|  2169  |  | 
|  2170 void WebRtcVideoChannel2::WebRtcVideoSendStream::FillBandwidthEstimationInfo( |  | 
|  2171     BandwidthEstimationInfo* bwe_info) { |  | 
|  2172   rtc::CritScope cs(&lock_); |  | 
|  2173   if (stream_ == NULL) { |  | 
|  2174     return; |  | 
|  2175   } |  | 
|  2176   webrtc::VideoSendStream::Stats stats = stream_->GetStats(); |  | 
|  2177   for (std::map<uint32_t, webrtc::VideoSendStream::StreamStats>::iterator it = |  | 
|  2178            stats.substreams.begin(); |  | 
|  2179        it != stats.substreams.end(); ++it) { |  | 
|  2180     bwe_info->transmit_bitrate += it->second.total_bitrate_bps; |  | 
|  2181     bwe_info->retransmit_bitrate += it->second.retransmit_bitrate_bps; |  | 
|  2182   } |  | 
|  2183   bwe_info->target_enc_bitrate += stats.target_media_bitrate_bps; |  | 
|  2184   bwe_info->actual_enc_bitrate += stats.media_bitrate_bps; |  | 
|  2185 } |  | 
|  2186  |  | 
|  2187 void WebRtcVideoChannel2::WebRtcVideoSendStream::SetMaxBitrateBps( |  | 
|  2188     int max_bitrate_bps) { |  | 
|  2189   rtc::CritScope cs(&lock_); |  | 
|  2190   parameters_.max_bitrate_bps = max_bitrate_bps; |  | 
|  2191  |  | 
|  2192   // No need to reconfigure if the stream hasn't been configured yet. |  | 
|  2193   if (parameters_.encoder_config.streams.empty()) |  | 
|  2194     return; |  | 
|  2195  |  | 
|  2196   // Force a stream reconfigure to set the new max bitrate. |  | 
|  2197   int width = last_dimensions_.width; |  | 
|  2198   last_dimensions_.width = 0; |  | 
|  2199   SetDimensions(width, last_dimensions_.height, last_dimensions_.is_screencast); |  | 
|  2200 } |  | 
|  2201  |  | 
|  2202 void WebRtcVideoChannel2::WebRtcVideoSendStream::RecreateWebRtcStream() { |  | 
|  2203   if (stream_ != NULL) { |  | 
|  2204     call_->DestroyVideoSendStream(stream_); |  | 
|  2205   } |  | 
|  2206  |  | 
|  2207   RTC_CHECK(parameters_.codec_settings); |  | 
|  2208   parameters_.encoder_config.encoder_specific_settings = |  | 
|  2209       ConfigureVideoEncoderSettings( |  | 
|  2210           parameters_.codec_settings->codec, parameters_.options, |  | 
|  2211           parameters_.encoder_config.content_type == |  | 
|  2212               webrtc::VideoEncoderConfig::ContentType::kScreen); |  | 
|  2213  |  | 
|  2214   webrtc::VideoSendStream::Config config = parameters_.config; |  | 
|  2215   if (!config.rtp.rtx.ssrcs.empty() && config.rtp.rtx.payload_type == -1) { |  | 
|  2216     LOG(LS_WARNING) << "RTX SSRCs configured but there's no configured RTX " |  | 
|  2217                        "payload type the set codec. Ignoring RTX."; |  | 
|  2218     config.rtp.rtx.ssrcs.clear(); |  | 
|  2219   } |  | 
|  2220   stream_ = call_->CreateVideoSendStream(config, parameters_.encoder_config); |  | 
|  2221  |  | 
|  2222   parameters_.encoder_config.encoder_specific_settings = NULL; |  | 
|  2223  |  | 
|  2224   if (sending_) { |  | 
|  2225     stream_->Start(); |  | 
|  2226   } |  | 
|  2227 } |  | 
|  2228  |  | 
|  2229 WebRtcVideoChannel2::WebRtcVideoReceiveStream::WebRtcVideoReceiveStream( |  | 
|  2230     webrtc::Call* call, |  | 
|  2231     const StreamParams& sp, |  | 
|  2232     const webrtc::VideoReceiveStream::Config& config, |  | 
|  2233     WebRtcVideoDecoderFactory* external_decoder_factory, |  | 
|  2234     bool default_stream, |  | 
|  2235     const std::vector<VideoCodecSettings>& recv_codecs, |  | 
|  2236     bool disable_prerenderer_smoothing) |  | 
|  2237     : call_(call), |  | 
|  2238       ssrcs_(sp.ssrcs), |  | 
|  2239       ssrc_groups_(sp.ssrc_groups), |  | 
|  2240       stream_(NULL), |  | 
|  2241       default_stream_(default_stream), |  | 
|  2242       config_(config), |  | 
|  2243       external_decoder_factory_(external_decoder_factory), |  | 
|  2244       disable_prerenderer_smoothing_(disable_prerenderer_smoothing), |  | 
|  2245       renderer_(NULL), |  | 
|  2246       last_width_(-1), |  | 
|  2247       last_height_(-1), |  | 
|  2248       first_frame_timestamp_(-1), |  | 
|  2249       estimated_remote_start_ntp_time_ms_(0) { |  | 
|  2250   config_.renderer = this; |  | 
|  2251   // SetRecvCodecs will also reset (start) the VideoReceiveStream. |  | 
|  2252   LOG(LS_INFO) << "SetRecvCodecs (recv) because we are creating the receive " |  | 
|  2253                   "stream for the first time: " |  | 
|  2254                << CodecSettingsVectorToString(recv_codecs); |  | 
|  2255   SetRecvCodecs(recv_codecs); |  | 
|  2256 } |  | 
|  2257  |  | 
|  2258 WebRtcVideoChannel2::WebRtcVideoReceiveStream::AllocatedDecoder:: |  | 
|  2259     AllocatedDecoder(webrtc::VideoDecoder* decoder, |  | 
|  2260                      webrtc::VideoCodecType type, |  | 
|  2261                      bool external) |  | 
|  2262     : decoder(decoder), |  | 
|  2263       external_decoder(nullptr), |  | 
|  2264       type(type), |  | 
|  2265       external(external) { |  | 
|  2266   if (external) { |  | 
|  2267     external_decoder = decoder; |  | 
|  2268     this->decoder = |  | 
|  2269         new webrtc::VideoDecoderSoftwareFallbackWrapper(type, external_decoder); |  | 
|  2270   } |  | 
|  2271 } |  | 
|  2272  |  | 
|  2273 WebRtcVideoChannel2::WebRtcVideoReceiveStream::~WebRtcVideoReceiveStream() { |  | 
|  2274   call_->DestroyVideoReceiveStream(stream_); |  | 
|  2275   ClearDecoders(&allocated_decoders_); |  | 
|  2276 } |  | 
|  2277  |  | 
|  2278 const std::vector<uint32_t>& |  | 
|  2279 WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetSsrcs() const { |  | 
|  2280   return ssrcs_; |  | 
|  2281 } |  | 
|  2282  |  | 
|  2283 WebRtcVideoChannel2::WebRtcVideoReceiveStream::AllocatedDecoder |  | 
|  2284 WebRtcVideoChannel2::WebRtcVideoReceiveStream::CreateOrReuseVideoDecoder( |  | 
|  2285     std::vector<AllocatedDecoder>* old_decoders, |  | 
|  2286     const VideoCodec& codec) { |  | 
|  2287   webrtc::VideoCodecType type = CodecTypeFromName(codec.name); |  | 
|  2288  |  | 
|  2289   for (size_t i = 0; i < old_decoders->size(); ++i) { |  | 
|  2290     if ((*old_decoders)[i].type == type) { |  | 
|  2291       AllocatedDecoder decoder = (*old_decoders)[i]; |  | 
|  2292       (*old_decoders)[i] = old_decoders->back(); |  | 
|  2293       old_decoders->pop_back(); |  | 
|  2294       return decoder; |  | 
|  2295     } |  | 
|  2296   } |  | 
|  2297  |  | 
|  2298   if (external_decoder_factory_ != NULL) { |  | 
|  2299     webrtc::VideoDecoder* decoder = |  | 
|  2300         external_decoder_factory_->CreateVideoDecoder(type); |  | 
|  2301     if (decoder != NULL) { |  | 
|  2302       return AllocatedDecoder(decoder, type, true); |  | 
|  2303     } |  | 
|  2304   } |  | 
|  2305  |  | 
|  2306   if (type == webrtc::kVideoCodecVP8) { |  | 
|  2307     return AllocatedDecoder( |  | 
|  2308         webrtc::VideoDecoder::Create(webrtc::VideoDecoder::kVp8), type, false); |  | 
|  2309   } |  | 
|  2310  |  | 
|  2311   if (type == webrtc::kVideoCodecVP9) { |  | 
|  2312     return AllocatedDecoder( |  | 
|  2313         webrtc::VideoDecoder::Create(webrtc::VideoDecoder::kVp9), type, false); |  | 
|  2314   } |  | 
|  2315  |  | 
|  2316   if (type == webrtc::kVideoCodecH264) { |  | 
|  2317     return AllocatedDecoder( |  | 
|  2318         webrtc::VideoDecoder::Create(webrtc::VideoDecoder::kH264), type, false); |  | 
|  2319   } |  | 
|  2320  |  | 
|  2321   // This shouldn't happen, we should not be trying to create something we don't |  | 
|  2322   // support. |  | 
|  2323   RTC_DCHECK(false); |  | 
|  2324   return AllocatedDecoder(NULL, webrtc::kVideoCodecUnknown, false); |  | 
|  2325 } |  | 
|  2326  |  | 
|  2327 void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvCodecs( |  | 
|  2328     const std::vector<VideoCodecSettings>& recv_codecs) { |  | 
|  2329   std::vector<AllocatedDecoder> old_decoders = allocated_decoders_; |  | 
|  2330   allocated_decoders_.clear(); |  | 
|  2331   config_.decoders.clear(); |  | 
|  2332   for (size_t i = 0; i < recv_codecs.size(); ++i) { |  | 
|  2333     AllocatedDecoder allocated_decoder = |  | 
|  2334         CreateOrReuseVideoDecoder(&old_decoders, recv_codecs[i].codec); |  | 
|  2335     allocated_decoders_.push_back(allocated_decoder); |  | 
|  2336  |  | 
|  2337     webrtc::VideoReceiveStream::Decoder decoder; |  | 
|  2338     decoder.decoder = allocated_decoder.decoder; |  | 
|  2339     decoder.payload_type = recv_codecs[i].codec.id; |  | 
|  2340     decoder.payload_name = recv_codecs[i].codec.name; |  | 
|  2341     config_.decoders.push_back(decoder); |  | 
|  2342   } |  | 
|  2343  |  | 
|  2344   // TODO(pbos): Reconfigure RTX based on incoming recv_codecs. |  | 
|  2345   config_.rtp.fec = recv_codecs.front().fec; |  | 
|  2346   config_.rtp.nack.rtp_history_ms = |  | 
|  2347       HasNack(recv_codecs.begin()->codec) ? kNackHistoryMs : 0; |  | 
|  2348  |  | 
|  2349   LOG(LS_INFO) << "RecreateWebRtcStream (recv) because of SetRecvCodecs: " |  | 
|  2350                << CodecSettingsVectorToString(recv_codecs); |  | 
|  2351   RecreateWebRtcStream(); |  | 
|  2352   ClearDecoders(&old_decoders); |  | 
|  2353 } |  | 
|  2354  |  | 
|  2355 void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetLocalSsrc( |  | 
|  2356     uint32_t local_ssrc) { |  | 
|  2357   // TODO(pbos): Consider turning this sanity check into a RTC_DCHECK. You |  | 
|  2358   // should not be able to create a sender with the same SSRC as a receiver, but |  | 
|  2359   // right now this can't be done due to unittests depending on receiving what |  | 
|  2360   // they are sending from the same MediaChannel. |  | 
|  2361   if (local_ssrc == config_.rtp.remote_ssrc) { |  | 
|  2362     LOG(LS_INFO) << "Ignoring call to SetLocalSsrc because parameters are " |  | 
|  2363                     "unchanged; local_ssrc=" << local_ssrc; |  | 
|  2364     return; |  | 
|  2365   } |  | 
|  2366  |  | 
|  2367   config_.rtp.local_ssrc = local_ssrc; |  | 
|  2368   LOG(LS_INFO) |  | 
|  2369       << "RecreateWebRtcStream (recv) because of SetLocalSsrc; local_ssrc=" |  | 
|  2370       << local_ssrc; |  | 
|  2371   RecreateWebRtcStream(); |  | 
|  2372 } |  | 
|  2373  |  | 
|  2374 void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetFeedbackParameters( |  | 
|  2375     bool nack_enabled, |  | 
|  2376     bool remb_enabled, |  | 
|  2377     bool transport_cc_enabled) { |  | 
|  2378   int nack_history_ms = nack_enabled ? kNackHistoryMs : 0; |  | 
|  2379   if (config_.rtp.nack.rtp_history_ms == nack_history_ms && |  | 
|  2380       config_.rtp.remb == remb_enabled && |  | 
|  2381       config_.rtp.transport_cc == transport_cc_enabled) { |  | 
|  2382     LOG(LS_INFO) |  | 
|  2383         << "Ignoring call to SetFeedbackParameters because parameters are " |  | 
|  2384            "unchanged; nack=" |  | 
|  2385         << nack_enabled << ", remb=" << remb_enabled |  | 
|  2386         << ", transport_cc=" << transport_cc_enabled; |  | 
|  2387     return; |  | 
|  2388   } |  | 
|  2389   config_.rtp.remb = remb_enabled; |  | 
|  2390   config_.rtp.nack.rtp_history_ms = nack_history_ms; |  | 
|  2391   config_.rtp.transport_cc = transport_cc_enabled; |  | 
|  2392   LOG(LS_INFO) |  | 
|  2393       << "RecreateWebRtcStream (recv) because of SetFeedbackParameters; nack=" |  | 
|  2394       << nack_enabled << ", remb=" << remb_enabled |  | 
|  2395       << ", transport_cc=" << transport_cc_enabled; |  | 
|  2396   RecreateWebRtcStream(); |  | 
|  2397 } |  | 
|  2398  |  | 
|  2399 void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRtpExtensions( |  | 
|  2400     const std::vector<webrtc::RtpExtension>& extensions) { |  | 
|  2401   config_.rtp.extensions = extensions; |  | 
|  2402   LOG(LS_INFO) << "RecreateWebRtcStream (recv) because of SetRtpExtensions"; |  | 
|  2403   RecreateWebRtcStream(); |  | 
|  2404 } |  | 
|  2405  |  | 
|  2406 void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRecvParameters( |  | 
|  2407     const VideoRecvParameters& recv_params) { |  | 
|  2408   config_.rtp.rtcp_mode = recv_params.rtcp.reduced_size |  | 
|  2409                               ? webrtc::RtcpMode::kReducedSize |  | 
|  2410                               : webrtc::RtcpMode::kCompound; |  | 
|  2411   LOG(LS_INFO) << "RecreateWebRtcStream (recv) because of SetRecvParameters"; |  | 
|  2412   RecreateWebRtcStream(); |  | 
|  2413 } |  | 
|  2414  |  | 
|  2415 void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RecreateWebRtcStream() { |  | 
|  2416   if (stream_ != NULL) { |  | 
|  2417     call_->DestroyVideoReceiveStream(stream_); |  | 
|  2418   } |  | 
|  2419   stream_ = call_->CreateVideoReceiveStream(config_); |  | 
|  2420   stream_->Start(); |  | 
|  2421 } |  | 
|  2422  |  | 
|  2423 void WebRtcVideoChannel2::WebRtcVideoReceiveStream::ClearDecoders( |  | 
|  2424     std::vector<AllocatedDecoder>* allocated_decoders) { |  | 
|  2425   for (size_t i = 0; i < allocated_decoders->size(); ++i) { |  | 
|  2426     if ((*allocated_decoders)[i].external) { |  | 
|  2427       external_decoder_factory_->DestroyVideoDecoder( |  | 
|  2428           (*allocated_decoders)[i].external_decoder); |  | 
|  2429     } |  | 
|  2430     delete (*allocated_decoders)[i].decoder; |  | 
|  2431   } |  | 
|  2432   allocated_decoders->clear(); |  | 
|  2433 } |  | 
|  2434  |  | 
|  2435 void WebRtcVideoChannel2::WebRtcVideoReceiveStream::RenderFrame( |  | 
|  2436     const webrtc::VideoFrame& frame, |  | 
|  2437     int time_to_render_ms) { |  | 
|  2438   rtc::CritScope crit(&renderer_lock_); |  | 
|  2439  |  | 
|  2440   if (first_frame_timestamp_ < 0) |  | 
|  2441     first_frame_timestamp_ = frame.timestamp(); |  | 
|  2442   int64_t rtp_time_elapsed_since_first_frame = |  | 
|  2443       (timestamp_wraparound_handler_.Unwrap(frame.timestamp()) - |  | 
|  2444        first_frame_timestamp_); |  | 
|  2445   int64_t elapsed_time_ms = rtp_time_elapsed_since_first_frame / |  | 
|  2446                             (cricket::kVideoCodecClockrate / 1000); |  | 
|  2447   if (frame.ntp_time_ms() > 0) |  | 
|  2448     estimated_remote_start_ntp_time_ms_ = frame.ntp_time_ms() - elapsed_time_ms; |  | 
|  2449  |  | 
|  2450   if (renderer_ == NULL) { |  | 
|  2451     LOG(LS_WARNING) << "VideoReceiveStream not connected to a VideoRenderer."; |  | 
|  2452     return; |  | 
|  2453   } |  | 
|  2454  |  | 
|  2455   if (frame.width() != last_width_ || frame.height() != last_height_) { |  | 
|  2456     SetSize(frame.width(), frame.height()); |  | 
|  2457   } |  | 
|  2458  |  | 
|  2459   const WebRtcVideoFrame render_frame( |  | 
|  2460       frame.video_frame_buffer(), |  | 
|  2461       frame.render_time_ms() * rtc::kNumNanosecsPerMillisec, frame.rotation()); |  | 
|  2462   renderer_->RenderFrame(&render_frame); |  | 
|  2463 } |  | 
|  2464  |  | 
|  2465 bool WebRtcVideoChannel2::WebRtcVideoReceiveStream::IsTextureSupported() const { |  | 
|  2466   return true; |  | 
|  2467 } |  | 
|  2468  |  | 
|  2469 bool WebRtcVideoChannel2::WebRtcVideoReceiveStream::SmoothsRenderedFrames() |  | 
|  2470     const { |  | 
|  2471   return disable_prerenderer_smoothing_; |  | 
|  2472 } |  | 
|  2473  |  | 
|  2474 bool WebRtcVideoChannel2::WebRtcVideoReceiveStream::IsDefaultStream() const { |  | 
|  2475   return default_stream_; |  | 
|  2476 } |  | 
|  2477  |  | 
|  2478 void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetRenderer( |  | 
|  2479     cricket::VideoRenderer* renderer) { |  | 
|  2480   rtc::CritScope crit(&renderer_lock_); |  | 
|  2481   renderer_ = renderer; |  | 
|  2482   if (renderer_ != NULL && last_width_ != -1) { |  | 
|  2483     SetSize(last_width_, last_height_); |  | 
|  2484   } |  | 
|  2485 } |  | 
|  2486  |  | 
|  2487 VideoRenderer* WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetRenderer() { |  | 
|  2488   // TODO(pbos): Remove GetRenderer and all uses of it, it's thread-unsafe by |  | 
|  2489   // design. |  | 
|  2490   rtc::CritScope crit(&renderer_lock_); |  | 
|  2491   return renderer_; |  | 
|  2492 } |  | 
|  2493  |  | 
|  2494 void WebRtcVideoChannel2::WebRtcVideoReceiveStream::SetSize(int width, |  | 
|  2495                                                             int height) { |  | 
|  2496   rtc::CritScope crit(&renderer_lock_); |  | 
|  2497   if (!renderer_->SetSize(width, height, 0)) { |  | 
|  2498     LOG(LS_ERROR) << "Could not set renderer size."; |  | 
|  2499   } |  | 
|  2500   last_width_ = width; |  | 
|  2501   last_height_ = height; |  | 
|  2502 } |  | 
|  2503  |  | 
|  2504 std::string |  | 
|  2505 WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetCodecNameFromPayloadType( |  | 
|  2506     int payload_type) { |  | 
|  2507   for (const webrtc::VideoReceiveStream::Decoder& decoder : config_.decoders) { |  | 
|  2508     if (decoder.payload_type == payload_type) { |  | 
|  2509       return decoder.payload_name; |  | 
|  2510     } |  | 
|  2511   } |  | 
|  2512   return ""; |  | 
|  2513 } |  | 
|  2514  |  | 
|  2515 VideoReceiverInfo |  | 
|  2516 WebRtcVideoChannel2::WebRtcVideoReceiveStream::GetVideoReceiverInfo() { |  | 
|  2517   VideoReceiverInfo info; |  | 
|  2518   info.ssrc_groups = ssrc_groups_; |  | 
|  2519   info.add_ssrc(config_.rtp.remote_ssrc); |  | 
|  2520   webrtc::VideoReceiveStream::Stats stats = stream_->GetStats(); |  | 
|  2521   info.decoder_implementation_name = stats.decoder_implementation_name; |  | 
|  2522   info.bytes_rcvd = stats.rtp_stats.transmitted.payload_bytes + |  | 
|  2523                     stats.rtp_stats.transmitted.header_bytes + |  | 
|  2524                     stats.rtp_stats.transmitted.padding_bytes; |  | 
|  2525   info.packets_rcvd = stats.rtp_stats.transmitted.packets; |  | 
|  2526   info.packets_lost = stats.rtcp_stats.cumulative_lost; |  | 
|  2527   info.fraction_lost = |  | 
|  2528       static_cast<float>(stats.rtcp_stats.fraction_lost) / (1 << 8); |  | 
|  2529  |  | 
|  2530   info.framerate_rcvd = stats.network_frame_rate; |  | 
|  2531   info.framerate_decoded = stats.decode_frame_rate; |  | 
|  2532   info.framerate_output = stats.render_frame_rate; |  | 
|  2533  |  | 
|  2534   { |  | 
|  2535     rtc::CritScope frame_cs(&renderer_lock_); |  | 
|  2536     info.frame_width = last_width_; |  | 
|  2537     info.frame_height = last_height_; |  | 
|  2538     info.capture_start_ntp_time_ms = estimated_remote_start_ntp_time_ms_; |  | 
|  2539   } |  | 
|  2540  |  | 
|  2541   info.decode_ms = stats.decode_ms; |  | 
|  2542   info.max_decode_ms = stats.max_decode_ms; |  | 
|  2543   info.current_delay_ms = stats.current_delay_ms; |  | 
|  2544   info.target_delay_ms = stats.target_delay_ms; |  | 
|  2545   info.jitter_buffer_ms = stats.jitter_buffer_ms; |  | 
|  2546   info.min_playout_delay_ms = stats.min_playout_delay_ms; |  | 
|  2547   info.render_delay_ms = stats.render_delay_ms; |  | 
|  2548  |  | 
|  2549   info.codec_name = GetCodecNameFromPayloadType(stats.current_payload_type); |  | 
|  2550  |  | 
|  2551   info.firs_sent = stats.rtcp_packet_type_counts.fir_packets; |  | 
|  2552   info.plis_sent = stats.rtcp_packet_type_counts.pli_packets; |  | 
|  2553   info.nacks_sent = stats.rtcp_packet_type_counts.nack_packets; |  | 
|  2554  |  | 
|  2555   return info; |  | 
|  2556 } |  | 
|  2557  |  | 
|  2558 WebRtcVideoChannel2::VideoCodecSettings::VideoCodecSettings() |  | 
|  2559     : rtx_payload_type(-1) {} |  | 
|  2560  |  | 
|  2561 bool WebRtcVideoChannel2::VideoCodecSettings::operator==( |  | 
|  2562     const WebRtcVideoChannel2::VideoCodecSettings& other) const { |  | 
|  2563   return codec == other.codec && |  | 
|  2564          fec.ulpfec_payload_type == other.fec.ulpfec_payload_type && |  | 
|  2565          fec.red_payload_type == other.fec.red_payload_type && |  | 
|  2566          fec.red_rtx_payload_type == other.fec.red_rtx_payload_type && |  | 
|  2567          rtx_payload_type == other.rtx_payload_type; |  | 
|  2568 } |  | 
|  2569  |  | 
|  2570 bool WebRtcVideoChannel2::VideoCodecSettings::operator!=( |  | 
|  2571     const WebRtcVideoChannel2::VideoCodecSettings& other) const { |  | 
|  2572   return !(*this == other); |  | 
|  2573 } |  | 
|  2574  |  | 
|  2575 std::vector<WebRtcVideoChannel2::VideoCodecSettings> |  | 
|  2576 WebRtcVideoChannel2::MapCodecs(const std::vector<VideoCodec>& codecs) { |  | 
|  2577   RTC_DCHECK(!codecs.empty()); |  | 
|  2578  |  | 
|  2579   std::vector<VideoCodecSettings> video_codecs; |  | 
|  2580   std::map<int, bool> payload_used; |  | 
|  2581   std::map<int, VideoCodec::CodecType> payload_codec_type; |  | 
|  2582   // |rtx_mapping| maps video payload type to rtx payload type. |  | 
|  2583   std::map<int, int> rtx_mapping; |  | 
|  2584  |  | 
|  2585   webrtc::FecConfig fec_settings; |  | 
|  2586  |  | 
|  2587   for (size_t i = 0; i < codecs.size(); ++i) { |  | 
|  2588     const VideoCodec& in_codec = codecs[i]; |  | 
|  2589     int payload_type = in_codec.id; |  | 
|  2590  |  | 
|  2591     if (payload_used[payload_type]) { |  | 
|  2592       LOG(LS_ERROR) << "Payload type already registered: " |  | 
|  2593                     << in_codec.ToString(); |  | 
|  2594       return std::vector<VideoCodecSettings>(); |  | 
|  2595     } |  | 
|  2596     payload_used[payload_type] = true; |  | 
|  2597     payload_codec_type[payload_type] = in_codec.GetCodecType(); |  | 
|  2598  |  | 
|  2599     switch (in_codec.GetCodecType()) { |  | 
|  2600       case VideoCodec::CODEC_RED: { |  | 
|  2601         // RED payload type, should not have duplicates. |  | 
|  2602         RTC_DCHECK(fec_settings.red_payload_type == -1); |  | 
|  2603         fec_settings.red_payload_type = in_codec.id; |  | 
|  2604         continue; |  | 
|  2605       } |  | 
|  2606  |  | 
|  2607       case VideoCodec::CODEC_ULPFEC: { |  | 
|  2608         // ULPFEC payload type, should not have duplicates. |  | 
|  2609         RTC_DCHECK(fec_settings.ulpfec_payload_type == -1); |  | 
|  2610         fec_settings.ulpfec_payload_type = in_codec.id; |  | 
|  2611         continue; |  | 
|  2612       } |  | 
|  2613  |  | 
|  2614       case VideoCodec::CODEC_RTX: { |  | 
|  2615         int associated_payload_type; |  | 
|  2616         if (!in_codec.GetParam(kCodecParamAssociatedPayloadType, |  | 
|  2617                                &associated_payload_type) || |  | 
|  2618             !IsValidRtpPayloadType(associated_payload_type)) { |  | 
|  2619           LOG(LS_ERROR) |  | 
|  2620               << "RTX codec with invalid or no associated payload type: " |  | 
|  2621               << in_codec.ToString(); |  | 
|  2622           return std::vector<VideoCodecSettings>(); |  | 
|  2623         } |  | 
|  2624         rtx_mapping[associated_payload_type] = in_codec.id; |  | 
|  2625         continue; |  | 
|  2626       } |  | 
|  2627  |  | 
|  2628       case VideoCodec::CODEC_VIDEO: |  | 
|  2629         break; |  | 
|  2630     } |  | 
|  2631  |  | 
|  2632     video_codecs.push_back(VideoCodecSettings()); |  | 
|  2633     video_codecs.back().codec = in_codec; |  | 
|  2634   } |  | 
|  2635  |  | 
|  2636   // One of these codecs should have been a video codec. Only having FEC |  | 
|  2637   // parameters into this code is a logic error. |  | 
|  2638   RTC_DCHECK(!video_codecs.empty()); |  | 
|  2639  |  | 
|  2640   for (std::map<int, int>::const_iterator it = rtx_mapping.begin(); |  | 
|  2641        it != rtx_mapping.end(); |  | 
|  2642        ++it) { |  | 
|  2643     if (!payload_used[it->first]) { |  | 
|  2644       LOG(LS_ERROR) << "RTX mapped to payload not in codec list."; |  | 
|  2645       return std::vector<VideoCodecSettings>(); |  | 
|  2646     } |  | 
|  2647     if (payload_codec_type[it->first] != VideoCodec::CODEC_VIDEO && |  | 
|  2648         payload_codec_type[it->first] != VideoCodec::CODEC_RED) { |  | 
|  2649       LOG(LS_ERROR) << "RTX not mapped to regular video codec or RED codec."; |  | 
|  2650       return std::vector<VideoCodecSettings>(); |  | 
|  2651     } |  | 
|  2652  |  | 
|  2653     if (it->first == fec_settings.red_payload_type) { |  | 
|  2654       fec_settings.red_rtx_payload_type = it->second; |  | 
|  2655     } |  | 
|  2656   } |  | 
|  2657  |  | 
|  2658   for (size_t i = 0; i < video_codecs.size(); ++i) { |  | 
|  2659     video_codecs[i].fec = fec_settings; |  | 
|  2660     if (rtx_mapping[video_codecs[i].codec.id] != 0 && |  | 
|  2661         rtx_mapping[video_codecs[i].codec.id] != |  | 
|  2662             fec_settings.red_payload_type) { |  | 
|  2663       video_codecs[i].rtx_payload_type = rtx_mapping[video_codecs[i].codec.id]; |  | 
|  2664     } |  | 
|  2665   } |  | 
|  2666  |  | 
|  2667   return video_codecs; |  | 
|  2668 } |  | 
|  2669  |  | 
|  2670 }  // namespace cricket |  | 
|  2671  |  | 
|  2672 #endif  // HAVE_WEBRTC_VIDEO |  | 
| OLD | NEW |