blob: 80f5b1f3b62a2a29f8ed24d3faa0b8d9689f55a6 [file] [log] [blame]
brandtra8b38552016-10-10 16:44:57 -07001/*
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
brandtr0a4c1612016-11-03 08:18:27 -070011#include "webrtc/modules/rtp_rtcp/include/flexfec_receiver.h"
brandtra8b38552016-10-10 16:44:57 -070012
brandtra8b38552016-10-10 16:44:57 -070013#include "webrtc/base/logging.h"
14#include "webrtc/base/scoped_ref_ptr.h"
brandtra8b38552016-10-10 16:44:57 -070015
16namespace webrtc {
17
18namespace {
19
20using Packet = ForwardErrorCorrection::Packet;
21using ReceivedPacket = ForwardErrorCorrection::ReceivedPacket;
22
23// Minimum header size (in bytes) of a well-formed non-singular FlexFEC packet.
24constexpr size_t kMinFlexfecHeaderSize = 20;
25
26// How often to log the recovered packets to the text log.
27constexpr int kPacketLogIntervalMs = 10000;
28
29} // namespace
30
brandtrb29e6522016-12-21 06:37:18 -080031FlexfecReceiver::FlexfecReceiver(
32 uint32_t ssrc,
33 uint32_t protected_media_ssrc,
34 RecoveredPacketReceiver* recovered_packet_receiver)
brandtr0a4c1612016-11-03 08:18:27 -070035 : ssrc_(ssrc),
brandtra8b38552016-10-10 16:44:57 -070036 protected_media_ssrc_(protected_media_ssrc),
37 erasure_code_(ForwardErrorCorrection::CreateFlexfec()),
brandtrb29e6522016-12-21 06:37:18 -080038 recovered_packet_receiver_(recovered_packet_receiver),
brandtra8b38552016-10-10 16:44:57 -070039 clock_(Clock::GetRealTimeClock()),
40 last_recovered_packet_ms_(-1) {
41 // It's OK to create this object on a different thread/task queue than
42 // the one used during main operation.
43 sequence_checker_.Detach();
44}
45
brandtr0a4c1612016-11-03 08:18:27 -070046FlexfecReceiver::~FlexfecReceiver() = default;
brandtra8b38552016-10-10 16:44:57 -070047
brandtrb29e6522016-12-21 06:37:18 -080048bool FlexfecReceiver::AddAndProcessReceivedPacket(RtpPacketReceived packet) {
brandtr8b5c3452016-12-19 10:02:30 -080049 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
brandtrb29e6522016-12-21 06:37:18 -080050 if (!AddReceivedPacket(std::move(packet))) {
brandtra8b38552016-10-10 16:44:57 -070051 return false;
52 }
53 return ProcessReceivedPackets();
54}
55
brandtr0a4c1612016-11-03 08:18:27 -070056FecPacketCounter FlexfecReceiver::GetPacketCounter() const {
brandtr8b5c3452016-12-19 10:02:30 -080057 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
brandtra8b38552016-10-10 16:44:57 -070058 return packet_counter_;
59}
60
brandtrb29e6522016-12-21 06:37:18 -080061bool FlexfecReceiver::AddReceivedPacket(RtpPacketReceived packet) {
brandtr8b5c3452016-12-19 10:02:30 -080062 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
brandtra8b38552016-10-10 16:44:57 -070063
64 // RTP packets with a full base header (12 bytes), but without payload,
65 // could conceivably be useful in the decoding. Therefore we check
brandtrb29e6522016-12-21 06:37:18 -080066 // with a non-strict inequality here.
67 RTC_DCHECK_GE(packet.size(), kRtpHeaderSize);
brandtra8b38552016-10-10 16:44:57 -070068
69 // Demultiplex based on SSRC, and insert into erasure code decoder.
70 std::unique_ptr<ReceivedPacket> received_packet(new ReceivedPacket());
brandtrb29e6522016-12-21 06:37:18 -080071 received_packet->seq_num = packet.SequenceNumber();
72 received_packet->ssrc = packet.Ssrc();
brandtr0a4c1612016-11-03 08:18:27 -070073 if (received_packet->ssrc == ssrc_) {
brandtrb29e6522016-12-21 06:37:18 -080074 // This is a FlexFEC packet.
75 if (packet.payload_size() < kMinFlexfecHeaderSize) {
brandtra8b38552016-10-10 16:44:57 -070076 LOG(LS_WARNING) << "Truncated FlexFEC packet, discarding.";
77 return false;
78 }
79 received_packet->is_fec = true;
80 ++packet_counter_.num_fec_packets;
brandtrb29e6522016-12-21 06:37:18 -080081
brandtra8b38552016-10-10 16:44:57 -070082 // Insert packet payload into erasure code.
83 // TODO(brandtr): Remove this memcpy when the FEC packet classes
84 // are using COW buffers internally.
85 received_packet->pkt = rtc::scoped_refptr<Packet>(new Packet());
brandtrb29e6522016-12-21 06:37:18 -080086 auto payload = packet.payload();
danilchap96c15872016-11-21 01:35:29 -080087 memcpy(received_packet->pkt->data, payload.data(), payload.size());
88 received_packet->pkt->length = payload.size();
brandtra8b38552016-10-10 16:44:57 -070089 } else {
90 // This is a media packet, or a FlexFEC packet belonging to some
91 // other FlexFEC stream.
92 if (received_packet->ssrc != protected_media_ssrc_) {
93 return false;
94 }
95 received_packet->is_fec = false;
brandtrb29e6522016-12-21 06:37:18 -080096
brandtra8b38552016-10-10 16:44:57 -070097 // Insert entire packet into erasure code.
98 // TODO(brandtr): Remove this memcpy too.
99 received_packet->pkt = rtc::scoped_refptr<Packet>(new Packet());
brandtrb29e6522016-12-21 06:37:18 -0800100 memcpy(received_packet->pkt->data, packet.data(), packet.size());
101 received_packet->pkt->length = packet.size();
brandtra8b38552016-10-10 16:44:57 -0700102 }
brandtrb29e6522016-12-21 06:37:18 -0800103
brandtra8b38552016-10-10 16:44:57 -0700104 received_packets_.push_back(std::move(received_packet));
105 ++packet_counter_.num_packets;
106
107 return true;
108}
109
110// Note that the implementation of this member function and the implementation
brandtrd55c3f62016-10-31 04:51:33 -0700111// in UlpfecReceiver::ProcessReceivedFec() are slightly different.
brandtra8b38552016-10-10 16:44:57 -0700112// This implementation only returns _recovered_ media packets through the
brandtrd55c3f62016-10-31 04:51:33 -0700113// callback, whereas the implementation in UlpfecReceiver returns _all inserted_
brandtra8b38552016-10-10 16:44:57 -0700114// media packets through the callback. The latter behaviour makes sense
115// for ULPFEC, since the ULPFEC receiver is owned by the RtpStreamReceiver.
116// Here, however, the received media pipeline is more decoupled from the
117// FlexFEC decoder, and we therefore do not interfere with the reception
118// of non-recovered media packets.
brandtr0a4c1612016-11-03 08:18:27 -0700119bool FlexfecReceiver::ProcessReceivedPackets() {
brandtr8b5c3452016-12-19 10:02:30 -0800120 RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
brandtra8b38552016-10-10 16:44:57 -0700121
122 // Decode.
123 if (!received_packets_.empty()) {
124 if (erasure_code_->DecodeFec(&received_packets_, &recovered_packets_) !=
125 0) {
126 return false;
127 }
128 }
129 // Return recovered packets through callback.
130 for (const auto& recovered_packet : recovered_packets_) {
131 if (recovered_packet->returned) {
132 continue;
133 }
134 ++packet_counter_.num_recovered_packets;
brandtrb29e6522016-12-21 06:37:18 -0800135 if (!recovered_packet_receiver_->OnRecoveredPacket(
136 recovered_packet->pkt->data, recovered_packet->pkt->length)) {
brandtra8b38552016-10-10 16:44:57 -0700137 return false;
138 }
139 recovered_packet->returned = true;
140 // Periodically log the incoming packets.
141 int64_t now_ms = clock_->TimeInMilliseconds();
142 if (now_ms - last_recovered_packet_ms_ > kPacketLogIntervalMs) {
143 uint32_t media_ssrc =
144 ForwardErrorCorrection::ParseSsrc(recovered_packet->pkt->data);
brandtr658024e2017-01-10 06:49:58 -0800145 LOG(LS_VERBOSE) << "Recovered media packet with SSRC: " << media_ssrc
146 << " from FlexFEC stream with SSRC: " << ssrc_ << ".";
brandtra8b38552016-10-10 16:44:57 -0700147 last_recovered_packet_ms_ = now_ms;
148 }
149 }
150 return true;
151}
152
153} // namespace webrtc