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

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

Issue 2760513002: h264_decoder_unittests: Initial Change. (Closed)
Patch Set: Refactor: uses gmock for expected calls. 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::InSequence;
22 using ::testing::Invoke;
23 using ::testing::MakeMatcher;
24 using ::testing::Matcher;
25 using ::testing::MatcherInterface;
26 using ::testing::MatchResultListener;
27 using ::testing::Mock;
28 using ::testing::Return;
29
30 namespace media {
31 namespace {
32
33 const std::string kBaselineFrame0 = "bear-320x192-baseline-frame-0.h264";
34 const std::string kBaselineFrame1 = "bear-320x192-baseline-frame-1.h264";
35 const std::string kBaselineFrame2 = "bear-320x192-baseline-frame-2.h264";
36 const std::string kBaselineFrame3 = "bear-320x192-baseline-frame-3.h264";
37 const std::string kHighFrame0 = "bear-320x192-high-frame-0.h264";
38 const std::string kHighFrame1 = "bear-320x192-high-frame-1.h264";
39 const std::string kHighFrame2 = "bear-320x192-high-frame-2.h264";
40 const std::string kHighFrame3 = "bear-320x192-high-frame-3.h264";
41
42 class MockH264Accelerator : public H264Decoder::H264Accelerator {
43 public:
44 MockH264Accelerator() {}
45
46 MOCK_METHOD0(CreateH264Picture, scoped_refptr<H264Picture>());
47 MOCK_METHOD1(SubmitDecode, bool(const scoped_refptr<H264Picture>& pic));
48 MOCK_METHOD1(OutputPicture, bool(const scoped_refptr<H264Picture>& pic));
49
50 bool SubmitFrameMetadata(const H264SPS* sps,
51 const H264PPS* pps,
52 const H264DPB& dpb,
53 const H264Picture::Vector& ref_pic_listp0,
54 const H264Picture::Vector& ref_pic_listb0,
55 const H264Picture::Vector& ref_pic_listb1,
56 const scoped_refptr<H264Picture>& pic) override {
57 return true;
58 }
59
60 bool SubmitSlice(const H264PPS* pps,
61 const H264SliceHeader* slice_hdr,
62 const H264Picture::Vector& ref_pic_list0,
63 const H264Picture::Vector& ref_pic_list1,
64 const scoped_refptr<H264Picture>& pic,
65 const uint8_t* data,
66 size_t size) override {
67 return true;
68 }
69
70 void Reset() override {}
71 };
72
73 // Test H264Decoder by feeding different of h264 frame sequences and make
74 // sure it behaves as expected.
75 class H264DecoderTest : public ::testing::Test {
76 public:
77 H264DecoderTest() = default;
78
79 void SetUp() override;
80
81 // Sets the bitstreams to be decoded, frame by frame. The content of each
82 // file is the encoded bitstream of a single video frame.
83 void SetInputFrameFiles(const std::vector<std::string>& frame_files);
84
85 // Keeps decoding the input bitstream set at |SetInputFrameFiles| until the
86 // decoder has consumed all bitstreams or returned from
87 // |H264Decoder::Decode|. Returns the same result as |H264Decoder::Decode|.
88 AcceleratedVideoDecoder::DecodeResult Decode();
89
90 protected:
91 std::unique_ptr<H264Decoder> decoder_;
92 MockH264Accelerator accelerator_;
93
94 private:
95 std::queue<std::string> input_frame_files_;
96 std::string bitstream_;
97 };
98
99 void H264DecoderTest::SetUp() {
100 decoder_.reset(new H264Decoder(&accelerator_));
101
102 // Sets default behaviors for mock methods for convenience.
103 ON_CALL(accelerator_, CreateH264Picture()).WillByDefault(Invoke([]() {
104 return new H264Picture();
105 }));
106 ON_CALL(accelerator_, SubmitDecode(_)).WillByDefault(Return(true));
107 ON_CALL(accelerator_, OutputPicture(_)).WillByDefault(Return(true));
108 }
109
110 void H264DecoderTest::SetInputFrameFiles(
111 const std::vector<std::string>& input_frame_files) {
112 for (auto f : input_frame_files)
113 input_frame_files_.push(f);
114 }
115
116 AcceleratedVideoDecoder::DecodeResult H264DecoderTest::Decode() {
117 while (true) {
118 auto result = decoder_->Decode();
119 if (result != AcceleratedVideoDecoder::kRanOutOfStreamData ||
120 input_frame_files_.empty())
121 return result;
122 auto input_file = GetTestDataFilePath(input_frame_files_.front());
123 input_frame_files_.pop();
124 CHECK(base::ReadFileToString(input_file, &bitstream_));
125 decoder_->SetStream(reinterpret_cast<const uint8_t*>(bitstream_.data()),
126 bitstream_.size());
127 }
128 }
129
130 // To have better description on mismatch.
131 class WithPocMatcher
132 : public MatcherInterface<const scoped_refptr<H264Picture>&> {
133 public:
134 explicit WithPocMatcher(int expected_poc) : expected_poc_(expected_poc) {}
135
136 bool MatchAndExplain(const scoped_refptr<H264Picture>& p,
137 MatchResultListener* listener) const override {
138 if (p->pic_order_cnt == expected_poc_)
139 return true;
140 *listener << "with poc: " << p->pic_order_cnt;
141 return false;
142 }
143
144 void DescribeTo(std::ostream* os) const override {
145 *os << "with poc " << expected_poc_;
146 }
147
148 private:
149 int expected_poc_;
150 };
151
152 inline Matcher<const scoped_refptr<H264Picture>&> WithPoc(int expected_poc) {
153 return MakeMatcher(new WithPocMatcher(expected_poc));
154 }
155
156 // Test Cases
157
158 TEST_F(H264DecoderTest, DecodeSingleFrame) {
159 SetInputFrameFiles({kBaselineFrame0});
160 ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode());
161 EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
162
163 EXPECT_CALL(accelerator_, CreateH264Picture()).WillOnce(Return(nullptr));
164 ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfSurfaces, Decode());
165 ASSERT_TRUE(Mock::VerifyAndClearExpectations(&accelerator_));
166
167 {
168 InSequence sequence;
169 EXPECT_CALL(accelerator_, CreateH264Picture());
170 EXPECT_CALL(accelerator_, SubmitDecode(_));
171 EXPECT_CALL(accelerator_, OutputPicture(_));
172 }
173 ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
174 ASSERT_TRUE(decoder_->Flush());
175 }
176
177 TEST_F(H264DecoderTest, SkipNoneIDRFrames) {
Pawel Osciak 2017/06/28 07:59:25 s/None/Non/
Owen Lin 2017/06/28 09:03:38 Done.
178 SetInputFrameFiles({kBaselineFrame1, kBaselineFrame2, kBaselineFrame0});
179 ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode());
180 EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
181 {
182 InSequence sequence;
183 EXPECT_CALL(accelerator_, CreateH264Picture());
184 EXPECT_CALL(accelerator_, SubmitDecode(_));
185 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0)));
186 }
187 ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
188 ASSERT_TRUE(decoder_->Flush());
189 }
190
191 TEST_F(H264DecoderTest, DecodeProfileBaseline) {
192 SetInputFrameFiles({
193 kBaselineFrame0, kBaselineFrame1, kBaselineFrame2, kBaselineFrame3,
194 });
195 ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode());
196 EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
197
198 EXPECT_CALL(accelerator_, CreateH264Picture()).Times(4);
199 {
200 InSequence sequence;
201 EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(0)));
Pawel Osciak 2017/06/28 07:59:25 If I understand the stream correctly, would this b
Owen Lin 2017/06/28 09:03:38 Done.
202 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0)));
203 EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(2)));
204 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(2)));
205 EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(4)));
206 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(4)));
207 EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(6)));
208 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(6)));
209 }
210 ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
211 ASSERT_TRUE(decoder_->Flush());
212 }
213
214 TEST_F(H264DecoderTest, DecodeProfileHigh) {
215 SetInputFrameFiles({kHighFrame0, kHighFrame1, kHighFrame2, kHighFrame3});
216 ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode());
217 EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
218
219 // Two pictures will be kept in DPB for reordering. The first picture should
220 // be outputted after feeding the third frame.
221 EXPECT_CALL(accelerator_, CreateH264Picture()).Times(4);
222 {
223 InSequence sequence;
224 EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(0)));
225 EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(4)));
226 EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(2)));
227 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0)));
228 EXPECT_CALL(accelerator_, SubmitDecode(WithPoc(6)));
229 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(2)));
230 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(4)));
231 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(6)));
232 }
233 ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
234 ASSERT_TRUE(decoder_->Flush());
235 }
236
237 TEST_F(H264DecoderTest, SwitchBaselineToHigh) {
238 SetInputFrameFiles({
239 kBaselineFrame0, kHighFrame0, kHighFrame1, kHighFrame2, kHighFrame3,
240 });
241 ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode());
242 EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
243
244 EXPECT_CALL(accelerator_, CreateH264Picture());
245 {
246 InSequence sequence;
247 EXPECT_CALL(accelerator_, SubmitDecode(_));
248 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0)));
249 }
250 ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode());
251 EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
Pawel Osciak 2017/06/28 07:59:25 Should we also EXPECT for decoder_->GetRequiredNum
Owen Lin 2017/06/28 09:03:38 Done.
252 ASSERT_TRUE(Mock::VerifyAndClearExpectations(&accelerator_));
253
254 EXPECT_CALL(accelerator_, CreateH264Picture()).Times(4);
255 {
256 InSequence sequence;
257 EXPECT_CALL(accelerator_, SubmitDecode(_)).Times(3);
258 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0)));
259 EXPECT_CALL(accelerator_, SubmitDecode(_));
260 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(2)));
261 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(4)));
262 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(6)));
263 }
264 ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
265 ASSERT_TRUE(decoder_->Flush());
266 }
267
268 TEST_F(H264DecoderTest, SwitchHighToBaseline) {
269 SetInputFrameFiles({
270 kHighFrame0, kBaselineFrame0, kBaselineFrame1, kBaselineFrame2,
271 kBaselineFrame3,
272 });
273 ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode());
274 EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
275
276 EXPECT_CALL(accelerator_, CreateH264Picture());
277 {
278 InSequence sequence;
279 EXPECT_CALL(accelerator_, SubmitDecode(_));
280 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0)));
281 }
282 ASSERT_EQ(AcceleratedVideoDecoder::kAllocateNewSurfaces, Decode());
283 EXPECT_EQ(gfx::Size(320, 192), decoder_->GetPicSize());
284 ASSERT_TRUE(Mock::VerifyAndClearExpectations(&accelerator_));
285
286 EXPECT_CALL(accelerator_, CreateH264Picture()).Times(4);
287 {
288 InSequence sequence;
289 EXPECT_CALL(accelerator_, SubmitDecode(_));
290 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(0)));
291 EXPECT_CALL(accelerator_, SubmitDecode(_));
292 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(2)));
293 EXPECT_CALL(accelerator_, SubmitDecode(_));
294 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(4)));
295 EXPECT_CALL(accelerator_, SubmitDecode(_));
296 EXPECT_CALL(accelerator_, OutputPicture(WithPoc(6)));
297 }
298 ASSERT_EQ(AcceleratedVideoDecoder::kRanOutOfStreamData, Decode());
299 ASSERT_TRUE(decoder_->Flush());
300 }
301
302 } // namespace
303 } // 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