TestMediaQueue.cpp (9774B)
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include <gtest/gtest.h> 8 9 #include "MediaData.h" 10 #include "MediaQueue.h" 11 #include "nsISupportsImpl.h" 12 13 using namespace mozilla; 14 using mozilla::media::TimeUnit; 15 16 MediaData* CreateDataRawPtr( 17 int64_t aStartTime, int64_t aEndTime, 18 MediaData::Type aType = MediaData::Type::NULL_DATA) { 19 const TimeUnit startTime = TimeUnit::FromMicroseconds(aStartTime); 20 const TimeUnit endTime = TimeUnit::FromMicroseconds(aEndTime); 21 MediaData* data; 22 if (aType == MediaData::Type::AUDIO_DATA) { 23 AlignedAudioBuffer samples; 24 data = new AudioData(0, startTime, std::move(samples), 2, 44100); 25 data->mDuration = endTime - startTime; 26 } else if (aType == MediaData::Type::VIDEO_DATA) { 27 data = new VideoData(0, startTime, endTime - startTime, true, startTime, 28 gfx::IntSize(), 0); 29 } else { 30 data = new NullData(0, startTime, endTime - startTime); 31 } 32 return data; 33 } 34 35 already_AddRefed<MediaData> CreateData(int64_t aStartTime, int64_t aEndTime) { 36 RefPtr<MediaData> data = CreateDataRawPtr(aStartTime, aEndTime); 37 return data.forget(); 38 } 39 40 // Used to avoid the compile error `comparison of integers of different signs` 41 // when comparing 'const unsigned long' and 'const int'. 42 #define EXPECT_EQUAL_SIZE_T(lhs, rhs) EXPECT_EQ(size_t(lhs), size_t(rhs)) 43 44 TEST(MediaQueue, BasicPopOperations) 45 { 46 MediaQueue<MediaData> queue; 47 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 0); 48 49 // Test only one element 50 const RefPtr<MediaData> data = CreateDataRawPtr(0, 10); 51 queue.Push(data.get()); 52 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 1); 53 54 RefPtr<MediaData> rv = queue.PopFront(); 55 EXPECT_EQ(rv, data); 56 57 queue.Push(data.get()); 58 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 1); 59 60 rv = queue.PopBack(); 61 EXPECT_EQ(rv, data); 62 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 0); 63 64 // Test multiple elements 65 const RefPtr<MediaData> data1 = CreateDataRawPtr(0, 10); 66 const RefPtr<MediaData> data2 = CreateDataRawPtr(11, 20); 67 const RefPtr<MediaData> data3 = CreateDataRawPtr(21, 30); 68 queue.Push(data1.get()); 69 queue.Push(data2.get()); 70 queue.Push(data3.get()); 71 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 3); 72 73 rv = queue.PopFront(); 74 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 2); 75 EXPECT_EQ(rv, data1); 76 77 rv = queue.PopBack(); 78 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 1); 79 EXPECT_EQ(rv, data3); 80 81 rv = queue.PopBack(); 82 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 0); 83 EXPECT_EQ(rv, data2); 84 } 85 86 TEST(MediaQueue, BasicPeekOperations) 87 { 88 MediaQueue<MediaData> queue; 89 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 0); 90 91 // Test only one element 92 const RefPtr<MediaData> data1 = CreateDataRawPtr(0, 10); 93 queue.Push(data1.get()); 94 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 1); 95 96 RefPtr<MediaData> rv = queue.PeekFront(); 97 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 1); 98 EXPECT_EQ(rv, data1); 99 100 rv = queue.PeekBack(); 101 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 1); 102 EXPECT_EQ(rv, data1); 103 104 // Test multiple elements 105 const RefPtr<MediaData> data2 = CreateDataRawPtr(11, 20); 106 const RefPtr<MediaData> data3 = CreateDataRawPtr(21, 30); 107 queue.Push(data2.get()); 108 queue.Push(data3.get()); 109 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 3); 110 111 rv = queue.PeekFront(); 112 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 3); 113 EXPECT_EQ(rv, data1); 114 115 rv = queue.PeekBack(); 116 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 3); 117 EXPECT_EQ(rv, data3); 118 } 119 120 TEST(MediaQueue, FinishQueue) 121 { 122 MediaQueue<MediaData> queue; 123 EXPECT_FALSE(queue.IsFinished()); 124 125 queue.Finish(); 126 EXPECT_TRUE(queue.IsFinished()); 127 } 128 129 TEST(MediaQueue, EndOfStream) 130 { 131 MediaQueue<MediaData> queue; 132 EXPECT_FALSE(queue.IsFinished()); 133 134 queue.Push(CreateData(0, 10)); 135 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 1); 136 137 queue.Finish(); 138 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 1); 139 EXPECT_TRUE(queue.IsFinished()); 140 EXPECT_FALSE(queue.AtEndOfStream()); 141 142 RefPtr<MediaData> rv = queue.PopFront(); 143 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 0); 144 EXPECT_TRUE(queue.IsFinished()); 145 EXPECT_TRUE(queue.AtEndOfStream()); 146 } 147 148 TEST(MediaQueue, QueueDuration) 149 { 150 MediaQueue<MediaData> queue; 151 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 0); 152 153 queue.Push(CreateData(0, 10)); 154 queue.Push(CreateData(11, 20)); 155 queue.Push(CreateData(21, 30)); 156 EXPECT_EQUAL_SIZE_T(queue.GetSize(), 3); 157 158 const int64_t rv = queue.Duration(); 159 EXPECT_EQ(rv, 30); 160 } 161 162 TEST(MediaQueue, CallGetElementAfterOnSingleElement) 163 { 164 MediaQueue<MediaData> queue; 165 queue.Push(CreateData(0, 10)); 166 167 // Target time is earlier than data's end time 168 TimeUnit targetTime = TimeUnit::FromMicroseconds(5); 169 nsTArray<RefPtr<MediaData>> foundResult; 170 queue.GetElementsAfter(targetTime, &foundResult); 171 EXPECT_EQUAL_SIZE_T(foundResult.Length(), 1); 172 EXPECT_TRUE(foundResult[0]->GetEndTime() > targetTime); 173 174 // Target time is later than data's end time 175 targetTime = TimeUnit::FromMicroseconds(15); 176 nsTArray<RefPtr<MediaData>> emptyResult; 177 queue.GetElementsAfter(targetTime, &emptyResult); 178 EXPECT_TRUE(emptyResult.IsEmpty()); 179 } 180 181 TEST(MediaQueue, CallGetElementAfterOnMultipleElements) 182 { 183 MediaQueue<MediaData> queue; 184 queue.Push(CreateData(0, 10)); 185 queue.Push(CreateData(11, 20)); 186 queue.Push(CreateData(21, 30)); 187 queue.Push(CreateData(31, 40)); 188 queue.Push(CreateData(41, 50)); 189 190 // Should find [21,30], [31,40] and [41,50] 191 TimeUnit targetTime = TimeUnit::FromMicroseconds(25); 192 nsTArray<RefPtr<MediaData>> foundResult; 193 queue.GetElementsAfter(targetTime, &foundResult); 194 EXPECT_EQUAL_SIZE_T(foundResult.Length(), 3); 195 for (const auto& data : foundResult) { 196 EXPECT_TRUE(data->GetEndTime() > targetTime); 197 } 198 199 // Should find [31,40] and [41,50] 200 targetTime = TimeUnit::FromMicroseconds(30); 201 foundResult.Clear(); 202 queue.GetElementsAfter(targetTime, &foundResult); 203 EXPECT_EQUAL_SIZE_T(foundResult.Length(), 2); 204 for (const auto& data : foundResult) { 205 EXPECT_TRUE(data->GetEndTime() > targetTime); 206 } 207 208 // Should find no data. 209 targetTime = TimeUnit::FromMicroseconds(60); 210 nsTArray<RefPtr<MediaData>> emptyResult; 211 queue.GetElementsAfter(targetTime, &emptyResult); 212 EXPECT_TRUE(emptyResult.IsEmpty()); 213 } 214 215 TEST(MediaQueue, TimestampAdjustmentForSupportDataType) 216 { 217 const size_t kOffSet = 30; 218 { 219 MediaQueue<AudioData> audioQueue; 220 audioQueue.Push( 221 CreateDataRawPtr(0, 10, MediaData::Type::AUDIO_DATA)->As<AudioData>()); 222 audioQueue.SetOffset(TimeUnit::FromMicroseconds(kOffSet)); 223 audioQueue.Push( 224 CreateDataRawPtr(0, 10, MediaData::Type::AUDIO_DATA)->As<AudioData>()); 225 226 // Data stored before setting the offset shouldn't be changed 227 RefPtr<AudioData> data = audioQueue.PopFront(); 228 EXPECT_EQ(data->mTime, TimeUnit::FromMicroseconds(0)); 229 EXPECT_EQ(data->GetEndTime(), TimeUnit::FromMicroseconds(10)); 230 231 // Data stored after setting the offset should be changed 232 data = audioQueue.PopFront(); 233 EXPECT_EQ(data->mTime, TimeUnit::FromMicroseconds(0 + kOffSet)); 234 EXPECT_EQ(data->GetEndTime(), TimeUnit::FromMicroseconds(10 + kOffSet)); 235 236 // Reset will clean the offset. 237 audioQueue.Reset(); 238 audioQueue.Push( 239 CreateDataRawPtr(0, 10, MediaData::Type::AUDIO_DATA)->As<AudioData>()); 240 data = audioQueue.PopFront(); 241 EXPECT_EQ(data->mTime, TimeUnit::FromMicroseconds(0)); 242 EXPECT_EQ(data->GetEndTime(), TimeUnit::FromMicroseconds(10)); 243 } 244 245 // Check another supported type 246 MediaQueue<VideoData> videoQueue; 247 videoQueue.Push( 248 CreateDataRawPtr(0, 10, MediaData::Type::VIDEO_DATA)->As<VideoData>()); 249 videoQueue.SetOffset(TimeUnit::FromMicroseconds(kOffSet)); 250 videoQueue.Push( 251 CreateDataRawPtr(0, 10, MediaData::Type::VIDEO_DATA)->As<VideoData>()); 252 253 // Data stored before setting the offset shouldn't be changed 254 RefPtr<VideoData> data = videoQueue.PopFront(); 255 EXPECT_EQ(data->mTime, TimeUnit::FromMicroseconds(0)); 256 EXPECT_EQ(data->GetEndTime(), TimeUnit::FromMicroseconds(10)); 257 258 // Data stored after setting the offset should be changed 259 data = videoQueue.PopFront(); 260 EXPECT_EQ(data->mTime, TimeUnit::FromMicroseconds(0 + kOffSet)); 261 EXPECT_EQ(data->GetEndTime(), TimeUnit::FromMicroseconds(10 + kOffSet)); 262 263 // Reset will clean the offset. 264 videoQueue.Reset(); 265 videoQueue.Push( 266 CreateDataRawPtr(0, 10, MediaData::Type::VIDEO_DATA)->As<VideoData>()); 267 data = videoQueue.PopFront(); 268 EXPECT_EQ(data->mTime, TimeUnit::FromMicroseconds(0)); 269 EXPECT_EQ(data->GetEndTime(), TimeUnit::FromMicroseconds(10)); 270 } 271 272 TEST(MediaQueue, TimestampAdjustmentForNotSupportDataType) 273 { 274 const size_t kOffSet = 30; 275 276 MediaQueue<MediaData> queue; 277 queue.Push(CreateDataRawPtr(0, 10)); 278 queue.SetOffset(TimeUnit::FromMicroseconds(kOffSet)); 279 queue.Push(CreateDataRawPtr(0, 10)); 280 281 // Offset won't affect any data at all. 282 RefPtr<MediaData> data = queue.PopFront(); 283 EXPECT_EQ(data->mTime, TimeUnit::FromMicroseconds(0)); 284 EXPECT_EQ(data->GetEndTime(), TimeUnit::FromMicroseconds(10)); 285 286 data = queue.PopFront(); 287 EXPECT_EQ(data->mTime, TimeUnit::FromMicroseconds(0)); 288 EXPECT_EQ(data->GetEndTime(), TimeUnit::FromMicroseconds(10)); 289 } 290 291 TEST(MediaQueue, PreciseDuration) 292 { 293 MediaQueue<MediaData> queueOff; 294 queueOff.Push(CreateDataRawPtr(5, 10)); 295 queueOff.Push(CreateDataRawPtr(0, 5)); 296 EXPECT_EQ(queueOff.Duration(), 0); 297 EXPECT_EQ(queueOff.PreciseDuration(), -1); 298 299 MediaQueue<MediaData> queueOn(true /* aEnablePreciseDuration */); 300 queueOn.Push(CreateDataRawPtr(5, 10)); 301 queueOn.Push(CreateDataRawPtr(0, 5)); 302 EXPECT_EQ(queueOn.Duration(), 0); 303 EXPECT_EQ(queueOn.PreciseDuration(), 10); 304 } 305 306 #undef EXPECT_EQUAL_SIZE_T