OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2015 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 "media/base/android/access_unit_queue.h" | |
6 #include "testing/gtest/include/gtest/gtest.h" | |
7 | |
8 #define ARRAY_SIZE(x) (int)(sizeof(x)/sizeof(x[0])) | |
wolenetz
2015/06/08 21:37:09
nit ditto: size_t to int truncation.
nit: add spac
Tima Vaisburd
2015/06/09 21:29:21
Done.
| |
9 | |
10 namespace media { | |
11 | |
12 class AccessUnitQueueTest : public testing::Test { | |
13 public: | |
14 AccessUnitQueueTest() {} | |
15 ~AccessUnitQueueTest() override {} | |
16 | |
17 protected: | |
18 enum Flags {kNone = 0, kKeyFrame = 1, kEOS = 2, kConfig = 4}; | |
qinmin
2015/06/08 19:39:38
nit: these flags are not used together, just enum
wolenetz
2015/06/08 21:37:09
Suggestion: Please run this CL through clang forma
Tima Vaisburd
2015/06/09 21:29:21
Done.
Tima Vaisburd
2015/06/09 21:29:21
Done renaming and ran through CL. After that I mod
| |
19 struct AUDescriptor { | |
20 int flags; | |
wolenetz
2015/06/08 21:37:09
nit: s/flags/unit_type/ (or unit_status ?) ?
Tima Vaisburd
2015/06/09 21:29:21
Done.
| |
21 std::string data; | |
22 }; | |
23 | |
24 DemuxerData CreateDemuxerData(const AUDescriptor* descr, int descr_length); | |
25 }; | |
26 | |
27 DemuxerData AccessUnitQueueTest::CreateDemuxerData( | |
28 const AUDescriptor* descr, int descr_length) { | |
29 DemuxerData result; | |
30 result.type = DemuxerStream::AUDIO; // assign a valid type | |
wolenetz
2015/06/08 21:37:09
nit: Here and elsewhere: two spaces prior to same-
Tima Vaisburd
2015/06/09 21:29:21
Done.
| |
31 | |
32 for (int i = 0; i < descr_length; ++i) { | |
33 result.access_units.push_back(AccessUnit()); | |
34 AccessUnit& au = result.access_units.back(); | |
35 au.status = (descr[i].flags & kConfig) ? | |
36 DemuxerStream::kConfigChanged : DemuxerStream::kOk; | |
37 if (au.status == DemuxerStream::kConfigChanged) { | |
38 result.demuxer_configs.push_back(DemuxerConfigs()); | |
39 continue; | |
40 } | |
41 | |
42 au.data = std::vector<uint8>(descr[i].data.begin(), descr[i].data.end()); | |
43 au.is_key_frame = (descr[i].flags & kKeyFrame); | |
44 au.is_end_of_stream = (descr[i].flags & kEOS); | |
45 } | |
46 return result; | |
47 } | |
48 | |
49 #define VERIFY_FIRST_BYTE(expected, info) \ | |
50 do { \ | |
51 EXPECT_NE(nullptr, info.front_unit); \ | |
52 EXPECT_TRUE(info.front_unit->data.size() > 0); \ | |
53 EXPECT_EQ(expected, info.front_unit->data[0]); \ | |
54 } \ | |
55 while (0) | |
wolenetz
2015/06/08 21:37:09
nit: put while on previous line
Tima Vaisburd
2015/06/09 21:29:21
Done.
| |
56 | |
57 TEST_F(AccessUnitQueueTest, InitializedEmpty) { | |
58 AccessUnitQueue au_queue; | |
59 AccessUnitQueue::Info info = au_queue.GetInfo(); | |
60 | |
61 EXPECT_EQ(0, info.length); | |
62 EXPECT_FALSE(info.has_eos); | |
63 EXPECT_EQ(nullptr, info.front_unit); | |
64 EXPECT_EQ(nullptr, info.configs); | |
65 } | |
66 | |
67 TEST_F(AccessUnitQueueTest, SkipToKeyFrameEmptyQueue) { | |
68 AccessUnitQueue au_queue; | |
69 EXPECT_FALSE(au_queue.SkipToKeyFrame()); | |
70 } | |
71 | |
72 TEST_F(AccessUnitQueueTest, PushAndAdvance) { | |
73 AUDescriptor chunk1[] = { | |
74 {kNone, "0"}, | |
qinmin
2015/06/08 19:39:38
nit: space before '}' and after '{', same below
Tima Vaisburd
2015/06/09 21:29:21
cl format removed these spaces.
| |
75 {kNone, "1"}, | |
76 {kNone, "2"}, | |
77 {kNone, "3"}, | |
78 {kNone, "4"}, | |
79 {kNone, "5"} | |
80 }; | |
81 AUDescriptor chunk2[] = { | |
82 {kNone, "6"}, | |
83 {kNone, "7"}, | |
84 {kNone, "8"} | |
85 }; | |
86 | |
87 int total_size = ARRAY_SIZE(chunk1) + ARRAY_SIZE(chunk2); | |
88 | |
89 AccessUnitQueue au_queue; | |
90 au_queue.PushBack(CreateDemuxerData(chunk1, ARRAY_SIZE(chunk1))); | |
91 au_queue.PushBack(CreateDemuxerData(chunk2, ARRAY_SIZE(chunk2))); | |
92 | |
93 AccessUnitQueue::Info info; | |
94 for (int i = 0; i < total_size; ++i) { | |
95 info = au_queue.GetInfo(); | |
96 | |
97 EXPECT_FALSE(info.has_eos); | |
98 EXPECT_EQ(total_size - i, info.length); | |
99 EXPECT_EQ(nullptr, info.configs); | |
100 | |
101 EXPECT_NE(nullptr, info.front_unit); | |
102 EXPECT_TRUE(info.front_unit->data.size() > 0); | |
103 EXPECT_EQ('0' + i, info.front_unit->data[0]); | |
104 | |
105 au_queue.Advance(); | |
106 } | |
107 | |
108 // After we advanced past the last AU, GetInfo() should report starvation. | |
109 info = au_queue.GetInfo(); | |
110 | |
111 EXPECT_EQ(0, info.length); | |
112 EXPECT_FALSE(info.has_eos); | |
113 EXPECT_EQ(nullptr, info.front_unit); | |
114 EXPECT_EQ(nullptr, info.configs); | |
115 } | |
116 | |
117 TEST_F(AccessUnitQueueTest, ChunksDoNotLeak) { | |
118 AUDescriptor chunk[] = { | |
119 {kNone, "0"}, | |
120 {kNone, "1"}, | |
121 {kNone, "2"}, | |
122 {kNone, "3"} | |
123 }; | |
124 | |
125 AccessUnitQueue au_queue; | |
126 au_queue.PushBack(CreateDemuxerData(chunk, ARRAY_SIZE(chunk))); | |
127 | |
128 // Verify that the old chunks get deleted (we rely on NumChunksForTesting()) | |
129 for (int i = 0; i < 100; ++i) { | |
130 au_queue.PushBack(CreateDemuxerData(chunk, ARRAY_SIZE(chunk))); | |
131 for (int j = 0; j < ARRAY_SIZE(chunk); ++j) | |
132 au_queue.Advance(); | |
133 | |
134 // 5 is an arbitrary number, it implies that we keep 4 chunks of history. | |
135 EXPECT_GT(5U, au_queue.NumChunksForTesting()); | |
136 } | |
137 } | |
138 | |
139 TEST_F(AccessUnitQueueTest, PushAfterStarvation) { | |
140 // Two chunks | |
141 AUDescriptor chunk[][4] = {{ | |
142 {kNone, "0"}, | |
143 {kNone, "1"}, | |
144 {kNone, "2"}, | |
145 {kNone, "3"} | |
146 }, { | |
147 {kNone, "4"}, | |
148 {kNone, "5"}, | |
149 {kNone, "6"}, | |
150 {kNone, "7"} | |
151 } | |
152 }; | |
153 | |
154 AccessUnitQueue au_queue; | |
155 | |
156 // Push the first chunk. | |
157 au_queue.PushBack(CreateDemuxerData(chunk[0], ARRAY_SIZE(chunk[0]))); | |
158 | |
159 // Advance past the end of queue. | |
160 for (int i = 0; i < ARRAY_SIZE(chunk[0]); ++i) | |
161 au_queue.Advance(); | |
162 | |
163 // An extra Advance() should not change anything. | |
164 au_queue.Advance(); | |
165 | |
166 // Push the second chunk | |
167 au_queue.PushBack(CreateDemuxerData(chunk[1], ARRAY_SIZE(chunk[1]))); | |
168 | |
169 // Verify that we get the next access unit. | |
170 AccessUnitQueue::Info info = au_queue.GetInfo(); | |
171 VERIFY_FIRST_BYTE('4', info); | |
172 } | |
173 | |
174 TEST_F(AccessUnitQueueTest, HasEOS) { | |
175 // Two chunks | |
176 AUDescriptor chunk[][4] = {{ | |
177 {kNone, "0"}, | |
178 {kNone, "1"}, | |
179 {kNone, "2"}, | |
180 {kNone, "3"} | |
181 }, { | |
182 {kNone, "4"}, | |
183 {kNone, "5"}, | |
184 {kNone, "6"}, | |
185 {kEOS, "7"} | |
186 } | |
187 }; | |
188 | |
189 AccessUnitQueue au_queue; | |
190 au_queue.PushBack(CreateDemuxerData(chunk[0], ARRAY_SIZE(chunk[0]))); | |
191 au_queue.PushBack(CreateDemuxerData(chunk[1], ARRAY_SIZE(chunk[1]))); | |
192 | |
193 // Verify that after EOS has been pushed into the queue, | |
194 // it is reported for every GetInfo() | |
195 for (int i = 0; i < 8; ++i) { | |
196 AccessUnitQueue::Info info = au_queue.GetInfo(); | |
197 | |
198 EXPECT_TRUE(info.has_eos); | |
199 EXPECT_EQ(nullptr, info.configs); | |
200 | |
201 VERIFY_FIRST_BYTE('0' + i, info); | |
202 | |
203 au_queue.Advance(); | |
204 } | |
205 } | |
206 | |
207 TEST_F(AccessUnitQueueTest, HasConfigs) { | |
208 AUDescriptor chunk[] = { | |
209 {kNone, "0"}, | |
210 {kNone, "1"}, | |
211 {kNone, "2"}, | |
212 {kConfig, "3"} | |
213 }; | |
214 | |
215 AccessUnitQueue au_queue; | |
216 au_queue.PushBack(CreateDemuxerData(chunk, ARRAY_SIZE(chunk))); | |
217 | |
218 for (int i = 0; i < 4; ++i) { | |
219 AccessUnitQueue::Info info = au_queue.GetInfo(); | |
220 | |
221 if (i != 3) | |
222 EXPECT_EQ(nullptr, info.configs); | |
223 else | |
224 EXPECT_NE(nullptr, info.configs); | |
225 | |
226 au_queue.Advance(); | |
227 } | |
228 } | |
229 | |
230 TEST_F(AccessUnitQueueTest, ConfigsAndKeyFrame) { | |
231 // Two chunks | |
232 AUDescriptor chunk[][4] = {{ | |
233 {kNone, "0"}, | |
234 {kKeyFrame, "1"}, | |
235 {kNone, "2"}, | |
236 {kConfig, "3"} | |
237 }, { | |
238 {kKeyFrame, "4"}, | |
239 {kNone, "5"}, | |
240 {kNone, "6"}, | |
241 {kNone, "7"} | |
242 } | |
243 }; | |
244 | |
245 AccessUnitQueue::Info info; | |
246 | |
247 AccessUnitQueue au_queue; | |
248 au_queue.PushBack(CreateDemuxerData(chunk[0], ARRAY_SIZE(chunk[0]))); | |
249 au_queue.PushBack(CreateDemuxerData(chunk[1], ARRAY_SIZE(chunk[1]))); | |
250 | |
251 // There is no prior key frame | |
252 EXPECT_FALSE(au_queue.SkipToKeyFrame()); | |
253 | |
254 // Consume first access unit. | |
255 au_queue.Advance(); | |
256 | |
257 // Now the current one is the key frame. It would be safe to configure codec | |
258 // at this moment, so SkipToKeyFrame() should return true. | |
259 EXPECT_TRUE(au_queue.SkipToKeyFrame()); | |
260 | |
261 info = au_queue.GetInfo(); | |
262 VERIFY_FIRST_BYTE('1', info); | |
263 | |
264 au_queue.Advance(); // now current unit is "2" | |
265 | |
266 info = au_queue.GetInfo(); | |
267 VERIFY_FIRST_BYTE('2', info); | |
268 | |
269 EXPECT_TRUE(au_queue.SkipToKeyFrame()); // should go back to "1" | |
270 | |
271 info = au_queue.GetInfo(); | |
272 VERIFY_FIRST_BYTE('1', info); | |
273 | |
274 au_queue.Advance(); // now current unit is "2" | |
275 au_queue.Advance(); // now current unit is "3" | |
276 | |
277 // Verify that we are at "3". | |
278 info = au_queue.GetInfo(); | |
279 EXPECT_NE(nullptr, info.configs); | |
280 | |
281 // Although it would be safe to configure codec (with old config) in this | |
282 // position since it will be immediately reconfigured from the next unit "3", | |
283 // current implementation returns unit "1". | |
284 | |
285 EXPECT_TRUE(au_queue.SkipToKeyFrame()); // should go back to "1" | |
286 | |
287 info = au_queue.GetInfo(); | |
288 VERIFY_FIRST_BYTE('1', info); | |
289 | |
290 au_queue.Advance(); // now current unit is "2" | |
291 au_queue.Advance(); // now current unit is "3" | |
292 au_queue.Advance(); // now current unit is "4" | |
293 | |
294 info = au_queue.GetInfo(); | |
295 VERIFY_FIRST_BYTE('4', info); | |
296 | |
297 EXPECT_TRUE(au_queue.SkipToKeyFrame()); // should stay at "4" | |
298 | |
299 info = au_queue.GetInfo(); | |
300 VERIFY_FIRST_BYTE('4', info); | |
301 | |
302 au_queue.Advance(); // now current unit is "5" | |
303 au_queue.Advance(); // now current unit is "6" | |
304 | |
305 info = au_queue.GetInfo(); | |
306 VERIFY_FIRST_BYTE('6', info); | |
307 | |
308 EXPECT_TRUE(au_queue.SkipToKeyFrame()); // should go back to "4" | |
309 | |
310 info = au_queue.GetInfo(); | |
311 VERIFY_FIRST_BYTE('4', info); | |
312 } | |
313 | |
314 } // namespace media | |
OLD | NEW |