TEST(VP8VideoTrackEncoder, FrameEncode) { // Initiate VP8 encoder TestVP8TrackEncoder encoder; InitParam param = {true, 640, 480, 90000}; encoder.TestInit(param); // Create YUV images as source. nsTArray<RefPtr<Image>> images; YUVBufferGenerator generator; generator.Init(mozilla::gfx::IntSize(640, 480)); generator.Generate(images); // Put generated YUV frame into video segment. // Duration of each frame is 1 second. VideoSegment segment; for (nsTArray<RefPtr<Image>>::size_type i = 0; i < images.Length(); i++) { RefPtr<Image> image = images[i]; segment.AppendFrame(image.forget(), mozilla::StreamTime(90000), generator.GetSize()); } // track change notification. encoder.NotifyQueuedTrackChanges(nullptr, 0, 0, 0, segment); // Pull Encoded Data back from encoder. EncodedFrameContainer container; EXPECT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container))); }
// Test encoding a track that starts with null data TEST(VP8VideoTrackEncoder, NullFrameFirst) { // Initiate VP8 encoder TestVP8TrackEncoder encoder; InitParam param = {true, 640, 480}; encoder.TestInit(param); YUVBufferGenerator generator; 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 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 generator.GetSize(), PRINCIPAL_HANDLE_NONE, false, now + TimeDuration::FromSeconds(0.3)); encoder.SetCurrentFrames(segment); // End the track. segment.Clear(); encoder.NotifyQueuedTrackChanges(nullptr, 0, 0, TrackEventCommand::TRACK_EVENT_ENDED, segment); EncodedFrameContainer container; ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container))); EXPECT_TRUE(encoder.IsEncodingComplete()); // Verify total duration being 0.3s. uint64_t totalDuration = 0; for (auto& frame : container.GetEncodedFrames()) { totalDuration += frame->GetDuration(); } const uint64_t pointThree = (PR_USEC_PER_SEC / 10) * 3; EXPECT_EQ(pointThree, totalDuration); }
// EOS test TEST(VP8VideoTrackEncoder, EncodeComplete) { // Initiate VP8 encoder TestVP8TrackEncoder encoder; InitParam param = {true, 640, 480, 90000}; encoder.TestInit(param); // track end notification. VideoSegment segment; encoder.NotifyQueuedTrackChanges(nullptr, 0, 0, MediaStreamListener::TRACK_EVENT_ENDED, segment); // Pull Encoded Data back from encoder. Since we have sent // EOS to encoder, encoder.GetEncodedTrack should return // NS_OK immidiately. EncodedFrameContainer container; EXPECT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container))); }
// Test encoding a track that has to skip frames. TEST(VP8VideoTrackEncoder, SkippedFrames) { // Initiate VP8 encoder TestVP8TrackEncoder encoder; InitParam param = {true, 640, 480}; encoder.TestInit(param); YUVBufferGenerator generator; generator.Init(mozilla::gfx::IntSize(640, 480)); TimeStamp now = TimeStamp::Now(); VideoSegment segment; // Pass 100 frames of the shortest possible duration where we don't get // rounding errors between input/output rate. for (uint32_t i = 0; i < 100; ++i) { segment.AppendFrame(generator.GenerateI420Image(), mozilla::StreamTime(90), // 1ms generator.GetSize(), PRINCIPAL_HANDLE_NONE, false, now + TimeDuration::FromMilliseconds(i)); } encoder.SetCurrentFrames(segment); // End the track. segment.Clear(); encoder.NotifyQueuedTrackChanges(nullptr, 0, 0, TrackEventCommand::TRACK_EVENT_ENDED, segment); EncodedFrameContainer container; ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container))); EXPECT_TRUE(encoder.IsEncodingComplete()); // Verify total duration being 100 * 1ms = 100ms. uint64_t totalDuration = 0; for (auto& frame : container.GetEncodedFrames()) { totalDuration += frame->GetDuration(); } const uint64_t hundredMillis = PR_USEC_PER_SEC / 10; EXPECT_EQ(hundredMillis, totalDuration); }
// Test that encoding a single frame gives useful output. TEST(VP8VideoTrackEncoder, SingleFrameEncode) { // Initiate VP8 encoder TestVP8TrackEncoder encoder; InitParam param = {true, 640, 480}; encoder.TestInit(param); // 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 generator.GetSize(), PRINCIPAL_HANDLE_NONE); encoder.SetCurrentFrames(segment); // End the track. segment.Clear(); encoder.NotifyQueuedTrackChanges(nullptr, 0, 0, TrackEventCommand::TRACK_EVENT_ENDED, segment); EncodedFrameContainer container; ASSERT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container))); EXPECT_TRUE(encoder.IsEncodingComplete()); // Read out encoded data, and verify. const nsTArray<RefPtr<EncodedFrame>>& frames = container.GetEncodedFrames(); const size_t oneElement = 1; ASSERT_EQ(oneElement, frames.Length()); EXPECT_EQ(EncodedFrame::VP8_I_FRAME, frames[0]->GetFrameType()) << "We only have one frame, so it should be a keyframe"; const uint64_t halfSecond = PR_USEC_PER_SEC / 2; EXPECT_EQ(halfSecond, frames[0]->GetDuration()); }
// Encode test TEST(VP8VideoTrackEncoder, FrameEncode) { // Initiate VP8 encoder TestVP8TrackEncoder encoder; InitParam param = {true, 640, 480}; encoder.TestInit(param); // Create YUV images as source. nsTArray<RefPtr<Image>> images; YUVBufferGenerator generator; generator.Init(mozilla::gfx::IntSize(640, 480)); images.AppendElement(generator.GenerateI420Image()); images.AppendElement(generator.GenerateNV12Image()); images.AppendElement(generator.GenerateNV21Image()); // 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), generator.GetSize(), PRINCIPAL_HANDLE_NONE, false, now + TimeDuration::FromSeconds(i)); } // track change notification. encoder.SetCurrentFrames(segment); // Pull Encoded Data back from encoder. EncodedFrameContainer container; EXPECT_TRUE(NS_SUCCEEDED(encoder.GetEncodedTrack(container))); }