Add RTPVideoHeader::GetAsMetadata().

In preparation of adding RTPVideoHeader::SetFromMetadata() method, the
VideoFrameMetadata construct-from-RTPVideoHeader is replaced by
RTPVideoHeader::GetAsMetadata(). This serves two purposes:
1. Having "GetAs" and "SetFrom" in the same file reduces the risk of
   these two methods getting out of sync as we expand its usage.
2. This is necessary to avoid a circular dependency that would
   otherwise be introduced by RTPVideoHeader::SetFromMetadata().

Bug: webrtc:14709
Change-Id: I127b3d15f9a8c6af210449a5a50d414c9ba79930
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/285080
Reviewed-by: Tony Herre <herre@google.com>
Reviewed-by: Harald Alvestrand <hta@webrtc.org>
Commit-Queue: Henrik Boström <hbos@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#38735}
This commit is contained in:
Henrik Boström
2022-11-25 14:46:40 +01:00
committed by WebRTC LUCI CQ
parent e862da376f
commit 158d5e3078
9 changed files with 123 additions and 47 deletions

View File

@ -333,7 +333,7 @@ rtc_source_set("video_frame_metadata") {
]
deps = [
"..:array_view",
"../../modules/rtp_rtcp:rtp_video_header",
"../../rtc_base/system:rtc_export",
"../transport/rtp:dependency_descriptor",
]
absl_deps = [

View File

@ -10,19 +10,69 @@
#include "api/video/video_frame_metadata.h"
#include "modules/rtp_rtcp/source/rtp_video_header.h"
namespace webrtc {
VideoFrameMetadata::VideoFrameMetadata(const RTPVideoHeader& header)
: width_(header.width), height_(header.height) {
if (header.generic) {
frame_id_ = header.generic->frame_id;
spatial_index_ = header.generic->spatial_index;
temporal_index_ = header.generic->temporal_index;
frame_dependencies_ = header.generic->dependencies;
decode_target_indications_ = header.generic->decode_target_indications;
}
VideoFrameMetadata::VideoFrameMetadata() = default;
uint16_t VideoFrameMetadata::GetWidth() const {
return width_;
}
void VideoFrameMetadata::SetWidth(uint16_t width) {
width_ = width;
}
uint16_t VideoFrameMetadata::GetHeight() const {
return height_;
}
void VideoFrameMetadata::SetHeight(uint16_t height) {
height_ = height;
}
absl::optional<int64_t> VideoFrameMetadata::GetFrameId() const {
return frame_id_;
}
void VideoFrameMetadata::SetFrameId(absl::optional<int64_t> frame_id) {
frame_id_ = frame_id;
}
int VideoFrameMetadata::GetSpatialIndex() const {
return spatial_index_;
}
void VideoFrameMetadata::SetSpatialIndex(int spatial_index) {
spatial_index_ = spatial_index;
}
int VideoFrameMetadata::GetTemporalIndex() const {
return temporal_index_;
}
void VideoFrameMetadata::SetTemporalIndex(int temporal_index) {
temporal_index_ = temporal_index;
}
rtc::ArrayView<const int64_t> VideoFrameMetadata::GetFrameDependencies() const {
return frame_dependencies_;
}
void VideoFrameMetadata::SetFrameDependencies(
rtc::ArrayView<const int64_t> frame_dependencies) {
frame_dependencies_.assign(frame_dependencies.begin(),
frame_dependencies.end());
}
rtc::ArrayView<const DecodeTargetIndication>
VideoFrameMetadata::GetDecodeTargetIndications() const {
return decode_target_indications_;
}
void VideoFrameMetadata::SetDecodeTargetIndications(
rtc::ArrayView<const DecodeTargetIndication> decode_target_indications) {
decode_target_indications_.assign(decode_target_indications.begin(),
decode_target_indications.end());
}
} // namespace webrtc

View File

@ -17,37 +17,44 @@
#include "absl/types/optional.h"
#include "api/array_view.h"
#include "api/transport/rtp/dependency_descriptor.h"
#include "rtc_base/system/rtc_export.h"
namespace webrtc {
struct RTPVideoHeader;
// A subset of metadata from the RTP video header, exposed in insertable streams
// API.
class VideoFrameMetadata {
class RTC_EXPORT VideoFrameMetadata {
public:
explicit VideoFrameMetadata(const RTPVideoHeader& header);
VideoFrameMetadata();
VideoFrameMetadata(const VideoFrameMetadata&) = default;
VideoFrameMetadata& operator=(const VideoFrameMetadata&) = default;
uint16_t GetWidth() const { return width_; }
uint16_t GetHeight() const { return height_; }
absl::optional<int64_t> GetFrameId() const { return frame_id_; }
int GetSpatialIndex() const { return spatial_index_; }
int GetTemporalIndex() const { return temporal_index_; }
uint16_t GetWidth() const;
void SetWidth(uint16_t width);
rtc::ArrayView<const int64_t> GetFrameDependencies() const {
return frame_dependencies_;
}
uint16_t GetHeight() const;
void SetHeight(uint16_t height);
absl::optional<int64_t> GetFrameId() const;
void SetFrameId(absl::optional<int64_t> frame_id);
int GetSpatialIndex() const;
void SetSpatialIndex(int spatial_index);
int GetTemporalIndex() const;
void SetTemporalIndex(int temporal_index);
rtc::ArrayView<const int64_t> GetFrameDependencies() const;
void SetFrameDependencies(rtc::ArrayView<const int64_t> frame_dependencies);
rtc::ArrayView<const DecodeTargetIndication> GetDecodeTargetIndications()
const {
return decode_target_indications_;
}
const;
void SetDecodeTargetIndications(
rtc::ArrayView<const DecodeTargetIndication> decode_target_indications);
private:
int16_t width_;
int16_t height_;
int16_t width_ = 0;
int16_t height_ = 0;
absl::optional<int64_t> frame_id_;
int spatial_index_ = 0;
int temporal_index_ = 0;

View File

@ -23,14 +23,14 @@ using ::testing::IsEmpty;
TEST(VideoFrameMetadata, GetWidthReturnsCorrectValue) {
RTPVideoHeader video_header;
video_header.width = 1280u;
VideoFrameMetadata metadata(video_header);
VideoFrameMetadata metadata = video_header.GetAsMetadata();
EXPECT_EQ(metadata.GetWidth(), video_header.width);
}
TEST(VideoFrameMetadata, GetHeightReturnsCorrectValue) {
RTPVideoHeader video_header;
video_header.height = 720u;
VideoFrameMetadata metadata(video_header);
VideoFrameMetadata metadata = video_header.GetAsMetadata();
EXPECT_EQ(metadata.GetHeight(), video_header.height);
}
@ -39,13 +39,13 @@ TEST(VideoFrameMetadata, GetFrameIdReturnsCorrectValue) {
RTPVideoHeader::GenericDescriptorInfo& generic =
video_header.generic.emplace();
generic.frame_id = 10;
VideoFrameMetadata metadata(video_header);
VideoFrameMetadata metadata = video_header.GetAsMetadata();
EXPECT_EQ(metadata.GetFrameId().value(), 10);
}
TEST(VideoFrameMetadata, HasNoFrameIdForHeaderWithoutGeneric) {
RTPVideoHeader video_header;
VideoFrameMetadata metadata(video_header);
VideoFrameMetadata metadata = video_header.GetAsMetadata();
ASSERT_FALSE(video_header.generic);
EXPECT_EQ(metadata.GetFrameId(), absl::nullopt);
}
@ -55,13 +55,13 @@ TEST(VideoFrameMetadata, GetSpatialIndexReturnsCorrectValue) {
RTPVideoHeader::GenericDescriptorInfo& generic =
video_header.generic.emplace();
generic.spatial_index = 2;
VideoFrameMetadata metadata(video_header);
VideoFrameMetadata metadata = video_header.GetAsMetadata();
EXPECT_EQ(metadata.GetSpatialIndex(), 2);
}
TEST(VideoFrameMetadata, SpatialIndexIsZeroForHeaderWithoutGeneric) {
RTPVideoHeader video_header;
VideoFrameMetadata metadata(video_header);
VideoFrameMetadata metadata = video_header.GetAsMetadata();
ASSERT_FALSE(video_header.generic);
EXPECT_EQ(metadata.GetSpatialIndex(), 0);
}
@ -71,13 +71,13 @@ TEST(VideoFrameMetadata, GetTemporalIndexReturnsCorrectValue) {
RTPVideoHeader::GenericDescriptorInfo& generic =
video_header.generic.emplace();
generic.temporal_index = 3;
VideoFrameMetadata metadata(video_header);
VideoFrameMetadata metadata = video_header.GetAsMetadata();
EXPECT_EQ(metadata.GetTemporalIndex(), 3);
}
TEST(VideoFrameMetadata, TemporalIndexIsZeroForHeaderWithoutGeneric) {
RTPVideoHeader video_header;
VideoFrameMetadata metadata(video_header);
VideoFrameMetadata metadata = video_header.GetAsMetadata();
ASSERT_FALSE(video_header.generic);
EXPECT_EQ(metadata.GetTemporalIndex(), 0);
}
@ -87,13 +87,13 @@ TEST(VideoFrameMetadata, GetFrameDependenciesReturnsCorrectValue) {
RTPVideoHeader::GenericDescriptorInfo& generic =
video_header.generic.emplace();
generic.dependencies = {5, 6, 7};
VideoFrameMetadata metadata(video_header);
VideoFrameMetadata metadata = video_header.GetAsMetadata();
EXPECT_THAT(metadata.GetFrameDependencies(), ElementsAre(5, 6, 7));
}
TEST(VideoFrameMetadata, FrameDependencyVectorIsEmptyForHeaderWithoutGeneric) {
RTPVideoHeader video_header;
VideoFrameMetadata metadata(video_header);
VideoFrameMetadata metadata = video_header.GetAsMetadata();
ASSERT_FALSE(video_header.generic);
EXPECT_THAT(metadata.GetFrameDependencies(), IsEmpty());
}
@ -103,7 +103,7 @@ TEST(VideoFrameMetadata, GetDecodeTargetIndicationsReturnsCorrectValue) {
RTPVideoHeader::GenericDescriptorInfo& generic =
video_header.generic.emplace();
generic.decode_target_indications = {DecodeTargetIndication::kSwitch};
VideoFrameMetadata metadata(video_header);
VideoFrameMetadata metadata = video_header.GetAsMetadata();
EXPECT_THAT(metadata.GetDecodeTargetIndications(),
ElementsAre(DecodeTargetIndication::kSwitch));
}
@ -111,7 +111,7 @@ TEST(VideoFrameMetadata, GetDecodeTargetIndicationsReturnsCorrectValue) {
TEST(VideoFrameMetadata,
DecodeTargetIndicationsVectorIsEmptyForHeaderWithoutGeneric) {
RTPVideoHeader video_header;
VideoFrameMetadata metadata(video_header);
VideoFrameMetadata metadata = video_header.GetAsMetadata();
ASSERT_FALSE(video_header.generic);
EXPECT_THAT(metadata.GetDecodeTargetIndications(), IsEmpty());
}

View File

@ -425,6 +425,7 @@ rtc_library("rtp_video_header") {
"../../api:rtp_headers",
"../../api/transport/rtp:dependency_descriptor",
"../../api/video:video_frame",
"../../api/video:video_frame_metadata",
"../../api/video:video_frame_type",
"../../api/video:video_rtp_headers",
"../../modules/video_coding:codec_globals_headers",

View File

@ -35,7 +35,7 @@ class TransformableVideoSenderFrame : public TransformableVideoFrameInterface {
uint32_t ssrc)
: encoded_data_(encoded_image.GetEncodedData()),
header_(video_header),
metadata_(header_),
metadata_(header_.GetAsMetadata()),
frame_type_(encoded_image._frameType),
payload_type_(payload_type),
codec_type_(codec_type),

View File

@ -12,13 +12,27 @@
namespace webrtc {
RTPVideoHeader::RTPVideoHeader() : video_timing() {}
RTPVideoHeader::RTPVideoHeader(const RTPVideoHeader& other) = default;
RTPVideoHeader::~RTPVideoHeader() = default;
RTPVideoHeader::GenericDescriptorInfo::GenericDescriptorInfo() = default;
RTPVideoHeader::GenericDescriptorInfo::GenericDescriptorInfo(
const GenericDescriptorInfo& other) = default;
RTPVideoHeader::GenericDescriptorInfo::~GenericDescriptorInfo() = default;
RTPVideoHeader::RTPVideoHeader() : video_timing() {}
RTPVideoHeader::RTPVideoHeader(const RTPVideoHeader& other) = default;
RTPVideoHeader::~RTPVideoHeader() = default;
VideoFrameMetadata RTPVideoHeader::GetAsMetadata() const {
VideoFrameMetadata metadata;
metadata.SetWidth(width);
metadata.SetHeight(height);
if (generic) {
metadata.SetFrameId(generic->frame_id);
metadata.SetSpatialIndex(generic->spatial_index);
metadata.SetTemporalIndex(generic->temporal_index);
metadata.SetFrameDependencies(generic->dependencies);
metadata.SetDecodeTargetIndications(generic->decode_target_indications);
}
return metadata;
}
} // namespace webrtc

View File

@ -21,6 +21,7 @@
#include "api/video/color_space.h"
#include "api/video/video_codec_type.h"
#include "api/video/video_content_type.h"
#include "api/video/video_frame_metadata.h"
#include "api/video/video_frame_type.h"
#include "api/video/video_rotation.h"
#include "api/video/video_timing.h"
@ -62,6 +63,9 @@ struct RTPVideoHeader {
~RTPVideoHeader();
// The subset of RTPVideoHeader that is exposed in the Insertable Streams API.
VideoFrameMetadata GetAsMetadata() const;
absl::optional<GenericDescriptorInfo> generic;
VideoFrameType frame_type = VideoFrameType::kEmptyFrame;

View File

@ -26,7 +26,7 @@ class TransformableVideoReceiverFrame
TransformableVideoReceiverFrame(std::unique_ptr<RtpFrameObject> frame,
uint32_t ssrc)
: frame_(std::move(frame)),
metadata_(frame_->GetRtpVideoHeader()),
metadata_(frame_->GetRtpVideoHeader().GetAsMetadata()),
ssrc_(ssrc) {}
~TransformableVideoReceiverFrame() override = default;