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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
|
/*
* Copyright 2017, The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef CCODEC_BUFFER_CHANNEL_H_
#define CCODEC_BUFFER_CHANNEL_H_
#include <map>
#include <memory>
#include <vector>
#include <C2Buffer.h>
#include <C2Component.h>
#include <Codec2Mapper.h>
#include <codec2/hidl/client.h>
#include <media/stagefright/foundation/Mutexed.h>
#include <media/stagefright/CodecBase.h>
#include "CCodecBuffers.h"
#include "InputSurfaceWrapper.h"
#include "PipelineWatcher.h"
namespace android {
class MemoryDealer;
class CCodecCallback {
public:
virtual ~CCodecCallback() = default;
virtual void onError(status_t err, enum ActionCode actionCode) = 0;
virtual void onOutputFramesRendered(int64_t mediaTimeUs, nsecs_t renderTimeNs) = 0;
virtual void onOutputBuffersChanged() = 0;
};
/**
* BufferChannelBase implementation for CCodec.
*/
class CCodecBufferChannel
: public BufferChannelBase, public std::enable_shared_from_this<CCodecBufferChannel> {
public:
explicit CCodecBufferChannel(const std::shared_ptr<CCodecCallback> &callback);
virtual ~CCodecBufferChannel();
// BufferChannelBase interface
void setCrypto(const sp<ICrypto> &crypto) override;
void setDescrambler(const sp<IDescrambler> &descrambler) override;
virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
virtual status_t queueSecureInputBuffer(
const sp<MediaCodecBuffer> &buffer,
bool secure,
const uint8_t *key,
const uint8_t *iv,
CryptoPlugin::Mode mode,
CryptoPlugin::Pattern pattern,
const CryptoPlugin::SubSample *subSamples,
size_t numSubSamples,
AString *errorDetailMsg) override;
virtual status_t attachBuffer(
const std::shared_ptr<C2Buffer> &c2Buffer,
const sp<MediaCodecBuffer> &buffer) override;
virtual status_t attachEncryptedBuffer(
const sp<hardware::HidlMemory> &memory,
bool secure,
const uint8_t *key,
const uint8_t *iv,
CryptoPlugin::Mode mode,
CryptoPlugin::Pattern pattern,
size_t offset,
const CryptoPlugin::SubSample *subSamples,
size_t numSubSamples,
const sp<MediaCodecBuffer> &buffer) override;
virtual status_t renderOutputBuffer(
const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
virtual void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
// Methods below are interface for CCodec to use.
/**
* Set the component object for buffer processing.
*/
void setComponent(const std::shared_ptr<Codec2Client::Component> &component);
/**
* Set output graphic surface for rendering.
*/
status_t setSurface(const sp<Surface> &surface);
/**
* Set GraphicBufferSource object from which the component extracts input
* buffers.
*/
status_t setInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface);
/**
* Signal EOS to input surface.
*/
status_t signalEndOfInputStream();
/**
* Set parameters.
*/
status_t setParameters(std::vector<std::unique_ptr<C2Param>> ¶ms);
/**
* Start queueing buffers to the component. This object should never queue
* buffers before this call has completed.
*/
status_t start(
const sp<AMessage> &inputFormat,
const sp<AMessage> &outputFormat,
bool buffersBoundToCodec);
/**
* Request initial input buffers to be filled by client.
*/
status_t requestInitialInputBuffers();
/**
* Stop queueing buffers to the component. This object should never queue
* buffers after this call, until start() is called.
*/
void stop();
/**
* Stop queueing buffers to the component and release all buffers.
*/
void reset();
/**
* Release all resources.
*/
void release();
void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork);
/**
* Notify input client about work done.
*
* @param workItems finished work item.
* @param outputFormat new output format if it has changed, otherwise nullptr
* @param initData new init data (CSD) if it has changed, otherwise nullptr
*/
void onWorkDone(
std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat,
const C2StreamInitDataInfo::output *initData);
/**
* Make an input buffer available for the client as it is no longer needed
* by the codec.
*
* @param frameIndex The index of input work
* @param arrayIndex The index of buffer in the input work buffers.
*/
void onInputBufferDone(uint64_t frameIndex, size_t arrayIndex);
PipelineWatcher::Clock::duration elapsed();
enum MetaMode {
MODE_NONE,
MODE_ANW,
};
void setMetaMode(MetaMode mode);
private:
class QueueGuard;
/**
* Special mutex-like object with the following properties:
*
* - At STOPPED state (initial, or after stop())
* - QueueGuard object gets created at STOPPED state, and the client is
* supposed to return immediately.
* - At RUNNING state (after start())
* - Each QueueGuard object
*/
class QueueSync {
public:
/**
* At construction the sync object is in STOPPED state.
*/
inline QueueSync() {}
~QueueSync() = default;
/**
* Transition to RUNNING state when stopped. No-op if already in RUNNING
* state.
*/
void start();
/**
* At RUNNING state, wait until all QueueGuard object created during
* RUNNING state are destroyed, and then transition to STOPPED state.
* No-op if already in STOPPED state.
*/
void stop();
private:
Mutex mGuardLock;
struct Counter {
inline Counter() : value(-1) {}
int32_t value;
Condition cond;
};
Mutexed<Counter> mCount;
friend class CCodecBufferChannel::QueueGuard;
};
class QueueGuard {
public:
QueueGuard(QueueSync &sync);
~QueueGuard();
inline bool isRunning() { return mRunning; }
private:
QueueSync &mSync;
bool mRunning;
};
void feedInputBufferIfAvailable();
void feedInputBufferIfAvailableInternal();
status_t queueInputBufferInternal(sp<MediaCodecBuffer> buffer);
bool handleWork(
std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat,
const C2StreamInitDataInfo::output *initData);
void sendOutputBuffers();
void ensureDecryptDestination(size_t size);
int32_t getHeapSeqNum(const sp<hardware::HidlMemory> &memory);
QueueSync mSync;
sp<MemoryDealer> mDealer;
sp<IMemory> mDecryptDestination;
int32_t mHeapSeqNum;
std::map<wp<hardware::HidlMemory>, int32_t> mHeapSeqNumMap;
std::shared_ptr<Codec2Client::Component> mComponent;
std::string mComponentName; ///< component name for debugging
const char *mName; ///< C-string version of component name
std::shared_ptr<CCodecCallback> mCCodecCallback;
std::shared_ptr<C2BlockPool> mInputAllocator;
QueueSync mQueueSync;
std::vector<std::unique_ptr<C2Param>> mParamsToBeSet;
struct Input {
Input();
std::unique_ptr<InputBuffers> buffers;
size_t numSlots;
FlexBuffersImpl extraBuffers;
size_t numExtraSlots;
uint32_t inputDelay;
uint32_t pipelineDelay;
};
Mutexed<Input> mInput;
struct Output {
std::unique_ptr<OutputBuffers> buffers;
size_t numSlots;
uint32_t outputDelay;
};
Mutexed<Output> mOutput;
Mutexed<std::list<sp<ABuffer>>> mFlushedConfigs;
std::atomic_uint64_t mFrameIndex;
std::atomic_uint64_t mFirstValidFrameIndex;
sp<MemoryDealer> makeMemoryDealer(size_t heapSize);
struct OutputSurface {
sp<Surface> surface;
uint32_t generation;
int maxDequeueBuffers;
};
Mutexed<OutputSurface> mOutputSurface;
struct BlockPools {
C2Allocator::id_t inputAllocatorId;
std::shared_ptr<C2BlockPool> inputPool;
C2Allocator::id_t outputAllocatorId;
C2BlockPool::local_id_t outputPoolId;
std::shared_ptr<Codec2Client::Configurable> outputPoolIntf;
};
Mutexed<BlockPools> mBlockPools;
std::shared_ptr<InputSurfaceWrapper> mInputSurface;
MetaMode mMetaMode;
Mutexed<PipelineWatcher> mPipelineWatcher;
std::atomic_bool mInputMetEos;
std::once_flag mRenderWarningFlag;
sp<ICrypto> mCrypto;
sp<IDescrambler> mDescrambler;
inline bool hasCryptoOrDescrambler() {
return mCrypto != nullptr || mDescrambler != nullptr;
}
};
// Conversion of a c2_status_t value to a status_t value may depend on the
// operation that returns the c2_status_t value.
enum c2_operation_t {
C2_OPERATION_NONE,
C2_OPERATION_Component_connectToOmxInputSurface,
C2_OPERATION_Component_createBlockPool,
C2_OPERATION_Component_destroyBlockPool,
C2_OPERATION_Component_disconnectFromInputSurface,
C2_OPERATION_Component_drain,
C2_OPERATION_Component_flush,
C2_OPERATION_Component_queue,
C2_OPERATION_Component_release,
C2_OPERATION_Component_reset,
C2_OPERATION_Component_setOutputSurface,
C2_OPERATION_Component_start,
C2_OPERATION_Component_stop,
C2_OPERATION_ComponentStore_copyBuffer,
C2_OPERATION_ComponentStore_createComponent,
C2_OPERATION_ComponentStore_createInputSurface,
C2_OPERATION_ComponentStore_createInterface,
C2_OPERATION_Configurable_config,
C2_OPERATION_Configurable_query,
C2_OPERATION_Configurable_querySupportedParams,
C2_OPERATION_Configurable_querySupportedValues,
C2_OPERATION_InputSurface_connectToComponent,
C2_OPERATION_InputSurfaceConnection_disconnect,
};
status_t toStatusT(c2_status_t c2s, c2_operation_t c2op = C2_OPERATION_NONE);
} // namespace android
#endif // CCODEC_BUFFER_CHANNEL_H_
|