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/bind.h" | |
13 #include "base/command_line.h" | |
14 #include "base/files/file_util.h" | |
15 #include "base/logging.h" | |
16 #include "base/strings/stringprintf.h" | |
17 #include "media/base/test_data_util.h" | |
18 #include "media/gpu/h264_decoder.h" | |
19 #include "testing/gtest/include/gtest/gtest.h" | |
20 | |
21 namespace media { | |
22 namespace { | |
23 | |
24 const std::string kBaselineFrame0 = "bear-320x192-baseline-frame-0.h264"; | |
25 const std::string kBaselineFrame1 = "bear-320x192-baseline-frame-1.h264"; | |
26 const std::string kBaselineFrame2 = "bear-320x192-baseline-frame-2.h264"; | |
27 const std::string kBaselineFrame3 = "bear-320x192-baseline-frame-3.h264"; | |
28 const std::string kHighFrame0 = "bear-320x192-high-frame-0.h264"; | |
29 const std::string kHighFrame1 = "bear-320x192-high-frame-1.h264"; | |
30 const std::string kHighFrame2 = "bear-320x192-high-frame-2.h264"; | |
31 const std::string kHighFrame3 = "bear-320x192-high-frame-3.h264"; | |
32 | |
33 class FakeH264Accelerator; | |
34 | |
35 // Test H264Decoder by feeding different of h264 frame sequences and make | |
36 // sure it behaves as expected. | |
37 class H264DecoderTest : public ::testing::Test { | |
38 public: | |
39 // The events we used to verify the correctness. Will check if these | |
40 // events are triggers in order. | |
Pawel Osciak
2017/06/23 02:07:34
s/triggers/triggered/
Also probably s/in order/at
Owen Lin
2017/06/26 09:09:00
The code is refactored out.
| |
41 enum class EventType { | |
Pawel Osciak
2017/06/23 02:07:34
Could this be inside the Event class still?
Owen Lin
2017/06/26 09:09:00
Ditto.
| |
42 CREATE_H264_PICTURE, | |
43 SUBMIT_DECODE, | |
44 OUTPUT_PICTURE, | |
45 RAN_OUT_OF_SURFACES, | |
46 NEED_CONTEXT_UPDATE, | |
47 ALLOCATE_NEW_SURFACES, | |
48 DECODE_ERROR, | |
49 }; | |
50 | |
51 struct Event { | |
52 EventType type; | |
53 | |
54 explicit Event(EventType type) : type(type) {} | |
55 virtual std::string ToString() const; | |
56 }; | |
57 | |
58 // The specialize Event for OutputPicture as we will also check the POC. | |
59 struct OutputPictureEvent : public Event { | |
60 int pic_order_cnt; | |
61 | |
62 OutputPictureEvent(int pic_order_cnt) | |
63 : Event(EventType::OUTPUT_PICTURE), pic_order_cnt(pic_order_cnt) {} | |
64 | |
65 std::string ToString() const override; | |
66 }; | |
67 | |
68 // Function called when an event dispatch to the test. | |
69 using EventHandler = base::Callback<void(const Event& event)>; | |
Pawel Osciak
2017/06/23 02:07:34
Nit: OnceCallback?
Owen Lin
2017/06/26 09:09:00
Done.
| |
70 | |
71 H264DecoderTest() = default; | |
72 | |
73 void SetUp() override; | |
74 | |
75 // Helper function to feed bitstreams. | |
76 void FeedData(const std::vector<std::string>& frames); | |
77 | |
78 // Called when an event happens. | |
79 void OnEvent(const Event& event); | |
80 | |
81 // A candy function to call OnEvent(Event(type)). | |
82 void OnEvent(const EventType type); | |
83 | |
84 // Expects the specified event will be dispatched to the test. When it | |
85 // happens, handler will be called. The expected events will be queued. | |
86 // This function could be called multiple times and we expect those | |
87 // events will happen in order. | |
88 void ExpectEvent(EventType type, const EventHandler& handler = {}); | |
Pawel Osciak
2017/06/23 02:07:34
To be honest it took me a bit to understand the id
Owen Lin
2017/06/26 09:09:00
Same. Code has been removed.
| |
89 | |
90 void ExpectEvent(EventType type, const base::Closure& closure); | |
Pawel Osciak
2017/06/23 02:07:34
... this ExpectEventAndRun() ?
Do we also need to
Owen Lin
2017/06/26 09:09:00
Ditto.
| |
91 | |
92 // Expects the decoder output a picture with the specified POC.. | |
93 void ExpectOutputPictureWithPoc(int expected_poc); | |
94 | |
95 // Expects the decoder request for new surfaces of the expected size. | |
96 void ExpectAllocateNewSurfaces(const gfx::Size& size); | |
97 | |
98 // Gets the number of remaining expected events. | |
99 size_t number_of_expected_events() const { return expected_events_.size(); } | |
100 | |
101 protected: | |
102 std::unique_ptr<H264Decoder> decoder_; | |
103 std::unique_ptr<FakeH264Accelerator> accelerator_; | |
104 | |
105 private: | |
106 struct ExpectedEvent { | |
107 EventType type; | |
108 EventHandler handler; | |
109 | |
110 ExpectedEvent(EventType type, const EventHandler& handler) | |
111 : type(type), handler(handler) {} | |
112 }; | |
113 | |
114 std::queue<ExpectedEvent> expected_events_; | |
115 | |
116 static void TestOutputPictureEvent(int expected_poc, const Event& e); | |
117 void TestAllocateNewSurfaceEvent(const gfx::Size& size); | |
118 }; | |
119 | |
120 class FakeH264Accelerator : public H264Decoder::H264Accelerator { | |
121 public: | |
122 FakeH264Accelerator(H264DecoderTest* test) : test_(test) {} | |
123 | |
124 scoped_refptr<H264Picture> CreateH264Picture() override { | |
125 if (new_picture_quota_ > 0) { | |
126 --new_picture_quota_; | |
127 return new H264Picture(); | |
128 } | |
129 return nullptr; | |
130 } | |
131 | |
132 // Implementations of H264Decoder::H264Accelerator interface. | |
133 | |
134 bool SubmitFrameMetadata(const H264SPS* sps, | |
135 const H264PPS* pps, | |
136 const H264DPB& dpb, | |
137 const H264Picture::Vector& ref_pic_listp0, | |
138 const H264Picture::Vector& ref_pic_listb0, | |
139 const H264Picture::Vector& ref_pic_listb1, | |
140 const scoped_refptr<H264Picture>& pic) override { | |
141 return true; | |
142 } | |
143 | |
144 bool SubmitSlice(const H264PPS* pps, | |
145 const H264SliceHeader* slice_hdr, | |
146 const H264Picture::Vector& ref_pic_list0, | |
147 const H264Picture::Vector& ref_pic_list1, | |
148 const scoped_refptr<H264Picture>& pic, | |
149 const uint8_t* data, | |
150 size_t size) override { | |
151 return true; | |
152 } | |
153 | |
154 bool SubmitDecode(const scoped_refptr<H264Picture>& pic) override { | |
155 test_->OnEvent(H264DecoderTest::EventType::SUBMIT_DECODE); | |
156 return true; | |
157 } | |
158 | |
159 bool OutputPicture(const scoped_refptr<H264Picture>& pic) override { | |
160 test_->OnEvent(H264DecoderTest::OutputPictureEvent(pic->pic_order_cnt)); | |
161 return true; | |
162 } | |
163 | |
164 void Reset() override {} | |
165 | |
166 // How many times CreateH264Picture() will returns valid H264Picture. | |
167 void SetNewPictureQuota(size_t quota) { new_picture_quota_ = quota; } | |
168 | |
169 size_t GetNewPictureQuota() const { return new_picture_quota_; } | |
170 | |
171 private: | |
172 H264DecoderTest* test_; | |
173 size_t new_picture_quota_ = 0; | |
174 }; | |
175 | |
176 std::string H264DecoderTest::Event::ToString() const { | |
177 switch (type) { | |
178 case EventType::CREATE_H264_PICTURE: | |
179 return "CreateH264Picture"; | |
180 case EventType::SUBMIT_DECODE: | |
181 return "SubmitDecode"; | |
182 case EventType::OUTPUT_PICTURE: | |
183 return "OutputPicture"; | |
184 case EventType::RAN_OUT_OF_SURFACES: | |
185 return "RanOutOfSurfaces"; | |
186 case EventType::NEED_CONTEXT_UPDATE: | |
187 return "NeedContextUpdate"; | |
188 case EventType::ALLOCATE_NEW_SURFACES: | |
189 return "AllocateNewSurfaces"; | |
190 case EventType::DECODE_ERROR: | |
191 return "DecodeError"; | |
192 } | |
193 NOTREACHED(); | |
194 } | |
195 | |
196 std::string H264DecoderTest::OutputPictureEvent::ToString() const { | |
197 return base::StringPrintf("%s (poc=%d)", Event::ToString().c_str(), | |
198 pic_order_cnt); | |
199 } | |
200 | |
201 void H264DecoderTest::SetUp() { | |
202 accelerator_.reset(new FakeH264Accelerator(this)); | |
203 decoder_.reset(new H264Decoder(accelerator_.get())); | |
204 } | |
205 | |
206 void H264DecoderTest::FeedData(const std::vector<std::string>& frames) { | |
207 std::string bitstream; | |
208 auto frame_iter = frames.begin(); | |
209 while (true) { | |
210 switch (decoder_->Decode()) { | |
211 case AcceleratedVideoDecoder::kAllocateNewSurfaces: | |
212 ASSERT_NO_FATAL_FAILURE( | |
213 OnEvent(Event(EventType::ALLOCATE_NEW_SURFACES))); | |
214 break; | |
215 case AcceleratedVideoDecoder::kRanOutOfStreamData: { | |
216 if (frame_iter == frames.end()) | |
217 return; | |
218 base::FilePath input_file = GetTestDataFilePath(*frame_iter++); | |
219 ASSERT_TRUE(base::ReadFileToString(input_file, &bitstream)) | |
220 << "failed to read input data from " << input_file.value(); | |
221 decoder_->SetStream(reinterpret_cast<const uint8_t*>(bitstream.data()), | |
222 bitstream.size()); | |
223 break; | |
224 } | |
225 case AcceleratedVideoDecoder::kRanOutOfSurfaces: | |
226 ASSERT_NO_FATAL_FAILURE(OnEvent(EventType::RAN_OUT_OF_SURFACES)); | |
227 break; | |
228 case AcceleratedVideoDecoder::kNeedContextUpdate: | |
229 ASSERT_NO_FATAL_FAILURE(OnEvent(EventType::NEED_CONTEXT_UPDATE)); | |
230 break; | |
231 case AcceleratedVideoDecoder::kDecodeError: | |
232 ASSERT_NO_FATAL_FAILURE(OnEvent(EventType::DECODE_ERROR)); | |
233 break; | |
234 } | |
235 } | |
236 } | |
237 | |
238 void H264DecoderTest::OnEvent(const Event& event) { | |
239 VLOG(2) << "OnEvent(" << event.ToString() << ")"; | |
240 ASSERT_FALSE(expected_events_.empty()) << "Unexpected event"; | |
241 ExpectedEvent ee = expected_events_.front(); | |
242 expected_events_.pop(); | |
243 ASSERT_EQ(ee.type, event.type); | |
244 if (ee.handler) | |
245 ASSERT_NO_FATAL_FAILURE(ee.handler.Run(event)); | |
246 } | |
247 | |
248 void H264DecoderTest::OnEvent(EventType type) { | |
249 OnEvent(Event(type)); | |
250 } | |
251 | |
252 void H264DecoderTest::ExpectEvent(EventType type, const EventHandler& handler) { | |
253 expected_events_.push({type, handler}); | |
254 } | |
255 | |
256 static void RunClosureAndIgnoreEvent(const base::Closure& closure, | |
257 const H264DecoderTest::Event&) { | |
258 closure.Run(); | |
259 } | |
260 | |
261 void H264DecoderTest::ExpectEvent(EventType type, | |
262 const base::Closure& closure) { | |
263 ExpectEvent(type, base::Bind(RunClosureAndIgnoreEvent, closure)); | |
Pawel Osciak
2017/06/23 02:07:34
Are we really ignoring the event here? I think we
Owen Lin
2017/06/26 09:09:00
Ditto.
| |
264 } | |
265 | |
266 void H264DecoderTest::TestOutputPictureEvent(int expected_poc, const Event& e) { | |
267 auto event = static_cast<const OutputPictureEvent&>(e); | |
Pawel Osciak
2017/06/23 02:07:34
Could we instead create a specialized event in Exp
Owen Lin
2017/06/26 09:09:00
Ditto.
| |
268 EXPECT_EQ(expected_poc, event.pic_order_cnt); | |
269 } | |
270 | |
271 void H264DecoderTest::ExpectOutputPictureWithPoc(int expected_poc) { | |
272 ExpectEvent(EventType::OUTPUT_PICTURE, | |
273 base::Bind(TestOutputPictureEvent, expected_poc)); | |
274 } | |
275 | |
276 void H264DecoderTest::TestAllocateNewSurfaceEvent(const gfx::Size& size) { | |
277 EXPECT_EQ(size, decoder_->GetPicSize()); | |
278 } | |
279 | |
280 void H264DecoderTest::ExpectAllocateNewSurfaces(const gfx::Size& size) { | |
281 ExpectEvent(EventType::ALLOCATE_NEW_SURFACES, | |
282 base::Bind(&H264DecoderTest::TestAllocateNewSurfaceEvent, | |
283 base::Unretained(this), size)); | |
284 } | |
285 | |
286 // Test Cases | |
287 | |
288 TEST_F(H264DecoderTest, DecodeSingleFrame) { | |
289 ExpectAllocateNewSurfaces(gfx::Size(320, 192)); | |
290 | |
291 ExpectEvent(EventType::RAN_OUT_OF_SURFACES, | |
292 base::Bind(&FakeH264Accelerator::SetNewPictureQuota, | |
293 base::Unretained(accelerator_.get()), 1)); | |
294 | |
295 ExpectEvent(EventType::SUBMIT_DECODE); | |
296 ExpectEvent(EventType::OUTPUT_PICTURE); | |
297 | |
298 ASSERT_NO_FATAL_FAILURE(FeedData({kBaselineFrame0})); | |
299 ASSERT_TRUE(decoder_->Flush()); | |
300 | |
301 EXPECT_EQ(0u, accelerator_->GetNewPictureQuota()); | |
302 EXPECT_EQ(0u, number_of_expected_events()); | |
303 } | |
304 | |
305 TEST_F(H264DecoderTest, SkipNoneIDRFrames) { | |
306 ExpectAllocateNewSurfaces(gfx::Size(320, 192)); | |
307 ExpectEvent(EventType::SUBMIT_DECODE); | |
308 ExpectOutputPictureWithPoc(0); | |
309 accelerator_->SetNewPictureQuota(1); | |
310 | |
311 ASSERT_NO_FATAL_FAILURE(FeedData({ | |
312 kBaselineFrame1, kBaselineFrame2, kBaselineFrame0, | |
313 })); | |
314 ASSERT_TRUE(decoder_->Flush()); | |
315 | |
316 EXPECT_EQ(0u, accelerator_->GetNewPictureQuota()); | |
317 EXPECT_EQ(0u, number_of_expected_events()); | |
318 } | |
319 | |
320 TEST_F(H264DecoderTest, DecodeProfileBaseline) { | |
321 accelerator_->SetNewPictureQuota(4); | |
322 ExpectEvent(EventType::ALLOCATE_NEW_SURFACES); | |
323 ExpectEvent(EventType::SUBMIT_DECODE); | |
324 ExpectOutputPictureWithPoc(0); | |
325 ExpectEvent(EventType::SUBMIT_DECODE); | |
326 ExpectOutputPictureWithPoc(2); | |
327 ExpectEvent(EventType::SUBMIT_DECODE); | |
328 ExpectOutputPictureWithPoc(4); | |
329 ExpectEvent(EventType::SUBMIT_DECODE); | |
330 ExpectOutputPictureWithPoc(6); | |
331 | |
332 ASSERT_NO_FATAL_FAILURE(FeedData({ | |
333 kBaselineFrame0, kBaselineFrame1, kBaselineFrame2, kBaselineFrame3, | |
334 })); | |
335 ASSERT_TRUE(decoder_->Flush()); | |
336 | |
337 EXPECT_EQ(0u, accelerator_->GetNewPictureQuota()); | |
338 EXPECT_EQ(0u, number_of_expected_events()); | |
339 } | |
340 | |
341 TEST_F(H264DecoderTest, DecodeProfileHigh) { | |
342 accelerator_->SetNewPictureQuota(4); | |
343 ExpectEvent(EventType::ALLOCATE_NEW_SURFACES); | |
344 | |
345 // Two pictures will be kept in DPB for reordering. The first picture should | |
346 // be outputted after feeding the third frame. | |
347 ExpectEvent(EventType::SUBMIT_DECODE); | |
348 ExpectEvent(EventType::SUBMIT_DECODE); | |
349 ExpectEvent(EventType::SUBMIT_DECODE); | |
350 ExpectOutputPictureWithPoc(0); | |
351 ExpectEvent(EventType::SUBMIT_DECODE); | |
352 ExpectOutputPictureWithPoc(2); | |
353 ExpectOutputPictureWithPoc(4); | |
354 ExpectOutputPictureWithPoc(6); | |
355 | |
356 ASSERT_NO_FATAL_FAILURE(FeedData({ | |
357 kHighFrame0, kHighFrame1, kHighFrame2, kHighFrame3, | |
358 })); | |
359 ASSERT_TRUE(decoder_->Flush()); | |
360 | |
361 EXPECT_EQ(0u, accelerator_->GetNewPictureQuota()); | |
362 EXPECT_EQ(0u, number_of_expected_events()); | |
363 } | |
364 | |
365 TEST_F(H264DecoderTest, SwitchBaselineToHigh) { | |
366 accelerator_->SetNewPictureQuota(5); | |
367 | |
368 ExpectEvent(EventType::ALLOCATE_NEW_SURFACES); | |
369 ExpectEvent(EventType::SUBMIT_DECODE); | |
370 ExpectOutputPictureWithPoc(0); | |
371 ExpectEvent(EventType::ALLOCATE_NEW_SURFACES); | |
372 ExpectEvent(EventType::SUBMIT_DECODE); | |
373 ExpectEvent(EventType::SUBMIT_DECODE); | |
374 ExpectEvent(EventType::SUBMIT_DECODE); | |
375 ExpectOutputPictureWithPoc(0); | |
376 ExpectEvent(EventType::SUBMIT_DECODE); | |
377 ExpectOutputPictureWithPoc(2); | |
378 ExpectOutputPictureWithPoc(4); | |
379 ExpectOutputPictureWithPoc(6); | |
380 | |
381 ASSERT_NO_FATAL_FAILURE(FeedData({ | |
382 kBaselineFrame0, kHighFrame0, kHighFrame1, kHighFrame2, kHighFrame3, | |
383 })); | |
384 ASSERT_TRUE(decoder_->Flush()); | |
385 | |
386 EXPECT_EQ(0u, accelerator_->GetNewPictureQuota()); | |
387 EXPECT_EQ(0u, number_of_expected_events()); | |
388 } | |
389 | |
390 TEST_F(H264DecoderTest, SwitchHighToBaseline) { | |
391 accelerator_->SetNewPictureQuota(5); | |
392 | |
393 ExpectEvent(EventType::ALLOCATE_NEW_SURFACES); | |
394 ExpectEvent(EventType::SUBMIT_DECODE); | |
395 ExpectOutputPictureWithPoc(0); | |
396 ExpectEvent(EventType::ALLOCATE_NEW_SURFACES); | |
397 ExpectEvent(EventType::SUBMIT_DECODE); | |
398 ExpectOutputPictureWithPoc(0); | |
399 ExpectEvent(EventType::SUBMIT_DECODE); | |
400 ExpectOutputPictureWithPoc(2); | |
401 ExpectEvent(EventType::SUBMIT_DECODE); | |
402 ExpectOutputPictureWithPoc(4); | |
403 ExpectEvent(EventType::SUBMIT_DECODE); | |
404 ExpectOutputPictureWithPoc(6); | |
405 | |
406 ASSERT_NO_FATAL_FAILURE(FeedData({ | |
407 kHighFrame0, kBaselineFrame0, kBaselineFrame1, kBaselineFrame2, | |
408 kBaselineFrame3, | |
409 })); | |
410 ASSERT_TRUE(decoder_->Flush()); | |
411 | |
412 EXPECT_EQ(0u, accelerator_->GetNewPictureQuota()); | |
413 EXPECT_EQ(0u, number_of_expected_events()); | |
414 } | |
415 | |
416 } // namespace | |
417 } // namespace media | |
OLD | NEW |