Commit e2069a89 authored by Emircan Uysaler's avatar Emircan Uysaler Committed by Commit Bot

Transfer WebRTC color space information to chromium color space

This CL adds functionality to convert webrtc::ColorSpace info into chromium's
media::VideoColorSpace and sets it in remote video receiver.

Bug: 867029
Change-Id: I175fcb6eb0f7918c510b7ff4f355aa300a89473c
Reviewed-on: https://chromium-review.googlesource.com/1154030
Commit-Queue: Emircan Uysaler <emircan@chromium.org>
Reviewed-by: default avatarChristian Fremerey <chfremer@chromium.org>
Reviewed-by: default avatarAvi Drissman <avi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#579202}
parent 95c73fc5
......@@ -439,6 +439,8 @@ target(link_target_type, "renderer") {
"media/webrtc/webrtc_video_capturer_adapter.h",
"media/webrtc/webrtc_video_frame_adapter.cc",
"media/webrtc/webrtc_video_frame_adapter.h",
"media/webrtc/webrtc_video_utils.cc",
"media/webrtc/webrtc_video_utils.h",
"media/webrtc_local_audio_source_provider.cc",
"media/webrtc_local_audio_source_provider.h",
"media/webrtc_logging.cc",
......
......@@ -114,6 +114,8 @@ class CONTENT_EXPORT MediaStreamVideoTrack : public MediaStreamTrack {
friend class MediaStreamVideoSink;
FRIEND_TEST_ALL_PREFIXES(MediaStreamRemoteVideoSourceTest, StartTrack);
FRIEND_TEST_ALL_PREFIXES(MediaStreamRemoteVideoSourceTest, RemoteTrackStop);
FRIEND_TEST_ALL_PREFIXES(MediaStreamRemoteVideoSourceTest,
PreservesColorSpace);
FRIEND_TEST_ALL_PREFIXES(PepperToVideoTrackAdapterTest, PutFrame);
// Add |sink| to receive state changes on the main render thread and video
......
......@@ -13,6 +13,7 @@
#include "base/trace_event/trace_event.h"
#include "content/renderer/media/webrtc/track_observer.h"
#include "content/renderer/media/webrtc/webrtc_video_frame_adapter.h"
#include "content/renderer/media/webrtc/webrtc_video_utils.h"
#include "media/base/bind_to_current_loop.h"
#include "media/base/timestamp_constants.h"
#include "media/base/video_frame.h"
......@@ -22,25 +23,6 @@
namespace content {
namespace {
media::VideoRotation WebRTCToMediaVideoRotation(
webrtc::VideoRotation rotation) {
switch (rotation) {
case webrtc::kVideoRotation_0:
return media::VIDEO_ROTATION_0;
case webrtc::kVideoRotation_90:
return media::VIDEO_ROTATION_90;
case webrtc::kVideoRotation_180:
return media::VIDEO_ROTATION_180;
case webrtc::kVideoRotation_270:
return media::VIDEO_ROTATION_270;
}
return media::VIDEO_ROTATION_0;
}
} // anonymous namespace
// Internal class used for receiving frames from the webrtc track on a
// libjingle thread and forward it to the IO-thread.
class MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate
......@@ -192,7 +174,13 @@ void MediaStreamRemoteVideoSource::RemoteVideoSourceDelegate::OnFrame(
if (incoming_frame.rotation() != webrtc::kVideoRotation_0) {
video_frame->metadata()->SetRotation(
media::VideoFrameMetadata::ROTATION,
WebRTCToMediaVideoRotation(incoming_frame.rotation()));
WebRtcToMediaVideoRotation(incoming_frame.rotation()));
}
if (incoming_frame.color_space().has_value()) {
video_frame->set_color_space(
WebRtcToMediaVideoColorSpace(incoming_frame.color_space().value())
.ToGfxColorSpace());
}
// Run render smoothness algorithm only when we don't have to render
......
......@@ -22,7 +22,9 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/web/web_heap.h"
#include "third_party/webrtc/api/video/color_space.h"
#include "third_party/webrtc/api/video/i420_buffer.h"
#include "ui/gfx/color_space.h"
namespace content {
......@@ -37,6 +39,7 @@ class MediaStreamRemoteVideoSourceUnderTest
std::unique_ptr<TrackObserver> observer)
: MediaStreamRemoteVideoSource(std::move(observer)) {}
using MediaStreamRemoteVideoSource::SinkInterfaceForTesting;
using MediaStreamRemoteVideoSource::StartSourceImpl;
};
class MediaStreamRemoteVideoSourceTest
......@@ -196,4 +199,39 @@ TEST_F(MediaStreamRemoteVideoSourceTest, RemoteTrackStop) {
track->RemoveSink(&sink);
}
TEST_F(MediaStreamRemoteVideoSourceTest, PreservesColorSpace) {
std::unique_ptr<MediaStreamVideoTrack> track(CreateTrack());
MockMediaStreamVideoSink sink;
track->AddSink(&sink, sink.GetDeliverFrameCB(), false);
base::RunLoop run_loop;
EXPECT_CALL(sink, OnVideoFrame())
.WillOnce(RunClosure(run_loop.QuitClosure()));
rtc::scoped_refptr<webrtc::I420Buffer> buffer(
new rtc::RefCountedObject<webrtc::I420Buffer>(320, 240));
webrtc::ColorSpace kColorSpace(webrtc::ColorSpace::PrimaryID::kSMPTE240M,
webrtc::ColorSpace::TransferID::kSMPTE240M,
webrtc::ColorSpace::MatrixID::kSMPTE240M,
webrtc::ColorSpace::RangeID::kLimited);
const webrtc::VideoFrame& input_frame =
webrtc::VideoFrame::Builder()
.set_video_frame_buffer(buffer)
.set_timestamp_ms(0)
.set_rotation(webrtc::kVideoRotation_0)
.set_color_space(kColorSpace)
.build();
source()->SinkInterfaceForTesting()->OnFrame(input_frame);
run_loop.Run();
EXPECT_EQ(1, sink.number_of_frames());
scoped_refptr<media::VideoFrame> output_frame = sink.last_frame();
EXPECT_TRUE(output_frame);
EXPECT_TRUE(output_frame->ColorSpace() ==
gfx::ColorSpace(gfx::ColorSpace::PrimaryID::SMPTE240M,
gfx::ColorSpace::TransferID::SMPTE240M,
gfx::ColorSpace::MatrixID::SMPTE240M,
gfx::ColorSpace::RangeID::LIMITED));
track->RemoveSink(&sink);
}
} // namespace content
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/renderer/media/webrtc/webrtc_video_utils.h"
namespace content {
media::VideoRotation WebRtcToMediaVideoRotation(
webrtc::VideoRotation rotation) {
switch (rotation) {
case webrtc::kVideoRotation_0:
return media::VIDEO_ROTATION_0;
case webrtc::kVideoRotation_90:
return media::VIDEO_ROTATION_90;
case webrtc::kVideoRotation_180:
return media::VIDEO_ROTATION_180;
case webrtc::kVideoRotation_270:
return media::VIDEO_ROTATION_270;
}
return media::VIDEO_ROTATION_0;
}
media::VideoColorSpace WebRtcToMediaVideoColorSpace(
const webrtc::ColorSpace& color_space) {
media::VideoColorSpace::PrimaryID primaries =
media::VideoColorSpace::PrimaryID::INVALID;
switch (color_space.primaries()) {
case webrtc::ColorSpace::PrimaryID::kBT709:
primaries = media::VideoColorSpace::PrimaryID::BT709;
break;
case webrtc::ColorSpace::PrimaryID::kBT470M:
primaries = media::VideoColorSpace::PrimaryID::BT470M;
break;
case webrtc::ColorSpace::PrimaryID::kBT470BG:
primaries = media::VideoColorSpace::PrimaryID::BT470BG;
break;
case webrtc::ColorSpace::PrimaryID::kSMPTE170M:
primaries = media::VideoColorSpace::PrimaryID::SMPTE170M;
break;
case webrtc::ColorSpace::PrimaryID::kSMPTE240M:
primaries = media::VideoColorSpace::PrimaryID::SMPTE240M;
break;
case webrtc::ColorSpace::PrimaryID::kFILM:
primaries = media::VideoColorSpace::PrimaryID::FILM;
break;
case webrtc::ColorSpace::PrimaryID::kBT2020:
primaries = media::VideoColorSpace::PrimaryID::BT2020;
break;
case webrtc::ColorSpace::PrimaryID::kSMPTEST428:
primaries = media::VideoColorSpace::PrimaryID::SMPTEST428_1;
break;
case webrtc::ColorSpace::PrimaryID::kSMPTEST431:
primaries = media::VideoColorSpace::PrimaryID::SMPTEST431_2;
break;
case webrtc::ColorSpace::PrimaryID::kSMPTEST432:
primaries = media::VideoColorSpace::PrimaryID::SMPTEST432_1;
break;
case webrtc::ColorSpace::PrimaryID::kJEDECP22:
primaries = media::VideoColorSpace::PrimaryID::EBU_3213_E;
break;
case webrtc::ColorSpace::PrimaryID::kInvalid:
default:
break;
}
media::VideoColorSpace::TransferID transfer =
media::VideoColorSpace::TransferID::INVALID;
switch (color_space.transfer()) {
case webrtc::ColorSpace::TransferID::kBT709:
transfer = media::VideoColorSpace::TransferID::BT709;
break;
case webrtc::ColorSpace::TransferID::kGAMMA22:
transfer = media::VideoColorSpace::TransferID::GAMMA22;
break;
case webrtc::ColorSpace::TransferID::kGAMMA28:
transfer = media::VideoColorSpace::TransferID::GAMMA28;
break;
case webrtc::ColorSpace::TransferID::kSMPTE170M:
transfer = media::VideoColorSpace::TransferID::SMPTE170M;
break;
case webrtc::ColorSpace::TransferID::kSMPTE240M:
transfer = media::VideoColorSpace::TransferID::SMPTE240M;
break;
case webrtc::ColorSpace::TransferID::kLINEAR:
transfer = media::VideoColorSpace::TransferID::LINEAR;
break;
case webrtc::ColorSpace::TransferID::kLOG:
transfer = media::VideoColorSpace::TransferID::LOG;
break;
case webrtc::ColorSpace::TransferID::kLOG_SQRT:
transfer = media::VideoColorSpace::TransferID::LOG_SQRT;
break;
case webrtc::ColorSpace::TransferID::kIEC61966_2_4:
transfer = media::VideoColorSpace::TransferID::IEC61966_2_4;
break;
case webrtc::ColorSpace::TransferID::kBT1361_ECG:
transfer = media::VideoColorSpace::TransferID::BT1361_ECG;
break;
case webrtc::ColorSpace::TransferID::kIEC61966_2_1:
transfer = media::VideoColorSpace::TransferID::IEC61966_2_1;
break;
case webrtc::ColorSpace::TransferID::kBT2020_10:
transfer = media::VideoColorSpace::TransferID::BT2020_10;
break;
case webrtc::ColorSpace::TransferID::kBT2020_12:
transfer = media::VideoColorSpace::TransferID::BT2020_12;
break;
case webrtc::ColorSpace::TransferID::kSMPTEST2084:
transfer = media::VideoColorSpace::TransferID::SMPTEST2084;
break;
case webrtc::ColorSpace::TransferID::kSMPTEST428:
transfer = media::VideoColorSpace::TransferID::SMPTEST428_1;
break;
case webrtc::ColorSpace::TransferID::kARIB_STD_B67:
transfer = media::VideoColorSpace::TransferID::ARIB_STD_B67;
break;
case webrtc::ColorSpace::TransferID::kInvalid:
default:
break;
}
media::VideoColorSpace::MatrixID matrix =
media::VideoColorSpace::MatrixID::INVALID;
switch (color_space.matrix()) {
case webrtc::ColorSpace::MatrixID::kRGB:
matrix = media::VideoColorSpace::MatrixID::RGB;
break;
case webrtc::ColorSpace::MatrixID::kBT709:
matrix = media::VideoColorSpace::MatrixID::BT709;
break;
case webrtc::ColorSpace::MatrixID::kFCC:
matrix = media::VideoColorSpace::MatrixID::FCC;
break;
case webrtc::ColorSpace::MatrixID::kBT470BG:
matrix = media::VideoColorSpace::MatrixID::BT470BG;
break;
case webrtc::ColorSpace::MatrixID::kSMPTE170M:
matrix = media::VideoColorSpace::MatrixID::SMPTE170M;
break;
case webrtc::ColorSpace::MatrixID::kSMPTE240M:
matrix = media::VideoColorSpace::MatrixID::SMPTE240M;
break;
case webrtc::ColorSpace::MatrixID::kYCOCG:
matrix = media::VideoColorSpace::MatrixID::YCOCG;
break;
case webrtc::ColorSpace::MatrixID::kBT2020_NCL:
matrix = media::VideoColorSpace::MatrixID::BT2020_NCL;
break;
case webrtc::ColorSpace::MatrixID::kBT2020_CL:
matrix = media::VideoColorSpace::MatrixID::BT2020_CL;
break;
case webrtc::ColorSpace::MatrixID::kSMPTE2085:
matrix = media::VideoColorSpace::MatrixID::YDZDX;
break;
case webrtc::ColorSpace::MatrixID::kInvalid:
default:
break;
}
gfx::ColorSpace::RangeID range = gfx::ColorSpace::RangeID::INVALID;
switch (color_space.range()) {
case webrtc::ColorSpace::RangeID::kLimited:
range = gfx::ColorSpace::RangeID::LIMITED;
break;
case webrtc::ColorSpace::RangeID::kFull:
range = gfx::ColorSpace::RangeID::FULL;
break;
case webrtc::ColorSpace::RangeID::kInvalid:
default:
break;
}
return media::VideoColorSpace(primaries, transfer, matrix, range);
}
} // namespace content
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_UTILS_H_
#define CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_UTILS_H_
#include "media/base/video_color_space.h"
#include "media/base/video_rotation.h"
#include "third_party/webrtc/api/video/color_space.h"
#include "third_party/webrtc/api/video/video_rotation.h"
namespace content {
// This file has helper methods for conversion between chromium types and
// webrtc/api/video types.
media::VideoRotation WebRtcToMediaVideoRotation(webrtc::VideoRotation rotation);
media::VideoColorSpace WebRtcToMediaVideoColorSpace(
const webrtc::ColorSpace& color_space);
} // namespace content
#endif // CONTENT_RENDERER_MEDIA_WEBRTC_WEBRTC_VIDEO_UTILS_H_
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment