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:
parent
e862da376f
commit
158d5e3078
@ -333,7 +333,7 @@ rtc_source_set("video_frame_metadata") {
|
|||||||
]
|
]
|
||||||
deps = [
|
deps = [
|
||||||
"..:array_view",
|
"..:array_view",
|
||||||
"../../modules/rtp_rtcp:rtp_video_header",
|
"../../rtc_base/system:rtc_export",
|
||||||
"../transport/rtp:dependency_descriptor",
|
"../transport/rtp:dependency_descriptor",
|
||||||
]
|
]
|
||||||
absl_deps = [
|
absl_deps = [
|
||||||
|
|||||||
@ -10,19 +10,69 @@
|
|||||||
|
|
||||||
#include "api/video/video_frame_metadata.h"
|
#include "api/video/video_frame_metadata.h"
|
||||||
|
|
||||||
#include "modules/rtp_rtcp/source/rtp_video_header.h"
|
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
VideoFrameMetadata::VideoFrameMetadata(const RTPVideoHeader& header)
|
VideoFrameMetadata::VideoFrameMetadata() = default;
|
||||||
: width_(header.width), height_(header.height) {
|
|
||||||
if (header.generic) {
|
uint16_t VideoFrameMetadata::GetWidth() const {
|
||||||
frame_id_ = header.generic->frame_id;
|
return width_;
|
||||||
spatial_index_ = header.generic->spatial_index;
|
}
|
||||||
temporal_index_ = header.generic->temporal_index;
|
|
||||||
frame_dependencies_ = header.generic->dependencies;
|
void VideoFrameMetadata::SetWidth(uint16_t width) {
|
||||||
decode_target_indications_ = header.generic->decode_target_indications;
|
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
|
} // namespace webrtc
|
||||||
|
|||||||
@ -17,37 +17,44 @@
|
|||||||
#include "absl/types/optional.h"
|
#include "absl/types/optional.h"
|
||||||
#include "api/array_view.h"
|
#include "api/array_view.h"
|
||||||
#include "api/transport/rtp/dependency_descriptor.h"
|
#include "api/transport/rtp/dependency_descriptor.h"
|
||||||
|
#include "rtc_base/system/rtc_export.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
struct RTPVideoHeader;
|
|
||||||
|
|
||||||
// A subset of metadata from the RTP video header, exposed in insertable streams
|
// A subset of metadata from the RTP video header, exposed in insertable streams
|
||||||
// API.
|
// API.
|
||||||
class VideoFrameMetadata {
|
class RTC_EXPORT VideoFrameMetadata {
|
||||||
public:
|
public:
|
||||||
explicit VideoFrameMetadata(const RTPVideoHeader& header);
|
VideoFrameMetadata();
|
||||||
VideoFrameMetadata(const VideoFrameMetadata&) = default;
|
VideoFrameMetadata(const VideoFrameMetadata&) = default;
|
||||||
VideoFrameMetadata& operator=(const VideoFrameMetadata&) = default;
|
VideoFrameMetadata& operator=(const VideoFrameMetadata&) = default;
|
||||||
|
|
||||||
uint16_t GetWidth() const { return width_; }
|
uint16_t GetWidth() const;
|
||||||
uint16_t GetHeight() const { return height_; }
|
void SetWidth(uint16_t width);
|
||||||
absl::optional<int64_t> GetFrameId() const { return frame_id_; }
|
|
||||||
int GetSpatialIndex() const { return spatial_index_; }
|
|
||||||
int GetTemporalIndex() const { return temporal_index_; }
|
|
||||||
|
|
||||||
rtc::ArrayView<const int64_t> GetFrameDependencies() const {
|
uint16_t GetHeight() const;
|
||||||
return frame_dependencies_;
|
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()
|
rtc::ArrayView<const DecodeTargetIndication> GetDecodeTargetIndications()
|
||||||
const {
|
const;
|
||||||
return decode_target_indications_;
|
void SetDecodeTargetIndications(
|
||||||
}
|
rtc::ArrayView<const DecodeTargetIndication> decode_target_indications);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int16_t width_;
|
int16_t width_ = 0;
|
||||||
int16_t height_;
|
int16_t height_ = 0;
|
||||||
absl::optional<int64_t> frame_id_;
|
absl::optional<int64_t> frame_id_;
|
||||||
int spatial_index_ = 0;
|
int spatial_index_ = 0;
|
||||||
int temporal_index_ = 0;
|
int temporal_index_ = 0;
|
||||||
|
|||||||
@ -23,14 +23,14 @@ using ::testing::IsEmpty;
|
|||||||
TEST(VideoFrameMetadata, GetWidthReturnsCorrectValue) {
|
TEST(VideoFrameMetadata, GetWidthReturnsCorrectValue) {
|
||||||
RTPVideoHeader video_header;
|
RTPVideoHeader video_header;
|
||||||
video_header.width = 1280u;
|
video_header.width = 1280u;
|
||||||
VideoFrameMetadata metadata(video_header);
|
VideoFrameMetadata metadata = video_header.GetAsMetadata();
|
||||||
EXPECT_EQ(metadata.GetWidth(), video_header.width);
|
EXPECT_EQ(metadata.GetWidth(), video_header.width);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(VideoFrameMetadata, GetHeightReturnsCorrectValue) {
|
TEST(VideoFrameMetadata, GetHeightReturnsCorrectValue) {
|
||||||
RTPVideoHeader video_header;
|
RTPVideoHeader video_header;
|
||||||
video_header.height = 720u;
|
video_header.height = 720u;
|
||||||
VideoFrameMetadata metadata(video_header);
|
VideoFrameMetadata metadata = video_header.GetAsMetadata();
|
||||||
EXPECT_EQ(metadata.GetHeight(), video_header.height);
|
EXPECT_EQ(metadata.GetHeight(), video_header.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,13 +39,13 @@ TEST(VideoFrameMetadata, GetFrameIdReturnsCorrectValue) {
|
|||||||
RTPVideoHeader::GenericDescriptorInfo& generic =
|
RTPVideoHeader::GenericDescriptorInfo& generic =
|
||||||
video_header.generic.emplace();
|
video_header.generic.emplace();
|
||||||
generic.frame_id = 10;
|
generic.frame_id = 10;
|
||||||
VideoFrameMetadata metadata(video_header);
|
VideoFrameMetadata metadata = video_header.GetAsMetadata();
|
||||||
EXPECT_EQ(metadata.GetFrameId().value(), 10);
|
EXPECT_EQ(metadata.GetFrameId().value(), 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(VideoFrameMetadata, HasNoFrameIdForHeaderWithoutGeneric) {
|
TEST(VideoFrameMetadata, HasNoFrameIdForHeaderWithoutGeneric) {
|
||||||
RTPVideoHeader video_header;
|
RTPVideoHeader video_header;
|
||||||
VideoFrameMetadata metadata(video_header);
|
VideoFrameMetadata metadata = video_header.GetAsMetadata();
|
||||||
ASSERT_FALSE(video_header.generic);
|
ASSERT_FALSE(video_header.generic);
|
||||||
EXPECT_EQ(metadata.GetFrameId(), absl::nullopt);
|
EXPECT_EQ(metadata.GetFrameId(), absl::nullopt);
|
||||||
}
|
}
|
||||||
@ -55,13 +55,13 @@ TEST(VideoFrameMetadata, GetSpatialIndexReturnsCorrectValue) {
|
|||||||
RTPVideoHeader::GenericDescriptorInfo& generic =
|
RTPVideoHeader::GenericDescriptorInfo& generic =
|
||||||
video_header.generic.emplace();
|
video_header.generic.emplace();
|
||||||
generic.spatial_index = 2;
|
generic.spatial_index = 2;
|
||||||
VideoFrameMetadata metadata(video_header);
|
VideoFrameMetadata metadata = video_header.GetAsMetadata();
|
||||||
EXPECT_EQ(metadata.GetSpatialIndex(), 2);
|
EXPECT_EQ(metadata.GetSpatialIndex(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(VideoFrameMetadata, SpatialIndexIsZeroForHeaderWithoutGeneric) {
|
TEST(VideoFrameMetadata, SpatialIndexIsZeroForHeaderWithoutGeneric) {
|
||||||
RTPVideoHeader video_header;
|
RTPVideoHeader video_header;
|
||||||
VideoFrameMetadata metadata(video_header);
|
VideoFrameMetadata metadata = video_header.GetAsMetadata();
|
||||||
ASSERT_FALSE(video_header.generic);
|
ASSERT_FALSE(video_header.generic);
|
||||||
EXPECT_EQ(metadata.GetSpatialIndex(), 0);
|
EXPECT_EQ(metadata.GetSpatialIndex(), 0);
|
||||||
}
|
}
|
||||||
@ -71,13 +71,13 @@ TEST(VideoFrameMetadata, GetTemporalIndexReturnsCorrectValue) {
|
|||||||
RTPVideoHeader::GenericDescriptorInfo& generic =
|
RTPVideoHeader::GenericDescriptorInfo& generic =
|
||||||
video_header.generic.emplace();
|
video_header.generic.emplace();
|
||||||
generic.temporal_index = 3;
|
generic.temporal_index = 3;
|
||||||
VideoFrameMetadata metadata(video_header);
|
VideoFrameMetadata metadata = video_header.GetAsMetadata();
|
||||||
EXPECT_EQ(metadata.GetTemporalIndex(), 3);
|
EXPECT_EQ(metadata.GetTemporalIndex(), 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(VideoFrameMetadata, TemporalIndexIsZeroForHeaderWithoutGeneric) {
|
TEST(VideoFrameMetadata, TemporalIndexIsZeroForHeaderWithoutGeneric) {
|
||||||
RTPVideoHeader video_header;
|
RTPVideoHeader video_header;
|
||||||
VideoFrameMetadata metadata(video_header);
|
VideoFrameMetadata metadata = video_header.GetAsMetadata();
|
||||||
ASSERT_FALSE(video_header.generic);
|
ASSERT_FALSE(video_header.generic);
|
||||||
EXPECT_EQ(metadata.GetTemporalIndex(), 0);
|
EXPECT_EQ(metadata.GetTemporalIndex(), 0);
|
||||||
}
|
}
|
||||||
@ -87,13 +87,13 @@ TEST(VideoFrameMetadata, GetFrameDependenciesReturnsCorrectValue) {
|
|||||||
RTPVideoHeader::GenericDescriptorInfo& generic =
|
RTPVideoHeader::GenericDescriptorInfo& generic =
|
||||||
video_header.generic.emplace();
|
video_header.generic.emplace();
|
||||||
generic.dependencies = {5, 6, 7};
|
generic.dependencies = {5, 6, 7};
|
||||||
VideoFrameMetadata metadata(video_header);
|
VideoFrameMetadata metadata = video_header.GetAsMetadata();
|
||||||
EXPECT_THAT(metadata.GetFrameDependencies(), ElementsAre(5, 6, 7));
|
EXPECT_THAT(metadata.GetFrameDependencies(), ElementsAre(5, 6, 7));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(VideoFrameMetadata, FrameDependencyVectorIsEmptyForHeaderWithoutGeneric) {
|
TEST(VideoFrameMetadata, FrameDependencyVectorIsEmptyForHeaderWithoutGeneric) {
|
||||||
RTPVideoHeader video_header;
|
RTPVideoHeader video_header;
|
||||||
VideoFrameMetadata metadata(video_header);
|
VideoFrameMetadata metadata = video_header.GetAsMetadata();
|
||||||
ASSERT_FALSE(video_header.generic);
|
ASSERT_FALSE(video_header.generic);
|
||||||
EXPECT_THAT(metadata.GetFrameDependencies(), IsEmpty());
|
EXPECT_THAT(metadata.GetFrameDependencies(), IsEmpty());
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ TEST(VideoFrameMetadata, GetDecodeTargetIndicationsReturnsCorrectValue) {
|
|||||||
RTPVideoHeader::GenericDescriptorInfo& generic =
|
RTPVideoHeader::GenericDescriptorInfo& generic =
|
||||||
video_header.generic.emplace();
|
video_header.generic.emplace();
|
||||||
generic.decode_target_indications = {DecodeTargetIndication::kSwitch};
|
generic.decode_target_indications = {DecodeTargetIndication::kSwitch};
|
||||||
VideoFrameMetadata metadata(video_header);
|
VideoFrameMetadata metadata = video_header.GetAsMetadata();
|
||||||
EXPECT_THAT(metadata.GetDecodeTargetIndications(),
|
EXPECT_THAT(metadata.GetDecodeTargetIndications(),
|
||||||
ElementsAre(DecodeTargetIndication::kSwitch));
|
ElementsAre(DecodeTargetIndication::kSwitch));
|
||||||
}
|
}
|
||||||
@ -111,7 +111,7 @@ TEST(VideoFrameMetadata, GetDecodeTargetIndicationsReturnsCorrectValue) {
|
|||||||
TEST(VideoFrameMetadata,
|
TEST(VideoFrameMetadata,
|
||||||
DecodeTargetIndicationsVectorIsEmptyForHeaderWithoutGeneric) {
|
DecodeTargetIndicationsVectorIsEmptyForHeaderWithoutGeneric) {
|
||||||
RTPVideoHeader video_header;
|
RTPVideoHeader video_header;
|
||||||
VideoFrameMetadata metadata(video_header);
|
VideoFrameMetadata metadata = video_header.GetAsMetadata();
|
||||||
ASSERT_FALSE(video_header.generic);
|
ASSERT_FALSE(video_header.generic);
|
||||||
EXPECT_THAT(metadata.GetDecodeTargetIndications(), IsEmpty());
|
EXPECT_THAT(metadata.GetDecodeTargetIndications(), IsEmpty());
|
||||||
}
|
}
|
||||||
|
|||||||
@ -425,6 +425,7 @@ rtc_library("rtp_video_header") {
|
|||||||
"../../api:rtp_headers",
|
"../../api:rtp_headers",
|
||||||
"../../api/transport/rtp:dependency_descriptor",
|
"../../api/transport/rtp:dependency_descriptor",
|
||||||
"../../api/video:video_frame",
|
"../../api/video:video_frame",
|
||||||
|
"../../api/video:video_frame_metadata",
|
||||||
"../../api/video:video_frame_type",
|
"../../api/video:video_frame_type",
|
||||||
"../../api/video:video_rtp_headers",
|
"../../api/video:video_rtp_headers",
|
||||||
"../../modules/video_coding:codec_globals_headers",
|
"../../modules/video_coding:codec_globals_headers",
|
||||||
|
|||||||
@ -35,7 +35,7 @@ class TransformableVideoSenderFrame : public TransformableVideoFrameInterface {
|
|||||||
uint32_t ssrc)
|
uint32_t ssrc)
|
||||||
: encoded_data_(encoded_image.GetEncodedData()),
|
: encoded_data_(encoded_image.GetEncodedData()),
|
||||||
header_(video_header),
|
header_(video_header),
|
||||||
metadata_(header_),
|
metadata_(header_.GetAsMetadata()),
|
||||||
frame_type_(encoded_image._frameType),
|
frame_type_(encoded_image._frameType),
|
||||||
payload_type_(payload_type),
|
payload_type_(payload_type),
|
||||||
codec_type_(codec_type),
|
codec_type_(codec_type),
|
||||||
|
|||||||
@ -12,13 +12,27 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
RTPVideoHeader::RTPVideoHeader() : video_timing() {}
|
|
||||||
RTPVideoHeader::RTPVideoHeader(const RTPVideoHeader& other) = default;
|
|
||||||
RTPVideoHeader::~RTPVideoHeader() = default;
|
|
||||||
|
|
||||||
RTPVideoHeader::GenericDescriptorInfo::GenericDescriptorInfo() = default;
|
RTPVideoHeader::GenericDescriptorInfo::GenericDescriptorInfo() = default;
|
||||||
RTPVideoHeader::GenericDescriptorInfo::GenericDescriptorInfo(
|
RTPVideoHeader::GenericDescriptorInfo::GenericDescriptorInfo(
|
||||||
const GenericDescriptorInfo& other) = default;
|
const GenericDescriptorInfo& other) = default;
|
||||||
RTPVideoHeader::GenericDescriptorInfo::~GenericDescriptorInfo() = 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
|
} // namespace webrtc
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
#include "api/video/color_space.h"
|
#include "api/video/color_space.h"
|
||||||
#include "api/video/video_codec_type.h"
|
#include "api/video/video_codec_type.h"
|
||||||
#include "api/video/video_content_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_frame_type.h"
|
||||||
#include "api/video/video_rotation.h"
|
#include "api/video/video_rotation.h"
|
||||||
#include "api/video/video_timing.h"
|
#include "api/video/video_timing.h"
|
||||||
@ -62,6 +63,9 @@ struct RTPVideoHeader {
|
|||||||
|
|
||||||
~RTPVideoHeader();
|
~RTPVideoHeader();
|
||||||
|
|
||||||
|
// The subset of RTPVideoHeader that is exposed in the Insertable Streams API.
|
||||||
|
VideoFrameMetadata GetAsMetadata() const;
|
||||||
|
|
||||||
absl::optional<GenericDescriptorInfo> generic;
|
absl::optional<GenericDescriptorInfo> generic;
|
||||||
|
|
||||||
VideoFrameType frame_type = VideoFrameType::kEmptyFrame;
|
VideoFrameType frame_type = VideoFrameType::kEmptyFrame;
|
||||||
|
|||||||
@ -26,7 +26,7 @@ class TransformableVideoReceiverFrame
|
|||||||
TransformableVideoReceiverFrame(std::unique_ptr<RtpFrameObject> frame,
|
TransformableVideoReceiverFrame(std::unique_ptr<RtpFrameObject> frame,
|
||||||
uint32_t ssrc)
|
uint32_t ssrc)
|
||||||
: frame_(std::move(frame)),
|
: frame_(std::move(frame)),
|
||||||
metadata_(frame_->GetRtpVideoHeader()),
|
metadata_(frame_->GetRtpVideoHeader().GetAsMetadata()),
|
||||||
ssrc_(ssrc) {}
|
ssrc_(ssrc) {}
|
||||||
~TransformableVideoReceiverFrame() override = default;
|
~TransformableVideoReceiverFrame() override = default;
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user