自己的webrtc代码版本和老师的不一样。

调用栈image.png

Channel中的SetRecvParameters

image.png
第一步,获取解码器变化的参数,然后获取最优解码器参数;
第二步,保存媒体协商时的接收到的解码器参数。

  1. bool WebRtcVideoChannel::SetRecvParameters(const VideoRecvParameters& params) {
  2. RTC_DCHECK_RUN_ON(&thread_checker_);
  3. TRACE_EVENT0("webrtc", "WebRtcVideoChannel::SetRecvParameters");
  4. RTC_DLOG(LS_INFO) << "SetRecvParameters: " << params.ToString();
  5. ChangedRecvParameters changed_params;
  6. if (!GetChangedRecvParameters(params, &changed_params)) {
  7. return false;
  8. }
  9. if (changed_params.flexfec_payload_type) {
  10. RTC_DLOG(LS_INFO) << "Changing FlexFEC payload type (recv) from "
  11. << recv_flexfec_payload_type_ << " to "
  12. << *changed_params.flexfec_payload_type;
  13. recv_flexfec_payload_type_ = *changed_params.flexfec_payload_type;
  14. }
  15. if (changed_params.rtp_header_extensions) {
  16. recv_rtp_extensions_ = *changed_params.rtp_header_extensions;
  17. }
  18. if (changed_params.codec_settings) {
  19. RTC_DLOG(LS_INFO) << "Changing recv codecs from "
  20. << CodecSettingsVectorToString(recv_codecs_) << " to "
  21. << CodecSettingsVectorToString(
  22. *changed_params.codec_settings);
  23. recv_codecs_ = *changed_params.codec_settings;
  24. }
  25. for (auto& kv : receive_streams_) {
  26. kv.second->SetRecvParameters(changed_params);
  27. }
  28. recv_params_ = params;
  29. return true;
  30. }

WebRtcVideoChannel::GetChangedRecvParameters

image.png
就是通过对比接收到的解码器信息,和创建解码器时的信息,获取改变的参数,这里忽略flexfec的参数变化。

  1. bool WebRtcVideoChannel::GetChangedRecvParameters(
  2. const VideoRecvParameters& params,
  3. ChangedRecvParameters* changed_params) const {
  4. if (!ValidateCodecFormats(params.codecs) ||
  5. !ValidateRtpExtensions(params.extensions)) {
  6. return false;
  7. }
  8. // Handle receive codecs.
  9. const std::vector<VideoCodecSettings> mapped_codecs =
  10. MapCodecs(params.codecs);
  11. if (mapped_codecs.empty()) {
  12. RTC_LOG(LS_ERROR)
  13. << "GetChangedRecvParameters called without any video codecs.";
  14. return false;
  15. }
  16. // Verify that every mapped codec is supported locally.
  17. if (params.is_stream_active) {
  18. const std::vector<VideoCodec> local_supported_codecs =
  19. GetPayloadTypesAndDefaultCodecs(decoder_factory_,
  20. /*is_decoder_factory=*/true,
  21. call_->trials());
  22. for (const VideoCodecSettings& mapped_codec : mapped_codecs) {
  23. if (!FindMatchingCodec(local_supported_codecs, mapped_codec.codec)) {
  24. RTC_LOG(LS_ERROR)
  25. << "GetChangedRecvParameters called with unsupported video codec: "
  26. << mapped_codec.codec.ToString();
  27. return false;
  28. }
  29. }
  30. }
  31. if (NonFlexfecReceiveCodecsHaveChanged(recv_codecs_, mapped_codecs)) {
  32. changed_params->codec_settings =
  33. absl::optional<std::vector<VideoCodecSettings>>(mapped_codecs);
  34. }
  35. // Handle RTP header extensions.
  36. std::vector<webrtc::RtpExtension> filtered_extensions = FilterRtpExtensions(
  37. params.extensions, webrtc::RtpExtension::IsSupportedForVideo, false,
  38. call_->trials());
  39. if (filtered_extensions != recv_rtp_extensions_) {
  40. changed_params->rtp_header_extensions =
  41. absl::optional<std::vector<webrtc::RtpExtension>>(filtered_extensions);
  42. }
  43. int flexfec_payload_type = mapped_codecs.front().flexfec_payload_type;
  44. if (flexfec_payload_type != recv_flexfec_payload_type_) {
  45. changed_params->flexfec_payload_type = flexfec_payload_type;
  46. }
  47. return true;
  48. }

