File: video_decoder_broker.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 (160 lines) | stat: -rw-r--r-- 6,301 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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
// 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_DECODER_BROKER_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_DECODER_BROKER_H_

#include <memory>
#include <optional>
#include <string>
#include <vector>

#include "base/functional/callback.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "media/base/decoder_status.h"
#include "media/base/video_decoder.h"
#include "media/base/video_frame.h"
#include "media/video/gpu_video_accelerator_factories.h"
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
#include "third_party/blink/renderer/modules/modules_export.h"
#include "third_party/blink/renderer/modules/webcodecs/hardware_preference.h"
#include "third_party/blink/renderer/platform/wtf/hash_map.h"

namespace base {
class SequencedTaskRunner;
}  // namespace base

namespace blink {

// Implementation detail of VideoDecoderBroker. Helps safely perform decoder
// tasks on the media thread.
class MediaVideoTaskWrapper;

// Client interface for MediaVideoTaskWrapper. Implementation detail of
// VideoDecoderBroker, but we need to define it here to implement it below.
//
// This avoids having pass-through callbacks from main->media task sequence,
// which is unsafe because the public callers of broker APIs may be broken if
// their callback is destructed on another thread.
//
// An int "cb_id" is used for those that are traditionally OnceCallbacks to
// lookup the correct public callback.
class CrossThreadVideoDecoderClient {
 public:
  struct DecoderDetails {
    media::VideoDecoderType decoder_id;
    bool is_platform_decoder;
    bool needs_bitstream_conversion;
    int max_decode_requests;
  };

  virtual void OnInitialize(media::DecoderStatus status,
                            std::optional<DecoderDetails> details) = 0;

  virtual void OnDecodeDone(int cb_id, media::DecoderStatus status) = 0;

  virtual void OnDecodeOutput(scoped_refptr<media::VideoFrame> frame,
                              bool can_read_without_stalling) = 0;

  virtual void OnReset(int cb_id) = 0;
};

// This class brokers the connection between WebCodecs and an underlying
// media::VideoDecoder. It abstracts away details of construction and selection
// of the media/ decoder. It also handles thread-hopping as required by
// underlying APIS.
//
// A new underlying decoder is selected anytime Initialize() is called.
// TODO(chcunningham): Elide re-selection if the config has not significantly
// changed.
//
// All API calls and callbacks must occur on the main thread.
class MODULES_EXPORT VideoDecoderBroker : public media::VideoDecoder,
                                          public CrossThreadVideoDecoderClient {
 public:
  // |gpu_factories| may be null when GPU accelerated decoding is not available.
  explicit VideoDecoderBroker(
      ExecutionContext& execution_context,
      media::GpuVideoAcceleratorFactories* gpu_factories,
      media::MediaLog* media_log);
  ~VideoDecoderBroker() override;

  // Disallow copy and assign.
  VideoDecoderBroker(const VideoDecoderBroker&) = delete;
  VideoDecoderBroker& operator=(const VideoDecoderBroker&) = delete;

  // VideoDecoder implementation.
  media::VideoDecoderType GetDecoderType() const override;
  bool IsPlatformDecoder() const override;
  void Initialize(const media::VideoDecoderConfig& config,
                  bool low_delay,
                  media::CdmContext* cdm_context,
                  InitCB init_cb,
                  const OutputCB& output_cb,
                  const media::WaitingCB& waiting_cb) override;
  void Decode(scoped_refptr<media::DecoderBuffer> buffer,
              DecodeCB decode_cb) override;
  void Reset(base::OnceClosure reset_cb) override;
  bool NeedsBitstreamConversion() const override;
  bool CanReadWithoutStalling() const override;
  int GetMaxDecodeRequests() const override;

  void SetHardwarePreference(HardwarePreference hardware_preference);

 private:
  // Creates a new (incremented) callback ID from |last_callback_id_| for
  // mapping in |pending_decode_cb_map_|.
  int CreateCallbackId();

  // MediaVideoTaskWrapper::CrossThreadVideoDecoderClient
  void OnInitialize(media::DecoderStatus status,
                    std::optional<DecoderDetails> details) override;
  void OnDecodeDone(int cb_id, media::DecoderStatus status) override;
  void OnDecodeOutput(scoped_refptr<media::VideoFrame> frame,
                      bool can_read_without_stalling) override;
  void OnReset(int cb_id) override;

  // When media::GpuVideoAcceleratorFactories is provided, its API requires
  // that we use its TaskRunner (the media thread). When not provided, this task
  // runner will still be used to reduce contention on the main thread.
  // TODO(chcunningham): Try to eliminate the Post(). Most of the
  // underlying::VideoDecoders already offload their work, so this just adds
  // overhead.
  scoped_refptr<base::SequencedTaskRunner> media_task_runner_;

  // Owner of state and methods to be used on media_task_runner_;
  std::unique_ptr<MediaVideoTaskWrapper> media_tasks_;

  // Wrapper state for GetDecoderType(), IsPlatformDecoder() and others.
  std::optional<DecoderDetails> decoder_details_;

  // Set to match the underlying decoder's answer at every OnDecodeOutput().
  bool can_read_without_stalling_ = true;

  // Holds the last key for callbacks in the map below. Incremented for each
  // usage via CreateCallbackId().
  uint32_t last_callback_id_ = 0;

  // Maps a callback ID to pending Decode(). See CrossThreadVideoDecoderClient.
  HashMap<int, DecodeCB> pending_decode_cb_map_;

  // Maps a callback ID to pending Reset(). See CrossThreadVideoDecoderClient.
  HashMap<int, base::OnceClosure> pending_reset_cb_map_;

  // Pending InitCB saved from the last call to Initialize();
  InitCB init_cb_;

  // OutputCB saved from last call to Initialize().
  OutputCB output_cb_;

  SEQUENCE_CHECKER(sequence_checker_);

  base::WeakPtrFactory<VideoDecoderBroker> weak_factory_{this};
};

}  // namespace blink

#endif  // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBCODECS_VIDEO_DECODER_BROKER_H_