chromium/third_party/blink/renderer/modules/mediastream/web_media_player_ms_test.cc

// Copyright 2015 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "third_party/blink/public/web/modules/mediastream/web_media_player_ms.h"

#include <stddef.h>

#include <memory>
#include <utility>
#include <vector>

#include "base/containers/circular_deque.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
#include "base/task/sequenced_task_runner.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/gmock_callback_support.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "cc/layers/layer.h"
#include "media/base/media_content_type.h"
#include "media/base/media_util.h"
#include "media/base/test_helpers.h"
#include "media/base/video_frame.h"
#include "media/video/fake_gpu_memory_buffer.h"
#include "media/video/mock_gpu_memory_buffer_video_frame_pool.h"
#include "media/video/mock_gpu_video_accelerator_factories.h"
#include "third_party/blink/public/common/media/display_type.h"
#include "third_party/blink/public/platform/scheduler/test/renderer_scheduler_test_support.h"
#include "third_party/blink/public/platform/web_fullscreen_video_status.h"
#include "third_party/blink/public/platform/web_media_player.h"
#include "third_party/blink/public/platform/web_media_player_client.h"
#include "third_party/blink/public/platform/web_media_player_source.h"
#include "third_party/blink/public/web/web_local_frame.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_audio_renderer.h"
#include "third_party/blink/renderer/modules/mediastream/media_stream_renderer_factory.h"
#include "third_party/blink/renderer/modules/mediastream/web_media_player_ms_compositor.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/testing/task_environment.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"

_;
ByRef;
Eq;
NiceMock;
Return;
ReturnRef;
SaveArg;
StrictMock;
WithArgs;

