File: realtime_audio_worklet_thread.cc

package info (click to toggle)
chromium 139.0.7258.138-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,120,676 kB
  • sloc: cpp: 35,100,869; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (145 lines) | stat: -rw-r--r-- 5,944 bytes parent folder | download | duplicates (7)
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// Copyright 2020 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/renderer/modules/webaudio/realtime_audio_worklet_thread.h"

#include "base/feature_list.h"
#include "base/metrics/histogram_functions.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/renderer/core/workers/global_scope_creation_params.h"
#include "third_party/blink/renderer/modules/webaudio/audio_worklet_global_scope.h"
#include "third_party/blink/renderer/platform/instrumentation/tracing/trace_event.h"

namespace blink {

namespace {

// The realtime AudioWorklet thread is managed by a pool system. The system
// can contain up to 4 concurrent real-time threads and it is based on “first
// come first served” policy.
// - The 1st ~ 3rd threads are a “dedicated” thread. The first 3 AudioWorklets
//   will have their own dedicated backing thread.
// - The 4th thread is a “shared” thread: Starting from the 4th AudioWorklet,
//   all subsequent contexts will share the same thread for the AudioWorklet
//   operation.
static constexpr int kMaxDedicatedBackingThreadCount = 3;

// Used for counting dedicated backing threads. Incremented by the constructor
// and decremented by destructor.
int dedicated_backing_thread_count = 0;

// Used for ref-counting of all backing thread in the current renderer process.
// Incremented by the constructor and decremented by destructor.
int shared_backing_thread_ref_count = 0;

// For UMA logging: Represents the maximum number of dedicated backing worklet
// threads throughout the lifetime of the document/frame. Can't exceed
// `kMaxDedicatedBackingThreadCount`.
int peak_dedicated_backing_thread_count = 0;

// For UMA logging: Represents the maximum number of ref counts using the
// shared backing thread throughout the lifetime of the document/frame.
int peak_shared_backing_thread_ref_count = 0;

}  // namespace

template class WorkletThreadHolder<RealtimeAudioWorkletThread>;

RealtimeAudioWorkletThread::RealtimeAudioWorkletThread(
    WorkerReportingProxy& worker_reporting_proxy,
    base::TimeDelta realtime_buffer_duration)
    : WorkerThread(worker_reporting_proxy) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("audio-worklet"),
               "RealtimeAudioWorkletThread()");

  DCHECK(IsMainThread());

  ThreadCreationParams params =
      ThreadCreationParams(ThreadType::kRealtimeAudioWorkletThread);

  // The real-time priority thread is enabled by default. A normal priority
  // thread is used when it is blocked by a field trial.
  if (base::FeatureList::IsEnabled(
          features::kAudioWorkletThreadRealtimePriority)) {
    // TODO(crbug.com/1022888): The worklet thread priority is always NORMAL on
    // Linux and Chrome OS regardless of this thread priority setting.
    params.base_thread_type = base::ThreadType::kRealtimeAudio;
    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("audio-worklet"),
                 "RealtimeAudioWorkletThread() - kRealtimeAudio");
#if BUILDFLAG(IS_APPLE)
    if (base::FeatureList::IsEnabled(
            features::kAudioWorkletThreadRealtimePeriodMac)) {
      params.realtime_period = realtime_buffer_duration;
      TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("audio-worklet"),
                   "RealtimeAudioWorkletThread()", "realtime period",
                   realtime_buffer_duration);
    }
#endif
  } else {
    params.base_thread_type = base::ThreadType::kDefault;
    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("audio-worklet"),
                 "RealtimeAudioWorkletThread() - kDefault");
  }

  if (base::FeatureList::IsEnabled(features::kAudioWorkletThreadPool) &&
      dedicated_backing_thread_count < kMaxDedicatedBackingThreadCount) {
    worker_backing_thread_ = std::make_unique<WorkerBackingThread>(params);
    dedicated_backing_thread_count++;
    if (peak_dedicated_backing_thread_count < dedicated_backing_thread_count) {
      peak_dedicated_backing_thread_count = dedicated_backing_thread_count;
      base::UmaHistogramExactLinear(
          "WebAudio.AudioWorklet.PeakDedicatedBackingThreadCount",
          peak_dedicated_backing_thread_count,
          kMaxDedicatedBackingThreadCount + 1);
    }
  } else {
    if (!shared_backing_thread_ref_count) {
      WorkletThreadHolder<RealtimeAudioWorkletThread>::EnsureInstance(params);
    }
    shared_backing_thread_ref_count++;
    if (peak_shared_backing_thread_ref_count <
        shared_backing_thread_ref_count) {
      peak_shared_backing_thread_ref_count = shared_backing_thread_ref_count;
      base::UmaHistogramExactLinear(
          "WebAudio.AudioWorklet.PeakSharedBackingThreadRefCount",
          peak_shared_backing_thread_ref_count, 101);
    }
  }
}

RealtimeAudioWorkletThread::~RealtimeAudioWorkletThread() {
  DCHECK(IsMainThread());

  if (worker_backing_thread_) {
    dedicated_backing_thread_count--;
    CHECK_GE(dedicated_backing_thread_count, 0);
  } else {
    shared_backing_thread_ref_count--;
    CHECK_GE(shared_backing_thread_ref_count, 0);
    if (!shared_backing_thread_ref_count) {
      WorkletThreadHolder<RealtimeAudioWorkletThread>::ClearInstance();
    }
  }
}

WorkerBackingThread& RealtimeAudioWorkletThread::GetWorkerBackingThread() {
  if (worker_backing_thread_) {
    return *worker_backing_thread_.get();
  }

  auto* shared_thread_instance =
      WorkletThreadHolder<RealtimeAudioWorkletThread>::GetInstance();
  CHECK(shared_thread_instance);
  return *shared_thread_instance->GetThread();
}

WorkerOrWorkletGlobalScope* RealtimeAudioWorkletThread::CreateWorkerGlobalScope(
    std::unique_ptr<GlobalScopeCreationParams> creation_params) {
  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("audio-worklet"),
               "RealtimeAudioWorkletThread::CreateWorkerGlobalScope");
  return MakeGarbageCollected<AudioWorkletGlobalScope>(
      std::move(creation_params), this);
}

}  // namespace blink