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