Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / media / base / android / access_unit_queue_unittest.cc
blob5dca0771a0aaa74b5990a857b200f5a3a204a4fb
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.
5 #include "media/base/android/access_unit_queue.h"
6 #include "testing/gtest/include/gtest/gtest.h"
8 #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
10 namespace media {
12 class AccessUnitQueueTest : public testing::Test {
13 public:
14 AccessUnitQueueTest() {}
15 ~AccessUnitQueueTest() override {}
17 protected:
18 enum UnitType { kNormal = 0, kKeyFrame, kEOS, kConfig };
19 struct AUDescriptor {
20 UnitType unit_type;
21 std::string data;
24 DemuxerData CreateDemuxerData(const AUDescriptor* descr, int descr_length);
27 DemuxerData AccessUnitQueueTest::CreateDemuxerData(const AUDescriptor* descr,
28 int descr_length) {
29 DemuxerData result;
30 result.type = DemuxerStream::AUDIO; // assign a valid type
32 for (int i = 0; i < descr_length; ++i) {
33 result.access_units.push_back(AccessUnit());
34 AccessUnit& au = result.access_units.back();
36 if (descr[i].unit_type == kConfig) {
37 au.status = DemuxerStream::kConfigChanged;
38 result.demuxer_configs.push_back(DemuxerConfigs());
39 // ignore data
40 continue;
43 au.status = DemuxerStream::kOk;
45 if (descr[i].unit_type == kEOS) {
46 au.is_end_of_stream = true;
47 // ignore data
48 continue;
51 au.data = std::vector<uint8>(descr[i].data.begin(), descr[i].data.end());
53 if (descr[i].unit_type == kKeyFrame)
54 au.is_key_frame = true;
56 return result;
59 #define VERIFY_FIRST_BYTE(expected, info) \
60 do { \
61 EXPECT_NE(nullptr, info.front_unit); \
62 EXPECT_TRUE(info.front_unit->data.size() > 0); \
63 EXPECT_EQ(expected, info.front_unit->data[0]); \
64 } while (0)
66 TEST_F(AccessUnitQueueTest, InitializedEmpty) {
67 AccessUnitQueue au_queue;
68 AccessUnitQueue::Info info = au_queue.GetInfo();
70 EXPECT_EQ(0, info.length);
71 EXPECT_FALSE(info.has_eos);
72 EXPECT_EQ(nullptr, info.front_unit);
73 EXPECT_EQ(nullptr, info.configs);
76 TEST_F(AccessUnitQueueTest, RewindToLastKeyFrameEmptyQueue) {
77 AccessUnitQueue au_queue;
78 EXPECT_FALSE(au_queue.RewindToLastKeyFrame());
81 TEST_F(AccessUnitQueueTest, PushAndAdvance) {
82 AUDescriptor chunk1[] = {{kNormal, "0"},
83 {kNormal, "1"},
84 {kNormal, "2"},
85 {kNormal, "3"},
86 {kNormal, "4"},
87 {kNormal, "5"}};
88 AUDescriptor chunk2[] = {{kNormal, "6"},
89 {kNormal, "7"},
90 {kNormal, "8"}};
92 int total_size = ARRAY_SIZE(chunk1) + ARRAY_SIZE(chunk2);
94 AccessUnitQueue au_queue;
95 au_queue.PushBack(CreateDemuxerData(chunk1, ARRAY_SIZE(chunk1)));
96 au_queue.PushBack(CreateDemuxerData(chunk2, ARRAY_SIZE(chunk2)));
98 AccessUnitQueue::Info info;
99 for (int i = 0; i < total_size; ++i) {
100 info = au_queue.GetInfo();
102 EXPECT_FALSE(info.has_eos);
103 EXPECT_EQ(total_size - i, info.length);
104 EXPECT_EQ(nullptr, info.configs);
106 ASSERT_NE(nullptr, info.front_unit);
107 EXPECT_TRUE(info.front_unit->data.size() > 0);
108 EXPECT_EQ('0' + i, info.front_unit->data[0]);
110 au_queue.Advance();
113 // After we advanced past the last AU, GetInfo() should report starvation.
114 info = au_queue.GetInfo();
116 EXPECT_EQ(0, info.length);
117 EXPECT_FALSE(info.has_eos);
118 EXPECT_EQ(nullptr, info.front_unit);
119 EXPECT_EQ(nullptr, info.configs);
122 TEST_F(AccessUnitQueueTest, ChunksDoNotLeak) {
123 AUDescriptor chunk[] = {
124 {kNormal, "0"}, {kNormal, "1"}, {kNormal, "2"}, {kNormal, "3"}};
126 AccessUnitQueue au_queue;
128 // Verify that the old chunks get deleted (we rely on NumChunksForTesting()).
129 // First, run the loop with default history size, which is zero chunks.
130 for (size_t i = 0; i < 100; ++i) {
131 au_queue.PushBack(CreateDemuxerData(chunk, ARRAY_SIZE(chunk)));
132 for (size_t j = 0; j < ARRAY_SIZE(chunk); ++j)
133 au_queue.Advance();
135 EXPECT_EQ(0U, au_queue.NumChunksForTesting());
138 // Change the history size and run again.
139 au_queue.SetHistorySizeForTesting(5);
141 for (size_t i = 0; i < 100; ++i) {
142 au_queue.PushBack(CreateDemuxerData(chunk, ARRAY_SIZE(chunk)));
143 for (size_t j = 0; j < ARRAY_SIZE(chunk); ++j)
144 au_queue.Advance();
146 if (i < 4)
147 EXPECT_EQ(i + 1, au_queue.NumChunksForTesting());
148 else
149 EXPECT_EQ(5U, au_queue.NumChunksForTesting());
153 TEST_F(AccessUnitQueueTest, PushAfterStarvation) {
154 // Two chunks
155 AUDescriptor chunk[][4] = {
156 {{kNormal, "0"}, {kNormal, "1"}, {kNormal, "2"}, {kNormal, "3"}},
157 {{kNormal, "4"}, {kNormal, "5"}, {kNormal, "6"}, {kNormal, "7"}}};
159 AccessUnitQueue au_queue;
161 // Push the first chunk.
162 au_queue.PushBack(CreateDemuxerData(chunk[0], ARRAY_SIZE(chunk[0])));
164 // Advance past the end of queue.
165 for (size_t i = 0; i < ARRAY_SIZE(chunk[0]); ++i)
166 au_queue.Advance();
168 // An extra Advance() should not change anything.
169 au_queue.Advance();
171 // Push the second chunk
172 au_queue.PushBack(CreateDemuxerData(chunk[1], ARRAY_SIZE(chunk[1])));
174 // Verify that we get the next access unit.
175 AccessUnitQueue::Info info = au_queue.GetInfo();
176 VERIFY_FIRST_BYTE('4', info);
179 TEST_F(AccessUnitQueueTest, HasEOS) {
180 // Two chunks
181 AUDescriptor chunk[][4] = {
182 {{kNormal, "0"}, {kNormal, "1"}, {kNormal, "2"}, {kNormal, "3"}},
183 {{kNormal, "4"}, {kNormal, "5"}, {kNormal, "6"}, {kEOS, "7"}}};
185 AccessUnitQueue au_queue;
186 au_queue.PushBack(CreateDemuxerData(chunk[0], ARRAY_SIZE(chunk[0])));
187 au_queue.PushBack(CreateDemuxerData(chunk[1], ARRAY_SIZE(chunk[1])));
189 // Verify that after EOS has been pushed into the queue,
190 // it is reported for every GetInfo()
191 for (int i = 0; i < 8; ++i) {
192 AccessUnitQueue::Info info = au_queue.GetInfo();
194 EXPECT_TRUE(info.has_eos);
195 EXPECT_EQ(nullptr, info.configs);
197 if (i == 7)
198 EXPECT_TRUE(info.front_unit->is_end_of_stream);
199 else
200 VERIFY_FIRST_BYTE('0' + i, info);
202 au_queue.Advance();
206 TEST_F(AccessUnitQueueTest, HasConfigs) {
207 AUDescriptor chunk[] = {
208 {kNormal, "0"}, {kNormal, "1"}, {kNormal, "2"}, {kConfig, "3"}};
210 AccessUnitQueue au_queue;
211 au_queue.PushBack(CreateDemuxerData(chunk, ARRAY_SIZE(chunk)));
213 for (int i = 0; i < 4; ++i) {
214 AccessUnitQueue::Info info = au_queue.GetInfo();
216 if (i != 3)
217 EXPECT_EQ(nullptr, info.configs);
218 else
219 EXPECT_NE(nullptr, info.configs);
221 au_queue.Advance();
225 TEST_F(AccessUnitQueueTest, ConfigsAndKeyFrame) {
226 // Two chunks
227 AUDescriptor chunk[][4] = {
228 {{kNormal, "0"}, {kKeyFrame, "1"}, {kNormal, "2"}, {kConfig, "3"}},
229 {{kKeyFrame, "4"}, {kNormal, "5"}, {kNormal, "6"}, {kNormal, "7"}}};
231 AccessUnitQueue::Info info;
233 AccessUnitQueue au_queue;
234 au_queue.PushBack(CreateDemuxerData(chunk[0], ARRAY_SIZE(chunk[0])));
235 au_queue.PushBack(CreateDemuxerData(chunk[1], ARRAY_SIZE(chunk[1])));
237 // There is no prior key frame
238 EXPECT_FALSE(au_queue.RewindToLastKeyFrame());
240 // Consume first access unit.
241 au_queue.Advance();
243 // Now the current one is the key frame. It would be safe to configure codec
244 // at this moment, so RewindToLastKeyFrame() should return true.
245 EXPECT_TRUE(au_queue.RewindToLastKeyFrame());
247 info = au_queue.GetInfo();
248 VERIFY_FIRST_BYTE('1', info);
250 au_queue.Advance(); // now current unit is "2"
252 info = au_queue.GetInfo();
253 VERIFY_FIRST_BYTE('2', info);
255 EXPECT_TRUE(au_queue.RewindToLastKeyFrame()); // should go back to "1"
257 info = au_queue.GetInfo();
258 VERIFY_FIRST_BYTE('1', info);
260 au_queue.Advance(); // now current unit is "2"
261 au_queue.Advance(); // now current unit is "3"
263 // Verify that we are at "3".
264 info = au_queue.GetInfo();
265 EXPECT_NE(nullptr, info.configs);
267 // Although it would be safe to configure codec (with old config) in this
268 // position since it will be immediately reconfigured from the next unit "3",
269 // current implementation returns unit "1".
271 EXPECT_TRUE(au_queue.RewindToLastKeyFrame()); // should go back to "1"
273 info = au_queue.GetInfo();
274 VERIFY_FIRST_BYTE('1', info);
276 au_queue.Advance(); // now current unit is "2"
277 au_queue.Advance(); // now current unit is "3"
278 au_queue.Advance(); // now current unit is "4"
280 info = au_queue.GetInfo();
281 VERIFY_FIRST_BYTE('4', info);
283 EXPECT_TRUE(au_queue.RewindToLastKeyFrame()); // should stay at "4"
285 info = au_queue.GetInfo();
286 VERIFY_FIRST_BYTE('4', info);
288 au_queue.Advance(); // now current unit is "5"
289 au_queue.Advance(); // now current unit is "6"
291 info = au_queue.GetInfo();
292 VERIFY_FIRST_BYTE('6', info);
294 EXPECT_TRUE(au_queue.RewindToLastKeyFrame()); // should go back to "4"
296 info = au_queue.GetInfo();
297 VERIFY_FIRST_BYTE('4', info);
300 TEST_F(AccessUnitQueueTest, KeyFrameWithLongHistory) {
301 // Four chunks
302 AUDescriptor chunk[][4] = {
303 {{kNormal, "0"}, {kKeyFrame, "1"}, {kNormal, "2"}, {kNormal, "3"}},
304 {{kNormal, "4"}, {kNormal, "5"}, {kNormal, "6"}, {kNormal, "7"}},
305 {{kNormal, "8"}, {kNormal, "9"}, {kNormal, "a"}, {kNormal, "b"}},
306 {{kNormal, "c"}, {kNormal, "d"}, {kKeyFrame, "e"}, {kNormal, "f"}}};
308 AccessUnitQueue::Info info;
310 AccessUnitQueue au_queue;
311 for (int i = 0; i < 4; ++i)
312 au_queue.PushBack(CreateDemuxerData(chunk[i], ARRAY_SIZE(chunk[i])));
314 au_queue.SetHistorySizeForTesting(3);
316 // Advance to '3'.
317 for (int i = 0; i < 3; ++i)
318 au_queue.Advance();
320 info = au_queue.GetInfo();
321 VERIFY_FIRST_BYTE('3', info);
323 // Rewind to key frame, the current unit should be '1'.
324 EXPECT_TRUE(au_queue.RewindToLastKeyFrame());
325 info = au_queue.GetInfo();
326 VERIFY_FIRST_BYTE('1', info);
328 // Advance to 'c'.
329 for (int i = 0; i < 11; ++i)
330 au_queue.Advance();
332 info = au_queue.GetInfo();
333 VERIFY_FIRST_BYTE('c', info);
335 // Rewind to key frame, the current unit should be '1' again.
336 EXPECT_TRUE(au_queue.RewindToLastKeyFrame());
337 info = au_queue.GetInfo();
338 VERIFY_FIRST_BYTE('1', info);
340 // Set history size to 0 (default)
341 au_queue.SetHistorySizeForTesting(0);
343 // Advance to 'd'. Should erase all chunks except the last.
344 for (int i = 0; i < 12; ++i)
345 au_queue.Advance();
347 info = au_queue.GetInfo();
348 VERIFY_FIRST_BYTE('d', info);
350 // Rewind should not find any key frames.
351 EXPECT_FALSE(au_queue.RewindToLastKeyFrame());
353 au_queue.Advance(); // Advance to key frame 'e'.
354 info = au_queue.GetInfo();
355 VERIFY_FIRST_BYTE('e', info);
357 // Rewind should find the same unit 'e.
358 EXPECT_TRUE(au_queue.RewindToLastKeyFrame());
359 info = au_queue.GetInfo();
360 VERIFY_FIRST_BYTE('e', info);
363 } // namespace media