blob: 0d4fa8117cbdf262fd39a026241b8946e623ba36 [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 */
75 virtual size_t numClientBuffers() const = 0;
76
77 /**
78 * Examine image data from the buffer and update the format if necessary.
79 */
80 void handleImageData(const sp<Codec2Buffer> &buffer);
81
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.
218 * @p notify determines whether the format comes with a buffer that should
219 * be reported to the client or not.
220 */
221 void updateSkipCutBuffer(const sp<AMessage> &format, bool notify = true);
222
223 /**
224 * Output Stash
225 * ============
226 *
227 * The output stash is a place to hold output buffers temporarily before
228 * they are registered to output slots. It has 2 main functions:
229 * 1. Allow reordering of output frames as the codec may produce frames in a
230 * different order.
231 * 2. Act as a "buffer" between the codec and the client because the codec
232 * may produce more buffers than available slots. This excess of codec's
233 * output buffers should be registered to slots later, after the client
234 * has released some slots.
235 *
236 * The stash consists of 2 lists of buffers: mPending and mReorderStash.
237 * mPending is a normal FIFO queue with not size limit, while mReorderStash
238 * is a sorted list with size limit mDepth.
239 *
240 * The normal flow of a non-csd output buffer is as follows:
241 *
242 * |----------------OutputBuffers---------------|
243 * |----------Output stash----------| |
244 * Codec --|-> mReorderStash --> mPending --|-> slots --|-> client
245 * | | |
246 * pushToStash() popFromStashAndRegister()
247 *
248 * The buffer that comes from the codec first enters mReorderStash. The
249 * first buffer in mReorderStash gets moved to mPending when mReorderStash
250 * overflows. Buffers in mPending are registered to slots and given to the
251 * client as soon as slots are available.
252 *
253 * Every output buffer that is not a csd buffer should be put on the stash
254 * by calling pushToStash(), then later registered to a slot by calling
255 * popFromStashAndRegister() before notifying the client with
256 * onOutputBufferAvailable().
257 *
258 * Reordering
259 * ==========
260 *
261 * mReorderStash is a sorted list with a specified size limit. The size
262 * limit can be set by calling setReorderDepth().
263 *
264 * Every buffer in mReorderStash has a C2WorkOrdinalStruct, which contains 3
265 * members, all of which are comparable. Which member of C2WorkOrdinalStruct
266 * should be used for reordering can be chosen by calling setReorderKey().
267 */
268
269 /**
270 * Return the reorder depth---the size of mReorderStash.
271 */
272 uint32_t getReorderDepth() const;
273
274 /**
275 * Set the reorder depth.
276 */
277 void setReorderDepth(uint32_t depth);
278
279 /**
280 * Set the type of "key" to use in comparisons.
281 */
282 void setReorderKey(C2Config::ordinal_key_t key);
283
284 /**
285 * Return whether the output stash has any pending buffers.
286 */
287 bool hasPending() const;
288
289 /**
290 * Flush the stash and reset the depth and the key to their default values.
291 */
292 void clearStash();
293
294 /**
295 * Flush the stash.
296 */
297 void flushStash();
298
299 /**
300 * Push a buffer to the reorder stash.
301 *
302 * @param buffer C2Buffer object from the returned work.
303 * @param notify Whether the returned work contains a buffer that should
304 * be reported to the client. This may be false if the
305 * caller wants to process the buffer without notifying the
306 * client.
307 * @param timestamp Buffer timestamp to report to the client.
308 * @param flags Buffer flags to report to the client.
309 * @param format Buffer format to report to the client.
310 * @param ordinal Ordinal used in reordering. This determines when the
311 * buffer will be popped from the output stash by
312 * `popFromStashAndRegister()`.
313 */
314 void pushToStash(
315 const std::shared_ptr<C2Buffer>& buffer,
316 bool notify,
317 int64_t timestamp,
318 int32_t flags,
319 const sp<AMessage>& format,
320 const C2WorkOrdinalStruct& ordinal);
321
322 enum BufferAction : int {
323 SKIP,
324 DISCARD,
325 NOTIFY_CLIENT,
326 REALLOCATE,
327 RETRY,
328 };
329
330 /**
331 * Try to atomically pop the first buffer from the reorder stash and
332 * register it to an output slot. The function returns a value that
333 * indicates a recommended course of action for the caller.
334 *
335 * If the stash is empty, the function will return `SKIP`.
336 *
337 * If the stash is not empty, the function will peek at the first (oldest)
338 * entry in mPending process the buffer in the entry as follows:
339 * - If the buffer should not be sent to the client, the function will
340 * return `DISCARD`. The stash entry will be removed.
341 * - If the buffer should be sent to the client, the function will attempt
342 * to register the buffer to a slot. The registration may have 3 outcomes
343 * corresponding to the following return values:
344 * - `NOTIFY_CLIENT`: The buffer is successfully registered to a slot. The
345 * output arguments @p index and @p outBuffer will contain valid values
346 * that the caller can use to call onOutputBufferAvailable(). The stash
347 * entry will be removed.
348 * - `REALLOCATE`: The buffer is not registered because it is not
349 * compatible with the current slots (which are available). The caller
350 * should reallocate the OutputBuffers with slots that can fit the
351 * returned @p c2Buffer. The stash entry will not be removed
352 * - `RETRY`: All slots are currently occupied by the client. The caller
353 * should try to call this function again after the client has released
354 * some slots.
355 *
356 * @return What the caller should do afterwards.
357 *
358 * @param[out] c2Buffer Underlying C2Buffer associated to the first buffer
359 * on the stash. This value is guaranteed to be valid
360 * unless the return value is `SKIP`.
361 * @param[out] index Slot index. This value is valid only if the return
362 * value is `NOTIFY_CLIENT`.
363 * @param[out] outBuffer Registered buffer. This value is valid only if the
364 * return valu is `NOTIFY_CLIENT`.
365 */
366 BufferAction popFromStashAndRegister(
367 std::shared_ptr<C2Buffer>* c2Buffer,
368 size_t* index,
369 sp<MediaCodecBuffer>* outBuffer);
370
371protected:
372 sp<SkipCutBuffer> mSkipCutBuffer;
373
374 /**
Wonsik Kim469c8342019-04-11 16:46:09 -0700375 * Update the SkipCutBuffer object. No-op if it's never initialized.
376 */
377 void updateSkipCutBuffer(int32_t sampleRate, int32_t channelCount);
378
379 /**
380 * Submit buffer to SkipCutBuffer object, if initialized.
381 */
382 void submit(const sp<MediaCodecBuffer> &buffer);
383
Wonsik Kim469c8342019-04-11 16:46:09 -0700384private:
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700385 // SkipCutBuffer
Wonsik Kim469c8342019-04-11 16:46:09 -0700386 int32_t mDelay;
387 int32_t mPadding;
388 int32_t mSampleRate;
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700389 int32_t mChannelCount;
Wonsik Kim469c8342019-04-11 16:46:09 -0700390
Wonsik Kim40b0b1d2020-03-25 15:47:35 -0700391 void setSkipCutBuffer(int32_t skip, int32_t cut);
Wonsik Kim469c8342019-04-11 16:46:09 -0700392
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700393 // Output stash
394
395 // Output format that has not been made available to the client.
396 sp<AMessage> mUnreportedFormat;
397
398 // Struct for an entry in the output stash (mPending and mReorderStash)
399 struct StashEntry {
400 inline StashEntry()
401 : buffer(nullptr),
402 notify(false),
403 timestamp(0),
404 flags(0),
405 format(),
406 ordinal({0, 0, 0}) {}
407 inline StashEntry(
408 const std::shared_ptr<C2Buffer> &b,
409 bool n,
410 int64_t t,
411 int32_t f,
412 const sp<AMessage> &fmt,
413 const C2WorkOrdinalStruct &o)
414 : buffer(b),
415 notify(n),
416 timestamp(t),
417 flags(f),
418 format(fmt),
419 ordinal(o) {}
420 std::shared_ptr<C2Buffer> buffer;
421 bool notify;
422 int64_t timestamp;
423 int32_t flags;
424 sp<AMessage> format;
425 C2WorkOrdinalStruct ordinal;
426 };
427
428 /**
429 * FIFO queue of stash entries.
430 */
431 std::list<StashEntry> mPending;
432 /**
433 * Sorted list of stash entries.
434 */
435 std::list<StashEntry> mReorderStash;
436 /**
437 * Size limit of mReorderStash.
438 */
439 uint32_t mDepth{0};
440 /**
441 * Choice of key to use in ordering of stash entries in mReorderStash.
442 */
443 C2Config::ordinal_key_t mKey{C2Config::ORDINAL};
444
445 /**
446 * Return false if mPending is empty; otherwise, pop the first entry from
447 * mPending and return true.
448 */
449 bool popPending(StashEntry *entry);
450
451 /**
452 * Push an entry as the first entry of mPending.
453 */
454 void deferPending(const StashEntry &entry);
455
456 /**
457 * Comparison of C2WorkOrdinalStruct based on mKey.
458 */
459 bool less(const C2WorkOrdinalStruct &o1,
460 const C2WorkOrdinalStruct &o2) const;
461
Wonsik Kim469c8342019-04-11 16:46:09 -0700462 DISALLOW_EVIL_CONSTRUCTORS(OutputBuffers);
Pawin Vongmasa9b906982020-04-11 05:07:15 -0700463
464 friend OutputBuffersArray;
Wonsik Kim469c8342019-04-11 16:46:09 -0700465};
466
467/**
468 * Simple local buffer pool backed by std::vector.
469 */
470class LocalBufferPool : public std::enable_shared_from_this<LocalBufferPool> {
471public:
472 /**
473 * Create a new LocalBufferPool object.
474 *
Wonsik Kim469c8342019-04-11 16:46:09 -0700475 * \return a newly created pool object.
476 */
Wonsik Kim41d83432020-04-27 16:40:49 -0700477 static std::shared_ptr<LocalBufferPool> Create();
Wonsik Kim469c8342019-04-11 16:46:09 -0700478
479 /**
480 * Return an ABuffer object whose size is at least |capacity|.
481 *
482 * \param capacity requested capacity
483 * \return nullptr if the pool capacity is reached
484 * an ABuffer object otherwise.
485 */
486 sp<ABuffer> newBuffer(size_t capacity);
487
488private:
489 /**
490 * ABuffer backed by std::vector.
491 */
492 class VectorBuffer : public ::android::ABuffer {
493 public:
494 /**
495 * Construct a VectorBuffer by taking the ownership of supplied vector.
496 *
497 * \param vec backing vector of the buffer. this object takes
498 * ownership at construction.
499 * \param pool a LocalBufferPool object to return the vector at
500 * destruction.
501 */
502 VectorBuffer(std::vector<uint8_t> &&vec, const std::shared_ptr<LocalBufferPool> &pool);
503
504 ~VectorBuffer() override;
505
506 private:
507 std::vector<uint8_t> mVec;
508 std::weak_ptr<LocalBufferPool> mPool;
509 };
510
511 Mutex mMutex;
512 size_t mPoolCapacity;
513 size_t mUsedSize;
514 std::list<std::vector<uint8_t>> mPool;
515
516 /**
517 * Private constructor to prevent constructing non-managed LocalBufferPool.
518 */
519 explicit LocalBufferPool(size_t poolCapacity)
520 : mPoolCapacity(poolCapacity), mUsedSize(0) {
521 }
522
523 /**
524 * Take back the ownership of vec from the destructed VectorBuffer and put
525 * it in front of the pool.
526 */
527 void returnVector(std::vector<uint8_t> &&vec);
528
529 DISALLOW_EVIL_CONSTRUCTORS(LocalBufferPool);
530};
531
532class BuffersArrayImpl;
533
534/**
535 * Flexible buffer slots implementation.
536 */
537class FlexBuffersImpl {
538public:
539 FlexBuffersImpl(const char *name)
540 : mImplName(std::string(name) + ".Impl"),
541 mName(mImplName.c_str()) { }
542
543 /**
544 * Assign an empty slot for a buffer and return the index. If there's no
545 * empty slot, just add one at the end and return it.
546 *
547 * \param buffer[in] a new buffer to assign a slot.
548 * \return index of the assigned slot.
549 */
550 size_t assignSlot(const sp<Codec2Buffer> &buffer);
551
552 /**
553 * Release the slot from the client, and get the C2Buffer object back from
554 * the previously assigned buffer. Note that the slot is not completely free
555 * until the returned C2Buffer object is freed.
556 *
557 * \param buffer[in] the buffer previously assigned a slot.
558 * \param c2buffer[in,out] pointer to C2Buffer to be populated. Ignored
559 * if null.
560 * \return true if the buffer is successfully released from a slot
561 * false otherwise
562 */
563 bool releaseSlot(
564 const sp<MediaCodecBuffer> &buffer,
565 std::shared_ptr<C2Buffer> *c2buffer,
566 bool release);
567
568 /**
569 * Expire the C2Buffer object in the slot.
570 *
571 * \param c2buffer[in] C2Buffer object which the component released.
572 * \return true if the buffer is found in one of the slots and
573 * successfully released
574 * false otherwise
575 */
576 bool expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer);
577
578 /**
579 * The client abandoned all known buffers, so reclaim the ownership.
580 */
581 void flush();
582
583 /**
584 * Return the number of buffers that are sent to the client but not released
585 * yet.
586 */
587 size_t numClientBuffers() const;
588
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700589 /**
590 * Return the number of buffers that are sent to the component but not
591 * returned back yet.
592 */
593 size_t numComponentBuffers() const;
594
Wonsik Kim469c8342019-04-11 16:46:09 -0700595private:
596 friend class BuffersArrayImpl;
597
598 std::string mImplName; ///< name for debugging
599 const char *mName; ///< C-string version of name
600
601 struct Entry {
602 sp<Codec2Buffer> clientBuffer;
603 std::weak_ptr<C2Buffer> compBuffer;
604 };
605 std::vector<Entry> mBuffers;
606};
607
608/**
609 * Static buffer slots implementation based on a fixed-size array.
610 */
611class BuffersArrayImpl {
612public:
613 BuffersArrayImpl()
614 : mImplName("BuffersArrayImpl"),
615 mName(mImplName.c_str()) { }
616
617 /**
618 * Initialize buffer array from the original |impl|. The buffers known by
619 * the client is preserved, and the empty slots are populated so that the
620 * array size is at least |minSize|.
621 *
622 * \param impl[in] FlexBuffersImpl object used so far.
623 * \param minSize[in] minimum size of the buffer array.
624 * \param allocate[in] function to allocate a client buffer for an empty slot.
625 */
626 void initialize(
627 const FlexBuffersImpl &impl,
628 size_t minSize,
629 std::function<sp<Codec2Buffer>()> allocate);
630
631 /**
632 * Grab a buffer from the underlying array which matches the criteria.
633 *
634 * \param index[out] index of the slot.
635 * \param buffer[out] the matching buffer.
636 * \param match[in] a function to test whether the buffer matches the
637 * criteria or not.
638 * \return OK if successful,
639 * WOULD_BLOCK if slots are being used,
640 * NO_MEMORY if no slot matches the criteria, even though it's
641 * available
642 */
643 status_t grabBuffer(
644 size_t *index,
645 sp<Codec2Buffer> *buffer,
646 std::function<bool(const sp<Codec2Buffer> &)> match =
Wonsik Kim936a89c2020-05-08 16:07:50 -0700647 [](const sp<Codec2Buffer> &buffer) { return (buffer != nullptr); });
Wonsik Kim469c8342019-04-11 16:46:09 -0700648
649 /**
650 * Return the buffer from the client, and get the C2Buffer object back from
651 * the buffer. Note that the slot is not completely free until the returned
652 * C2Buffer object is freed.
653 *
654 * \param buffer[in] the buffer previously grabbed.
655 * \param c2buffer[in,out] pointer to C2Buffer to be populated. Ignored
656 * if null.
657 * \return true if the buffer is successfully returned
658 * false otherwise
659 */
660 bool returnBuffer(
661 const sp<MediaCodecBuffer> &buffer,
662 std::shared_ptr<C2Buffer> *c2buffer,
663 bool release);
664
665 /**
666 * Expire the C2Buffer object in the slot.
667 *
668 * \param c2buffer[in] C2Buffer object which the component released.
669 * \return true if the buffer is found in one of the slots and
670 * successfully released
671 * false otherwise
672 */
673 bool expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer);
674
675 /**
676 * Populate |array| with the underlying buffer array.
677 *
678 * \param array[out] an array to be filled with the underlying buffer array.
679 */
680 void getArray(Vector<sp<MediaCodecBuffer>> *array) const;
681
682 /**
683 * The client abandoned all known buffers, so reclaim the ownership.
684 */
685 void flush();
686
687 /**
688 * Reallocate the array with the given allocation function.
689 *
690 * \param alloc[in] the allocation function for client buffers.
691 */
692 void realloc(std::function<sp<Codec2Buffer>()> alloc);
693
694 /**
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700695 * Grow the array to the new size. It is a programming error to supply
696 * smaller size as the new size.
697 *
698 * \param newSize[in] new size of the array.
699 * \param alloc[in] the alllocation function for client buffers to fill
700 * the new empty slots.
701 */
702 void grow(size_t newSize, std::function<sp<Codec2Buffer>()> alloc);
703
704 /**
Wonsik Kim469c8342019-04-11 16:46:09 -0700705 * Return the number of buffers that are sent to the client but not released
706 * yet.
707 */
708 size_t numClientBuffers() const;
709
Wonsik Kima39882b2019-06-20 16:13:56 -0700710 /**
711 * Return the size of the array.
712 */
713 size_t arraySize() const;
714
Wonsik Kim469c8342019-04-11 16:46:09 -0700715private:
716 std::string mImplName; ///< name for debugging
717 const char *mName; ///< C-string version of name
718
719 struct Entry {
720 const sp<Codec2Buffer> clientBuffer;
721 std::weak_ptr<C2Buffer> compBuffer;
722 bool ownedByClient;
723 };
724 std::vector<Entry> mBuffers;
725};
726
727class InputBuffersArray : public InputBuffers {
728public:
729 InputBuffersArray(const char *componentName, const char *name = "Input[N]")
730 : InputBuffers(componentName, name) { }
731 ~InputBuffersArray() override = default;
732
733 /**
734 * Initialize this object from the non-array state. We keep existing slots
735 * at the same index, and for empty slots we allocate client buffers with
736 * the given allocate function. If the number of slots is less than minSize,
737 * we fill the array to the minimum size.
738 *
739 * \param impl[in] existing non-array state
740 * \param minSize[in] minimum size of the array
741 * \param allocate[in] allocate function to fill empty slots
742 */
743 void initialize(
744 const FlexBuffersImpl &impl,
745 size_t minSize,
746 std::function<sp<Codec2Buffer>()> allocate);
747
748 bool isArrayMode() const final { return true; }
749
750 std::unique_ptr<InputBuffers> toArrayMode(size_t) final {
751 return nullptr;
752 }
753
754 void getArray(Vector<sp<MediaCodecBuffer>> *array) const final;
755
756 bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override;
757
758 bool releaseBuffer(
759 const sp<MediaCodecBuffer> &buffer,
760 std::shared_ptr<C2Buffer> *c2buffer,
761 bool release) override;
762
763 bool expireComponentBuffer(
764 const std::shared_ptr<C2Buffer> &c2buffer) override;
765
766 void flush() override;
767
768 size_t numClientBuffers() const final;
769
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700770protected:
771 sp<Codec2Buffer> createNewBuffer() override;
772
Wonsik Kim469c8342019-04-11 16:46:09 -0700773private:
774 BuffersArrayImpl mImpl;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700775 std::function<sp<Codec2Buffer>()> mAllocate;
Wonsik Kim469c8342019-04-11 16:46:09 -0700776};
777
Wonsik Kimfb7a7672019-12-27 17:13:33 -0800778class SlotInputBuffers : public InputBuffers {
779public:
780 SlotInputBuffers(const char *componentName, const char *name = "Slot-Input")
781 : InputBuffers(componentName, name),
782 mImpl(mName) { }
783 ~SlotInputBuffers() override = default;
784
785 bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) final;
786
787 bool releaseBuffer(
788 const sp<MediaCodecBuffer> &buffer,
789 std::shared_ptr<C2Buffer> *c2buffer,
790 bool release) final;
791
792 bool expireComponentBuffer(
793 const std::shared_ptr<C2Buffer> &c2buffer) final;
794
795 void flush() final;
796
797 std::unique_ptr<InputBuffers> toArrayMode(size_t size) final;
798
799 size_t numClientBuffers() const final;
800
801protected:
802 sp<Codec2Buffer> createNewBuffer() final;
803
804private:
805 FlexBuffersImpl mImpl;
806};
807
Wonsik Kim469c8342019-04-11 16:46:09 -0700808class LinearInputBuffers : public InputBuffers {
809public:
810 LinearInputBuffers(const char *componentName, const char *name = "1D-Input")
811 : InputBuffers(componentName, name),
812 mImpl(mName) { }
813 ~LinearInputBuffers() override = default;
814
815 bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override;
816
817 bool releaseBuffer(
818 const sp<MediaCodecBuffer> &buffer,
819 std::shared_ptr<C2Buffer> *c2buffer,
820 bool release) override;
821
822 bool expireComponentBuffer(
823 const std::shared_ptr<C2Buffer> &c2buffer) override;
824
825 void flush() override;
826
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700827 std::unique_ptr<InputBuffers> toArrayMode(size_t size) override;
Wonsik Kim469c8342019-04-11 16:46:09 -0700828
829 size_t numClientBuffers() const final;
830
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700831protected:
832 sp<Codec2Buffer> createNewBuffer() override;
833
834 FlexBuffersImpl mImpl;
Wonsik Kim469c8342019-04-11 16:46:09 -0700835
836private:
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700837 static sp<Codec2Buffer> Alloc(
838 const std::shared_ptr<C2BlockPool> &pool, const sp<AMessage> &format);
Wonsik Kim469c8342019-04-11 16:46:09 -0700839};
840
841class EncryptedLinearInputBuffers : public LinearInputBuffers {
842public:
843 EncryptedLinearInputBuffers(
844 bool secure,
845 const sp<MemoryDealer> &dealer,
846 const sp<ICrypto> &crypto,
847 int32_t heapSeqNum,
848 size_t capacity,
849 size_t numInputSlots,
850 const char *componentName, const char *name = "EncryptedInput");
851
852 ~EncryptedLinearInputBuffers() override = default;
853
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700854 std::unique_ptr<InputBuffers> toArrayMode(size_t size) override;
855
856protected:
857 sp<Codec2Buffer> createNewBuffer() override;
Wonsik Kim469c8342019-04-11 16:46:09 -0700858
859private:
Wonsik Kim469c8342019-04-11 16:46:09 -0700860 struct Entry {
861 std::weak_ptr<C2LinearBlock> block;
862 sp<IMemory> memory;
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700863 int32_t heapSeqNum;
Wonsik Kim469c8342019-04-11 16:46:09 -0700864 };
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700865
866 static sp<Codec2Buffer> Alloc(
867 const std::shared_ptr<C2BlockPool> &pool,
868 const sp<AMessage> &format,
869 C2MemoryUsage usage,
870 const std::shared_ptr<std::vector<Entry>> &memoryVector);
871
872 C2MemoryUsage mUsage;
873 sp<MemoryDealer> mDealer;
874 sp<ICrypto> mCrypto;
875 std::shared_ptr<std::vector<Entry>> mMemoryVector;
Wonsik Kim469c8342019-04-11 16:46:09 -0700876};
877
878class GraphicMetadataInputBuffers : public InputBuffers {
879public:
880 GraphicMetadataInputBuffers(const char *componentName, const char *name = "2D-MetaInput");
881 ~GraphicMetadataInputBuffers() override = default;
882
883 bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override;
884
885 bool releaseBuffer(
886 const sp<MediaCodecBuffer> &buffer,
887 std::shared_ptr<C2Buffer> *c2buffer,
888 bool release) override;
889
890 bool expireComponentBuffer(
891 const std::shared_ptr<C2Buffer> &c2buffer) override;
892
893 void flush() override;
894
895 std::unique_ptr<InputBuffers> toArrayMode(size_t size) final;
896
897 size_t numClientBuffers() const final;
898
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700899protected:
900 sp<Codec2Buffer> createNewBuffer() override;
901
Wonsik Kim469c8342019-04-11 16:46:09 -0700902private:
903 FlexBuffersImpl mImpl;
904 std::shared_ptr<C2AllocatorStore> mStore;
905};
906
907class GraphicInputBuffers : public InputBuffers {
908public:
Wonsik Kim41d83432020-04-27 16:40:49 -0700909 GraphicInputBuffers(const char *componentName, const char *name = "2D-BB-Input");
Wonsik Kim469c8342019-04-11 16:46:09 -0700910 ~GraphicInputBuffers() override = default;
911
912 bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override;
913
914 bool releaseBuffer(
915 const sp<MediaCodecBuffer> &buffer,
916 std::shared_ptr<C2Buffer> *c2buffer,
917 bool release) override;
918
919 bool expireComponentBuffer(
920 const std::shared_ptr<C2Buffer> &c2buffer) override;
921
922 void flush() override;
923
924 std::unique_ptr<InputBuffers> toArrayMode(
925 size_t size) final;
926
927 size_t numClientBuffers() const final;
928
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700929protected:
930 sp<Codec2Buffer> createNewBuffer() override;
931
Wonsik Kim469c8342019-04-11 16:46:09 -0700932private:
933 FlexBuffersImpl mImpl;
934 std::shared_ptr<LocalBufferPool> mLocalBufferPool;
935};
936
937class DummyInputBuffers : public InputBuffers {
938public:
939 DummyInputBuffers(const char *componentName, const char *name = "2D-Input")
940 : InputBuffers(componentName, name) { }
941 ~DummyInputBuffers() override = default;
942
943 bool requestNewBuffer(size_t *, sp<MediaCodecBuffer> *) override {
944 return false;
945 }
946
947 bool releaseBuffer(
948 const sp<MediaCodecBuffer> &, std::shared_ptr<C2Buffer> *, bool) override {
949 return false;
950 }
951
952 bool expireComponentBuffer(const std::shared_ptr<C2Buffer> &) override {
953 return false;
954 }
955 void flush() override {
956 }
957
958 std::unique_ptr<InputBuffers> toArrayMode(size_t) final {
959 return nullptr;
960 }
961
962 bool isArrayMode() const final { return true; }
963
964 void getArray(Vector<sp<MediaCodecBuffer>> *array) const final {
965 array->clear();
966 }
967
968 size_t numClientBuffers() const final {
969 return 0u;
970 }
Wonsik Kim5ecf3832019-04-18 10:28:58 -0700971
972protected:
973 sp<Codec2Buffer> createNewBuffer() override {
974 return nullptr;
975 }
Wonsik Kim469c8342019-04-11 16:46:09 -0700976};
977
978class OutputBuffersArray : public OutputBuffers {
979public:
980 OutputBuffersArray(const char *componentName, const char *name = "Output[N]")
981 : OutputBuffers(componentName, name) { }
982 ~OutputBuffersArray() override = default;
983
984 /**
985 * Initialize this object from the non-array state. We keep existing slots
986 * at the same index, and for empty slots we allocate client buffers with
987 * the given allocate function. If the number of slots is less than minSize,
988 * we fill the array to the minimum size.
989 *
990 * \param impl[in] existing non-array state
991 * \param minSize[in] minimum size of the array
992 * \param allocate[in] allocate function to fill empty slots
993 */
994 void initialize(
995 const FlexBuffersImpl &impl,
996 size_t minSize,
997 std::function<sp<Codec2Buffer>()> allocate);
998
999 bool isArrayMode() const final { return true; }
1000
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001001 std::unique_ptr<OutputBuffersArray> toArrayMode(size_t) final {
Wonsik Kim469c8342019-04-11 16:46:09 -07001002 return nullptr;
1003 }
1004
1005 status_t registerBuffer(
1006 const std::shared_ptr<C2Buffer> &buffer,
1007 size_t *index,
1008 sp<MediaCodecBuffer> *clientBuffer) final;
1009
1010 status_t registerCsd(
1011 const C2StreamInitDataInfo::output *csd,
1012 size_t *index,
1013 sp<MediaCodecBuffer> *clientBuffer) final;
1014
1015 bool releaseBuffer(
1016 const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) override;
1017
1018 void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) override;
1019
1020 void getArray(Vector<sp<MediaCodecBuffer>> *array) const final;
1021
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001022 size_t numClientBuffers() const final;
1023
Wonsik Kim469c8342019-04-11 16:46:09 -07001024 /**
1025 * Reallocate the array, filled with buffers with the same size as given
1026 * buffer.
1027 *
1028 * \param c2buffer[in] the reference buffer
1029 */
1030 void realloc(const std::shared_ptr<C2Buffer> &c2buffer);
1031
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001032 /**
1033 * Grow the array to the new size. It is a programming error to supply
1034 * smaller size as the new size.
1035 *
1036 * \param newSize[in] new size of the array.
1037 */
1038 void grow(size_t newSize);
Wonsik Kim469c8342019-04-11 16:46:09 -07001039
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001040 /**
1041 * Transfer the SkipCutBuffer and the output stash from another
1042 * OutputBuffers.
1043 */
1044 void transferFrom(OutputBuffers* source);
1045
Wonsik Kim469c8342019-04-11 16:46:09 -07001046private:
1047 BuffersArrayImpl mImpl;
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001048 std::function<sp<Codec2Buffer>()> mAlloc;
Wonsik Kim469c8342019-04-11 16:46:09 -07001049};
1050
1051class FlexOutputBuffers : public OutputBuffers {
1052public:
1053 FlexOutputBuffers(const char *componentName, const char *name = "Output[]")
1054 : OutputBuffers(componentName, name),
1055 mImpl(mName) { }
1056
1057 status_t registerBuffer(
1058 const std::shared_ptr<C2Buffer> &buffer,
1059 size_t *index,
1060 sp<MediaCodecBuffer> *clientBuffer) override;
1061
1062 status_t registerCsd(
1063 const C2StreamInitDataInfo::output *csd,
1064 size_t *index,
1065 sp<MediaCodecBuffer> *clientBuffer) final;
1066
1067 bool releaseBuffer(
1068 const sp<MediaCodecBuffer> &buffer,
1069 std::shared_ptr<C2Buffer> *c2buffer) override;
1070
1071 void flush(
1072 const std::list<std::unique_ptr<C2Work>> &flushedWork) override;
1073
Pawin Vongmasa9b906982020-04-11 05:07:15 -07001074 std::unique_ptr<OutputBuffersArray> toArrayMode(size_t size) override;
Wonsik Kim469c8342019-04-11 16:46:09 -07001075
1076 size_t numClientBuffers() const final;
1077
1078 /**
1079 * Return an appropriate Codec2Buffer object for the type of buffers.
1080 *
1081 * \param buffer C2Buffer object to wrap.
1082 *
1083 * \return appropriate Codec2Buffer object to wrap |buffer|.
1084 */
1085 virtual sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) = 0;
1086
1087 /**
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001088 * Return a function that allocates an appropriate Codec2Buffer object for
1089 * the type of buffers, to be used as an empty array buffer. The function
1090 * must not refer to this pointer, since it may be used after this object
1091 * destructs.
Wonsik Kim469c8342019-04-11 16:46:09 -07001092 *
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001093 * \return a function that allocates appropriate Codec2Buffer object,
1094 * which can copy() from C2Buffers.
Wonsik Kim469c8342019-04-11 16:46:09 -07001095 */
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001096 virtual std::function<sp<Codec2Buffer>()> getAlloc() = 0;
Wonsik Kim469c8342019-04-11 16:46:09 -07001097
1098private:
1099 FlexBuffersImpl mImpl;
1100};
1101
1102class LinearOutputBuffers : public FlexOutputBuffers {
1103public:
1104 LinearOutputBuffers(const char *componentName, const char *name = "1D-Output")
1105 : FlexOutputBuffers(componentName, name) { }
1106
1107 void flush(
1108 const std::list<std::unique_ptr<C2Work>> &flushedWork) override;
1109
1110 sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override;
1111
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001112 std::function<sp<Codec2Buffer>()> getAlloc() override;
Wonsik Kim469c8342019-04-11 16:46:09 -07001113};
1114
1115class GraphicOutputBuffers : public FlexOutputBuffers {
1116public:
1117 GraphicOutputBuffers(const char *componentName, const char *name = "2D-Output")
1118 : FlexOutputBuffers(componentName, name) { }
1119
1120 sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override;
1121
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001122 std::function<sp<Codec2Buffer>()> getAlloc() override;
Wonsik Kim469c8342019-04-11 16:46:09 -07001123};
1124
1125class RawGraphicOutputBuffers : public FlexOutputBuffers {
1126public:
Wonsik Kim41d83432020-04-27 16:40:49 -07001127 RawGraphicOutputBuffers(const char *componentName, const char *name = "2D-BB-Output");
Wonsik Kim469c8342019-04-11 16:46:09 -07001128 ~RawGraphicOutputBuffers() override = default;
1129
1130 sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override;
1131
Wonsik Kim5ecf3832019-04-18 10:28:58 -07001132 std::function<sp<Codec2Buffer>()> getAlloc() override;
Wonsik Kim469c8342019-04-11 16:46:09 -07001133
1134private:
1135 std::shared_ptr<LocalBufferPool> mLocalBufferPool;
1136};
1137
1138} // namespace android
1139
1140#endif // CCODEC_BUFFERS_H_