Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(497)

Unified Diff: webrtc/modules/rtp_rtcp/source/flexfec_sender_impl.cc

Issue 2441613002: Add FlexfecSender. (Closed)
Patch Set: Feedback response 1. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/rtp_rtcp/source/flexfec_sender_impl.cc
diff --git a/webrtc/modules/rtp_rtcp/source/flexfec_sender_impl.cc b/webrtc/modules/rtp_rtcp/source/flexfec_sender_impl.cc
new file mode 100644
index 0000000000000000000000000000000000000000..6aef22445a7a8c3e3018454b988d2f19bb6229d1
--- /dev/null
+++ b/webrtc/modules/rtp_rtcp/source/flexfec_sender_impl.cc
@@ -0,0 +1,175 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "webrtc/modules/rtp_rtcp/source/flexfec_sender_impl.h"
+
+#include <utility>
+
+#include "webrtc/base/logging.h"
+#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h"
+#include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h"
+
+namespace webrtc {
+
+namespace {
+
+constexpr uint16_t kMaxInitRtpSeqNumber = 32767; // 2^15 -1.
+
+// Since we will mainly use FlexFEC to protect video streams, we use a 90 kHz
+// clock for the RTP timestamps. (This is according to the RFC, which states
+// that it is RECOMMENDED to use the same clock frequency for FlexFEC as for
+// the protected media stream.)
+// The constant converts from clock millisecond timestamps to the 90 kHz
+// RTP timestamp.
+const int kMsToRtpTimestamp = kVideoPayloadTypeFrequency / 1000;
+
+// How often to log the generated FEC packets to the text log.
+constexpr int kPacketLogIntervalMs = 10000;
+
+} // namespace
+
+std::unique_ptr<FlexfecSender> FlexfecSender::Create(
+ int flexfec_payload_type,
+ uint32_t flexfec_ssrc,
+ uint32_t protected_media_ssrc,
+ const std::vector<RtpExtension>& rtp_header_extensions,
+ Clock* clock) {
+ // Don't instantiate this object if FlexFEC is disabled.
+ RTC_DCHECK_GE(flexfec_payload_type, 0);
+ RTC_DCHECK_LE(flexfec_payload_type, 127);
+ return std::unique_ptr<FlexfecSender>(new FlexfecSenderImpl(
+ flexfec_payload_type, flexfec_ssrc, protected_media_ssrc,
+ rtp_header_extensions, clock));
+}
+
+FlexfecSenderImpl::FlexfecSenderImpl(
+ int flexfec_payload_type,
+ uint32_t flexfec_ssrc,
+ uint32_t protected_media_ssrc,
+ const std::vector<RtpExtension>& rtp_header_extensions,
+ Clock* clock)
+ : clock_(clock),
+ random_(clock_->TimeInMicroseconds()),
+ last_generated_packet_ms_(-1),
+ flexfec_payload_type_(flexfec_payload_type),
+ // Initialize the RTP sequence numbers and timestamp offset randomly.
+ // (This is not intended to be cryptographically strong.)
+ seq_num_(random_.Rand(1, kMaxInitRtpSeqNumber)),
+ timestamp_offset_(random_.Rand<uint32_t>()),
+ flexfec_ssrc_(flexfec_ssrc),
+ protected_media_ssrc_(protected_media_ssrc),
+ ulpfec_sender_(ForwardErrorCorrection::CreateFlexfec()),
+ rtp_header_extension_map_() {
+ // It's OK to create this object on a different thread/task queue than
+ // the one used during main operation.
+ sequence_checker_.Detach();
+
+ // Register RTP header extensions for BWE.
+ for (const auto& extension : rtp_header_extensions) {
+ if (extension.uri == RtpExtension::kTransportSequenceNumberUri) {
+ rtp_header_extension_map_.Register(kRtpExtensionTransportSequenceNumber,
+ extension.id);
+ } else if (extension.uri == RtpExtension::kAbsSendTimeUri) {
+ rtp_header_extension_map_.Register(kRtpExtensionAbsoluteSendTime,
+ extension.id);
+ } else if (extension.uri == RtpExtension::kTimestampOffsetUri) {
+ rtp_header_extension_map_.Register(kRtpExtensionTransmissionTimeOffset,
+ extension.id);
+ } else {
+ LOG(LS_WARNING) << "RTP header extension with id: " << extension.id
+ << ", uri: " << extension.uri
+ << ", is unsupported by FlexfecSender.";
+ }
+ }
+}
+
+FlexfecSenderImpl::~FlexfecSenderImpl() = default;
+
+// We are reusing the implementation from ProducerFec for SetFecParameters,
+// AddRtpPacketAndGenerateFec, and FecAvailable.
+void FlexfecSenderImpl::SetFecParameters(const FecProtectionParams& params) {
+ RTC_DCHECK(sequence_checker_.CalledSequentially());
+ ulpfec_sender_.SetFecParameters(&params);
+}
+
+int FlexfecSenderImpl::AddRtpPacketAndGenerateFec(
+ const RtpPacketToSend& packet) {
+ RTC_DCHECK(sequence_checker_.CalledSequentially());
+ if (packet.Ssrc() != protected_media_ssrc_) {
+ return 0;
+ }
+ return ulpfec_sender_.AddRtpPacketAndGenerateFec(
+ packet.data(), packet.payload_size(), packet.headers_size());
+}
+
+bool FlexfecSenderImpl::FecAvailable() const {
+ RTC_DCHECK(sequence_checker_.CalledSequentially());
+ return ulpfec_sender_.FecAvailable();
+}
+
+std::vector<std::unique_ptr<RtpPacketToSend>>
+FlexfecSenderImpl::GetFecPackets() {
+ RTC_DCHECK(sequence_checker_.CalledSequentially());
+
+ std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets_to_send;
+ fec_packets_to_send.reserve(ulpfec_sender_.generated_fec_packets_.size());
+ for (const auto& fec_packet : ulpfec_sender_.generated_fec_packets_) {
+ std::unique_ptr<RtpPacketToSend> fec_packet_to_send(
+ new RtpPacketToSend(&rtp_header_extension_map_));
+
+ // RTP header.
+ fec_packet_to_send->SetMarker(false);
+ fec_packet_to_send->SetPayloadType(flexfec_payload_type_);
+ fec_packet_to_send->SetSequenceNumber(seq_num_++);
+ fec_packet_to_send->SetTimestamp(
+ timestamp_offset_ +
+ static_cast<uint32_t>(kMsToRtpTimestamp *
+ clock_->TimeInMilliseconds()));
+ // Set "capture time" so that the TransmissionOffset header extension
+ // can be set by the RTPSender.
+ fec_packet_to_send->set_capture_time_ms(clock_->CurrentNtpInMilliseconds());
danilchap 2016/10/24 13:40:31 sorry for not beeing detailed enough. it is expect
brandtr 2016/10/24 14:16:30 Done :)
+ fec_packet_to_send->SetSsrc(flexfec_ssrc_);
+ // Reserve extensions, if registered. These will be set by the RTPSender.
+ fec_packet_to_send->ReserveExtension<AbsoluteSendTime>();
+ fec_packet_to_send->ReserveExtension<TransmissionOffset>();
+ fec_packet_to_send->ReserveExtension<TransportSequenceNumber>();
+
+ // RTP payload.
+ uint8_t* payload = fec_packet_to_send->AllocatePayload(fec_packet->length);
+ memcpy(payload, fec_packet->data, fec_packet->length);
+
+ fec_packets_to_send.push_back(std::move(fec_packet_to_send));
+ }
+ ulpfec_sender_.ResetState();
+
+ // Periodically log generated FEC packets.
+ int64_t now_ms = clock_->TimeInMilliseconds();
+ if (!fec_packets_to_send.empty() &&
+ now_ms - last_generated_packet_ms_ > kPacketLogIntervalMs) {
+ LOG(LS_INFO) << "Generated " << fec_packets_to_send.size()
+ << " FlexFEC packets with payload type: "
+ << flexfec_payload_type_ << " and SSRC: " << flexfec_ssrc_
+ << ".";
+ last_generated_packet_ms_ = now_ms;
+ }
+
+ return fec_packets_to_send;
+}
+
+// This member function is called from the pacer thread sometimes. No need
+// for synchronization however, since it always returns the same constant.
+// TODO(brandtr): Remove the underlying call and make the packet overhead
+// explicit here.
+size_t FlexfecSenderImpl::MaxPacketOverhead() const {
+ return ulpfec_sender_.MaxPacketOverhead();
+}
+
+} // namespace webrtc

Powered by Google App Engine
This is Rietveld 408576698