1 /*
2  * Copyright 2019, 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_BUFFERS_H_
18 
19 #define CCODEC_BUFFERS_H_
20 
21 #include <string>
22 
23 #include <C2Config.h>
24 #include <media/stagefright/foundation/AMessage.h>
25 #include <media/MediaCodecBuffer.h>
26 
27 #include "Codec2Buffer.h"
28 
29 namespace android {
30 
31 struct ICrypto;
32 class MemoryDealer;
33 class SkipCutBuffer;
34 
35 constexpr size_t kLinearBufferSize = 1048576;
36 // This can fit 4K RGBA frame, and most likely client won't need more than this.
37 constexpr size_t kMaxLinearBufferSize = 4096 * 2304 * 4;
38 
39 /**
40  * Base class for representation of buffers at one port.
41  */
42 class CCodecBuffers {
43 public:
44     CCodecBuffers(const char *componentName, const char *name = "Buffers")
mComponentName(componentName)45         : mComponentName(componentName),
46           mChannelName(std::string(componentName) + ":" + name),
47           mName(mChannelName.c_str()) {
48     }
49     virtual ~CCodecBuffers() = default;
50 
51     /**
52      * Set format for MediaCodec-facing buffers.
53      */
54     void setFormat(const sp<AMessage> &format);
55 
56     /**
57      * Return a copy of current format.
58      */
59     sp<AMessage> dupFormat();
60 
61     /**
62      * Returns true if the buffers are operating under array mode.
63      */
isArrayMode()64     virtual bool isArrayMode() const { return false; }
65 
66     /**
67      * Fills the vector with MediaCodecBuffer's if in array mode; otherwise,
68      * no-op.
69      */
getArray(Vector<sp<MediaCodecBuffer>> *)70     virtual void getArray(Vector<sp<MediaCodecBuffer>> *) const {}
71 
72     /**
73      * Return number of buffers the client owns.
74      */
75     virtual size_t numClientBuffers() const = 0;
76 
77     /**
78      * Examine image data from the buffer and update the format if necessary.
79      */
80     void handleImageData(const sp<Codec2Buffer> &buffer);
81 
82 protected:
83     std::string mComponentName; ///< name of component for debugging
84     std::string mChannelName; ///< name of channel for debugging
85     const char *mName; ///< C-string version of channel name
86     // Format to be used for creating MediaCodec-facing buffers.
87     sp<AMessage> mFormat;
88 
89 private:
90     DISALLOW_EVIL_CONSTRUCTORS(CCodecBuffers);
91 };
92 
93 class InputBuffers : public CCodecBuffers {
94 public:
95     InputBuffers(const char *componentName, const char *name = "Input[]")
CCodecBuffers(componentName,name)96         : CCodecBuffers(componentName, name) { }
97     virtual ~InputBuffers() = default;
98 
99     /**
100      * Set a block pool to obtain input memory blocks.
101      */
setPool(const std::shared_ptr<C2BlockPool> & pool)102     void setPool(const std::shared_ptr<C2BlockPool> &pool) { mPool = pool; }
103 
104     /**
105      * Get a new MediaCodecBuffer for input and its corresponding index.
106      * Returns false if no new buffer can be obtained at the moment.
107      */
108     virtual bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) = 0;
109 
110     /**
111      * Release the buffer obtained from requestNewBuffer() and get the
112      * associated C2Buffer object back. Returns true if the buffer was on file
113      * and released successfully.
114      */
115     virtual bool releaseBuffer(
116             const sp<MediaCodecBuffer> &buffer,
117             std::shared_ptr<C2Buffer> *c2buffer,
118             bool release) = 0;
119 
120     /**
121      * Release the buffer that is no longer used by the codec process. Return
122      * true if and only if the buffer was on file and released successfully.
123      */
124     virtual bool expireComponentBuffer(
125             const std::shared_ptr<C2Buffer> &c2buffer) = 0;
126 
127     /**
128      * Flush internal state. After this call, no index or buffer previously
129      * returned from requestNewBuffer() is valid.
130      */
131     virtual void flush() = 0;
132 
133     /**
134      * Return array-backed version of input buffers. The returned object
135      * shall retain the internal state so that it will honor index and
136      * buffer from previous calls of requestNewBuffer().
137      */
138     virtual std::unique_ptr<InputBuffers> toArrayMode(size_t size) = 0;
139 
140     /**
141      * Release the buffer obtained from requestNewBuffer(), and create a deep
142      * copy clone of the buffer.
143      *
144      * \return  the deep copy clone of the buffer; nullptr if cloning is not
145      *          possible.
146      */
147     sp<Codec2Buffer> cloneAndReleaseBuffer(const sp<MediaCodecBuffer> &buffer);
148 
149 protected:
150     virtual sp<Codec2Buffer> createNewBuffer() = 0;
151 
152     // Pool to obtain blocks for input buffers.
153     std::shared_ptr<C2BlockPool> mPool;
154 
155 private:
156     DISALLOW_EVIL_CONSTRUCTORS(InputBuffers);
157 };
158 
159 class OutputBuffersArray;
160 
161 class OutputBuffers : public CCodecBuffers {
162 public:
163     OutputBuffers(const char *componentName, const char *name = "Output");
164     virtual ~OutputBuffers();
165 
166     /**
167      * Register output C2Buffer from the component and obtain corresponding
168      * index and MediaCodecBuffer object.
169      *
170      * Returns:
171      *   OK if registration succeeds.
172      *   NO_MEMORY if all buffers are available but not compatible.
173      *   WOULD_BLOCK if there are compatible buffers, but they are all in use.
174      */
175     virtual status_t registerBuffer(
176             const std::shared_ptr<C2Buffer> &buffer,
177             size_t *index,
178             sp<MediaCodecBuffer> *clientBuffer) = 0;
179 
180     /**
181      * Register codec specific data as a buffer to be consistent with
182      * MediaCodec behavior.
183      */
184     virtual status_t registerCsd(
185             const C2StreamInitDataInfo::output * /* csd */,
186             size_t * /* index */,
187             sp<MediaCodecBuffer> * /* clientBuffer */) = 0;
188 
189     /**
190      * Release the buffer obtained from registerBuffer() and get the
191      * associated C2Buffer object back. Returns true if the buffer was on file
192      * and released successfully.
193      */
194     virtual bool releaseBuffer(
195             const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) = 0;
196 
197     /**
198      * Flush internal state. After this call, no index or buffer previously
199      * returned from registerBuffer() is valid.
200      */
201     virtual void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) = 0;
202 
203     /**
204      * Return array-backed version of output buffers. The returned object
205      * shall retain the internal state so that it will honor index and
206      * buffer from previous calls of registerBuffer().
207      */
208     virtual std::unique_ptr<OutputBuffersArray> toArrayMode(size_t size) = 0;
209 
210     /**
211      * Initialize SkipCutBuffer object.
212      */
213     void initSkipCutBuffer(
214             int32_t delay, int32_t padding, int32_t sampleRate, int32_t channelCount);
215 
216     /**
217      * Update SkipCutBuffer from format. The @p format must not be null.
218      * @p notify determines whether the format comes with a buffer that should
219      * be reported to the client or not.
220      */
221     void updateSkipCutBuffer(const sp<AMessage> &format, bool notify = true);
222 
223     /**
224      * Output Stash
225      * ============
226      *
227      * The output stash is a place to hold output buffers temporarily before
228      * they are registered to output slots. It has 2 main functions:
229      * 1. Allow reordering of output frames as the codec may produce frames in a
230      *    different order.
231      * 2. Act as a "buffer" between the codec and the client because the codec
232      *    may produce more buffers than available slots. This excess of codec's
233      *    output buffers should be registered to slots later, after the client
234      *    has released some slots.
235      *
236      * The stash consists of 2 lists of buffers: mPending and mReorderStash.
237      * mPending is a normal FIFO queue with not size limit, while mReorderStash
238      * is a sorted list with size limit mDepth.
239      *
240      * The normal flow of a non-csd output buffer is as follows:
241      *
242      *           |----------------OutputBuffers---------------|
243      *           |----------Output stash----------|           |
244      *   Codec --|-> mReorderStash --> mPending --|-> slots --|-> client
245      *           |                                |           |
246      *     pushToStash()                    popFromStashAndRegister()
247      *
248      * The buffer that comes from the codec first enters mReorderStash. The
249      * first buffer in mReorderStash gets moved to mPending when mReorderStash
250      * overflows. Buffers in mPending are registered to slots and given to the
251      * client as soon as slots are available.
252      *
253      * Every output buffer that is not a csd buffer should be put on the stash
254      * by calling pushToStash(), then later registered to a slot by calling
255      * popFromStashAndRegister() before notifying the client with
256      * onOutputBufferAvailable().
257      *
258      * Reordering
259      * ==========
260      *
261      * mReorderStash is a sorted list with a specified size limit. The size
262      * limit can be set by calling setReorderDepth().
263      *
264      * Every buffer in mReorderStash has a C2WorkOrdinalStruct, which contains 3
265      * members, all of which are comparable. Which member of C2WorkOrdinalStruct
266      * should be used for reordering can be chosen by calling setReorderKey().
267      */
268 
269     /**
270      * Return the reorder depth---the size of mReorderStash.
271      */
272     uint32_t getReorderDepth() const;
273 
274     /**
275      * Set the reorder depth.
276      */
277     void setReorderDepth(uint32_t depth);
278 
279     /**
280      * Set the type of "key" to use in comparisons.
281      */
282     void setReorderKey(C2Config::ordinal_key_t key);
283 
284     /**
285      * Return whether the output stash has any pending buffers.
286      */
287     bool hasPending() const;
288 
289     /**
290      * Flush the stash and reset the depth and the key to their default values.
291      */
292     void clearStash();
293 
294     /**
295      * Flush the stash.
296      */
297     void flushStash();
298 
299     /**
300      * Push a buffer to the reorder stash.
301      *
302      * @param buffer    C2Buffer object from the returned work.
303      * @param notify    Whether the returned work contains a buffer that should
304      *                  be reported to the client. This may be false if the
305      *                  caller wants to process the buffer without notifying the
306      *                  client.
307      * @param timestamp Buffer timestamp to report to the client.
308      * @param flags     Buffer flags to report to the client.
309      * @param format    Buffer format to report to the client.
310      * @param ordinal   Ordinal used in reordering. This determines when the
311      *                  buffer will be popped from the output stash by
312      *                  `popFromStashAndRegister()`.
313      */
314     void pushToStash(
315             const std::shared_ptr<C2Buffer>& buffer,
316             bool notify,
317             int64_t timestamp,
318             int32_t flags,
319             const sp<AMessage>& format,
320             const C2WorkOrdinalStruct& ordinal);
321 
322     enum BufferAction : int {
323         SKIP,
324         DISCARD,
325         NOTIFY_CLIENT,
326         REALLOCATE,
327         RETRY,
328     };
329 
330     /**
331      * Try to atomically pop the first buffer from the reorder stash and
332      * register it to an output slot. The function returns a value that
333      * indicates a recommended course of action for the caller.
334      *
335      * If the stash is empty, the function will return `SKIP`.
336      *
337      * If the stash is not empty, the function will peek at the first (oldest)
338      * entry in mPending process the buffer in the entry as follows:
339      * - If the buffer should not be sent to the client, the function will
340      *   return `DISCARD`. The stash entry will be removed.
341      * - If the buffer should be sent to the client, the function will attempt
342      *   to register the buffer to a slot. The registration may have 3 outcomes
343      *   corresponding to the following return values:
344      *   - `NOTIFY_CLIENT`: The buffer is successfully registered to a slot. The
345      *     output arguments @p index and @p outBuffer will contain valid values
346      *     that the caller can use to call onOutputBufferAvailable(). The stash
347      *     entry will be removed.
348      *   - `REALLOCATE`: The buffer is not registered because it is not
349      *     compatible with the current slots (which are available). The caller
350      *     should reallocate the OutputBuffers with slots that can fit the
351      *     returned @p c2Buffer. The stash entry will not be removed
352      *   - `RETRY`: All slots are currently occupied by the client. The caller
353      *     should try to call this function again after the client has released
354      *     some slots.
355      *
356      * @return What the caller should do afterwards.
357      *
358      * @param[out] c2Buffer   Underlying C2Buffer associated to the first buffer
359      *                        on the stash. This value is guaranteed to be valid
360      *                        unless the return value is `SKIP`.
361      * @param[out] index      Slot index. This value is valid only if the return
362      *                        value is `NOTIFY_CLIENT`.
363      * @param[out] outBuffer  Registered buffer. This value is valid only if the
364      *                        return valu is `NOTIFY_CLIENT`.
365      */
366     BufferAction popFromStashAndRegister(
367             std::shared_ptr<C2Buffer>* c2Buffer,
368             size_t* index,
369             sp<MediaCodecBuffer>* outBuffer);
370 
371 protected:
372     sp<SkipCutBuffer> mSkipCutBuffer;
373 
374     /**
375      * Update the SkipCutBuffer object. No-op if it's never initialized.
376      */
377     void updateSkipCutBuffer(int32_t sampleRate, int32_t channelCount);
378 
379     /**
380      * Submit buffer to SkipCutBuffer object, if initialized.
381      */
382     void submit(const sp<MediaCodecBuffer> &buffer);
383 
384 private:
385     // SkipCutBuffer
386     int32_t mDelay;
387     int32_t mPadding;
388     int32_t mSampleRate;
389     int32_t mChannelCount;
390 
391     void setSkipCutBuffer(int32_t skip, int32_t cut);
392 
393     // Output stash
394 
395     // Output format that has not been made available to the client.
396     sp<AMessage> mUnreportedFormat;
397 
398     // Struct for an entry in the output stash (mPending and mReorderStash)
399     struct StashEntry {
StashEntryStashEntry400         inline StashEntry()
401             : buffer(nullptr),
402               notify(false),
403               timestamp(0),
404               flags(0),
405               format(),
406               ordinal({0, 0, 0}) {}
StashEntryStashEntry407         inline StashEntry(
408                 const std::shared_ptr<C2Buffer> &b,
409                 bool n,
410                 int64_t t,
411                 int32_t f,
412                 const sp<AMessage> &fmt,
413                 const C2WorkOrdinalStruct &o)
414             : buffer(b),
415               notify(n),
416               timestamp(t),
417               flags(f),
418               format(fmt),
419               ordinal(o) {}
420         std::shared_ptr<C2Buffer> buffer;
421         bool notify;
422         int64_t timestamp;
423         int32_t flags;
424         sp<AMessage> format;
425         C2WorkOrdinalStruct ordinal;
426     };
427 
428     /**
429      * FIFO queue of stash entries.
430      */
431     std::list<StashEntry> mPending;
432     /**
433      * Sorted list of stash entries.
434      */
435     std::list<StashEntry> mReorderStash;
436     /**
437      * Size limit of mReorderStash.
438      */
439     uint32_t mDepth{0};
440     /**
441      * Choice of key to use in ordering of stash entries in mReorderStash.
442      */
443     C2Config::ordinal_key_t mKey{C2Config::ORDINAL};
444 
445     /**
446      * Return false if mPending is empty; otherwise, pop the first entry from
447      * mPending and return true.
448      */
449     bool popPending(StashEntry *entry);
450 
451     /**
452      * Push an entry as the first entry of mPending.
453      */
454     void deferPending(const StashEntry &entry);
455 
456     /**
457      * Comparison of C2WorkOrdinalStruct based on mKey.
458      */
459     bool less(const C2WorkOrdinalStruct &o1,
460               const C2WorkOrdinalStruct &o2) const;
461 
462     DISALLOW_EVIL_CONSTRUCTORS(OutputBuffers);
463 
464     friend OutputBuffersArray;
465 };
466 
467 /**
468  * Simple local buffer pool backed by std::vector.
469  */
470 class LocalBufferPool : public std::enable_shared_from_this<LocalBufferPool> {
471 public:
472     /**
473      * Create a new LocalBufferPool object.
474      *
475      * \return  a newly created pool object.
476      */
477     static std::shared_ptr<LocalBufferPool> Create();
478 
479     /**
480      * Return an ABuffer object whose size is at least |capacity|.
481      *
482      * \param   capacity  requested capacity
483      * \return  nullptr if the pool capacity is reached
484      *          an ABuffer object otherwise.
485      */
486     sp<ABuffer> newBuffer(size_t capacity);
487 
488 private:
489     /**
490      * ABuffer backed by std::vector.
491      */
492     class VectorBuffer : public ::android::ABuffer {
493     public:
494         /**
495          * Construct a VectorBuffer by taking the ownership of supplied vector.
496          *
497          * \param vec   backing vector of the buffer. this object takes
498          *              ownership at construction.
499          * \param pool  a LocalBufferPool object to return the vector at
500          *              destruction.
501          */
502         VectorBuffer(std::vector<uint8_t> &&vec, const std::shared_ptr<LocalBufferPool> &pool);
503 
504         ~VectorBuffer() override;
505 
506     private:
507         std::vector<uint8_t> mVec;
508         std::weak_ptr<LocalBufferPool> mPool;
509     };
510 
511     Mutex mMutex;
512     size_t mPoolCapacity;
513     size_t mUsedSize;
514     std::list<std::vector<uint8_t>> mPool;
515 
516     /**
517      * Private constructor to prevent constructing non-managed LocalBufferPool.
518      */
LocalBufferPool(size_t poolCapacity)519     explicit LocalBufferPool(size_t poolCapacity)
520         : mPoolCapacity(poolCapacity), mUsedSize(0) {
521     }
522 
523     /**
524      * Take back the ownership of vec from the destructed VectorBuffer and put
525      * it in front of the pool.
526      */
527     void returnVector(std::vector<uint8_t> &&vec);
528 
529     DISALLOW_EVIL_CONSTRUCTORS(LocalBufferPool);
530 };
531 
532 class BuffersArrayImpl;
533 
534 /**
535  * Flexible buffer slots implementation.
536  */
537 class FlexBuffersImpl {
538 public:
FlexBuffersImpl(const char * name)539     FlexBuffersImpl(const char *name)
540         : mImplName(std::string(name) + ".Impl"),
541           mName(mImplName.c_str()) { }
542 
543     /**
544      * Assign an empty slot for a buffer and return the index. If there's no
545      * empty slot, just add one at the end and return it.
546      *
547      * \param buffer[in]  a new buffer to assign a slot.
548      * \return            index of the assigned slot.
549      */
550     size_t assignSlot(const sp<Codec2Buffer> &buffer);
551 
552     /**
553      * Release the slot from the client, and get the C2Buffer object back from
554      * the previously assigned buffer. Note that the slot is not completely free
555      * until the returned C2Buffer object is freed.
556      *
557      * \param   buffer[in]        the buffer previously assigned a slot.
558      * \param   c2buffer[in,out]  pointer to C2Buffer to be populated. Ignored
559      *                            if null.
560      * \return  true  if the buffer is successfully released from a slot
561      *          false otherwise
562      */
563     bool releaseSlot(
564             const sp<MediaCodecBuffer> &buffer,
565             std::shared_ptr<C2Buffer> *c2buffer,
566             bool release);
567 
568     /**
569      * Expire the C2Buffer object in the slot.
570      *
571      * \param   c2buffer[in]  C2Buffer object which the component released.
572      * \return  true  if the buffer is found in one of the slots and
573      *                successfully released
574      *          false otherwise
575      */
576     bool expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer);
577 
578     /**
579      * The client abandoned all known buffers, so reclaim the ownership.
580      */
581     void flush();
582 
583     /**
584      * Return the number of buffers that are sent to the client but not released
585      * yet.
586      */
587     size_t numClientBuffers() const;
588 
589     /**
590      * Return the number of buffers that are sent to the component but not
591      * returned back yet.
592      */
593     size_t numComponentBuffers() const;
594 
595 private:
596     friend class BuffersArrayImpl;
597 
598     std::string mImplName; ///< name for debugging
599     const char *mName; ///< C-string version of name
600 
601     struct Entry {
602         sp<Codec2Buffer> clientBuffer;
603         std::weak_ptr<C2Buffer> compBuffer;
604     };
605     std::vector<Entry> mBuffers;
606 };
607 
608 /**
609  * Static buffer slots implementation based on a fixed-size array.
610  */
611 class BuffersArrayImpl {
612 public:
BuffersArrayImpl()613     BuffersArrayImpl()
614         : mImplName("BuffersArrayImpl"),
615           mName(mImplName.c_str()) { }
616 
617     /**
618      * Initialize buffer array from the original |impl|. The buffers known by
619      * the client is preserved, and the empty slots are populated so that the
620      * array size is at least |minSize|.
621      *
622      * \param impl[in]      FlexBuffersImpl object used so far.
623      * \param minSize[in]   minimum size of the buffer array.
624      * \param allocate[in]  function to allocate a client buffer for an empty slot.
625      */
626     void initialize(
627             const FlexBuffersImpl &impl,
628             size_t minSize,
629             std::function<sp<Codec2Buffer>()> allocate);
630 
631     /**
632      * Grab a buffer from the underlying array which matches the criteria.
633      *
634      * \param index[out]    index of the slot.
635      * \param buffer[out]   the matching buffer.
636      * \param match[in]     a function to test whether the buffer matches the
637      *                      criteria or not.
638      * \return OK           if successful,
639      *         WOULD_BLOCK  if slots are being used,
640      *         NO_MEMORY    if no slot matches the criteria, even though it's
641      *                      available
642      */
643     status_t grabBuffer(
644             size_t *index,
645             sp<Codec2Buffer> *buffer,
646             std::function<bool(const sp<Codec2Buffer> &)> match =
647                 [](const sp<Codec2Buffer> &buffer) { return (buffer != nullptr); });
648 
649     /**
650      * Return the buffer from the client, and get the C2Buffer object back from
651      * the buffer. Note that the slot is not completely free until the returned
652      * C2Buffer object is freed.
653      *
654      * \param   buffer[in]        the buffer previously grabbed.
655      * \param   c2buffer[in,out]  pointer to C2Buffer to be populated. Ignored
656      *                            if null.
657      * \return  true  if the buffer is successfully returned
658      *          false otherwise
659      */
660     bool returnBuffer(
661             const sp<MediaCodecBuffer> &buffer,
662             std::shared_ptr<C2Buffer> *c2buffer,
663             bool release);
664 
665     /**
666      * Expire the C2Buffer object in the slot.
667      *
668      * \param   c2buffer[in]  C2Buffer object which the component released.
669      * \return  true  if the buffer is found in one of the slots and
670      *                successfully released
671      *          false otherwise
672      */
673     bool expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer);
674 
675     /**
676      * Populate |array| with the underlying buffer array.
677      *
678      * \param array[out]  an array to be filled with the underlying buffer array.
679      */
680     void getArray(Vector<sp<MediaCodecBuffer>> *array) const;
681 
682     /**
683      * The client abandoned all known buffers, so reclaim the ownership.
684      */
685     void flush();
686 
687     /**
688      * Reallocate the array with the given allocation function.
689      *
690      * \param alloc[in] the allocation function for client buffers.
691      */
692     void realloc(std::function<sp<Codec2Buffer>()> alloc);
693 
694     /**
695      * Grow the array to the new size. It is a programming error to supply
696      * smaller size as the new size.
697      *
698      * \param newSize[in] new size of the array.
699      * \param alloc[in]   the alllocation function for client buffers to fill
700      *                    the new empty slots.
701      */
702     void grow(size_t newSize, std::function<sp<Codec2Buffer>()> alloc);
703 
704     /**
705      * Return the number of buffers that are sent to the client but not released
706      * yet.
707      */
708     size_t numClientBuffers() const;
709 
710     /**
711      * Return the size of the array.
712      */
713     size_t arraySize() const;
714 
715 private:
716     std::string mImplName; ///< name for debugging
717     const char *mName; ///< C-string version of name
718 
719     struct Entry {
720         const sp<Codec2Buffer> clientBuffer;
721         std::weak_ptr<C2Buffer> compBuffer;
722         bool ownedByClient;
723     };
724     std::vector<Entry> mBuffers;
725 };
726 
727 class InputBuffersArray : public InputBuffers {
728 public:
729     InputBuffersArray(const char *componentName, const char *name = "Input[N]")
InputBuffers(componentName,name)730         : InputBuffers(componentName, name) { }
731     ~InputBuffersArray() override = default;
732 
733     /**
734      * Initialize this object from the non-array state. We keep existing slots
735      * at the same index, and for empty slots we allocate client buffers with
736      * the given allocate function. If the number of slots is less than minSize,
737      * we fill the array to the minimum size.
738      *
739      * \param impl[in]      existing non-array state
740      * \param minSize[in]   minimum size of the array
741      * \param allocate[in]  allocate function to fill empty slots
742      */
743     void initialize(
744             const FlexBuffersImpl &impl,
745             size_t minSize,
746             std::function<sp<Codec2Buffer>()> allocate);
747 
isArrayMode()748     bool isArrayMode() const final { return true; }
749 
toArrayMode(size_t)750     std::unique_ptr<InputBuffers> toArrayMode(size_t) final {
751         return nullptr;
752     }
753 
754     void getArray(Vector<sp<MediaCodecBuffer>> *array) const final;
755 
756     bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override;
757 
758     bool releaseBuffer(
759             const sp<MediaCodecBuffer> &buffer,
760             std::shared_ptr<C2Buffer> *c2buffer,
761             bool release) override;
762 
763     bool expireComponentBuffer(
764             const std::shared_ptr<C2Buffer> &c2buffer) override;
765 
766     void flush() override;
767 
768     size_t numClientBuffers() const final;
769 
770 protected:
771     sp<Codec2Buffer> createNewBuffer() override;
772 
773 private:
774     BuffersArrayImpl mImpl;
775     std::function<sp<Codec2Buffer>()> mAllocate;
776 };
777 
778 class SlotInputBuffers : public InputBuffers {
779 public:
780     SlotInputBuffers(const char *componentName, const char *name = "Slot-Input")
InputBuffers(componentName,name)781         : InputBuffers(componentName, name),
782           mImpl(mName) { }
783     ~SlotInputBuffers() override = default;
784 
785     bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) final;
786 
787     bool releaseBuffer(
788             const sp<MediaCodecBuffer> &buffer,
789             std::shared_ptr<C2Buffer> *c2buffer,
790             bool release) final;
791 
792     bool expireComponentBuffer(
793             const std::shared_ptr<C2Buffer> &c2buffer) final;
794 
795     void flush() final;
796 
797     std::unique_ptr<InputBuffers> toArrayMode(size_t size) final;
798 
799     size_t numClientBuffers() const final;
800 
801 protected:
802     sp<Codec2Buffer> createNewBuffer() final;
803 
804 private:
805     FlexBuffersImpl mImpl;
806 };
807 
808 class LinearInputBuffers : public InputBuffers {
809 public:
810     LinearInputBuffers(const char *componentName, const char *name = "1D-Input")
InputBuffers(componentName,name)811         : InputBuffers(componentName, name),
812           mImpl(mName) { }
813     ~LinearInputBuffers() override = default;
814 
815     bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override;
816 
817     bool releaseBuffer(
818             const sp<MediaCodecBuffer> &buffer,
819             std::shared_ptr<C2Buffer> *c2buffer,
820             bool release) override;
821 
822     bool expireComponentBuffer(
823             const std::shared_ptr<C2Buffer> &c2buffer) override;
824 
825     void flush() override;
826 
827     std::unique_ptr<InputBuffers> toArrayMode(size_t size) override;
828 
829     size_t numClientBuffers() const final;
830 
831 protected:
832     sp<Codec2Buffer> createNewBuffer() override;
833 
834     FlexBuffersImpl mImpl;
835 
836 private:
837     static sp<Codec2Buffer> Alloc(
838             const std::shared_ptr<C2BlockPool> &pool, const sp<AMessage> &format);
839 };
840 
841 class EncryptedLinearInputBuffers : public LinearInputBuffers {
842 public:
843     EncryptedLinearInputBuffers(
844             bool secure,
845             const sp<MemoryDealer> &dealer,
846             const sp<ICrypto> &crypto,
847             int32_t heapSeqNum,
848             size_t capacity,
849             size_t numInputSlots,
850             const char *componentName, const char *name = "EncryptedInput");
851 
852     ~EncryptedLinearInputBuffers() override = default;
853 
854     std::unique_ptr<InputBuffers> toArrayMode(size_t size) override;
855 
856 protected:
857     sp<Codec2Buffer> createNewBuffer() override;
858 
859 private:
860     struct Entry {
861         std::weak_ptr<C2LinearBlock> block;
862         sp<IMemory> memory;
863         int32_t heapSeqNum;
864     };
865 
866     static sp<Codec2Buffer> Alloc(
867             const std::shared_ptr<C2BlockPool> &pool,
868             const sp<AMessage> &format,
869             C2MemoryUsage usage,
870             const std::shared_ptr<std::vector<Entry>> &memoryVector);
871 
872     C2MemoryUsage mUsage;
873     sp<MemoryDealer> mDealer;
874     sp<ICrypto> mCrypto;
875     std::shared_ptr<std::vector<Entry>> mMemoryVector;
876 };
877 
878 class GraphicMetadataInputBuffers : public InputBuffers {
879 public:
880     GraphicMetadataInputBuffers(const char *componentName, const char *name = "2D-MetaInput");
881     ~GraphicMetadataInputBuffers() override = default;
882 
883     bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override;
884 
885     bool releaseBuffer(
886             const sp<MediaCodecBuffer> &buffer,
887             std::shared_ptr<C2Buffer> *c2buffer,
888             bool release) override;
889 
890     bool expireComponentBuffer(
891             const std::shared_ptr<C2Buffer> &c2buffer) override;
892 
893     void flush() override;
894 
895     std::unique_ptr<InputBuffers> toArrayMode(size_t size) final;
896 
897     size_t numClientBuffers() const final;
898 
899 protected:
900     sp<Codec2Buffer> createNewBuffer() override;
901 
902 private:
903     FlexBuffersImpl mImpl;
904     std::shared_ptr<C2AllocatorStore> mStore;
905 };
906 
907 class GraphicInputBuffers : public InputBuffers {
908 public:
909     GraphicInputBuffers(const char *componentName, const char *name = "2D-BB-Input");
910     ~GraphicInputBuffers() override = default;
911 
912     bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override;
913 
914     bool releaseBuffer(
915             const sp<MediaCodecBuffer> &buffer,
916             std::shared_ptr<C2Buffer> *c2buffer,
917             bool release) override;
918 
919     bool expireComponentBuffer(
920             const std::shared_ptr<C2Buffer> &c2buffer) override;
921 
922     void flush() override;
923 
924     std::unique_ptr<InputBuffers> toArrayMode(
925             size_t size) final;
926 
927     size_t numClientBuffers() const final;
928 
929 protected:
930     sp<Codec2Buffer> createNewBuffer() override;
931 
932 private:
933     FlexBuffersImpl mImpl;
934     std::shared_ptr<LocalBufferPool> mLocalBufferPool;
935 };
936 
937 class DummyInputBuffers : public InputBuffers {
938 public:
939     DummyInputBuffers(const char *componentName, const char *name = "2D-Input")
InputBuffers(componentName,name)940         : InputBuffers(componentName, name) { }
941     ~DummyInputBuffers() override = default;
942 
requestNewBuffer(size_t *,sp<MediaCodecBuffer> *)943     bool requestNewBuffer(size_t *, sp<MediaCodecBuffer> *) override {
944         return false;
945     }
946 
releaseBuffer(const sp<MediaCodecBuffer> &,std::shared_ptr<C2Buffer> *,bool)947     bool releaseBuffer(
948             const sp<MediaCodecBuffer> &, std::shared_ptr<C2Buffer> *, bool) override {
949         return false;
950     }
951 
expireComponentBuffer(const std::shared_ptr<C2Buffer> &)952     bool expireComponentBuffer(const std::shared_ptr<C2Buffer> &) override {
953         return false;
954     }
flush()955     void flush() override {
956     }
957 
toArrayMode(size_t)958     std::unique_ptr<InputBuffers> toArrayMode(size_t) final {
959         return nullptr;
960     }
961 
isArrayMode()962     bool isArrayMode() const final { return true; }
963 
getArray(Vector<sp<MediaCodecBuffer>> * array)964     void getArray(Vector<sp<MediaCodecBuffer>> *array) const final {
965         array->clear();
966     }
967 
numClientBuffers()968     size_t numClientBuffers() const final {
969         return 0u;
970     }
971 
972 protected:
createNewBuffer()973     sp<Codec2Buffer> createNewBuffer() override {
974         return nullptr;
975     }
976 };
977 
978 class OutputBuffersArray : public OutputBuffers {
979 public:
980     OutputBuffersArray(const char *componentName, const char *name = "Output[N]")
OutputBuffers(componentName,name)981         : OutputBuffers(componentName, name) { }
982     ~OutputBuffersArray() override = default;
983 
984     /**
985      * Initialize this object from the non-array state. We keep existing slots
986      * at the same index, and for empty slots we allocate client buffers with
987      * the given allocate function. If the number of slots is less than minSize,
988      * we fill the array to the minimum size.
989      *
990      * \param impl[in]      existing non-array state
991      * \param minSize[in]   minimum size of the array
992      * \param allocate[in]  allocate function to fill empty slots
993      */
994     void initialize(
995             const FlexBuffersImpl &impl,
996             size_t minSize,
997             std::function<sp<Codec2Buffer>()> allocate);
998 
isArrayMode()999     bool isArrayMode() const final { return true; }
1000 
toArrayMode(size_t)1001     std::unique_ptr<OutputBuffersArray> toArrayMode(size_t) final {
1002         return nullptr;
1003     }
1004 
1005     status_t registerBuffer(
1006             const std::shared_ptr<C2Buffer> &buffer,
1007             size_t *index,
1008             sp<MediaCodecBuffer> *clientBuffer) final;
1009 
1010     status_t registerCsd(
1011             const C2StreamInitDataInfo::output *csd,
1012             size_t *index,
1013             sp<MediaCodecBuffer> *clientBuffer) final;
1014 
1015     bool releaseBuffer(
1016             const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) override;
1017 
1018     void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) override;
1019 
1020     void getArray(Vector<sp<MediaCodecBuffer>> *array) const final;
1021 
1022     size_t numClientBuffers() const final;
1023 
1024     /**
1025      * Reallocate the array, filled with buffers with the same size as given
1026      * buffer.
1027      *
1028      * \param c2buffer[in] the reference buffer
1029      */
1030     void realloc(const std::shared_ptr<C2Buffer> &c2buffer);
1031 
1032     /**
1033      * Grow the array to the new size. It is a programming error to supply
1034      * smaller size as the new size.
1035      *
1036      * \param newSize[in] new size of the array.
1037      */
1038     void grow(size_t newSize);
1039 
1040     /**
1041      * Transfer the SkipCutBuffer and the output stash from another
1042      * OutputBuffers.
1043      */
1044     void transferFrom(OutputBuffers* source);
1045 
1046 private:
1047     BuffersArrayImpl mImpl;
1048     std::function<sp<Codec2Buffer>()> mAlloc;
1049 };
1050 
1051 class FlexOutputBuffers : public OutputBuffers {
1052 public:
1053     FlexOutputBuffers(const char *componentName, const char *name = "Output[]")
OutputBuffers(componentName,name)1054         : OutputBuffers(componentName, name),
1055           mImpl(mName) { }
1056 
1057     status_t registerBuffer(
1058             const std::shared_ptr<C2Buffer> &buffer,
1059             size_t *index,
1060             sp<MediaCodecBuffer> *clientBuffer) override;
1061 
1062     status_t registerCsd(
1063             const C2StreamInitDataInfo::output *csd,
1064             size_t *index,
1065             sp<MediaCodecBuffer> *clientBuffer) final;
1066 
1067     bool releaseBuffer(
1068             const sp<MediaCodecBuffer> &buffer,
1069             std::shared_ptr<C2Buffer> *c2buffer) override;
1070 
1071     void flush(
1072             const std::list<std::unique_ptr<C2Work>> &flushedWork) override;
1073 
1074     std::unique_ptr<OutputBuffersArray> toArrayMode(size_t size) override;
1075 
1076     size_t numClientBuffers() const final;
1077 
1078     /**
1079      * Return an appropriate Codec2Buffer object for the type of buffers.
1080      *
1081      * \param buffer  C2Buffer object to wrap.
1082      *
1083      * \return  appropriate Codec2Buffer object to wrap |buffer|.
1084      */
1085     virtual sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) = 0;
1086 
1087     /**
1088      * Return a function that allocates an appropriate Codec2Buffer object for
1089      * the type of buffers, to be used as an empty array buffer. The function
1090      * must not refer to this pointer, since it may be used after this object
1091      * destructs.
1092      *
1093      * \return  a function that allocates appropriate Codec2Buffer object,
1094      *          which can copy() from C2Buffers.
1095      */
1096     virtual std::function<sp<Codec2Buffer>()> getAlloc() = 0;
1097 
1098 private:
1099     FlexBuffersImpl mImpl;
1100 };
1101 
1102 class LinearOutputBuffers : public FlexOutputBuffers {
1103 public:
1104     LinearOutputBuffers(const char *componentName, const char *name = "1D-Output")
FlexOutputBuffers(componentName,name)1105         : FlexOutputBuffers(componentName, name) { }
1106 
1107     void flush(
1108             const std::list<std::unique_ptr<C2Work>> &flushedWork) override;
1109 
1110     sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override;
1111 
1112     std::function<sp<Codec2Buffer>()> getAlloc() override;
1113 };
1114 
1115 class GraphicOutputBuffers : public FlexOutputBuffers {
1116 public:
1117     GraphicOutputBuffers(const char *componentName, const char *name = "2D-Output")
FlexOutputBuffers(componentName,name)1118         : FlexOutputBuffers(componentName, name) { }
1119 
1120     sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override;
1121 
1122     std::function<sp<Codec2Buffer>()> getAlloc() override;
1123 };
1124 
1125 class RawGraphicOutputBuffers : public FlexOutputBuffers {
1126 public:
1127     RawGraphicOutputBuffers(const char *componentName, const char *name = "2D-BB-Output");
1128     ~RawGraphicOutputBuffers() override = default;
1129 
1130     sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override;
1131 
1132     std::function<sp<Codec2Buffer>()> getAlloc() override;
1133 
1134 private:
1135     std::shared_ptr<LocalBufferPool> mLocalBufferPool;
1136 };
1137 
1138 }  // namespace android
1139 
1140 #endif  // CCODEC_BUFFERS_H_
1141