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