File: rtc_encoded_video_underlying_source.cc

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 (156 lines) | stat: -rw-r--r-- 6,121 bytes parent folder | download | duplicates (6)
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
// 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/peerconnection/rtc_encoded_video_underlying_source.h"

#include "base/memory/ptr_util.h"
#include "base/unguessable_token.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h"
#include "third_party/blink/renderer/core/streams/readable_stream_default_controller_with_script_scope.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame.h"
#include "third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_frame_delegate.h"
#include "third_party/blink/renderer/platform/bindings/exception_code.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
#include "third_party/blink/renderer/platform/heap/cross_thread_persistent.h"
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
#include "third_party/webrtc/api/frame_transformer_interface.h"

namespace blink {

// Frames should not be queued at all. We allow queuing a few frames to deal
// with transient slowdowns. Specified as a negative number of frames since
// queuing is reported by the stream controller as a negative desired size.
const int RTCEncodedVideoUnderlyingSource::kMinQueueDesiredSize = -60;

RTCEncodedVideoUnderlyingSource::RTCEncodedVideoUnderlyingSource(
    ScriptState* script_state,
    WTF::CrossThreadOnceClosure disconnect_callback)
    : blink::RTCEncodedVideoUnderlyingSource(
          script_state,
          std::move(disconnect_callback),
          /*enable_frame_restrictions=*/false,
          base::UnguessableToken::Null(),
          /*controller_override=*/nullptr) {}

RTCEncodedVideoUnderlyingSource::RTCEncodedVideoUnderlyingSource(
    ScriptState* script_state,
    WTF::CrossThreadOnceClosure disconnect_callback,
    bool enable_frame_restrictions,
    base::UnguessableToken owner_id,
    ReadableStreamDefaultControllerWithScriptScope* override_controller)
    : UnderlyingSourceBase(script_state),
      script_state_(script_state),
      disconnect_callback_(std::move(disconnect_callback)),
      controller_override_(override_controller),
      enable_frame_restrictions_(enable_frame_restrictions),
      owner_id_(owner_id) {
  DCHECK(disconnect_callback_);

  ExecutionContext* context = ExecutionContext::From(script_state);
  task_runner_ = context->GetTaskRunner(TaskType::kInternalMediaRealTime);
}

ScriptPromise<IDLUndefined> RTCEncodedVideoUnderlyingSource::Pull(
    ScriptState* script_state,
    ExceptionState&) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  // WebRTC is a push source without backpressure support, so nothing to do
  // here.
  return ToResolvedUndefinedPromise(script_state);
}

ScriptPromise<IDLUndefined> RTCEncodedVideoUnderlyingSource::Cancel(
    ScriptState* script_state,
    ScriptValue reason,
    ExceptionState&) {
  DCHECK(task_runner_->BelongsToCurrentThread());
  if (disconnect_callback_)
    std::move(disconnect_callback_).Run();
  return ToResolvedUndefinedPromise(script_state);
}

void RTCEncodedVideoUnderlyingSource::Trace(Visitor* visitor) const {
  visitor->Trace(script_state_);
  visitor->Trace(controller_override_);
  UnderlyingSourceBase::Trace(visitor);
}

ReadableStreamDefaultControllerWithScriptScope*
RTCEncodedVideoUnderlyingSource::GetController() {
  if (controller_override_) {
    return controller_override_;
  }
  return Controller();
}

void RTCEncodedVideoUnderlyingSource::OnFrameFromSource(
    std::unique_ptr<webrtc::TransformableVideoFrameInterface> webrtc_frame) {
  // It can happen that a frame is posted to the task runner of the old
  // execution context during a stream transfer to a new context.
  // TODO(https://crbug.com/1506631): Make the state updates related to the
  // transfer atomic and turn this into a DCHECK.
  if (!task_runner_->BelongsToCurrentThread()) {
    DVLOG(1) << "Dropped frame posted to incorrect task runner. This can "
                "happen during transfer.";
    return;
  }
  // If the source is canceled or there are too many queued frames,
  // drop the new frame.
  if (!disconnect_callback_ || !GetExecutionContext()) {
    return;
  }
  if (!GetController()) {
    // TODO(ricea): Maybe avoid dropping frames during transfer?
    DVLOG(1) << "Dropped frame due to null Controller(). This can happen "
                "during transfer.";
    return;
  }
  if (GetController()->DesiredSize() <= kMinQueueDesiredSize) {
    dropped_frames_++;
    VLOG_IF(2, (dropped_frames_ % 20 == 0))
        << "Dropped total of " << dropped_frames_
        << " encoded video frames due to too many already being queued.";
    return;
  }
  RTCEncodedVideoFrame* encoded_frame;
  if (enable_frame_restrictions_) {
    encoded_frame = MakeGarbageCollected<RTCEncodedVideoFrame>(
        std::move(webrtc_frame), owner_id_, ++last_enqueued_frame_counter_);
  } else {
    encoded_frame =
        MakeGarbageCollected<RTCEncodedVideoFrame>(std::move(webrtc_frame));
  }
  GetController()->Enqueue(encoded_frame);
}

void RTCEncodedVideoUnderlyingSource::Close() {
  DCHECK(task_runner_->BelongsToCurrentThread());
  if (disconnect_callback_)
    std::move(disconnect_callback_).Run();

  if (GetController()) {
    GetController()->Close();
  }
}

void RTCEncodedVideoUnderlyingSource::OnSourceTransferStartedOnTaskRunner() {
  DCHECK(task_runner_->BelongsToCurrentThread());
  // This can potentially be called before the stream is constructed and so
  // Controller() is still unset.
  if (GetController()) {
    GetController()->Close();
  }
}

void RTCEncodedVideoUnderlyingSource::OnSourceTransferStarted() {
  PostCrossThreadTask(
      *task_runner_, FROM_HERE,
      CrossThreadBindOnce(
          &RTCEncodedVideoUnderlyingSource::OnSourceTransferStartedOnTaskRunner,
          WrapCrossThreadPersistent(this)));
}

}  // namespace blink