File: frame_queue_underlying_source.h

package info (click to toggle)
chromium 138.0.7204.183-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 6,071,908 kB
  • sloc: cpp: 34,937,088; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,953; 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,806; 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 (181 lines) | stat: -rw-r--r-- 7,428 bytes parent folder | download | duplicates (3)
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_BREAKOUT_BOX_FRAME_QUEUE_UNDERLYING_SOURCE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_BREAKOUT_BOX_FRAME_QUEUE_UNDERLYING_SOURCE_H_

#include "base/synchronization/lock.h"
#include "base/task/sequenced_task_runner.h"
#include "base/threading/thread_checker.h"
#include "media/base/audio_buffer.h"
#include "media/base/video_frame.h"
#include "third_party/blink/renderer/core/streams/underlying_source_base.h"
#include "third_party/blink/renderer/modules/breakout_box/frame_queue.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/heap/cross_thread_persistent.h"
#include "third_party/blink/renderer/platform/wtf/deque.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"

namespace blink {

MODULES_EXPORT BASE_DECLARE_FEATURE(kBreakoutBoxInsertVideoCaptureTimestamp);

template <typename NativeFrameType>
class FrameQueueUnderlyingSource : public UnderlyingSourceBase {
 public:
  using TransferFramesCB = CrossThreadFunction<void(NativeFrameType)>;

  // Initializes a new FrameQueueUnderlyingSource with a new internal circular
  // queue that can hold up to |queue_size| elements. If a nonempty |device_id|
  // is given, it will be used as a key to monitor open frames.
  FrameQueueUnderlyingSource(ScriptState*,
                             wtf_size_t queue_size,
                             std::string device_id,
                             wtf_size_t frame_pool_size);
  FrameQueueUnderlyingSource(ScriptState*, wtf_size_t queue_size);
  ~FrameQueueUnderlyingSource() override = default;

  FrameQueueUnderlyingSource(const FrameQueueUnderlyingSource&) = delete;
  FrameQueueUnderlyingSource& operator=(const FrameQueueUnderlyingSource&) =
      delete;

  // UnderlyingSourceBase
  ScriptPromise<IDLUndefined> Pull(ScriptState*, ExceptionState&) override;
  ScriptPromise<IDLUndefined> Start(ScriptState*) override;
  ScriptPromise<IDLUndefined> Cancel(ScriptState*,
                                     ScriptValue reason,
                                     ExceptionState&) override;

  // ExecutionLifecycleObserver
  void ContextDestroyed() override;

  wtf_size_t MaxQueueSize() const;

  // Clears all internal state and closes the UnderlyingSource's Controller.
  // Must be called on |realm_task_runner_|.
  void Close();

  bool IsClosed() { return is_closed_; }

  // Start or stop the delivery of frames via QueueFrame().
  // Must be called on |realm_task_runner_|.
  virtual bool StartFrameDelivery() = 0;
  virtual void StopFrameDelivery() = 0;

  // Delivers a new frame to this source.
  void QueueFrame(NativeFrameType);

  int NumPendingPullsForTesting() const;
  double DesiredSizeForTesting() const;

  void Trace(Visitor*) const override;

 protected:
  // Initializes a new FrameQueueUnderlyingSource containing a
  // |frame_queue_handle_| that references the same internal circular queue as
  // |other_source|.
  FrameQueueUnderlyingSource(
      ScriptState*,
      FrameQueueUnderlyingSource<NativeFrameType>* other_source);
  scoped_refptr<base::SequencedTaskRunner> GetRealmRunner() {
    return realm_task_runner_;
  }

  // Sets |transferred_source| as the new target for frames arriving via
  // QueueFrame(). |transferred_source| will pull frames from the same circular
  // queue. Must be called on |realm_task_runner_|.
  void TransferSource(
      CrossThreadPersistent<FrameQueueUnderlyingSource<NativeFrameType>>
          transferred_source);

  // Due to a potential race condition between |transferred_source_|'s heap
  // being destroyed and the Close() method being called, we need to explicitly
  // clear |transferred_source_| when its context is being destroyed.
  void ClearTransferredSource();

