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

Unified Diff: webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc

Issue 2999063002: Add flag enabling more packets to be retransmittable. (Closed)
Patch Set: 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/rtp_sender_video.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
index 38450742be9e29022cbabd2245952a88a1b09ddf..4e46b78baa6090fd98c68529b6d1a9700fa735fc 100644
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender_video.cc
@@ -13,9 +13,10 @@
#include <stdlib.h>
#include <string.h>
+#include <limits>
#include <memory>
-#include <vector>
#include <utility>
+#include <vector>
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "webrtc/modules/rtp_rtcp/source/byte_io.h"
@@ -33,6 +34,7 @@ namespace webrtc {
namespace {
constexpr size_t kRedForFecHeaderLength = 1;
+constexpr int64_t kMaxUnretransmittableFrameIntervalMs = 33 * 4;
void BuildRedPayload(const RtpPacketToSend& media_packet,
RtpPacketToSend* red_packet) {
@@ -53,7 +55,8 @@ RTPSenderVideo::RTPSenderVideo(Clock* clock,
: rtp_sender_(rtp_sender),
clock_(clock),
video_type_(kRtpVideoGeneric),
- retransmission_settings_(kRetransmitBaseLayer),
+ retransmission_settings_(kRetransmitBaseLayer |
+ kConditionallyRetransmitHigherLayers),
last_rotation_(kVideoRotation_0),
red_payload_type_(-1),
ulpfec_payload_type_(-1),
@@ -292,7 +295,8 @@ bool RTPSenderVideo::SendVideo(RtpVideoCodecTypes video_type,
const uint8_t* payload_data,
size_t payload_size,
const RTPFragmentationHeader* fragmentation,
- const RTPVideoHeader* video_header) {
+ const RTPVideoHeader* video_header,
+ int64_t expected_retransmission_time_ms) {
if (payload_size == 0)
return false;
@@ -365,8 +369,11 @@ bool RTPSenderVideo::SendVideo(RtpVideoCodecTypes video_type,
std::unique_ptr<RtpPacketizer> packetizer(RtpPacketizer::Create(
video_type, max_data_payload_length, last_packet_reduction_len,
video_header ? &(video_header->codecHeader) : nullptr, frame_type));
- // Media packet storage.
- StorageType storage = packetizer->GetStorageType(retransmission_settings);
+
+ const uint8_t temporal_id =
+ video_header ? GetTemporalId(*video_header) : kNoTemporalIdx;
+ StorageType storage = GetStorageType(temporal_id, retransmission_settings,
+ expected_retransmission_time_ms);
// TODO(changbin): we currently don't support to configure the codec to
// output multiple partitions for VP8. Should remove below check after the
@@ -392,7 +399,9 @@ bool RTPSenderVideo::SendVideo(RtpVideoCodecTypes video_type,
if (!rtp_sender_->AssignSequenceNumber(packet.get()))
return false;
- bool protect_packet = (packetizer->GetProtectionType() == kProtectedPacket);
+ // No FEC protection for upper temporal layers, if used.
+ bool protect_packet = temporal_id == 0 || temporal_id == kNoTemporalIdx;
+
// Put packetization finish timestamp into extension.
if (packet->HasExtension<VideoTimingExtension>()) {
packet->set_packetization_finish_time_ms(clock_->TimeInMilliseconds());
@@ -453,4 +462,90 @@ void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) {
retransmission_settings_ = settings;
}
+StorageType RTPSenderVideo::GetStorageType(
+ uint8_t temporal_id,
+ int32_t retransmission_settings,
+ int64_t expected_retransmission_time_ms) {
+ if (retransmission_settings == kRetransmitOff)
+ return StorageType::kDontRetransmit;
+ if (retransmission_settings == kRetransmitAllPackets)
+ return StorageType::kAllowRetransmission;
+
+ rtc::CritScope cs(&stats_crit_);
+ // Media packet storage.
+ if ((retransmission_settings & kConditionallyRetransmitHigherLayers) &&
+ UpdateConditionalRetransmit(temporal_id,
+ expected_retransmission_time_ms)) {
+ retransmission_settings |= kRetransmitHigherLayers;
+ }
+
+ if (temporal_id == kNoTemporalIdx)
+ return kAllowRetransmission;
+
+ if ((retransmission_settings & kRetransmitBaseLayer) && temporal_id == 0)
+ return kAllowRetransmission;
+
+ if ((retransmission_settings & kRetransmitHigherLayers) && temporal_id > 0)
+ return kAllowRetransmission;
+
+ return kDontRetransmit;
+}
+
+uint8_t RTPSenderVideo::GetTemporalId(const RTPVideoHeader& header) {
+ switch (header.codec) {
+ case kRtpVideoVp8:
+ return header.codecHeader.VP8.temporalIdx;
+ case kRtpVideoVp9:
+ return header.codecHeader.VP9.temporal_idx;
+ default:
+ return kNoTemporalIdx;
+ }
+}
+
+bool RTPSenderVideo::UpdateConditionalRetransmit(
+ uint8_t temporal_id,
+ int64_t expected_retransmission_time_ms) {
+ int64_t now_ms = clock_->TimeInMilliseconds();
+ // Update stats for any temporal layer.
+ TemporalLayerStats* current_layer_stats =
+ &frame_stats_by_temporal_layer_[temporal_id];
+ current_layer_stats->frame_rate_fp1000s.Update(1, now_ms);
+ int64_t tl_frame_interval = now_ms - current_layer_stats->last_frame_time_ms;
+ current_layer_stats->last_frame_time_ms = now_ms;
+
+ // Conditional retransmit only applies to upper layers.
+ if (temporal_id != kNoTemporalIdx && temporal_id > 0) {
+ if (tl_frame_interval >= kMaxUnretransmittableFrameIntervalMs) {
+ // Too long since a retransmittable frame in this layer, enable NACK
+ // protection.
+ return true;
+ } else {
+ // Estimate when the next frame of any lower layer will be sent.
+ const int64_t kUndefined = std::numeric_limits<int64_t>::max();
+ int64_t expected_next_frame_time = kUndefined;
+ for (int i = temporal_id - 1; i >= 0; --i) {
+ TemporalLayerStats* stats = &frame_stats_by_temporal_layer_[i];
+ rtc::Optional<uint32_t> rate = stats->frame_rate_fp1000s.Rate(now_ms);
+ if (rate) {
+ int64_t tl_next = stats->last_frame_time_ms + 1000000 / *rate;
+ if (tl_next - now_ms > -expected_retransmission_time_ms &&
+ tl_next < expected_next_frame_time) {
+ expected_next_frame_time = tl_next;
+ }
+ }
+ }
+
+ if (expected_next_frame_time == kUndefined ||
+ expected_next_frame_time - now_ms > expected_retransmission_time_ms) {
+ // The next frame in a lower layer is expected at a later time (or
+ // unable to tell due to lack of data) than a retransmission is
+ // estimated to be able to arrive, so allow this packet to be nacked.
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
} // namespace webrtc
« no previous file with comments | « webrtc/modules/rtp_rtcp/source/rtp_sender_video.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698