blob: fd806b7dc06d6cbf132e407b9af743ad8a3136c1 [file] [log] [blame]
Pawin Vongmasa36653902018-11-15 00:10:25 -08001/*
2 * Copyright 2017, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef CCODEC_BUFFER_CHANNEL_H_
18
19#define CCODEC_BUFFER_CHANNEL_H_
20
21#include <map>
22#include <memory>
23#include <vector>
24
25#include <C2Buffer.h>
26#include <C2Component.h>
27#include <Codec2Mapper.h>
28
29#include <codec2/hidl/client.h>
30#include <media/stagefright/bqhelper/GraphicBufferSource.h>
31#include <media/stagefright/codec2/1.0/InputSurface.h>
32#include <media/stagefright/foundation/Mutexed.h>
33#include <media/stagefright/CodecBase.h>
34#include <media/ICrypto.h>
35
36#include "InputSurfaceWrapper.h"
37
38namespace android {
39
Wonsik Kim078b58e2019-01-09 15:08:06 -080040class MemoryDealer;
41
Pawin Vongmasa36653902018-11-15 00:10:25 -080042class CCodecCallback {
43public:
44 virtual ~CCodecCallback() = default;
45 virtual void onError(status_t err, enum ActionCode actionCode) = 0;
46 virtual void onOutputFramesRendered(int64_t mediaTimeUs, nsecs_t renderTimeNs) = 0;
47 virtual void onWorkQueued(bool eos) = 0;
48 virtual void onOutputBuffersChanged() = 0;
49};
50
51/**
52 * BufferChannelBase implementation for CCodec.
53 */
54class CCodecBufferChannel
55 : public BufferChannelBase, public std::enable_shared_from_this<CCodecBufferChannel> {
56public:
57 explicit CCodecBufferChannel(const std::shared_ptr<CCodecCallback> &callback);
58 virtual ~CCodecBufferChannel();
59
60 // BufferChannelBase interface
61 virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override;
62 virtual status_t queueSecureInputBuffer(
63 const sp<MediaCodecBuffer> &buffer,
64 bool secure,
65 const uint8_t *key,
66 const uint8_t *iv,
67 CryptoPlugin::Mode mode,
68 CryptoPlugin::Pattern pattern,
69 const CryptoPlugin::SubSample *subSamples,
70 size_t numSubSamples,
71 AString *errorDetailMsg) override;
72 virtual status_t renderOutputBuffer(
73 const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override;
74 virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override;
75 virtual void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
76 virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override;
77
78 // Methods below are interface for CCodec to use.
79
80 /**
81 * Set the component object for buffer processing.
82 */
83 void setComponent(const std::shared_ptr<Codec2Client::Component> &component);
84
85 /**
86 * Set output graphic surface for rendering.
87 */
88 status_t setSurface(const sp<Surface> &surface);
89
90 /**
91 * Set GraphicBufferSource object from which the component extracts input
92 * buffers.
93 */
94 status_t setInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface);
95
96 /**
97 * Signal EOS to input surface.
98 */
99 status_t signalEndOfInputStream();
100
101 /**
102 * Set parameters.
103 */
104 status_t setParameters(std::vector<std::unique_ptr<C2Param>> &params);
105
106 /**
107 * Start queueing buffers to the component. This object should never queue
108 * buffers before this call has completed.
109 */
110 status_t start(const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat);
111
112 /**
113 * Request initial input buffers to be filled by client.
114 */
115 status_t requestInitialInputBuffers();
116
117 /**
118 * Stop queueing buffers to the component. This object should never queue
119 * buffers after this call, until start() is called.
120 */
121 void stop();
122
123 void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork);
124
125 /**
126 * Notify input client about work done.
127 *
128 * @param workItems finished work item.
129 * @param outputFormat new output format if it has changed, otherwise nullptr
130 * @param initData new init data (CSD) if it has changed, otherwise nullptr
131 * @param numDiscardedInputBuffers the number of input buffers that are
132 * returned for the first time (not previously returned by
133 * onInputBufferDone()).
134 */
135 void onWorkDone(
136 std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat,
137 const C2StreamInitDataInfo::output *initData,
138 size_t numDiscardedInputBuffers);
139
140 /**
141 * Make an input buffer available for the client as it is no longer needed
142 * by the codec.
143 *
144 * @param buffer The buffer that becomes unused.
145 */
146 void onInputBufferDone(const std::shared_ptr<C2Buffer>& buffer);
147
148 enum MetaMode {
149 MODE_NONE,
150 MODE_ANW,
151 };
152
153 void setMetaMode(MetaMode mode);
154
155 // Internal classes
156 class Buffers;
157 class InputBuffers;
158 class OutputBuffers;
159
160private:
161 class QueueGuard;
162
163 /**
164 * Special mutex-like object with the following properties:
165 *
166 * - At STOPPED state (initial, or after stop())
167 * - QueueGuard object gets created at STOPPED state, and the client is
168 * supposed to return immediately.
169 * - At RUNNING state (after start())
170 * - Each QueueGuard object
171 */
172 class QueueSync {
173 public:
174 /**
175 * At construction the sync object is in STOPPED state.
176 */
177 inline QueueSync() {}
178 ~QueueSync() = default;
179
180 /**
181 * Transition to RUNNING state when stopped. No-op if already in RUNNING
182 * state.
183 */
184 void start();
185
186 /**
187 * At RUNNING state, wait until all QueueGuard object created during
188 * RUNNING state are destroyed, and then transition to STOPPED state.
189 * No-op if already in STOPPED state.
190 */
191 void stop();
192
193 private:
194 Mutex mGuardLock;
195
196 struct Counter {
197 inline Counter() : value(-1) {}
198 int32_t value;
199 Condition cond;
200 };
201 Mutexed<Counter> mCount;
202
203 friend class CCodecBufferChannel::QueueGuard;
204 };
205
206 class QueueGuard {
207 public:
208 QueueGuard(QueueSync &sync);
209 ~QueueGuard();
210 inline bool isRunning() { return mRunning; }
211
212 private:
213 QueueSync &mSync;
214 bool mRunning;
215 };
216
217 void feedInputBufferIfAvailable();
218 void feedInputBufferIfAvailableInternal();
219 status_t queueInputBufferInternal(const sp<MediaCodecBuffer> &buffer);
220 bool handleWork(
221 std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat,
222 const C2StreamInitDataInfo::output *initData);
223 void sendOutputBuffers();
224
225 QueueSync mSync;
226 sp<MemoryDealer> mDealer;
227 sp<IMemory> mDecryptDestination;
228 int32_t mHeapSeqNum;
229
230 std::shared_ptr<Codec2Client::Component> mComponent;
231 std::string mComponentName; ///< component name for debugging
232 const char *mName; ///< C-string version of component name
233 std::shared_ptr<CCodecCallback> mCCodecCallback;
234 std::shared_ptr<C2BlockPool> mInputAllocator;
235 QueueSync mQueueSync;
236 std::vector<std::unique_ptr<C2Param>> mParamsToBeSet;
237
Wonsik Kim078b58e2019-01-09 15:08:06 -0800238 size_t mNumInputSlots;
239 size_t mNumOutputSlots;
240
Pawin Vongmasa36653902018-11-15 00:10:25 -0800241 Mutexed<std::unique_ptr<InputBuffers>> mInputBuffers;
242 Mutexed<std::list<sp<ABuffer>>> mFlushedConfigs;
243 Mutexed<std::unique_ptr<OutputBuffers>> mOutputBuffers;
244
245 std::atomic_uint64_t mFrameIndex;
246 std::atomic_uint64_t mFirstValidFrameIndex;
247
248 sp<MemoryDealer> makeMemoryDealer(size_t heapSize);
249
250 struct OutputSurface {
251 sp<Surface> surface;
252 uint32_t generation;
253 };
254 Mutexed<OutputSurface> mOutputSurface;
255
256 struct BlockPools {
257 C2Allocator::id_t inputAllocatorId;
258 std::shared_ptr<C2BlockPool> inputPool;
259 C2Allocator::id_t outputAllocatorId;
260 C2BlockPool::local_id_t outputPoolId;
261 std::shared_ptr<Codec2Client::Configurable> outputPoolIntf;
262 };
263 Mutexed<BlockPools> mBlockPools;
264
265 std::shared_ptr<InputSurfaceWrapper> mInputSurface;
266
267 MetaMode mMetaMode;
268
269 // PipelineCapacity is used in the input buffer gating logic.
270 //
271 // There are three criteria that need to be met before
272 // onInputBufferAvailable() is called:
273 // 1. The number of input buffers that have been received by
274 // CCodecBufferChannel but not returned via onWorkDone() or
275 // onInputBufferDone() does not exceed a certain limit. (Let us call this
276 // number the "input" capacity.)
277 // 2. The number of work items that have been received by
278 // CCodecBufferChannel whose outputs have not been returned from the
279 // component (by calling onWorkDone()) does not exceed a certain limit.
280 // (Let us call this the "component" capacity.)
281 //
282 // These three criteria guarantee that a new input buffer that arrives from
283 // the invocation of onInputBufferAvailable() will not
284 // 1. overload CCodecBufferChannel's input buffers;
285 // 2. overload the component; or
286 //
287 struct PipelineCapacity {
288 // The number of available input capacity.
289 std::atomic_int input;
290 // The number of available component capacity.
291 std::atomic_int component;
292
293 PipelineCapacity();
294 // Set the values of #input and #component.
295 void initialize(int newInput, int newComponent,
296 const char* newName = "<UNKNOWN COMPONENT>",
297 const char* callerTag = nullptr);
298
299 // Return true and decrease #input and #component by one if
300 // they are all greater than zero; return false otherwise.
301 //
302 // callerTag is used for logging only.
303 //
304 // allocate() is called by CCodecBufferChannel to check whether it can
305 // receive another input buffer. If the return value is true,
306 // onInputBufferAvailable() and onOutputBufferAvailable() can be called
307 // afterwards.
308 bool allocate(const char* callerTag = nullptr);
309
310 // Increase #input and #component by one.
311 //
312 // callerTag is used for logging only.
313 //
314 // free() is called by CCodecBufferChannel after allocate() returns true
315 // but onInputBufferAvailable() cannot be called for any reasons. It
316 // essentially undoes an allocate() call.
317 void free(const char* callerTag = nullptr);
318
319 // Increase #input by @p numDiscardedInputBuffers.
320 //
321 // callerTag is used for logging only.
322 //
323 // freeInputSlots() is called by CCodecBufferChannel when onWorkDone()
324 // or onInputBufferDone() is called. @p numDiscardedInputBuffers is
325 // provided in onWorkDone(), and is 1 in onInputBufferDone().
326 int freeInputSlots(size_t numDiscardedInputBuffers,
327 const char* callerTag = nullptr);
328
329 // Increase #component by one and return the updated value.
330 //
331 // callerTag is used for logging only.
332 //
333 // freeComponentSlot() is called by CCodecBufferChannel when
334 // onWorkDone() is called.
335 int freeComponentSlot(const char* callerTag = nullptr);
336
337 private:
338 // Component name. Used for logging.
339 const char* mName;
340 };
341 PipelineCapacity mAvailablePipelineCapacity;
342
343 class ReorderStash {
344 public:
345 struct Entry {
346 inline Entry() : buffer(nullptr), timestamp(0), flags(0), ordinal({0, 0, 0}) {}
347 inline Entry(
348 const std::shared_ptr<C2Buffer> &b,
349 int64_t t,
350 int32_t f,
351 const C2WorkOrdinalStruct &o)
352 : buffer(b), timestamp(t), flags(f), ordinal(o) {}
353 std::shared_ptr<C2Buffer> buffer;
354 int64_t timestamp;
355 int32_t flags;
356 C2WorkOrdinalStruct ordinal;
357 };
358
359 ReorderStash();
360
361 void clear();
362 void setDepth(uint32_t depth);
363 void setKey(C2Config::ordinal_key_t key);
364 bool pop(Entry *entry);
365 void emplace(
366 const std::shared_ptr<C2Buffer> &buffer,
367 int64_t timestamp,
368 int32_t flags,
369 const C2WorkOrdinalStruct &ordinal);
370 void defer(const Entry &entry);
371 bool hasPending() const;
372
373 private:
374 std::list<Entry> mPending;
375 std::list<Entry> mStash;
376 uint32_t mDepth;
377 C2Config::ordinal_key_t mKey;
378
379 bool less(const C2WorkOrdinalStruct &o1, const C2WorkOrdinalStruct &o2);
380 };
381 Mutexed<ReorderStash> mReorderStash;
382
383 std::atomic_bool mInputMetEos;
384
385 inline bool hasCryptoOrDescrambler() {
386 return mCrypto != nullptr || mDescrambler != nullptr;
387 }
388};
389
390// Conversion of a c2_status_t value to a status_t value may depend on the
391// operation that returns the c2_status_t value.
392enum c2_operation_t {
393 C2_OPERATION_NONE,
394 C2_OPERATION_Component_connectToOmxInputSurface,
395 C2_OPERATION_Component_createBlockPool,
396 C2_OPERATION_Component_destroyBlockPool,
397 C2_OPERATION_Component_disconnectFromInputSurface,
398 C2_OPERATION_Component_drain,
399 C2_OPERATION_Component_flush,
400 C2_OPERATION_Component_queue,
401 C2_OPERATION_Component_release,
402 C2_OPERATION_Component_reset,
403 C2_OPERATION_Component_setOutputSurface,
404 C2_OPERATION_Component_start,
405 C2_OPERATION_Component_stop,
406 C2_OPERATION_ComponentStore_copyBuffer,
407 C2_OPERATION_ComponentStore_createComponent,
408 C2_OPERATION_ComponentStore_createInputSurface,
409 C2_OPERATION_ComponentStore_createInterface,
410 C2_OPERATION_Configurable_config,
411 C2_OPERATION_Configurable_query,
412 C2_OPERATION_Configurable_querySupportedParams,
413 C2_OPERATION_Configurable_querySupportedValues,
414 C2_OPERATION_InputSurface_connectToComponent,
415 C2_OPERATION_InputSurfaceConnection_disconnect,
416};
417
418status_t toStatusT(c2_status_t c2s, c2_operation_t c2op = C2_OPERATION_NONE);
419
420} // namespace android
421
422#endif // CCODEC_BUFFER_CHANNEL_H_