File: video_frame_monitor.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 (131 lines) | stat: -rw-r--r-- 6,021 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
// 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_WEBCODECS_VIDEO_FRAME_MONITOR_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_FRAME_MONITOR_H_

#include <map>
#include <optional>
#include <string>

#include "base/synchronization/lock.h"
#include "media/base/video_frame.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/platform/allow_discouraged_type.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"
#include "third_party/blink/renderer/platform/wtf/hash_traits.h"

namespace blink {

// This class helps monitor usage of media::VideoFrame objects. This class does
// not directly use VideoFrames, but references them using the ID returned by
// media::VideoFrame::unique_id.
// This class is an alternative to using media::VideoFrame destruction observers
// for cases that require monitoring to stop well before the media::VideoFrame
// is destroyed. For example, monitoring blink::VideoFrames backed by
// media::VideoFrames, where the JS-exposed blink::VideoFrames can be closed
// but the backing media::VideoFrames can continue to live outside the
// blink::VideoFrames.
// This class is a per-renderer-process singleton and relies on the fact
// that VideoFrame IDs are unique per process. That means that the same ID
// identifies the same frame regardless of the execution context.
// The motivating use case for this class is keeping track of frames coming
// from sources that have global limits in the number of in-flight frames
// allowed. Thus, frames are monitored per source. Sources are identified with
// a nonempty std::string, so any way to group frames can be used as long as a
// source ID is given. std::string is chosen over the Blink-standard WTF::String
// because:
//   1. source IDs often come from outside Blink (e.g., camera and screen
//      device IDs)
//   2. std::string is easier to use in a multithreaded environment.
// All the methods of this class can be called from any thread.
class MODULES_EXPORT VideoFrameMonitor {
 public:
  // Returns the singleton VideoFrameMonitor.
  static VideoFrameMonitor& Instance();
  VideoFrameMonitor(const VideoFrameMonitor&) = delete;
  VideoFrameMonitor& operator=(const VideoFrameMonitor&) = delete;

  // Report that a new frame with ID |frame_id| associated with the source with
  // ID |source_id| is being monitored.
  void OnOpenFrame(const std::string& source_id,
                   media::VideoFrame::ID frame_id);
  // Report that a new frame with ID |frame_id| associated with the source with
  // ID |source_id| is being monitored.
  void OnCloseFrame(const std::string& source_id,
                    media::VideoFrame::ID frame_id);
  // Reports the number of distinct monitored frames associated with
  // |source_id|.
  wtf_size_t NumFrames(const std::string& source_id);
  // Reports the reference count for the frame with ID |frame_id| associated
  // with the source with ID |source_id|.
  int NumRefs(const std::string& source_id, media::VideoFrame::ID frame_id);

  // Reports true if nothing is being monitored, false otherwise.
  bool IsEmpty();

  // This function returns a lock that can be used to lock the
  // VideoFrameMonitor so that multiple invocations to the methods below
  // (suffixed with "Locked" can be done atomically, as a single update to
  // the monitor. Locking the VideoFrameMonitor using GetLock() must be done
  // very carefully, as any invocation to any non-Locked method while the lock
  // is acquired will result in deadlock.
  // For example, blink::VideoFrame objects may be automatically monitored, so
  // they should not be created, cloned or closed while the lock is acquired.
  base::Lock& GetLock() { return lock_; }

  // The methods below can be called only when the mutex returned by GetLock()
  // has been acquired. Other than that, they are equivalent to their
  // corresponding non-locked version.
  void OnOpenFrameLocked(const std::string& source_id,
                         media::VideoFrame::ID frame_id)
      EXCLUSIVE_LOCKS_REQUIRED(GetLock());
  void OnCloseFrameLocked(const std::string& source_id,
                          media::VideoFrame::ID frame_id)
      EXCLUSIVE_LOCKS_REQUIRED(GetLock());
  wtf_size_t NumFramesLocked(const std::string& source_id)
      EXCLUSIVE_LOCKS_REQUIRED(GetLock());
  int NumRefsLocked(const std::string& source_id,
                    media::VideoFrame::ID frame_id)
      EXCLUSIVE_LOCKS_REQUIRED(GetLock());

 private:
  VideoFrameMonitor() = default;

  // key: unique ID of a frame.
  // value: reference count for the frame (among objects explicitly tracking
  //        the frame with VideoFrameMonitor).
  struct VideoFrameIDHashTraits
      : WTF::GenericHashTraits<media::VideoFrame::ID> {
    static unsigned GetHash(media::VideoFrame::ID key) {
      static_assert(std::is_same_v<decltype(key.GetUnsafeValue()), uint64_t>);
      return WTF::HashInt(key.GetUnsafeValue());
    }

    static const bool kEmptyValueIsZero = false;

    static media::VideoFrame::ID EmptyValue() {
      return media::VideoFrame::ID();
    }
    static media::VideoFrame::ID DeletedValue() {
      return media::VideoFrame::ID::FromUnsafeValue(
          std::numeric_limits<media::VideoFrame::ID::underlying_type>::max());
    }
  };
  using FrameMap = HashMap<media::VideoFrame::ID, int, VideoFrameIDHashTraits>;

  // key: ID of the source of the frames.
  // value: References to frames associated to that source.
  // Using std::map because HashMap does not directly support std::string.
  using SourceMap ALLOW_DISCOURAGED_TYPE("TODO(crbug.com/1404327)") =
      std::map<std::string, FrameMap>;

  base::Lock lock_;
  // Contains all data for VideoFrameMonitor.
  SourceMap map_ GUARDED_BY(GetLock());
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_FRAME_MONITOR_H_