diff options
Diffstat (limited to 'dom/media/gtest/TestMediaQueue.cpp')
-rw-r--r-- | dom/media/gtest/TestMediaQueue.cpp | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/dom/media/gtest/TestMediaQueue.cpp b/dom/media/gtest/TestMediaQueue.cpp new file mode 100644 index 0000000000..5b049dc7fe --- /dev/null +++ b/dom/media/gtest/TestMediaQueue.cpp @@ -0,0 +1,288 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <gtest/gtest.h> + +#include "MediaData.h" +#include "MediaQueue.h" + +using namespace mozilla; +using mozilla::media::TimeUnit; + +MediaData* CreateDataRawPtr( + int64_t aStartTime, int64_t aEndTime, + MediaData::Type aType = MediaData::Type::NULL_DATA) { + const TimeUnit startTime = TimeUnit::FromMicroseconds(aStartTime); + const TimeUnit endTime = TimeUnit::FromMicroseconds(aEndTime); + MediaData* data; + if (aType == MediaData::Type::AUDIO_DATA) { + AlignedAudioBuffer samples; + data = new AudioData(0, startTime, std::move(samples), 2, 44100); + data->mDuration = endTime - startTime; + } else if (aType == MediaData::Type::VIDEO_DATA) { + data = new VideoData(0, startTime, endTime - startTime, true, startTime, + gfx::IntSize(), 0); + } else { + data = new NullData(0, startTime, endTime - startTime); + } + return data; +} + +already_AddRefed<MediaData> CreateData(int64_t aStartTime, int64_t aEndTime) { + RefPtr<MediaData> data = CreateDataRawPtr(aStartTime, aEndTime); + return data.forget(); +} + +// Used to avoid the compile error `comparison of integers of different signs` +// when comparing 'const unsigned long' and 'const int'. +#define EXPECT_EQUAL_SIZE_T(lhs, rhs) EXPECT_EQ(size_t(lhs), size_t(rhs)) + +TEST(MediaQueue, BasicPopOperations) +{ + MediaQueue<MediaData> queue; + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 0); + + // Test only one element + const RefPtr<MediaData> data = CreateDataRawPtr(0, 10); + queue.Push(data.get()); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 1); + + RefPtr<MediaData> rv = queue.PopFront(); + EXPECT_EQ(rv, data); + + queue.Push(data.get()); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 1); + + rv = queue.PopBack(); + EXPECT_EQ(rv, data); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 0); + + // Test multiple elements + const RefPtr<MediaData> data1 = CreateDataRawPtr(0, 10); + const RefPtr<MediaData> data2 = CreateDataRawPtr(11, 20); + const RefPtr<MediaData> data3 = CreateDataRawPtr(21, 30); + queue.Push(data1.get()); + queue.Push(data2.get()); + queue.Push(data3.get()); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 3); + + rv = queue.PopFront(); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 2); + EXPECT_EQ(rv, data1); + + rv = queue.PopBack(); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 1); + EXPECT_EQ(rv, data3); + + rv = queue.PopBack(); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 0); + EXPECT_EQ(rv, data2); +} + +TEST(MediaQueue, BasicPeekOperations) +{ + MediaQueue<MediaData> queue; + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 0); + + // Test only one element + const RefPtr<MediaData> data1 = CreateDataRawPtr(0, 10); + queue.Push(data1.get()); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 1); + + RefPtr<MediaData> rv = queue.PeekFront(); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 1); + EXPECT_EQ(rv, data1); + + rv = queue.PeekBack(); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 1); + EXPECT_EQ(rv, data1); + + // Test multiple elements + const RefPtr<MediaData> data2 = CreateDataRawPtr(11, 20); + const RefPtr<MediaData> data3 = CreateDataRawPtr(21, 30); + queue.Push(data2.get()); + queue.Push(data3.get()); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 3); + + rv = queue.PeekFront(); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 3); + EXPECT_EQ(rv, data1); + + rv = queue.PeekBack(); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 3); + EXPECT_EQ(rv, data3); +} + +TEST(MediaQueue, FinishQueue) +{ + MediaQueue<MediaData> queue; + EXPECT_FALSE(queue.IsFinished()); + + queue.Finish(); + EXPECT_TRUE(queue.IsFinished()); +} + +TEST(MediaQueue, EndOfStream) +{ + MediaQueue<MediaData> queue; + EXPECT_FALSE(queue.IsFinished()); + + queue.Push(CreateData(0, 10)); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 1); + + queue.Finish(); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 1); + EXPECT_TRUE(queue.IsFinished()); + EXPECT_FALSE(queue.AtEndOfStream()); + + RefPtr<MediaData> rv = queue.PopFront(); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 0); + EXPECT_TRUE(queue.IsFinished()); + EXPECT_TRUE(queue.AtEndOfStream()); +} + +TEST(MediaQueue, QueueDuration) +{ + MediaQueue<MediaData> queue; + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 0); + + queue.Push(CreateData(0, 10)); + queue.Push(CreateData(11, 20)); + queue.Push(CreateData(21, 30)); + EXPECT_EQUAL_SIZE_T(queue.GetSize(), 3); + + const int64_t rv = queue.Duration(); + EXPECT_EQ(rv, 30); +} + +TEST(MediaQueue, CallGetElementAfterOnSingleElement) +{ + MediaQueue<MediaData> queue; + queue.Push(CreateData(0, 10)); + + // Target time is earlier than data's end time + TimeUnit targetTime = TimeUnit::FromMicroseconds(5); + nsTArray<RefPtr<MediaData>> foundResult; + queue.GetElementsAfter(targetTime, &foundResult); + EXPECT_EQUAL_SIZE_T(foundResult.Length(), 1); + EXPECT_TRUE(foundResult[0]->GetEndTime() > targetTime); + + // Target time is later than data's end time + targetTime = TimeUnit::FromMicroseconds(15); + nsTArray<RefPtr<MediaData>> emptyResult; + queue.GetElementsAfter(targetTime, &emptyResult); + EXPECT_TRUE(emptyResult.IsEmpty()); +} + +TEST(MediaQueue, CallGetElementAfterOnMultipleElements) +{ + MediaQueue<MediaData> queue; + queue.Push(CreateData(0, 10)); + queue.Push(CreateData(11, 20)); + queue.Push(CreateData(21, 30)); + queue.Push(CreateData(31, 40)); + queue.Push(CreateData(41, 50)); + + // Should find [21,30], [31,40] and [41,50] + TimeUnit targetTime = TimeUnit::FromMicroseconds(25); + nsTArray<RefPtr<MediaData>> foundResult; + queue.GetElementsAfter(targetTime, &foundResult); + EXPECT_EQUAL_SIZE_T(foundResult.Length(), 3); + for (const auto& data : foundResult) { + EXPECT_TRUE(data->GetEndTime() > targetTime); + } + + // Should find [31,40] and [41,50] + targetTime = TimeUnit::FromMicroseconds(30); + foundResult.Clear(); + queue.GetElementsAfter(targetTime, &foundResult); + EXPECT_EQUAL_SIZE_T(foundResult.Length(), 2); + for (const auto& data : foundResult) { + EXPECT_TRUE(data->GetEndTime() > targetTime); + } + + // Should find no data. + targetTime = TimeUnit::FromMicroseconds(60); + nsTArray<RefPtr<MediaData>> emptyResult; + queue.GetElementsAfter(targetTime, &emptyResult); + EXPECT_TRUE(emptyResult.IsEmpty()); +} + +TEST(MediaQueue, TimestampAdjustmentForSupportDataType) +{ + const size_t kOffSet = 30; + { + MediaQueue<AudioData> audioQueue; + audioQueue.Push( + CreateDataRawPtr(0, 10, MediaData::Type::AUDIO_DATA)->As<AudioData>()); + audioQueue.SetOffset(TimeUnit::FromMicroseconds(kOffSet)); + audioQueue.Push( + CreateDataRawPtr(0, 10, MediaData::Type::AUDIO_DATA)->As<AudioData>()); + + // Data stored before setting the offset shouldn't be changed + RefPtr<AudioData> data = audioQueue.PopFront(); + EXPECT_EQ(data->mTime, TimeUnit::FromMicroseconds(0)); + EXPECT_EQ(data->GetEndTime(), TimeUnit::FromMicroseconds(10)); + + // Data stored after setting the offset should be changed + data = audioQueue.PopFront(); + EXPECT_EQ(data->mTime, TimeUnit::FromMicroseconds(0 + kOffSet)); + EXPECT_EQ(data->GetEndTime(), TimeUnit::FromMicroseconds(10 + kOffSet)); + + // Reset will clean the offset. + audioQueue.Reset(); + audioQueue.Push( + CreateDataRawPtr(0, 10, MediaData::Type::AUDIO_DATA)->As<AudioData>()); + data = audioQueue.PopFront(); + EXPECT_EQ(data->mTime, TimeUnit::FromMicroseconds(0)); + EXPECT_EQ(data->GetEndTime(), TimeUnit::FromMicroseconds(10)); + } + + // Check another supported type + MediaQueue<VideoData> videoQueue; + videoQueue.Push( + CreateDataRawPtr(0, 10, MediaData::Type::VIDEO_DATA)->As<VideoData>()); + videoQueue.SetOffset(TimeUnit::FromMicroseconds(kOffSet)); + videoQueue.Push( + CreateDataRawPtr(0, 10, MediaData::Type::VIDEO_DATA)->As<VideoData>()); + + // Data stored before setting the offset shouldn't be changed + RefPtr<VideoData> data = videoQueue.PopFront(); + EXPECT_EQ(data->mTime, TimeUnit::FromMicroseconds(0)); + EXPECT_EQ(data->GetEndTime(), TimeUnit::FromMicroseconds(10)); + + // Data stored after setting the offset should be changed + data = videoQueue.PopFront(); + EXPECT_EQ(data->mTime, TimeUnit::FromMicroseconds(0 + kOffSet)); + EXPECT_EQ(data->GetEndTime(), TimeUnit::FromMicroseconds(10 + kOffSet)); + + // Reset will clean the offset. + videoQueue.Reset(); + videoQueue.Push( + CreateDataRawPtr(0, 10, MediaData::Type::VIDEO_DATA)->As<VideoData>()); + data = videoQueue.PopFront(); + EXPECT_EQ(data->mTime, TimeUnit::FromMicroseconds(0)); + EXPECT_EQ(data->GetEndTime(), TimeUnit::FromMicroseconds(10)); +} + +TEST(MediaQueue, TimestampAdjustmentForNotSupportDataType) +{ + const size_t kOffSet = 30; + + MediaQueue<MediaData> queue; + queue.Push(CreateDataRawPtr(0, 10)); + queue.SetOffset(TimeUnit::FromMicroseconds(kOffSet)); + queue.Push(CreateDataRawPtr(0, 10)); + + // Offset won't affect any data at all. + RefPtr<MediaData> data = queue.PopFront(); + EXPECT_EQ(data->mTime, TimeUnit::FromMicroseconds(0)); + EXPECT_EQ(data->GetEndTime(), TimeUnit::FromMicroseconds(10)); + + data = queue.PopFront(); + EXPECT_EQ(data->mTime, TimeUnit::FromMicroseconds(0)); + EXPECT_EQ(data->GetEndTime(), TimeUnit::FromMicroseconds(10)); +} + +#undef EXPECT_EQUAL_SIZE_T |