In DependencyDescriptor rtp header extension drop partial chain support

i.e. when chain are used,
require each decode target to be protected by some chain.
where previously it was allowed to mark decode target as unprotected.

See https://github.com/AOMediaCodec/av1-rtp-spec/pull/125

Bug: webrtc:10342
Change-Id: Ia2800036e890db44bb1162abfa1a497ff68f3b24
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/178807
Reviewed-by: Philip Eliasson <philipel@webrtc.org>
Reviewed-by: Björn Terelius <terelius@webrtc.org>
Commit-Queue: Danil Chapovalov <danilchap@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#31772}
This commit is contained in:
Danil Chapovalov
2020-07-14 18:00:17 +02:00
committed by Commit Bot
parent 0bc68bd164
commit a5d9c1a45c
7 changed files with 17 additions and 46 deletions

View File

@ -91,8 +91,7 @@ struct FrameDependencyStructure {
int num_decode_targets = 0; int num_decode_targets = 0;
int num_chains = 0; int num_chains = 0;
// If chains are used (num_chains > 0), maps decode target index into index of // If chains are used (num_chains > 0), maps decode target index into index of
// the chain protecting that target or |num_chains| value if decode target is // the chain protecting that target.
// not protected by a chain.
absl::InlinedVector<int, 10> decode_target_protected_by_chain; absl::InlinedVector<int, 10> decode_target_protected_by_chain;
absl::InlinedVector<RenderResolution, 4> resolutions; absl::InlinedVector<RenderResolution, 4> resolutions;
std::vector<FrameDependencyTemplate> templates; std::vector<FrameDependencyTemplate> templates;

View File

@ -50,13 +50,10 @@ std::bitset<32> ActiveChains(
if (dt < active_decode_targets.size() && !active_decode_targets[dt]) { if (dt < active_decode_targets.size() && !active_decode_targets[dt]) {
continue; continue;
} }
// chain_idx == num_chains is valid and means the decode target is
// not protected by any chain.
int chain_idx = decode_target_protected_by_chain[dt]; int chain_idx = decode_target_protected_by_chain[dt];
if (chain_idx < num_chains) { RTC_DCHECK_LT(chain_idx, num_chains);
active_chains.set(chain_idx); active_chains.set(chain_idx);
} }
}
return active_chains; return active_chains;
} }
@ -109,20 +106,19 @@ void ActiveDecodeTargetsHelper::OnFrame(
return; return;
} }
last_active_decode_targets_ = active_decode_targets; last_active_decode_targets_ = active_decode_targets;
if (active_decode_targets.none()) {
RTC_LOG(LS_ERROR) << "It is invalid to produce a frame (" << frame_id
<< ") while there are no active decode targets";
return;
}
last_active_chains_ = ActiveChains(decode_target_protected_by_chain, last_active_chains_ = ActiveChains(decode_target_protected_by_chain,
num_chains, active_decode_targets); 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_ = last_active_chains_; unsent_on_chain_ = last_active_chains_;
if (unsent_on_chain_.none()) { RTC_DCHECK(!unsent_on_chain_.none());
// 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.
RTC_LOG(LS_WARNING)
<< "Active decode targets protected by no chains. (In)active decode "
"targets information will be send overreliably.";
unsent_on_chain_.set(1);
}
} }
} // namespace webrtc } // namespace webrtc

View File

