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

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

Issue 2999063002: Add flag enabling more packets to be retransmittable. (Closed)
Patch Set: Removed GetStorageType and ProtectionType from packetizers. Refactorings. Addressed comments. Created 3 years, 3 months 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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698