OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #include "webrtc/modules/rtp_rtcp/include/flexfec_receiver.h" | 11 #include "webrtc/modules/rtp_rtcp/include/flexfec_receiver.h" |
12 | 12 |
13 #include <utility> | 13 #include <utility> |
14 | 14 |
15 #include "webrtc/base/logging.h" | 15 #include "webrtc/base/logging.h" |
16 #include "webrtc/base/scoped_ref_ptr.h" | 16 #include "webrtc/base/scoped_ref_ptr.h" |
17 #include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimat or.h" | |
18 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" | |
17 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h" | 19 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h" |
18 | 20 |
19 namespace webrtc { | 21 namespace webrtc { |
20 | 22 |
21 namespace { | 23 namespace { |
22 | 24 |
23 using Packet = ForwardErrorCorrection::Packet; | 25 using Packet = ForwardErrorCorrection::Packet; |
24 using ReceivedPacket = ForwardErrorCorrection::ReceivedPacket; | 26 using ReceivedPacket = ForwardErrorCorrection::ReceivedPacket; |
25 | 27 |
26 // Minimum header size (in bytes) of a well-formed non-singular FlexFEC packet. | 28 // Minimum header size (in bytes) of a well-formed non-singular FlexFEC packet. |
27 constexpr size_t kMinFlexfecHeaderSize = 20; | 29 constexpr size_t kMinFlexfecHeaderSize = 20; |
28 | 30 |
29 // How often to log the recovered packets to the text log. | 31 // How often to log the recovered packets to the text log. |
30 constexpr int kPacketLogIntervalMs = 10000; | 32 constexpr int kPacketLogIntervalMs = 10000; |
31 | 33 |
34 bool HasBweExtension(const RtpPacketReceived& packet) { | |
35 if (packet.HasExtension<TransportSequenceNumber>()) { | |
danilchap
2016/12/06 15:04:30
may be
return packet.HasExtension<TransportSequenc
brandtr
2016/12/12 13:51:08
Done.
| |
36 return true; | |
37 } else if (packet.HasExtension<AbsoluteSendTime>()) { | |
38 return true; | |
39 } else if (packet.HasExtension<TransmissionOffset>()) { | |
40 return true; | |
41 } | |
42 return false; | |
43 } | |
44 | |
32 } // namespace | 45 } // namespace |
33 | 46 |
34 FlexfecReceiver::FlexfecReceiver(uint32_t ssrc, | 47 FlexfecReceiver::FlexfecReceiver( |
35 uint32_t protected_media_ssrc, | 48 uint32_t ssrc, |
36 RecoveredPacketReceiver* callback) | 49 uint32_t protected_media_ssrc, |
50 RecoveredPacketReceiver* recovered_packet_receiver, | |
51 RemoteBitrateEstimator* remote_bitrate_estimator) | |
37 : ssrc_(ssrc), | 52 : ssrc_(ssrc), |
38 protected_media_ssrc_(protected_media_ssrc), | 53 protected_media_ssrc_(protected_media_ssrc), |
39 erasure_code_(ForwardErrorCorrection::CreateFlexfec()), | 54 erasure_code_(ForwardErrorCorrection::CreateFlexfec()), |
40 callback_(callback), | 55 recovered_packet_receiver_(recovered_packet_receiver), |
56 remote_bitrate_estimator_(remote_bitrate_estimator), | |
41 clock_(Clock::GetRealTimeClock()), | 57 clock_(Clock::GetRealTimeClock()), |
42 last_recovered_packet_ms_(-1) { | 58 last_recovered_packet_ms_(-1) { |
43 // It's OK to create this object on a different thread/task queue than | 59 // It's OK to create this object on a different thread/task queue than |
44 // the one used during main operation. | 60 // the one used during main operation. |
45 sequence_checker_.Detach(); | 61 sequence_checker_.Detach(); |
46 } | 62 } |
47 | 63 |
48 FlexfecReceiver::~FlexfecReceiver() = default; | 64 FlexfecReceiver::~FlexfecReceiver() = default; |
49 | 65 |
50 bool FlexfecReceiver::AddAndProcessReceivedPacket(const uint8_t* packet, | 66 bool FlexfecReceiver::AddAndProcessReceivedPacket(RtpPacketReceived packet) { |
51 size_t packet_length) { | |
52 RTC_DCHECK(sequence_checker_.CalledSequentially()); | 67 RTC_DCHECK(sequence_checker_.CalledSequentially()); |
53 | 68 |
54 if (!AddReceivedPacket(packet, packet_length)) { | 69 if (!AddReceivedPacket(std::move(packet))) { |
55 return false; | 70 return false; |
56 } | 71 } |
57 return ProcessReceivedPackets(); | 72 return ProcessReceivedPackets(); |
58 } | 73 } |
59 | 74 |
60 FecPacketCounter FlexfecReceiver::GetPacketCounter() const { | 75 FecPacketCounter FlexfecReceiver::GetPacketCounter() const { |
61 RTC_DCHECK(sequence_checker_.CalledSequentially()); | 76 RTC_DCHECK(sequence_checker_.CalledSequentially()); |
62 return packet_counter_; | 77 return packet_counter_; |
63 } | 78 } |
64 | 79 |
65 bool FlexfecReceiver::AddReceivedPacket(const uint8_t* packet, | 80 bool FlexfecReceiver::AddReceivedPacket(RtpPacketReceived packet) { |
66 size_t packet_length) { | |
67 RTC_DCHECK(sequence_checker_.CalledSequentially()); | 81 RTC_DCHECK(sequence_checker_.CalledSequentially()); |
68 | 82 |
69 // RTP packets with a full base header (12 bytes), but without payload, | 83 // RTP packets with a full base header (12 bytes), but without payload, |
70 // could conceivably be useful in the decoding. Therefore we check | 84 // could conceivably be useful in the decoding. Therefore we check |
71 // with a strict inequality here. | 85 // with a strict inequality here. |
72 if (packet_length < kRtpHeaderSize) { | 86 if (packet.size() < kRtpHeaderSize) { |
danilchap
2016/12/06 15:04:30
feel free to DCHECK now instead: RtpPacket should
brandtr
2016/12/12 13:51:07
Done.
| |
73 LOG(LS_WARNING) << "Truncated packet, discarding."; | 87 LOG(LS_WARNING) << "Truncated packet, discarding."; |
74 return false; | 88 return false; |
75 } | 89 } |
76 | 90 |
77 // TODO(brandtr): Consider how to handle received FlexFEC packets and | |
78 // the bandwidth estimator. | |
79 RtpPacketReceived parsed_packet; | |
80 if (!parsed_packet.Parse(packet, packet_length)) { | |
81 return false; | |
82 } | |
83 | |
84 // Demultiplex based on SSRC, and insert into erasure code decoder. | 91 // Demultiplex based on SSRC, and insert into erasure code decoder. |
85 std::unique_ptr<ReceivedPacket> received_packet(new ReceivedPacket()); | 92 std::unique_ptr<ReceivedPacket> received_packet(new ReceivedPacket()); |
86 received_packet->seq_num = parsed_packet.SequenceNumber(); | 93 received_packet->seq_num = packet.SequenceNumber(); |
87 received_packet->ssrc = parsed_packet.Ssrc(); | 94 received_packet->ssrc = packet.Ssrc(); |
88 if (received_packet->ssrc == ssrc_) { | 95 if (received_packet->ssrc == ssrc_) { |
89 // This is a FEC packet belonging to this FlexFEC stream. | 96 // This is a FlexFEC packet. |
90 if (parsed_packet.payload_size() < kMinFlexfecHeaderSize) { | 97 if (packet.payload_size() < kMinFlexfecHeaderSize) { |
91 LOG(LS_WARNING) << "Truncated FlexFEC packet, discarding."; | 98 LOG(LS_WARNING) << "Truncated FlexFEC packet, discarding."; |
92 return false; | 99 return false; |
93 } | 100 } |
94 received_packet->is_fec = true; | 101 received_packet->is_fec = true; |
95 ++packet_counter_.num_fec_packets; | 102 ++packet_counter_.num_fec_packets; |
103 | |
104 // Notify BWE. | |
105 if (HasBweExtension(packet)) { | |
106 RTPHeader header; | |
107 packet.GetHeader(&header); | |
108 remote_bitrate_estimator_->IncomingPacket(packet.arrival_time_ms(), | |
109 packet.payload_size(), header); | |
110 } | |
111 | |
96 // Insert packet payload into erasure code. | 112 // Insert packet payload into erasure code. |
97 // TODO(brandtr): Remove this memcpy when the FEC packet classes | 113 // TODO(brandtr): Remove this memcpy when the FEC packet classes |
98 // are using COW buffers internally. | 114 // are using COW buffers internally. |
99 received_packet->pkt = rtc::scoped_refptr<Packet>(new Packet()); | 115 received_packet->pkt = rtc::scoped_refptr<Packet>(new Packet()); |
100 auto payload = parsed_packet.payload(); | 116 auto payload = packet.payload(); |
101 memcpy(received_packet->pkt->data, payload.data(), payload.size()); | 117 memcpy(received_packet->pkt->data, payload.data(), payload.size()); |
102 received_packet->pkt->length = payload.size(); | 118 received_packet->pkt->length = payload.size(); |
103 } else { | 119 } else { |
104 // This is a media packet, or a FlexFEC packet belonging to some | 120 // This is a media packet, or a FlexFEC packet belonging to some |
105 // other FlexFEC stream. | 121 // other FlexFEC stream. |
106 if (received_packet->ssrc != protected_media_ssrc_) { | 122 if (received_packet->ssrc != protected_media_ssrc_) { |
107 return false; | 123 return false; |
108 } | 124 } |
109 received_packet->is_fec = false; | 125 received_packet->is_fec = false; |
126 | |
110 // Insert entire packet into erasure code. | 127 // Insert entire packet into erasure code. |
111 // TODO(brandtr): Remove this memcpy too. | 128 // TODO(brandtr): Remove this memcpy too. |
112 received_packet->pkt = rtc::scoped_refptr<Packet>(new Packet()); | 129 received_packet->pkt = rtc::scoped_refptr<Packet>(new Packet()); |
113 memcpy(received_packet->pkt->data, parsed_packet.data(), | 130 memcpy(received_packet->pkt->data, packet.data(), packet.size()); |
114 parsed_packet.size()); | 131 received_packet->pkt->length = packet.size(); |
115 received_packet->pkt->length = parsed_packet.size(); | |
116 } | 132 } |
133 | |
117 received_packets_.push_back(std::move(received_packet)); | 134 received_packets_.push_back(std::move(received_packet)); |
118 ++packet_counter_.num_packets; | 135 ++packet_counter_.num_packets; |
119 | 136 |
120 return true; | 137 return true; |
121 } | 138 } |
122 | 139 |
123 // Note that the implementation of this member function and the implementation | 140 // Note that the implementation of this member function and the implementation |
124 // in UlpfecReceiver::ProcessReceivedFec() are slightly different. | 141 // in UlpfecReceiver::ProcessReceivedFec() are slightly different. |
125 // This implementation only returns _recovered_ media packets through the | 142 // This implementation only returns _recovered_ media packets through the |
126 // callback, whereas the implementation in UlpfecReceiver returns _all inserted_ | 143 // callback, whereas the implementation in UlpfecReceiver returns _all inserted_ |
(...skipping 11 matching lines...) Expand all Loading... | |
138 0) { | 155 0) { |
139 return false; | 156 return false; |
140 } | 157 } |
141 } | 158 } |
142 // Return recovered packets through callback. | 159 // Return recovered packets through callback. |
143 for (const auto& recovered_packet : recovered_packets_) { | 160 for (const auto& recovered_packet : recovered_packets_) { |
144 if (recovered_packet->returned) { | 161 if (recovered_packet->returned) { |
145 continue; | 162 continue; |
146 } | 163 } |
147 ++packet_counter_.num_recovered_packets; | 164 ++packet_counter_.num_recovered_packets; |
148 if (!callback_->OnRecoveredPacket(recovered_packet->pkt->data, | 165 if (!recovered_packet_receiver_->OnRecoveredPacket( |
149 recovered_packet->pkt->length)) { | 166 recovered_packet->pkt->data, recovered_packet->pkt->length)) { |
150 return false; | 167 return false; |
151 } | 168 } |
152 recovered_packet->returned = true; | 169 recovered_packet->returned = true; |
153 // Periodically log the incoming packets. | 170 // Periodically log the incoming packets. |
154 int64_t now_ms = clock_->TimeInMilliseconds(); | 171 int64_t now_ms = clock_->TimeInMilliseconds(); |
155 if (now_ms - last_recovered_packet_ms_ > kPacketLogIntervalMs) { | 172 if (now_ms - last_recovered_packet_ms_ > kPacketLogIntervalMs) { |
156 uint32_t media_ssrc = | 173 uint32_t media_ssrc = |
157 ForwardErrorCorrection::ParseSsrc(recovered_packet->pkt->data); | 174 ForwardErrorCorrection::ParseSsrc(recovered_packet->pkt->data); |
158 LOG(LS_INFO) << "Recovered media packet with SSRC: " << media_ssrc | 175 LOG(LS_INFO) << "Recovered media packet with SSRC: " << media_ssrc |
159 << " from FlexFEC stream with SSRC: " << ssrc_ << "."; | 176 << " from FlexFEC stream with SSRC: " << ssrc_ << "."; |
160 last_recovered_packet_ms_ = now_ms; | 177 last_recovered_packet_ms_ = now_ms; |
161 } | 178 } |
162 } | 179 } |
163 return true; | 180 return true; |
164 } | 181 } |
165 | 182 |
166 } // namespace webrtc | 183 } // namespace webrtc |
OLD | NEW |