File: v4l2_video_decoder_backend_stateful.h

package info (click to toggle)
chromium 138.0.7204.183-1~deb12u1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm-proposed-updates
  • size: 6,080,960 kB
  • sloc: cpp: 34,937,079; ansic: 7,176,967; javascript: 4,110,704; python: 1,419,954; 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,811; 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 (181 lines) | stat: -rw-r--r-- 6,673 bytes parent folder | download | duplicates (7)
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// 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 MEDIA_GPU_V4L2_LEGACY_V4L2_VIDEO_DECODER_BACKEND_STATEFUL_H_
#define MEDIA_GPU_V4L2_LEGACY_V4L2_VIDEO_DECODER_BACKEND_STATEFUL_H_

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

#include "base/containers/queue.h"
#include "base/task/sequenced_task_runner.h"
#include "base/time/time.h"
#include "media/base/video_codecs.h"
#include "media/gpu/v4l2/v4l2_device.h"
#include "media/gpu/v4l2/v4l2_framerate_control.h"
#include "media/gpu/v4l2/v4l2_video_decoder_backend.h"

namespace media {

namespace v4l2_vda_helpers {
class InputBufferFragmentSplitter;
}

class V4L2StatefulVideoDecoderBackend : public V4L2VideoDecoderBackend {
 public:
  V4L2StatefulVideoDecoderBackend(
      Client* const client,
      scoped_refptr<V4L2Device> device,
      VideoCodecProfile profile,
      const VideoColorSpace& color_space,
      scoped_refptr<base::SequencedTaskRunner> task_runner);
  ~V4L2StatefulVideoDecoderBackend() override;

  // We don't ever want to copy or move this.
  V4L2StatefulVideoDecoderBackend(const V4L2StatefulVideoDecoderBackend&) =
      delete;
  V4L2StatefulVideoDecoderBackend& operator=(
      const V4L2StatefulVideoDecoderBackend&) = delete;

  // V4L2VideoDecoderBackend implementation
  bool Initialize() override;
  void EnqueueDecodeTask(scoped_refptr<DecoderBuffer> buffer,
                         VideoDecoder::DecodeCB decode_cb) override;
  void OnOutputBufferDequeued(V4L2ReadableBufferRef buffer) override;
  void OnServiceDeviceTask(bool event) override;
  void OnStreamStopped(bool stop_input_queue) override;
  bool ApplyResolution(const gfx::Size& pic_size,
                       const gfx::Rect& visible_rect) override;
  void OnChangeResolutionDone(CroStatus status) override;
  void ClearPendingRequests(DecoderStatus status) override;
  bool StopInputQueueOnResChange() const override;
  size_t GetNumOUTPUTQueueBuffers(bool secure_mode) const override;

 private:
  // TODO(b:149663704): merge with stateless?
  // Request for decoding buffer. Every EnqueueDecodeTask() call generates 1
  // DecodeRequest.
  struct DecodeRequest {
    // The decode buffer passed to EnqueueDecodeTask().
    scoped_refptr<DecoderBuffer> buffer;
    // Number of bytes used so far from |buffer|.
    size_t bytes_used = 0;
    // The callback function passed to EnqueueDecodeTask().
    VideoDecoder::DecodeCB decode_cb;

    DecodeRequest(scoped_refptr<DecoderBuffer> buf, VideoDecoder::DecodeCB cb);

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

    // Allow move, but not copy
    DecodeRequest(DecodeRequest&&);
    DecodeRequest& operator=(DecodeRequest&&);

    ~DecodeRequest();

    bool IsCompleted() const;
  };

  bool IsSupportedProfile(VideoCodecProfile profile);

  void DoDecodeWork();

  static void ReuseOutputBufferThunk(
      scoped_refptr<base::SequencedTaskRunner> task_runner,
      std::optional<base::WeakPtr<V4L2StatefulVideoDecoderBackend>> weak_this,
      V4L2ReadableBufferRef buffer);
  void ReuseOutputBuffer(V4L2ReadableBufferRef buffer);

  // Called when the format has changed, in order to reallocate the output
  // buffers according to the new format.
  void ChangeResolution();
  // Called when the flush triggered by a resolution change has completed,
  // to actually apply the resolution.
  void ContinueChangeResolution(const gfx::Size& pic_size,
                                const gfx::Rect& visible_rect,
                                const size_t num_codec_reference_frames,
                                uint8_t bit_depth);

  // Enqueue all output buffers that are available.
  void EnqueueOutputBuffers();
  // When a video frame pool is in use, obtain a frame from the pool or, if
  // none is available, schedule |EnqueueOutputBuffers()| to be called when one
  // becomes available.
  scoped_refptr<FrameResource> GetPoolVideoFrame();

  bool SendStopCommand();
  bool InitiateFlush(VideoDecoder::DecodeCB flush_cb);
  bool CompleteFlush();

  void ScheduleDecodeWork();

  // Process all the event in the event queue
  void ProcessEventQueue();

  // The name of the running driver.
  const std::string driver_name_;

  // Video profile we are decoding.
  VideoCodecProfile profile_;

  // Video color space we are decoding.
  VideoColorSpace color_space_;

  // The task runner we are running on, for convenience.
  const scoped_refptr<base::SequencedTaskRunner> task_runner_;

  // VideoCodecProfiles supported by a v4l2 stateless decoder driver.
  std::vector<VideoCodecProfile> supported_profiles_;

  // Queue of pending decode request.
  base::queue<DecodeRequest> decode_request_queue_;

  // The decode request which is currently processed.
  std::optional<DecodeRequest> current_decode_request_;
  // V4L2 input buffer currently being prepared.
  std::optional<V4L2WritableBufferRef> current_input_buffer_;

  std::unique_ptr<v4l2_vda_helpers::InputBufferFragmentSplitter>
      frame_splitter_;

  std::optional<gfx::Rect> visible_rect_;

  // Map of enqueuing timecodes to system timestamp, for histogramming purposes.
  std::map<int64_t, base::TimeTicks> encoding_timestamps_;

  // Callback of the buffer that triggered a flush, to be called when the
  // flush completes.
  VideoDecoder::DecodeCB flush_cb_;
  // Closure that will be called once the flush triggered by a resolution change
  // event completes.
  base::OnceClosure resolution_change_cb_;

  // Whether there is any decoding request coming after
  // initialization/flush/reset is finished.
  // This flag is set on the first decode request, and reset after a successful
  // flush or reset.
  bool has_pending_requests_ = false;

  // The venus driver is the only implementation that requires the client
  // to inform the driver of the framerate.
  std::unique_ptr<V4L2FrameRateControl> framerate_control_;

  // If the resolution change is interrupted and aborted by reset, then V4L2
  // stateful API won't send the resolution change event again when the decoder
  // receives the input buffer with the same resolution after reset.
  // Set |need_resume_resolution_change_| to true in this scenario to resume the
  // resolution change after the reset is done.
  bool need_resume_resolution_change_ = false;

  base::WeakPtr<V4L2StatefulVideoDecoderBackend> weak_this_;
  base::WeakPtrFactory<V4L2StatefulVideoDecoderBackend> weak_this_factory_{
      this};
};

}  // namespace media

#endif  // MEDIA_GPU_V4L2_LEGACY_V4L2_VIDEO_DECODER_BACKEND_STATEFUL_H_