namespace blink {

enum class FrameType {};

class MockSurfaceLayerBridge : public WebSurfaceLayerBridge {};

TestFrame;

static const int kOddSizeOffset =;
static const int kStandardWidth =;
static const int kStandardHeight =;

class FakeWebMediaPlayerDelegate : public WebMediaPlayerDelegate {};

class ReusableMessageLoopEvent {};

// The class is used mainly to inject VideoFrames into WebMediaPlayerMS.
class MockMediaStreamVideoRenderer : public MediaStreamVideoRenderer {};

class MockMediaStreamAudioRenderer : public MediaStreamAudioRenderer {};

void MockMediaStreamVideoRenderer::Start() {}

void MockMediaStreamVideoRenderer::Stop() {}

void MockMediaStreamVideoRenderer::Resume() {}

void MockMediaStreamVideoRenderer::Pause() {}

void MockMediaStreamVideoRenderer::AddFrame(
    FrameType category,
    scoped_refptr<media::VideoFrame> frame) {}

void MockMediaStreamVideoRenderer::QueueFrames(
    const Vector<int>& timestamp_or_frame_type,
    bool opaque_frame,
    bool odd_size_frame,
    int double_size_index,
    media::VideoRotation rotation) {}

void MockMediaStreamVideoRenderer::InjectFrame() {}

class MockWebVideoFrameSubmitter : public WebVideoFrameSubmitter {};

// The class is used to generate a MockVideoProvider in
// WebMediaPlayerMS::load().
class MockRenderFactory : public MediaStreamRendererFactory {};

scoped_refptr<MediaStreamVideoRenderer> MockRenderFactory::GetVideoRenderer(
    const WebMediaStream& web_stream,
    const MediaStreamVideoRenderer::RepaintCB& repaint_cb,
    scoped_refptr<base::SequencedTaskRunner> video_task_runner,
    scoped_refptr<base::SingleThreadTaskRunner> main_render_task_runner) {}

// This is the main class coordinating the tests.
// Basic workflow:
// 1. WebMediaPlayerMS::Load will generate and start
// MediaStreamVideoRenderer.
// 2. MediaStreamVideoRenderer will start pushing frames into
//    WebMediaPlayerMS repeatedly.
// 3. On WebMediaPlayerMS receiving the first frame, a cc::Layer will be
//    created.
// 4. The cc::Layer will call
//    WebMediaPlayerMSCompositor::SetVideoFrameProviderClient, which in turn
//    will trigger cc::VideoFrameProviderClient::StartRendering.
// 5. Then cc::VideoFrameProviderClient will start calling
//    WebMediaPlayerMSCompositor::UpdateCurrentFrame, GetCurrentFrame for
//    rendering repeatedly.
// 6. When WebMediaPlayerMS::pause gets called, it should trigger
//    MediaStreamVideoRenderer::Pause, and then the provider will stop
//    pushing frames into WebMediaPlayerMS, but instead digesting them;
//    simultanously, it should call cc::VideoFrameProviderClient::StopRendering,
//    so cc::VideoFrameProviderClient will stop asking frames from
//    WebMediaPlayerMSCompositor.
// 7. When WebMediaPlayerMS::play gets called, evething paused in step 6 should
//    be resumed.
class WebMediaPlayerMSTest
    : public testing::TestWithParam<
          testing::tuple<bool /* enable_surface_layer_for_video */,
                         bool /* opaque_frame */,
                         bool /* odd_size_frame */>>,
      public WebMediaPlayerClient,
      public cc::VideoFrameProvider::Client {};

void WebMediaPlayerMSTest::InitializeWebMediaPlayerMS() {}

MockMediaStreamVideoRenderer* WebMediaPlayerMSTest::LoadAndGetFrameProvider(
    bool algorithm_enabled) {}

void WebMediaPlayerMSTest::NetworkStateChanged() {}

void WebMediaPlayerMSTest::ReadyStateChanged() {}

void WebMediaPlayerMSTest::SetCcLayer(cc::Layer* layer) {}

void WebMediaPlayerMSTest::StopUsingProvider() {}

void WebMediaPlayerMSTest::StartRendering() {}

void WebMediaPlayerMSTest::StopRendering() {}

void WebMediaPlayerMSTest::DidReceiveFrame() {}

void WebMediaPlayerMSTest::RenderFrame() {}

void WebMediaPlayerMSTest::SizeChanged() {}

void WebMediaPlayerMSTest::TestGetVideoFramePresentationMetadata(
    bool algorithm_enabled) {}

void WebMediaPlayerMSTest::TestRequestFrameCallbackWithVideoFrameMetadata(
    bool algorithm_enabled) {}

TEST_P(WebMediaPlayerMSTest, NoDataDuringLoadForVideo) {}

TEST_P(WebMediaPlayerMSTest, NoWaitForFrameForAudio) {}

// Test that OnPictureInPictureStateChange is not called for audio elements.
// This test explicitly sets display type to picture in picture, for an audio
// element, for testing purposes only (See crbug.com/1403547 for reference).
TEST_P(WebMediaPlayerMSTest, PictureInPictureStateChangeNotCalled) {}

TEST_P(WebMediaPlayerMSTest, NoWaitForFrameForAudioOnly) {}

TEST_P(WebMediaPlayerMSTest, Playing_Normal) {}

TEST_P(WebMediaPlayerMSTest, PlayThenPause) {}

TEST_P(WebMediaPlayerMSTest, PlayThenPauseThenPlay) {}

// During this test, we check that when we send rotated video frames, it applies
// to player's natural size.
TEST_P(WebMediaPlayerMSTest, RotationChange) {}

// During this test, we check that web layer changes opacity according to the
// given frames.
TEST_P(WebMediaPlayerMSTest, OpacityChange) {}

TEST_P(WebMediaPlayerMSTest, BackgroundRendering) {}

TEST_P(WebMediaPlayerMSTest, FrameSizeChange) {}

// Tests that GpuMemoryBufferVideoFramePool is called in the expected sequence.
TEST_P(WebMediaPlayerMSTest, CreateHardwareFrames) {}
#if BUILDFLAG(IS_ANDROID)
TEST_P(WebMediaPlayerMSTest, HiddenPlayerTests) {
  InitializeWebMediaPlayerMS();
  LoadAndGetFrameProvider(true);

  // Hidden status should not affect playback.
  delegate_.set_page_hidden(true);
  player_->Play();
  EXPECT_FALSE(player_->Paused());

  // A hidden player should start still be playing upon shown.
  delegate_.set_page_hidden(false);
  player_->OnPageShown();
  EXPECT_FALSE(player_->Paused());

  // A hidden event should not pause the player.
  delegate_.set_page_hidden(true);
  player_->OnPageHidden();
  EXPECT_FALSE(player_->Paused());

  // A user generated pause() should clear the automatic resumption.
  player_->Pause();
  delegate_.set_page_hidden(false);
  player_->OnPageShown();
  EXPECT_TRUE(player_->Paused());

  // A user generated play() should start playback.
  player_->Play();
  EXPECT_FALSE(player_->Paused());

  // An OnSuspendRequested() without forced suspension should do nothing.
  player_->OnIdleTimeout();
  EXPECT_FALSE(player_->Paused());

  // An OnSuspendRequested() with forced suspension should pause playback.
  player_->SuspendForFrameClosed();
  EXPECT_TRUE(player_->Paused());

  // OnShown() should restart after a forced suspension.
  player_->OnPageShown();
  EXPECT_FALSE(player_->Paused());
  EXPECT_CALL(*this, DoSetCcLayer(false));

  base::RunLoop().RunUntilIdle();
}
#endif

TEST_P(WebMediaPlayerMSTest, RequestVideoFrameCallback) {}

TEST_P(WebMediaPlayerMSTest, RequestVideoFrameCallbackWithNoAlgorithm) {}

TEST_P(WebMediaPlayerMSTest, RequestVideoFrameCallback_ForcesBeginFrames) {}

TEST_P(WebMediaPlayerMSTest, GetVideoFramePresentationMetadata) {}

TEST_P(WebMediaPlayerMSTest, GetVideoFramePresentationMetadataWithNoAlgorithm) {}

TEST_P(WebMediaPlayerMSTest, DuplicateFrameTimestamp) {}

TEST_P(WebMediaPlayerMSTest, HandlesArbitraryTimestampConversions) {}

TEST_P(WebMediaPlayerMSTest, OutOfOrderEnqueue) {}

TEST_P(WebMediaPlayerMSTest, ValidPreferredInterval) {}

TEST_P(WebMediaPlayerMSTest, OnContextLost) {}

INSTANTIATE_TEST_SUITE_P();
}  // namespace blink