File: video_frame_handle.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; 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-- 6,474 bytes parent folder | download | duplicates (9)
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.

#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_FRAME_HANDLE_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_FRAME_HANDLE_H_

#include "base/memory/scoped_refptr.h"
#include "base/synchronization/lock.h"
#include "base/thread_annotations.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/webcodecs/webcodecs_logger.h"
#include "third_party/blink/renderer/platform/wtf/functional.h"
#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
#include "third_party/skia/include/core/SkRefCnt.h"

// Note: Don't include "media/base/video_frame.h" here without good reason,
// since it includes a lot of non-blink types which can pollute the namespace.

class SkImage;

namespace media {
class VideoFrame;
}

namespace blink {

class ExecutionContext;

// Wrapper class that allows sharing a single |frame_| reference across
// multiple VideoFrames, which can be invalidated for all frames at once.
//
// If Invalidate() is not called before the handle's destructor runs, this means
// that none of the VideoFrames sharing this handle were closed, and they were
// all GC'ed instead. This can lead to stalls, since frames are not released
// fast enough through the GC to keep a pipeline running smoothly. In that case
// report an unclosed frame through |close_auditor_|.
class MODULES_EXPORT VideoFrameHandle
    : public WTF::ThreadSafeRefCounted<VideoFrameHandle> {
 public:
  VideoFrameHandle(scoped_refptr<media::VideoFrame>,
                   ExecutionContext*,
                   std::string monitoring_source_id = std::string(),
                   bool use_capture_timestamp = false);
  VideoFrameHandle(scoped_refptr<media::VideoFrame>,
                   sk_sp<SkImage> sk_image,
                   ExecutionContext*,
                   std::string monitoring_source_id = std::string(),
                   bool use_capture_timestamp = false);
  VideoFrameHandle(scoped_refptr<media::VideoFrame>,
                   sk_sp<SkImage> sk_image,
                   base::TimeDelta timestamp,
                   scoped_refptr<WebCodecsLogger::VideoFrameCloseAuditor>,
                   std::string monitoring_source_id = std::string());
  VideoFrameHandle(scoped_refptr<media::VideoFrame>,
                   sk_sp<SkImage> sk_image,
                   base::TimeDelta timestamp,
                   std::string monitoring_source_id = std::string());
  VideoFrameHandle(scoped_refptr<media::VideoFrame>,
                   sk_sp<SkImage> sk_image,
                   std::string monitoring_source_id = std::string());
  VideoFrameHandle(scoped_refptr<media::VideoFrame>,
                   sk_sp<SkImage> sk_image,
                   scoped_refptr<WebCodecsLogger::VideoFrameCloseAuditor>,
                   std::string monitoring_source_id = std::string());

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

  // Expire all GPUExternalTextures which are generated from
  // importExternalTexture and using VideoFrame as source. This callback should
  // be called when VideoFrameHandle is destroyed/Invalidate.
  using WebGPUExternalTextureExpireCallback = CrossThreadOnceFunction<void()>;

  // Returns a copy of |frame_|, which should be re-used throughout the scope
  // of a function call, instead of calling frame() multiple times. Otherwise
  // the frame could be destroyed between calls.
  scoped_refptr<media::VideoFrame> frame();

  // Returns a copy of |sk_image_| which may be nullptr if this isn't an SkImage
  // backed VideoFrame.
  sk_sp<SkImage> sk_image();

  // Releases the underlying media::VideoFrame reference, affecting all
  // blink::VideoFrames and blink::Planes that hold a reference to |this|.
  void Invalidate();

  // Temporary workaround for crbug.com/1182497.
  // Overrides the next call to Clone() to return |this| without adding a new
  // reference. This prevents cloning handles when internally posting frames to
  // a transferred stream, which cannot be cleared.
  void SetCloseOnClone();

  // Clones this VideoFrameHandle into a new VideoFrameHandle object.
  scoped_refptr<VideoFrameHandle> Clone();

  // Same as above, but for internal (non-garbage-collected) usage. Drops the
  // close auditor so warning messages aren't created for unclosed frames.
  scoped_refptr<VideoFrameHandle> CloneForInternalUse();

  // GPUExternalTexture generated with VideoFrame source needs to listen to
  // the VideoFrameHandle to expire themselves. Return false if the
  // VideoFrameHandle has been destroyed.
  bool WebGPURegisterExternalTextureExpireCallback(
      WebGPUExternalTextureExpireCallback
          webgpu_external_texture_expire_callback);

  base::TimeDelta timestamp() const { return timestamp_; }
  std::optional<base::TimeDelta> duration() const { return duration_; }

 private:
  friend class WTF::ThreadSafeRefCounted<VideoFrameHandle>;
  ~VideoFrameHandle();

  void InvalidateLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_);

  // Inform the GPUExternalTexture that VideoFrame is closed and expire the
  // external texture. |mutex_| must be held before calling into this.
  void NotifyExpiredLocked() EXCLUSIVE_LOCKS_REQUIRED(lock_);

  void MaybeMonitorOpenFrame() EXCLUSIVE_LOCKS_REQUIRED(lock_);
  void MaybeMonitorCloseFrame() EXCLUSIVE_LOCKS_REQUIRED(lock_);

  // Flag that prevents the creation of a new handle during the next Clone()
  // call. Used as a temporary workaround for crbug.com/1182497.
  bool close_on_clone_ GUARDED_BY(lock_) = false;

  base::Lock lock_;
  sk_sp<SkImage> sk_image_ GUARDED_BY(lock_);
  scoped_refptr<media::VideoFrame> frame_ GUARDED_BY(lock_);
  scoped_refptr<WebCodecsLogger::VideoFrameCloseAuditor> close_auditor_;
  Vector<WebGPUExternalTextureExpireCallback>
      webgpu_external_texture_expire_callbacks_;
  std::string monitoring_source_id_;

  // Timestamp and duration must remain valid after close(). If the timestamp or
  // duration of the underlying media::VideoFrame are modified after
  // blink::VideoFrame construction, those updates won't appear here.
  const base::TimeDelta timestamp_;
  const std::optional<base::TimeDelta> duration_;
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_FRAME_HANDLE_H_