diff --git a/modules/rtp_rtcp/BUILD.gn b/modules/rtp_rtcp/BUILD.gn index 4cb4396553..0fc9931f39 100644 --- a/modules/rtp_rtcp/BUILD.gn +++ b/modules/rtp_rtcp/BUILD.gn @@ -297,6 +297,7 @@ rtc_library("rtp_rtcp") { "../../api/video:video_bitrate_allocator", "../../api/video:video_codec_constants", "../../api/video:video_frame", + "../../api/video:video_frame_metadata", "../../api/video:video_frame_type", "../../api/video:video_layers_allocation", "../../api/video:video_rtp_headers", diff --git a/modules/rtp_rtcp/source/frame_object.cc b/modules/rtp_rtcp/source/frame_object.cc index cd056d527c..734f1b0a4f 100644 --- a/modules/rtp_rtcp/source/frame_object.cc +++ b/modules/rtp_rtcp/source/frame_object.cc @@ -131,4 +131,7 @@ const RTPVideoHeader& RtpFrameObject::GetRtpVideoHeader() const { return rtp_video_header_; } +void RtpFrameObject::SetHeaderFromMetadata(const VideoFrameMetadata& metadata) { + rtp_video_header_.SetFromMetadata(metadata); +} } // namespace webrtc diff --git a/modules/rtp_rtcp/source/frame_object.h b/modules/rtp_rtcp/source/frame_object.h index 2cbb932765..481c561795 100644 --- a/modules/rtp_rtcp/source/frame_object.h +++ b/modules/rtp_rtcp/source/frame_object.h @@ -15,6 +15,7 @@ #include "absl/types/optional.h" #include "api/video/encoded_frame.h" +#include "api/video/video_frame_metadata.h" namespace webrtc { @@ -57,6 +58,7 @@ class RtpFrameObject : public EncodedFrame { first_seq_num_ = first_seq_num; } void SetLastSeqNum(uint16_t last_seq_num) { last_seq_num_ = last_seq_num; } + void SetHeaderFromMetadata(const VideoFrameMetadata& metadata); private: // Reference for mutable access. diff --git a/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate.cc b/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate.cc index 5db5664147..4913445860 100644 --- a/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate.cc +++ b/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate.cc @@ -46,7 +46,7 @@ class TransformableVideoReceiverFrame } uint8_t GetPayloadType() const override { return frame_->PayloadType(); } - uint32_t GetSsrc() const override { return metadata_.GetSsrc(); } + uint32_t GetSsrc() const override { return Metadata().GetSsrc(); } uint32_t GetTimestamp() const override { return frame_->Timestamp(); } void SetRTPTimestamp(uint32_t timestamp) override { frame_->SetTimestamp(timestamp); @@ -58,9 +58,16 @@ class TransformableVideoReceiverFrame VideoFrameMetadata Metadata() const override { return metadata_; } - void SetMetadata(const VideoFrameMetadata&) override { - RTC_DCHECK_NOTREACHED() - << "TransformableVideoReceiverFrame::SetMetadata is not implemented"; + void SetMetadata(const VideoFrameMetadata& metadata) override { + // Create |new_metadata| from existing metadata and change only frameId and + // dependencies. + VideoFrameMetadata new_metadata = Metadata(); + new_metadata.SetFrameId(metadata.GetFrameId()); + new_metadata.SetFrameDependencies(metadata.GetFrameDependencies()); + RTC_DCHECK(new_metadata == metadata) + << "TransformableVideoReceiverFrame::SetMetadata can be only used to " + "change frameID and dependencies"; + frame_->SetHeaderFromMetadata(new_metadata); } std::unique_ptr ExtractFrame() && { diff --git a/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate_unittest.cc b/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate_unittest.cc index 5c72412404..bbc1b62b5e 100644 --- a/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_video_stream_receiver_frame_transformer_delegate_unittest.cc @@ -32,6 +32,7 @@ namespace { using ::testing::_; using ::testing::ElementsAre; using ::testing::NiceMock; +using ::testing::NotNull; using ::testing::Return; using ::testing::SaveArg; @@ -191,6 +192,70 @@ TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest, delegate->TransformFrame(CreateRtpFrameObject(video_header, csrcs)); } +TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest, + TransformableFrameMetadataHasCorrectValueAfterSetMetadata) { + rtc::AutoThread main_thread; + TestRtpVideoFrameReceiver receiver; + auto mock_frame_transformer = + rtc::make_ref_counted>(); + SimulatedClock clock(1000); + auto delegate = + rtc::make_ref_counted( + &receiver, &clock, mock_frame_transformer, rtc::Thread::Current(), + 1111); + + rtc::scoped_refptr callback; + EXPECT_CALL(*mock_frame_transformer, RegisterTransformedFrameSinkCallback) + .WillOnce(SaveArg<0>(&callback)); + delegate->Init(); + ASSERT_TRUE(callback); + + RTPVideoHeader video_header; + RTPVideoHeader::GenericDescriptorInfo& generic = + video_header.generic.emplace(); + generic.frame_id = 10; + generic.dependencies = {5}; + + std::vector csrcs = {234, 345, 456}; + + // Checks that the recieved RTPFrameObject has the new metadata. + EXPECT_CALL(receiver, ManageFrame) + .WillOnce([&](std::unique_ptr frame) { + const absl::optional& + descriptor = frame->GetRtpVideoHeader().generic; + if (!descriptor.has_value()) { + ADD_FAILURE() << "GenericDescriptorInfo in RTPVideoHeader doesn't " + "have a value."; + } else { + EXPECT_EQ(descriptor->frame_id, 20); + EXPECT_THAT(descriptor->dependencies, ElementsAre(15)); + } + EXPECT_EQ(frame->Csrcs(), csrcs); + }); + + // Sets new metadata to the transformable frame. + ON_CALL(*mock_frame_transformer, Transform) + .WillByDefault([&](std::unique_ptr + transformable_frame) { + ASSERT_THAT(transformable_frame, NotNull()); + auto& video_frame = static_cast( + *transformable_frame); + VideoFrameMetadata metadata = video_frame.Metadata(); + EXPECT_EQ(metadata.GetFrameId(), 10); + EXPECT_THAT(metadata.GetFrameDependencies(), ElementsAre(5)); + EXPECT_EQ(metadata.GetCsrcs(), csrcs); + + metadata.SetFrameId(20); + metadata.SetFrameDependencies(std::vector{15}); + video_frame.SetMetadata(metadata); + callback->OnTransformedFrame(std::move(transformable_frame)); + }); + + // The delegate creates a transformable frame from the RtpFrameObject. + delegate->TransformFrame(CreateRtpFrameObject(video_header, csrcs)); + rtc::ThreadManager::ProcessAllMessageQueuesForTesting(); +} + TEST(RtpVideoStreamReceiverFrameTransformerDelegateTest, SenderFramesAreConvertedToReceiverFrames) { rtc::AutoThread main_thread_;