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