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 |
11 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h" | 11 #include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h" |
12 | 12 |
13 #include <stdlib.h> | 13 #include <stdlib.h> |
14 #include <string.h> | 14 #include <string.h> |
15 | 15 |
16 #include <limits> | |
16 #include <memory> | 17 #include <memory> |
18 #include <utility> | |
17 #include <vector> | 19 #include <vector> |
18 #include <utility> | |
19 | 20 |
20 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" | 21 #include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h" |
21 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" | 22 #include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
22 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" | 23 #include "webrtc/modules/rtp_rtcp/source/rtp_format_video_generic.h" |
23 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" | 24 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp8.h" |
24 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h" | 25 #include "webrtc/modules/rtp_rtcp/source/rtp_format_vp9.h" |
25 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" | 26 #include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" |
26 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" | 27 #include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" |
27 #include "webrtc/rtc_base/checks.h" | 28 #include "webrtc/rtc_base/checks.h" |
28 #include "webrtc/rtc_base/logging.h" | 29 #include "webrtc/rtc_base/logging.h" |
29 #include "webrtc/rtc_base/ptr_util.h" | 30 #include "webrtc/rtc_base/ptr_util.h" |
30 #include "webrtc/rtc_base/trace_event.h" | 31 #include "webrtc/rtc_base/trace_event.h" |
31 | 32 |
32 namespace webrtc { | 33 namespace webrtc { |
33 | 34 |
34 namespace { | 35 namespace { |
35 constexpr size_t kRedForFecHeaderLength = 1; | 36 constexpr size_t kRedForFecHeaderLength = 1; |
37 constexpr int64_t kMaxUnretransmittableFrameIntervalMs = 33 * 4; | |
36 | 38 |
37 void BuildRedPayload(const RtpPacketToSend& media_packet, | 39 void BuildRedPayload(const RtpPacketToSend& media_packet, |
38 RtpPacketToSend* red_packet) { | 40 RtpPacketToSend* red_packet) { |
39 uint8_t* red_payload = red_packet->AllocatePayload( | 41 uint8_t* red_payload = red_packet->AllocatePayload( |
40 kRedForFecHeaderLength + media_packet.payload_size()); | 42 kRedForFecHeaderLength + media_packet.payload_size()); |
41 RTC_DCHECK(red_payload); | 43 RTC_DCHECK(red_payload); |
42 red_payload[0] = media_packet.PayloadType(); | 44 red_payload[0] = media_packet.PayloadType(); |
43 | 45 |
44 auto media_payload = media_packet.payload(); | 46 auto media_payload = media_packet.payload(); |
45 memcpy(&red_payload[kRedForFecHeaderLength], media_payload.data(), | 47 memcpy(&red_payload[kRedForFecHeaderLength], media_payload.data(), |
46 media_payload.size()); | 48 media_payload.size()); |
47 } | 49 } |
48 } // namespace | 50 } // namespace |
49 | 51 |
50 RTPSenderVideo::RTPSenderVideo(Clock* clock, | 52 RTPSenderVideo::RTPSenderVideo(Clock* clock, |
51 RTPSender* rtp_sender, | 53 RTPSender* rtp_sender, |
52 FlexfecSender* flexfec_sender) | 54 FlexfecSender* flexfec_sender) |
53 : rtp_sender_(rtp_sender), | 55 : rtp_sender_(rtp_sender), |
54 clock_(clock), | 56 clock_(clock), |
55 video_type_(kRtpVideoGeneric), | 57 video_type_(kRtpVideoGeneric), |
56 retransmission_settings_(kRetransmitBaseLayer), | 58 retransmission_settings_(kRetransmitBaseLayer | |
59 kConditionallyRetransmitHigherLayers), | |
57 last_rotation_(kVideoRotation_0), | 60 last_rotation_(kVideoRotation_0), |
58 red_payload_type_(-1), | 61 red_payload_type_(-1), |
59 ulpfec_payload_type_(-1), | 62 ulpfec_payload_type_(-1), |
60 flexfec_sender_(flexfec_sender), | 63 flexfec_sender_(flexfec_sender), |
61 delta_fec_params_{0, 1, kFecMaskRandom}, | 64 delta_fec_params_{0, 1, kFecMaskRandom}, |
62 key_fec_params_{0, 1, kFecMaskRandom}, | 65 key_fec_params_{0, 1, kFecMaskRandom}, |
63 fec_bitrate_(1000, RateStatistics::kBpsScale), | 66 fec_bitrate_(1000, RateStatistics::kBpsScale), |
64 video_bitrate_(1000, RateStatistics::kBpsScale) {} | 67 video_bitrate_(1000, RateStatistics::kBpsScale) {} |
65 | 68 |
66 RTPSenderVideo::~RTPSenderVideo() {} | 69 RTPSenderVideo::~RTPSenderVideo() {} |
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
285 } | 288 } |
286 | 289 |
287 bool RTPSenderVideo::SendVideo(RtpVideoCodecTypes video_type, | 290 bool RTPSenderVideo::SendVideo(RtpVideoCodecTypes video_type, |
288 FrameType frame_type, | 291 FrameType frame_type, |
289 int8_t payload_type, | 292 int8_t payload_type, |
290 uint32_t rtp_timestamp, | 293 uint32_t rtp_timestamp, |
291 int64_t capture_time_ms, | 294 int64_t capture_time_ms, |
292 const uint8_t* payload_data, | 295 const uint8_t* payload_data, |
293 size_t payload_size, | 296 size_t payload_size, |
294 const RTPFragmentationHeader* fragmentation, | 297 const RTPFragmentationHeader* fragmentation, |
295 const RTPVideoHeader* video_header) { | 298 const RTPVideoHeader* video_header, |
299 int64_t expected_retransmission_time_ms) { | |
296 if (payload_size == 0) | 300 if (payload_size == 0) |
297 return false; | 301 return false; |
298 | 302 |
299 // Create header that will be reused in all packets. | 303 // Create header that will be reused in all packets. |
300 std::unique_ptr<RtpPacketToSend> rtp_header = rtp_sender_->AllocatePacket(); | 304 std::unique_ptr<RtpPacketToSend> rtp_header = rtp_sender_->AllocatePacket(); |
301 rtp_header->SetPayloadType(payload_type); | 305 rtp_header->SetPayloadType(payload_type); |
302 rtp_header->SetTimestamp(rtp_timestamp); | 306 rtp_header->SetTimestamp(rtp_timestamp); |
303 rtp_header->set_capture_time_ms(capture_time_ms); | 307 rtp_header->set_capture_time_ms(capture_time_ms); |
304 auto last_packet = rtc::MakeUnique<RtpPacketToSend>(*rtp_header); | 308 auto last_packet = rtc::MakeUnique<RtpPacketToSend>(*rtp_header); |
305 | 309 |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
358 RTC_DCHECK_GT(packet_capacity, rtp_header->headers_size()); | 362 RTC_DCHECK_GT(packet_capacity, rtp_header->headers_size()); |
359 RTC_DCHECK_GT(packet_capacity, last_packet->headers_size()); | 363 RTC_DCHECK_GT(packet_capacity, last_packet->headers_size()); |
360 size_t max_data_payload_length = packet_capacity - rtp_header->headers_size(); | 364 size_t max_data_payload_length = packet_capacity - rtp_header->headers_size(); |
361 RTC_DCHECK_GE(last_packet->headers_size(), rtp_header->headers_size()); | 365 RTC_DCHECK_GE(last_packet->headers_size(), rtp_header->headers_size()); |
362 size_t last_packet_reduction_len = | 366 size_t last_packet_reduction_len = |
363 last_packet->headers_size() - rtp_header->headers_size(); | 367 last_packet->headers_size() - rtp_header->headers_size(); |
364 | 368 |
365 std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( | 369 std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create( |
366 video_type, max_data_payload_length, last_packet_reduction_len, | 370 video_type, max_data_payload_length, last_packet_reduction_len, |
367 video_header ? &(video_header->codecHeader) : nullptr, frame_type)); | 371 video_header ? &(video_header->codecHeader) : nullptr, frame_type)); |
368 // Media packet storage. | 372 |
369 StorageType storage = packetizer->GetStorageType(retransmission_settings); | 373 const uint8_t temporal_id = |
374 video_header ? GetTemporalId(*video_header) : kNoTemporalIdx; | |
375 StorageType storage = | |
376 GetStorageType(temporal_id, retransmission_settings, packetizer.get(), | |
377 expected_retransmission_time_ms); | |
370 | 378 |
371 // TODO(changbin): we currently don't support to configure the codec to | 379 // TODO(changbin): we currently don't support to configure the codec to |
372 // output multiple partitions for VP8. Should remove below check after the | 380 // output multiple partitions for VP8. Should remove below check after the |
373 // issue is fixed. | 381 // issue is fixed. |
374 const RTPFragmentationHeader* frag = | 382 const RTPFragmentationHeader* frag = |
375 (video_type == kRtpVideoVp8) ? nullptr : fragmentation; | 383 (video_type == kRtpVideoVp8) ? nullptr : fragmentation; |
376 size_t num_packets = | 384 size_t num_packets = |
377 packetizer->SetPayloadData(payload_data, payload_size, frag); | 385 packetizer->SetPayloadData(payload_data, payload_size, frag); |
378 | 386 |
379 if (num_packets == 0) | 387 if (num_packets == 0) |
380 return false; | 388 return false; |
381 | 389 |
382 bool first_frame = first_frame_sent_(); | 390 bool first_frame = first_frame_sent_(); |
383 for (size_t i = 0; i < num_packets; ++i) { | 391 for (size_t i = 0; i < num_packets; ++i) { |
384 bool last = (i + 1) == num_packets; | 392 bool last = (i + 1) == num_packets; |
385 auto packet = last ? std::move(last_packet) | 393 auto packet = last ? std::move(last_packet) |
386 : rtc::MakeUnique<RtpPacketToSend>(*rtp_header); | 394 : rtc::MakeUnique<RtpPacketToSend>(*rtp_header); |
387 if (!packetizer->NextPacket(packet.get())) | 395 if (!packetizer->NextPacket(packet.get())) |
388 return false; | 396 return false; |
389 RTC_DCHECK_LE(packet->payload_size(), | 397 RTC_DCHECK_LE(packet->payload_size(), |
390 last ? max_data_payload_length - last_packet_reduction_len | 398 last ? max_data_payload_length - last_packet_reduction_len |
391 : max_data_payload_length); | 399 : max_data_payload_length); |
392 if (!rtp_sender_->AssignSequenceNumber(packet.get())) | 400 if (!rtp_sender_->AssignSequenceNumber(packet.get())) |
393 return false; | 401 return false; |
394 | 402 |
395 bool protect_packet = (packetizer->GetProtectionType() == kProtectedPacket); | 403 // No FEC protection for upper temporal layers, if used. |
404 const uint8_t temporal_id = | |
danilchap
2017/09/04 09:03:04
this statement can be removed - temporal_id alread
brandtr
2017/09/04 10:29:22
Reuse |temporal_id| from line 373?
sprang_webrtc
2017/09/04 11:09:28
Done.
sprang_webrtc
2017/09/04 11:09:28
Done.
| |
405 video_header ? GetTemporalId(*video_header) : kNoTemporalIdx; | |
406 bool protect_packet = temporal_id == 0 || temporal_id == kNoTemporalIdx; | |
407 | |
396 // Put packetization finish timestamp into extension. | 408 // Put packetization finish timestamp into extension. |
397 if (packet->HasExtension<VideoTimingExtension>()) { | 409 if (packet->HasExtension<VideoTimingExtension>()) { |
398 packet->set_packetization_finish_time_ms(clock_->TimeInMilliseconds()); | 410 packet->set_packetization_finish_time_ms(clock_->TimeInMilliseconds()); |
399 // TODO(ilnik): Due to webrtc:7859, packets with timing extensions are not | 411 // TODO(ilnik): Due to webrtc:7859, packets with timing extensions are not |
400 // protected by FEC. It reduces FEC efficiency a bit. When FEC is moved | 412 // protected by FEC. It reduces FEC efficiency a bit. When FEC is moved |
401 // below the pacer, it can be re-enabled for these packets. | 413 // below the pacer, it can be re-enabled for these packets. |
402 // NOTE: Any RTP stream processor in the network, modifying 'network' | 414 // NOTE: Any RTP stream processor in the network, modifying 'network' |
403 // timestamps in the timing frames extension have to be an end-point for | 415 // timestamps in the timing frames extension have to be an end-point for |
404 // FEC, otherwise recovered by FEC packets will be corrupted. | 416 // FEC, otherwise recovered by FEC packets will be corrupted. |
405 protect_packet = false; | 417 protect_packet = false; |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
446 int RTPSenderVideo::SelectiveRetransmissions() const { | 458 int RTPSenderVideo::SelectiveRetransmissions() const { |
447 rtc::CritScope cs(&crit_); | 459 rtc::CritScope cs(&crit_); |
448 return retransmission_settings_; | 460 return retransmission_settings_; |
449 } | 461 } |
450 | 462 |
451 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { | 463 void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) { |
452 rtc::CritScope cs(&crit_); | 464 rtc::CritScope cs(&crit_); |
453 retransmission_settings_ = settings; | 465 retransmission_settings_ = settings; |
454 } | 466 } |
455 | 467 |
468 StorageType RTPSenderVideo::GetStorageType( | |
469 uint8_t temporal_id, | |
470 int32_t retransmission_settings, | |
danilchap
2017/09/04 09:03:04
since retransmission_settings is a bitmask, may be
sprang_webrtc
2017/09/04 11:09:28
Using RetransmissionMode directly forces a lot of
| |
471 RtpPacketizer* packetizer, | |
danilchap
2017/09/04 09:03:04
this parameter is no longer needed
sprang_webrtc
2017/09/04 11:09:28
Done.
| |
472 int64_t expected_retransmission_time) { | |
danilchap
2017/09/04 09:03:04
add _ms
sprang_webrtc
2017/09/04 11:09:28
Done.
| |
473 if (retransmission_settings == kRetransmitOff) | |
474 return StorageType::kDontRetransmit; | |
475 if (retransmission_settings == kRetransmitAllPackets) | |
476 return StorageType::kAllowRetransmission; | |
477 | |
478 rtc::CritScope cs(&stats_crit_); | |
479 // Media packet storage. | |
480 if ((retransmission_settings & kConditionallyRetransmitHigherLayers) && | |
481 (UpdateConditionalRetransmit(temporal_id, | |
danilchap
2017/09/04 09:03:04
extra () around function call can be removed
sprang_webrtc
2017/09/04 11:09:28
Done.
| |
482 expected_retransmission_time))) { | |
483 retransmission_settings |= kRetransmitHigherLayers; | |
484 } | |
485 | |
486 if (temporal_id == kNoTemporalIdx) | |
487 return kAllowRetransmission; | |
488 | |
489 if ((retransmission_settings & kRetransmitBaseLayer) && temporal_id == 0) | |
490 return kAllowRetransmission; | |
491 | |
492 if ((retransmission_settings & kRetransmitHigherLayers) && temporal_id > 0) | |
493 return kAllowRetransmission; | |
494 | |
495 return kDontRetransmit; | |
496 } | |
497 | |
498 uint8_t RTPSenderVideo::GetTemporalId(const RTPVideoHeader& header) const { | |
499 switch (header.codec) { | |
500 case kRtpVideoVp8: | |
501 return header.codecHeader.VP8.temporalIdx; | |
502 case kRtpVideoVp9: | |
503 return header.codecHeader.VP9.temporal_idx; | |
504 default: | |
505 return kNoTemporalIdx; | |
506 } | |
507 } | |
508 | |
509 bool RTPSenderVideo::UpdateConditionalRetransmit( | |
510 uint8_t temporal_id, | |
511 int64_t expected_retransmission_time_ms) { | |
512 int64_t now_ms = clock_->TimeInMilliseconds(); | |
513 // Update stats for any temporal layer. | |
514 TemporalLayerStats* current_layer_stats = | |
515 &frame_stats_by_temporal_layer_[temporal_id]; | |
516 current_layer_stats->frame_rate_fp1000s.Update(1, now_ms); | |
517 int64_t tl_frame_interval = now_ms - current_layer_stats->last_frame_time; | |
518 current_layer_stats->last_frame_time = now_ms; | |
519 | |
520 // Conditional retransmit only applies to upper layers. | |
521 if (temporal_id != kNoTemporalIdx && temporal_id > 0) { | |
522 if (tl_frame_interval >= kMaxUnretransmittableFrameIntervalMs) { | |
523 // Too long since a retransmittable frame in this layer, enable NACK | |
524 // protection. | |
525 return true; | |
526 } else { | |
527 // Estimate when the next frame of any lower layer will be sent. | |
528 const int64_t kUndefined = std::numeric_limits<int64_t>::max(); | |
529 int64_t expected_next_frame_time = kUndefined; | |
530 for (int i = temporal_id - 1; i >= 0; --i) { | |
531 TemporalLayerStats* stats = &frame_stats_by_temporal_layer_[i]; | |
532 rtc::Optional<uint32_t> rate = stats->frame_rate_fp1000s.Rate(now_ms); | |
533 if (rate) { | |
534 int64_t tl_next = stats->last_frame_time + 1000000 / *rate; | |
535 if (tl_next - now_ms > -expected_retransmission_time_ms && | |
536 tl_next < expected_next_frame_time) { | |
537 expected_next_frame_time = tl_next; | |
538 } | |
539 } | |
540 } | |
541 | |
542 if (expected_next_frame_time == kUndefined || | |
543 expected_next_frame_time - now_ms > expected_retransmission_time_ms) { | |
544 // The next frame in a lower layer is expected at a later time (or | |
545 // unable to tell due to lack of data) than a retransmission is | |
546 // estimated to be able to arrive, so allow this packet to be nacked. | |
547 return true; | |
548 } | |
549 } | |
550 } | |
551 | |
552 return false; | |
553 } | |
554 | |
456 } // namespace webrtc | 555 } // namespace webrtc |
OLD | NEW |