Implement setMetadata for receiver encoded video frames

This change adds a new function to RTPFrameObject to allow setting the
RTPVideoHeader from VideoFrameMetadata.

The setMetadata function in TransformableVideoReceiverFrame disallows
changing anything other than frameID and dependencies.

Change-Id: I74e55ffbe1f426b660c2e243b20358c6a6cc2ffd
Bug: chromium:1464853
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/314963
Reviewed-by: Danil Chapovalov <danilchap@webrtc.org>
Commit-Queue: Palak Agarwal <agpalak@google.com>
Reviewed-by: Tony Herre <herre@google.com>
Cr-Commit-Position: refs/heads/main@{#40530}
This commit is contained in:
Palak Agarwal 2023-08-09 10:52:39 +02:00 committed by WebRTC LUCI CQ
parent 762f193ca4
commit 86162d94d5
5 changed files with 82 additions and 4 deletions

View File

@ -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",

View File

@ -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

View File

@ -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.

View File

@ -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<RtpFrameObject> ExtractFrame() && {

View File

@ -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<NiceMock<MockFrameTransformer>>();
SimulatedClock clock(1000);
auto delegate =
rtc::make_ref_counted<RtpVideoStreamReceiverFrameTransformerDelegate>(
&receiver, &clock, mock_frame_transformer, rtc::Thread::Current(),
1111);
rtc::scoped_refptr<TransformedFrameCallback> 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<uint32_t> csrcs = {234, 345, 456};
// Checks that the recieved RTPFrameObject has the new metadata.
EXPECT_CALL(receiver, ManageFrame)
.WillOnce([&](std::unique_ptr<RtpFrameObject> frame) {
const absl::optional<RTPVideoHeader::GenericDescriptorInfo>&
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<TransformableFrameInterface>
transformable_frame) {
ASSERT_THAT(transformable_frame, NotNull());
auto& video_frame = static_cast<TransformableVideoFrameInterface&>(
*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<int64_t>{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_;