blob: 6357e4de097be7447b63227ced2310e5ccec5f91 [file] [log] [blame]
Linus Nilssoncb9198e2020-04-01 13:38:09 -07001/*
2 * Copyright (C) 2020 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17// Unit Test for MediaSampleQueue
18
19// #define LOG_NDEBUG 0
20#define LOG_TAG "MediaSampleQueueTests"
21
22#include <android-base/logging.h>
23#include <gtest/gtest.h>
24#include <media/MediaSampleQueue.h>
25
26#include <thread>
27
28namespace android {
29
30/** Duration to use when delaying threads to order operations. */
31static constexpr int64_t kThreadDelayDurationMs = 100;
32
33class MediaSampleQueueTests : public ::testing::Test {
34public:
35 MediaSampleQueueTests() { LOG(DEBUG) << "MediaSampleQueueTests created"; }
36 ~MediaSampleQueueTests() { LOG(DEBUG) << "MediaSampleQueueTests destroyed"; }
37};
38
39static std::shared_ptr<MediaSample> newSample(uint32_t id) {
40 return MediaSample::createWithReleaseCallback(nullptr /* buffer */, 0 /* offset */, id,
41 nullptr /* callback */);
42}
43
44TEST_F(MediaSampleQueueTests, TestSequentialDequeueOrder) {
45 LOG(DEBUG) << "TestSequentialDequeueOrder Starts";
46
47 static constexpr int kNumSamples = 4;
48 MediaSampleQueue sampleQueue;
Linus Nilssonb09aac22020-07-29 11:56:53 -070049 EXPECT_TRUE(sampleQueue.isEmpty());
Linus Nilssoncb9198e2020-04-01 13:38:09 -070050
51 // Enqueue loop.
52 for (int i = 0; i < kNumSamples; ++i) {
53 sampleQueue.enqueue(newSample(i));
Linus Nilssonb09aac22020-07-29 11:56:53 -070054 EXPECT_FALSE(sampleQueue.isEmpty());
Linus Nilssoncb9198e2020-04-01 13:38:09 -070055 }
56
57 // Dequeue loop.
58 for (int i = 0; i < kNumSamples; ++i) {
59 std::shared_ptr<MediaSample> sample;
60 bool aborted = sampleQueue.dequeue(&sample);
61 EXPECT_NE(sample, nullptr);
62 EXPECT_EQ(sample->bufferId, i);
63 EXPECT_FALSE(aborted);
64 }
Linus Nilssonb09aac22020-07-29 11:56:53 -070065 EXPECT_TRUE(sampleQueue.isEmpty());
Linus Nilssoncb9198e2020-04-01 13:38:09 -070066}
67
68TEST_F(MediaSampleQueueTests, TestInterleavedDequeueOrder) {
69 LOG(DEBUG) << "TestInterleavedDequeueOrder Starts";
70
71 static constexpr int kNumSamples = 4;
72 MediaSampleQueue sampleQueue;
73
74 // Enqueue and dequeue.
75 for (int i = 0; i < kNumSamples; ++i) {
76 sampleQueue.enqueue(newSample(i));
Linus Nilssonb09aac22020-07-29 11:56:53 -070077 EXPECT_FALSE(sampleQueue.isEmpty());
Linus Nilssoncb9198e2020-04-01 13:38:09 -070078
79 std::shared_ptr<MediaSample> sample;
80 bool aborted = sampleQueue.dequeue(&sample);
81 EXPECT_NE(sample, nullptr);
82 EXPECT_EQ(sample->bufferId, i);
83 EXPECT_FALSE(aborted);
Linus Nilssonb09aac22020-07-29 11:56:53 -070084 EXPECT_TRUE(sampleQueue.isEmpty());
Linus Nilssoncb9198e2020-04-01 13:38:09 -070085 }
86}
87
88TEST_F(MediaSampleQueueTests, TestBlockingDequeue) {
89 LOG(DEBUG) << "TestBlockingDequeue Starts";
90
91 MediaSampleQueue sampleQueue;
92
93 std::thread enqueueThread([&sampleQueue] {
94 // Note: This implementation is a bit racy. Any amount of sleep will not guarantee that the
95 // main thread will be blocked on the sample queue by the time this thread calls enqueue.
96 // But we can say with high confidence that it will and the test will not fail regardless.
97 std::this_thread::sleep_for(std::chrono::milliseconds(kThreadDelayDurationMs));
98 sampleQueue.enqueue(newSample(1));
99 });
100
101 std::shared_ptr<MediaSample> sample;
102 bool aborted = sampleQueue.dequeue(&sample);
103 EXPECT_NE(sample, nullptr);
104 EXPECT_EQ(sample->bufferId, 1);
105 EXPECT_FALSE(aborted);
Linus Nilssonb09aac22020-07-29 11:56:53 -0700106 EXPECT_TRUE(sampleQueue.isEmpty());
Linus Nilssoncb9198e2020-04-01 13:38:09 -0700107
108 enqueueThread.join();
109}
110
111TEST_F(MediaSampleQueueTests, TestDequeueBufferRelease) {
112 LOG(DEBUG) << "TestDequeueBufferRelease Starts";
113
114 static constexpr int kNumSamples = 4;
115 std::vector<bool> bufferReleased(kNumSamples, false);
116
117 MediaSample::OnSampleReleasedCallback callback = [&bufferReleased](MediaSample* sample) {
118 bufferReleased[sample->bufferId] = true;
119 };
120
121 MediaSampleQueue sampleQueue;
122 for (int i = 0; i < kNumSamples; ++i) {
123 bool aborted = sampleQueue.enqueue(
124 MediaSample::createWithReleaseCallback(nullptr, 0, i, callback));
125 EXPECT_FALSE(aborted);
126 }
127
128 for (int i = 0; i < kNumSamples; ++i) {
129 EXPECT_FALSE(bufferReleased[i]);
130 }
131
132 for (int i = 0; i < kNumSamples; ++i) {
133 {
134 std::shared_ptr<MediaSample> sample;
135 bool aborted = sampleQueue.dequeue(&sample);
136 EXPECT_NE(sample, nullptr);
137 EXPECT_EQ(sample->bufferId, i);
138 EXPECT_FALSE(bufferReleased[i]);
139 EXPECT_FALSE(aborted);
140 }
141
142 for (int j = 0; j < kNumSamples; ++j) {
143 EXPECT_EQ(bufferReleased[j], j <= i);
144 }
145 }
146}
147
148TEST_F(MediaSampleQueueTests, TestAbortBufferRelease) {
149 LOG(DEBUG) << "TestAbortBufferRelease Starts";
150
151 static constexpr int kNumSamples = 4;
152 std::vector<bool> bufferReleased(kNumSamples, false);
153
154 MediaSample::OnSampleReleasedCallback callback = [&bufferReleased](MediaSample* sample) {
155 bufferReleased[sample->bufferId] = true;
156 };
157
158 MediaSampleQueue sampleQueue;
159 for (int i = 0; i < kNumSamples; ++i) {
160 bool aborted = sampleQueue.enqueue(
161 MediaSample::createWithReleaseCallback(nullptr, 0, i, callback));
162 EXPECT_FALSE(aborted);
163 }
164
165 for (int i = 0; i < kNumSamples; ++i) {
166 EXPECT_FALSE(bufferReleased[i]);
167 }
168
Linus Nilssonb09aac22020-07-29 11:56:53 -0700169 EXPECT_FALSE(sampleQueue.isEmpty());
Linus Nilssoncb9198e2020-04-01 13:38:09 -0700170 sampleQueue.abort();
Linus Nilssonb09aac22020-07-29 11:56:53 -0700171 EXPECT_TRUE(sampleQueue.isEmpty());
Linus Nilssoncb9198e2020-04-01 13:38:09 -0700172
173 for (int i = 0; i < kNumSamples; ++i) {
174 EXPECT_TRUE(bufferReleased[i]);
175 }
176}
177
178TEST_F(MediaSampleQueueTests, TestNonEmptyAbort) {
179 LOG(DEBUG) << "TestNonEmptyAbort Starts";
180
181 MediaSampleQueue sampleQueue;
182 bool aborted = sampleQueue.enqueue(newSample(1));
183 EXPECT_FALSE(aborted);
184
185 sampleQueue.abort();
186
187 std::shared_ptr<MediaSample> sample;
188 aborted = sampleQueue.dequeue(&sample);
189 EXPECT_TRUE(aborted);
190 EXPECT_EQ(sample, nullptr);
191
192 aborted = sampleQueue.enqueue(sample);
193 EXPECT_TRUE(aborted);
194}
195
196TEST_F(MediaSampleQueueTests, TestEmptyAbort) {
197 LOG(DEBUG) << "TestEmptyAbort Starts";
198
199 MediaSampleQueue sampleQueue;
200 sampleQueue.abort();
201
202 std::shared_ptr<MediaSample> sample;
203 bool aborted = sampleQueue.dequeue(&sample);
204 EXPECT_TRUE(aborted);
205 EXPECT_EQ(sample, nullptr);
206
207 aborted = sampleQueue.enqueue(sample);
208 EXPECT_TRUE(aborted);
209}
210
211TEST_F(MediaSampleQueueTests, TestBlockingAbort) {
212 LOG(DEBUG) << "TestBlockingAbort Starts";
213
214 MediaSampleQueue sampleQueue;
215
216 std::thread abortingThread([&sampleQueue] {
217 // Note: This implementation is a bit racy. Any amount of sleep will not guarantee that the
218 // main thread will be blocked on the sample queue by the time this thread calls abort.
219 // But we can say with high confidence that it will and the test will not fail regardless.
220 std::this_thread::sleep_for(std::chrono::milliseconds(kThreadDelayDurationMs));
221 sampleQueue.abort();
222 });
223
224 std::shared_ptr<MediaSample> sample;
225 bool aborted = sampleQueue.dequeue(&sample);
226 EXPECT_TRUE(aborted);
227 EXPECT_EQ(sample, nullptr);
228
229 abortingThread.join();
230}
231
232} // namespace android
233
234int main(int argc, char** argv) {
235 ::testing::InitGoogleTest(&argc, argv);
236 return RUN_ALL_TESTS();
237}