Bug 1296531 - Add gtests for starting a video track at t > 0. r=jesup
authorAndreas Pehrson <pehrsons@gmail.com>
Tue, 16 May 2017 13:25:02 +0200
changeset 433803 fbb794b4ab77eb66d7c20f04fc895403d4b54132
parent 433802 9fb91aa67681f291a0693ecbccc6ec0462b6cdfb
child 433804 55682948b181377b5e77a554baf063757b3ccaa9
push id8114
push userjlorenzo@mozilla.com
push dateThu, 02 Nov 2017 16:33:21 +0000
treeherdermozilla-beta@73e0d89a540f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjesup
bugs1296531
milestone58.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1296531 - Add gtests for starting a video track at t > 0. r=jesup MozReview-Commit-ID: 4Nt4Ldcy4I6
dom/media/gtest/TestVideoTrackEncoder.cpp
--- a/dom/media/gtest/TestVideoTrackEncoder.cpp
+++ b/dom/media/gtest/TestVideoTrackEncoder.cpp
@@ -8,16 +8,18 @@
 #include "prtime.h"
 #include "mozilla/ArrayUtils.h"
 #include "VP8TrackEncoder.h"
 #include "ImageContainer.h"
 #include "MediaStreamGraph.h"
 #include "MediaStreamListener.h"
 #include "WebMWriter.h" // TODO: it's weird to include muxer header to get the class definition of VP8 METADATA
 
