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

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

Issue 2392663006: Add a FlexfecReceiver class. (Closed)
Patch Set: holmer's comments 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_receiver_impl.cc
diff --git a/webrtc/modules/rtp_rtcp/source/flexfec_receiver_impl.cc b/webrtc/modules/rtp_rtcp/source/flexfec_receiver_impl.cc
new file mode 100644
index 0000000000000000000000000000000000000000..e9dcd6f109e79d3ce52941f79f97d498dd6726fa
--- /dev/null
+++ b/webrtc/modules/rtp_rtcp/source/flexfec_receiver_impl.cc
@@ -0,0 +1,178 @@
+/*
+ * 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_receiver_impl.h"
+
+#include <utility>
+
+#include "webrtc/base/logging.h"
+#include "webrtc/base/scoped_ref_ptr.h"
+#include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h"
+
+namespace webrtc {
+
+namespace {
+
+using Packet = ForwardErrorCorrection::Packet;
+using ReceivedPacket = ForwardErrorCorrection::ReceivedPacket;
+
+// Minimum header size (in bytes) of a well-formed non-singular FlexFEC packet.
+constexpr size_t kMinFlexfecHeaderSize = 20;
+
+// How often to log the recovered packets to the text log.
+constexpr int kPacketLogIntervalMs = 10000;
+
+} // namespace
+
+std::unique_ptr<FlexfecReceiver> FlexfecReceiver::Create(
+ uint32_t flexfec_ssrc,
+ uint32_t protected_media_ssrc,
+ RecoveredPacketReceiver* callback) {
+ return std::unique_ptr<FlexfecReceiver>(
+ new FlexfecReceiverImpl(flexfec_ssrc, protected_media_ssrc, callback));
+}
+
+FlexfecReceiver::~FlexfecReceiver() = default;
+
+FlexfecReceiverImpl::FlexfecReceiverImpl(uint32_t flexfec_ssrc,
+ uint32_t protected_media_ssrc,
+ RecoveredPacketReceiver* callback)
+ : flexfec_ssrc_(flexfec_ssrc),
+ protected_media_ssrc_(protected_media_ssrc),
+ erasure_code_(ForwardErrorCorrection::CreateFlexfec()),
+ callback_(callback),
+ clock_(Clock::GetRealTimeClock()),
+ last_recovered_packet_ms_(-1) {
+ // It's OK to create this object on a different thread/task queue than
+ // the one used during main operation.
+ sequence_checker_.Detach();
+}
+
+FlexfecReceiverImpl::~FlexfecReceiverImpl() = default;
+
+bool FlexfecReceiverImpl::AddAndProcessReceivedPacket(const uint8_t* packet,
+ size_t packet_length) {
+ RTC_DCHECK(sequence_checker_.CalledSequentially());
+
+ if (!AddReceivedPacket(packet, packet_length)) {
+ return false;
+ }
+ return ProcessReceivedPackets();
+}
+
+FecPacketCounter FlexfecReceiverImpl::GetPacketCounter() const {
+ RTC_DCHECK(sequence_checker_.CalledSequentially());
+ return packet_counter_;
+}
+
+bool FlexfecReceiverImpl::AddReceivedPacket(const uint8_t* packet,
+ size_t packet_length) {
+ RTC_DCHECK(sequence_checker_.CalledSequentially());
+
+ // RTP packets with a full base header (12 bytes), but without payload,
+ // could conceivably be useful in the decoding. Therefore we check
+ // with a strict inequality here.
+ if (packet_length < kRtpHeaderSize) {
+ LOG(LS_WARNING) << "Truncated packet, discarding.";
+ return false;
+ }
+
+ // TODO(brandtr): Consider how to handle received FlexFEC packets and
+ // the bandwidth estimator.
+ RtpPacketReceived parsed_packet;
+ if (!parsed_packet.Parse(packet, packet_length)) {
+ return false;
+ }
+
+ // Demultiplex based on SSRC, and insert into erasure code decoder.
+ std::unique_ptr<ReceivedPacket> received_packet(new ReceivedPacket());
+ received_packet->seq_num = parsed_packet.SequenceNumber();
+ received_packet->ssrc = parsed_packet.Ssrc();
+ if (received_packet->ssrc == flexfec_ssrc_) {
+ // This is a FEC packet belonging to this FlexFEC stream.
+ if (parsed_packet.payload_size() < kMinFlexfecHeaderSize) {
+ LOG(LS_WARNING) << "Truncated FlexFEC packet, discarding.";
+ return false;
+ }
+ received_packet->is_fec = true;
+ ++packet_counter_.num_fec_packets;
+ // Insert packet payload into erasure code.
+ // TODO(brandtr): Remove this memcpy when the FEC packet classes
+ // are using COW buffers internally.
+ received_packet->pkt = rtc::scoped_refptr<Packet>(new Packet());
+ memcpy(received_packet->pkt->data, parsed_packet.payload(),
+ parsed_packet.payload_size());
+ received_packet->pkt->length = parsed_packet.payload_size();
+ } else {
+ // This is a media packet, or a FlexFEC packet belonging to some
+ // other FlexFEC stream.
+ if (received_packet->ssrc != protected_media_ssrc_) {
+ return false;
+ }
+ received_packet->is_fec = false;
+ // Insert entire packet into erasure code.
+ // TODO(brandtr): Remove this memcpy too.
+ received_packet->pkt = rtc::scoped_refptr<Packet>(new Packet());
+ memcpy(received_packet->pkt->data, parsed_packet.data(),
+ parsed_packet.size());
+ received_packet->pkt->length = parsed_packet.size();
+ }
+ received_packets_.push_back(std::move(received_packet));
+ ++packet_counter_.num_packets;
+
+ return true;
+}
+
+// Note that the implementation of this member function and the implementation
+// in FecReceiver::ProcessReceivedFec() are slightly different.
+// This implementation only returns _recovered_ media packets through the
+// callback, whereas the implementation in FecReceiver returns _all inserted_
+// media packets through the callback. The latter behaviour makes sense
+// for ULPFEC, since the ULPFEC receiver is owned by the RtpStreamReceiver.
+// Here, however, the received media pipeline is more decoupled from the
+// FlexFEC decoder, and we therefore do not interfere with the reception
+// of non-recovered media packets.
+bool FlexfecReceiverImpl::ProcessReceivedPackets() {
+ RTC_DCHECK(sequence_checker_.CalledSequentially());
+
+ // Decode.
+ if (!received_packets_.empty()) {
+ if (erasure_code_->DecodeFec(&received_packets_, &recovered_packets_) !=
+ 0) {
+ return false;
+ }
+ }
+ // Return recovered packets through callback.
+ for (const auto& recovered_packet : recovered_packets_) {
+ if (recovered_packet->returned) {
+ continue;
+ }
+ ++packet_counter_.num_recovered_packets;
+ if (!callback_->OnRecoveredPacket(recovered_packet->pkt->data,
+ recovered_packet->pkt->length)) {
+ return false;
+ }
+ recovered_packet->returned = true;
+ // Periodically log the incoming packets.
+ int64_t now_ms = clock_->TimeInMilliseconds();
+ if (now_ms - last_recovered_packet_ms_ > kPacketLogIntervalMs) {
+ uint32_t media_ssrc =
+ ForwardErrorCorrection::ParseSsrc(recovered_packet->pkt->data);
+ std::stringstream ss;
+ ss << "Recovered media packet with SSRC: " << media_ssrc
+ << " from FlexFEC stream with SSRC: " << flexfec_ssrc_ << ".";
+ LOG(LS_INFO) << ss.str();
+ last_recovered_packet_ms_ = now_ms;
+ }
+ }
+ return true;
+}
+
+} // namespace webrtc
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/flexfec_receiver_impl.h ('k') | webrtc/modules/rtp_rtcp/source/flexfec_receiver_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698