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
media / gpu / chromeos / vd_video_decode_accelerator.h [blame]
// 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_CHROMEOS_VD_VIDEO_DECODE_ACCELERATOR_H_
#define MEDIA_GPU_CHROMEOS_VD_VIDEO_DECODE_ACCELERATOR_H_
#include <map>
#include <memory>
#include <optional>
#include "base/functional/callback_forward.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "base/thread_annotations.h"
#include "base/unguessable_token.h"
#include "build/chromeos_buildflags.h"
#include "media/base/status.h"
#include "media/base/video_decoder.h"
#include "media/gpu/chromeos/dmabuf_video_frame_pool.h"
#include "media/gpu/chromeos/fourcc.h"
#include "media/gpu/chromeos/platform_video_frame_utils.h"
#include "media/gpu/chromeos/vda_video_frame_pool.h"
#include "media/gpu/chromeos/video_decoder_pipeline.h"
#include "media/gpu/media_gpu_export.h"
#include "media/mojo/mojom/stable/stable_video_decoder.mojom.h"
#include "media/video/video_decode_accelerator.h"
#include "ui/gfx/gpu_memory_buffer.h"
namespace media {
class FrameResource;
// Implements the VideoDecodeAccelerator backed by a VideoDecoder.
// Currently GpuArcVideoDecodeAccelerator bridges the video codec from
// ARC++ to a VDA instance. We plan to deprecate to VDA implementation at
// chromium by new VD implementation. So we need the adapter between
// these two interface.
//
// Important note: This adaptor is only used temporary as an intermediate step
// while the GpuArcVideoDecodeAccelerator is being ported to the new VD
// interface. This Adaptor will be deprecated soon and should not be used
// anywhere else.
class MEDIA_GPU_EXPORT VdVideoDecodeAccelerator
: public VideoDecodeAccelerator,
public VdaVideoFramePool::VdaDelegate {
public:
// Callback for creating VideoDecoder instance.
using CreateVideoDecoderCb =
base::RepeatingCallback<decltype(VideoDecoderPipeline::CreateForARC)>;
// Create VdVideoDecodeAccelerator instance, and call Initialize().
// Return nullptr if Initialize() failed.
static std::unique_ptr<VideoDecodeAccelerator> Create(
CreateVideoDecoderCb create_vd_cb,
Client* client,
const Config& config,
scoped_refptr<base::SequencedTaskRunner> task_runner);
VdVideoDecodeAccelerator(const VdVideoDecodeAccelerator&) = delete;
VdVideoDecodeAccelerator& operator=(const VdVideoDecodeAccelerator&) = delete;
~VdVideoDecodeAccelerator() override;
// Initializer to set the |low_delay| pipeline.
bool Initialize(const Config& config, Client* client, bool low_delay);
// Implementation of VideoDecodeAccelerator.
bool Initialize(const Config& config, Client* client) override;
void AssignPictureBuffers(const std::vector<PictureBuffer>& buffers) override;
void ImportBufferForPicture(
int32_t picture_buffer_id,
VideoPixelFormat pixel_format,
gfx::GpuMemoryBufferHandle gpu_memory_buffer_handle) override;
void ReusePictureBuffer(int32_t picture_buffer_id) override;
void Decode(BitstreamBuffer bitstream_buffer) override;
void Decode(scoped_refptr<DecoderBuffer> buffer,
int32_t bitstream_id) override;
void Flush() override;
void Reset() override;
void Destroy() override;
// Implementation of VdaVideoFramePool::VdaDelegate.
void RequestFrames(const Fourcc& fourcc,
const gfx::Size& coded_size,
const gfx::Rect& visible_rect,
size_t max_num_frames,
NotifyLayoutChangedCb notify_layout_changed_cb,
ImportFrameCb import_frame_cb) override;
VideoFrame::StorageType GetFrameStorageType() const override;
private:
VdVideoDecodeAccelerator(
CreateVideoDecoderCb create_vd_cb,
scoped_refptr<base::SequencedTaskRunner> task_runner);
// Callback methods of |vd_|.
void OnInitializeDone(DecoderStatus status);
void OnDecodeDone(int32_t bitstream_buffer_id, DecoderStatus status);
void OnFrameReady(scoped_refptr<VideoFrame> frame);
void OnFlushDone(DecoderStatus status);
void OnResetDone();
// Get Picture instance that represents the same buffer as |frame|. Return
// std::nullopt if the buffer is already dismissed.
std::optional<Picture> GetPicture(const VideoFrame& frame);
// Thunk to post OnFrameReleased() to |task_runner|.
// Because this thunk may be called in any thread, We don't want to
// dereference WeakPtr. Therefore we wrap the WeakPtr by std::optional to
// avoid the task runner defererencing the WeakPtr.
static void OnFrameReleasedThunk(
std::optional<base::WeakPtr<VdVideoDecodeAccelerator>> weak_this,
scoped_refptr<base::SequencedTaskRunner> task_runner,
scoped_refptr<FrameResource> origin_frame);
// Called when a frame gets destroyed.
void OnFrameReleased(scoped_refptr<FrameResource> origin_frame);
// Called when any error occurs. Notify |client_| an error occurred.
void OnError(base::Location location, Error error);
// Callback to generate VideoDecoder.
CreateVideoDecoderCb create_vd_cb_;
// The client of this VDA.
raw_ptr<VideoDecodeAccelerator::Client> client_ = nullptr;
// The delegated VideoDecoder instance.
std::unique_ptr<VideoDecoder> vd_;
// Callback for returning the result after this instance is asked to request
// new frames. The VdaVideoFramePool is blocked until this callback is called.
NotifyLayoutChangedCb notify_layout_changed_cb_
GUARDED_BY_CONTEXT(client_sequence_checker_);
// Callback for passing the available frames to the pool.
ImportFrameCb import_frame_cb_ GUARDED_BY_CONTEXT(client_sequence_checker_);
// Set to true when |vd_| is resetting.
bool is_resetting_ GUARDED_BY_CONTEXT(client_sequence_checker_) = false;
// The size requested from VdaVideoFramePool.
gfx::Size pending_coded_size_;
// The formats of the current buffers.
gfx::Size coded_size_;
std::optional<VideoFrameLayout> layout_;
// Used to guarantee that frames are produced with unique tracking tokens.
media::UniqueTrackingTokenHelper frame_tracking_token_helper_;
// Mapping from a frame's UnguessableToken to picture buffer id.
std::map<base::UnguessableToken, int32_t /* picture_buffer_id */>
frame_token_to_picture_id_;
// Record how many times the picture is sent to the client, and keep a refptr
// of corresponding VideoFrame when the client owns the buffers.
std::map<int32_t /* picture_buffer_id */,
std::pair<scoped_refptr<VideoFrame>, size_t /* num_sent */>>
picture_at_client_;
#if BUILDFLAG(IS_CHROMEOS_ASH)
// Indicates we are handling encrypted content which requires an extra check
// to see if it is a secure buffer format.
bool is_encrypted_ = false;
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
// Value of |low_delay| from the most recent initialization (via either Create
// or Initialize(const Config&, Client*, bool). When re-initialization happens
// via the VideoDecodeAccelerator interface (where we cannot pass
// |low_delay|), we use this value.
bool low_delay_ = false;
// Main task runner and its sequence checker. All methods should be called
// on it.
scoped_refptr<base::SequencedTaskRunner> client_task_runner_;
SEQUENCE_CHECKER(client_sequence_checker_);
// The weak pointer of this class instance, bound to |client_task_runner_|.
base::WeakPtr<VdVideoDecodeAccelerator> weak_this_;
base::WeakPtrFactory<VdVideoDecodeAccelerator> weak_this_factory_{this};
};
} // namespace media
#endif // MEDIA_GPU_CHROMEOS_VD_VIDEO_DECODE_ACCELERATOR_H_