summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--remoting/BUILD.gn1
-rw-r--r--remoting/remoting_test.gypi1
-rw-r--r--remoting/test/DEPS1
-rw-r--r--remoting/test/test_video_renderer.cc174
-rw-r--r--remoting/test/test_video_renderer.h32
-rw-r--r--remoting/test/test_video_renderer_unittest.cc247
6 files changed, 10 insertions, 446 deletions
diff --git a/remoting/BUILD.gn b/remoting/BUILD.gn
index 314a484..899f9d8 100644
--- a/remoting/BUILD.gn
+++ b/remoting/BUILD.gn
@@ -150,7 +150,6 @@ if (!is_mac) {
"test/app_remoting_test_driver_environment_unittest.cc",
"test/remote_host_info_fetcher_unittest.cc",
"test/test_chromoting_client_unittest.cc",
- "test/test_video_renderer_unittest.cc",
]
configs += [
diff --git a/remoting/remoting_test.gypi b/remoting/remoting_test.gypi
index 3d284f7..807e86e 100644
--- a/remoting/remoting_test.gypi
+++ b/remoting/remoting_test.gypi
@@ -357,7 +357,6 @@
'test/app_remoting_test_driver_environment_unittest.cc',
'test/remote_host_info_fetcher_unittest.cc',
'test/test_chromoting_client_unittest.cc',
- 'test/test_video_renderer_unittest.cc',
],
'conditions': [
[ 'OS=="win"', {
diff --git a/remoting/test/DEPS b/remoting/test/DEPS
index f5971fe..58a26ba 100644
--- a/remoting/test/DEPS
+++ b/remoting/test/DEPS
@@ -2,7 +2,6 @@ include_rules = [
"+jingle/glue",
"+net",
"+remoting/client",
- "+remoting/codec",
"+remoting/host",
"+remoting/protocol",
"+remoting/signaling",
diff --git a/remoting/test/test_video_renderer.cc b/remoting/test/test_video_renderer.cc
index 9a9e66f..864356a 100644
--- a/remoting/test/test_video_renderer.cc
+++ b/remoting/test/test_video_renderer.cc
@@ -4,173 +4,20 @@
#include "remoting/test/test_video_renderer.h"
-#include "base/bind.h"
#include "base/logging.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/thread.h"
-#include "remoting/codec/video_decoder.h"
-#include "remoting/codec/video_decoder_verbatim.h"
-#include "remoting/codec/video_decoder_vpx.h"
#include "remoting/proto/video.pb.h"
-#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
-#include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
namespace remoting {
namespace test {
-// Implements video decoding functionality.
-class TestVideoRenderer::Core {
- public:
- Core();
- ~Core();
-
- // Initializes the internal structures of the class.
- void Initialize();
-
- // Set negotiated session configuration.
- void OnSessionConfig(const protocol::SessionConfig& config);
-
- // Used to decode video packets.
- void ProcessVideoPacket(scoped_ptr<VideoPacket> packet);
-
- // Returns a copy of the current buffer.
- scoped_ptr<webrtc::DesktopFrame> GetBufferForTest() const;
-
- private:
- // Used to ensure TestVideoRenderer::Core methods are called on the same
- // thread.
- base::ThreadChecker thread_checker_;
-
- // Used to decode video packets.
- scoped_ptr<VideoDecoder> decoder_;
-
- // Updated region of the current desktop frame compared to previous one.
- webrtc::DesktopRegion updated_region_;
-
- // Screen size of the remote host.
- webrtc::DesktopSize screen_size_;
-
- // Used to store decoded video frame.
- scoped_ptr<webrtc::DesktopFrame> buffer_;
-
- // Protects access to |buffer_|.
- mutable base::Lock lock_;
-
- DISALLOW_COPY_AND_ASSIGN(Core);
-};
-
-TestVideoRenderer::Core::Core() {
- thread_checker_.DetachFromThread();
-}
-
-TestVideoRenderer::Core::~Core() {
- DCHECK(thread_checker_.CalledOnValidThread());
-}
-
-void TestVideoRenderer::Core::Initialize() {
- DCHECK(thread_checker_.CalledOnValidThread());
-}
-
-void TestVideoRenderer::Core::OnSessionConfig(
- const protocol::SessionConfig& config) {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- protocol::ChannelConfig::Codec codec = config.video_config().codec;
- switch(codec) {
- case protocol::ChannelConfig::CODEC_VP8: {
- DVLOG(2) << "Test Video Renderer will use VP8 decoder";
- decoder_ = VideoDecoderVpx::CreateForVP8();
- break;
- }
- case protocol::ChannelConfig::CODEC_VP9: {
- DVLOG(2) << "Test Video Renderer will use VP9 decoder";
- decoder_ = VideoDecoderVpx::CreateForVP9();
- break;
- }
- case protocol::ChannelConfig::CODEC_VERBATIM: {
- DVLOG(2) << "Test Video Renderer will use VERBATIM decoder";
- decoder_.reset(new VideoDecoderVerbatim());
- break;
- }
- default: {
- NOTREACHED() << "Unsupported codec: " << codec;
- }
- }
-}
-
-scoped_ptr<webrtc::DesktopFrame>
- TestVideoRenderer::Core::GetBufferForTest() const {
- base::AutoLock auto_lock(lock_);
- return make_scoped_ptr(webrtc::BasicDesktopFrame::CopyOf(*buffer_.get()));
-}
-
-void TestVideoRenderer::Core::ProcessVideoPacket(
- scoped_ptr<VideoPacket> packet) {
- DCHECK(thread_checker_.CalledOnValidThread());
- DCHECK(decoder_);
- DCHECK(packet);
-
- DVLOG(2) << "TestVideoRenderer::Core::ProcessVideoPacket() Called";
-
- // Screen size is attached on the first packet as well as when the
- // host screen is resized.
- if (packet->format().has_screen_width() &&
- packet->format().has_screen_height()) {
- webrtc::DesktopSize source_size(packet->format().screen_width(),
- packet->format().screen_height());
- if (!screen_size_.equals(source_size)) {
- screen_size_ = source_size;
- decoder_->Initialize(screen_size_);
- buffer_.reset(new webrtc::BasicDesktopFrame(screen_size_));
- }
- }
-
- // To make life easier, assume that the desktop shape is a single rectangle.
- packet->clear_use_desktop_shape();
- if (!decoder_->DecodePacket(*packet.get())) {
- LOG(ERROR) << "Decoder::DecodePacket() failed.";
- return;
- }
- {
- base::AutoLock auto_lock(lock_);
-
- // Render the decoded packet and write results to the buffer.
- // Note that the |updated_region_| maintains the changed regions compared to
- // previous video frame.
- decoder_->RenderFrame(screen_size_,
- webrtc::DesktopRect::MakeWH(screen_size_.width(),
- screen_size_.height()), buffer_->data(),
- buffer_->stride(), &updated_region_);
- }
-}
-
-TestVideoRenderer::TestVideoRenderer()
- : core_(new Core()),
- video_decode_thread_(
- new base::Thread("TestVideoRendererVideoDecodingThread")) {
- if (!video_decode_thread_->Start()) {
- LOG(ERROR) << "Cannot start TestVideoRenderer";
- } else {
- video_decode_task_runner_ = video_decode_thread_->task_runner();
- video_decode_task_runner_->PostTask(FROM_HERE, base::Bind(&Core::Initialize,
- base::Unretained(core_.get())));
- }
+TestVideoRenderer::TestVideoRenderer() : video_frames_processed_(0) {
}
TestVideoRenderer::~TestVideoRenderer() {
- DCHECK(thread_checker_.CalledOnValidThread());
-
- video_decode_task_runner_->DeleteSoon(FROM_HERE, core_.release());
-
- // The thread's message loop will run until it runs out of work.
- video_decode_thread_->Stop();
}
void TestVideoRenderer::OnSessionConfig(const protocol::SessionConfig& config) {
DVLOG(2) << "TestVideoRenderer::OnSessionConfig() Called";
- video_decode_task_runner_->PostTask(
- FROM_HERE, base::Bind(&Core::OnSessionConfig,
- base::Unretained(core_.get()), config));
}
ChromotingStats* TestVideoRenderer::GetStats() {
@@ -185,26 +32,17 @@ protocol::VideoStub* TestVideoRenderer::GetVideoStub() {
void TestVideoRenderer::ProcessVideoPacket(scoped_ptr<VideoPacket> video_packet,
const base::Closure& done) {
- DCHECK(video_decode_task_runner_) << "Failed to start video decode thread";
-
- if (video_packet->has_data() && video_packet->data().size() != 0) {
- DVLOG(2) << "process video packet is called!";
-
- // Post video process task to the video decode thread.
- base::Closure process_video_task = base::Bind(
- &TestVideoRenderer::Core::ProcessVideoPacket,
- base::Unretained(core_.get()), base::Passed(&video_packet));
- video_decode_task_runner_->PostTask(FROM_HERE, process_video_task);
+ if (!video_packet->data().empty()) {
+ // If the video frame was not a keep alive frame (i.e. not empty) then
+ // count it.
+ DVLOG(2) << "Video Packet Processed, Total: " << ++video_frames_processed_;
} else {
// Log at a high verbosity level as we receive empty packets frequently and
// they can clutter up the debug output if the level is set too low.
DVLOG(3) << "Empty Video Packet received.";
}
- done.Run();
-}
-scoped_ptr<webrtc::DesktopFrame> TestVideoRenderer::GetBufferForTest() const {
- return core_->GetBufferForTest();
+ done.Run();
}
} // namespace test
diff --git a/remoting/test/test_video_renderer.h b/remoting/test/test_video_renderer.h
index acaa739..fcf122a 100644
--- a/remoting/test/test_video_renderer.h
+++ b/remoting/test/test_video_renderer.h
@@ -5,22 +5,11 @@
#ifndef REMOTING_TEST_TEST_VIDEO_RENDERER_H_
#define REMOTING_TEST_TEST_VIDEO_RENDERER_H_
+#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "media/base/video_frame.h"
#include "remoting/client/video_renderer.h"
-#include "remoting/protocol/session_config.h"
#include "remoting/protocol/video_stub.h"
-namespace base {
-class Thread;
-class SingleThreadTaskRunner;
-}
-
-namespace webrtc {
-class DesktopFrame;
-}
-
namespace remoting {
namespace test {
@@ -35,26 +24,13 @@ class TestVideoRenderer : public VideoRenderer, public protocol::VideoStub {
ChromotingStats* GetStats() override;
protocol::VideoStub* GetVideoStub() override;
+ private:
// protocol::VideoStub interface.
void ProcessVideoPacket(scoped_ptr<VideoPacket> video_packet,
const base::Closure& done) override;
- // Returns a copy of the current buffer.
- scoped_ptr<webrtc::DesktopFrame> GetBufferForTest() const;
-
- private:
- // The actual implementation resides in Core class.
- class Core;
- scoped_ptr<Core> core_;
-
- // Used to ensure TestVideoRenderer methods are called on the same thread.
- base::ThreadChecker thread_checker_;
-
- // Used to decode and process video packets.
- scoped_ptr<base::Thread> video_decode_thread_;
-
- // Used to post tasks to video decode thread.
- scoped_refptr<base::SingleThreadTaskRunner> video_decode_task_runner_;
+ // Track the number of populated video frames which have been received.
+ int video_frames_processed_;
DISALLOW_COPY_AND_ASSIGN(TestVideoRenderer);
};
diff --git a/remoting/test/test_video_renderer_unittest.cc b/remoting/test/test_video_renderer_unittest.cc
deleted file mode 100644
index 7ee9b02..0000000
--- a/remoting/test/test_video_renderer_unittest.cc
+++ /dev/null
@@ -1,247 +0,0 @@
-// Copyright 2015 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 "remoting/test/test_video_renderer.h"
-
-#include <cmath>
-
-#include "base/memory/scoped_vector.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/timer/timer.h"
-#include "media/base/video_frame.h"
-#include "remoting/codec/video_encoder.h"
-#include "remoting/codec/video_encoder_verbatim.h"
-#include "remoting/codec/video_encoder_vpx.h"
-#include "remoting/proto/video.pb.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
-#include "third_party/webrtc/modules/desktop_capture/desktop_region.h"
-
-namespace {
-const int kBytesPerPixel = 4;
-const int kDefaultScreenWidth = 1024;
-const int kDefaultScreenHeight = 768;
-const double kDefaultErrorLimit = 0.02;
-}
-
-namespace remoting {
-namespace test {
-
-// Provides basic functionality for for the TestVideoRenderer Tests below.
-// This fixture also creates an MessageLoop to test decoding video packets.
-class TestVideoRendererTest : public testing::Test {
- public:
- TestVideoRendererTest();
- ~TestVideoRendererTest() override;
-
- // Generate a frame containing a gradient and test decoding of
- // TestVideoRenderer. The original frame is compared to the one obtained from
- // decoding the video packet, and the error at each pixel is the root mean
- // square of the errors in the R, G and B components, each normalized to
- // [0, 1]. This routine checks that the mean error over all pixels do not
- // exceed a given limit.
- void TestVideoPacketProcessing(int screen_width, int screen_height,
- double error_limit) ;
-
- // Generate a basic desktop frame containing a gradient.
- scoped_ptr<webrtc::DesktopFrame> CreateDesktopFrameWithGradient(
- int screen_width, int screen_height) const;
-
- protected:
- // Used to post tasks to the message loop.
- scoped_ptr<base::RunLoop> run_loop_;
-
- // Used to set timeouts and delays.
- scoped_ptr<base::Timer> timer_;
-
- // Manages the decoder and process generated video packets.
- scoped_ptr<TestVideoRenderer> test_video_renderer_;
-
- // Used to encode desktop frames to generate video packets.
- scoped_ptr<VideoEncoder> encoder_;
-
- private:
- // testing::Test interface.
- void SetUp() override;
-
- // return the mean error of two frames.
- double CalculateError(const webrtc::DesktopFrame* original_frame,
- const webrtc::DesktopFrame* decoded_frame) const;
-
- // Fill a desktop frame with a gradient.
- void FillFrameWithGradient(webrtc::DesktopFrame* frame) const;
-
- // The thread's message loop. Valid only when the thread is alive.
- scoped_ptr<base::MessageLoop> message_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(TestVideoRendererTest);
-};
-
-TestVideoRendererTest::TestVideoRendererTest()
- : timer_(new base::Timer(true, false)) {}
-
-TestVideoRendererTest::~TestVideoRendererTest() {}
-
-void TestVideoRendererTest::SetUp() {
- if (!base::MessageLoop::current()) {
- // Create a temporary message loop if the current thread does not already
- // have one.
- message_loop_.reset(new base::MessageLoop);
- }
- test_video_renderer_.reset(new TestVideoRenderer());
-}
-
-void TestVideoRendererTest::TestVideoPacketProcessing(int screen_width,
- int screen_height,
- double error_limit) {
- scoped_ptr<webrtc::DesktopFrame> original_frame =
- CreateDesktopFrameWithGradient(screen_width, screen_height);
- EXPECT_TRUE(original_frame.get());
-
- scoped_ptr<VideoPacket> packet = encoder_->Encode(*original_frame.get());
- test_video_renderer_->ProcessVideoPacket(packet.Pass(),
- base::Bind(&base::DoNothing));
-
- // wait for long enough so that the video packet is decoded and rendered to
- // the buffer.
- run_loop_.reset(new base::RunLoop());
- timer_->Start(FROM_HERE, base::TimeDelta::FromMilliseconds(100),
- run_loop_->QuitClosure());
- run_loop_->Run();
- timer_->Stop();
-
- scoped_ptr<webrtc::DesktopFrame> buffer_copy =
- test_video_renderer_->GetBufferForTest();
- EXPECT_NE(buffer_copy, nullptr);
- double error = CalculateError(original_frame.get(), buffer_copy.get());
- EXPECT_LT(error, error_limit);
-}
-
-double TestVideoRendererTest::CalculateError(
- const webrtc::DesktopFrame* original_frame,
- const webrtc::DesktopFrame* decoded_frame) const {
- // Check size remains the same after encoding and decoding.
- EXPECT_EQ(original_frame->size().width(), decoded_frame->size().width());
- EXPECT_EQ(original_frame->size().height(), decoded_frame->size().height());
- EXPECT_EQ(original_frame->stride(), decoded_frame->stride());
- int screen_width = original_frame->size().width();
- int screen_height = original_frame->size().height();
-
- // Error is calculated as the sum of the square error at each pixel in the
- // R, G and B components, each normalized to [0, 1]
- double error_sum_squares = 0.0;
-
- // The mapping between the position of a pixel on 3-dimensional image
- // (origin at top left corner) and its position in 1-dimensional buffer.
- //
- // _______________
- // | | | stride = 4 * width;
- // | | |
- // | | height | height * stride + width + 0; Red channel.
- // | | | => height * stride + width + 1; Green channel.
- // |------- | height * stride + width + 2; Blue channel.
- // | width |
- // |_______________|
- //
- for (int height = 0; height < screen_height; ++height) {
- uint8_t* original_ptr = original_frame->data() +
- height * original_frame->stride();
- uint8_t* decoded_ptr = decoded_frame->data() +
- height * decoded_frame->stride();
-
- for (int width = 0; width < screen_width; ++width) {
- // Errors are calculated in the R, G, B components.
- for (int j = 0; j < 3; ++j) {
- int offset = kBytesPerPixel * width + j;
- double original_value = static_cast<double>(*(original_ptr + offset));
- double decoded_value = static_cast<double>(*(decoded_ptr + offset));
- double error = original_value - decoded_value;
-
- // Normalize the error to [0, 1].
- error /= 255.0;
- error_sum_squares += error * error;
- }
- }
- }
- return sqrt(error_sum_squares / (3 * screen_width * screen_height));
-}
-
-scoped_ptr<webrtc::DesktopFrame>
- TestVideoRendererTest::CreateDesktopFrameWithGradient(
- int screen_width, int screen_height) const {
- webrtc::DesktopSize screen_size(screen_width, screen_height);
- scoped_ptr<webrtc::DesktopFrame> frame(
- new webrtc::BasicDesktopFrame(screen_size));
- frame->mutable_updated_region()->SetRect(
- webrtc::DesktopRect::MakeSize(screen_size));
- FillFrameWithGradient(frame.get());
- return frame.Pass();
-}
-
-void TestVideoRendererTest::FillFrameWithGradient(
- webrtc::DesktopFrame* frame) const {
- for (int y = 0; y < frame->size().height(); ++y) {
- uint8* p = frame->data() + y * frame->stride();
- for (int x = 0; x < frame->size().width(); ++x) {
- *p++ = (255.0 * x) / frame->size().width();
- *p++ = (164.0 * y) / frame->size().height();
- *p++ = (82.0 * (x + y)) /
- (frame->size().width() + frame->size().height());
- *p++ = 0;
- }
- }
-}
-
-// Verify video packets are processed correctly.
-TEST_F(TestVideoRendererTest, VerifyVideoProcessing) {
- encoder_ = VideoEncoderVpx::CreateForVP8();
- scoped_ptr<protocol::SessionConfig> config =
- protocol::SessionConfig::ForTest();
- test_video_renderer_->OnSessionConfig(*config.get());
-
- TestVideoPacketProcessing(kDefaultScreenWidth, kDefaultScreenHeight,
- kDefaultErrorLimit);
-
- // Post multiple tasks to |test_video_renderer_|, and it should not crash.
- // 20 is chosen because it's large enough to make sure that there will be
- // more than one task on the video decode thread, while not too large to wait
- // for too long for the unit test to complete.
- int task_num = 20;
- ScopedVector<VideoPacket> video_packets;
- for (int i = 0; i < task_num; ++i){
- scoped_ptr<webrtc::DesktopFrame> original_frame =
- CreateDesktopFrameWithGradient(kDefaultScreenWidth,
- kDefaultScreenHeight);
- video_packets.push_back(encoder_->Encode(*original_frame.get()));
- }
-
- for (int i = 0; i < task_num; ++i) {
- // Transfer ownership of video packet.
- VideoPacket* packet = video_packets[i];
- video_packets[i] = nullptr;
- test_video_renderer_->ProcessVideoPacket(make_scoped_ptr(packet),
- base::Bind(&base::DoNothing));
- }
-}
-
-// Verify video packet size change is handled properly.
-TEST_F(TestVideoRendererTest, VerifyVideoPacketSizeChange) {
- encoder_ = VideoEncoderVpx::CreateForVP8();
- scoped_ptr<protocol::SessionConfig> config =
- protocol::SessionConfig::ForTest();
- test_video_renderer_->OnSessionConfig(*config.get());
-
- TestVideoPacketProcessing(kDefaultScreenWidth, kDefaultScreenHeight,
- kDefaultErrorLimit);
-
- TestVideoPacketProcessing(2 * kDefaultScreenWidth, 2 * kDefaultScreenHeight,
- kDefaultErrorLimit);
-
- TestVideoPacketProcessing(kDefaultScreenWidth / 2, kDefaultScreenHeight / 2,
- kDefaultErrorLimit);
-}
-
-} // namespace test
-} // namespace remoting