chromium/content/browser/media/android/browser_gpu_video_accelerator_factories.cc

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

#include "content/browser/media/android/browser_gpu_video_accelerator_factories.h"

#include "base/functional/bind.h"
#include "base/task/sequenced_task_runner.h"
#include "content/browser/browser_main_loop.h"
#include "content/public/browser/android/gpu_video_accelerator_factories_provider.h"
#include "content/public/common/gpu_stream_constants.h"
#include "gpu/command_buffer/client/shared_memory_limits.h"
#include "gpu/command_buffer/common/context_creation_attribs.h"
#include "gpu/ipc/client/command_buffer_proxy_impl.h"
#include "gpu/ipc/client/gpu_channel_host.h"
#include "media/gpu/gpu_video_accelerator_util.h"
#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"

namespace content {

namespace {

void OnGpuChannelEstablished(
    GpuVideoAcceleratorFactoriesCallback callback,
    scoped_refptr<gpu::GpuChannelHost> gpu_channel_host) {
  gpu::ContextCreationAttribs attributes;
  attributes.bind_generates_resource = false;
  attributes.enable_raster_interface = true;
  attributes.enable_oop_rasterization = true;
  attributes.enable_gles2_interface = false;
  attributes.enable_grcontext = false;

  int32_t stream_id = kGpuStreamIdDefault;
  gpu::SchedulingPriority stream_priority = kGpuStreamPriorityUI;

  constexpr bool automatic_flushes = false;
  constexpr bool support_locking = false;

  auto context_provider =
      base::MakeRefCounted<viz::ContextProviderCommandBuffer>(
          std::move(gpu_channel_host), stream_id, stream_priority,
          gpu::kNullSurfaceHandle,
          GURL(std::string("chrome://gpu/"
                           "BrowserGpuVideoAcceleratorFactories::"
                           "CreateGpuVideoAcceleratorFactories")),
          automatic_flushes, support_locking,
          gpu::SharedMemoryLimits::ForMailboxContext(), attributes,
          viz::command_buffer_metrics::ContextType::UNKNOWN);
  context_provider->BindToCurrentSequence();

  auto gpu_factories = std::make_unique<BrowserGpuVideoAcceleratorFactories>(
      std::move(context_provider));
  std::move(callback).Run(std::move(gpu_factories));
}

}  // namespace

void CreateGpuVideoAcceleratorFactories(
    GpuVideoAcceleratorFactoriesCallback callback) {
  BrowserMainLoop::GetInstance()
      ->gpu_channel_establish_factory()
      ->EstablishGpuChannel(
          base::BindOnce(&OnGpuChannelEstablished, std::move(callback)));
}

BrowserGpuVideoAcceleratorFactories::BrowserGpuVideoAcceleratorFactories(
    scoped_refptr<viz::ContextProviderCommandBuffer> context_provider)
    : context_provider_(std::move(context_provider)) {}

BrowserGpuVideoAcceleratorFactories::~BrowserGpuVideoAcceleratorFactories() =
    default;

bool BrowserGpuVideoAcceleratorFactories::IsGpuVideoDecodeAcceleratorEnabled() {
  return false;
}

bool BrowserGpuVideoAcceleratorFactories::IsGpuVideoEncodeAcceleratorEnabled() {
  return false;
}

void BrowserGpuVideoAcceleratorFactories::GetChannelToken(
    gpu::mojom::GpuChannel::GetChannelTokenCallback cb) {
  DCHECK(cb);
  if (!channel_token_.is_empty()) {
    // Use cached token.
    std::move(cb).Run(channel_token_);
    return;
  }

  // Retrieve a channel token if needed.
  bool request_channel_token = channel_token_callbacks_.empty();
  channel_token_callbacks_.AddUnsafe(std::move(cb));
  if (request_channel_token) {
    context_provider_->GetCommandBufferProxy()->GetGpuChannel().GetChannelToken(
        base::BindOnce(
            &BrowserGpuVideoAcceleratorFactories::OnChannelTokenReady,
            base::Unretained(this)));
  }
}

void BrowserGpuVideoAcceleratorFactories::OnChannelTokenReady(
    const base::UnguessableToken& token) {
  channel_token_ = token;
  channel_token_callbacks_.Notify(channel_token_);
  DCHECK(channel_token_callbacks_.empty());
}

int32_t BrowserGpuVideoAcceleratorFactories::GetCommandBufferRouteId() {
  return context_provider_->GetCommandBufferProxy()->route_id();
}

media::GpuVideoAcceleratorFactories::Supported
BrowserGpuVideoAcceleratorFactories::IsDecoderConfigSupported(
    const media::VideoDecoderConfig& config) {
  // Tell the caller to just try it, there are no other decoders to fall back on
  // anyway.
  return media::GpuVideoAcceleratorFactories::Supported::kTrue;
}

media::VideoDecoderType BrowserGpuVideoAcceleratorFactories::GetDecoderType() {
  return media::VideoDecoderType::kMediaCodec;
}

bool BrowserGpuVideoAcceleratorFactories::IsDecoderSupportKnown() {
  return true;
}

void BrowserGpuVideoAcceleratorFactories::NotifyDecoderSupportKnown(
    base::OnceClosure callback) {
  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE,
                                                           std::move(callback));
}

