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