/* * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.h" #include "api/array_view.h" #include "api/transport/rtp/dependency_descriptor.h" #include "common_video/generic_frame_descriptor/generic_frame_info.h" #include "test/gmock.h" namespace webrtc { namespace { using ::testing::Each; TEST(RtpDependencyDescriptorExtensionTest, Writer3BytesForPerfectTemplate) { uint8_t buffer[3]; FrameDependencyStructure structure; structure.num_decode_targets = 2; structure.num_chains = 2; structure.templates = { FrameDependencyTemplate().Dtis("SR").FrameDiffs({1}).ChainDiffs({2, 2})}; DependencyDescriptor descriptor; descriptor.frame_dependencies = structure.templates[0]; EXPECT_EQ(RtpDependencyDescriptorExtension::ValueSize(structure, descriptor), 3u); EXPECT_TRUE( RtpDependencyDescriptorExtension::Write(buffer, structure, descriptor)); } TEST(RtpDependencyDescriptorExtensionTest, WriteZeroInUnusedBits) { uint8_t buffer[32]; std::memset(buffer, 0xff, sizeof(buffer)); FrameDependencyStructure structure; structure.num_decode_targets = 2; structure.num_chains = 2; structure.templates = { FrameDependencyTemplate().Dtis("SR").FrameDiffs({1}).ChainDiffs({1, 1})}; DependencyDescriptor descriptor; descriptor.frame_dependencies = structure.templates[0]; descriptor.frame_dependencies.frame_diffs = {2}; // To test unused bytes are zeroed, need a buffer large enough. size_t value_size = RtpDependencyDescriptorExtension::ValueSize(structure, descriptor); ASSERT_LT(value_size, sizeof(buffer)); ASSERT_TRUE( RtpDependencyDescriptorExtension::Write(buffer, structure, descriptor)); const uint8_t* unused_bytes = buffer + value_size; size_t num_unused_bytes = buffer + sizeof(buffer) - unused_bytes; // Check remaining bytes are zeroed. EXPECT_THAT(rtc::MakeArrayView(unused_bytes, num_unused_bytes), Each(0)); } // In practice chain diff for inactive chain will grow uboundly because no // frames are produced for it, that shouldn't block writing the extension. TEST(RtpDependencyDescriptorExtensionTest, TemplateMatchingSkipsInactiveChains) { uint8_t buffer[3]; FrameDependencyStructure structure; structure.num_decode_targets = 2; structure.num_chains = 2; structure.templates = { FrameDependencyTemplate().Dtis("SR").ChainDiffs({2, 2})}; DependencyDescriptor descriptor; descriptor.frame_dependencies = structure.templates[0]; // Set only 1st chain as active. std::bitset<32> active_chains = 0b01; descriptor.frame_dependencies.chain_diffs[1] = 1000; // Expect perfect template match since the only difference is for an inactive // chain. Pefect template match consumes 3 bytes. EXPECT_EQ(RtpDependencyDescriptorExtension::ValueSize( structure, active_chains, descriptor), 3u); EXPECT_TRUE(RtpDependencyDescriptorExtension::Write( buffer, structure, active_chains, descriptor)); } TEST(RtpDependencyDescriptorExtensionTest, AcceptsInvalidChainDiffForInactiveChainWhenChainsAreCustom) { uint8_t buffer[256]; FrameDependencyStructure structure; structure.num_decode_targets = 2; structure.num_chains = 2; structure.templates = { FrameDependencyTemplate().Dtis("SR").ChainDiffs({2, 2})}; DependencyDescriptor descriptor; descriptor.frame_dependencies = structure.templates[0]; // Set only 1st chain as active. std::bitset<32> active_chains = 0b01; // Set chain_diff different to the template to make it custom. descriptor.frame_dependencies.chain_diffs[0] = 1; // Set chain diff for inactive chain beyound limit of 255 max chain diff. descriptor.frame_dependencies.chain_diffs[1] = 1000; // Because chains are custom, should use more than base 3 bytes. EXPECT_GT(RtpDependencyDescriptorExtension::ValueSize( structure, active_chains, descriptor), 3u); EXPECT_TRUE(RtpDependencyDescriptorExtension::Write( buffer, structure, active_chains, descriptor)); } TEST(RtpDependencyDescriptorExtensionTest, FailsToWriteInvalidDescriptor) { uint8_t buffer[256]; FrameDependencyStructure structure; structure.num_decode_targets = 2; structure.num_chains = 2; structure.templates = { FrameDependencyTemplate().T(0).Dtis("SR").ChainDiffs({2, 2})}; DependencyDescriptor descriptor; descriptor.frame_dependencies = structure.templates[0]; descriptor.frame_dependencies.temporal_id = 1; EXPECT_EQ( RtpDependencyDescriptorExtension::ValueSize(structure, 0b11, descriptor), 0u); EXPECT_FALSE(RtpDependencyDescriptorExtension::Write(buffer, structure, 0b11, descriptor)); } } // namespace } // namespace webrtc