WebRtcVideoChannel中的recvcodecs参数

image.png
这里是指构造WebRtcVideoChannel对象时,它的recvcodecs参数是从encoderfactory编码工厂中获取到的,这时候获取的编码的payloadtype值还是不确定的。
协商后的这个值,是从MediaSessionDescriptionFactory对象后获得的,是最终确定的编码参数值。

  1. WebRtcVideoChannel::WebRtcVideoChannel(
  2. webrtc::Call* call,
  3. const MediaConfig& config,
  4. const VideoOptions& options,
  5. const webrtc::CryptoOptions& crypto_options,
  6. webrtc::VideoEncoderFactory* encoder_factory,
  7. webrtc::VideoDecoderFactory* decoder_factory,
  8. webrtc::VideoBitrateAllocatorFactory* bitrate_allocator_factory)
  9. : VideoMediaChannel(config),
  10. worker_thread_(rtc::Thread::Current()),
  11. call_(call),
  12. unsignalled_ssrc_handler_(&default_unsignalled_ssrc_handler_),
  13. video_config_(config.video),
  14. encoder_factory_(encoder_factory),
  15. decoder_factory_(decoder_factory),
  16. bitrate_allocator_factory_(bitrate_allocator_factory),
  17. default_send_options_(options),
  18. last_stats_log_ms_(-1),
  19. discard_unknown_ssrc_packets_(
  20. IsEnabled(call_->trials(),
  21. "WebRTC-Video-DiscardPacketsWithUnknownSsrc")),
  22. crypto_options_(crypto_options),
  23. unknown_ssrc_packet_buffer_(
  24. IsEnabled(call_->trials(),
  25. "WebRTC-Video-BufferPacketsWithUnknownSsrc")
  26. ? new UnhandledPacketsBuffer()
  27. : nullptr) {
  28. RTC_DCHECK_RUN_ON(&thread_checker_);
  29. network_thread_checker_.Detach();
  30. rtcp_receiver_report_ssrc_ = kDefaultRtcpReceiverReportSsrc;
  31. sending_ = false;
  32. recv_codecs_ = MapCodecs(GetPayloadTypesAndDefaultCodecs(
  33. decoder_factory_, /*is_decoder_factory=*/true, call_->trials()));
  34. recv_flexfec_payload_type_ =
  35. recv_codecs_.empty() ? 0 : recv_codecs_.front().flexfec_payload_type;
  36. }

