1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "remoting/codec/video_encoder_vpx.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "remoting/codec/codec_test.h"
12 #include "remoting/proto/video.pb.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "third_party/webrtc/modules/desktop_capture/desktop_frame.h"
18 // xRGB pixel colors for use by tests.
19 const uint32 kBlueColor
= 0x0000ff;
20 const uint32 kGreenColor
= 0x00ff00;
22 // Creates a frame stippled between blue and red pixels, which is useful for
23 // lossy/lossless encode and color tests. By default all pixels in the frame
24 // are included in the updated_region().
25 static scoped_ptr
<webrtc::DesktopFrame
> CreateTestFrame(
26 const webrtc::DesktopSize
& frame_size
) {
27 scoped_ptr
<webrtc::DesktopFrame
> frame(
28 new webrtc::BasicDesktopFrame(frame_size
));
29 for (int x
= 0; x
< frame_size
.width(); ++x
) {
30 for (int y
= 0; y
< frame_size
.height(); ++y
) {
31 uint8
* pixel_u8
= frame
->data() + (y
* frame
->stride()) +
32 (x
* webrtc::DesktopFrame::kBytesPerPixel
);
33 *(reinterpret_cast<uint32
*>(pixel_u8
)) =
34 ((x
+ y
) & 1) ? kGreenColor
: kBlueColor
;
37 frame
->mutable_updated_region()->SetRect(
38 webrtc::DesktopRect::MakeSize(frame_size
));
42 TEST(VideoEncoderVpxTest
, Vp8
) {
43 scoped_ptr
<VideoEncoderVpx
> encoder(VideoEncoderVpx::CreateForVP8());
44 TestVideoEncoder(encoder
.get(), false);
47 TEST(VideoEncoderVpxTest
, Vp9
) {
48 scoped_ptr
<VideoEncoderVpx
> encoder(VideoEncoderVpx::CreateForVP9());
49 // VP9 encoder defaults to lossless encode and lossy (I420) color.
50 TestVideoEncoder(encoder
.get(), false);
53 // Test that the VP9 encoder can switch between lossy & lossless encode.
54 TEST(VideoEncoderVpxTest
, Vp9LossyEncodeSwitching
) {
55 scoped_ptr
<VideoEncoderVpx
> encoder(VideoEncoderVpx::CreateForVP9());
57 webrtc::DesktopSize
frame_size(100, 100);
58 scoped_ptr
<webrtc::DesktopFrame
> frame(CreateTestFrame(frame_size
));
60 // Lossy encode the first frame.
61 encoder
->SetLosslessEncode(false);
62 scoped_ptr
<VideoPacket
> lossy_packet
= encoder
->Encode(*frame
);
64 // Lossless encode the second frame.
65 encoder
->SetLosslessEncode(true);
66 scoped_ptr
<VideoPacket
> lossless_packet
= encoder
->Encode(*frame
);
67 // Lossless encode is so good that the frames are smaller than the lossy
68 // encodes. This comparison needs to be revisited.
69 // http://crbug.com/439166
70 // EXPECT_GT(lossless_packet->data().size(), lossy_packet->data().size());
72 // Lossy encode one more frame.
73 encoder
->SetLosslessEncode(false);
74 lossy_packet
= encoder
->Encode(*frame
);
76 // EXPECT_LT(lossy_packet->data().size(), lossless_packet->data().size());
79 // Test that the VP9 encoder can switch between lossy & lossless color.
80 TEST(VideoEncoderVpxTest
, Vp9LossyColorSwitching
) {
81 scoped_ptr
<VideoEncoderVpx
> encoder(VideoEncoderVpx::CreateForVP9());
83 webrtc::DesktopSize
frame_size(100, 100);
84 scoped_ptr
<webrtc::DesktopFrame
> frame(CreateTestFrame(frame_size
));
86 // Lossy encode the first frame.
87 encoder
->SetLosslessColor(false);
88 scoped_ptr
<VideoPacket
> lossy_packet
= encoder
->Encode(*frame
);
90 // Lossless encode the second frame.
91 encoder
->SetLosslessColor(true);
92 scoped_ptr
<VideoPacket
> lossless_packet
= encoder
->Encode(*frame
);
94 // Lossy encode one more frame.
95 encoder
->SetLosslessColor(false);
96 lossy_packet
= encoder
->Encode(*frame
);
99 // Test that the VP8 encoder ignores lossless modes without crashing.
100 TEST(VideoEncoderVpxTest
, Vp8IgnoreLossy
) {
101 scoped_ptr
<VideoEncoderVpx
> encoder(VideoEncoderVpx::CreateForVP8());
103 webrtc::DesktopSize
frame_size(100, 100);
104 scoped_ptr
<webrtc::DesktopFrame
> frame(CreateTestFrame(frame_size
));
106 // Encode a frame, to give the encoder a chance to crash if misconfigured.
107 encoder
->SetLosslessEncode(true);
108 encoder
->SetLosslessColor(true);
109 scoped_ptr
<VideoPacket
> packet
= encoder
->Encode(*frame
);
113 // Test that calling Encode with a larger frame size than the initial one
114 // does not cause VP8 to crash.
115 TEST(VideoEncoderVpxTest
, Vp8SizeChangeNoCrash
) {
116 webrtc::DesktopSize
frame_size(100, 100);
118 scoped_ptr
<VideoEncoderVpx
> encoder(VideoEncoderVpx::CreateForVP8());
120 // Create first frame & encode it.
121 scoped_ptr
<webrtc::DesktopFrame
> frame(CreateTestFrame(frame_size
));
122 scoped_ptr
<VideoPacket
> packet
= encoder
->Encode(*frame
);
125 // Double the size of the frame, and updated region, and encode again.
126 frame_size
.set(frame_size
.width() * 2, frame_size
.height() * 2);
127 frame
= CreateTestFrame(frame_size
);
128 packet
= encoder
->Encode(*frame
);
132 // Test that calling Encode with a larger frame size than the initial one
133 // does not cause VP9 to crash.
134 TEST(VideoEncoderVpxTest
, Vp9SizeChangeNoCrash
) {
135 webrtc::DesktopSize
frame_size(100, 100);
137 scoped_ptr
<VideoEncoderVpx
> encoder(VideoEncoderVpx::CreateForVP9());
139 // Create first frame & encode it.
140 scoped_ptr
<webrtc::DesktopFrame
> frame(CreateTestFrame(frame_size
));
141 scoped_ptr
<VideoPacket
> packet
= encoder
->Encode(*frame
);
144 // Double the size of the frame, and updated region, and encode again.
145 frame_size
.set(frame_size
.width() * 2, frame_size
.height() * 2);
146 frame
= CreateTestFrame(frame_size
);
147 packet
= encoder
->Encode(*frame
);
151 // Test that the DPI information is correctly propagated from the
152 // media::ScreenCaptureData to the VideoPacket.
153 TEST(VideoEncoderVpxTest
, DpiPropagation
) {
154 webrtc::DesktopSize
frame_size(32, 32);
156 scoped_ptr
<VideoEncoderVpx
> encoder(VideoEncoderVpx::CreateForVP8());
158 scoped_ptr
<webrtc::DesktopFrame
> frame(CreateTestFrame(frame_size
));
159 frame
->set_dpi(webrtc::DesktopVector(96, 97));
160 scoped_ptr
<VideoPacket
> packet
= encoder
->Encode(*frame
);
161 EXPECT_EQ(packet
->format().x_dpi(), 96);
162 EXPECT_EQ(packet
->format().y_dpi(), 97);
165 TEST(VideoEncoderVpxTest
, Vp8EncodeUnchangedFrame
) {
166 scoped_ptr
<VideoEncoderVpx
> encoder(VideoEncoderVpx::CreateForVP8());
167 TestVideoEncoderEmptyFrames(encoder
.get(), 0);
170 TEST(VideoEncoderVpxTest
, Vp9LosslessUnchangedFrame
) {
171 scoped_ptr
<VideoEncoderVpx
> encoder(VideoEncoderVpx::CreateForVP9());
172 encoder
->SetLosslessEncode(true);
173 TestVideoEncoderEmptyFrames(encoder
.get(), 0);
176 TEST(VideoEncoderVpxTest
, Vp9LossyUnchangedFrame
) {
177 scoped_ptr
<VideoEncoderVpx
> encoder(VideoEncoderVpx::CreateForVP9());
178 encoder
->SetLosslessEncode(false);
179 // Expect that VP9+CR should generate no more than 10 top-off frames
180 // per cycle, and take no more than 2 cycles to top-off.
181 TestVideoEncoderEmptyFrames(encoder
.get(), 20);
184 } // namespace remoting