1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=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 https://mozilla.org/MPL/2.0/. */
6 
7 #include "gtest/gtest.h"
8 #include "DriftCompensation.h"
9 
10 using namespace mozilla;
11 
12 class DriftCompensatorTest : public ::testing::Test {
13  public:
14   const TrackRate mRate = 44100;
15   const TimeStamp mStart;
16   const RefPtr<DriftCompensator> mComp;
17 
DriftCompensatorTest()18   DriftCompensatorTest()
19       : mStart(TimeStamp::Now()),
20         mComp(MakeRefPtr<DriftCompensator>(GetCurrentThreadEventTarget(),
21                                            mRate)) {
22     mComp->NotifyAudioStart(mStart);
23     // NotifyAudioStart dispatched a runnable to update the audio mStart time on
24     // the video thread. Because this is a test, the video thread is the current
25     // thread. We spin the event loop until we know the mStart time is updated.
26     {
27       bool updated = false;
28       NS_DispatchToCurrentThread(
29           NS_NewRunnableFunction(__func__, [&] { updated = true; }));
30       SpinEventLoopUntil([&] { return updated; });
31     }
32   }
33 
34   // Past() is half as far from `mStart` as `aNow`.
Past(TimeStamp aNow)35   TimeStamp Past(TimeStamp aNow) {
36     return mStart + (aNow - mStart) / (int64_t)2;
37   }
38 
39   // Future() is twice as far from `mStart` as `aNow`.
Future(TimeStamp aNow)40   TimeStamp Future(TimeStamp aNow) { return mStart + (aNow - mStart) * 2; }
41 };
42 
TEST_F(DriftCompensatorTest,Initialized)43 TEST_F(DriftCompensatorTest, Initialized) {
44   EXPECT_EQ(mComp->GetVideoTime(mStart, mStart), mStart);
45 }
46 
TEST_F(DriftCompensatorTest,SlowerAudio)47 TEST_F(DriftCompensatorTest, SlowerAudio) {
48   // 10s of audio took 20 seconds of wall clock to play out
49   mComp->NotifyAudio(mRate * 10);
50   TimeStamp now = mStart + TimeDuration::FromSeconds(20);
51   EXPECT_EQ((mComp->GetVideoTime(now, mStart) - mStart).ToSeconds(), 0.0);
52   EXPECT_EQ((mComp->GetVideoTime(now, Past(now)) - mStart).ToSeconds(), 5.0);
53   EXPECT_EQ((mComp->GetVideoTime(now, now) - mStart).ToSeconds(), 10.0);
54   EXPECT_EQ((mComp->GetVideoTime(now, Future(now)) - mStart).ToSeconds(), 20.0);
55 }
56 
TEST_F(DriftCompensatorTest,NoDrift)57 TEST_F(DriftCompensatorTest, NoDrift) {
58   // 10s of audio took 10 seconds of wall clock to play out
59   mComp->NotifyAudio(mRate * 10);
60   TimeStamp now = mStart + TimeDuration::FromSeconds(10);
61   EXPECT_EQ((mComp->GetVideoTime(now, mStart) - mStart).ToSeconds(), 0.0);
62   EXPECT_EQ((mComp->GetVideoTime(now, Past(now)) - mStart).ToSeconds(), 5.0);
63   EXPECT_EQ((mComp->GetVideoTime(now, now) - mStart).ToSeconds(), 10.0);
64   EXPECT_EQ((mComp->GetVideoTime(now, Future(now)) - mStart).ToSeconds(), 20.0);
65 }
66 
TEST_F(DriftCompensatorTest,NoProgress)67 TEST_F(DriftCompensatorTest, NoProgress) {
68   // 10s of audio took 0 seconds of wall clock to play out
69   mComp->NotifyAudio(mRate * 10);
70   TimeStamp now = mStart;
71   TimeStamp future = mStart + TimeDuration::FromSeconds(5);
72   EXPECT_EQ((mComp->GetVideoTime(now, mStart) - mStart).ToSeconds(), 0.0);
73   EXPECT_EQ((mComp->GetVideoTime(now, future) - mStart).ToSeconds(), 5.0);
74 }
75 
TEST_F(DriftCompensatorTest,FasterAudio)76 TEST_F(DriftCompensatorTest, FasterAudio) {
77   // 20s of audio took 10 seconds of wall clock to play out
78   mComp->NotifyAudio(mRate * 20);
79   TimeStamp now = mStart + TimeDuration::FromSeconds(10);
80   EXPECT_EQ((mComp->GetVideoTime(now, mStart) - mStart).ToSeconds(), 0.0);
81   EXPECT_EQ((mComp->GetVideoTime(now, Past(now)) - mStart).ToSeconds(), 10.0);
82   EXPECT_EQ((mComp->GetVideoTime(now, now) - mStart).ToSeconds(), 20.0);
83   EXPECT_EQ((mComp->GetVideoTime(now, Future(now)) - mStart).ToSeconds(), 40.0);
84 }
85