 protected:
  bool MustUseMonitor() const;

 private:
  // Must be called on |realm_task_runner_|.
  void CloseController();

  // If the internal queue is not empty, pops a frame from it and enqueues it
  // into the the stream's controller. Must be called on |realm_task_runner|.
  void MaybeSendFrameFromQueueToStream();

  base::Lock& GetMonitorLock();

  void MaybeMonitorPopFrameId(media::VideoFrame::ID frame_id);
  void MonitorPopFrameLocked(const NativeFrameType& media_frame)
      EXCLUSIVE_LOCKS_REQUIRED(GetMonitorLock());
  void MonitorPushFrameLocked(const NativeFrameType& media_frame)
      EXCLUSIVE_LOCKS_REQUIRED(GetMonitorLock());

  enum class NewFrameAction { kPush, kReplace, kDrop };
  NewFrameAction AnalyzeNewFrameLocked(
      const NativeFrameType& media_frame,
      const std::optional<NativeFrameType>& old_frame);

  // Creates a JS frame (VideoFrame or AudioData) backed by |media_frame|.
  // Must be called on |realm_task_runner_|.
  ScriptWrappable* MakeBlinkFrame(NativeFrameType media_frame);

  void EnqueueBlinkFrame(ScriptWrappable* blink_frame) const;

  bool is_closed_ = false;

  // Main task runner for the window or worker context this source runs on.
  const scoped_refptr<base::SequencedTaskRunner> realm_task_runner_;

  // |frame_queue_handle_| is a handle containing a reference to an internal
  // circular queue prior to the stream controller's queue. It allows dropping
  // older frames in case frames accumulate due to slow consumption.
  // Frames are normally pushed on a background task runner (for example, the
  // IO thread) and popped on |realm_task_runner_|.
  FrameQueueHandle<NativeFrameType> frame_queue_handle_;

  mutable base::Lock lock_;
  // If the stream backed by this source is transferred to another in-process
  // realm (e.g., a Worker), |transferred_source_| is the source of the
  // transferred stream.
  CrossThreadPersistent<FrameQueueUnderlyingSource<NativeFrameType>>
      transferred_source_ GUARDED_BY(lock_);
  int num_pending_pulls_ GUARDED_BY(lock_) = 0;
  // When nonempty, |device_id_| is used to monitor all frames queued by this
  // source or exposed to JS via the stream connected to this source.
  // Frame monitoring applies only to video. Audio is never monitored.
  const std::string device_id_;
  // Maximum number of distinct frames allowed to be used by this source.
  // This limit applies only when |device_id_| is nonempty.
  const wtf_size_t frame_pool_size_ = 0;

  std::optional<base::TimeTicks> first_frame_ticks_;
};

template <>
ScriptWrappable* FrameQueueUnderlyingSource<scoped_refptr<media::VideoFrame>>::
    MakeBlinkFrame(scoped_refptr<media::VideoFrame>);

template <>
ScriptWrappable* FrameQueueUnderlyingSource<scoped_refptr<media::AudioBuffer>>::
    MakeBlinkFrame(scoped_refptr<media::AudioBuffer>);

template <>
bool FrameQueueUnderlyingSource<
    scoped_refptr<media::AudioBuffer>>::MustUseMonitor() const;

extern template class MODULES_EXTERN_TEMPLATE_EXPORT
    FrameQueueUnderlyingSource<scoped_refptr<media::VideoFrame>>;
extern template class MODULES_EXTERN_TEMPLATE_EXPORT
    FrameQueueUnderlyingSource<scoped_refptr<media::AudioBuffer>>;

using VideoFrameQueueUnderlyingSource =
    FrameQueueUnderlyingSource<scoped_refptr<media::VideoFrame>>;
using AudioDataQueueUnderlyingSource =
    FrameQueueUnderlyingSource<scoped_refptr<media::AudioBuffer>>;

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_BREAKOUT_BOX_FRAME_QUEUE_UNDERLYING_SOURCE_H_