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
media / gpu / chromeos / vda_video_frame_pool.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_VDA_VIDEO_FRAME_POOL_H_
#define MEDIA_GPU_CHROMEOS_VDA_VIDEO_FRAME_POOL_H_
#include <optional>
#include "base/containers/queue.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "media/gpu/chromeos/chromeos_status.h"
#include "media/gpu/chromeos/dmabuf_video_frame_pool.h"
#include "media/gpu/chromeos/fourcc.h"
#include "media/gpu/chromeos/frame_resource.h"
namespace base {
class WaitableEvent;
}
namespace media {
class GpuBufferLayout;
// This class is used by VdVideoDecodeAccelerator, which adapts
// VideoDecodeAccelerator to VideoDecoder interface.
// The mission is to allocate and manage DMA-buf FrameResource by delegating the
// requests of buffer allocation to a VideoDecodeAccelerator instance, and
// provide FrameResource to the VideoDecoder instance.
// The communication with VdVideoDecodeAccelerator, which inherits
// VdaDelegate, is executed on |vda_task_runner_|, and the communication with
// VideoDecoder instance is on |parent_task_runner_|.
class VdaVideoFramePool : public DmabufVideoFramePool {
public:
class VdaDelegate {
public:
// Callback for returning the layout of requested buffer.
using NotifyLayoutChangedCb =
base::OnceCallback<void(CroStatus::Or<GpuBufferLayout>)>;
// Callback for importing available frames to this pool.
using ImportFrameCb =
base::RepeatingCallback<void(scoped_refptr<FrameResource>)>;
// Request new frames from VDA's client. VdaDelegate has to return the
// layout of frames by calling |notify_layout_changed_cb|.
// After that, VdaDelegate should pass frames by calling
// |import_frame_cb|.
// Note: RequestFrames(), |notify_layout_changed_cb|, and |import_frame_cb|
// should be called on VdaVideoFramePool's |vda_task_runner_|.
virtual 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) = 0;
virtual VideoFrame::StorageType GetFrameStorageType() const = 0;
};
VdaVideoFramePool(base::WeakPtr<VdaDelegate> vda,
scoped_refptr<base::SequencedTaskRunner> vda_task_runner);
~VdaVideoFramePool() override;
// DmabufVideoFramePool implementation.
CroStatus::Or<GpuBufferLayout> Initialize(const Fourcc& fourcc,
const gfx::Size& coded_size,
const gfx::Rect& visible_rect,
const gfx::Size& natural_size,
size_t max_num_frames,
bool use_protected,
bool use_linear_buffers) override;
scoped_refptr<FrameResource> GetFrame() override;
VideoFrame::StorageType GetFrameStorageType() const override;
bool IsExhausted() override;
void NotifyWhenFrameAvailable(base::OnceClosure cb) override;
void ReleaseAllFrames() override;
std::optional<GpuBufferLayout> GetGpuBufferLayout() override;
private:
// Update the layout of the buffers. |vda_| calls this as
// NotifyLayoutChangedCb.
static void OnRequestFramesDone(base::WaitableEvent* done,
CroStatus::Or<GpuBufferLayout>* layout,
CroStatus::Or<GpuBufferLayout> layout_value);
// Thunk to post ImportFrame() 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 ImportFrameThunk(
scoped_refptr<base::SequencedTaskRunner> task_runner,
std::optional<base::WeakPtr<VdaVideoFramePool>> weak_this,
scoped_refptr<FrameResource> frame);
// Import an available frame.
void ImportFrame(scoped_refptr<FrameResource> frame);
// Call |frame_available_cb_| when the pool is not exhausted.
void CallFrameAvailableCbIfNeeded();
// WeakPtr of VdaDelegate instance, bound at |vda_task_runner_|.
base::WeakPtr<VdaDelegate> vda_;
// Task runner that interacts with VdaDelegate. All VdaDelegate's methods
// and their callbacks should be called on this task runner.
// Note: DmabufVideoFrame's public methods like Initialize() and GetFrame()
// should be called on |parent_task_runner_|.
scoped_refptr<base::SequencedTaskRunner> vda_task_runner_;
// The storage type of frames imported by |vda_|. This is set at
// construction time by calling |vda_->GetFrameStorageType()|.
const VideoFrame::StorageType vda_frame_storage_type_;
// The callback which is called when the pool is not exhausted.
base::OnceClosure frame_available_cb_;
// The layout of the frames in |frame_pool_|.
std::optional<GpuBufferLayout> layout_;
// Data passed from Initialize().
size_t max_num_frames_ = 0;
std::optional<Fourcc> fourcc_;
gfx::Size coded_size_;
gfx::Rect visible_rect_;
gfx::Size natural_size_;
base::queue<scoped_refptr<FrameResource>> frame_pool_;
// Sequence checker for |parent_task_runner_|.
SEQUENCE_CHECKER(parent_sequence_checker_);
// The weak pointer of this, bound at |parent_task_runner_|.
base::WeakPtr<VdaVideoFramePool> weak_this_;
base::WeakPtrFactory<VdaVideoFramePool> weak_this_factory_{this};
};
} // namespace media
#endif // MEDIA_GPU_CHROMEOS_VDA_VIDEO_FRAME_POOL_H_