Pass on explicit color space for VP8 and H264
Bug: webtc:8651 Change-Id: I9d478e7123e915bff858d725d6008fcfeeb0779d Reviewed-on: https://webrtc-review.googlesource.com/c/114424 Reviewed-by: Erik Språng <sprang@webrtc.org> Commit-Queue: Johannes Kron <kron@webrtc.org> Cr-Commit-Position: refs/heads/master@{#26044}
This commit is contained in:

committed by
Commit Bot

parent
0fcf4b1dbd
commit
a1bec23f6c
@ -300,7 +300,10 @@ int32_t H264DecoderImpl::Decode(const EncodedImage& input_image,
|
||||
RTC_CHECK_EQ(av_frame_->data[kUPlaneIndex], i420_buffer->DataU());
|
||||
RTC_CHECK_EQ(av_frame_->data[kVPlaneIndex], i420_buffer->DataV());
|
||||
|
||||
const ColorSpace& color_space = ExtractH264ColorSpace(av_context_.get());
|
||||
// Pass on color space from input frame if explicitly specified.
|
||||
const ColorSpace& color_space =
|
||||
input_frame->color_space() ? *input_frame->color_space()
|
||||
: ExtractH264ColorSpace(av_context_.get());
|
||||
VideoFrame decoded_frame =
|
||||
VideoFrame::Builder()
|
||||
.set_video_frame_buffer(input_frame->video_frame_buffer())
|
||||
|
@ -502,6 +502,7 @@ int32_t H264EncoderImpl::Encode(const VideoFrame& input_frame,
|
||||
encoded_images_[i].ntp_time_ms_ = input_frame.ntp_time_ms();
|
||||
encoded_images_[i].capture_time_ms_ = input_frame.render_time_ms();
|
||||
encoded_images_[i].rotation_ = input_frame.rotation();
|
||||
encoded_images_[i].SetColorSpace(input_frame.color_space());
|
||||
encoded_images_[i].content_type_ =
|
||||
(codec_.mode == VideoCodecMode::kScreensharing)
|
||||
? VideoContentType::SCREENSHARE
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "api/video_codecs/video_encoder.h"
|
||||
#include "common_types.h" // NOLINT(build/include)
|
||||
#include "common_video/libyuv/include/webrtc_libyuv.h"
|
||||
#include "common_video/test/utilities.h"
|
||||
#include "media/base/codec.h"
|
||||
#include "media/base/mediaconstants.h"
|
||||
#include "modules/video_coding/codecs/h264/include/h264.h"
|
||||
@ -49,9 +50,17 @@ class TestH264Impl : public VideoCodecUnitTest {
|
||||
#ifdef WEBRTC_USE_H264
|
||||
#define MAYBE_EncodeDecode EncodeDecode
|
||||
#define MAYBE_DecodedQpEqualsEncodedQp DecodedQpEqualsEncodedQp
|
||||
#define MAYBE_EncodedColorSpaceEqualsInputColorSpace \
|
||||
EncodedColorSpaceEqualsInputColorSpace
|
||||
#define MAYBE_DecodedColorSpaceEqualsEncodedColorSpace \
|
||||
DecodedColorSpaceEqualsEncodedColorSpace
|
||||
#else
|
||||
#define MAYBE_EncodeDecode DISABLED_EncodeDecode
|
||||
#define MAYBE_DecodedQpEqualsEncodedQp DISABLED_DecodedQpEqualsEncodedQp
|
||||
#define MAYBE_EncodedColorSpaceEqualsInputColorSpace \
|
||||
DISABLED_EncodedColorSpaceEqualsInputColorSpace
|
||||
#define MAYBE_DecodedColorSpaceEqualsEncodedColorSpace \
|
||||
DISABLED_DecodedColorSpaceEqualsEncodedColorSpace
|
||||
#endif
|
||||
|
||||
TEST_F(TestH264Impl, MAYBE_EncodeDecode) {
|
||||
@ -100,4 +109,47 @@ TEST_F(TestH264Impl, MAYBE_DecodedQpEqualsEncodedQp) {
|
||||
EXPECT_EQ(encoded_frame.qp_, *decoded_qp);
|
||||
}
|
||||
|
||||
TEST_F(TestH264Impl, MAYBE_EncodedColorSpaceEqualsInputColorSpace) {
|
||||
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.ColorSpace());
|
||||
|
||||
// Video frame with explicit color space information.
|
||||
ColorSpace color_space = CreateTestColorSpace(/*with_hdr_metadata=*/false);
|
||||
VideoFrame input_frame_w_color_space =
|
||||
VideoFrame::Builder()
|
||||
.set_video_frame_buffer(input_frame->video_frame_buffer())
|
||||
.set_color_space(&color_space)
|
||||
.build();
|
||||
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
encoder_->Encode(input_frame_w_color_space, nullptr, nullptr));
|
||||
ASSERT_TRUE(WaitForEncodedFrame(&encoded_frame, &codec_specific_info));
|
||||
ASSERT_TRUE(encoded_frame.ColorSpace());
|
||||
EXPECT_EQ(*encoded_frame.ColorSpace(), color_space);
|
||||
}
|
||||
|
||||
TEST_F(TestH264Impl, MAYBE_DecodedColorSpaceEqualsEncodedColorSpace) {
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
encoder_->Encode(*NextInputFrame(), nullptr, nullptr));
|
||||
EncodedImage encoded_frame;
|
||||
CodecSpecificInfo codec_specific_info;
|
||||
ASSERT_TRUE(WaitForEncodedFrame(&encoded_frame, &codec_specific_info));
|
||||
// Add color space to encoded frame.
|
||||
ColorSpace color_space = CreateTestColorSpace(/*with_hdr_metadata=*/false);
|
||||
encoded_frame.SetColorSpace(&color_space);
|
||||
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);
|
||||
ASSERT_TRUE(decoded_frame->color_space());
|
||||
EXPECT_EQ(color_space, *decoded_frame->color_space());
|
||||
}
|
||||
|
||||
} // namespace webrtc
|
||||
|
@ -266,7 +266,8 @@ int LibvpxVp8Decoder::Decode(const EncodedImage& input_image,
|
||||
vpx_codec_err_t vpx_ret =
|
||||
vpx_codec_control(decoder_, VPXD_GET_LAST_QUANTIZER, &qp);
|
||||
RTC_DCHECK_EQ(vpx_ret, VPX_CODEC_OK);
|
||||
ret = ReturnFrame(img, input_image.Timestamp(), input_image.ntp_time_ms_, qp);
|
||||
ret = ReturnFrame(img, input_image.Timestamp(), input_image.ntp_time_ms_, qp,
|
||||
input_image.ColorSpace());
|
||||
if (ret != 0) {
|
||||
// Reset to avoid requesting key frames too often.
|
||||
if (ret < 0 && propagation_cnt_ > 0)
|
||||
@ -285,7 +286,8 @@ int LibvpxVp8Decoder::Decode(const EncodedImage& input_image,
|
||||
int LibvpxVp8Decoder::ReturnFrame(const vpx_image_t* img,
|
||||
uint32_t timestamp,
|
||||
int64_t ntp_time_ms,
|
||||
int qp) {
|
||||
int qp,
|
||||
const ColorSpace* explicit_color_space) {
|
||||
if (img == NULL) {
|
||||
// Decoder OK and NULL image => No show frame
|
||||
return WEBRTC_VIDEO_CODEC_NO_OUTPUT;
|
||||
@ -317,8 +319,12 @@ int LibvpxVp8Decoder::ReturnFrame(const vpx_image_t* img,
|
||||
buffer->MutableDataV(), buffer->StrideV(), img->d_w,
|
||||
img->d_h);
|
||||
|
||||
VideoFrame decoded_image(buffer, timestamp, 0, kVideoRotation_0);
|
||||
decoded_image.set_ntp_time_ms(ntp_time_ms);
|
||||
VideoFrame decoded_image = VideoFrame::Builder()
|
||||
.set_video_frame_buffer(buffer)
|
||||
.set_timestamp_rtp(timestamp)
|
||||
.set_ntp_time_ms(ntp_time_ms)
|
||||
.set_color_space(explicit_color_space)
|
||||
.build();
|
||||
decode_complete_callback_->Decoded(decoded_image, absl::nullopt, qp);
|
||||
|
||||
return WEBRTC_VIDEO_CODEC_OK;
|
||||
|
@ -53,8 +53,8 @@ class LibvpxVp8Decoder : public VideoDecoder {
|
||||
int ReturnFrame(const vpx_image_t* img,
|
||||
uint32_t timeStamp,
|
||||
int64_t ntp_time_ms,
|
||||
int qp);
|
||||
|
||||
int qp,
|
||||
const ColorSpace* explicit_color_space);
|
||||
const bool use_postproc_arm_;
|
||||
|
||||
I420BufferPool buffer_pool_;
|
||||
|
@ -918,6 +918,7 @@ int LibvpxVp8Encoder::GetEncodedPartitions(const VideoFrame& input_image) {
|
||||
? VideoContentType::SCREENSHARE
|
||||
: VideoContentType::UNSPECIFIED;
|
||||
encoded_images_[encoder_idx].timing_.flags = VideoSendTiming::kInvalid;
|
||||
encoded_images_[encoder_idx].SetColorSpace(input_image.color_space());
|
||||
|
||||
if (send_stream_[stream_idx]) {
|
||||
if (encoded_images_[encoder_idx]._length > 0) {
|
||||
|
@ -16,6 +16,7 @@
|
||||
#include "api/test/mock_video_encoder.h"
|
||||
#include "api/video_codecs/vp8_temporal_layers.h"
|
||||
#include "common_video/libyuv/include/webrtc_libyuv.h"
|
||||
#include "common_video/test/utilities.h"
|
||||
#include "modules/video_coding/codecs/test/video_codec_unittest.h"
|
||||
#include "modules/video_coding/codecs/vp8/include/vp8.h"
|
||||
#include "modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h"
|
||||
@ -173,6 +174,28 @@ TEST_F(TestVp8Impl, EncodedRotationEqualsInputRotation) {
|
||||
EXPECT_EQ(kVideoRotation_90, encoded_frame.rotation_);
|
||||
}
|
||||
|
||||
TEST_F(TestVp8Impl, EncodedColorSpaceEqualsInputColorSpace) {
|
||||
// Video frame without explicit color space information.
|
||||
VideoFrame* input_frame = NextInputFrame();
|
||||
EncodedImage encoded_frame;
|
||||
CodecSpecificInfo codec_specific_info;
|
||||
EncodeAndWaitForFrame(*input_frame, &encoded_frame, &codec_specific_info);
|
||||
EXPECT_FALSE(encoded_frame.ColorSpace());
|
||||
|
||||
// Video frame with explicit color space information.
|
||||
ColorSpace color_space = CreateTestColorSpace(/*with_hdr_metadata=*/false);
|
||||
VideoFrame input_frame_w_color_space =
|
||||
VideoFrame::Builder()
|
||||
.set_video_frame_buffer(input_frame->video_frame_buffer())
|
||||
.set_color_space(&color_space)
|
||||
.build();
|
||||
|
||||
EncodeAndWaitForFrame(input_frame_w_color_space, &encoded_frame,
|
||||
&codec_specific_info);
|
||||
ASSERT_TRUE(encoded_frame.ColorSpace());
|
||||
EXPECT_EQ(*encoded_frame.ColorSpace(), color_space);
|
||||
}
|
||||
|
||||
TEST_F(TestVp8Impl, DecodedQpEqualsEncodedQp) {
|
||||
VideoFrame* input_frame = NextInputFrame();
|
||||
EncodedImage encoded_frame;
|
||||
@ -192,6 +215,25 @@ TEST_F(TestVp8Impl, DecodedQpEqualsEncodedQp) {
|
||||
EXPECT_EQ(encoded_frame.qp_, *decoded_qp);
|
||||
}
|
||||
|
||||
TEST_F(TestVp8Impl, DecodedColorSpaceEqualsEncodedColorSpace) {
|
||||
VideoFrame* input_frame = NextInputFrame();
|
||||
EncodedImage encoded_frame;
|
||||
CodecSpecificInfo codec_specific_info;
|
||||
EncodeAndWaitForFrame(*input_frame, &encoded_frame, &codec_specific_info);
|
||||
|
||||
// Encoded frame with explicit color space information.
|
||||
ColorSpace color_space = CreateTestColorSpace(/*with_hdr_metadata=*/false);
|
||||
encoded_frame.SetColorSpace(&color_space);
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
decoder_->Decode(encoded_frame, false, nullptr, -1));
|
||||
std::unique_ptr<VideoFrame> decoded_frame;
|
||||
absl::optional<uint8_t> decoded_qp;
|
||||
ASSERT_TRUE(WaitForDecodedFrame(&decoded_frame, &decoded_qp));
|
||||
ASSERT_TRUE(decoded_frame);
|
||||
ASSERT_TRUE(decoded_frame->color_space());
|
||||
EXPECT_EQ(color_space, *decoded_frame->color_space());
|
||||
}
|
||||
|
||||
TEST_F(TestVp8Impl, ChecksSimulcastSettings) {
|
||||
codec_settings_.numberOfSimulcastStreams = 2;
|
||||
// Reslutions are not scaled by 2, temporal layers do not match.
|
||||
|
@ -187,7 +187,7 @@ TEST_F(TestVp9Impl, EncodedColorSpaceEqualsInputColorSpace) {
|
||||
EXPECT_EQ(*encoded_frame.ColorSpace(), color_space);
|
||||
}
|
||||
|
||||
TEST_F(TestVp9Impl, DecodedHdrMetadataEqualsEncodedHdrMetadata) {
|
||||
TEST_F(TestVp9Impl, DecodedColorSpaceEqualsEncodedColorSpace) {
|
||||
EXPECT_EQ(WEBRTC_VIDEO_CODEC_OK,
|
||||
encoder_->Encode(*NextInputFrame(), nullptr, nullptr));
|
||||
EncodedImage encoded_frame;
|
||||
|
Reference in New Issue
Block a user