diff --git a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.cc b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.cc index 1b931327ba..0d1b9d157c 100644 --- a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.cc +++ b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.cc @@ -56,6 +56,16 @@ void RtpGenericFrameDescriptor::SetSpatialLayersBitmask( spatial_layers_ = spatial_layers; } +void RtpGenericFrameDescriptor::SetResolution(int width, int height) { + RTC_DCHECK(FirstPacketInSubFrame()); + RTC_DCHECK_GE(width, 0); + RTC_DCHECK_LE(width, 0xFFFF); + RTC_DCHECK_GE(height, 0); + RTC_DCHECK_LE(height, 0xFFFF); + width_ = width; + height_ = height; +} + uint16_t RtpGenericFrameDescriptor::FrameId() const { RTC_DCHECK(FirstPacketInSubFrame()); return frame_id_; diff --git a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h index 1bde4fa56d..3a6c34d59f 100644 --- a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h +++ b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor.h @@ -50,6 +50,10 @@ class RtpGenericFrameDescriptor { uint8_t SpatialLayersBitmask() const; void SetSpatialLayersBitmask(uint8_t spatial_layers); + int Width() const { return width_; } + int Height() const { return height_; } + void SetResolution(int width, int height); + uint16_t FrameId() const; void SetFrameId(uint16_t frame_id); @@ -72,6 +76,9 @@ class RtpGenericFrameDescriptor { uint8_t temporal_layer_ = 0; size_t num_frame_deps_ = 0; uint16_t frame_deps_id_diffs_[kMaxNumFrameDependencies]; + int width_ = 0; + int height_ = 0; + std::vector byte_representation_; }; diff --git a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.cc b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.cc index c7b52d5ba6..7cd120d9f4 100644 --- a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.cc +++ b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.cc @@ -36,6 +36,14 @@ constexpr uint8_t kFlageXtendedOffset = 0x02; // B: + FID + // | | // +-+-+-+-+-+-+-+-+ +// | | +// + Width + +// B=1 | | +// and +-+-+-+-+-+-+-+-+ +// D=0 | | +// + Height + +// | | +// +-+-+-+-+-+-+-+-+ // D: | FDIFF |X|M| // +---------------+ // X: | ... | @@ -75,6 +83,12 @@ bool RtpGenericFrameDescriptorExtension::Parse( descriptor->ClearFrameDependencies(); size_t offset = 4; bool has_more_dependencies = (data[0] & kFlagDependencies) != 0; + if (!has_more_dependencies && data.size() >= offset + 4) { + uint16_t width = (data[offset] << 8) | data[offset + 1]; + uint16_t height = (data[offset + 2] << 8) | data[offset + 3]; + descriptor->SetResolution(width, height); + offset += 4; + } while (has_more_dependencies) { if (data.size() == offset) return false; @@ -91,7 +105,7 @@ bool RtpGenericFrameDescriptorExtension::Parse( if (!descriptor->AddFrameDependencyDiff(fdiff)) return false; } - return data.size() == offset; + return true; } size_t RtpGenericFrameDescriptorExtension::ValueSize( @@ -103,6 +117,11 @@ size_t RtpGenericFrameDescriptorExtension::ValueSize( for (uint16_t fdiff : descriptor.FrameDependenciesDiffs()) { size += (fdiff >= (1 << 6)) ? 2 : 1; } + if (descriptor.FirstPacketInSubFrame() && + descriptor.FrameDependenciesDiffs().empty() && descriptor.Width() > 0 && + descriptor.Height() > 0) { + size += 4; + } return size; } @@ -129,6 +148,13 @@ bool RtpGenericFrameDescriptorExtension::Write( data[3] = frame_id >> 8; rtc::ArrayView fdiffs = descriptor.FrameDependenciesDiffs(); size_t offset = 4; + if (descriptor.FirstPacketInSubFrame() && fdiffs.empty() && + descriptor.Width() > 0 && descriptor.Height() > 0) { + data[offset++] = (descriptor.Width() >> 8); + data[offset++] = (descriptor.Width() & 0xFF); + data[offset++] = (descriptor.Height() >> 8); + data[offset++] = (descriptor.Height() & 0xFF); + } for (size_t i = 0; i < fdiffs.size(); i++) { bool extended = fdiffs[i] >= (1 << 6); bool more = i < fdiffs.size() - 1; diff --git a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension_unittest.cc b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension_unittest.cc index bb69e1455d..7f8fa2f5a4 100644 --- a/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension_unittest.cc @@ -279,5 +279,32 @@ TEST(RtpGenericFrameDescriptorExtensionTest, WriteTwoFrameDependencies) { EXPECT_THAT(buffer, ElementsAreArray(kRaw)); } +TEST(RtpGenericFrameDescriptorExtensionTest, + ParseResolutionOnIndependentFrame) { + constexpr int kWidth = 0x2468; + constexpr int kHeight = 0x6543; + constexpr uint8_t kRaw[] = {0x80, 0x01, 0x00, 0x00, 0x24, 0x68, 0x65, 0x43}; + RtpGenericFrameDescriptor descriptor; + + ASSERT_TRUE(RtpGenericFrameDescriptorExtension::Parse(kRaw, &descriptor)); + EXPECT_EQ(descriptor.Width(), kWidth); + EXPECT_EQ(descriptor.Height(), kHeight); +} + +TEST(RtpGenericFrameDescriptorExtensionTest, + WriteResolutionOnIndependentFrame) { + constexpr int kWidth = 0x2468; + constexpr int kHeight = 0x6543; + constexpr uint8_t kRaw[] = {0x80, 0x01, 0x00, 0x00, 0x24, 0x68, 0x65, 0x43}; + RtpGenericFrameDescriptor descriptor; + descriptor.SetFirstPacketInSubFrame(true); + descriptor.SetResolution(kWidth, kHeight); + + ASSERT_EQ(RtpGenericFrameDescriptorExtension::ValueSize(descriptor), + sizeof(kRaw)); + uint8_t buffer[sizeof(kRaw)]; + EXPECT_TRUE(RtpGenericFrameDescriptorExtension::Write(buffer, descriptor)); + EXPECT_THAT(buffer, ElementsAreArray(kRaw)); +} } // namespace } // namespace webrtc