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

Side by Side Diff: media/base/android/access_unit_queue_unittest.cc

Issue 2276343005: Delete MediaCodecPlayer, it's time! (Closed)
Patch Set: Created 4 years, 3 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/base/android/access_unit_queue.cc ('k') | media/base/android/audio_media_codec_decoder.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 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 <stddef.h>
6 #include <stdint.h>
7
8 #include "media/base/android/access_unit_queue.h"
9 #include "testing/gtest/include/gtest/gtest.h"
10
11 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
12
13 namespace media {
14
15 class AccessUnitQueueTest : public testing::Test {
16 public:
17 AccessUnitQueueTest() {}
18 ~AccessUnitQueueTest() override {}
19
20 protected:
21 enum UnitType { kNormal = 0, kKeyFrame, kEOS, kConfig };
22 struct AUDescriptor {
23 UnitType unit_type;
24 std::string data;
25 };
26
27 DemuxerData CreateDemuxerData(const AUDescriptor* descr, int descr_length);
28 };
29
30 DemuxerData AccessUnitQueueTest::CreateDemuxerData(const AUDescriptor* descr,
31 int descr_length) {
32 DemuxerData result;
33 result.type = DemuxerStream::AUDIO; // assign a valid type
34
35 for (int i = 0; i < descr_length; ++i) {
36 result.access_units.push_back(AccessUnit());
37 AccessUnit& au = result.access_units.back();
38
39 if (descr[i].unit_type == kConfig) {
40 au.status = DemuxerStream::kConfigChanged;
41 result.demuxer_configs.push_back(DemuxerConfigs());
42 // ignore data
43 continue;
44 }
45
46 au.status = DemuxerStream::kOk;
47
48 if (descr[i].unit_type == kEOS) {
49 au.is_end_of_stream = true;
50 // ignore data
51 continue;
52 }
53
54 au.data = std::vector<uint8_t>(descr[i].data.begin(), descr[i].data.end());
55
56 if (descr[i].unit_type == kKeyFrame)
57 au.is_key_frame = true;
58 }
59 return result;
60 }
61
62 #define VERIFY_FIRST_BYTE(expected, info) \
63 do { \
64 EXPECT_NE(nullptr, info.front_unit); \
65 EXPECT_TRUE(info.front_unit->data.size() > 0); \
66 EXPECT_EQ(expected, info.front_unit->data[0]); \
67 } while (0)
68
69 TEST_F(AccessUnitQueueTest, InitializedEmpty) {
70 AccessUnitQueue au_queue;
71 AccessUnitQueue::Info info = au_queue.GetInfo();
72
73 EXPECT_EQ(0, info.length);
74 EXPECT_FALSE(info.has_eos);
75 EXPECT_EQ(nullptr, info.front_unit);
76 EXPECT_EQ(nullptr, info.configs);
77 }
78
79 TEST_F(AccessUnitQueueTest, RewindToLastKeyFrameEmptyQueue) {
80 AccessUnitQueue au_queue;
81 EXPECT_FALSE(au_queue.RewindToLastKeyFrame());
82 }
83
84 TEST_F(AccessUnitQueueTest, PushAndAdvance) {
85 AUDescriptor chunk1[] = {{kNormal, "0"},
86 {kNormal, "1"},
87 {kNormal, "2"},
88 {kNormal, "3"},
89 {kNormal, "4"},
90 {kNormal, "5"}};
91 AUDescriptor chunk2[] = {{kNormal, "6"},
92 {kNormal, "7"},
93 {kNormal, "8"}};
94
95 int total_size = ARRAY_SIZE(chunk1) + ARRAY_SIZE(chunk2);
96
97 AccessUnitQueue au_queue;
98 au_queue.PushBack(CreateDemuxerData(chunk1, ARRAY_SIZE(chunk1)));
99 au_queue.PushBack(CreateDemuxerData(chunk2, ARRAY_SIZE(chunk2)));
100
101 AccessUnitQueue::Info info;
102 for (int i = 0; i < total_size; ++i) {
103 info = au_queue.GetInfo();
104
105 EXPECT_FALSE(info.has_eos);
106 EXPECT_EQ(total_size - i, info.length);
107 EXPECT_EQ(nullptr, info.configs);
108
109 ASSERT_NE(nullptr, info.front_unit);
110 EXPECT_TRUE(info.front_unit->data.size() > 0);
111 EXPECT_EQ('0' + i, info.front_unit->data[0]);
112
113 au_queue.Advance();
114 }
115
116 // After we advanced past the last AU, GetInfo() should report starvation.
117 info = au_queue.GetInfo();
118
119 EXPECT_EQ(0, info.length);
120 EXPECT_FALSE(info.has_eos);
121 EXPECT_EQ(nullptr, info.front_unit);
122 EXPECT_EQ(nullptr, info.configs);
123 }
124
125 TEST_F(AccessUnitQueueTest, ChunksDoNotLeak) {
126 AUDescriptor chunk[] = {
127 {kNormal, "0"}, {kNormal, "1"}, {kNormal, "2"}, {kNormal, "3"}};
128
129 AccessUnitQueue au_queue;
130
131 // Verify that the old chunks get deleted (we rely on NumChunksForTesting()).
132 // First, run the loop with default history size, which is zero chunks.
133 for (size_t i = 0; i < 100; ++i) {
134 au_queue.PushBack(CreateDemuxerData(chunk, ARRAY_SIZE(chunk)));
135 for (size_t j = 0; j < ARRAY_SIZE(chunk); ++j)
136 au_queue.Advance();
137
138 EXPECT_EQ(0U, au_queue.NumChunksForTesting());
139 }
140
141 // Change the history size and run again.
142 au_queue.SetHistorySizeForTesting(5);
143
144 for (size_t i = 0; i < 100; ++i) {
145 au_queue.PushBack(CreateDemuxerData(chunk, ARRAY_SIZE(chunk)));
146 for (size_t j = 0; j < ARRAY_SIZE(chunk); ++j)
147 au_queue.Advance();
148
149 if (i < 4)
150 EXPECT_EQ(i + 1, au_queue.NumChunksForTesting());
151 else
152 EXPECT_EQ(5U, au_queue.NumChunksForTesting());
153 }
154 }
155
156 TEST_F(AccessUnitQueueTest, PushAfterStarvation) {
157 // Two chunks
158 AUDescriptor chunk[][4] = {
159 {{kNormal, "0"}, {kNormal, "1"}, {kNormal, "2"}, {kNormal, "3"}},
160 {{kNormal, "4"}, {kNormal, "5"}, {kNormal, "6"}, {kNormal, "7"}}};
161
162 AccessUnitQueue au_queue;
163
164 // Push the first chunk.
165 au_queue.PushBack(CreateDemuxerData(chunk[0], ARRAY_SIZE(chunk[0])));
166
167 // Advance past the end of queue.
168 for (size_t i = 0; i < ARRAY_SIZE(chunk[0]); ++i)
169 au_queue.Advance();
170
171 // An extra Advance() should not change anything.
172 au_queue.Advance();
173
174 // Push the second chunk
175 au_queue.PushBack(CreateDemuxerData(chunk[1], ARRAY_SIZE(chunk[1])));
176
177 // Verify that we get the next access unit.
178 AccessUnitQueue::Info info = au_queue.GetInfo();
179 VERIFY_FIRST_BYTE('4', info);
180 }
181
182 TEST_F(AccessUnitQueueTest, HasEOS) {
183 // Two chunks
184 AUDescriptor chunk[][4] = {
185 {{kNormal, "0"}, {kNormal, "1"}, {kNormal, "2"}, {kNormal, "3"}},
186 {{kNormal, "4"}, {kNormal, "5"}, {kNormal, "6"}, {kEOS, "7"}}};
187
188 AccessUnitQueue au_queue;
189 au_queue.PushBack(CreateDemuxerData(chunk[0], ARRAY_SIZE(chunk[0])));
190 au_queue.PushBack(CreateDemuxerData(chunk[1], ARRAY_SIZE(chunk[1])));
191
192 // Verify that after EOS has been pushed into the queue,
193 // it is reported for every GetInfo()
194 for (int i = 0; i < 8; ++i) {
195 AccessUnitQueue::Info info = au_queue.GetInfo();
196
197 EXPECT_TRUE(info.has_eos);
198 EXPECT_EQ(nullptr, info.configs);
199
200 if (i == 7)
201 EXPECT_TRUE(info.front_unit->is_end_of_stream);
202 else
203 VERIFY_FIRST_BYTE('0' + i, info);
204
205 au_queue.Advance();
206 }
207 }
208
209 TEST_F(AccessUnitQueueTest, HasConfigs) {
210 AUDescriptor chunk[] = {
211 {kNormal, "0"}, {kNormal, "1"}, {kNormal, "2"}, {kConfig, "3"}};
212
213 AccessUnitQueue au_queue;
214 au_queue.PushBack(CreateDemuxerData(chunk, ARRAY_SIZE(chunk)));
215
216 for (int i = 0; i < 4; ++i) {
217 AccessUnitQueue::Info info = au_queue.GetInfo();
218
219 if (i != 3)
220 EXPECT_EQ(nullptr, info.configs);
221 else
222 EXPECT_NE(nullptr, info.configs);
223
224 au_queue.Advance();
225 }
226 }
227
228 TEST_F(AccessUnitQueueTest, ConfigsAndKeyFrame) {
229 // Two chunks
230 AUDescriptor chunk[][4] = {
231 {{kNormal, "0"}, {kKeyFrame, "1"}, {kNormal, "2"}, {kConfig, "3"}},
232 {{kKeyFrame, "4"}, {kNormal, "5"}, {kNormal, "6"}, {kNormal, "7"}}};
233
234 AccessUnitQueue::Info info;
235
236 AccessUnitQueue au_queue;
237 au_queue.PushBack(CreateDemuxerData(chunk[0], ARRAY_SIZE(chunk[0])));
238 au_queue.PushBack(CreateDemuxerData(chunk[1], ARRAY_SIZE(chunk[1])));
239
240 // There is no prior key frame
241 EXPECT_FALSE(au_queue.RewindToLastKeyFrame());
242
243 // Consume first access unit.
244 au_queue.Advance();
245
246 // Now the current one is the key frame. It would be safe to configure codec
247 // at this moment, so RewindToLastKeyFrame() should return true.
248 EXPECT_TRUE(au_queue.RewindToLastKeyFrame());
249
250 info = au_queue.GetInfo();
251 VERIFY_FIRST_BYTE('1', info);
252
253 au_queue.Advance(); // now current unit is "2"
254
255 info = au_queue.GetInfo();
256 VERIFY_FIRST_BYTE('2', info);
257
258 EXPECT_TRUE(au_queue.RewindToLastKeyFrame()); // should go back to "1"
259
260 info = au_queue.GetInfo();
261 VERIFY_FIRST_BYTE('1', info);
262
263 au_queue.Advance(); // now current unit is "2"
264 au_queue.Advance(); // now current unit is "3"
265
266 // Verify that we are at "3".
267 info = au_queue.GetInfo();
268 EXPECT_NE(nullptr, info.configs);
269
270 // Although it would be safe to configure codec (with old config) in this
271 // position since it will be immediately reconfigured from the next unit "3",
272 // current implementation returns unit "1".
273
274 EXPECT_TRUE(au_queue.RewindToLastKeyFrame()); // should go back to "1"
275
276 info = au_queue.GetInfo();
277 VERIFY_FIRST_BYTE('1', info);
278
279 au_queue.Advance(); // now current unit is "2"
280 au_queue.Advance(); // now current unit is "3"
281 au_queue.Advance(); // now current unit is "4"
282
283 info = au_queue.GetInfo();
284 VERIFY_FIRST_BYTE('4', info);
285
286 EXPECT_TRUE(au_queue.RewindToLastKeyFrame()); // should stay at "4"
287
288 info = au_queue.GetInfo();
289 VERIFY_FIRST_BYTE('4', info);
290
291 au_queue.Advance(); // now current unit is "5"
292 au_queue.Advance(); // now current unit is "6"
293
294 info = au_queue.GetInfo();
295 VERIFY_FIRST_BYTE('6', info);
296
297 EXPECT_TRUE(au_queue.RewindToLastKeyFrame()); // should go back to "4"
298
299 info = au_queue.GetInfo();
300 VERIFY_FIRST_BYTE('4', info);
301 }
302
303 TEST_F(AccessUnitQueueTest, KeyFrameWithLongHistory) {
304 // Four chunks
305 AUDescriptor chunk[][4] = {
306 {{kNormal, "0"}, {kKeyFrame, "1"}, {kNormal, "2"}, {kNormal, "3"}},
307 {{kNormal, "4"}, {kNormal, "5"}, {kNormal, "6"}, {kNormal, "7"}},
308 {{kNormal, "8"}, {kNormal, "9"}, {kNormal, "a"}, {kNormal, "b"}},
309 {{kNormal, "c"}, {kNormal, "d"}, {kKeyFrame, "e"}, {kNormal, "f"}}};
310
311 AccessUnitQueue::Info info;
312
313 AccessUnitQueue au_queue;
314 for (int i = 0; i < 4; ++i)
315 au_queue.PushBack(CreateDemuxerData(chunk[i], ARRAY_SIZE(chunk[i])));
316
317 au_queue.SetHistorySizeForTesting(3);
318
319 // Advance to '3'.
320 for (int i = 0; i < 3; ++i)
321 au_queue.Advance();
322
323 info = au_queue.GetInfo();
324 VERIFY_FIRST_BYTE('3', info);
325
326 // Rewind to key frame, the current unit should be '1'.
327 EXPECT_TRUE(au_queue.RewindToLastKeyFrame());
328 info = au_queue.GetInfo();
329 VERIFY_FIRST_BYTE('1', info);
330
331 // Advance to 'c'.
332 for (int i = 0; i < 11; ++i)
333 au_queue.Advance();
334
335 info = au_queue.GetInfo();
336 VERIFY_FIRST_BYTE('c', info);
337
338 // Rewind to key frame, the current unit should be '1' again.
339 EXPECT_TRUE(au_queue.RewindToLastKeyFrame());
340 info = au_queue.GetInfo();
341 VERIFY_FIRST_BYTE('1', info);
342
343 // Set history size to 0 (default)
344 au_queue.SetHistorySizeForTesting(0);
345
346 // Advance to 'd'. Should erase all chunks except the last.
347 for (int i = 0; i < 12; ++i)
348 au_queue.Advance();
349
350 info = au_queue.GetInfo();
351 VERIFY_FIRST_BYTE('d', info);
352
353 // Rewind should not find any key frames.
354 EXPECT_FALSE(au_queue.RewindToLastKeyFrame());
355
356 au_queue.Advance(); // Advance to key frame 'e'.
357 info = au_queue.GetInfo();
358 VERIFY_FIRST_BYTE('e', info);
359
360 // Rewind should find the same unit 'e.
361 EXPECT_TRUE(au_queue.RewindToLastKeyFrame());
362 info = au_queue.GetInfo();
363 VERIFY_FIRST_BYTE('e', info);
364 }
365
366 } // namespace media
OLDNEW
« no previous file with comments | « media/base/android/access_unit_queue.cc ('k') | media/base/android/audio_media_codec_decoder.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698