std::unique_ptr<media::VideoDecoder>
BrowserGpuVideoAcceleratorFactories::CreateVideoDecoder(
    media::MediaLog* media_log,
    media::RequestOverlayInfoCB request_overlay_info_cb) {
  return nullptr;
}

std::unique_ptr<media::VideoEncodeAccelerator>
BrowserGpuVideoAcceleratorFactories::CreateVideoEncodeAccelerator() {
  return nullptr;
}

std::unique_ptr<gfx::GpuMemoryBuffer>
BrowserGpuVideoAcceleratorFactories::CreateGpuMemoryBuffer(
    const gfx::Size& size,
    gfx::BufferFormat format,
    gfx::BufferUsage usage) {
  return nullptr;
}

bool BrowserGpuVideoAcceleratorFactories::
    ShouldUseGpuMemoryBuffersForVideoFrames(bool for_media_stream) const {
  return false;
}

media::GpuVideoAcceleratorFactories::OutputFormat
BrowserGpuVideoAcceleratorFactories::VideoFrameOutputFormat(
    media::VideoPixelFormat pixel_format) {
  return GpuVideoAcceleratorFactories::OutputFormat::UNDEFINED;
}

gpu::SharedImageInterface*
BrowserGpuVideoAcceleratorFactories::SharedImageInterface() {
  NOTREACHED();
}

gpu::GpuMemoryBufferManager*
BrowserGpuVideoAcceleratorFactories::GpuMemoryBufferManager() {
  NOTREACHED();
}

base::UnsafeSharedMemoryRegion
BrowserGpuVideoAcceleratorFactories::CreateSharedMemoryRegion(size_t size) {
  return {};
}

scoped_refptr<base::SequencedTaskRunner>
BrowserGpuVideoAcceleratorFactories::GetTaskRunner() {
  return nullptr;
}

std::optional<media::VideoEncodeAccelerator::SupportedProfiles>
BrowserGpuVideoAcceleratorFactories::
    GetVideoEncodeAcceleratorSupportedProfiles() {
  return media::VideoEncodeAccelerator::SupportedProfiles();
}

bool BrowserGpuVideoAcceleratorFactories::IsEncoderSupportKnown() {
  return true;
}

void BrowserGpuVideoAcceleratorFactories::NotifyEncoderSupportKnown(
    base::OnceClosure callback) {
  base::SequencedTaskRunner::GetCurrentDefault()->PostTask(FROM_HERE,
                                                           std::move(callback));
}

viz::RasterContextProvider*
BrowserGpuVideoAcceleratorFactories::GetMediaContextProvider() {
  return context_provider_.get();
}

const gpu::Capabilities*
BrowserGpuVideoAcceleratorFactories::ContextCapabilities() {
  return context_provider_ ? &(context_provider_->ContextCapabilities())
                           : nullptr;
}

void BrowserGpuVideoAcceleratorFactories::SetRenderingColorSpace(
    const gfx::ColorSpace& color_space) {}

const gfx::ColorSpace&
BrowserGpuVideoAcceleratorFactories::GetRenderingColorSpace() const {
  static constexpr gfx::ColorSpace cs = gfx::ColorSpace::CreateSRGB();
  return cs;
}

}  // namespace content