Move HdrMetadata to ColorSpace
Move HdrMetadata to ColorSpace as part of preparing for joint transmission
of these two objects.
Bug: webrtc:8651
Change-Id: Ie948011a2c0106d5967cb5ef3b9565217e798272
Reviewed-on: https://webrtc-review.googlesource.com/c/111481
Commit-Queue: Johannes Kron <kron@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Åsa Persson <asapersson@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#25730}
diff --git a/api/video/color_space.cc b/api/video/color_space.cc
index a8be5cd..2f07e00 100644
--- a/api/video/color_space.cc
+++ b/api/video/color_space.cc
@@ -13,15 +13,27 @@
namespace webrtc {
ColorSpace::ColorSpace() = default;
+ColorSpace::ColorSpace(const ColorSpace& other) = default;
+ColorSpace::ColorSpace(ColorSpace&& other) = default;
+ColorSpace& ColorSpace::operator=(const ColorSpace& other) = default;
ColorSpace::ColorSpace(PrimaryID primaries,
TransferID transfer,
MatrixID matrix,
RangeID range)
+ : ColorSpace(primaries, transfer, matrix, range, nullptr) {}
+
+ColorSpace::ColorSpace(PrimaryID primaries,
+ TransferID transfer,
+ MatrixID matrix,
+ RangeID range,
+ const HdrMetadata* hdr_metadata)
: primaries_(primaries),
transfer_(transfer),
matrix_(matrix),
- range_(range) {}
+ range_(range),
+ hdr_metadata_(hdr_metadata ? absl::make_optional(*hdr_metadata)
+ : absl::nullopt) {}
ColorSpace::PrimaryID ColorSpace::primaries() const {
return primaries_;
@@ -39,4 +51,8 @@
return range_;
}
+const HdrMetadata* ColorSpace::hdr_metadata() const {
+ return hdr_metadata_ ? &*hdr_metadata_ : nullptr;
+}
+
} // namespace webrtc
diff --git a/api/video/color_space.h b/api/video/color_space.h
index cce3d92..385734a 100644
--- a/api/video/color_space.h
+++ b/api/video/color_space.h
@@ -13,6 +13,9 @@
#include <stdint.h>
+#include "absl/types/optional.h"
+#include "api/video/hdr_metadata.h"
+
namespace webrtc {
// This class represents color information as specified in T-REC H.273,
@@ -101,21 +104,38 @@
};
ColorSpace();
+ ColorSpace(const ColorSpace& other);
+ ColorSpace(ColorSpace&& other);
+ ColorSpace& operator=(const ColorSpace& other);
ColorSpace(PrimaryID primaries,
TransferID transfer,
MatrixID matrix,
RangeID full_range);
+ ColorSpace(PrimaryID primaries,
+ TransferID transfer,
+ MatrixID matrix,
+ RangeID range,
+ const HdrMetadata* hdr_metadata);
+ bool operator==(const ColorSpace& other) const {
+ return primaries_ == other.primaries() && transfer_ == other.transfer() &&
+ matrix_ == other.matrix() && range_ == other.range() &&
+ ((hdr_metadata_.has_value() && other.hdr_metadata() &&
+ *hdr_metadata_ == *other.hdr_metadata()) ||
+ (!hdr_metadata_.has_value() && other.hdr_metadata() == nullptr));
+ }
PrimaryID primaries() const;
TransferID transfer() const;
MatrixID matrix() const;
RangeID range() const;
+ const HdrMetadata* hdr_metadata() const;
private:
PrimaryID primaries_ = PrimaryID::kInvalid;
TransferID transfer_ = TransferID::kInvalid;
MatrixID matrix_ = MatrixID::kInvalid;
RangeID range_ = RangeID::kInvalid;
+ absl::optional<HdrMetadata> hdr_metadata_;
};
} // namespace webrtc
diff --git a/api/video/encoded_image.h b/api/video/encoded_image.h
index 4cf410b..a7c719c 100644
--- a/api/video/encoded_image.h
+++ b/api/video/encoded_image.h
@@ -14,7 +14,7 @@
#include <stdint.h>
#include "absl/types/optional.h"
-#include "api/video/hdr_metadata.h"
+#include "api/video/color_space.h"
#include "api/video/video_bitrate_allocation.h"
#include "api/video/video_codec_type.h"
#include "api/video/video_content_type.h"
@@ -59,12 +59,12 @@
spatial_index_ = spatial_index;
}
- const webrtc::HdrMetadata* HdrMetadata() const {
- return hdr_metadata_ ? &*hdr_metadata_ : nullptr;
+ const webrtc::ColorSpace* ColorSpace() const {
+ return color_space_ ? &*color_space_ : nullptr;
}
- void SetHdrMetadata(const webrtc::HdrMetadata* hdr_metadata) {
- hdr_metadata_ =
- hdr_metadata ? absl::make_optional(*hdr_metadata) : absl::nullopt;
+ void SetColorSpace(const webrtc::ColorSpace* color_space) {
+ color_space_ =
+ color_space ? absl::make_optional(*color_space) : absl::nullopt;
}
uint32_t _encodedWidth = 0;
@@ -101,7 +101,7 @@
private:
uint32_t timestamp_rtp_ = 0;
absl::optional<int> spatial_index_;
- absl::optional<webrtc::HdrMetadata> hdr_metadata_;
+ absl::optional<webrtc::ColorSpace> color_space_;
};
} // namespace webrtc
diff --git a/api/video/video_frame.cc b/api/video/video_frame.cc
index 23d3140..eaae33b 100644
--- a/api/video/video_frame.cc
+++ b/api/video/video_frame.cc
@@ -21,7 +21,7 @@
VideoFrame VideoFrame::Builder::build() {
return VideoFrame(video_frame_buffer_, timestamp_us_, timestamp_rtp_,
- ntp_time_ms_, rotation_, color_space_, hdr_metadata_);
+ ntp_time_ms_, rotation_, color_space_);
}
VideoFrame::Builder& VideoFrame::Builder::set_video_frame_buffer(
@@ -64,10 +64,10 @@
return *this;
}
-VideoFrame::Builder& VideoFrame::Builder::set_hdr_metadata(
- const HdrMetadata* hdr_metadata) {
- hdr_metadata_ =
- hdr_metadata ? absl::make_optional(*hdr_metadata) : absl::nullopt;
+VideoFrame::Builder& VideoFrame::Builder::set_color_space(
+ const ColorSpace* color_space) {
+ color_space_ =
+ color_space ? absl::make_optional(*color_space) : absl::nullopt;
return *this;
}
@@ -97,15 +97,13 @@
uint32_t timestamp_rtp,
int64_t ntp_time_ms,
VideoRotation rotation,
- const absl::optional<ColorSpace>& color_space,
- const absl::optional<HdrMetadata>& hdr_metadata)
+ const absl::optional<ColorSpace>& color_space)
: video_frame_buffer_(buffer),
timestamp_rtp_(timestamp_rtp),
ntp_time_ms_(ntp_time_ms),
timestamp_us_(timestamp_us),
rotation_(rotation),
- color_space_(color_space),
- hdr_metadata_(hdr_metadata) {}
+ color_space_(color_space) {}
VideoFrame::~VideoFrame() = default;
diff --git a/api/video/video_frame.h b/api/video/video_frame.h
index 321eb97..2c5d081 100644
--- a/api/video/video_frame.h
+++ b/api/video/video_frame.h
@@ -40,7 +40,7 @@
Builder& set_ntp_time_ms(int64_t ntp_time_ms);
Builder& set_rotation(VideoRotation rotation);
Builder& set_color_space(const ColorSpace& color_space);
- Builder& set_hdr_metadata(const HdrMetadata* hdr_metadata);
+ Builder& set_color_space(const ColorSpace* color_space);
private:
rtc::scoped_refptr<webrtc::VideoFrameBuffer> video_frame_buffer_;
@@ -49,7 +49,6 @@
int64_t ntp_time_ms_ = 0;
VideoRotation rotation_ = kVideoRotation_0;
absl::optional<ColorSpace> color_space_;
- absl::optional<HdrMetadata> hdr_metadata_;
};
// To be deprecated. Migrate all use to Builder.
@@ -116,11 +115,8 @@
void set_rotation(VideoRotation rotation) { rotation_ = rotation; }
// Get color space when available.
- absl::optional<ColorSpace> color_space() const { return color_space_; }
-
- // Get HDR metadata when available.
- const HdrMetadata* hdr_metadata() const {
- return hdr_metadata_ ? &*hdr_metadata_ : nullptr;
+ const ColorSpace* color_space() const {
+ return color_space_ ? &*color_space_ : nullptr;
}
// Get render time in milliseconds.
@@ -143,8 +139,7 @@
uint32_t timestamp_rtp,
int64_t ntp_time_ms,
VideoRotation rotation,
- const absl::optional<ColorSpace>& color_space,
- const absl::optional<HdrMetadata>& hdr_metadata);
+ const absl::optional<ColorSpace>& color_space);
// An opaque reference counted handle that stores the pixel data.
rtc::scoped_refptr<webrtc::VideoFrameBuffer> video_frame_buffer_;
@@ -153,7 +148,6 @@
int64_t timestamp_us_;
VideoRotation rotation_;
absl::optional<ColorSpace> color_space_;
- absl::optional<HdrMetadata> hdr_metadata_;
};
} // namespace webrtc
diff --git a/modules/video_coding/codecs/h264/test/h264_impl_unittest.cc b/modules/video_coding/codecs/h264/test/h264_impl_unittest.cc
index 14bb6bc..82c14b7 100644
--- a/modules/video_coding/codecs/h264/test/h264_impl_unittest.cc
+++ b/modules/video_coding/codecs/h264/test/h264_impl_unittest.cc
@@ -56,7 +56,7 @@
ASSERT_TRUE(decoded_frame);
EXPECT_GT(I420PSNR(input_frame, decoded_frame.get()), 36);
- const ColorSpace color_space = decoded_frame->color_space().value();
+ const ColorSpace color_space = *decoded_frame->color_space();
EXPECT_EQ(ColorSpace::PrimaryID::kInvalid, color_space.primaries());
EXPECT_EQ(ColorSpace::TransferID::kInvalid, color_space.transfer());
EXPECT_EQ(ColorSpace::MatrixID::kInvalid, color_space.matrix());
diff --git a/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc b/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc
index 8cc919b..85fa278 100644
--- a/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc
+++ b/modules/video_coding/codecs/vp9/test/vp9_impl_unittest.cc
@@ -105,7 +105,7 @@
}
}
- HdrMetadata CreateTestHdrMetadata() {
+ HdrMetadata CreateTestHdrMetadata() const {
// Random but reasonable HDR metadata.
HdrMetadata hdr_metadata;
hdr_metadata.mastering_metadata.luminance_max = 2000.0;
@@ -122,6 +122,15 @@
hdr_metadata.max_frame_average_light_level = 1789;
return hdr_metadata;
}
+
+ ColorSpace CreateTestColorSpace() const {
+ HdrMetadata hdr_metadata = CreateTestHdrMetadata();
+ ColorSpace color_space(ColorSpace::PrimaryID::kBT709,
+ ColorSpace::TransferID::kGAMMA22,
+ ColorSpace::MatrixID::kSMPTE2085,
+ ColorSpace::RangeID::kFull, &hdr_metadata);
+ return color_space;
+ }
};
// Disabled on ios as flake, see https://crbug.com/webrtc/7057
@@ -146,7 +155,7 @@
ASSERT_TRUE(decoded_frame);
EXPECT_GT(I420PSNR(input_frame, decoded_frame.get()), 36);
- const ColorSpace color_space = decoded_frame->color_space().value();
+ const ColorSpace color_space = *decoded_frame->color_space();
EXPECT_EQ(ColorSpace::PrimaryID::kInvalid, color_space.primaries());
EXPECT_EQ(ColorSpace::TransferID::kInvalid, color_space.transfer());
EXPECT_EQ(ColorSpace::MatrixID::kInvalid, color_space.matrix());
@@ -175,28 +184,28 @@
EXPECT_EQ(kVideoRotation_90, encoded_frame.rotation_);
}
-TEST_F(TestVp9Impl, EncodedHdrMetadataEqualsInputHdrMetadata) {
- // Video frame without HDR metadata.
+TEST_F(TestVp9Impl, EncodedColorSpaceEqualsInputColorSpace) {
+ // Video frame without explicit color space information.
VideoFrame* input_frame = NextInputFrame();
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
encoder_->Encode(*input_frame, nullptr, nullptr));
EncodedImage encoded_frame;
CodecSpecificInfo codec_specific_info;
ASSERT_TRUE(WaitForEncodedFrame(&encoded_frame, &codec_specific_info));
- EXPECT_FALSE(encoded_frame.HdrMetadata());
+ EXPECT_FALSE(encoded_frame.ColorSpace());
- // Video frame with HDR metadata.
- HdrMetadata hdr_metadata = CreateTestHdrMetadata();
+ // Video frame with explicit color space information.
+ ColorSpace color_space = CreateTestColorSpace();
VideoFrame input_frame_w_hdr =
VideoFrame::Builder()
.set_video_frame_buffer(input_frame->video_frame_buffer())
- .set_hdr_metadata(&hdr_metadata)
+ .set_color_space(&color_space)
.build();
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
encoder_->Encode(input_frame_w_hdr, nullptr, nullptr));
ASSERT_TRUE(WaitForEncodedFrame(&encoded_frame, &codec_specific_info));
- EXPECT_TRUE(encoded_frame.HdrMetadata());
- EXPECT_EQ(hdr_metadata, *encoded_frame.HdrMetadata());
+ ASSERT_TRUE(encoded_frame.ColorSpace());
+ EXPECT_EQ(*encoded_frame.ColorSpace(), color_space);
}
TEST_F(TestVp9Impl, DecodedHdrMetadataEqualsEncodedHdrMetadata) {
@@ -206,24 +215,27 @@
CodecSpecificInfo codec_specific_info;
ASSERT_TRUE(WaitForEncodedFrame(&encoded_frame, &codec_specific_info));
- // Encoded frame without HDR metadata.
+ // Encoded frame without explicit color space information.
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
decoder_->Decode(encoded_frame, false, nullptr, 0));
std::unique_ptr<VideoFrame> decoded_frame;
absl::optional<uint8_t> decoded_qp;
ASSERT_TRUE(WaitForDecodedFrame(&decoded_frame, &decoded_qp));
ASSERT_TRUE(decoded_frame);
- EXPECT_FALSE(decoded_frame->hdr_metadata());
+ // Color space present from encoded bitstream.
+ ASSERT_TRUE(decoded_frame->color_space());
+ // No HDR metadata present.
+ EXPECT_FALSE(decoded_frame->color_space()->hdr_metadata());
- // Encoded frame with HDR metadata.
- HdrMetadata hdr_metadata = CreateTestHdrMetadata();
- encoded_frame.SetHdrMetadata(&hdr_metadata);
+ // Encoded frame with explicit color space information.
+ ColorSpace color_space = CreateTestColorSpace();
+ encoded_frame.SetColorSpace(&color_space);
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
decoder_->Decode(encoded_frame, false, nullptr, 0));
ASSERT_TRUE(WaitForDecodedFrame(&decoded_frame, &decoded_qp));
ASSERT_TRUE(decoded_frame);
- ASSERT_TRUE(decoded_frame->hdr_metadata());
- EXPECT_EQ(hdr_metadata, *decoded_frame->hdr_metadata());
+ ASSERT_TRUE(decoded_frame->color_space());
+ EXPECT_EQ(color_space, *decoded_frame->color_space());
}
TEST_F(TestVp9Impl, DecodedQpEqualsEncodedQp) {
diff --git a/modules/video_coding/codecs/vp9/vp9_impl.cc b/modules/video_coding/codecs/vp9/vp9_impl.cc
index a19316c..427e446 100644
--- a/modules/video_coding/codecs/vp9/vp9_impl.cc
+++ b/modules/video_coding/codecs/vp9/vp9_impl.cc
@@ -1199,7 +1199,7 @@
int qp = -1;
vpx_codec_control(encoder_, VP8E_GET_LAST_QUANTIZER, &qp);
encoded_image_.qp_ = qp;
- encoded_image_.SetHdrMetadata(input_image_->hdr_metadata());
+ encoded_image_.SetColorSpace(input_image_->color_space());
return WEBRTC_VIDEO_CODEC_OK;
}
@@ -1339,7 +1339,7 @@
vpx_codec_control(decoder_, VPXD_GET_LAST_QUANTIZER, &qp);
RTC_DCHECK_EQ(vpx_ret, VPX_CODEC_OK);
int ret = ReturnFrame(img, input_image.Timestamp(), input_image.ntp_time_ms_,
- qp, input_image.HdrMetadata());
+ qp, input_image.ColorSpace());
if (ret != 0) {
return ret;
}
@@ -1350,7 +1350,7 @@
uint32_t timestamp,
int64_t ntp_time_ms,
int qp,
- const HdrMetadata* hdr_metadata) {
+ const ColorSpace* explicit_color_space) {
if (img == nullptr) {
// Decoder OK and nullptr image => No show frame.
return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
@@ -1392,16 +1392,21 @@
return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
}
- VideoFrame decoded_image = VideoFrame::Builder()
- .set_video_frame_buffer(img_wrapped_buffer)
- .set_timestamp_ms(0)
- .set_timestamp_rtp(timestamp)
- .set_ntp_time_ms(ntp_time_ms)
- .set_rotation(webrtc::kVideoRotation_0)
- .set_color_space(ExtractVP9ColorSpace(
- img->cs, img->range, img->bit_depth))
- .set_hdr_metadata(hdr_metadata)
- .build();
+ auto builder = VideoFrame::Builder()
+ .set_video_frame_buffer(img_wrapped_buffer)
+ .set_timestamp_ms(0)
+ .set_timestamp_rtp(timestamp)
+ .set_ntp_time_ms(ntp_time_ms)
+ .set_rotation(webrtc::kVideoRotation_0);
+ if (explicit_color_space) {
+ builder.set_color_space(explicit_color_space);
+ } else {
+ builder.set_color_space(
+ ExtractVP9ColorSpace(img->cs, img->range, img->bit_depth));
+ }
+
+ VideoFrame decoded_image = builder.build();
+
decode_complete_callback_->Decoded(decoded_image, absl::nullopt, qp);
return WEBRTC_VIDEO_CODEC_OK;
}
diff --git a/modules/video_coding/codecs/vp9/vp9_impl.h b/modules/video_coding/codecs/vp9/vp9_impl.h
index d26c53d..072e8408 100644
--- a/modules/video_coding/codecs/vp9/vp9_impl.h
+++ b/modules/video_coding/codecs/vp9/vp9_impl.h
@@ -170,7 +170,7 @@
uint32_t timestamp,
int64_t ntp_time_ms,
int qp,
- const HdrMetadata* hdr_metadata);
+ const ColorSpace* explicit_color_space);
// Memory pool used to share buffers between libvpx and webrtc.
Vp9FrameBufferPool frame_buffer_pool_;