diff options
Diffstat (limited to 'dom/media/gtest/TestMP4Reader.cpp')
-rw-r--r-- | dom/media/gtest/TestMP4Reader.cpp | 217 |
1 files changed, 217 insertions, 0 deletions
diff --git a/dom/media/gtest/TestMP4Reader.cpp b/dom/media/gtest/TestMP4Reader.cpp new file mode 100644 index 000000000..f08f7a40d --- /dev/null +++ b/dom/media/gtest/TestMP4Reader.cpp @@ -0,0 +1,217 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* 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 "MP4Reader.h" +#include "MP4Decoder.h" +#include "mozilla/SharedThreadPool.h" +#include "MockMediaResource.h" +#include "MockMediaDecoderOwner.h" +#include "mozilla/Preferences.h" +#include "TimeUnits.h" + +using namespace mozilla; +using namespace mozilla::dom; + +class TestBinding +{ +public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestBinding); + + RefPtr<MP4Decoder> decoder; + RefPtr<MockMediaResource> resource; + RefPtr<MP4Reader> reader; + + explicit TestBinding(const char* aFileName = "gizmo.mp4") + : decoder(new MP4Decoder()) + , resource(new MockMediaResource(aFileName)) + , reader(new MP4Reader(decoder)) + { + EXPECT_EQ(NS_OK, Preferences::SetBool( + "media.use-blank-decoder", true)); + + EXPECT_EQ(NS_OK, resource->Open(nullptr)); + decoder->SetResource(resource); + + reader->Init(nullptr); + // This needs to be done before invoking GetBuffered. This is normally + // done by MediaDecoderStateMachine. + reader->DispatchSetStartTime(0); + } + + void Init() { + nsCOMPtr<nsIThread> thread; + nsCOMPtr<nsIRunnable> r = NewRunnableMethod(this, &TestBinding::ReadMetadata); + nsresult rv = NS_NewThread(getter_AddRefs(thread), r); + EXPECT_EQ(NS_OK, rv); + thread->Shutdown(); + } + +private: + virtual ~TestBinding() + { + { + RefPtr<TaskQueue> queue = reader->OwnerThread(); + nsCOMPtr<nsIRunnable> task = NewRunnableMethod(reader, &MP4Reader::Shutdown); + // Hackily bypass the tail dispatcher so that we can AwaitShutdownAndIdle. + // In production code we'd use BeginShutdown + promises. + queue->Dispatch(task.forget(), AbstractThread::AssertDispatchSuccess, + AbstractThread::TailDispatch); + queue->AwaitShutdownAndIdle(); + } + decoder = nullptr; + resource = nullptr; + reader = nullptr; + SharedThreadPool::SpinUntilEmpty(); + } + + void ReadMetadata() + { + MediaInfo info; + MetadataTags* tags; + EXPECT_EQ(NS_OK, reader->ReadMetadata(&info, &tags)); + } +}; + +TEST(MP4Reader, BufferedRange) +{ + RefPtr<TestBinding> b = new TestBinding(); + b->Init(); + + // Video 3-4 sec, audio 2.986666-4.010666 sec + b->resource->MockAddBufferedRange(248400, 327455); + + media::TimeIntervals ranges = b->reader->GetBuffered(); + EXPECT_EQ(1U, ranges.Length()); + EXPECT_NEAR(270000 / 90000.0, ranges.Start(0).ToSeconds(), 0.000001); + EXPECT_NEAR(360000 / 90000.0, ranges.End(0).ToSeconds(), 0.000001); +} + +TEST(MP4Reader, BufferedRangeMissingLastByte) +{ + RefPtr<TestBinding> b = new TestBinding(); + b->Init(); + + // Dropping the last byte of the video + b->resource->MockClearBufferedRanges(); + b->resource->MockAddBufferedRange(248400, 324912); + b->resource->MockAddBufferedRange(324913, 327455); + + media::TimeIntervals ranges = b->reader->GetBuffered(); + EXPECT_EQ(1U, ranges.Length()); + EXPECT_NEAR(270000.0 / 90000.0, ranges.Start(0).ToSeconds(), 0.000001); + EXPECT_NEAR(357000 / 90000.0, ranges.End(0).ToSeconds(), 0.000001); +} + +TEST(MP4Reader, BufferedRangeSyncFrame) +{ + RefPtr<TestBinding> b = new TestBinding(); + b->Init(); + + // Check that missing the first byte at 2 seconds skips right through to 3 + // seconds because of a missing sync frame + b->resource->MockClearBufferedRanges(); + b->resource->MockAddBufferedRange(146336, 327455); + + media::TimeIntervals ranges = b->reader->GetBuffered(); + EXPECT_EQ(1U, ranges.Length()); + EXPECT_NEAR(270000.0 / 90000.0, ranges.Start(0).ToSeconds(), 0.000001); + EXPECT_NEAR(360000 / 90000.0, ranges.End(0).ToSeconds(), 0.000001); +} + +TEST(MP4Reader, CompositionOrder) +{ + RefPtr<TestBinding> b = new TestBinding("mediasource_test.mp4"); + b->Init(); + + // The first 5 video samples of this file are: + // Video timescale=2500 + // Frame Start Size Time Duration Sync + // 1 48 5455 166 83 Yes + // 2 5503 145 249 83 + // 3 6228 575 581 83 + // 4 7383 235 415 83 + // 5 8779 183 332 83 + // 6 9543 191 498 83 + // + // Audio timescale=44100 + // 1 5648 580 0 1024 Yes + // 2 6803 580 1024 1058 Yes + // 3 7618 581 2082 1014 Yes + // 4 8199 580 3096 1015 Yes + // 5 8962 581 4111 1014 Yes + // 6 9734 580 5125 1014 Yes + // 7 10314 581 6139 1059 Yes + // 8 11207 580 7198 1014 Yes + // 9 12035 581 8212 1014 Yes + // 10 12616 580 9226 1015 Yes + // 11 13220 581 10241 1014 Yes + + b->resource->MockClearBufferedRanges(); + // First two frames in decoding + first audio frame + b->resource->MockAddBufferedRange(48, 5503); // Video 1 + b->resource->MockAddBufferedRange(5503, 5648); // Video 2 + b->resource->MockAddBufferedRange(6228, 6803); // Video 3 + + // Audio - 5 frames; 0 - 139206 us + b->resource->MockAddBufferedRange(5648, 6228); + b->resource->MockAddBufferedRange(6803, 7383); + b->resource->MockAddBufferedRange(7618, 8199); + b->resource->MockAddBufferedRange(8199, 8779); + b->resource->MockAddBufferedRange(8962, 9563); + b->resource->MockAddBufferedRange(9734, 10314); + b->resource->MockAddBufferedRange(10314, 10895); + b->resource->MockAddBufferedRange(11207, 11787); + b->resource->MockAddBufferedRange(12035, 12616); + b->resource->MockAddBufferedRange(12616, 13196); + b->resource->MockAddBufferedRange(13220, 13901); + + media::TimeIntervals ranges = b->reader->GetBuffered(); + EXPECT_EQ(2U, ranges.Length()); + + EXPECT_NEAR(166.0 / 2500.0, ranges.Start(0).ToSeconds(), 0.000001); + EXPECT_NEAR(332.0 / 2500.0, ranges.End(0).ToSeconds(), 0.000001); + + EXPECT_NEAR(581.0 / 2500.0, ranges.Start(1).ToSeconds(), 0.000001); + EXPECT_NEAR(11255.0 / 44100.0, ranges.End(1).ToSeconds(), 0.000001); +} + +TEST(MP4Reader, Normalised) +{ + RefPtr<TestBinding> b = new TestBinding("mediasource_test.mp4"); + b->Init(); + + // The first 5 video samples of this file are: + // Video timescale=2500 + // Frame Start Size Time Duration Sync + // 1 48 5455 166 83 Yes + // 2 5503 145 249 83 + // 3 6228 575 581 83 + // 4 7383 235 415 83 + // 5 8779 183 332 83 + // 6 9543 191 498 83 + // + // Audio timescale=44100 + // 1 5648 580 0 1024 Yes + // 2 6803 580 1024 1058 Yes + // 3 7618 581 2082 1014 Yes + // 4 8199 580 3096 1015 Yes + // 5 8962 581 4111 1014 Yes + // 6 9734 580 5125 1014 Yes + // 7 10314 581 6139 1059 Yes + // 8 11207 580 7198 1014 Yes + // 9 12035 581 8212 1014 Yes + // 10 12616 580 9226 1015 Yes + // 11 13220 581 10241 1014 Yes + + b->resource->MockClearBufferedRanges(); + b->resource->MockAddBufferedRange(48, 13901); + + media::TimeIntervals ranges = b->reader->GetBuffered(); + EXPECT_EQ(1U, ranges.Length()); + + EXPECT_NEAR(166.0 / 2500.0, ranges.Start(0).ToSeconds(), 0.000001); + EXPECT_NEAR(11255.0 / 44100.0, ranges.End(0).ToSeconds(), 0.000001); +} |