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

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

Issue 2451643002: Rename FecReceiver to UlpfecReceiver. (Closed)
Patch Set: Fix GYP. Created 4 years, 1 month 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 unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * Copyright (c) 2012 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/fec_receiver_impl.h"
12
13 #include <memory>
14 #include <utility>
15
16 #include "webrtc/base/checks.h"
17 #include "webrtc/base/logging.h"
18 #include "webrtc/modules/rtp_rtcp/source/byte_io.h"
19 #include "webrtc/modules/rtp_rtcp/source/rtp_receiver_video.h"
20
21 namespace webrtc {
22
23 FecReceiver* FecReceiver::Create(RtpData* callback) {
24 return new FecReceiverImpl(callback);
25 }
26
27 FecReceiverImpl::FecReceiverImpl(RtpData* callback)
28 : recovered_packet_callback_(callback),
29 fec_(ForwardErrorCorrection::CreateUlpfec()) {}
30
31 FecReceiverImpl::~FecReceiverImpl() {
32 received_packets_.clear();
33 fec_->ResetState(&recovered_packets_);
34 }
35
36 FecPacketCounter FecReceiverImpl::GetPacketCounter() const {
37 rtc::CritScope cs(&crit_sect_);
38 return packet_counter_;
39 }
40
41 // 0 1 2 3
42 // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
43 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
44 // |F| block PT | timestamp offset | block length |
45 // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
46 //
47 //
48 // RFC 2198 RTP Payload for Redundant Audio Data September 1997
49 //
50 // The bits in the header are specified as follows:
51 //
52 // F: 1 bit First bit in header indicates whether another header block
53 // follows. If 1 further header blocks follow, if 0 this is the
54 // last header block.
55 // If 0 there is only 1 byte RED header
56 //
57 // block PT: 7 bits RTP payload type for this block.
58 //
59 // timestamp offset: 14 bits Unsigned offset of timestamp of this block
60 // relative to timestamp given in RTP header. The use of an unsigned
61 // offset implies that redundant data must be sent after the primary
62 // data, and is hence a time to be subtracted from the current
63 // timestamp to determine the timestamp of the data for which this
64 // block is the redundancy.
65 //
66 // block length: 10 bits Length in bytes of the corresponding data
67 // block excluding header.
68
69 int32_t FecReceiverImpl::AddReceivedRedPacket(
70 const RTPHeader& header, const uint8_t* incoming_rtp_packet,
71 size_t packet_length, uint8_t ulpfec_payload_type) {
72 rtc::CritScope cs(&crit_sect_);
73
74 uint8_t red_header_length = 1;
75 size_t payload_data_length = packet_length - header.headerLength;
76
77 if (payload_data_length == 0) {
78 LOG(LS_WARNING) << "Corrupt/truncated FEC packet.";
79 return -1;
80 }
81
82 // Remove RED header of incoming packet and store as a virtual RTP packet.
83 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket> received_packet(
84 new ForwardErrorCorrection::ReceivedPacket());
85 received_packet->pkt = new ForwardErrorCorrection::Packet();
86
87 // Get payload type from RED header and sequence number from RTP header.
88 uint8_t payload_type = incoming_rtp_packet[header.headerLength] & 0x7f;
89 received_packet->is_fec = payload_type == ulpfec_payload_type;
90 received_packet->seq_num = header.sequenceNumber;
91
92 uint16_t block_length = 0;
93 if (incoming_rtp_packet[header.headerLength] & 0x80) {
94 // f bit set in RED header, i.e. there are more than one RED header blocks.
95 red_header_length = 4;
96 if (payload_data_length < red_header_length + 1u) {
97 LOG(LS_WARNING) << "Corrupt/truncated FEC packet.";
98 return -1;
99 }
100
101 uint16_t timestamp_offset = incoming_rtp_packet[header.headerLength + 1]
102 << 8;
103 timestamp_offset +=
104 incoming_rtp_packet[header.headerLength + 2];
105 timestamp_offset = timestamp_offset >> 2;
106 if (timestamp_offset != 0) {
107 LOG(LS_WARNING) << "Corrupt payload found.";
108 return -1;
109 }
110
111 block_length = (0x3 & incoming_rtp_packet[header.headerLength + 2]) << 8;
112 block_length += incoming_rtp_packet[header.headerLength + 3];
113
114 // Check next RED header block.
115 if (incoming_rtp_packet[header.headerLength + 4] & 0x80) {
116 LOG(LS_WARNING) << "More than 2 blocks in packet not supported.";
117 return -1;
118 }
119 // Check that the packet is long enough to contain data in the following
120 // block.
121 if (block_length > payload_data_length - (red_header_length + 1)) {
122 LOG(LS_WARNING) << "Block length longer than packet.";
123 return -1;
124 }
125 }
126 ++packet_counter_.num_packets;
127
128 std::unique_ptr<ForwardErrorCorrection::ReceivedPacket>
129 second_received_packet;
130 if (block_length > 0) {
131 // Handle block length, split into two packets.
132 red_header_length = 5;
133
134 // Copy RTP header.
135 memcpy(received_packet->pkt->data, incoming_rtp_packet,
136 header.headerLength);
137
138 // Set payload type.
139 received_packet->pkt->data[1] &= 0x80; // Reset RED payload type.
140 received_packet->pkt->data[1] += payload_type; // Set media payload type.
141
142 // Copy payload data.
143 memcpy(received_packet->pkt->data + header.headerLength,
144 incoming_rtp_packet + header.headerLength + red_header_length,
145 block_length);
146 received_packet->pkt->length = block_length;
147
148 second_received_packet.reset(new ForwardErrorCorrection::ReceivedPacket);
149 second_received_packet->pkt = new ForwardErrorCorrection::Packet;
150
151 second_received_packet->is_fec = true;
152 second_received_packet->seq_num = header.sequenceNumber;
153 ++packet_counter_.num_fec_packets;
154
155 // Copy FEC payload data.
156 memcpy(second_received_packet->pkt->data,
157 incoming_rtp_packet + header.headerLength + red_header_length +
158 block_length,
159 payload_data_length - red_header_length - block_length);
160
161 second_received_packet->pkt->length =
162 payload_data_length - red_header_length - block_length;
163
164 } else if (received_packet->is_fec) {
165 ++packet_counter_.num_fec_packets;
166 // everything behind the RED header
167 memcpy(received_packet->pkt->data,
168 incoming_rtp_packet + header.headerLength + red_header_length,
169 payload_data_length - red_header_length);
170 received_packet->pkt->length = payload_data_length - red_header_length;
171 received_packet->ssrc =
172 ByteReader<uint32_t>::ReadBigEndian(&incoming_rtp_packet[8]);
173
174 } else {
175 // Copy RTP header.
176 memcpy(received_packet->pkt->data, incoming_rtp_packet,
177 header.headerLength);
178
179 // Set payload type.
180 received_packet->pkt->data[1] &= 0x80; // Reset RED payload type.
181 received_packet->pkt->data[1] += payload_type; // Set media payload type.
182
183 // Copy payload data.
184 memcpy(received_packet->pkt->data + header.headerLength,
185 incoming_rtp_packet + header.headerLength + red_header_length,
186 payload_data_length - red_header_length);
187 received_packet->pkt->length =
188 header.headerLength + payload_data_length - red_header_length;
189 }
190
191 if (received_packet->pkt->length == 0) {
192 return 0;
193 }
194
195 received_packets_.push_back(std::move(received_packet));
196 if (second_received_packet) {
197 received_packets_.push_back(std::move(second_received_packet));
198 }
199 return 0;
200 }
201
202 int32_t FecReceiverImpl::ProcessReceivedFec() {
203 crit_sect_.Enter();
204 if (!received_packets_.empty()) {
205 // Send received media packet to VCM.
206 if (!received_packets_.front()->is_fec) {
207 ForwardErrorCorrection::Packet* packet = received_packets_.front()->pkt;
208 crit_sect_.Leave();
209 if (!recovered_packet_callback_->OnRecoveredPacket(packet->data,
210 packet->length)) {
211 return -1;
212 }
213 crit_sect_.Enter();
214 }
215 if (fec_->DecodeFec(&received_packets_, &recovered_packets_) != 0) {
216 crit_sect_.Leave();
217 return -1;
218 }
219 RTC_DCHECK(received_packets_.empty());
220 }
221 // Send any recovered media packets to VCM.
222 for (const auto& recovered_packet : recovered_packets_) {
223 if (recovered_packet->returned) {
224 // Already sent to the VCM and the jitter buffer.
225 continue;
226 }
227 ForwardErrorCorrection::Packet* packet = recovered_packet->pkt;
228 ++packet_counter_.num_recovered_packets;
229 crit_sect_.Leave();
230 if (!recovered_packet_callback_->OnRecoveredPacket(packet->data,
231 packet->length)) {
232 return -1;
233 }
234 crit_sect_.Enter();
235 recovered_packet->returned = true;
236 }
237 crit_sect_.Leave();
238 return 0;
239 }
240
241 } // namespace webrtc
OLDNEW
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/fec_receiver_impl.h ('k') | webrtc/modules/rtp_rtcp/source/fec_receiver_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698