File: mirroring_gpu_factories_factory.cc

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; asm: 946,768; xml: 739,971; pascal: 187,324; sh: 89,623; perl: 88,663; objc: 79,944; sql: 50,304; cs: 41,786; fortran: 24,137; makefile: 21,811; php: 13,980; tcl: 13,166; yacc: 8,925; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (128 lines) | stat: -rw-r--r-- 4,819 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/mirroring/service/mirroring_gpu_factories_factory.h"

#include "base/functional/bind.h"
#include "media/mojo/mojom/video_encode_accelerator.mojom.h"
#include "services/viz/public/cpp/gpu/command_buffer_metrics.h"
#include "services/viz/public/cpp/gpu/context_provider_command_buffer.h"
#include "services/viz/public/cpp/gpu/gpu.h"

namespace mirroring {

namespace {

using media::cast::CastEnvironment;

}

MirroringGpuFactoriesFactory::MirroringGpuFactoriesFactory(
    scoped_refptr<CastEnvironment> cast_environment,
    viz::Gpu& gpu,
    base::RepeatingClosure context_lost_cb)
    : cast_environment_(std::move(cast_environment)),
      gpu_(gpu),
      context_lost_cb_(std::move(context_lost_cb)) {}

MirroringGpuFactoriesFactory::MirroringGpuFactoriesFactory(
    MirroringGpuFactoriesFactory&&) = default;
MirroringGpuFactoriesFactory& MirroringGpuFactoriesFactory::operator=(
    MirroringGpuFactoriesFactory&&) = default;
MirroringGpuFactoriesFactory::~MirroringGpuFactoriesFactory() {
  CHECK(cast_environment_->CurrentlyOn(CastEnvironment::ThreadId::kVideo));
  if (instance_) {
    DestroyInstance();
  }
  context_provider_->RemoveObserver(this);
  context_provider_ = nullptr;
}

media::GpuVideoAcceleratorFactories&
MirroringGpuFactoriesFactory::GetInstance() {
  // If we have a valid context, return the current instance as it is still
  // valid.
  if (instance_) {
    return *instance_;
  }

  // Finally, create and return a new instance.
  static constexpr int32_t kStreamId = 0;

  // TODO(crbug.com/282984511): experiment with creation attributes.
  gpu::ContextCreationAttribs creation_attribs;
  creation_attribs.gpu_preference = gl::GpuPreference::kHighPerformance,
  creation_attribs.bind_generates_resource = false,
  creation_attribs.enable_gles2_interface = true,
  creation_attribs.context_type = gpu::CONTEXT_TYPE_OPENGLES3;

  auto gpu_channel_host = gpu_->EstablishGpuChannelSync();
  context_provider_ = base::MakeRefCounted<viz::ContextProviderCommandBuffer>(
      gpu_channel_host, kStreamId, gpu::SchedulingPriority::kHigh,
      GURL(std::string("chrome://gpu/CastStreaming")),
      /* automatic_flushes = */ false, /* support_locking = */ false,
      gpu::SharedMemoryLimits::ForMailboxContext(), creation_attribs,
      viz::command_buffer_metrics::ContextType::VIDEO_CAPTURE);

  // NOTE: this Unretained is safe because `this` is deleted on the VIDEO
  // thread.
  cast_environment_->PostTask(
      CastEnvironment::ThreadId::kVideo, FROM_HERE,
      base::BindOnce(&MirroringGpuFactoriesFactory::BindOnVideoThread,
                     base::Unretained(this)));

  mojo::PendingRemote<media::mojom::VideoEncodeAcceleratorProvider>
      vea_provider;
  gpu_->CreateVideoEncodeAcceleratorProvider(
      vea_provider.InitWithNewPipeAndPassReceiver());

  auto codec_factory = std::make_unique<media::MojoCodecFactoryDefault>(
      cast_environment_->GetTaskRunner(CastEnvironment::ThreadId::kVideo),
      context_provider_,
      /*enable_video_decode_accelerator=*/false,
      /*enable_video_encode_accelerator=*/true, std::move(vea_provider));

  instance_ = media::MojoGpuVideoAcceleratorFactories::Create(
      std::move(gpu_channel_host),
      cast_environment_->GetTaskRunner(CastEnvironment::ThreadId::kMain),
      cast_environment_->GetTaskRunner(CastEnvironment::ThreadId::kVideo),
      context_provider_, std::move(codec_factory),
      /*enable_video_gpu_memory_buffers=*/true,
      /*enable_media_stream_gpu_memory_buffers=*/false,
      /*enable_video_decode_accelerator=*/false,
      /*enable_video_encode_accelerator=*/true);

  return *instance_;
}

void MirroringGpuFactoriesFactory::BindOnVideoThread() {
  CHECK(cast_environment_->CurrentlyOn(CastEnvironment::ThreadId::kVideo));
  CHECK(context_provider_);
  if (context_provider_->BindToCurrentSequence() !=
      gpu::ContextResult::kSuccess) {
    OnContextLost();
    return;
  }
  context_provider_->AddObserver(this);
}

void MirroringGpuFactoriesFactory::OnContextLost() {
  cast_environment_->PostTask(
      CastEnvironment::ThreadId::kVideo, FROM_HERE,
      base::BindOnce(&media::MojoGpuVideoAcceleratorFactories::DestroyContext,
                     base::Unretained(instance_.get())));

  std::move(context_lost_cb_).Run();
  DestroyInstance();
}

void MirroringGpuFactoriesFactory::DestroyInstance() {
  CHECK(instance_);
  // The GPU factories object, after construction, must only be accessed on the
  // video encoding thread (including for deletion).
  cast_environment_->GetTaskRunner(CastEnvironment::ThreadId::kVideo)
      ->DeleteSoon(FROM_HERE, std::move(instance_));
}

}  // namespace mirroring