OLD | NEW |
---|---|
(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_EQ(15U, 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_EQ(15U, decoder_->GetRequiredNumOfPictures()); | |
Pawel Osciak
2017/06/29 04:57:44
Perhaps EXPECT_GE(9u, ) to ensure at least the min
Owen Lin
2017/06/29 05:19:50
Done.
| |
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_EQ(15U, 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_EQ(22U, decoder_->GetRequiredNumOfPictures()); | |
Pawel Osciak
2017/06/29 04:57:44
GE 16U and everywhere for high please.
Owen Lin
2017/06/29 05:19:50
Done. Thank you.
| |
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_EQ(15U, 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_EQ(22U, 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_EQ(22U, 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_EQ(15U, 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 | |
OLD | NEW |