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 #include "SkipCutBuffer.h"
29 
30 namespace android {
31 
32 constexpr size_t kLinearBufferSize = 1048576;
33 // This can fit 4K RGBA frame, and most likely client won't need more than this.
34 constexpr size_t kMaxLinearBufferSize = 4096 * 2304 * 4;
35 
36 /**
37  * Base class for representation of buffers at one port.
38  */
39 class CCodecBuffers {
40 public:
41     CCodecBuffers(const char *componentName, const char *name = "Buffers")
mComponentName(componentName)42         : mComponentName(componentName),
43           mChannelName(std::string(componentName) + ":" + name),
44           mName(mChannelName.c_str()) {
45     }
46     virtual ~CCodecBuffers() = default;
47 
48     /**
49      * Set format for MediaCodec-facing buffers.
50      */
51     void setFormat(const sp<AMessage> &format);
52 
53     /**
54      * Return a copy of current format.
55      */
56     sp<AMessage> dupFormat();
57 
58     /**
59      * Returns true if the buffers are operating under array mode.
60      */
isArrayMode()61     virtual bool isArrayMode() const { return false; }
62 
63     /**
64      * Fills the vector with MediaCodecBuffer's if in array mode; otherwise,
65      * no-op.
66      */
getArray(Vector<sp<MediaCodecBuffer>> *)67     virtual void getArray(Vector<sp<MediaCodecBuffer>> *) const {}
68 
69     /**
70      * Return number of buffers the client owns.
71      */
72     virtual size_t numClientBuffers() const = 0;
73 
74     /**
75      * Examine image data from the buffer and update the format if necessary.
76      */
77     void handleImageData(const sp<Codec2Buffer> &buffer);
78 
79 protected:
80     std::string mComponentName; ///< name of component for debugging
81     std::string mChannelName; ///< name of channel for debugging
82     const char *mName; ///< C-string version of channel name
83     // Format to be used for creating MediaCodec-facing buffers.
84     sp<AMessage> mFormat;
85 
86 private:
87     DISALLOW_EVIL_CONSTRUCTORS(CCodecBuffers);
88 };
89 
90 class InputBuffers : public CCodecBuffers {
91 public:
92     InputBuffers(const char *componentName, const char *name = "Input[]")
CCodecBuffers(componentName,name)93         : CCodecBuffers(componentName, name) { }
94     virtual ~InputBuffers() = default;
95 
96     /**
97      * Set a block pool to obtain input memory blocks.
98      */
setPool(const std::shared_ptr<C2BlockPool> & pool)99     void setPool(const std::shared_ptr<C2BlockPool> &pool) { mPool = pool; }
100 
101     /**
102      * Get a new MediaCodecBuffer for input and its corresponding index.
103      * Returns false if no new buffer can be obtained at the moment.
104      */
105     virtual bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) = 0;
106 
107     /**
108      * Release the buffer obtained from requestNewBuffer() and get the
109      * associated C2Buffer object back. Returns true if the buffer was on file
110      * and released successfully.
111      */
112     virtual bool releaseBuffer(
113             const sp<MediaCodecBuffer> &buffer,
114             std::shared_ptr<C2Buffer> *c2buffer,
115             bool release) = 0;
116 
117     /**
118      * Release the buffer that is no longer used by the codec process. Return
119      * true if and only if the buffer was on file and released successfully.
120      */
121     virtual bool expireComponentBuffer(
122             const std::shared_ptr<C2Buffer> &c2buffer) = 0;
123 
124     /**
125      * Flush internal state. After this call, no index or buffer previously
126      * returned from requestNewBuffer() is valid.
127      */
128     virtual void flush() = 0;
129 
130     /**
131      * Return array-backed version of input buffers. The returned object
132      * shall retain the internal state so that it will honor index and
133      * buffer from previous calls of requestNewBuffer().
134      */
135     virtual std::unique_ptr<InputBuffers> toArrayMode(size_t size) = 0;
136 
137     /**
138      * Release the buffer obtained from requestNewBuffer(), and create a deep
139      * copy clone of the buffer.
140      *
141      * \return  the deep copy clone of the buffer; nullptr if cloning is not
142      *          possible.
143      */
144     sp<Codec2Buffer> cloneAndReleaseBuffer(const sp<MediaCodecBuffer> &buffer);
145 
146 protected:
147     virtual sp<Codec2Buffer> createNewBuffer() = 0;
148 
149     // Pool to obtain blocks for input buffers.
150     std::shared_ptr<C2BlockPool> mPool;
151 
152 private:
153     DISALLOW_EVIL_CONSTRUCTORS(InputBuffers);
154 };
155 
156 class OutputBuffers : public CCodecBuffers {
157 public:
158     OutputBuffers(const char *componentName, const char *name = "Output")
CCodecBuffers(componentName,name)159         : CCodecBuffers(componentName, name) { }
160     virtual ~OutputBuffers() = default;
161 
162     /**
163      * Register output C2Buffer from the component and obtain corresponding
164      * index and MediaCodecBuffer object. Returns false if registration
165      * fails.
166      */
167     virtual status_t registerBuffer(
168             const std::shared_ptr<C2Buffer> &buffer,
169             size_t *index,
170             sp<MediaCodecBuffer> *clientBuffer) = 0;
171 
172     /**
173      * Register codec specific data as a buffer to be consistent with
174      * MediaCodec behavior.
175      */
176     virtual status_t registerCsd(
177             const C2StreamInitDataInfo::output * /* csd */,
178             size_t * /* index */,
179             sp<MediaCodecBuffer> * /* clientBuffer */) = 0;
180 
181     /**
182      * Release the buffer obtained from registerBuffer() and get the
183      * associated C2Buffer object back. Returns true if the buffer was on file
184      * and released successfully.
185      */
186     virtual bool releaseBuffer(
187             const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) = 0;
188 
189     /**
190      * Flush internal state. After this call, no index or buffer previously
191      * returned from registerBuffer() is valid.
192      */
193     virtual void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) = 0;
194 
195     /**
196      * Return array-backed version of output buffers. The returned object
197      * shall retain the internal state so that it will honor index and
198      * buffer from previous calls of registerBuffer().
199      */
200     virtual std::unique_ptr<OutputBuffers> toArrayMode(size_t size) = 0;
201 
202     /**
203      * Initialize SkipCutBuffer object.
204      */
205     void initSkipCutBuffer(
206             int32_t delay, int32_t padding, int32_t sampleRate, int32_t channelCount);
207 
208     /**
209      * Update the SkipCutBuffer object. No-op if it's never initialized.
210      */
211     void updateSkipCutBuffer(int32_t sampleRate, int32_t channelCount);
212 
213     /**
214      * Submit buffer to SkipCutBuffer object, if initialized.
215      */
216     void submit(const sp<MediaCodecBuffer> &buffer);
217 
218     /**
219      * Transfer SkipCutBuffer object to the other Buffers object.
220      */
221     void transferSkipCutBuffer(const sp<SkipCutBuffer> &scb);
222 
223 protected:
224     sp<SkipCutBuffer> mSkipCutBuffer;
225 
226 private:
227     int32_t mDelay;
228     int32_t mPadding;
229     int32_t mSampleRate;
230 
231     void setSkipCutBuffer(int32_t skip, int32_t cut, int32_t channelCount);
232 
233     DISALLOW_EVIL_CONSTRUCTORS(OutputBuffers);
234 };
235 
236 /**
237  * Simple local buffer pool backed by std::vector.
238  */
239 class LocalBufferPool : public std::enable_shared_from_this<LocalBufferPool> {
240 public:
241     /**
242      * Create a new LocalBufferPool object.
243      *
244      * \param poolCapacity  max total size of buffers managed by this pool.
245      *
246      * \return  a newly created pool object.
247      */
248     static std::shared_ptr<LocalBufferPool> Create(size_t poolCapacity);
249 
250     /**
251      * Return an ABuffer object whose size is at least |capacity|.
252      *
253      * \param   capacity  requested capacity
254      * \return  nullptr if the pool capacity is reached
255      *          an ABuffer object otherwise.
256      */
257     sp<ABuffer> newBuffer(size_t capacity);
258 
259 private:
260     /**
261      * ABuffer backed by std::vector.
262      */
263     class VectorBuffer : public ::android::ABuffer {
264     public:
265         /**
266          * Construct a VectorBuffer by taking the ownership of supplied vector.
267          *
268          * \param vec   backing vector of the buffer. this object takes
269          *              ownership at construction.
270          * \param pool  a LocalBufferPool object to return the vector at
271          *              destruction.
272          */
273         VectorBuffer(std::vector<uint8_t> &&vec, const std::shared_ptr<LocalBufferPool> &pool);
274 
275         ~VectorBuffer() override;
276 
277     private:
278         std::vector<uint8_t> mVec;
279         std::weak_ptr<LocalBufferPool> mPool;
280     };
281 
282     Mutex mMutex;
283     size_t mPoolCapacity;
284     size_t mUsedSize;
285     std::list<std::vector<uint8_t>> mPool;
286 
287     /**
288      * Private constructor to prevent constructing non-managed LocalBufferPool.
289      */
LocalBufferPool(size_t poolCapacity)290     explicit LocalBufferPool(size_t poolCapacity)
291         : mPoolCapacity(poolCapacity), mUsedSize(0) {
292     }
293 
294     /**
295      * Take back the ownership of vec from the destructed VectorBuffer and put
296      * it in front of the pool.
297      */
298     void returnVector(std::vector<uint8_t> &&vec);
299 
300     DISALLOW_EVIL_CONSTRUCTORS(LocalBufferPool);
301 };
302 
303 class BuffersArrayImpl;
304 
305 /**
306  * Flexible buffer slots implementation.
307  */
308 class FlexBuffersImpl {
309 public:
FlexBuffersImpl(const char * name)310     FlexBuffersImpl(const char *name)
311         : mImplName(std::string(name) + ".Impl"),
312           mName(mImplName.c_str()) { }
313 
314     /**
315      * Assign an empty slot for a buffer and return the index. If there's no
316      * empty slot, just add one at the end and return it.
317      *
318      * \param buffer[in]  a new buffer to assign a slot.
319      * \return            index of the assigned slot.
320      */
321     size_t assignSlot(const sp<Codec2Buffer> &buffer);
322 
323     /**
324      * Release the slot from the client, and get the C2Buffer object back from
325      * the previously assigned buffer. Note that the slot is not completely free
326      * until the returned C2Buffer object is freed.
327      *
328      * \param   buffer[in]        the buffer previously assigned a slot.
329      * \param   c2buffer[in,out]  pointer to C2Buffer to be populated. Ignored
330      *                            if null.
331      * \return  true  if the buffer is successfully released from a slot
332      *          false otherwise
333      */
334     bool releaseSlot(
335             const sp<MediaCodecBuffer> &buffer,
336             std::shared_ptr<C2Buffer> *c2buffer,
337             bool release);
338 
339     /**
340      * Expire the C2Buffer object in the slot.
341      *
342      * \param   c2buffer[in]  C2Buffer object which the component released.
343      * \return  true  if the buffer is found in one of the slots and
344      *                successfully released
345      *          false otherwise
346      */
347     bool expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer);
348 
349     /**
350      * The client abandoned all known buffers, so reclaim the ownership.
351      */
352     void flush();
353 
354     /**
355      * Return the number of buffers that are sent to the client but not released
356      * yet.
357      */
358     size_t numClientBuffers() const;
359 
360     /**
361      * Return the number of buffers that are sent to the component but not
362      * returned back yet.
363      */
364     size_t numComponentBuffers() const;
365 
366 private:
367     friend class BuffersArrayImpl;
368 
369     std::string mImplName; ///< name for debugging
370     const char *mName; ///< C-string version of name
371 
372     struct Entry {
373         sp<Codec2Buffer> clientBuffer;
374         std::weak_ptr<C2Buffer> compBuffer;
375     };
376     std::vector<Entry> mBuffers;
377 };
378 
379 /**
380  * Static buffer slots implementation based on a fixed-size array.
381  */
382 class BuffersArrayImpl {
383 public:
BuffersArrayImpl()384     BuffersArrayImpl()
385         : mImplName("BuffersArrayImpl"),
386           mName(mImplName.c_str()) { }
387 
388     /**
389      * Initialize buffer array from the original |impl|. The buffers known by
390      * the client is preserved, and the empty slots are populated so that the
391      * array size is at least |minSize|.
392      *
393      * \param impl[in]      FlexBuffersImpl object used so far.
394      * \param minSize[in]   minimum size of the buffer array.
395      * \param allocate[in]  function to allocate a client buffer for an empty slot.
396      */
397     void initialize(
398             const FlexBuffersImpl &impl,
399             size_t minSize,
400             std::function<sp<Codec2Buffer>()> allocate);
401 
402     /**
403      * Grab a buffer from the underlying array which matches the criteria.
404      *
405      * \param index[out]    index of the slot.
406      * \param buffer[out]   the matching buffer.
407      * \param match[in]     a function to test whether the buffer matches the
408      *                      criteria or not.
409      * \return OK           if successful,
410      *         WOULD_BLOCK  if slots are being used,
411      *         NO_MEMORY    if no slot matches the criteria, even though it's
412      *                      available
413      */
414     status_t grabBuffer(
415             size_t *index,
416             sp<Codec2Buffer> *buffer,
417             std::function<bool(const sp<Codec2Buffer> &)> match =
418                 [](const sp<Codec2Buffer> &) { return true; });
419 
420     /**
421      * Return the buffer from the client, and get the C2Buffer object back from
422      * the buffer. Note that the slot is not completely free until the returned
423      * C2Buffer object is freed.
424      *
425      * \param   buffer[in]        the buffer previously grabbed.
426      * \param   c2buffer[in,out]  pointer to C2Buffer to be populated. Ignored
427      *                            if null.
428      * \return  true  if the buffer is successfully returned
429      *          false otherwise
430      */
431     bool returnBuffer(
432             const sp<MediaCodecBuffer> &buffer,
433             std::shared_ptr<C2Buffer> *c2buffer,
434             bool release);
435 
436     /**
437      * Expire the C2Buffer object in the slot.
438      *
439      * \param   c2buffer[in]  C2Buffer object which the component released.
440      * \return  true  if the buffer is found in one of the slots and
441      *                successfully released
442      *          false otherwise
443      */
444     bool expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer);
445 
446     /**
447      * Populate |array| with the underlying buffer array.
448      *
449      * \param array[out]  an array to be filled with the underlying buffer array.
450      */
451     void getArray(Vector<sp<MediaCodecBuffer>> *array) const;
452 
453     /**
454      * The client abandoned all known buffers, so reclaim the ownership.
455      */
456     void flush();
457 
458     /**
459      * Reallocate the array with the given allocation function.
460      *
461      * \param alloc[in] the allocation function for client buffers.
462      */
463     void realloc(std::function<sp<Codec2Buffer>()> alloc);
464 
465     /**
466      * Grow the array to the new size. It is a programming error to supply
467      * smaller size as the new size.
468      *
469      * \param newSize[in] new size of the array.
470      * \param alloc[in]   the alllocation function for client buffers to fill
471      *                    the new empty slots.
472      */
473     void grow(size_t newSize, std::function<sp<Codec2Buffer>()> alloc);
474 
475     /**
476      * Return the number of buffers that are sent to the client but not released
477      * yet.
478      */
479     size_t numClientBuffers() const;
480 
481     /**
482      * Return the size of the array.
483      */
484     size_t arraySize() const;
485 
486 private:
487     std::string mImplName; ///< name for debugging
488     const char *mName; ///< C-string version of name
489 
490     struct Entry {
491         const sp<Codec2Buffer> clientBuffer;
492         std::weak_ptr<C2Buffer> compBuffer;
493         bool ownedByClient;
494     };
495     std::vector<Entry> mBuffers;
496 };
497 
498 class InputBuffersArray : public InputBuffers {
499 public:
500     InputBuffersArray(const char *componentName, const char *name = "Input[N]")
InputBuffers(componentName,name)501         : InputBuffers(componentName, name) { }
502     ~InputBuffersArray() override = default;
503 
504     /**
505      * Initialize this object from the non-array state. We keep existing slots
506      * at the same index, and for empty slots we allocate client buffers with
507      * the given allocate function. If the number of slots is less than minSize,
508      * we fill the array to the minimum size.
509      *
510      * \param impl[in]      existing non-array state
511      * \param minSize[in]   minimum size of the array
512      * \param allocate[in]  allocate function to fill empty slots
513      */
514     void initialize(
515             const FlexBuffersImpl &impl,
516             size_t minSize,
517             std::function<sp<Codec2Buffer>()> allocate);
518 
isArrayMode()519     bool isArrayMode() const final { return true; }
520 
toArrayMode(size_t)521     std::unique_ptr<InputBuffers> toArrayMode(size_t) final {
522         return nullptr;
523     }
524 
525     void getArray(Vector<sp<MediaCodecBuffer>> *array) const final;
526 
527     bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override;
528 
529     bool releaseBuffer(
530             const sp<MediaCodecBuffer> &buffer,
531             std::shared_ptr<C2Buffer> *c2buffer,
532             bool release) override;
533 
534     bool expireComponentBuffer(
535             const std::shared_ptr<C2Buffer> &c2buffer) override;
536 
537     void flush() override;
538 
539     size_t numClientBuffers() const final;
540 
541 protected:
542     sp<Codec2Buffer> createNewBuffer() override;
543 
544 private:
545     BuffersArrayImpl mImpl;
546     std::function<sp<Codec2Buffer>()> mAllocate;
547 };
548 
549 class LinearInputBuffers : public InputBuffers {
550 public:
551     LinearInputBuffers(const char *componentName, const char *name = "1D-Input")
InputBuffers(componentName,name)552         : InputBuffers(componentName, name),
553           mImpl(mName) { }
554     ~LinearInputBuffers() override = default;
555 
556     bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override;
557 
558     bool releaseBuffer(
559             const sp<MediaCodecBuffer> &buffer,
560             std::shared_ptr<C2Buffer> *c2buffer,
561             bool release) override;
562 
563     bool expireComponentBuffer(
564             const std::shared_ptr<C2Buffer> &c2buffer) override;
565 
566     void flush() override;
567 
568     std::unique_ptr<InputBuffers> toArrayMode(size_t size) override;
569 
570     size_t numClientBuffers() const final;
571 
572 protected:
573     sp<Codec2Buffer> createNewBuffer() override;
574 
575     FlexBuffersImpl mImpl;
576 
577 private:
578     static sp<Codec2Buffer> Alloc(
579             const std::shared_ptr<C2BlockPool> &pool, const sp<AMessage> &format);
580 };
581 
582 class EncryptedLinearInputBuffers : public LinearInputBuffers {
583 public:
584     EncryptedLinearInputBuffers(
585             bool secure,
586             const sp<MemoryDealer> &dealer,
587             const sp<ICrypto> &crypto,
588             int32_t heapSeqNum,
589             size_t capacity,
590             size_t numInputSlots,
591             const char *componentName, const char *name = "EncryptedInput");
592 
593     ~EncryptedLinearInputBuffers() override = default;
594 
595     std::unique_ptr<InputBuffers> toArrayMode(size_t size) override;
596 
597 protected:
598     sp<Codec2Buffer> createNewBuffer() override;
599 
600 private:
601     struct Entry {
602         std::weak_ptr<C2LinearBlock> block;
603         sp<IMemory> memory;
604         int32_t heapSeqNum;
605     };
606 
607     static sp<Codec2Buffer> Alloc(
608             const std::shared_ptr<C2BlockPool> &pool,
609             const sp<AMessage> &format,
610             C2MemoryUsage usage,
611             const std::shared_ptr<std::vector<Entry>> &memoryVector);
612 
613     C2MemoryUsage mUsage;
614     sp<MemoryDealer> mDealer;
615     sp<ICrypto> mCrypto;
616     std::shared_ptr<std::vector<Entry>> mMemoryVector;
617 };
618 
619 class GraphicMetadataInputBuffers : public InputBuffers {
620 public:
621     GraphicMetadataInputBuffers(const char *componentName, const char *name = "2D-MetaInput");
622     ~GraphicMetadataInputBuffers() override = default;
623 
624     bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override;
625 
626     bool releaseBuffer(
627             const sp<MediaCodecBuffer> &buffer,
628             std::shared_ptr<C2Buffer> *c2buffer,
629             bool release) override;
630 
631     bool expireComponentBuffer(
632             const std::shared_ptr<C2Buffer> &c2buffer) override;
633 
634     void flush() override;
635 
636     std::unique_ptr<InputBuffers> toArrayMode(size_t size) final;
637 
638     size_t numClientBuffers() const final;
639 
640 protected:
641     sp<Codec2Buffer> createNewBuffer() override;
642 
643 private:
644     FlexBuffersImpl mImpl;
645     std::shared_ptr<C2AllocatorStore> mStore;
646 };
647 
648 class GraphicInputBuffers : public InputBuffers {
649 public:
650     GraphicInputBuffers(
651             size_t numInputSlots, const char *componentName, const char *name = "2D-BB-Input");
652     ~GraphicInputBuffers() override = default;
653 
654     bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override;
655 
656     bool releaseBuffer(
657             const sp<MediaCodecBuffer> &buffer,
658             std::shared_ptr<C2Buffer> *c2buffer,
659             bool release) override;
660 
661     bool expireComponentBuffer(
662             const std::shared_ptr<C2Buffer> &c2buffer) override;
663 
664     void flush() override;
665 
666     std::unique_ptr<InputBuffers> toArrayMode(
667             size_t size) final;
668 
669     size_t numClientBuffers() const final;
670 
671 protected:
672     sp<Codec2Buffer> createNewBuffer() override;
673 
674 private:
675     FlexBuffersImpl mImpl;
676     std::shared_ptr<LocalBufferPool> mLocalBufferPool;
677 };
678 
679 class DummyInputBuffers : public InputBuffers {
680 public:
681     DummyInputBuffers(const char *componentName, const char *name = "2D-Input")
InputBuffers(componentName,name)682         : InputBuffers(componentName, name) { }
683     ~DummyInputBuffers() override = default;
684 
requestNewBuffer(size_t *,sp<MediaCodecBuffer> *)685     bool requestNewBuffer(size_t *, sp<MediaCodecBuffer> *) override {
686         return false;
687     }
688 
releaseBuffer(const sp<MediaCodecBuffer> &,std::shared_ptr<C2Buffer> *,bool)689     bool releaseBuffer(
690             const sp<MediaCodecBuffer> &, std::shared_ptr<C2Buffer> *, bool) override {
691         return false;
692     }
693 
expireComponentBuffer(const std::shared_ptr<C2Buffer> &)694     bool expireComponentBuffer(const std::shared_ptr<C2Buffer> &) override {
695         return false;
696     }
flush()697     void flush() override {
698     }
699 
toArrayMode(size_t)700     std::unique_ptr<InputBuffers> toArrayMode(size_t) final {
701         return nullptr;
702     }
703 
isArrayMode()704     bool isArrayMode() const final { return true; }
705 
getArray(Vector<sp<MediaCodecBuffer>> * array)706     void getArray(Vector<sp<MediaCodecBuffer>> *array) const final {
707         array->clear();
708     }
709 
numClientBuffers()710     size_t numClientBuffers() const final {
711         return 0u;
712     }
713 
714 protected:
createNewBuffer()715     sp<Codec2Buffer> createNewBuffer() override {
716         return nullptr;
717     }
718 };
719 
720 class OutputBuffersArray : public OutputBuffers {
721 public:
722     OutputBuffersArray(const char *componentName, const char *name = "Output[N]")
OutputBuffers(componentName,name)723         : OutputBuffers(componentName, name) { }
724     ~OutputBuffersArray() override = default;
725 
726     /**
727      * Initialize this object from the non-array state. We keep existing slots
728      * at the same index, and for empty slots we allocate client buffers with
729      * the given allocate function. If the number of slots is less than minSize,
730      * we fill the array to the minimum size.
731      *
732      * \param impl[in]      existing non-array state
733      * \param minSize[in]   minimum size of the array
734      * \param allocate[in]  allocate function to fill empty slots
735      */
736     void initialize(
737             const FlexBuffersImpl &impl,
738             size_t minSize,
739             std::function<sp<Codec2Buffer>()> allocate);
740 
isArrayMode()741     bool isArrayMode() const final { return true; }
742 
toArrayMode(size_t)743     std::unique_ptr<OutputBuffers> toArrayMode(size_t) final {
744         return nullptr;
745     }
746 
747     status_t registerBuffer(
748             const std::shared_ptr<C2Buffer> &buffer,
749             size_t *index,
750             sp<MediaCodecBuffer> *clientBuffer) final;
751 
752     status_t registerCsd(
753             const C2StreamInitDataInfo::output *csd,
754             size_t *index,
755             sp<MediaCodecBuffer> *clientBuffer) final;
756 
757     bool releaseBuffer(
758             const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) override;
759 
760     void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) override;
761 
762     void getArray(Vector<sp<MediaCodecBuffer>> *array) const final;
763 
764     size_t numClientBuffers() const final;
765 
766     /**
767      * Reallocate the array, filled with buffers with the same size as given
768      * buffer.
769      *
770      * \param c2buffer[in] the reference buffer
771      */
772     void realloc(const std::shared_ptr<C2Buffer> &c2buffer);
773 
774     /**
775      * Grow the array to the new size. It is a programming error to supply
776      * smaller size as the new size.
777      *
778      * \param newSize[in] new size of the array.
779      */
780     void grow(size_t newSize);
781 
782 private:
783     BuffersArrayImpl mImpl;
784     std::function<sp<Codec2Buffer>()> mAlloc;
785 };
786 
787 class FlexOutputBuffers : public OutputBuffers {
788 public:
789     FlexOutputBuffers(const char *componentName, const char *name = "Output[]")
OutputBuffers(componentName,name)790         : OutputBuffers(componentName, name),
791           mImpl(mName) { }
792 
793     status_t registerBuffer(
794             const std::shared_ptr<C2Buffer> &buffer,
795             size_t *index,
796             sp<MediaCodecBuffer> *clientBuffer) override;
797 
798     status_t registerCsd(
799             const C2StreamInitDataInfo::output *csd,
800             size_t *index,
801             sp<MediaCodecBuffer> *clientBuffer) final;
802 
803     bool releaseBuffer(
804             const sp<MediaCodecBuffer> &buffer,
805             std::shared_ptr<C2Buffer> *c2buffer) override;
806 
807     void flush(
808             const std::list<std::unique_ptr<C2Work>> &flushedWork) override;
809 
810     std::unique_ptr<OutputBuffers> toArrayMode(size_t size) override;
811 
812     size_t numClientBuffers() const final;
813 
814     /**
815      * Return an appropriate Codec2Buffer object for the type of buffers.
816      *
817      * \param buffer  C2Buffer object to wrap.
818      *
819      * \return  appropriate Codec2Buffer object to wrap |buffer|.
820      */
821     virtual sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) = 0;
822 
823     /**
824      * Return a function that allocates an appropriate Codec2Buffer object for
825      * the type of buffers, to be used as an empty array buffer. The function
826      * must not refer to this pointer, since it may be used after this object
827      * destructs.
828      *
829      * \return  a function that allocates appropriate Codec2Buffer object,
830      *          which can copy() from C2Buffers.
831      */
832     virtual std::function<sp<Codec2Buffer>()> getAlloc() = 0;
833 
834 private:
835     FlexBuffersImpl mImpl;
836 };
837 
838 class LinearOutputBuffers : public FlexOutputBuffers {
839 public:
840     LinearOutputBuffers(const char *componentName, const char *name = "1D-Output")
FlexOutputBuffers(componentName,name)841         : FlexOutputBuffers(componentName, name) { }
842 
843     void flush(
844             const std::list<std::unique_ptr<C2Work>> &flushedWork) override;
845 
846     sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override;
847 
848     std::function<sp<Codec2Buffer>()> getAlloc() override;
849 };
850 
851 class GraphicOutputBuffers : public FlexOutputBuffers {
852 public:
853     GraphicOutputBuffers(const char *componentName, const char *name = "2D-Output")
FlexOutputBuffers(componentName,name)854         : FlexOutputBuffers(componentName, name) { }
855 
856     sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override;
857 
858     std::function<sp<Codec2Buffer>()> getAlloc() override;
859 };
860 
861 class RawGraphicOutputBuffers : public FlexOutputBuffers {
862 public:
863     RawGraphicOutputBuffers(
864             size_t numOutputSlots, const char *componentName, const char *name = "2D-BB-Output");
865     ~RawGraphicOutputBuffers() override = default;
866 
867     sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override;
868 
869     std::function<sp<Codec2Buffer>()> getAlloc() override;
870 
871 private:
872     std::shared_ptr<LocalBufferPool> mLocalBufferPool;
873 };
874 
875 }  // namespace android
876 
877 #endif  // CCODEC_BUFFERS_H_
878