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
ash / components / arc / video_accelerator / gpu_arc_video_decoder.h [blame]
// 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 ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODER_H_
#define ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODER_H_
#include <map>
#include <memory>
#include <optional>
#include <queue>
#include "ash/components/arc/mojom/video_decoder.mojom.h"
#include "base/functional/callback_forward.h"
#include "base/memory/weak_ptr.h"
#include "base/sequence_checker.h"
#include "base/task/sequenced_task_runner.h"
#include "media/base/decoder_buffer.h"
#include "media/base/video_decoder.h"
#include "media/gpu/chromeos/vda_video_frame_pool.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
namespace arc {
class GpuArcVideoFramePool;
class ProtectedBufferManager;
// The GpuArcVideoDecoder listens to mojo IPC requests and forwards these to an
// instance of media::VideoDecoder. Decoded frames are passed back to the mojo
// client.
class GpuArcVideoDecoder : public mojom::VideoDecoder {
public:
GpuArcVideoDecoder(
scoped_refptr<ProtectedBufferManager> protected_buffer_manager);
~GpuArcVideoDecoder() override;
GpuArcVideoDecoder(const GpuArcVideoDecoder&) = delete;
GpuArcVideoDecoder& operator=(const GpuArcVideoDecoder&) = delete;
GpuArcVideoDecoder(GpuArcVideoDecoder&&) = delete;
GpuArcVideoDecoder& operator=(GpuArcVideoDecoder&&) = delete;
// Implementation of mojom::VideoDecoder.
void Initialize(
arc::mojom::VideoDecoderConfigPtr config,
mojo::PendingRemote<mojom::VideoDecoderClient> client,
mojo::PendingAssociatedReceiver<mojom::VideoFramePool> video_frame_pool,
InitializeCallback callback) override;
void Decode(arc::mojom::DecoderBufferPtr buffer,
DecodeCallback callback) override;
void Reset(ResetCallback callback) override;
void ReleaseVideoFrame(int32_t video_frame_id) override;
private:
using Request = base::OnceClosure;
// Called by the decoder when initialization is done.
void OnInitializeDone(media::DecoderStatus status);
// Called by the decoder when the specified buffer has been decoded.
void OnDecodeDone(DecodeCallback callback, media::DecoderStatus status);
// Called by the decoder when a decoded frame is ready.
void OnFrameReady(scoped_refptr<media::VideoFrame> frame);
// Called by the decoder when a reset has been completed.
void OnResetDone();
// Called by the video frame pool to notify us that the pool won't be tracking
// the current set of the video frames so we should release references to
// them. This can indicate that new frames will be soon added to the pool
// using the same IDs.
void ReleaseClientVideoFrames();
// Called when an error occurred.
void OnError(media::DecoderStatus status);
// Handle all requests that are currently in the |requests_| queue.
void HandleRequests();
// Handle the specified request. If the decoder is currently resetting the
// request will be queued and handled once OnResetDone() is called.
void HandleRequest(Request request);
// Handle a decode request of the specified |buffer|.
void HandleDecodeRequest(scoped_refptr<media::DecoderBuffer> buffer,
DecodeCallback callback);
// Handle a reset request with specified |callback|. All ongoing flush
// operations will be reported as canceled.
void HandleResetRequest(ResetCallback callback);
// Create a decoder buffer from the specified |fd|.
scoped_refptr<media::DecoderBuffer> CreateDecoderBuffer(base::ScopedFD fd,
uint32_t offset,
uint32_t bytes_used);
// The number of currently active instances. Always accessed on the same
// thread, so we don't need to use a lock.
static size_t num_instances_;
// Whether the video decoder encountered an error and is aborting.
bool error_state_ = false;
// The remote mojo client.
mojo::Remote<mojom::VideoDecoderClient> client_;
// The local video decoder.
std::unique_ptr<media::VideoDecoder> decoder_;
// The video frame pool service.
std::unique_ptr<GpuArcVideoFramePool> video_frame_pool_;
// Initialization callback, used while the decoder is being initialized.
InitializeCallback init_callback_;
// The callback associated with the ongoing reset request if any.
ResetCallback reset_callback_;
// Requests currently waiting until resetting the decoder has completed.
std::queue<Request> requests_;
// The video frames currently in use by the client and their associated
// video frame ids. We need to hold references to video frames to prevent
// them from being returned to the video frame pool for reuse while they are
// still in use by our client. The use count is tracked as the same frame
// might be sent multiple times to the client when using the VP9
// 'show_existing_frame' feature.
std::map<int32_t, std::pair<scoped_refptr<media::VideoFrame>, size_t>>
client_video_frames_;
// The protected buffer manager, used when decoding an encrypted video.
scoped_refptr<ProtectedBufferManager> protected_buffer_manager_;
// Whether we're decoding an encrypted video.
std::optional<bool> secure_mode_;
// The client task runner and its sequence checker. All methods should be run
// on this task runner.
scoped_refptr<base::SequencedTaskRunner> client_task_runner_;
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtr<GpuArcVideoDecoder> weak_this_;
base::WeakPtrFactory<GpuArcVideoDecoder> weak_this_factory_{this};
};
} // namespace arc
#endif // ASH_COMPONENTS_ARC_VIDEO_ACCELERATOR_GPU_ARC_VIDEO_DECODER_H_