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:
Johannes Kron
2018-12-14 13:55:23 +01:00
committed by Commit Bot
parent 0fcf4b1dbd
commit a1bec23f6c
8 changed files with 113 additions and 8 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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