summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/modules/video_rvfc/video_frame_request_callback_collection.cc
blob: b9676a22842fb3fc5b2eb53bc9d1cff831d256bd (plain)
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
// Copyright 2019 The Chromium Authors. All rights reserved.
// 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/video_rvfc/video_frame_request_callback_collection.h"

#include "third_party/blink/renderer/core/inspector/inspector_trace_events.h"
#include "third_party/blink/renderer/core/probe/core_probes.h"

namespace blink {

VideoFrameRequestCallbackCollection::VideoFrameRequestCallbackCollection(
    ExecutionContext* context)
    : context_(context) {}

VideoFrameRequestCallbackCollection::CallbackId
VideoFrameRequestCallbackCollection::RegisterFrameCallback(
    VideoFrameCallback* callback) {
  VideoFrameRequestCallbackCollection::CallbackId id = ++next_callback_id_;
  callback->SetIsCancelled(false);
  callback->SetId(id);
  frame_callbacks_.push_back(callback);

  return id;
}

void VideoFrameRequestCallbackCollection::CancelFrameCallback(CallbackId id) {
  for (wtf_size_t i = 0; i < frame_callbacks_.size(); ++i) {
    if (frame_callbacks_[i]->Id() == id) {
      frame_callbacks_.EraseAt(i);
      return;
    }
  }
  for (const auto& callback : callbacks_to_invoke_) {
    if (callback->Id() == id) {
      callback->SetIsCancelled(true);
      // will be removed at the end of ExecuteCallbacks().
      return;
    }
  }
}

void VideoFrameRequestCallbackCollection::ExecuteFrameCallbacks(
    double high_res_now_ms,
    const VideoFrameMetadata* metadata) {
  // First, generate a list of callbacks to consider. Callbacks registered from
  // this point on are considered only for the "next" frame, not this one.
  DCHECK(callbacks_to_invoke_.IsEmpty());
  std::swap(callbacks_to_invoke_, frame_callbacks_);

  for (const auto& callback : callbacks_to_invoke_) {
    // When the ExecutionContext is destroyed (e.g. an iframe is detached),
    // there is no path to perform wrapper tracing for the callbacks. In such a
    // case, the callback functions may already have been collected by V8 GC.
    // Since it's possible that a callback function being invoked detaches an
    // iframe, we need to check the condition for each callback.
    if (context_->IsContextDestroyed())
      break;

    // Another requestAnimationFrame callback already cancelled this one.
    if (callback->IsCancelled())
      continue;

    callback->Invoke(high_res_now_ms, metadata);
  }

  callbacks_to_invoke_.clear();
}

void VideoFrameRequestCallbackCollection::Trace(Visitor* visitor) {
  visitor->Trace(frame_callbacks_);
  visitor->Trace(callbacks_to_invoke_);
  visitor->Trace(context_);
}

VideoFrameRequestCallbackCollection::V8VideoFrameCallback::V8VideoFrameCallback(
    V8VideoFrameRequestCallback* callback)
    : callback_(callback) {}

void VideoFrameRequestCallbackCollection::V8VideoFrameCallback::Trace(
    blink::Visitor* visitor) {
  visitor->Trace(callback_);
  VideoFrameRequestCallbackCollection::VideoFrameCallback::Trace(visitor);
}

void VideoFrameRequestCallbackCollection::V8VideoFrameCallback::Invoke(
    double highResTime,
    const VideoFrameMetadata* metadata) {
  callback_->InvokeAndReportException(nullptr, highResTime, metadata);
}

}  // namespace blink