GetPayloadTypesAndDefaultCodecs

  1. // This function will assign dynamic payload types (in the range [96, 127]) to
  2. // the input codecs, and also add ULPFEC, RED, FlexFEC, and associated RTX
  3. // codecs for recognized codecs (VP8, VP9, H264, and RED). It will also add
  4. // default feedback params to the codecs.
  5. // is_decoder_factory is needed to keep track of the implict assumption that any
  6. // H264 decoder also supports constrained base line profile.
  7. // Also, is_decoder_factory is used to decide whether FlexFEC video format
  8. // should be advertised as supported.
  9. // TODO(kron): Perhaps it is better to move the implicit knowledge to the place
  10. // where codecs are negotiated.
  11. template <class T>
  12. std::vector<VideoCodec> GetPayloadTypesAndDefaultCodecs(
  13. const T* factory,
  14. bool is_decoder_factory,
  15. const webrtc::WebRtcKeyValueConfig& trials) {
  16. if (!factory) {
  17. return {};
  18. }
  19. std::vector<webrtc::SdpVideoFormat> supported_formats =
  20. factory->GetSupportedFormats();
  21. if (is_decoder_factory) {
  22. AddH264ConstrainedBaselineProfileToSupportedFormats(&supported_formats);
  23. }
  24. if (supported_formats.empty())
  25. return std::vector<VideoCodec>();
  26. // Due to interoperability issues with old Chrome/WebRTC versions only use
  27. // the lower range for new codecs.
  28. static const int kFirstDynamicPayloadTypeLowerRange = 35;
  29. static const int kLastDynamicPayloadTypeLowerRange = 65;
  30. static const int kFirstDynamicPayloadTypeUpperRange = 96;
  31. static const int kLastDynamicPayloadTypeUpperRange = 127;
  32. int payload_type_upper = kFirstDynamicPayloadTypeUpperRange;
  33. int payload_type_lower = kFirstDynamicPayloadTypeLowerRange;
  34. supported_formats.push_back(webrtc::SdpVideoFormat(kRedCodecName));
  35. supported_formats.push_back(webrtc::SdpVideoFormat(kUlpfecCodecName));
  36. // flexfec-03 is supported as
  37. // - receive codec unless WebRTC-FlexFEC-03-Advertised is disabled
  38. // - send codec if WebRTC-FlexFEC-03-Advertised is enabled
  39. if ((is_decoder_factory &&
  40. !IsDisabled(trials, "WebRTC-FlexFEC-03-Advertised")) ||
  41. (!is_decoder_factory &&
  42. IsEnabled(trials, "WebRTC-FlexFEC-03-Advertised"))) {
  43. webrtc::SdpVideoFormat flexfec_format(kFlexfecCodecName);
  44. // This value is currently arbitrarily set to 10 seconds. (The unit
  45. // is microseconds.) This parameter MUST be present in the SDP, but
  46. // we never use the actual value anywhere in our code however.
  47. // TODO(brandtr): Consider honouring this value in the sender and receiver.
  48. flexfec_format.parameters = {{kFlexfecFmtpRepairWindow, "10000000"}};
  49. supported_formats.push_back(flexfec_format);
  50. }
  51. std::vector<VideoCodec> output_codecs;
  52. for (const webrtc::SdpVideoFormat& format : supported_formats) {
  53. VideoCodec codec(format);
  54. bool isCodecValidForLowerRange =
  55. absl::EqualsIgnoreCase(codec.name, kFlexfecCodecName) ||
  56. absl::EqualsIgnoreCase(codec.name, kAv1CodecName);
  57. if (!isCodecValidForLowerRange) {
  58. codec.id = payload_type_upper++;
  59. } else {
  60. codec.id = payload_type_lower++;
  61. }
  62. AddDefaultFeedbackParams(&codec, trials);
  63. output_codecs.push_back(codec);
  64. if (payload_type_upper > kLastDynamicPayloadTypeUpperRange) {
  65. RTC_LOG(LS_ERROR)
  66. << "Out of dynamic payload types [96,127], skipping the rest.";
  67. // TODO(https://bugs.chromium.org/p/webrtc/issues/detail?id=12194):
  68. // continue in lower range.
  69. break;
  70. }
  71. if (payload_type_lower > kLastDynamicPayloadTypeLowerRange) {
  72. // TODO(https://bugs.chromium.org/p/webrtc/issues/detail?id=12248):
  73. // return an error.
  74. RTC_LOG(LS_ERROR)
  75. << "Out of dynamic payload types [35,65], skipping the rest.";
  76. break;
  77. }
  78. // Add associated RTX codec for non-FEC codecs.
  79. if (!absl::EqualsIgnoreCase(codec.name, kUlpfecCodecName) &&
  80. !absl::EqualsIgnoreCase(codec.name, kFlexfecCodecName)) {
  81. if (!isCodecValidForLowerRange) {
  82. output_codecs.push_back(
  83. VideoCodec::CreateRtxCodec(payload_type_upper++, codec.id));
  84. } else {
  85. output_codecs.push_back(
  86. VideoCodec::CreateRtxCodec(payload_type_lower++, codec.id));
  87. }
  88. if (payload_type_upper > kLastDynamicPayloadTypeUpperRange) {
  89. RTC_LOG(LS_ERROR)
  90. << "Out of dynamic payload types [96,127], skipping rtx.";
  91. // TODO(https://bugs.chromium.org/p/webrtc/issues/detail?id=12194):
  92. // continue in lower range.
  93. break;
  94. }
  95. if (payload_type_lower > kLastDynamicPayloadTypeLowerRange) {
  96. // TODO(https://bugs.chromium.org/p/webrtc/issues/detail?id=12248):
  97. // return an error.
  98. RTC_LOG(LS_ERROR)
  99. << "Out of dynamic payload types [35,65], skipping rtx.";
  100. break;
  101. }
  102. }
  103. }
  104. return output_codecs;
  105. }

image.png