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