diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder_unittest.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder_unittest.cc | 239 |
1 files changed, 157 insertions, 82 deletions
diff --git a/chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder_unittest.cc b/chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder_unittest.cc index 52c87d28284..c534e793c00 100644 --- a/chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder_unittest.cc +++ b/chromium/third_party/blink/renderer/modules/mediarecorder/video_track_recorder_unittest.cc @@ -8,8 +8,11 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h" +#include "base/test/gmock_callback_support.h" #include "media/base/video_codecs.h" #include "media/base/video_frame.h" +#include "media/base/video_util.h" +#include "media/video/mock_gpu_video_accelerator_factories.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h" @@ -30,7 +33,6 @@ #include "third_party/blink/renderer/platform/wtf/functional.h" #include "ui/gfx/gpu_memory_buffer.h" -using media::VideoFrame; using video_track_recorder::kVEAEncoderMinResolutionHeight; using video_track_recorder::kVEAEncoderMinResolutionWidth; @@ -44,10 +46,18 @@ using ::testing::TestWithParam; using ::testing::ValuesIn; namespace blink { +namespace { -ACTION_P(RunClosure, closure) { - closure.Run(); -} +// Specifies frame type for test. +enum class TestFrameType { + kNv12GpuMemoryBuffer, // Implies media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER + kNv12Software, // Implies media::VideoFrame::STORAGE_OWNED_MEMORY + kI420 // Implies media::VideoFrame::STORAGE_OWNED_MEMORY +}; + +const TestFrameType kTestFrameTypes[] = {TestFrameType::kNv12GpuMemoryBuffer, + TestFrameType::kNv12Software, + TestFrameType::kI420}; const VideoTrackRecorder::CodecId kTrackRecorderTestCodec[] = { VideoTrackRecorder::CodecId::VP8, VideoTrackRecorder::CodecId::VP9 @@ -60,12 +70,10 @@ const gfx::Size kTrackRecorderTestSize[] = { gfx::Size(kVEAEncoderMinResolutionWidth / 2, kVEAEncoderMinResolutionHeight / 2), gfx::Size(kVEAEncoderMinResolutionWidth, kVEAEncoderMinResolutionHeight)}; -const media::VideoFrame::StorageType kStorageTypeToTest[] = { - media::VideoFrame::STORAGE_OWNED_MEMORY, - media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER}; static const int kTrackRecorderTestSizeDiff = 20; -media::VideoCodec MediaVideoCodecFromCodecId(VideoTrackRecorder::CodecId id) { +constexpr media::VideoCodec MediaVideoCodecFromCodecId( + VideoTrackRecorder::CodecId id) { switch (id) { case VideoTrackRecorder::CodecId::VP8: return media::kCodecVP8; @@ -82,11 +90,28 @@ media::VideoCodec MediaVideoCodecFromCodecId(VideoTrackRecorder::CodecId id) { return media::kUnknownVideoCodec; } +} // namespace + +ACTION_P(RunClosure, closure) { + closure.Run(); +} + +class MockTestingPlatform : public IOTaskRunnerTestingPlatformSupport { + public: + MockTestingPlatform() = default; + ~MockTestingPlatform() override = default; + + MOCK_METHOD0(GetGpuFactories, media::GpuVideoAcceleratorFactories*()); +}; + +// TODO(crbug/1177593): refactor the test parameter space to something more +// reasonable. Many tests below ignore parts of the space leading to too much +// being tested. class VideoTrackRecorderTest : public TestWithParam<testing::tuple<VideoTrackRecorder::CodecId, gfx::Size, bool, - media::VideoFrame::StorageType>> { + TestFrameType>> { public: VideoTrackRecorderTest() : mock_source_(new MockMediaStreamVideoSource()) { const String track_id("dummy"); @@ -109,9 +134,11 @@ class VideoTrackRecorderTest source_->GetPlatformSource()); EXPECT_TRUE(scheduler::GetSingleThreadTaskRunnerForTesting() ->BelongsToCurrentThread()); + + ON_CALL(*platform_, GetGpuFactories()).WillByDefault(Return(nullptr)); } - ~VideoTrackRecorderTest() { + ~VideoTrackRecorderTest() override { component_ = nullptr; source_ = nullptr; video_track_recorder_.reset(); @@ -144,7 +171,8 @@ class VideoTrackRecorderTest base::TimeTicks timestamp, bool keyframe)); - void Encode(scoped_refptr<VideoFrame> frame, base::TimeTicks capture_time) { + void Encode(scoped_refptr<media::VideoFrame> frame, + base::TimeTicks capture_time) { EXPECT_TRUE(scheduler::GetSingleThreadTaskRunnerForTesting() ->BelongsToCurrentThread()); video_track_recorder_->OnVideoFrameForTesting(std::move(frame), @@ -163,7 +191,7 @@ class VideoTrackRecorderTest return video_track_recorder_->encoder_->num_frames_in_encode_->count(); } - ScopedTestingPlatformSupport<IOTaskRunnerTestingPlatformSupport> platform_; + ScopedTestingPlatformSupport<MockTestingPlatform> platform_; // All members are non-const due to the series of initialize() calls needed. // |mock_source_| is owned by |source_|, |track_| by |component_|. @@ -174,6 +202,43 @@ class VideoTrackRecorderTest std::unique_ptr<VideoTrackRecorderImpl> video_track_recorder_; + protected: + scoped_refptr<media::VideoFrame> CreateFrameForTest( + TestFrameType frame_type, + const gfx::Size& frame_size, + bool encode_alpha_channel, + int padding) { + const gfx::Size padded_size(frame_size.width() + padding, + frame_size.height()); + if (frame_type == TestFrameType::kI420) { + return media::VideoFrame::CreateZeroInitializedFrame( + encode_alpha_channel ? media::PIXEL_FORMAT_I420A + : media::PIXEL_FORMAT_I420, + padded_size, gfx::Rect(frame_size), frame_size, base::TimeDelta()); + } + + scoped_refptr<media::VideoFrame> video_frame = blink::CreateTestFrame( + padded_size, gfx::Rect(frame_size), frame_size, + frame_type == TestFrameType::kNv12Software + ? media::VideoFrame::STORAGE_OWNED_MEMORY + : media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER, + media::VideoPixelFormat::PIXEL_FORMAT_NV12); + scoped_refptr<media::VideoFrame> video_frame2 = video_frame; + if (frame_type == TestFrameType::kNv12GpuMemoryBuffer) + video_frame2 = media::ConvertToMemoryMappedFrame(video_frame); + + // Fade to black. + const uint8_t kBlackY = 0x00; + const uint8_t kBlackUV = 0x80; + memset(static_cast<uint8_t*>(video_frame2->data(0)), kBlackY, + video_frame2->stride(0) * frame_size.height()); + memset(static_cast<uint8_t*>(video_frame2->data(1)), kBlackUV, + video_frame2->stride(1) * (frame_size.height() / 2)); + if (frame_type == TestFrameType::kNv12GpuMemoryBuffer) + return video_frame; + return video_frame2; + } + private: DISALLOW_COPY_AND_ASSIGN(VideoTrackRecorderTest); }; @@ -201,54 +266,20 @@ TEST_P(VideoTrackRecorderTest, VideoEncoding) { const bool encode_alpha_channel = testing::get<2>(GetParam()); // |frame_size| cannot be arbitrarily small, should be reasonable. const gfx::Size& frame_size = testing::get<1>(GetParam()); - const media::VideoFrame::StorageType storage_type = - testing::get<3>(GetParam()); + const TestFrameType test_frame_type = testing::get<3>(GetParam()); // We don't support alpha channel with GpuMemoryBuffer frames. - if (storage_type == media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER && - encode_alpha_channel) { + if (test_frame_type != TestFrameType::kI420 && encode_alpha_channel) { return; } - auto create_test_frame = - [](media::VideoFrame::StorageType storage_type, - const gfx::Size& frame_size, - bool encode_alpha_channel) -> scoped_refptr<VideoFrame> { - scoped_refptr<VideoFrame> video_frame; - switch (storage_type) { - case media::VideoFrame::STORAGE_OWNED_MEMORY: - video_frame = encode_alpha_channel - ? VideoFrame::CreateTransparentFrame(frame_size) - : VideoFrame::CreateBlackFrame(frame_size); - break; - case media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER: { - video_frame = CreateTestFrame(frame_size, gfx::Rect(frame_size), - frame_size, storage_type); - // Create a black NV12 frame. - auto* gmb = video_frame->GetGpuMemoryBuffer(); - gmb->Map(); - const uint8_t kBlackY = 0x00; - const uint8_t kBlackUV = 0x80; - memset(static_cast<uint8_t*>(gmb->memory(0)), kBlackY, - gmb->stride(0) * frame_size.height()); - memset(static_cast<uint8_t*>(gmb->memory(1)), kBlackUV, - gmb->stride(1) * (frame_size.height() / 2)); - gmb->Unmap(); - break; - } - default: - DLOG(ERROR) << "Unexpected storage type"; - } - return video_frame; - }; - - const scoped_refptr<VideoFrame> video_frame = - create_test_frame(storage_type, frame_size, encode_alpha_channel); + const scoped_refptr<media::VideoFrame> video_frame = CreateFrameForTest( + test_frame_type, frame_size, encode_alpha_channel, /*padding=*/0); if (!video_frame) ASSERT_TRUE(!!video_frame); const double kFrameRate = 60.0f; - video_frame->metadata()->frame_rate = kFrameRate; + video_frame->metadata().frame_rate = kFrameRate; InSequence s; const base::TimeTicks timeticks_now = base::TimeTicks::Now(); @@ -273,8 +304,8 @@ TEST_P(VideoTrackRecorderTest, VideoEncoding) { // Send another Video Frame and expect only an OnEncodedVideo() callback. const gfx::Size frame_size2(frame_size.width() + kTrackRecorderTestSizeDiff, frame_size.height()); - const scoped_refptr<VideoFrame> video_frame2 = - create_test_frame(storage_type, frame_size2, encode_alpha_channel); + const scoped_refptr<media::VideoFrame> video_frame2 = CreateFrameForTest( + test_frame_type, frame_size2, encode_alpha_channel, /*padding=*/0); base::RunLoop run_loop; @@ -295,8 +326,8 @@ TEST_P(VideoTrackRecorderTest, VideoEncoding) { EXPECT_GE(third_frame_encoded_data.size(), kEncodedSizeThreshold); // We only support NV12 with GpuMemoryBuffer video frame. - if (storage_type != media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER && - encode_alpha_channel && CanEncodeAlphaChannel()) { + if (test_frame_type == TestFrameType::kI420 && encode_alpha_channel && + CanEncodeAlphaChannel()) { EXPECT_GE(first_frame_encoded_alpha.size(), kEncodedSizeThreshold); EXPECT_GE(second_frame_encoded_alpha.size(), kEncodedSizeThreshold); EXPECT_GE(third_frame_encoded_alpha.size(), kEncodedSizeThreshold); @@ -317,24 +348,46 @@ TEST_P(VideoTrackRecorderTest, EncodeFrameWithPaddedCodedSize) { const gfx::Size& frame_size = testing::get<1>(GetParam()); const size_t kCodedSizePadding = 16; - const media::VideoFrame::StorageType storage_type = - testing::get<3>(GetParam()); - const gfx::Size padded_size(frame_size.width() + kCodedSizePadding, - frame_size.height()); - scoped_refptr<VideoFrame> video_frame; - switch (storage_type) { - case media::VideoFrame::STORAGE_OWNED_MEMORY: - video_frame = VideoFrame::CreateZeroInitializedFrame( - media::PIXEL_FORMAT_I420, padded_size, gfx::Rect(frame_size), - frame_size, base::TimeDelta()); - break; - case media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER: - video_frame = CreateTestFrame(padded_size, gfx::Rect(frame_size), - frame_size, storage_type); - break; - default: - NOTREACHED() << "Unexpected storage type"; - } + const TestFrameType test_frame_type = testing::get<3>(GetParam()); + scoped_refptr<media::VideoFrame> video_frame = + CreateFrameForTest(test_frame_type, frame_size, + /*encode_alpha_channel=*/false, kCodedSizePadding); + + base::RunLoop run_loop; + EXPECT_CALL(*this, OnEncodedVideo(_, _, _, _, true)) + .Times(1) + .WillOnce(RunClosure(run_loop.QuitClosure())); + Encode(video_frame, base::TimeTicks::Now()); + run_loop.Run(); + + Mock::VerifyAndClearExpectations(this); +} + +TEST_P(VideoTrackRecorderTest, EncodeFrameRGB) { + InitializeRecorder(testing::get<0>(GetParam())); + + const gfx::Size& frame_size = testing::get<1>(GetParam()); + // TODO(crbug/1177593): Refactor test harness to use a cleaner parameter + // space. + if (testing::get<2>(GetParam())) + return; + // TODO(crbug/1177593): Refactor test harness to use a cleaner parameter + // space. + // Let kI420 indicate owned memory, and kNv12GpuMemoryBuffer to indicate GMB + // storage. Don't test for kNv12Software. + const TestFrameType test_frame_type = testing::get<3>(GetParam()); + if (test_frame_type == TestFrameType::kNv12Software) + return; + + scoped_refptr<media::VideoFrame> video_frame = + test_frame_type == TestFrameType::kI420 + ? media::VideoFrame::CreateZeroInitializedFrame( + media::PIXEL_FORMAT_XRGB, frame_size, gfx::Rect(frame_size), + frame_size, base::TimeDelta()) + : blink::CreateTestFrame(frame_size, gfx::Rect(frame_size), + frame_size, + media::VideoFrame::STORAGE_GPU_MEMORY_BUFFER, + media::PIXEL_FORMAT_XRGB); base::RunLoop run_loop; EXPECT_CALL(*this, OnEncodedVideo(_, _, _, _, true)) @@ -352,8 +405,8 @@ TEST_F(VideoTrackRecorderTest, ForceKeyframeOnAlphaSwitch) { InitializeRecorder(VideoTrackRecorder::CodecId::VP8); const gfx::Size& frame_size = kTrackRecorderTestSize[0]; - const scoped_refptr<VideoFrame> opaque_frame = - VideoFrame::CreateBlackFrame(frame_size); + const scoped_refptr<media::VideoFrame> opaque_frame = + media::VideoFrame::CreateBlackFrame(frame_size); InSequence s; base::StringPiece first_frame_encoded_alpha; @@ -362,8 +415,8 @@ TEST_F(VideoTrackRecorderTest, ForceKeyframeOnAlphaSwitch) { .WillOnce(SaveArg<2>(&first_frame_encoded_alpha)); Encode(opaque_frame, base::TimeTicks::Now()); - const scoped_refptr<VideoFrame> alpha_frame = - VideoFrame::CreateTransparentFrame(frame_size); + const scoped_refptr<media::VideoFrame> alpha_frame = + media::VideoFrame::CreateTransparentFrame(frame_size); base::StringPiece second_frame_encoded_alpha; EXPECT_CALL(*this, OnEncodedVideo(_, _, _, _, true)) .Times(1) @@ -392,8 +445,8 @@ TEST_F(VideoTrackRecorderTest, HandlesOnError) { InitializeRecorder(VideoTrackRecorder::CodecId::VP8); const gfx::Size& frame_size = kTrackRecorderTestSize[0]; - const scoped_refptr<VideoFrame> video_frame = - VideoFrame::CreateBlackFrame(frame_size); + const scoped_refptr<media::VideoFrame> video_frame = + media::VideoFrame::CreateBlackFrame(frame_size); InSequence s; EXPECT_CALL(*this, OnEncodedVideo(_, _, _, _, true)).Times(1); @@ -419,8 +472,8 @@ TEST_F(VideoTrackRecorderTest, ReleasesFrame) { InitializeRecorder(VideoTrackRecorder::CodecId::VP8); const gfx::Size& frame_size = kTrackRecorderTestSize[0]; - scoped_refptr<VideoFrame> video_frame = - VideoFrame::CreateBlackFrame(frame_size); + scoped_refptr<media::VideoFrame> video_frame = + media::VideoFrame::CreateBlackFrame(frame_size); base::RunLoop run_loop; bool frame_is_destroyed = false; @@ -439,6 +492,28 @@ TEST_F(VideoTrackRecorderTest, ReleasesFrame) { Mock::VerifyAndClearExpectations(this); } +// Waits for HW encoder support to be enumerated before setting up and +// performing an encode. +TEST_F(VideoTrackRecorderTest, WaitForEncoderSupport) { + media::MockGpuVideoAcceleratorFactories mock_gpu_factories(nullptr); + EXPECT_CALL(*platform_, GetGpuFactories()) + .WillRepeatedly(Return(&mock_gpu_factories)); + + EXPECT_CALL(mock_gpu_factories, NotifyEncoderSupportKnown(_)) + .WillOnce(base::test::RunOnceClosure<0>()); + InitializeRecorder(VideoTrackRecorder::CodecId::VP8); + + const gfx::Size& frame_size = kTrackRecorderTestSize[0]; + scoped_refptr<media::VideoFrame> video_frame = + media::VideoFrame::CreateBlackFrame(frame_size); + + base::RunLoop run_loop; + EXPECT_CALL(*this, OnEncodedVideo(_, _, _, _, true)) + .WillOnce(RunClosure(run_loop.QuitWhenIdleClosure())); + Encode(video_frame, base::TimeTicks::Now()); + run_loop.Run(); +} + TEST_F(VideoTrackRecorderTest, RequiredRefreshRate) { // |RequestRefreshFrame| will be called first by |AddSink| and the second time // by the refresh timer using the required min fps. @@ -457,7 +532,7 @@ INSTANTIATE_TEST_SUITE_P(All, ::testing::Combine(ValuesIn(kTrackRecorderTestCodec), ValuesIn(kTrackRecorderTestSize), ::testing::Bool(), - ValuesIn(kStorageTypeToTest))); + ValuesIn(kTestFrameTypes))); class VideoTrackRecorderPassthroughTest : public TestWithParam<VideoTrackRecorder::CodecId> { |