OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 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 |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 media_packet.payload_size()); | 43 media_packet.payload_size()); |
44 } | 44 } |
45 } // namespace | 45 } // namespace |
46 | 46 |
47 RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSender* rtp_sender) | 47 RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSender* rtp_sender) |
48 : rtp_sender_(rtp_sender), | 48 : rtp_sender_(rtp_sender), |
49 clock_(clock), | 49 clock_(clock), |
50 video_type_(kRtpVideoGeneric), | 50 video_type_(kRtpVideoGeneric), |
51 retransmission_settings_(kRetransmitBaseLayer), | 51 retransmission_settings_(kRetransmitBaseLayer), |
52 last_rotation_(kVideoRotation_0), | 52 last_rotation_(kVideoRotation_0), |
53 fec_enabled_(false), | |
54 red_payload_type_(-1), | 53 red_payload_type_(-1), |
55 fec_payload_type_(-1), | 54 ulpfec_payload_type_(-1), |
56 delta_fec_params_{0, 1, kFecMaskRandom}, | 55 delta_fec_params_{0, 1, kFecMaskRandom}, |
57 key_fec_params_{0, 1, kFecMaskRandom}, | 56 key_fec_params_{0, 1, kFecMaskRandom}, |
58 fec_bitrate_(1000, RateStatistics::kBpsScale), | 57 fec_bitrate_(1000, RateStatistics::kBpsScale), |
59 video_bitrate_(1000, RateStatistics::kBpsScale) { | 58 video_bitrate_(1000, RateStatistics::kBpsScale) { |
60 encoder_checker_.Detach(); | 59 encoder_checker_.Detach(); |
61 } | 60 } |
62 | 61 |
63 RTPSenderVideo::~RTPSenderVideo() {} | 62 RTPSenderVideo::~RTPSenderVideo() {} |
64 | 63 |
65 void RTPSenderVideo::SetVideoCodecType(RtpVideoCodecTypes video_type) { | 64 void RTPSenderVideo::SetVideoCodecType(RtpVideoCodecTypes video_type) { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
132 if (protect) { | 131 if (protect) { |
133 ulpfec_generator_.AddRtpPacketAndGenerateFec( | 132 ulpfec_generator_.AddRtpPacketAndGenerateFec( |
134 media_packet->data(), media_packet->payload_size(), | 133 media_packet->data(), media_packet->payload_size(), |
135 media_packet->headers_size()); | 134 media_packet->headers_size()); |
136 } | 135 } |
137 uint16_t num_fec_packets = ulpfec_generator_.NumAvailableFecPackets(); | 136 uint16_t num_fec_packets = ulpfec_generator_.NumAvailableFecPackets(); |
138 if (num_fec_packets > 0) { | 137 if (num_fec_packets > 0) { |
139 uint16_t first_fec_sequence_number = | 138 uint16_t first_fec_sequence_number = |
140 rtp_sender_->AllocateSequenceNumber(num_fec_packets); | 139 rtp_sender_->AllocateSequenceNumber(num_fec_packets); |
141 fec_packets = ulpfec_generator_.GetUlpfecPacketsAsRed( | 140 fec_packets = ulpfec_generator_.GetUlpfecPacketsAsRed( |
142 red_payload_type_, fec_payload_type_, first_fec_sequence_number, | 141 red_payload_type_, ulpfec_payload_type_, first_fec_sequence_number, |
143 media_packet->headers_size()); | 142 media_packet->headers_size()); |
144 RTC_DCHECK_EQ(num_fec_packets, fec_packets.size()); | 143 RTC_DCHECK_EQ(num_fec_packets, fec_packets.size()); |
145 if (retransmission_settings_ & kRetransmitFECPackets) | 144 if (retransmission_settings_ & kRetransmitFECPackets) |
146 fec_storage = kAllowRetransmission; | 145 fec_storage = kAllowRetransmission; |
147 } | 146 } |
148 } | 147 } |
149 // Send |red_packet| instead of |packet| for allocated sequence number. | 148 // Send |red_packet| instead of |packet| for allocated sequence number. |
150 size_t red_packet_size = red_packet->size(); | 149 size_t red_packet_size = red_packet->size(); |
151 if (rtp_sender_->SendToNetwork(std::move(red_packet), media_packet_storage, | 150 if (rtp_sender_->SendToNetwork(std::move(red_packet), media_packet_storage, |
152 RtpPacketSender::kLowPriority)) { | 151 RtpPacketSender::kLowPriority)) { |
(...skipping 19 matching lines...) Expand all Loading... |
172 fec_bitrate_.Update(fec_packet->length(), clock_->TimeInMilliseconds()); | 171 fec_bitrate_.Update(fec_packet->length(), clock_->TimeInMilliseconds()); |
173 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), | 172 TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
174 "Video::PacketFec", "timestamp", rtp_timestamp, | 173 "Video::PacketFec", "timestamp", rtp_timestamp, |
175 "seqnum", fec_sequence_number); | 174 "seqnum", fec_sequence_number); |
176 } else { | 175 } else { |
177 LOG(LS_WARNING) << "Failed to send FEC packet " << fec_sequence_number; | 176 LOG(LS_WARNING) << "Failed to send FEC packet " << fec_sequence_number; |
178 } | 177 } |
179 } | 178 } |
180 } | 179 } |
181 | 180 |
182 void RTPSenderVideo::SetUlpfecConfig(bool enabled, | 181 void RTPSenderVideo::SetUlpfecConfig(int red_payload_type, |
183 int red_payload_type, | |
184 int ulpfec_payload_type) { | 182 int ulpfec_payload_type) { |
185 RTC_DCHECK(!enabled || red_payload_type > 0); | 183 // Sanity check. Per the definition of UlpfecConfig (see config.h), |
| 184 // a payload type of -1 means that the corresponding feature is |
| 185 // turned off. |
| 186 RTC_DCHECK_GE(red_payload_type, -1); |
186 RTC_DCHECK_LE(red_payload_type, 127); | 187 RTC_DCHECK_LE(red_payload_type, 127); |
| 188 RTC_DCHECK_GE(ulpfec_payload_type, -1); |
187 RTC_DCHECK_LE(ulpfec_payload_type, 127); | 189 RTC_DCHECK_LE(ulpfec_payload_type, 127); |
188 | 190 |
189 rtc::CritScope cs(&crit_); | 191 rtc::CritScope cs(&crit_); |
190 fec_enabled_ = enabled; | |
191 red_payload_type_ = red_payload_type; | 192 red_payload_type_ = red_payload_type; |
192 fec_payload_type_ = ulpfec_payload_type; | 193 ulpfec_payload_type_ = ulpfec_payload_type; |
| 194 |
| 195 // Must not enable ULPFEC without RED. |
| 196 // TODO(brandtr): We currently support enabling RED without ULPFEC. Change |
| 197 // this when we have removed the RED/RTX send-side workaround, so that we |
| 198 // ensure that RED and ULPFEC are only enabled together. |
| 199 RTC_DCHECK(red_enabled() || !ulpfec_enabled()); |
193 | 200 |
194 // Reset FEC rates. | 201 // Reset FEC rates. |
195 delta_fec_params_ = FecProtectionParams{0, 1, kFecMaskRandom}; | 202 delta_fec_params_ = FecProtectionParams{0, 1, kFecMaskRandom}; |
196 key_fec_params_ = FecProtectionParams{0, 1, kFecMaskRandom}; | 203 key_fec_params_ = FecProtectionParams{0, 1, kFecMaskRandom}; |
197 } | 204 } |
198 | 205 |
199 void RTPSenderVideo::GetUlpfecConfig(bool* enabled, | 206 void RTPSenderVideo::GetUlpfecConfig(int* red_payload_type, |
200 int* red_payload_type, | |
201 int* ulpfec_payload_type) const { | 207 int* ulpfec_payload_type) const { |
202 rtc::CritScope cs(&crit_); | 208 rtc::CritScope cs(&crit_); |
203 *enabled = fec_enabled_; | |
204 *red_payload_type = red_payload_type_; | 209 *red_payload_type = red_payload_type_; |
205 *ulpfec_payload_type = fec_payload_type_; | 210 *ulpfec_payload_type = ulpfec_payload_type_; |
206 } | 211 } |
207 | 212 |
208 size_t RTPSenderVideo::FecPacketOverhead() const { | 213 size_t RTPSenderVideo::FecPacketOverhead() const { |
209 rtc::CritScope cs(&crit_); | 214 rtc::CritScope cs(&crit_); |
210 size_t overhead = 0; | 215 size_t overhead = 0; |
211 if (red_payload_type_ != -1) { | 216 if (red_enabled()) { |
212 // Overhead is FEC headers plus RED for FEC header plus anything in RTP | 217 // Overhead is FEC headers plus RED for FEC header plus anything in RTP |
213 // header beyond the 12 bytes base header (CSRC list, extensions...) | 218 // header beyond the 12 bytes base header (CSRC list, extensions...) |
214 // This reason for the header extensions to be included here is that | 219 // This reason for the header extensions to be included here is that |
215 // from an FEC viewpoint, they are part of the payload to be protected. | 220 // from an FEC viewpoint, they are part of the payload to be protected. |
216 // (The base RTP header is already protected by the FEC header.) | 221 // (The base RTP header is already protected by the FEC header.) |
217 return ulpfec_generator_.MaxPacketOverhead() + kRedForFecHeaderLength + | 222 return ulpfec_generator_.MaxPacketOverhead() + kRedForFecHeaderLength + |
218 (rtp_sender_->RtpHeaderLength() - kRtpHeaderSize); | 223 (rtp_sender_->RtpHeaderLength() - kRtpHeaderSize); |
219 } | 224 } |
220 if (fec_enabled_) | 225 if (ulpfec_enabled()) |
221 overhead += ulpfec_generator_.MaxPacketOverhead(); | 226 overhead += ulpfec_generator_.MaxPacketOverhead(); |
222 return overhead; | 227 return overhead; |
223 } | 228 } |
224 | 229 |
225 void RTPSenderVideo::SetFecParameters(const FecProtectionParams* delta_params, | 230 void RTPSenderVideo::SetFecParameters(const FecProtectionParams* delta_params, |
226 const FecProtectionParams* key_params) { | 231 const FecProtectionParams* key_params) { |
227 rtc::CritScope cs(&crit_); | 232 rtc::CritScope cs(&crit_); |
228 RTC_DCHECK(delta_params); | 233 RTC_DCHECK(delta_params); |
229 RTC_DCHECK(key_params); | 234 RTC_DCHECK(key_params); |
230 if (fec_enabled_) { | 235 if (ulpfec_enabled()) { |
231 delta_fec_params_ = *delta_params; | 236 delta_fec_params_ = *delta_params; |
232 key_fec_params_ = *key_params; | 237 key_fec_params_ = *key_params; |
233 } | 238 } |
234 } | 239 } |
235 | 240 |
236 bool RTPSenderVideo::SendVideo(RtpVideoCodecTypes video_type, | 241 bool RTPSenderVideo::SendVideo(RtpVideoCodecTypes video_type, |
237 FrameType frame_type, | 242 FrameType frame_type, |
238 int8_t payload_type, | 243 int8_t payload_type, |
239 uint32_t rtp_timestamp, | 244 uint32_t rtp_timestamp, |
240 int64_t capture_time_ms, | 245 int64_t capture_time_ms, |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 (rtp_sender_->RtxStatus() ? kRtxHeaderSize : 0); | 281 (rtp_sender_->RtxStatus() ? kRtxHeaderSize : 0); |
277 RTC_DCHECK_LE(packet_capacity, rtp_header->capacity()); | 282 RTC_DCHECK_LE(packet_capacity, rtp_header->capacity()); |
278 RTC_DCHECK_GT(packet_capacity, rtp_header->headers_size()); | 283 RTC_DCHECK_GT(packet_capacity, rtp_header->headers_size()); |
279 size_t max_data_payload_length = packet_capacity - rtp_header->headers_size(); | 284 size_t max_data_payload_length = packet_capacity - rtp_header->headers_size(); |
280 | 285 |
281 std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( | 286 std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( |
282 video_type, max_data_payload_length, | 287 video_type, max_data_payload_length, |
283 video_header ? &(video_header->codecHeader) : nullptr, frame_type)); | 288 video_header ? &(video_header->codecHeader) : nullptr, frame_type)); |
284 | 289 |
285 StorageType storage; | 290 StorageType storage; |
286 int red_payload_type; | 291 bool red_enabled; |
287 bool first_frame = first_frame_sent_(); | 292 bool first_frame = first_frame_sent_(); |
288 { | 293 { |
289 rtc::CritScope cs(&crit_); | 294 rtc::CritScope cs(&crit_); |
290 FecProtectionParams* fec_params = | 295 FecProtectionParams* fec_params = |
291 frame_type == kVideoFrameKey ? &key_fec_params_ : &delta_fec_params_; | 296 frame_type == kVideoFrameKey ? &key_fec_params_ : &delta_fec_params_; |
292 ulpfec_generator_.SetFecParameters(fec_params); | 297 ulpfec_generator_.SetFecParameters(fec_params); |
293 storage = packetizer->GetStorageType(retransmission_settings_); | 298 storage = packetizer->GetStorageType(retransmission_settings_); |
294 red_payload_type = red_payload_type_; | 299 red_enabled = this->red_enabled(); |
295 } | 300 } |
296 | 301 |
297 // TODO(changbin): we currently don't support to configure the codec to | 302 // TODO(changbin): we currently don't support to configure the codec to |
298 // output multiple partitions for VP8. Should remove below check after the | 303 // output multiple partitions for VP8. Should remove below check after the |
299 // issue is fixed. | 304 // issue is fixed. |
300 const RTPFragmentationHeader* frag = | 305 const RTPFragmentationHeader* frag = |
301 (video_type == kRtpVideoVp8) ? NULL : fragmentation; | 306 (video_type == kRtpVideoVp8) ? NULL : fragmentation; |
302 | 307 |
303 packetizer->SetPayloadData(payload_data, payload_size, frag); | 308 packetizer->SetPayloadData(payload_data, payload_size, frag); |
304 | 309 |
305 bool first = true; | 310 bool first = true; |
306 bool last = false; | 311 bool last = false; |
307 while (!last) { | 312 while (!last) { |
308 std::unique_ptr<RtpPacketToSend> packet(new RtpPacketToSend(*rtp_header)); | 313 std::unique_ptr<RtpPacketToSend> packet(new RtpPacketToSend(*rtp_header)); |
309 uint8_t* payload = packet->AllocatePayload(max_data_payload_length); | 314 uint8_t* payload = packet->AllocatePayload(max_data_payload_length); |
310 RTC_DCHECK(payload); | 315 RTC_DCHECK(payload); |
311 | 316 |
312 size_t payload_bytes_in_packet = 0; | 317 size_t payload_bytes_in_packet = 0; |
313 if (!packetizer->NextPacket(payload, &payload_bytes_in_packet, &last)) | 318 if (!packetizer->NextPacket(payload, &payload_bytes_in_packet, &last)) |
314 return false; | 319 return false; |
315 | 320 |
316 packet->SetPayloadSize(payload_bytes_in_packet); | 321 packet->SetPayloadSize(payload_bytes_in_packet); |
317 packet->SetMarker(last); | 322 packet->SetMarker(last); |
318 if (!rtp_sender_->AssignSequenceNumber(packet.get())) | 323 if (!rtp_sender_->AssignSequenceNumber(packet.get())) |
319 return false; | 324 return false; |
320 | 325 |
321 if (red_payload_type != -1) { | 326 if (red_enabled) { |
322 SendVideoPacketAsRed(std::move(packet), storage, | 327 SendVideoPacketAsRed(std::move(packet), storage, |
323 packetizer->GetProtectionType() == kProtectedPacket); | 328 packetizer->GetProtectionType() == kProtectedPacket); |
324 } else { | 329 } else { |
325 SendVideoPacket(std::move(packet), storage); | 330 SendVideoPacket(std::move(packet), storage); |
326 } | 331 } |
327 | 332 |
328 if (first_frame) { | 333 if (first_frame) { |
329 if (first) { | 334 if (first) { |
330 LOG(LS_INFO) | 335 LOG(LS_INFO) |
331 << "Sent first RTP packet of the first video frame (pre-pacer)"; | 336 << "Sent first RTP packet of the first video frame (pre-pacer)"; |
(...skipping 25 matching lines...) Expand all Loading... |
357 rtc::CritScope cs(&crit_); | 362 rtc::CritScope cs(&crit_); |
358 return retransmission_settings_; | 363 return retransmission_settings_; |
359 } | 364 } |
360 | 365 |
361 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { | 366 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { |
362 rtc::CritScope cs(&crit_); | 367 rtc::CritScope cs(&crit_); |
363 retransmission_settings_ = settings; | 368 retransmission_settings_ = settings; |
364 } | 369 } |
365 | 370 |
366 } // namespace webrtc | 371 } // namespace webrtc |
OLD | NEW |