Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(253)

Side by Side Diff: media/gpu/h264_decoder_unittest.cc

Issue 2760513002: h264_decoder_unittests: Initial Change. (Closed)
Patch Set: Rebase Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/gpu/BUILD.gn ('k') | media/gpu/h264_dpb.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2017 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.
4
5 #include <stdint.h>
6 #include <string.h>
7
8 #include <memory>
9 #include <queue>
10 #include <string>
11
12 #include "base/command_line.h"
13 #include "base/files/file_util.h"
14 #include "base/logging.h"
15 #include "media/base/test_data_util.h"
16 #include "media/gpu/h264_decoder.h"
17 #include "testing/gmock/include/gmock/gmock.h"
18 #include "testing/gtest/include/gtest/gtest.h"
19
20 using ::testing::_;
21 using ::testing::Expectation;
22 using ::testing::InSequence;
23 using ::testing::Invoke;
24 using ::testing::MakeMatcher;
25 using ::testing::Matcher;
26 using ::testing::MatcherInterface;
27 using ::testing::MatchResultListener;
28 using ::testing::Mock;
29 using ::testing::Return;
30
31 namespace media {
32 namespace {
33
34 const std::string kBaselineFrame0 = "bear-320x192-baseline-frame-0.h264";
35 const std::string kBaselineFrame1 = "bear-320x192-baseline-frame-1.h264";
36 const std::string kBaselineFrame2 = "bear-320x192-baseline-frame-2.h264";
37 const std::string kBaselineFrame3 = "bear-320x192-baseline-frame-3.h264";
38 const std::string kHighFrame0 = "bear-320x192-high-frame-0.h264";
39 const std::string kHighFrame1 = "bear-320x192-high-frame-1.h264";
40 const std::string kHighFrame2 = "bear-320x192-high-frame-2.h264";
41 const std::string kHighFrame3 = "bear-320x192-high-frame-3.h264";
42
43 class MockH264Accelerator : public H264Decoder::H264Accelerator {
44 public:
45 MockH264Accelerator() {}
46
47 MOCK_METHOD0(CreateH264Picture, scoped_refptr<H264Picture>());
48 MOCK_METHOD1(SubmitDecode, bool(const scoped_refptr<H264Picture>& pic));
49 MOCK_METHOD1(OutputPicture, bool(const scoped_refptr<H264Picture>& pic));
50
51 bool SubmitFrameMetadata(const H264SPS* sps,
52 const H264PPS* pps,
53 const H264DPB& dpb,
54 const H264Picture::Vector& ref_pic_listp0,
55 const H264Picture::Vector& ref_pic_listb0,
56 const H264Picture::Vector& ref_pic_listb1,
57 const scoped_refptr<H264Picture>& pic) override {
58 return true;
59 }
60
61 bool SubmitSlice(const H264PPS* pps,
62 const H264SliceHeader* slice_hdr,
63 const H264Picture::Vector& ref_pic_list0,
64 const H264Picture::Vector& ref_pic_list1,
65 const scoped_refptr<H264Picture>& pic,
66 const uint8_t* data,
67 size_t size) override {
68 return true;
69 }
70
71 void Reset() override {}
72 };
73
74 // Test H264Decoder by feeding different of h264 frame sequences and make
75 // sure it behaves as expected.
76 class H264DecoderTest : public ::testing::Test {
77 public:
78 H264DecoderTest() = default;
79
80 void SetUp() override;
81
82 // Sets the bitstreams to be decoded, frame by frame. The content of each
83 // file is the encoded bitstream of a single video frame.
84 void SetInputFrameFiles(const std::vector<std::string>& frame_files);
85
86 // Keeps decoding the input bitstream set at |SetInputFrameFiles| until the
87 // decoder has consumed all bitstreams or returned from
88 // |H264Decoder::Decode|. Returns the same result as |H264Decoder::Decode|.
89 AcceleratedVideoDecoder::DecodeResult Decode();
90
91 protected:
92 std::unique_ptr<H264Decoder> decoder_;
93 MockH264Accelerator accelerator_;
94
95 private:
96 std::queue<std::string> input_frame_files_;
97 std::string bitstream_;
98 };
99
100 void H264DecoderTest::SetUp() {
101 decoder_.reset(new H264Decoder(&accelerator_));
102
103 // Sets default behaviors for mock methods for convenience.
104 ON_CALL(accelerator_, CreateH264Picture()).WillByDefault(Invoke([]() {
105 return new H264Picture();
106 }));
107 ON_CALL(accelerator_, SubmitDecode(_)).WillByDefault(Return(true));
108 ON_CALL(accelerator_, OutputPicture(_)).WillByDefault(Return(true));
109 }
110
111 void H264DecoderTest::SetInputFrameFiles(
112 const std::vector<std::string>& input_frame_files) {
113 for (auto f : input_frame_files)
114 input_frame_files_.push(f);
115 }
116
117 AcceleratedVideoDecoder::DecodeResult H264DecoderTest::Decode() {
118 while (true) {
119 auto result = decoder_->Decode();
120 if (result != AcceleratedVideoDecoder::kRanOutOfStreamData ||
121 input_frame_files_.empty())
122 return result;
123 auto input_file = GetTestDataFilePath(input_frame_files_.front());
124 input_frame_files_.pop();
125 CHECK(base::ReadFileToString(input_file, &bitstream_));
126 decoder_->SetStream(reinterpret_cast<const uint8_t*>(bitstream_.data()),
127 bitstream_.size());
128 }
129 }
130
131 // To have better description on mismatch.
132 class WithPocMatcher
133 : public MatcherInterface<const scoped_refptr<H264Picture>&> {
134 public:
135 explicit WithPocMatcher(int expected_poc) : expected_poc_(expected_poc) {}
136
137 bool MatchAndExplain(const scoped_refptr<H264Picture>& p,
138 MatchResultListener* listener) const override {
139 if (p->pic_order_cnt == expected_poc_)
140 return true;
141 *listener << "with poc: " << p->pic_order_cnt;
142 return false;
143 }
144
145 void DescribeTo(std::ostream* os) const override {
146 *os << "with poc " << expected_poc_;
147 }
148
149 private:
150 int expected_poc_;
151 };
152
153 inline Matcher<const scoped_refptr<H264Picture>&> WithPoc(int expected_poc) {
154 return MakeMatcher(new WithPocMatcher(expected_poc));
155 }
156
157 // Test Cases
158
159 TEST_F(H264DecoderTest, DecodeSingleFrame) {
160 SetInputFrameFiles({kBaselineFrame0});
161 ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode());
162 EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
163 EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
164
165 EXPECT_CALL(accelerator_, CreateH264Picture()).WillOnce(Return(nullptr));
166 ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfSurfaces, Decode());
167 ASSERT_TRUE(Mock::VerifyAndClearExpectations(&accelerator_));
168
169 {
170 InSequence sequence;
171 EXPECT_CALL(accelerator_, CreateH264Picture());
172 EXPECT_CALL(accelerator_, SubmitDecode(_));
173 EXPECT_CALL(accelerator_, OutputPicture(_));
174 }
175 ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
176 ASSERT_TRUE(decoder_->Flush());
177 }
178
179 TEST_F(H264DecoderTest, SkipNonIDRFrames) {
180 SetInputFrameFiles({kBaselineFrame1, kBaselineFrame2, kBaselineFrame0});
181 ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode());
182 EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
183 EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
184 {
185 InSequence sequence;
186 EXPECT_CALL(accelerator_, CreateH264Picture());
187 EXPECT_CALL(accelerator_, SubmitDecode(_));
188 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0)));
189 }
190 ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
191 ASSERT_TRUE(decoder_->Flush());
192 }
193
194 TEST_F(H264DecoderTest, DecodeProfileBaseline) {
195 SetInputFrameFiles({
196 kBaselineFrame0, kBaselineFrame1, kBaselineFrame2, kBaselineFrame3,
197 });
198 ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode());
199 EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
200 EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
201
202 EXPECT_CALL(accelerator_, CreateH264Picture()).Times(4);
203 Expectation decode_poc0, decode_poc2, decode_poc4, decode_poc6;
204 {
205 InSequence decode_order;
206 decode_poc0 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(0)));
207 decode_poc2 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(2)));
208 decode_poc4 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(4)));
209 decode_poc6 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(6)));
210 }
211 {
212 InSequence display_order;
213 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0))).After(decode_poc0);
214 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(2))).After(decode_poc2);
215 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(4))).After(decode_poc4);
216 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(6))).After(decode_poc6);
217 }
218 ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
219 ASSERT_TRUE(decoder_->Flush());
220 }
221
222 TEST_F(H264DecoderTest, DecodeProfileHigh) {
223 SetInputFrameFiles({kHighFrame0, kHighFrame1, kHighFrame2, kHighFrame3});
224 ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode());
225 EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
226 EXPECT_LE(16u, decoder_->GetRequiredNumOfPictures());
227
228 // Two pictures will be kept in DPB for reordering. The first picture should
229 // be outputted after feeding the third frame.
230 EXPECT_CALL(accelerator_, CreateH264Picture()).Times(4);
231 Expectation decode_poc0, decode_poc2, decode_poc4, decode_poc6;
232 {
233 InSequence decode_order;
234 decode_poc0 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(0)));
235 decode_poc4 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(4)));
236 decode_poc2 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(2)));
237 decode_poc6 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(6)));
238 }
239 {
240 InSequence display_order;
241 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0))).After(decode_poc0);
242 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(2))).After(decode_poc2);
243 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(4))).After(decode_poc4);
244 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(6))).After(decode_poc6);
245 }
246 ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
247 ASSERT_TRUE(decoder_->Flush());
248 }
249
250 TEST_F(H264DecoderTest, SwitchBaselineToHigh) {
251 SetInputFrameFiles({
252 kBaselineFrame0, kHighFrame0, kHighFrame1, kHighFrame2, kHighFrame3,
253 });
254 ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode());
255 EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
256 EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
257
258 EXPECT_CALL(accelerator_, CreateH264Picture());
259 {
260 InSequence sequence;
261 EXPECT_CALL(accelerator_, SubmitDecode(_));
262 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0)));
263 }
264 ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode());
265 EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
266 EXPECT_LE(16u, decoder_->GetRequiredNumOfPictures());
267
268 ASSERT_TRUE(Mock::VerifyAndClearExpectations(&accelerator_));
269
270 EXPECT_CALL(accelerator_, CreateH264Picture()).Times(4);
271 Expectation decode_poc0, decode_poc2, decode_poc4, decode_poc6;
272 {
273 InSequence decode_order;
274 decode_poc0 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(0)));
275 decode_poc4 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(4)));
276 decode_poc2 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(2)));
277 decode_poc6 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(6)));
278 }
279 {
280 InSequence display_order;
281 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0))).After(decode_poc0);
282 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(2))).After(decode_poc2);
283 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(4))).After(decode_poc4);
284 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(6))).After(decode_poc6);
285 }
286 ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
287 ASSERT_TRUE(decoder_->Flush());
288 }
289
290 TEST_F(H264DecoderTest, SwitchHighToBaseline) {
291 SetInputFrameFiles({
292 kHighFrame0, kBaselineFrame0, kBaselineFrame1, kBaselineFrame2,
293 kBaselineFrame3,
294 });
295 ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode());
296 EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
297 EXPECT_LE(16u, decoder_->GetRequiredNumOfPictures());
298
299 EXPECT_CALL(accelerator_, CreateH264Picture());
300 {
301 InSequence sequence;
302 EXPECT_CALL(accelerator_, SubmitDecode(_));
303 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0)));
304 }
305 ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode());
306 EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
307 EXPECT_LE(9u, decoder_->GetRequiredNumOfPictures());
308
309 ASSERT_TRUE(Mock::VerifyAndClearExpectations(&accelerator_));
310
311 EXPECT_CALL(accelerator_, CreateH264Picture()).Times(4);
312 Expectation decode_poc0, decode_poc2, decode_poc4, decode_poc6;
313 {
314 InSequence decode_order;
315 decode_poc0 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(0)));
316 decode_poc2 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(2)));
317 decode_poc4 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(4)));
318 decode_poc6 = EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(6)));
319 }
320 {
321 InSequence display_order;
322 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0))).After(decode_poc0);
323 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(2))).After(decode_poc2);
324 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(4))).After(decode_poc4);
325 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(6))).After(decode_poc6);
326 }
327 ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
328 ASSERT_TRUE(decoder_->Flush());
329 }
330
331 } // namespace
332 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/BUILD.gn ('k') | media/gpu/h264_dpb.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698