@ -241,29 +241,6 @@ TEST(ActiveDecodeTargetsHelperTest, ReturnsNulloptWhenChainsAreNotUsed) {
EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), absl::nullopt); EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), absl::nullopt);
} }
TEST(ActiveDecodeTargetsHelperTest,
KeepReturningBitmaskWhenAllChainsAreInactive) {
// Two decode targets, but single chain.
// 2nd decode target is not protected by any chain.
constexpr int kDecodeTargetProtectedByChain[] = {0, 1};
ActiveDecodeTargetsHelper helper;
int chain_diffs_key[] = {0};
helper.OnFrame(kDecodeTargetProtectedByChain, /*active_decode_targets=*/0b10,
/*is_keyframe=*/true,
/*frame_id=*/0, chain_diffs_key);
EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), 0b10u);
// Even though previous frame is part of the only chain, that inactive chain
// doesn't provide guaranted delivery.
int chain_diffs_delta[] = {1};
helper.OnFrame(kDecodeTargetProtectedByChain,
/*active_decode_targets=*/0b10,
/*is_keyframe=*/false,
/*frame_id=*/1, chain_diffs_delta);
EXPECT_EQ(helper.ActiveDecodeTargetsBitmask(), 0b10u);
}
TEST(ActiveDecodeTargetsHelperTest, Supports32DecodeTargets) { TEST(ActiveDecodeTargetsHelperTest, Supports32DecodeTargets) {
std::bitset<32> some; std::bitset<32> some;
std::vector<int> decode_target_protected_by_chain(32); std::vector<int> decode_target_protected_by_chain(32);

View File

@ -146,7 +146,7 @@ void RtpDependencyDescriptorReader::ReadTemplateChains() {
if (structure->num_chains == 0) if (structure->num_chains == 0)
return; return;
for (int i = 0; i < structure->num_decode_targets; ++i) { for (int i = 0; i < structure->num_decode_targets; ++i) {
uint32_t protected_by_chain = ReadNonSymmetric(structure->num_chains + 1); uint32_t protected_by_chain = ReadNonSymmetric(structure->num_chains);
structure->decode_target_protected_by_chain.push_back(protected_by_chain); structure->decode_target_protected_by_chain.push_back(protected_by_chain);
} }
for (FrameDependencyTemplate& frame_template : structure->templates) { for (FrameDependencyTemplate& frame_template : structure->templates) {

View File

@ -111,8 +111,8 @@ int RtpDependencyDescriptorWriter::StructureSizeBits() const {
structure_.num_chains, structure_.num_decode_targets + 1); structure_.num_chains, structure_.num_decode_targets + 1);
if (structure_.num_chains > 0) { if (structure_.num_chains > 0) {
for (int protected_by : structure_.decode_target_protected_by_chain) { for (int protected_by : structure_.decode_target_protected_by_chain) {
bits += rtc::BitBufferWriter::SizeNonSymmetricBits( bits += rtc::BitBufferWriter::SizeNonSymmetricBits(protected_by,
protected_by, structure_.num_chains + 1); structure_.num_chains);
} }
bits += 4 * structure_.templates.size() * structure_.num_chains; bits += 4 * structure_.templates.size() * structure_.num_chains;
} }
@ -288,8 +288,8 @@ void RtpDependencyDescriptorWriter::WriteTemplateChains() {
structure_.num_decode_targets); structure_.num_decode_targets);
for (int protected_by : structure_.decode_target_protected_by_chain) { for (int protected_by : structure_.decode_target_protected_by_chain) {
RTC_DCHECK_GE(protected_by, 0); RTC_DCHECK_GE(protected_by, 0);
RTC_DCHECK_LE(protected_by, structure_.num_chains); RTC_DCHECK_LT(protected_by, structure_.num_chains);
WriteNonSymmetric(protected_by, structure_.num_chains + 1); WriteNonSymmetric(protected_by, structure_.num_chains);
} }
for (const auto& frame_template : structure_.templates) { for (const auto& frame_template : structure_.templates) {
RTC_DCHECK_EQ(frame_template.chain_diffs.size(), structure_.num_chains); RTC_DCHECK_EQ(frame_template.chain_diffs.size(), structure_.num_chains);

View File

@ -567,8 +567,7 @@ TEST_P(RtpSenderVideoTest, PropagatesChainDiffsIntoDependencyDescriptor) {
FrameDependencyStructure video_structure; FrameDependencyStructure video_structure;
video_structure.num_decode_targets = 2; video_structure.num_decode_targets = 2;
video_structure.num_chains = 1; video_structure.num_chains = 1;
// First decode target is protected by the only chain, second one - is not. video_structure.decode_target_protected_by_chain = {0, 0};
video_structure.decode_target_protected_by_chain = {0, 1};
video_structure.templates = { video_structure.templates = {
FrameDependencyTemplate().S(0).T(0).Dtis("SS").ChainDiffs({1}), FrameDependencyTemplate().S(0).T(0).Dtis("SS").ChainDiffs({1}),
}; };

View File

@ -104,7 +104,7 @@ TEST_P(ScalabilityStructureTest,
} else { } else {
EXPECT_THAT(structure.decode_target_protected_by_chain, EXPECT_THAT(structure.decode_target_protected_by_chain,
AllOf(SizeIs(structure.num_decode_targets), Each(Ge(0)), AllOf(SizeIs(structure.num_decode_targets), Each(Ge(0)),
Each(Le(structure.num_chains)))); Each(Lt(structure.num_chains))));
} }
EXPECT_THAT(structure.templates, EXPECT_THAT(structure.templates,
SizeIs(Lt(size_t{DependencyDescriptor::kMaxTemplates}))); SizeIs(Lt(size_t{DependencyDescriptor::kMaxTemplates})));