+#define VIDEO_TRACK_RATE 90000
+
 using ::testing::TestWithParam;
 using ::testing::Values;
 
 using namespace mozilla::layers;
 using namespace mozilla;
 
 // A helper object to generate of different YUV planes.
 class YUVBufferGenerator {
@@ -184,17 +186,17 @@ struct InitParam {
   bool mShouldSucceed;  // This parameter should cause success or fail result
   int  mWidth;          // frame width
   int  mHeight;         // frame height
 };
 
 class TestVP8TrackEncoder: public VP8TrackEncoder
 {
 public:
-  explicit TestVP8TrackEncoder(TrackRate aTrackRate = 90000)
+  explicit TestVP8TrackEncoder(TrackRate aTrackRate = VIDEO_TRACK_RATE)
     : VP8TrackEncoder(aTrackRate) {}
 
   ::testing::AssertionResult TestInit(const InitParam &aParam)
   {
     nsresult result = Init(aParam.mWidth, aParam.mHeight, aParam.mWidth, aParam.mHeight);
 
     if (((NS_FAILED(result) && aParam.mShouldSucceed)) || (NS_SUCCEEDED(result) && !aParam.mShouldSucceed))
     {
@@ -273,49 +275,49 @@ TEST(VP8VideoTrackEncoder, FrameEncode)
   // Put generated YUV frame into video segment.
   // Duration of each frame is 1 second.
   VideoSegment segment;
   TimeStamp now = TimeStamp::Now();
   for (nsTArray<RefPtr<Image>>::size_type i = 0; i < images.Length(); i++)
   {
     RefPtr<Image> image = images[i];
     segment.AppendFrame(image.forget(),
-                        mozilla::StreamTime(90000),
+                        mozilla::StreamTime(VIDEO_TRACK_RATE),
                         generator.GetSize(),
                         PRINCIPAL_HANDLE_NONE,
                         false,
                         now + TimeDuration::FromSeconds(i));
   }
 
   encoder.SetStartOffset(0);
   encoder.AppendVideoSegment(Move(segment));
-  encoder.AdvanceCurrentTime(images.Length() * 90000);
+  encoder.AdvanceCurrentTime(images.Length() * VIDEO_TRACK_RATE);
 
   // Pull Encoded Data back from encoder.
   EncodedFrameContainer container;
   EXPECT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
 }
 
 // Test that encoding a single frame gives useful output.
 TEST(VP8VideoTrackEncoder, SingleFrameEncode)
 {
   TestVP8TrackEncoder encoder;
 
   // Pass a half-second frame to the encoder.
   YUVBufferGenerator generator;
   generator.Init(mozilla::gfx::IntSize(640, 480));
   VideoSegment segment;
   segment.AppendFrame(generator.GenerateI420Image(),
-                      mozilla::StreamTime(45000), // 1/2 second
+                      mozilla::StreamTime(VIDEO_TRACK_RATE / 2), // 1/2 second
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE);
 
   encoder.SetStartOffset(0);
   encoder.AppendVideoSegment(Move(segment));
-  encoder.AdvanceCurrentTime(45000);
+  encoder.AdvanceCurrentTime(VIDEO_TRACK_RATE / 2);
   encoder.NotifyEndOfStream();
 
   EncodedFrameContainer container;
   ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
 
   EXPECT_TRUE(encoder.IsEncodingComplete());
 
   // Read out encoded data, and verify.
@@ -338,26 +340,26 @@ TEST(VP8VideoTrackEncoder, SameFrameEnco
   // Pass 15 100ms frames to the encoder.
   YUVBufferGenerator generator;
   generator.Init(mozilla::gfx::IntSize(640, 480));
   RefPtr<Image> image = generator.GenerateI420Image();
   TimeStamp now = TimeStamp::Now();
   VideoSegment segment;
   for (uint32_t i = 0; i < 15; ++i) {
     segment.AppendFrame(do_AddRef(image),
-                        mozilla::StreamTime(9000), // 100ms
+                        mozilla::StreamTime(VIDEO_TRACK_RATE / 10), // 100ms
                         generator.GetSize(),
                         PRINCIPAL_HANDLE_NONE,
                         false,
                         now + TimeDuration::FromSeconds(i * 0.1));
   }
 
   encoder.SetStartOffset(0);
   encoder.AppendVideoSegment(Move(segment));
-  encoder.AdvanceCurrentTime(15 * 9000);
+  encoder.AdvanceCurrentTime((VIDEO_TRACK_RATE / 10) * 15);
   encoder.NotifyEndOfStream();
 
   EncodedFrameContainer container;
   ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
 
   EXPECT_TRUE(encoder.IsEncodingComplete());
 
   // Verify total duration being 1.5s.
@@ -377,34 +379,34 @@ TEST(VP8VideoTrackEncoder, NullFrameFirs
   generator.Init(mozilla::gfx::IntSize(640, 480));
   RefPtr<Image> image = generator.GenerateI420Image();
   TimeStamp now = TimeStamp::Now();
   VideoSegment segment;
 
   // Pass 2 100ms null frames to the encoder.
   for (uint32_t i = 0; i < 2; ++i) {
     segment.AppendFrame(nullptr,
-                        mozilla::StreamTime(9000), // 100ms
+                        mozilla::StreamTime(VIDEO_TRACK_RATE / 10), // 100ms
                         generator.GetSize(),
                         PRINCIPAL_HANDLE_NONE,
                         false,
                         now + TimeDuration::FromSeconds(i * 0.1));
   }
 
   // Pass a real 100ms frame to the encoder.
   segment.AppendFrame(image.forget(),
-                      mozilla::StreamTime(9000), // 100ms
+                      mozilla::StreamTime(VIDEO_TRACK_RATE / 10), // 100ms
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE,
                       false,
                       now + TimeDuration::FromSeconds(0.3));
 
   encoder.SetStartOffset(0);
   encoder.AppendVideoSegment(Move(segment));
-  encoder.AdvanceCurrentTime(3 * 9000);
+  encoder.AdvanceCurrentTime(3 * VIDEO_TRACK_RATE / 10);
   encoder.NotifyEndOfStream();
 
   EncodedFrameContainer container;
   ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
 
   EXPECT_TRUE(encoder.IsEncodingComplete());
 
   // Verify total duration being 0.3s.
@@ -464,34 +466,34 @@ TEST(VP8VideoTrackEncoder, RoundingError
   TimeStamp now = TimeStamp::Now();
   VideoSegment segment;
 
   // Pass nine frames with timestamps not expressable in 90kHz sample rate,
   // then one frame to make the total duration one second.
   uint32_t usPerFrame = 99999; //99.999ms
   for (uint32_t i = 0; i < 9; ++i) {
     segment.AppendFrame(generator.GenerateI420Image(),
-                        mozilla::StreamTime(9000), // 100ms
+                        mozilla::StreamTime(VIDEO_TRACK_RATE / 10), // 100ms
                         generator.GetSize(),
                         PRINCIPAL_HANDLE_NONE,
                         false,
                         now + TimeDuration::FromMicroseconds(i * usPerFrame));
   }
 
   // This last frame has timestamp start + 0.9s and duration 0.1s.
   segment.AppendFrame(generator.GenerateI420Image(),
-                      mozilla::StreamTime(9000), // 100ms
+                      mozilla::StreamTime(VIDEO_TRACK_RATE / 10), // 100ms
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE,
                       false,
                       now + TimeDuration::FromSeconds(0.9));
 
   encoder.SetStartOffset(0);
   encoder.AppendVideoSegment(Move(segment));
-  encoder.AdvanceCurrentTime(10 * 9000);
+  encoder.AdvanceCurrentTime(10 * VIDEO_TRACK_RATE / 10);
   encoder.NotifyEndOfStream();
 
   EncodedFrameContainer container;
   ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
 
   EXPECT_TRUE(encoder.IsEncodingComplete());
 
   // Verify total duration being 1s.
@@ -510,37 +512,37 @@ TEST(VP8VideoTrackEncoder, TimestampFram
 
   // Pass 3 frames with duration 0.1s, but varying timestamps to the encoder.
   // Total duration of the segment should be the same for both.
   YUVBufferGenerator generator;
   generator.Init(mozilla::gfx::IntSize(640, 480));
   TimeStamp now = TimeStamp::Now();
   VideoSegment segment;
   segment.AppendFrame(generator.GenerateI420Image(),
-                      mozilla::StreamTime(9000), // 0.1s
+                      mozilla::StreamTime(VIDEO_TRACK_RATE / 10), // 0.1s
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE,
                       false,
                       now);
   segment.AppendFrame(generator.GenerateI420Image(),
-                      mozilla::StreamTime(9000), // 0.1s
+                      mozilla::StreamTime(VIDEO_TRACK_RATE / 10), // 0.1s
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE,
                       false,
                       now + TimeDuration::FromSeconds(0.05));
   segment.AppendFrame(generator.GenerateI420Image(),
-                      mozilla::StreamTime(9000), // 0.1s
+                      mozilla::StreamTime(VIDEO_TRACK_RATE / 10), // 0.1s
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE,
                       false,
                       now + TimeDuration::FromSeconds(0.2));
 
   encoder.SetStartOffset(0);
   encoder.AppendVideoSegment(Move(segment));
-  encoder.AdvanceCurrentTime(3 * 9000);
+  encoder.AdvanceCurrentTime(3 * VIDEO_TRACK_RATE / 10);
   encoder.NotifyEndOfStream();
 
   EncodedFrameContainer container;
   ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
 
   EXPECT_TRUE(encoder.IsEncodingComplete());
 
   // Verify total duration being 4s and individual frames being [0.5s, 1.5s, 1s, 1s]
@@ -564,47 +566,47 @@ TEST(VP8VideoTrackEncoder, Suspended)
 
   // Pass 3 frames with duration 0.1s. We suspend before and resume after the
   // second frame.
   YUVBufferGenerator generator;
   generator.Init(mozilla::gfx::IntSize(640, 480));
   TimeStamp now = TimeStamp::Now();
   VideoSegment segment;
   segment.AppendFrame(generator.GenerateI420Image(),
-                      mozilla::StreamTime(9000), // 0.1s
+                      mozilla::StreamTime(VIDEO_TRACK_RATE / 10), // 0.1s
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE,
                       false,
                       now);
 
   encoder.SetStartOffset(0);
   encoder.AppendVideoSegment(Move(segment));
-  encoder.AdvanceCurrentTime(9000);
+  encoder.AdvanceCurrentTime(VIDEO_TRACK_RATE / 10);
 
   encoder.Suspend(now + TimeDuration::FromSeconds(0.1));
 
   segment.AppendFrame(generator.GenerateI420Image(),
-                      mozilla::StreamTime(9000), // 0.1s
+                      mozilla::StreamTime(VIDEO_TRACK_RATE / 10), // 0.1s
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE,
                       false,
                       now + TimeDuration::FromSeconds(0.1));
   encoder.AppendVideoSegment(Move(segment));
-  encoder.AdvanceCurrentTime(9000);
+  encoder.AdvanceCurrentTime(VIDEO_TRACK_RATE / 10);
 
   encoder.Resume(now + TimeDuration::FromSeconds(0.2));
 
   segment.AppendFrame(generator.GenerateI420Image(),
-                      mozilla::StreamTime(9000), // 0.1s
+                      mozilla::StreamTime(VIDEO_TRACK_RATE / 10), // 0.1s
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE,
                       false,
                       now + TimeDuration::FromSeconds(0.2));
   encoder.AppendVideoSegment(Move(segment));
-  encoder.AdvanceCurrentTime(9000);
+  encoder.AdvanceCurrentTime(VIDEO_TRACK_RATE / 10);
 
   encoder.NotifyEndOfStream();
 
   EncodedFrameContainer container;
   ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
 
   EXPECT_TRUE(encoder.IsEncodingComplete());
 
@@ -626,36 +628,36 @@ TEST(VP8VideoTrackEncoder, SuspendedUnti
   TestVP8TrackEncoder encoder;
 
   // Pass 2 frames with duration 0.1s. We suspend before the second frame.
   YUVBufferGenerator generator;
   generator.Init(mozilla::gfx::IntSize(640, 480));
   TimeStamp now = TimeStamp::Now();
   VideoSegment segment;
   segment.AppendFrame(generator.GenerateI420Image(),
-                      mozilla::StreamTime(9000), // 0.1s
+                      mozilla::StreamTime(VIDEO_TRACK_RATE / 10), // 0.1s
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE,
                       false,
                       now);
 
   encoder.SetStartOffset(0);
   encoder.AppendVideoSegment(Move(segment));
-  encoder.AdvanceCurrentTime(9000);
+  encoder.AdvanceCurrentTime(VIDEO_TRACK_RATE / 10);
 
   encoder.Suspend(now + TimeDuration::FromSeconds(0.1));
 
   segment.AppendFrame(generator.GenerateI420Image(),
-                      mozilla::StreamTime(9000), // 0.1s
+                      mozilla::StreamTime(VIDEO_TRACK_RATE / 10), // 0.1s
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE,
                       false,
                       now + TimeDuration::FromSeconds(0.1));
   encoder.AppendVideoSegment(Move(segment));
-  encoder.AdvanceCurrentTime(9000);
+  encoder.AdvanceCurrentTime(VIDEO_TRACK_RATE / 10);
 
   encoder.NotifyEndOfStream();
 
   EncodedFrameContainer container;
   ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
 
   EXPECT_TRUE(encoder.IsEncodingComplete());
 
@@ -681,25 +683,25 @@ TEST(VP8VideoTrackEncoder, AlwaysSuspend
   generator.Init(mozilla::gfx::IntSize(640, 480));
 
   TimeStamp now = TimeStamp::Now();
 
   encoder.Suspend(now);
 
   VideoSegment segment;
   segment.AppendFrame(generator.GenerateI420Image(),
-                      mozilla::StreamTime(180000), // 2s
+                      mozilla::StreamTime(2 * VIDEO_TRACK_RATE), // 2s
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE,
                       false,
                       now);
 
   encoder.SetStartOffset(0);
   encoder.AppendVideoSegment(Move(segment));
-  encoder.AdvanceCurrentTime(180000);
+  encoder.AdvanceCurrentTime(2 * VIDEO_TRACK_RATE);
 
   encoder.NotifyEndOfStream();
 
   EncodedFrameContainer container;
   ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
 
   EXPECT_TRUE(encoder.IsEncodingComplete());
 
@@ -716,36 +718,36 @@ TEST(VP8VideoTrackEncoder, SuspendedBegi
 
   // Suspend and pass a frame with duration 0.5s. Then resume and pass one more.
   encoder.Suspend(now);
 
   YUVBufferGenerator generator;
   generator.Init(mozilla::gfx::IntSize(640, 480));
   VideoSegment segment;
   segment.AppendFrame(generator.GenerateI420Image(),
-                      mozilla::StreamTime(45000), // 0.5s
+                      mozilla::StreamTime(VIDEO_TRACK_RATE / 2), // 0.5s
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE,
                       false,
                       now);
 
   encoder.SetStartOffset(0);
   encoder.AppendVideoSegment(Move(segment));
-  encoder.AdvanceCurrentTime(45000);
+  encoder.AdvanceCurrentTime(VIDEO_TRACK_RATE / 2);
 
   encoder.Resume(now + TimeDuration::FromSeconds(0.5));
 
   segment.AppendFrame(generator.GenerateI420Image(),
-                      mozilla::StreamTime(45000), // 0.5s
+                      mozilla::StreamTime(VIDEO_TRACK_RATE / 2), // 0.5s
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE,
                       false,
                       now + TimeDuration::FromSeconds(0.5));
   encoder.AppendVideoSegment(Move(segment));
-  encoder.AdvanceCurrentTime(45000);
+  encoder.AdvanceCurrentTime(VIDEO_TRACK_RATE / 2);
 
   encoder.NotifyEndOfStream();
 
   EncodedFrameContainer container;
   ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
 
   EXPECT_TRUE(encoder.IsEncodingComplete());
 
@@ -768,39 +770,39 @@ TEST(VP8VideoTrackEncoder, SuspendedOver
   TestVP8TrackEncoder encoder;
 
   // Pass a 1s frame and suspend after 0.5s.
   YUVBufferGenerator generator;
   generator.Init(mozilla::gfx::IntSize(640, 480));
   TimeStamp now = TimeStamp::Now();
   VideoSegment segment;
   segment.AppendFrame(generator.GenerateI420Image(),
-                      mozilla::StreamTime(90000), // 1s
+                      mozilla::StreamTime(VIDEO_TRACK_RATE), // 1s
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE,
                       false,
                       now);
 
   encoder.SetStartOffset(0);
   encoder.AppendVideoSegment(Move(segment));
 
-  encoder.AdvanceCurrentTime(45000);
+  encoder.AdvanceCurrentTime(VIDEO_TRACK_RATE / 2);
   encoder.Suspend(now + TimeDuration::FromSeconds(0.5));
 
   // Pass another 1s frame and resume after 0.3 of this new frame.
   segment.AppendFrame(generator.GenerateI420Image(),
-                      mozilla::StreamTime(90000), // 1s
+                      mozilla::StreamTime(VIDEO_TRACK_RATE), // 1s
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE,
                       false,
                       now + TimeDuration::FromSeconds(1));
   encoder.AppendVideoSegment(Move(segment));
-  encoder.AdvanceCurrentTime(72000);
+  encoder.AdvanceCurrentTime((VIDEO_TRACK_RATE / 10) * 8);
   encoder.Resume(now + TimeDuration::FromSeconds(1.3));
-  encoder.AdvanceCurrentTime(63000);
+  encoder.AdvanceCurrentTime((VIDEO_TRACK_RATE / 10) * 7);
 
   encoder.NotifyEndOfStream();
 
   EncodedFrameContainer container;
   ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
 
   EXPECT_TRUE(encoder.IsEncodingComplete());
 
@@ -822,25 +824,134 @@ TEST(VP8VideoTrackEncoder, PrematureEndi
   TestVP8TrackEncoder encoder;
 
   // Pass a 1s frame and end the track after 0.5s.
   YUVBufferGenerator generator;
   generator.Init(mozilla::gfx::IntSize(640, 480));
   TimeStamp now = TimeStamp::Now();
   VideoSegment segment;
   segment.AppendFrame(generator.GenerateI420Image(),
-                      mozilla::StreamTime(90000), // 1s
+                      mozilla::StreamTime(VIDEO_TRACK_RATE), // 1s
                       generator.GetSize(),
                       PRINCIPAL_HANDLE_NONE,
                       false,
                       now);
 
   encoder.SetStartOffset(0);
   encoder.AppendVideoSegment(Move(segment));
-  encoder.AdvanceCurrentTime(45000);
+  encoder.AdvanceCurrentTime(VIDEO_TRACK_RATE / 2);
+  encoder.NotifyEndOfStream();
+
+  EncodedFrameContainer container;
+  ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
+
+  EXPECT_TRUE(encoder.IsEncodingComplete());
+
+  uint64_t totalDuration = 0;
+  for (auto& frame : container.GetEncodedFrames()) {
+    totalDuration += frame->GetDuration();
+  }
+  const uint64_t half = PR_USEC_PER_SEC / 2;
+  EXPECT_EQ(half, totalDuration);
+}
+
+// Test that a track that starts at t > 0 works as expected.
+TEST(VP8VideoTrackEncoder, DelayedStart)
+{
+  TestVP8TrackEncoder encoder;
+
+  // Pass a 2s frame, start (pass first CurrentTime) at 0.5s, end at 1s.
+  // Should result in a 0.5s encoding.
+  YUVBufferGenerator generator;
+  generator.Init(mozilla::gfx::IntSize(640, 480));
+  TimeStamp now = TimeStamp::Now();
+  VideoSegment segment;
+  segment.AppendFrame(generator.GenerateI420Image(),
+                      mozilla::StreamTime(2 * VIDEO_TRACK_RATE), // 2s
+                      generator.GetSize(),
+                      PRINCIPAL_HANDLE_NONE,
+                      false,
+                      now);
+
+  encoder.SetStartOffset(VIDEO_TRACK_RATE / 2);
+  encoder.AppendVideoSegment(Move(segment));
+  encoder.AdvanceCurrentTime(VIDEO_TRACK_RATE / 2);
+  encoder.NotifyEndOfStream();
+
+  EncodedFrameContainer container;
+  ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
+
+  EXPECT_TRUE(encoder.IsEncodingComplete());
+
+  uint64_t totalDuration = 0;
+  for (auto& frame : container.GetEncodedFrames()) {
+    totalDuration += frame->GetDuration();
+  }
+  const uint64_t half = PR_USEC_PER_SEC / 2;
+  EXPECT_EQ(half, totalDuration);
+}
+
+// Test that a track that starts at t > 0 works as expected, when
+// SetStartOffset comes after AppendVideoSegment.
+TEST(VP8VideoTrackEncoder, DelayedStartOtherEventOrder)
+{
+  TestVP8TrackEncoder encoder;
+
+  // Pass a 2s frame, start (pass first CurrentTime) at 0.5s, end at 1s.
+  // Should result in a 0.5s encoding.
+  YUVBufferGenerator generator;
+  generator.Init(mozilla::gfx::IntSize(640, 480));
+  TimeStamp now = TimeStamp::Now();
+  VideoSegment segment;
+  segment.AppendFrame(generator.GenerateI420Image(),
+                      mozilla::StreamTime(2 * VIDEO_TRACK_RATE), // 2s
+                      generator.GetSize(),
+                      PRINCIPAL_HANDLE_NONE,
+                      false,
+                      now);
+
+  encoder.AppendVideoSegment(Move(segment));
+  encoder.SetStartOffset(VIDEO_TRACK_RATE / 2);
+  encoder.AdvanceCurrentTime(VIDEO_TRACK_RATE / 2);
+  encoder.NotifyEndOfStream();
+
+  EncodedFrameContainer container;
+  ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
+
+  EXPECT_TRUE(encoder.IsEncodingComplete());
+
+  uint64_t totalDuration = 0;
+  for (auto& frame : container.GetEncodedFrames()) {
+    totalDuration += frame->GetDuration();
+  }
+  const uint64_t half = PR_USEC_PER_SEC / 2;
+  EXPECT_EQ(half, totalDuration);
+}
+
+// Test that a track that starts at t >>> 0 works as expected.
+TEST(VP8VideoTrackEncoder, VeryDelayedStart)
+{
+  TestVP8TrackEncoder encoder;
+
+  // Pass a 1s frame, start (pass first CurrentTime) at 10s, end at 10.5s.
+  // Should result in a 0.5s encoding.
+  YUVBufferGenerator generator;
+  generator.Init(mozilla::gfx::IntSize(640, 480));
+  TimeStamp now = TimeStamp::Now();
+  VideoSegment segment;
+  segment.AppendFrame(generator.GenerateI420Image(),
+                      mozilla::StreamTime(VIDEO_TRACK_RATE), // 1s
+                      generator.GetSize(),
+                      PRINCIPAL_HANDLE_NONE,
+                      false,
+                      now);
+
+  encoder.SetStartOffset(VIDEO_TRACK_RATE * 10);
+  encoder.AppendVideoSegment(Move(segment));
+  encoder.AdvanceCurrentTime(VIDEO_TRACK_RATE / 2);
   encoder.NotifyEndOfStream();
 
   EncodedFrameContainer container;
   ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container)));
 
   EXPECT_TRUE(encoder.IsEncodingComplete());
 
   uint64_t totalDuration = 0;