Propagate active decode targets bitmask into DependencyDescriptor
Bug: webrtc:10342 Change-Id: I5e8a204881b94fe5786b14e27cefce2fe056e91b Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/178140 Reviewed-by: Björn Terelius <terelius@webrtc.org> Reviewed-by: Philip Eliasson <philipel@webrtc.org> Commit-Queue: Danil Chapovalov <danilchap@webrtc.org> Cr-Commit-Position: refs/heads/master@{#31579}
This commit is contained in:

committed by
Commit Bot

parent
11b6f6857f
commit
e6ac8ff162
@ -245,6 +245,7 @@ RtpPayloadParams::GenericDescriptorFromFrameInfo(
|
|||||||
generic.spatial_index = frame_info.spatial_id;
|
generic.spatial_index = frame_info.spatial_id;
|
||||||
generic.temporal_index = frame_info.temporal_id;
|
generic.temporal_index = frame_info.temporal_id;
|
||||||
generic.decode_target_indications = frame_info.decode_target_indications;
|
generic.decode_target_indications = frame_info.decode_target_indications;
|
||||||
|
generic.active_decode_targets = frame_info.active_decode_targets;
|
||||||
return generic;
|
return generic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,6 +93,7 @@ void ActiveDecodeTargetsHelper::OnFrame(
|
|||||||
if (is_keyframe) {
|
if (is_keyframe) {
|
||||||
// Key frame resets the state.
|
// Key frame resets the state.
|
||||||
last_active_decode_targets_ = all_decode_targets;
|
last_active_decode_targets_ = all_decode_targets;
|
||||||
|
last_active_chains_ = AllActive(num_chains);
|
||||||
unsent_on_chain_.reset();
|
unsent_on_chain_.reset();
|
||||||
} else {
|
} else {
|
||||||
// Update state assuming previous frame was sent.
|
// Update state assuming previous frame was sent.
|
||||||
@ -108,12 +109,12 @@ void ActiveDecodeTargetsHelper::OnFrame(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
last_active_decode_targets_ = active_decode_targets;
|
last_active_decode_targets_ = active_decode_targets;
|
||||||
|
last_active_chains_ = ActiveChains(decode_target_protected_by_chain,
|
||||||
|
num_chains, active_decode_targets);
|
||||||
// Frames that are part of inactive chains might not be produced by the
|
// Frames that are part of inactive chains might not be produced by the
|
||||||
// encoder. Thus stop sending `active_decode_target` bitmask when it is sent
|
// encoder. Thus stop sending `active_decode_target` bitmask when it is sent
|
||||||
// on all active chains rather than on all chains.
|
// on all active chains rather than on all chains.
|
||||||
unsent_on_chain_ = ActiveChains(decode_target_protected_by_chain, num_chains,
|
unsent_on_chain_ = last_active_chains_;
|
||||||
active_decode_targets);
|
|
||||||
if (unsent_on_chain_.none()) {
|
if (unsent_on_chain_.none()) {
|
||||||
// Active decode targets are not protected by any chains. To be on the
|
// Active decode targets are not protected by any chains. To be on the
|
||||||
// safe side always send the active_decode_targets_bitmask from now on.
|
// safe side always send the active_decode_targets_bitmask from now on.
|
||||||
|
@ -47,11 +47,14 @@ class ActiveDecodeTargetsHelper {
|
|||||||
return last_active_decode_targets_.to_ulong();
|
return last_active_decode_targets_.to_ulong();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::bitset<32> ActiveChainsBitmask() const { return last_active_chains_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// `unsent_on_chain_[i]` indicates last active decode
|
// `unsent_on_chain_[i]` indicates last active decode
|
||||||
// target bitmask wasn't attached to a packet on the chain with id `i`.
|
// target bitmask wasn't attached to a packet on the chain with id `i`.
|
||||||
std::bitset<32> unsent_on_chain_ = 0;
|
std::bitset<32> unsent_on_chain_ = 0;
|
||||||
std::bitset<32> last_active_decode_targets_ = 0;
|
std::bitset<32> last_active_decode_targets_ = 0;
|
||||||
|
std::bitset<32> last_active_chains_ = 0;
|
||||||
int64_t last_frame_id_ = 0;
|
int64_t last_frame_id_ = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -335,6 +335,10 @@ void RTPSenderVideo::AddRtpHeaderExtensions(
|
|||||||
descriptor.frame_dependencies.decode_target_indications.size(),
|
descriptor.frame_dependencies.decode_target_indications.size(),
|
||||||
video_structure_->num_decode_targets);
|
video_structure_->num_decode_targets);
|
||||||
|
|
||||||
|
if (first_packet) {
|
||||||
|
descriptor.active_decode_targets_bitmask =
|
||||||
|
active_decode_targets_tracker_.ActiveDecodeTargetsBitmask();
|
||||||
|
}
|
||||||
// To avoid extra structure copy, temporary share ownership of the
|
// To avoid extra structure copy, temporary share ownership of the
|
||||||
// video_structure with the dependency descriptor.
|
// video_structure with the dependency descriptor.
|
||||||
if (video_header.frame_type == VideoFrameType::kVideoFrameKey &&
|
if (video_header.frame_type == VideoFrameType::kVideoFrameKey &&
|
||||||
@ -343,7 +347,8 @@ void RTPSenderVideo::AddRtpHeaderExtensions(
|
|||||||
absl::WrapUnique(video_structure_.get());
|
absl::WrapUnique(video_structure_.get());
|
||||||
}
|
}
|
||||||
extension_is_set = packet->SetExtension<RtpDependencyDescriptorExtension>(
|
extension_is_set = packet->SetExtension<RtpDependencyDescriptorExtension>(
|
||||||
*video_structure_, descriptor);
|
*video_structure_,
|
||||||
|
active_decode_targets_tracker_.ActiveChainsBitmask(), descriptor);
|
||||||
|
|
||||||
// Remove the temporary shared ownership.
|
// Remove the temporary shared ownership.
|
||||||
descriptor.attached_structure.release();
|
descriptor.attached_structure.release();
|
||||||
@ -415,6 +420,14 @@ bool RTPSenderVideo::SendVideo(
|
|||||||
playout_delay_pending_ = true;
|
playout_delay_pending_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (video_structure_ != nullptr && video_header.generic) {
|
||||||
|
active_decode_targets_tracker_.OnFrame(
|
||||||
|
video_structure_->decode_target_protected_by_chain,
|
||||||
|
video_header.generic->active_decode_targets,
|
||||||
|
video_header.frame_type == VideoFrameType::kVideoFrameKey,
|
||||||
|
video_header.generic->frame_id, video_header.generic->chain_diffs);
|
||||||
|
}
|
||||||
|
|
||||||
// Maximum size of packet including rtp headers.
|
// Maximum size of packet including rtp headers.
|
||||||
// Extra space left in case packet will be resent using fec or rtx.
|
// Extra space left in case packet will be resent using fec or rtx.
|
||||||
int packet_capacity = rtp_sender_->MaxRtpPacketSize() - FecPacketOverhead() -
|
int packet_capacity = rtp_sender_->MaxRtpPacketSize() - FecPacketOverhead() -
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include "modules/include/module_common_types.h"
|
#include "modules/include/module_common_types.h"
|
||||||
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
|
||||||
#include "modules/rtp_rtcp/source/absolute_capture_time_sender.h"
|
#include "modules/rtp_rtcp/source/absolute_capture_time_sender.h"
|
||||||
|
#include "modules/rtp_rtcp/source/active_decode_targets_helper.h"
|
||||||
#include "modules/rtp_rtcp/source/rtp_rtcp_config.h"
|
#include "modules/rtp_rtcp/source/rtp_rtcp_config.h"
|
||||||
#include "modules/rtp_rtcp/source/rtp_sender.h"
|
#include "modules/rtp_rtcp/source/rtp_sender.h"
|
||||||
#include "modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.h"
|
#include "modules/rtp_rtcp/source/rtp_sender_video_frame_transformer_delegate.h"
|
||||||
@ -214,6 +215,9 @@ class RTPSenderVideo {
|
|||||||
const bool generic_descriptor_auth_experiment_;
|
const bool generic_descriptor_auth_experiment_;
|
||||||
|
|
||||||
AbsoluteCaptureTimeSender absolute_capture_time_sender_;
|
AbsoluteCaptureTimeSender absolute_capture_time_sender_;
|
||||||
|
// Tracks updates to the active decode targets and decides when active decode
|
||||||
|
// targets bitmask should be attached to the dependency descriptor.
|
||||||
|
ActiveDecodeTargetsHelper active_decode_targets_tracker_;
|
||||||
|
|
||||||
const rtc::scoped_refptr<RTPSenderVideoFrameTransformerDelegate>
|
const rtc::scoped_refptr<RTPSenderVideoFrameTransformerDelegate>
|
||||||
frame_transformer_delegate_;
|
frame_transformer_delegate_;
|
||||||
|
@ -593,6 +593,40 @@ TEST_P(RtpSenderVideoTest, PropagatesChainDiffsIntoDependencyDescriptor) {
|
|||||||
ContainerEq(generic.chain_diffs));
|
ContainerEq(generic.chain_diffs));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_P(RtpSenderVideoTest,
|
||||||
|
PropagatesActiveDecodeTargetsIntoDependencyDescriptor) {
|
||||||
|
const int64_t kFrameId = 100000;
|
||||||
|
uint8_t kFrame[100];
|
||||||
|
rtp_module_->RegisterRtpHeaderExtension(
|
||||||
|
RtpDependencyDescriptorExtension::kUri, kDependencyDescriptorId);
|
||||||
|
FrameDependencyStructure video_structure;
|
||||||
|
video_structure.num_decode_targets = 2;
|
||||||
|
video_structure.num_chains = 1;
|
||||||
|
video_structure.decode_target_protected_by_chain = {0, 0};
|
||||||
|
video_structure.templates = {
|
||||||
|
FrameDependencyTemplate().S(0).T(0).Dtis("SS").ChainDiffs({1}),
|
||||||
|
};
|
||||||
|
rtp_sender_video_.SetVideoStructure(&video_structure);
|
||||||
|
|
||||||
|
RTPVideoHeader hdr;
|
||||||
|
RTPVideoHeader::GenericDescriptorInfo& generic = hdr.generic.emplace();
|
||||||
|
generic.frame_id = kFrameId;
|
||||||
|
generic.decode_target_indications = {DecodeTargetIndication::kSwitch,
|
||||||
|
DecodeTargetIndication::kSwitch};
|
||||||
|
generic.active_decode_targets = 0b01;
|
||||||
|
generic.chain_diffs = {1};
|
||||||
|
hdr.frame_type = VideoFrameType::kVideoFrameKey;
|
||||||
|
rtp_sender_video_.SendVideo(kPayload, kType, kTimestamp, 0, kFrame, nullptr,
|
||||||
|
hdr, kDefaultExpectedRetransmissionTimeMs);
|
||||||
|
|
||||||
|
ASSERT_EQ(transport_.packets_sent(), 1);
|
||||||
|
DependencyDescriptor descriptor_key;
|
||||||
|
ASSERT_TRUE(transport_.last_sent_packet()
|
||||||
|
.GetExtension<RtpDependencyDescriptorExtension>(
|
||||||
|
nullptr, &descriptor_key));
|
||||||
|
EXPECT_EQ(descriptor_key.active_decode_targets_bitmask, 0b01u);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_P(RtpSenderVideoTest,
|
TEST_P(RtpSenderVideoTest,
|
||||||
SetDiffentVideoStructureAvoidsCollisionWithThePreviousStructure) {
|
SetDiffentVideoStructureAvoidsCollisionWithThePreviousStructure) {
|
||||||
const int64_t kFrameId = 100000;
|
const int64_t kFrameId = 100000;
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#ifndef MODULES_RTP_RTCP_SOURCE_RTP_VIDEO_HEADER_H_
|
#ifndef MODULES_RTP_RTCP_SOURCE_RTP_VIDEO_HEADER_H_
|
||||||
#define MODULES_RTP_RTCP_SOURCE_RTP_VIDEO_HEADER_H_
|
#define MODULES_RTP_RTCP_SOURCE_RTP_VIDEO_HEADER_H_
|
||||||
|
|
||||||
|
#include <bitset>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include "absl/container/inlined_vector.h"
|
#include "absl/container/inlined_vector.h"
|
||||||
@ -53,6 +54,7 @@ struct RTPVideoHeader {
|
|||||||
absl::InlinedVector<DecodeTargetIndication, 10> decode_target_indications;
|
absl::InlinedVector<DecodeTargetIndication, 10> decode_target_indications;
|
||||||
absl::InlinedVector<int64_t, 5> dependencies;
|
absl::InlinedVector<int64_t, 5> dependencies;
|
||||||
absl::InlinedVector<int, 4> chain_diffs;
|
absl::InlinedVector<int, 4> chain_diffs;
|
||||||
|
std::bitset<32> active_decode_targets = ~uint32_t{0};
|
||||||
};
|
};
|
||||||
|
|
||||||
RTPVideoHeader();
|
RTPVideoHeader();
|
||||||
|
Reference in New Issue
Block a user