Chromium Code Reviews

Side by Side Diff: webrtc/modules/rtp_rtcp/source/flexfec_receiver_impl.cc

Issue 2392663006: Add a FlexfecReceiver class. (Closed)
Patch Set: Add a FlexfecReceiver class. Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff |
OLDNEW
(Empty)
1 /*
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
11 #include "webrtc/modules/rtp_rtcp/source/flexfec_receiver_impl.h"
12
13 #include <utility>
14
15 #include "webrtc/base/logging.h"
16 #include "webrtc/base/scoped_ref_ptr.h"
17 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h"
18
19 namespace webrtc {
20
21 namespace {
22
23 using Packet = ForwardErrorCorrection::Packet;
24 using ReceivedPacket = ForwardErrorCorrection::ReceivedPacket;
25
26 // Minimum header size (in bytes) of a well-formed non-singular FlexFEC packet.
27 constexpr size_t kMinFlexfecHeaderSize = 20;
28
29 // How often to log the recovered packets to the text log.
30 constexpr int kPacketLogIntervalMs = 10000;
31
32 } // namespace
33
34 RecoveredPacketReceiver::~RecoveredPacketReceiver() = default;
35
36 std::unique_ptr<FlexfecReceiver> FlexfecReceiver::Create(
37 uint32_t flexfec_ssrc,
38 uint32_t protected_media_ssrc,
39 RecoveredPacketReceiver* callback) {
40 return std::unique_ptr<FlexfecReceiver>(
41 new FlexfecReceiverImpl(flexfec_ssrc, protected_media_ssrc, callback));
42 }
43
44 FlexfecReceiver::~FlexfecReceiver() = default;
45
46 FlexfecReceiverImpl::FlexfecReceiverImpl(uint32_t flexfec_ssrc,
47 uint32_t protected_media_ssrc,
48 RecoveredPacketReceiver* callback)
49 : flexfec_ssrc_(flexfec_ssrc),
50 protected_media_ssrc_(protected_media_ssrc),
51 erasure_code_(ForwardErrorCorrection::CreateFlexfec()),
52 callback_(callback),
53 clock_(Clock::GetRealTimeClock()),
54 last_recovered_packet_ms_(-1) {
55 // Can be created on a different thread than run on.
56 thread_checker_.DetachFromThread();
57 }
58
59 FlexfecReceiverImpl::~FlexfecReceiverImpl() = default;
60
61 bool FlexfecReceiverImpl::AddReceivedPacket(const uint8_t* packet,
62 size_t packet_length) {
63 RTC_DCHECK(thread_checker_.CalledOnValidThread());
64
65 // RTP packets with a full base header (12 bytes), but without payload,
66 // could conceivably be useful in the decoding. Therefore we check
67 // with a strict inequality here.
68 if (packet_length < kRtpHeaderSize) {
69 LOG(LS_WARNING) << "Truncated packet, discarding.";
70 return false;
71 }
72
73 // TODO(brandtr): Consider how to handle received FlexFEC packets and
74 // the bandwidth estimator.
75 RtpPacketReceived parsed_packet;
76 if (!parsed_packet.Parse(packet, packet_length)) {
77 return false;
78 }
79
80 // Demultiplex based on SSRC, and insert into erasure code decoder.
81 std::unique_ptr<ReceivedPacket> received_packet(new ReceivedPacket());
82 received_packet->seq_num = parsed_packet.SequenceNumber();
83 received_packet->ssrc = parsed_packet.Ssrc();
84 if (received_packet->ssrc == flexfec_ssrc_) {
85 // This is a FEC packet belonging to this FlexFEC stream.
86 if (parsed_packet.payload_size() < kMinFlexfecHeaderSize) {
87 LOG(LS_WARNING) << "Truncated FlexFEC packet, discarding.";
88 return false;
89 }
90 received_packet->is_fec = true;
91 ++packet_counter_.num_fec_packets;
92 // Insert packet payload into erasure code.
93 // TODO(brandtr): Remove this memcpy when the FEC packet classes
94 // are using COW buffers internally.
95 received_packet->pkt = rtc::scoped_refptr<Packet>(new Packet());
96 memcpy(received_packet->pkt->data, parsed_packet.payload(),
97 parsed_packet.payload_size());
98 received_packet->pkt->length = parsed_packet.payload_size();
99 } else {
100 // This is a media packet, or a FlexFEC packet belonging to some
101 // other FlexFEC stream.
102 if (received_packet->ssrc != protected_media_ssrc_) {
103 return false;
104 }
105 received_packet->is_fec = false;
106 // Insert entire packet into erasure code.
107 // TODO(brandtr): Remove this memcpy too.
108 received_packet->pkt = rtc::scoped_refptr<Packet>(new Packet());
109 memcpy(received_packet->pkt->data, parsed_packet.data(),
110 parsed_packet.size());
111 received_packet->pkt->length = parsed_packet.size();
112 }
113 received_packets_.push_back(std::move(received_packet));
114 ++packet_counter_.num_packets;
115
116 return true;
117 }
118
119 // Note that the implementation of this member function and the implementation
120 // in FecReceiver::ProcessReceivedFec() are slightly different.
121 // This implementation only returns _recovered_ media packets through the
122 // callback, whereas the implementation in FecReceiver returns _all inserted_
123 // media packets through the callback. The latter behaviour makes sense
124 // for ULPFEC, since the ULPFEC receiver is owned by the RtpStreamReceiver.
125 // Here, however, the received media pipeline is more decoupled from the
126 // FlexFEC decoder, and we therefore do not interfere with the reception
127 // of non-recovered media packets.
128 bool FlexfecReceiverImpl::ProcessReceivedPackets() {
129 RTC_DCHECK(thread_checker_.CalledOnValidThread());
130
131 // Decode.
132 if (!received_packets_.empty()) {
133 if (erasure_code_->DecodeFec(&received_packets_, &recovered_packets_) !=
134 0) {
stefan-webrtc 2016/10/05 14:45:59 Will you update this method to return bool later?
brandtr 2016/10/06 08:38:57 This method currently always returns 0, so it coul
135 return false;
136 }
137 }
138 // Return recovered packets through callback.
139 for (const auto& recovered_packet : recovered_packets_) {
140 if (recovered_packet->returned) {
stefan-webrtc 2016/10/05 14:45:59 If you don't prefer this, I prefer removing {} :)
brandtr 2016/10/06 08:38:57 I prefer it :) All of the existing FEC source cod
stefan-webrtc 2016/10/06 08:43:55 Acknowledged.
141 continue;
142 }
143 ++packet_counter_.num_recovered_packets;
144 if (!callback_->OnRecoveredPacket(recovered_packet->pkt->data,
145 recovered_packet->pkt->length)) {
146 return false;
147 }
148 recovered_packet->returned = true;
149 // Periodically log the incoming packets.
150 int64_t now_ms = clock_->TimeInMilliseconds();
151 if (now_ms - last_recovered_packet_ms_ > kPacketLogIntervalMs) {
152 uint32_t media_ssrc =
153 ForwardErrorCorrection::ParseSsrc(recovered_packet->pkt->data);
154 std::stringstream ss;
155 ss << "Recovered media packet with SSRC: " << media_ssrc
156 << " from FlexFEC stream with SSRC: " << flexfec_ssrc_ << ".";
157 LOG(LS_INFO) << ss.str();
158 last_recovered_packet_ms_ = now_ms;
159 }
160 }
161 return true;
162 }
163
164 FecPacketCounter FlexfecReceiverImpl::GetPacketCounter() const {
165 RTC_DCHECK(thread_checker_.CalledOnValidThread());
166 return packet_counter_;
167 }
168
169 } // namespace webrtc
OLDNEW

Powered by Google App Engine