OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/cast/net/rtcp/rtcp_sender.h" | 5 #include "media/cast/net/rtcp/rtcp_builder.h" |
6 | 6 |
7 #include <stdint.h> | 7 #include <stdint.h> |
8 | 8 |
9 #include <algorithm> | 9 #include <algorithm> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/big_endian.h" | |
13 #include "base/logging.h" | 12 #include "base/logging.h" |
14 #include "media/cast/net/cast_transport_defines.h" | 13 #include "media/cast/net/cast_transport_defines.h" |
15 #include "media/cast/net/pacing/paced_sender.h" | |
16 #include "media/cast/net/rtcp/rtcp_defines.h" | 14 #include "media/cast/net/rtcp/rtcp_defines.h" |
17 #include "media/cast/net/rtcp/rtcp_utility.h" | 15 #include "media/cast/net/rtcp/rtcp_utility.h" |
18 | 16 |
19 namespace media { | 17 namespace media { |
20 namespace cast { | 18 namespace cast { |
21 namespace { | 19 namespace { |
22 | 20 |
23 // Max delta is 4095 milliseconds because we need to be able to encode it in | 21 // Max delta is 4095 milliseconds because we need to be able to encode it in |
24 // 12 bits. | 22 // 12 bits. |
25 const int64 kMaxWireFormatTimeDeltaMs = INT64_C(0xfff); | 23 const int64 kMaxWireFormatTimeDeltaMs = INT64_C(0xfff); |
(...skipping 13 matching lines...) Expand all Loading... |
39 DCHECK(event_type_4_bits); | 37 DCHECK(event_type_4_bits); |
40 DCHECK(~(event_type_4_bits & 0xfff0)); | 38 DCHECK(~(event_type_4_bits & 0xfff0)); |
41 return (event_type_4_bits << 12) | time_delta_12_bits; | 39 return (event_type_4_bits << 12) | time_delta_12_bits; |
42 } | 40 } |
43 | 41 |
44 bool EventTimestampLessThan(const RtcpReceiverEventLogMessage& lhs, | 42 bool EventTimestampLessThan(const RtcpReceiverEventLogMessage& lhs, |
45 const RtcpReceiverEventLogMessage& rhs) { | 43 const RtcpReceiverEventLogMessage& rhs) { |
46 return lhs.event_timestamp < rhs.event_timestamp; | 44 return lhs.event_timestamp < rhs.event_timestamp; |
47 } | 45 } |
48 | 46 |
49 void AddReceiverLog( | 47 void AddReceiverLogEntries( |
50 const RtcpReceiverLogMessage& redundancy_receiver_log_message, | 48 const RtcpReceiverLogMessage& redundancy_receiver_log_message, |
51 RtcpReceiverLogMessage* receiver_log_message, | 49 RtcpReceiverLogMessage* receiver_log_message, |
52 size_t* remaining_space, | 50 size_t* remaining_space, |
53 size_t* number_of_frames, | 51 size_t* number_of_frames, |
54 size_t* total_number_of_messages_to_send) { | 52 size_t* total_number_of_messages_to_send) { |
55 RtcpReceiverLogMessage::const_iterator it = | 53 RtcpReceiverLogMessage::const_iterator it = |
56 redundancy_receiver_log_message.begin(); | 54 redundancy_receiver_log_message.begin(); |
57 while (it != redundancy_receiver_log_message.end() && | 55 while (it != redundancy_receiver_log_message.end() && |
58 *remaining_space >= | 56 *remaining_space >= |
59 kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) { | 57 kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) { |
60 receiver_log_message->push_front(*it); | 58 receiver_log_message->push_front(*it); |
61 size_t num_event_logs = (*remaining_space - kRtcpReceiverFrameLogSize) / | 59 size_t num_event_logs = (*remaining_space - kRtcpReceiverFrameLogSize) / |
62 kRtcpReceiverEventLogSize; | 60 kRtcpReceiverEventLogSize; |
63 RtcpReceiverEventLogMessages& event_log_messages = | 61 RtcpReceiverEventLogMessages& event_log_messages = |
64 receiver_log_message->front().event_log_messages_; | 62 receiver_log_message->front().event_log_messages_; |
65 if (num_event_logs < event_log_messages.size()) | 63 if (num_event_logs < event_log_messages.size()) |
66 event_log_messages.resize(num_event_logs); | 64 event_log_messages.resize(num_event_logs); |
67 | 65 |
68 *remaining_space -= kRtcpReceiverFrameLogSize + | 66 *remaining_space -= kRtcpReceiverFrameLogSize + |
69 event_log_messages.size() * kRtcpReceiverEventLogSize; | 67 event_log_messages.size() * kRtcpReceiverEventLogSize; |
70 ++*number_of_frames; | 68 ++number_of_frames; |
71 *total_number_of_messages_to_send += event_log_messages.size(); | 69 *total_number_of_messages_to_send += event_log_messages.size(); |
72 ++it; | 70 ++it; |
73 } | 71 } |
74 } | 72 } |
75 | 73 |
76 // A class to build a string representing the NACK list in Cast message. | 74 // A class to build a string representing the NACK list in Cast message. |
77 // | 75 // |
78 // The string will look like "23:3-6 25:1,5-6", meaning packets 3 to 6 in frame | 76 // The string will look like "23:3-6 25:1,5-6", meaning packets 3 to 6 in frame |
79 // 23 are being NACK'ed (i.e. they are missing from the receiver's point of | 77 // 23 are being NACK'ed (i.e. they are missing from the receiver's point of |
80 // view) and packets 1, 5 and 6 are missing in frame 25. A frame that is | 78 // view) and packets 1, 5 and 6 are missing in frame 25. A frame that is |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 private: | 136 private: |
139 std::ostringstream stream_; | 137 std::ostringstream stream_; |
140 int frame_count_; | 138 int frame_count_; |
141 int packet_count_; | 139 int packet_count_; |
142 int last_frame_id_; | 140 int last_frame_id_; |
143 int last_packet_id_; | 141 int last_packet_id_; |
144 bool contiguous_sequence_; | 142 bool contiguous_sequence_; |
145 }; | 143 }; |
146 } // namespace | 144 } // namespace |
147 | 145 |
148 RtcpSender::RtcpSender(PacedPacketSender* outgoing_transport, | 146 RtcpBuilder::RtcpBuilder(uint32 sending_ssrc) |
149 uint32 sending_ssrc) | 147 : writer_(NULL, 0), |
150 : ssrc_(sending_ssrc), | 148 ssrc_(sending_ssrc), |
151 transport_(outgoing_transport) { | 149 ptr_of_length_(NULL) { |
152 } | 150 } |
153 | 151 |
154 RtcpSender::~RtcpSender() {} | 152 RtcpBuilder::~RtcpBuilder() {} |
155 | 153 |
156 void RtcpSender::SendRtcpFromRtpReceiver( | 154 void RtcpBuilder::PatchLengthField() { |
| 155 if (ptr_of_length_) { |
| 156 // Back-patch the packet length. The client must have taken |
| 157 // care of proper padding to 32-bit words. |
| 158 int this_packet_length = (writer_.ptr() - ptr_of_length_ - 2); |
| 159 DCHECK_EQ(0, this_packet_length % 4) |
| 160 << "Packets must be a multiple of 32 bits long"; |
| 161 *ptr_of_length_ = this_packet_length >> 10; |
| 162 *(ptr_of_length_ + 1) = (this_packet_length >> 2) & 0xFF; |
| 163 ptr_of_length_ = NULL; |
| 164 } |
| 165 } |
| 166 |
| 167 // Set the 5-bit value in the 1st byte of the header |
| 168 // and the payload type. Set aside room for the length field, |
| 169 // and make provision for back-patching it. |
| 170 void RtcpBuilder::AddRtcpHeader(RtcpPacketFields payload, int format_or_count) { |
| 171 PatchLengthField(); |
| 172 writer_.WriteU8(0x80 | (format_or_count & 0x1F)); |
| 173 writer_.WriteU8(payload); |
| 174 ptr_of_length_ = writer_.ptr(); |
| 175 |
| 176 // Initialize length to "clearly illegal". |
| 177 writer_.WriteU16(0xDEAD); |
| 178 } |
| 179 |
| 180 void RtcpBuilder::Start() { |
| 181 packet_ = new base::RefCountedData<Packet>; |
| 182 packet_->data.resize(kMaxIpPacketSize); |
| 183 writer_ = base::BigEndianWriter( |
| 184 reinterpret_cast<char*>(&(packet_->data[0])), kMaxIpPacketSize); |
| 185 } |
| 186 |
| 187 PacketRef RtcpBuilder::Finish() { |
| 188 PatchLengthField(); |
| 189 packet_->data.resize(kMaxIpPacketSize - writer_.remaining()); |
| 190 writer_ = base::BigEndianWriter(NULL, 0); |
| 191 PacketRef ret = packet_; |
| 192 packet_ = NULL; |
| 193 return ret; |
| 194 } |
| 195 |
| 196 PacketRef RtcpBuilder::BuildRtcpFromReceiver( |
157 const RtcpReportBlock* report_block, | 197 const RtcpReportBlock* report_block, |
158 const RtcpReceiverReferenceTimeReport* rrtr, | 198 const RtcpReceiverReferenceTimeReport* rrtr, |
159 const RtcpCastMessage* cast_message, | 199 const RtcpCastMessage* cast_message, |
160 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events, | 200 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap* rtcp_events, |
161 base::TimeDelta target_delay) { | 201 base::TimeDelta target_delay) { |
162 PacketRef packet(new base::RefCountedData<Packet>); | 202 Start(); |
163 packet->data.reserve(kMaxIpPacketSize); | 203 |
164 if (report_block) | 204 if (report_block) |
165 BuildRR(report_block, &packet->data); | 205 AddRR(report_block); |
166 if (rrtr) | 206 if (rrtr) |
167 BuildRrtr(rrtr, &packet->data); | 207 AddRrtr(rrtr); |
168 if (cast_message) | 208 if (cast_message) |
169 BuildCast(cast_message, target_delay, &packet->data); | 209 AddCast(cast_message, target_delay); |
170 if (rtcp_events) | 210 if (rtcp_events) |
171 BuildReceiverLog(*rtcp_events, &packet->data); | 211 AddReceiverLog(*rtcp_events); |
172 | 212 |
173 if (packet->data.empty()) { | 213 return Finish(); |
174 NOTREACHED() << "Empty packet."; | |
175 return; // Sanity don't send empty packets. | |
176 } | |
177 | |
178 transport_->SendRtcpPacket(ssrc_, packet); | |
179 } | 214 } |
180 | 215 |
181 void RtcpSender::SendRtcpFromRtpSender( | 216 PacketRef RtcpBuilder::BuildRtcpFromSender(const RtcpSenderInfo& sender_info) { |
182 const RtcpSenderInfo& sender_info) { | 217 Start(); |
183 PacketRef packet(new base::RefCountedData<Packet>); | 218 AddSR(sender_info); |
184 packet->data.reserve(kMaxIpPacketSize); | 219 return Finish(); |
185 BuildSR(sender_info, &packet->data); | |
186 | |
187 if (packet->data.empty()) { | |
188 NOTREACHED() << "Empty packet."; | |
189 return; // Sanity - don't send empty packets. | |
190 } | |
191 | |
192 transport_->SendRtcpPacket(ssrc_, packet); | |
193 } | 220 } |
194 | 221 |
195 void RtcpSender::BuildRR(const RtcpReportBlock* report_block, | 222 void RtcpBuilder::AddRR(const RtcpReportBlock* report_block) { |
196 Packet* packet) const { | 223 AddRtcpHeader(kPacketTypeReceiverReport, report_block ? 1 : 0); |
197 size_t start_size = packet->size(); | 224 writer_.WriteU32(ssrc_); |
198 DCHECK_LT(start_size + 32, kMaxIpPacketSize) << "Not enough buffer space"; | |
199 if (start_size + 32 > kMaxIpPacketSize) | |
200 return; | |
201 | |
202 uint16 number_of_rows = (report_block) ? 7 : 1; | |
203 packet->resize(start_size + 8); | |
204 | |
205 base::BigEndianWriter big_endian_writer( | |
206 reinterpret_cast<char*>(&((*packet)[start_size])), 8); | |
207 big_endian_writer.WriteU8(0x80 + (report_block ? 1 : 0)); | |
208 big_endian_writer.WriteU8(kPacketTypeReceiverReport); | |
209 big_endian_writer.WriteU16(number_of_rows); | |
210 big_endian_writer.WriteU32(ssrc_); | |
211 | |
212 if (report_block) { | 225 if (report_block) { |
213 AddReportBlocks(*report_block, packet); // Adds 24 bytes. | 226 AddReportBlocks(*report_block); // Adds 24 bytes. |
214 } | 227 } |
215 } | 228 } |
216 | 229 |
217 void RtcpSender::AddReportBlocks(const RtcpReportBlock& report_block, | 230 void RtcpBuilder::AddReportBlocks(const RtcpReportBlock& report_block) { |
218 Packet* packet) const { | 231 writer_.WriteU32(report_block.media_ssrc); |
219 size_t start_size = packet->size(); | 232 writer_.WriteU8(report_block.fraction_lost); |
220 DCHECK_LT(start_size + 24, kMaxIpPacketSize) << "Not enough buffer space"; | 233 writer_.WriteU8(report_block.cumulative_lost >> 16); |
221 if (start_size + 24 > kMaxIpPacketSize) | 234 writer_.WriteU8(report_block.cumulative_lost >> 8); |
222 return; | 235 writer_.WriteU8(report_block.cumulative_lost); |
223 | |
224 packet->resize(start_size + 24); | |
225 | |
226 base::BigEndianWriter big_endian_writer( | |
227 reinterpret_cast<char*>(&((*packet)[start_size])), 24); | |
228 big_endian_writer.WriteU32(report_block.media_ssrc); | |
229 big_endian_writer.WriteU8(report_block.fraction_lost); | |
230 big_endian_writer.WriteU8(report_block.cumulative_lost >> 16); | |
231 big_endian_writer.WriteU8(report_block.cumulative_lost >> 8); | |
232 big_endian_writer.WriteU8(report_block.cumulative_lost); | |
233 | 236 |
234 // Extended highest seq_no, contain the highest sequence number received. | 237 // Extended highest seq_no, contain the highest sequence number received. |
235 big_endian_writer.WriteU32(report_block.extended_high_sequence_number); | 238 writer_.WriteU32(report_block.extended_high_sequence_number); |
236 big_endian_writer.WriteU32(report_block.jitter); | 239 writer_.WriteU32(report_block.jitter); |
237 | 240 |
238 // Last SR timestamp; our NTP time when we received the last report. | 241 // Last SR timestamp; our NTP time when we received the last report. |
239 // This is the value that we read from the send report packet not when we | 242 // This is the value that we read from the send report packet not when we |
240 // received it. | 243 // received it. |
241 big_endian_writer.WriteU32(report_block.last_sr); | 244 writer_.WriteU32(report_block.last_sr); |
242 | 245 |
243 // Delay since last received report, time since we received the report. | 246 // Delay since last received report, time since we received the report. |
244 big_endian_writer.WriteU32(report_block.delay_since_last_sr); | 247 writer_.WriteU32(report_block.delay_since_last_sr); |
245 } | 248 } |
246 | 249 |
247 void RtcpSender::BuildRrtr(const RtcpReceiverReferenceTimeReport* rrtr, | 250 void RtcpBuilder::AddRrtr(const RtcpReceiverReferenceTimeReport* rrtr) { |
248 Packet* packet) const { | 251 AddRtcpHeader(kPacketTypeXr, 0); |
249 size_t start_size = packet->size(); | 252 writer_.WriteU32(ssrc_); // Add our own SSRC. |
250 DCHECK_LT(start_size + 20, kMaxIpPacketSize) << "Not enough buffer space"; | 253 writer_.WriteU8(4); // Add block type. |
251 if (start_size + 20 > kMaxIpPacketSize) | 254 writer_.WriteU8(0); // Add reserved. |
252 return; | 255 writer_.WriteU16(2); // Block length. |
253 | |
254 packet->resize(start_size + 20); | |
255 | |
256 base::BigEndianWriter big_endian_writer( | |
257 reinterpret_cast<char*>(&((*packet)[start_size])), 20); | |
258 | |
259 big_endian_writer.WriteU8(0x80); | |
260 big_endian_writer.WriteU8(kPacketTypeXr); | |
261 big_endian_writer.WriteU16(4); // Length. | |
262 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | |
263 big_endian_writer.WriteU8(4); // Add block type. | |
264 big_endian_writer.WriteU8(0); // Add reserved. | |
265 big_endian_writer.WriteU16(2); // Block length. | |
266 | 256 |
267 // Add the media (received RTP) SSRC. | 257 // Add the media (received RTP) SSRC. |
268 big_endian_writer.WriteU32(rrtr->ntp_seconds); | 258 writer_.WriteU32(rrtr->ntp_seconds); |
269 big_endian_writer.WriteU32(rrtr->ntp_fraction); | 259 writer_.WriteU32(rrtr->ntp_fraction); |
270 } | 260 } |
271 | 261 |
272 void RtcpSender::BuildCast(const RtcpCastMessage* cast, | 262 void RtcpBuilder::AddCast(const RtcpCastMessage* cast, |
273 base::TimeDelta target_delay, | 263 base::TimeDelta target_delay) { |
274 Packet* packet) const { | 264 // See RTC 4585 Section 6.4 for application specific feedback messages. |
275 size_t start_size = packet->size(); | 265 AddRtcpHeader(kPacketTypePayloadSpecific, 15); |
276 DCHECK_LT(start_size + 20, kMaxIpPacketSize) << "Not enough buffer space"; | 266 writer_.WriteU32(ssrc_); // Add our own SSRC. |
277 if (start_size + 20 > kMaxIpPacketSize) | 267 writer_.WriteU32(cast->media_ssrc); // Remote SSRC. |
278 return; | 268 writer_.WriteU32(kCast); |
279 | 269 writer_.WriteU8(static_cast<uint8>(cast->ack_frame_id)); |
280 packet->resize(start_size + 20); | 270 uint8* cast_loss_field_pos = reinterpret_cast<uint8*>(writer_.ptr()); |
281 | 271 writer_.WriteU8(0); // Overwritten with number_of_loss_fields. |
282 base::BigEndianWriter big_endian_writer( | |
283 reinterpret_cast<char*>(&((*packet)[start_size])), 20); | |
284 uint8 FMT = 15; // Application layer feedback. | |
285 big_endian_writer.WriteU8(0x80 + FMT); | |
286 big_endian_writer.WriteU8(kPacketTypePayloadSpecific); | |
287 big_endian_writer.WriteU8(0); | |
288 size_t cast_size_pos = start_size + 3; // Save length position. | |
289 big_endian_writer.WriteU8(4); | |
290 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | |
291 big_endian_writer.WriteU32(cast->media_ssrc); // Remote SSRC. | |
292 big_endian_writer.WriteU32(kCast); | |
293 big_endian_writer.WriteU8(static_cast<uint8>(cast->ack_frame_id)); | |
294 size_t cast_loss_field_pos = start_size + 17; // Save loss field position. | |
295 big_endian_writer.WriteU8(0); // Overwritten with number_of_loss_fields. | |
296 DCHECK_LE(target_delay.InMilliseconds(), | 272 DCHECK_LE(target_delay.InMilliseconds(), |
297 std::numeric_limits<uint16_t>::max()); | 273 std::numeric_limits<uint16_t>::max()); |
298 big_endian_writer.WriteU16(target_delay.InMilliseconds()); | 274 writer_.WriteU16(target_delay.InMilliseconds()); |
299 | 275 |
300 size_t number_of_loss_fields = 0; | 276 size_t number_of_loss_fields = 0; |
301 size_t max_number_of_loss_fields = std::min<size_t>( | 277 size_t max_number_of_loss_fields = std::min<size_t>( |
302 kRtcpMaxCastLossFields, (kMaxIpPacketSize - packet->size()) / 4); | 278 kRtcpMaxCastLossFields, writer_.remaining() / 4); |
303 | 279 |
304 MissingFramesAndPacketsMap::const_iterator frame_it = | 280 MissingFramesAndPacketsMap::const_iterator frame_it = |
305 cast->missing_frames_and_packets.begin(); | 281 cast->missing_frames_and_packets.begin(); |
306 | 282 |
307 NackStringBuilder nack_string_builder; | 283 NackStringBuilder nack_string_builder; |
308 for (; frame_it != cast->missing_frames_and_packets.end() && | 284 for (; frame_it != cast->missing_frames_and_packets.end() && |
309 number_of_loss_fields < max_number_of_loss_fields; | 285 number_of_loss_fields < max_number_of_loss_fields; |
310 ++frame_it) { | 286 ++frame_it) { |
311 nack_string_builder.PushFrame(frame_it->first); | 287 nack_string_builder.PushFrame(frame_it->first); |
312 // Iterate through all frames with missing packets. | 288 // Iterate through all frames with missing packets. |
313 if (frame_it->second.empty()) { | 289 if (frame_it->second.empty()) { |
314 // Special case all packets in a frame is missing. | 290 // Special case all packets in a frame is missing. |
315 start_size = packet->size(); | 291 writer_.WriteU8(static_cast<uint8>(frame_it->first)); |
316 packet->resize(start_size + 4); | 292 writer_.WriteU16(kRtcpCastAllPacketsLost); |
317 base::BigEndianWriter big_endian_nack_writer( | 293 writer_.WriteU8(0); |
318 reinterpret_cast<char*>(&((*packet)[start_size])), 4); | |
319 big_endian_nack_writer.WriteU8(static_cast<uint8>(frame_it->first)); | |
320 big_endian_nack_writer.WriteU16(kRtcpCastAllPacketsLost); | |
321 big_endian_nack_writer.WriteU8(0); | |
322 nack_string_builder.PushPacket(kRtcpCastAllPacketsLost); | 294 nack_string_builder.PushPacket(kRtcpCastAllPacketsLost); |
323 ++number_of_loss_fields; | 295 ++number_of_loss_fields; |
324 } else { | 296 } else { |
325 PacketIdSet::const_iterator packet_it = frame_it->second.begin(); | 297 PacketIdSet::const_iterator packet_it = frame_it->second.begin(); |
326 while (packet_it != frame_it->second.end()) { | 298 while (packet_it != frame_it->second.end()) { |
327 uint16 packet_id = *packet_it; | 299 uint16 packet_id = *packet_it; |
328 | |
329 start_size = packet->size(); | |
330 packet->resize(start_size + 4); | |
331 base::BigEndianWriter big_endian_nack_writer( | |
332 reinterpret_cast<char*>(&((*packet)[start_size])), 4); | |
333 | |
334 // Write frame and packet id to buffer before calculating bitmask. | 300 // Write frame and packet id to buffer before calculating bitmask. |
335 big_endian_nack_writer.WriteU8(static_cast<uint8>(frame_it->first)); | 301 writer_.WriteU8(static_cast<uint8>(frame_it->first)); |
336 big_endian_nack_writer.WriteU16(packet_id); | 302 writer_.WriteU16(packet_id); |
337 nack_string_builder.PushPacket(packet_id); | 303 nack_string_builder.PushPacket(packet_id); |
338 | 304 |
339 uint8 bitmask = 0; | 305 uint8 bitmask = 0; |
340 ++packet_it; | 306 ++packet_it; |
341 while (packet_it != frame_it->second.end()) { | 307 while (packet_it != frame_it->second.end()) { |
342 int shift = static_cast<uint8>(*packet_it - packet_id) - 1; | 308 int shift = static_cast<uint8>(*packet_it - packet_id) - 1; |
343 if (shift >= 0 && shift <= 7) { | 309 if (shift >= 0 && shift <= 7) { |
344 nack_string_builder.PushPacket(*packet_it); | 310 nack_string_builder.PushPacket(*packet_it); |
345 bitmask |= (1 << shift); | 311 bitmask |= (1 << shift); |
346 ++packet_it; | 312 ++packet_it; |
347 } else { | 313 } else { |
348 break; | 314 break; |
349 } | 315 } |
350 } | 316 } |
351 big_endian_nack_writer.WriteU8(bitmask); | 317 writer_.WriteU8(bitmask); |
352 ++number_of_loss_fields; | 318 ++number_of_loss_fields; |
353 } | 319 } |
354 } | 320 } |
355 } | 321 } |
356 VLOG_IF(1, !nack_string_builder.Empty()) | 322 VLOG_IF(1, !nack_string_builder.Empty()) |
357 << "SSRC: " << cast->media_ssrc | 323 << "SSRC: " << cast->media_ssrc |
358 << ", ACK: " << cast->ack_frame_id | 324 << ", ACK: " << cast->ack_frame_id |
359 << ", NACK: " << nack_string_builder.GetString(); | 325 << ", NACK: " << nack_string_builder.GetString(); |
360 DCHECK_LE(number_of_loss_fields, kRtcpMaxCastLossFields); | 326 DCHECK_LE(number_of_loss_fields, kRtcpMaxCastLossFields); |
361 (*packet)[cast_size_pos] = static_cast<uint8>(4 + number_of_loss_fields); | 327 *cast_loss_field_pos = static_cast<uint8>(number_of_loss_fields); |
362 (*packet)[cast_loss_field_pos] = static_cast<uint8>(number_of_loss_fields); | |
363 } | 328 } |
364 | 329 |
365 void RtcpSender::BuildSR(const RtcpSenderInfo& sender_info, | 330 void RtcpBuilder::AddSR(const RtcpSenderInfo& sender_info) { |
366 Packet* packet) const { | 331 AddRtcpHeader(kPacketTypeSenderReport, 0); |
367 // Sender report. | 332 writer_.WriteU32(ssrc_); |
368 size_t start_size = packet->size(); | 333 writer_.WriteU32(sender_info.ntp_seconds); |
369 if (start_size + 52 > kMaxIpPacketSize) { | 334 writer_.WriteU32(sender_info.ntp_fraction); |
370 DLOG(FATAL) << "Not enough buffer space"; | 335 writer_.WriteU32(sender_info.rtp_timestamp); |
371 return; | 336 writer_.WriteU32(sender_info.send_packet_count); |
372 } | 337 writer_.WriteU32(static_cast<uint32>(sender_info.send_octet_count)); |
373 | |
374 uint16 number_of_rows = 6; | |
375 packet->resize(start_size + 28); | |
376 | |
377 base::BigEndianWriter big_endian_writer( | |
378 reinterpret_cast<char*>(&((*packet)[start_size])), 28); | |
379 big_endian_writer.WriteU8(0x80); | |
380 big_endian_writer.WriteU8(kPacketTypeSenderReport); | |
381 big_endian_writer.WriteU16(number_of_rows); | |
382 big_endian_writer.WriteU32(ssrc_); | |
383 big_endian_writer.WriteU32(sender_info.ntp_seconds); | |
384 big_endian_writer.WriteU32(sender_info.ntp_fraction); | |
385 big_endian_writer.WriteU32(sender_info.rtp_timestamp); | |
386 big_endian_writer.WriteU32(sender_info.send_packet_count); | |
387 big_endian_writer.WriteU32(static_cast<uint32>(sender_info.send_octet_count)); | |
388 return; | |
389 } | 338 } |
390 | 339 |
391 /* | 340 /* |
392 0 1 2 3 | 341 0 1 2 3 |
393 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 | 342 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 |
394 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 343 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
395 |V=2|P|reserved | PT=XR=207 | length | | 344 |V=2|P|reserved | PT=XR=207 | length | |
396 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 345 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
397 | SSRC | | 346 | SSRC | |
398 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 347 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
399 | BT=5 | reserved | block length | | 348 | BT=5 | reserved | block length | |
400 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | 349 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |
401 | SSRC1 (SSRC of first receiver) | sub- | 350 | SSRC1 (SSRC of first receiver) | sub- |
402 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block | 351 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ block |
403 | last RR (LRR) | 1 | 352 | last RR (LRR) | 1 |
404 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 353 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
405 | delay since last RR (DLRR) | | 354 | delay since last RR (DLRR) | |
406 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ | 355 +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+ |
407 */ | 356 */ |
408 void RtcpSender::BuildDlrrRb(const RtcpDlrrReportBlock& dlrr, | 357 void RtcpBuilder::AddDlrrRb(const RtcpDlrrReportBlock& dlrr) { |
409 Packet* packet) const { | 358 AddRtcpHeader(kPacketTypeXr, 0); |
410 size_t start_size = packet->size(); | 359 writer_.WriteU32(ssrc_); // Add our own SSRC. |
411 if (start_size + 24 > kMaxIpPacketSize) { | 360 writer_.WriteU8(5); // Add block type. |
412 DLOG(FATAL) << "Not enough buffer space"; | 361 writer_.WriteU8(0); // Add reserved. |
| 362 writer_.WriteU16(3); // Block length. |
| 363 writer_.WriteU32(ssrc_); // Add the media (received RTP) SSRC. |
| 364 writer_.WriteU32(dlrr.last_rr); |
| 365 writer_.WriteU32(dlrr.delay_since_last_rr); |
| 366 } |
| 367 |
| 368 void RtcpBuilder::AddReceiverLog( |
| 369 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events) { |
| 370 size_t total_number_of_messages_to_send = 0; |
| 371 RtcpReceiverLogMessage receiver_log_message; |
| 372 |
| 373 if (!GetRtcpReceiverLogMessage(rtcp_events, |
| 374 &receiver_log_message, |
| 375 &total_number_of_messages_to_send)) { |
413 return; | 376 return; |
414 } | 377 } |
415 | 378 |
416 packet->resize(start_size + 24); | 379 AddRtcpHeader(kPacketTypeApplicationDefined, kReceiverLogSubtype); |
417 | 380 writer_.WriteU32(ssrc_); // Add our own SSRC. |
418 base::BigEndianWriter big_endian_writer( | 381 writer_.WriteU32(kCast); |
419 reinterpret_cast<char*>(&((*packet)[start_size])), 24); | |
420 big_endian_writer.WriteU8(0x80); | |
421 big_endian_writer.WriteU8(kPacketTypeXr); | |
422 big_endian_writer.WriteU16(5); // Length. | |
423 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | |
424 big_endian_writer.WriteU8(5); // Add block type. | |
425 big_endian_writer.WriteU8(0); // Add reserved. | |
426 big_endian_writer.WriteU16(3); // Block length. | |
427 big_endian_writer.WriteU32(ssrc_); // Add the media (received RTP) SSRC. | |
428 big_endian_writer.WriteU32(dlrr.last_rr); | |
429 big_endian_writer.WriteU32(dlrr.delay_since_last_rr); | |
430 return; | |
431 } | |
432 | |
433 void RtcpSender::BuildReceiverLog( | |
434 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events, | |
435 Packet* packet) { | |
436 const size_t packet_start_size = packet->size(); | |
437 size_t number_of_frames = 0; | |
438 size_t total_number_of_messages_to_send = 0; | |
439 size_t rtcp_log_size = 0; | |
440 RtcpReceiverLogMessage receiver_log_message; | |
441 | |
442 if (!BuildRtcpReceiverLogMessage(rtcp_events, | |
443 packet_start_size, | |
444 &receiver_log_message, | |
445 &number_of_frames, | |
446 &total_number_of_messages_to_send, | |
447 &rtcp_log_size)) { | |
448 return; | |
449 } | |
450 packet->resize(packet_start_size + rtcp_log_size); | |
451 | |
452 base::BigEndianWriter big_endian_writer( | |
453 reinterpret_cast<char*>(&((*packet)[packet_start_size])), rtcp_log_size); | |
454 big_endian_writer.WriteU8(0x80 + kReceiverLogSubtype); | |
455 big_endian_writer.WriteU8(kPacketTypeApplicationDefined); | |
456 big_endian_writer.WriteU16(static_cast<uint16>( | |
457 2 + 2 * number_of_frames + total_number_of_messages_to_send)); | |
458 big_endian_writer.WriteU32(ssrc_); // Add our own SSRC. | |
459 big_endian_writer.WriteU32(kCast); | |
460 | 382 |
461 while (!receiver_log_message.empty() && | 383 while (!receiver_log_message.empty() && |
462 total_number_of_messages_to_send > 0) { | 384 total_number_of_messages_to_send > 0) { |
463 RtcpReceiverFrameLogMessage& frame_log_messages( | 385 RtcpReceiverFrameLogMessage& frame_log_messages( |
464 receiver_log_message.front()); | 386 receiver_log_message.front()); |
465 | 387 |
466 // Add our frame header. | 388 // Add our frame header. |
467 big_endian_writer.WriteU32(frame_log_messages.rtp_timestamp_); | 389 writer_.WriteU32(frame_log_messages.rtp_timestamp_); |
468 size_t messages_in_frame = frame_log_messages.event_log_messages_.size(); | 390 size_t messages_in_frame = frame_log_messages.event_log_messages_.size(); |
469 if (messages_in_frame > total_number_of_messages_to_send) { | 391 if (messages_in_frame > total_number_of_messages_to_send) { |
470 // We are running out of space. | 392 // We are running out of space. |
471 messages_in_frame = total_number_of_messages_to_send; | 393 messages_in_frame = total_number_of_messages_to_send; |
472 } | 394 } |
473 // Keep track of how many messages we have left to send. | 395 // Keep track of how many messages we have left to send. |
474 total_number_of_messages_to_send -= messages_in_frame; | 396 total_number_of_messages_to_send -= messages_in_frame; |
475 | 397 |
476 // On the wire format is number of messages - 1. | 398 // On the wire format is number of messages - 1. |
477 big_endian_writer.WriteU8(static_cast<uint8>(messages_in_frame - 1)); | 399 writer_.WriteU8(static_cast<uint8>(messages_in_frame - 1)); |
478 | 400 |
479 base::TimeTicks event_timestamp_base = | 401 base::TimeTicks event_timestamp_base = |
480 frame_log_messages.event_log_messages_.front().event_timestamp; | 402 frame_log_messages.event_log_messages_.front().event_timestamp; |
481 uint32 base_timestamp_ms = | 403 uint32 base_timestamp_ms = |
482 (event_timestamp_base - base::TimeTicks()).InMilliseconds(); | 404 (event_timestamp_base - base::TimeTicks()).InMilliseconds(); |
483 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms >> 16)); | 405 writer_.WriteU8(static_cast<uint8>(base_timestamp_ms >> 16)); |
484 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms >> 8)); | 406 writer_.WriteU8(static_cast<uint8>(base_timestamp_ms >> 8)); |
485 big_endian_writer.WriteU8(static_cast<uint8>(base_timestamp_ms)); | 407 writer_.WriteU8(static_cast<uint8>(base_timestamp_ms)); |
486 | 408 |
487 while (!frame_log_messages.event_log_messages_.empty() && | 409 while (!frame_log_messages.event_log_messages_.empty() && |
488 messages_in_frame > 0) { | 410 messages_in_frame > 0) { |
489 const RtcpReceiverEventLogMessage& event_message = | 411 const RtcpReceiverEventLogMessage& event_message = |
490 frame_log_messages.event_log_messages_.front(); | 412 frame_log_messages.event_log_messages_.front(); |
491 uint16 event_type_and_timestamp_delta = | 413 uint16 event_type_and_timestamp_delta = |
492 MergeEventTypeAndTimestampForWireFormat( | 414 MergeEventTypeAndTimestampForWireFormat( |
493 event_message.type, | 415 event_message.type, |
494 event_message.event_timestamp - event_timestamp_base); | 416 event_message.event_timestamp - event_timestamp_base); |
495 switch (event_message.type) { | 417 switch (event_message.type) { |
496 case FRAME_ACK_SENT: | 418 case FRAME_ACK_SENT: |
497 case FRAME_PLAYOUT: | 419 case FRAME_PLAYOUT: |
498 case FRAME_DECODED: | 420 case FRAME_DECODED: |
499 big_endian_writer.WriteU16( | 421 writer_.WriteU16( |
500 static_cast<uint16>(event_message.delay_delta.InMilliseconds())); | 422 static_cast<uint16>(event_message.delay_delta.InMilliseconds())); |
501 big_endian_writer.WriteU16(event_type_and_timestamp_delta); | 423 writer_.WriteU16(event_type_and_timestamp_delta); |
502 break; | 424 break; |
503 case PACKET_RECEIVED: | 425 case PACKET_RECEIVED: |
504 big_endian_writer.WriteU16(event_message.packet_id); | 426 writer_.WriteU16(event_message.packet_id); |
505 big_endian_writer.WriteU16(event_type_and_timestamp_delta); | 427 writer_.WriteU16(event_type_and_timestamp_delta); |
506 break; | 428 break; |
507 default: | 429 default: |
508 NOTREACHED(); | 430 NOTREACHED(); |
509 } | 431 } |
510 messages_in_frame--; | 432 messages_in_frame--; |
511 frame_log_messages.event_log_messages_.pop_front(); | 433 frame_log_messages.event_log_messages_.pop_front(); |
512 } | 434 } |
513 if (frame_log_messages.event_log_messages_.empty()) { | 435 if (frame_log_messages.event_log_messages_.empty()) { |
514 // We sent all messages on this frame; pop the frame header. | 436 // We sent all messages on this frame; pop the frame header. |
515 receiver_log_message.pop_front(); | 437 receiver_log_message.pop_front(); |
516 } | 438 } |
517 } | 439 } |
518 DCHECK_EQ(total_number_of_messages_to_send, 0u); | 440 DCHECK_EQ(total_number_of_messages_to_send, 0u); |
519 } | 441 } |
520 | 442 |
521 bool RtcpSender::BuildRtcpReceiverLogMessage( | 443 bool RtcpBuilder::GetRtcpReceiverLogMessage( |
522 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events, | 444 const ReceiverRtcpEventSubscriber::RtcpEventMultiMap& rtcp_events, |
523 size_t start_size, | |
524 RtcpReceiverLogMessage* receiver_log_message, | 445 RtcpReceiverLogMessage* receiver_log_message, |
525 size_t* number_of_frames, | 446 size_t* total_number_of_messages_to_send) { |
526 size_t* total_number_of_messages_to_send, | 447 size_t number_of_frames = 0; |
527 size_t* rtcp_log_size) { | |
528 size_t remaining_space = | 448 size_t remaining_space = |
529 std::min(kMaxReceiverLogBytes, kMaxIpPacketSize - start_size); | 449 std::min<size_t>(kMaxReceiverLogBytes, writer_.remaining()); |
530 if (remaining_space < kRtcpCastLogHeaderSize + kRtcpReceiverFrameLogSize + | 450 if (remaining_space < kRtcpCastLogHeaderSize + kRtcpReceiverFrameLogSize + |
531 kRtcpReceiverEventLogSize) { | 451 kRtcpReceiverEventLogSize) { |
532 return false; | 452 return false; |
533 } | 453 } |
534 | 454 |
535 // We use this to do event timestamp sorting and truncating for events of | 455 // We use this to do event timestamp sorting and truncating for events of |
536 // a single frame. | 456 // a single frame. |
537 std::vector<RtcpReceiverEventLogMessage> sorted_log_messages; | 457 std::vector<RtcpReceiverEventLogMessage> sorted_log_messages; |
538 | 458 |
539 // Account for the RTCP header for an application-defined packet. | 459 // Account for the RTCP header for an application-defined packet. |
540 remaining_space -= kRtcpCastLogHeaderSize; | 460 remaining_space -= kRtcpCastLogHeaderSize; |
541 | 461 |
542 ReceiverRtcpEventSubscriber::RtcpEventMultiMap::const_reverse_iterator rit = | 462 ReceiverRtcpEventSubscriber::RtcpEventMultiMap::const_reverse_iterator rit = |
543 rtcp_events.rbegin(); | 463 rtcp_events.rbegin(); |
544 | 464 |
545 while (rit != rtcp_events.rend() && | 465 while (rit != rtcp_events.rend() && |
546 remaining_space >= | 466 remaining_space >= |
547 kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) { | 467 kRtcpReceiverFrameLogSize + kRtcpReceiverEventLogSize) { |
548 const RtpTimestamp rtp_timestamp = rit->first; | 468 const RtpTimestamp rtp_timestamp = rit->first; |
549 RtcpReceiverFrameLogMessage frame_log(rtp_timestamp); | 469 RtcpReceiverFrameLogMessage frame_log(rtp_timestamp); |
550 remaining_space -= kRtcpReceiverFrameLogSize; | 470 remaining_space -= kRtcpReceiverFrameLogSize; |
551 ++*number_of_frames; | 471 ++number_of_frames; |
552 | 472 |
553 // Get all events of a single frame. | 473 // Get all events of a single frame. |
554 sorted_log_messages.clear(); | 474 sorted_log_messages.clear(); |
555 do { | 475 do { |
556 RtcpReceiverEventLogMessage event_log_message; | 476 RtcpReceiverEventLogMessage event_log_message; |
557 event_log_message.type = rit->second.type; | 477 event_log_message.type = rit->second.type; |
558 event_log_message.event_timestamp = rit->second.timestamp; | 478 event_log_message.event_timestamp = rit->second.timestamp; |
559 event_log_message.delay_delta = rit->second.delay_delta; | 479 event_log_message.delay_delta = rit->second.delay_delta; |
560 event_log_message.packet_id = rit->second.packet_id; | 480 event_log_message.packet_id = rit->second.packet_id; |
561 sorted_log_messages.push_back(event_log_message); | 481 sorted_log_messages.push_back(event_log_message); |
(...skipping 29 matching lines...) Expand all Loading... |
591 } | 511 } |
592 | 512 |
593 rtcp_events_history_.push_front(*receiver_log_message); | 513 rtcp_events_history_.push_front(*receiver_log_message); |
594 | 514 |
595 // We don't try to match RTP timestamps of redundancy frame logs with those | 515 // We don't try to match RTP timestamps of redundancy frame logs with those |
596 // from the newest set (which would save the space of an extra RTP timestamp | 516 // from the newest set (which would save the space of an extra RTP timestamp |
597 // over the wire). Unless the redundancy frame logs are very recent, it's | 517 // over the wire). Unless the redundancy frame logs are very recent, it's |
598 // unlikely there will be a match anyway. | 518 // unlikely there will be a match anyway. |
599 if (rtcp_events_history_.size() > kFirstRedundancyOffset) { | 519 if (rtcp_events_history_.size() > kFirstRedundancyOffset) { |
600 // Add first redundnacy messages, if enough space remaining | 520 // Add first redundnacy messages, if enough space remaining |
601 AddReceiverLog(rtcp_events_history_[kFirstRedundancyOffset], | 521 AddReceiverLogEntries(rtcp_events_history_[kFirstRedundancyOffset], |
602 receiver_log_message, | 522 receiver_log_message, |
603 &remaining_space, | 523 &remaining_space, |
604 number_of_frames, | 524 &number_of_frames, |
605 total_number_of_messages_to_send); | 525 total_number_of_messages_to_send); |
606 } | 526 } |
607 | 527 |
608 if (rtcp_events_history_.size() > kSecondRedundancyOffset) { | 528 if (rtcp_events_history_.size() > kSecondRedundancyOffset) { |
609 // Add second redundancy messages, if enough space remaining | 529 // Add second redundancy messages, if enough space remaining |
610 AddReceiverLog(rtcp_events_history_[kSecondRedundancyOffset], | 530 AddReceiverLogEntries(rtcp_events_history_[kSecondRedundancyOffset], |
611 receiver_log_message, | 531 receiver_log_message, |
612 &remaining_space, | 532 &remaining_space, |
613 number_of_frames, | 533 &number_of_frames, |
614 total_number_of_messages_to_send); | 534 total_number_of_messages_to_send); |
615 } | 535 } |
616 | 536 |
617 if (rtcp_events_history_.size() > kReceiveLogMessageHistorySize) { | 537 if (rtcp_events_history_.size() > kReceiveLogMessageHistorySize) { |
618 rtcp_events_history_.pop_back(); | 538 rtcp_events_history_.pop_back(); |
619 } | 539 } |
620 | 540 |
621 DCHECK_LE(rtcp_events_history_.size(), kReceiveLogMessageHistorySize); | 541 DCHECK_LE(rtcp_events_history_.size(), kReceiveLogMessageHistorySize); |
622 | 542 |
623 *rtcp_log_size = | 543 VLOG(3) << "number of frames: " << number_of_frames; |
624 kRtcpCastLogHeaderSize + *number_of_frames * kRtcpReceiverFrameLogSize + | |
625 *total_number_of_messages_to_send * kRtcpReceiverEventLogSize; | |
626 DCHECK_GE(kMaxIpPacketSize, start_size + *rtcp_log_size) | |
627 << "Not enough buffer space."; | |
628 | |
629 VLOG(3) << "number of frames: " << *number_of_frames; | |
630 VLOG(3) << "total messages to send: " << *total_number_of_messages_to_send; | 544 VLOG(3) << "total messages to send: " << *total_number_of_messages_to_send; |
631 VLOG(3) << "rtcp log size: " << *rtcp_log_size; | 545 return number_of_frames > 0; |
632 return *number_of_frames > 0; | |
633 } | 546 } |
634 | 547 |
635 } // namespace cast | 548 } // namespace cast |
636 } // namespace media | 549 } // namespace media |
OLD | NEW |