1 /* 2 * Copyright 2019, The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef CCODEC_BUFFERS_H_ 18 19 #define CCODEC_BUFFERS_H_ 20 21 #include <string> 22 23 #include <C2Config.h> 24 #include <media/stagefright/foundation/AMessage.h> 25 #include <media/MediaCodecBuffer.h> 26 27 #include "Codec2Buffer.h" 28 29 namespace android { 30 31 struct ICrypto; 32 class MemoryDealer; 33 class SkipCutBuffer; 34 35 constexpr size_t kLinearBufferSize = 1048576; 36 // This can fit 4K RGBA frame, and most likely client won't need more than this. 37 constexpr size_t kMaxLinearBufferSize = 4096 * 2304 * 4; 38 39 /** 40 * Base class for representation of buffers at one port. 41 */ 42 class CCodecBuffers { 43 public: 44 CCodecBuffers(const char *componentName, const char *name = "Buffers") mComponentName(componentName)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 */ isArrayMode()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 */ getArray(Vector<sp<MediaCodecBuffer>> *)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 82 protected: 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 89 private: 90 DISALLOW_EVIL_CONSTRUCTORS(CCodecBuffers); 91 }; 92 93 class InputBuffers : public CCodecBuffers { 94 public: 95 InputBuffers(const char *componentName, const char *name = "Input[]") CCodecBuffers(componentName,name)96 : CCodecBuffers(componentName, name) { } 97 virtual ~InputBuffers() = default; 98 99 /** 100 * Set a block pool to obtain input memory blocks. 101 */ setPool(const std::shared_ptr<C2BlockPool> & pool)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 140 /** 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 149 protected: 150 virtual sp<Codec2Buffer> createNewBuffer() = 0; 151 152 // Pool to obtain blocks for input buffers. 153 std::shared_ptr<C2BlockPool> mPool; 154 155 private: 156 DISALLOW_EVIL_CONSTRUCTORS(InputBuffers); 157 }; 158 159 class OutputBuffersArray; 160 161 class OutputBuffers : public CCodecBuffers { 162 public: 163 OutputBuffers(const char *componentName, const char *name = "Output"); 164 virtual ~OutputBuffers(); 165 166 /** 167 * Register output C2Buffer from the component and obtain corresponding 168 * 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. 174 */ 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 */ 208 virtual std::unique_ptr<OutputBuffersArray> toArrayMode(size_t size) = 0; 209 210 /** 211 * Initialize SkipCutBuffer object. 212 */ 213 void initSkipCutBuffer( 214 int32_t delay, int32_t padding, int32_t sampleRate, int32_t channelCount); 215 216 /** 217 * 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 371 protected: 372 sp<SkipCutBuffer> mSkipCutBuffer; 373 374 /** 375 * 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 384 private: 385 // SkipCutBuffer 386 int32_t mDelay; 387 int32_t mPadding; 388 int32_t mSampleRate; 389 int32_t mChannelCount; 390 391 void setSkipCutBuffer(int32_t skip, int32_t cut); 392 393 // 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 { StashEntryStashEntry400 inline StashEntry() 401 : buffer(nullptr), 402 notify(false), 403 timestamp(0), 404 flags(0), 405 format(), 406 ordinal({0, 0, 0}) {} StashEntryStashEntry407 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 462 DISALLOW_EVIL_CONSTRUCTORS(OutputBuffers); 463 464 friend OutputBuffersArray; 465 }; 466 467 /** 468 * Simple local buffer pool backed by std::vector. 469 */ 470 class LocalBufferPool : public std::enable_shared_from_this<LocalBufferPool> { 471 public: 472 /** 473 * Create a new LocalBufferPool object. 474 * 475 * \return a newly created pool object. 476 */ 477 static std::shared_ptr<LocalBufferPool> Create(); 478 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 488 private: 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 */ LocalBufferPool(size_t poolCapacity)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 532 class BuffersArrayImpl; 533 534 /** 535 * Flexible buffer slots implementation. 536 */ 537 class FlexBuffersImpl { 538 public: FlexBuffersImpl(const char * name)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 589 /** 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 595 private: 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 */ 611 class BuffersArrayImpl { 612 public: BuffersArrayImpl()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 = 647 [](const sp<Codec2Buffer> &buffer) { return (buffer != nullptr); }); 648 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 /** 695 * 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 /** 705 * Return the number of buffers that are sent to the client but not released 706 * yet. 707 */ 708 size_t numClientBuffers() const; 709 710 /** 711 * Return the size of the array. 712 */ 713 size_t arraySize() const; 714 715 private: 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 727 class InputBuffersArray : public InputBuffers { 728 public: 729 InputBuffersArray(const char *componentName, const char *name = "Input[N]") InputBuffers(componentName,name)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 isArrayMode()748 bool isArrayMode() const final { return true; } 749 toArrayMode(size_t)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 770 protected: 771 sp<Codec2Buffer> createNewBuffer() override; 772 773 private: 774 BuffersArrayImpl mImpl; 775 std::function<sp<Codec2Buffer>()> mAllocate; 776 }; 777 778 class SlotInputBuffers : public InputBuffers { 779 public: 780 SlotInputBuffers(const char *componentName, const char *name = "Slot-Input") InputBuffers(componentName,name)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 801 protected: 802 sp<Codec2Buffer> createNewBuffer() final; 803 804 private: 805 FlexBuffersImpl mImpl; 806 }; 807 808 class LinearInputBuffers : public InputBuffers { 809 public: 810 LinearInputBuffers(const char *componentName, const char *name = "1D-Input") InputBuffers(componentName,name)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 827 std::unique_ptr<InputBuffers> toArrayMode(size_t size) override; 828 829 size_t numClientBuffers() const final; 830 831 protected: 832 sp<Codec2Buffer> createNewBuffer() override; 833 834 FlexBuffersImpl mImpl; 835 836 private: 837 static sp<Codec2Buffer> Alloc( 838 const std::shared_ptr<C2BlockPool> &pool, const sp<AMessage> &format); 839 }; 840 841 class EncryptedLinearInputBuffers : public LinearInputBuffers { 842 public: 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 854 std::unique_ptr<InputBuffers> toArrayMode(size_t size) override; 855 856 protected: 857 sp<Codec2Buffer> createNewBuffer() override; 858 859 private: 860 struct Entry { 861 std::weak_ptr<C2LinearBlock> block; 862 sp<IMemory> memory; 863 int32_t heapSeqNum; 864 }; 865 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; 876 }; 877 878 class GraphicMetadataInputBuffers : public InputBuffers { 879 public: 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 899 protected: 900 sp<Codec2Buffer> createNewBuffer() override; 901 902 private: 903 FlexBuffersImpl mImpl; 904 std::shared_ptr<C2AllocatorStore> mStore; 905 }; 906 907 class GraphicInputBuffers : public InputBuffers { 908 public: 909 GraphicInputBuffers(const char *componentName, const char *name = "2D-BB-Input"); 910 ~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 929 protected: 930 sp<Codec2Buffer> createNewBuffer() override; 931 932 private: 933 FlexBuffersImpl mImpl; 934 std::shared_ptr<LocalBufferPool> mLocalBufferPool; 935 }; 936 937 class DummyInputBuffers : public InputBuffers { 938 public: 939 DummyInputBuffers(const char *componentName, const char *name = "2D-Input") InputBuffers(componentName,name)940 : InputBuffers(componentName, name) { } 941 ~DummyInputBuffers() override = default; 942 requestNewBuffer(size_t *,sp<MediaCodecBuffer> *)943 bool requestNewBuffer(size_t *, sp<MediaCodecBuffer> *) override { 944 return false; 945 } 946 releaseBuffer(const sp<MediaCodecBuffer> &,std::shared_ptr<C2Buffer> *,bool)947 bool releaseBuffer( 948 const sp<MediaCodecBuffer> &, std::shared_ptr<C2Buffer> *, bool) override { 949 return false; 950 } 951 expireComponentBuffer(const std::shared_ptr<C2Buffer> &)952 bool expireComponentBuffer(const std::shared_ptr<C2Buffer> &) override { 953 return false; 954 } flush()955 void flush() override { 956 } 957 toArrayMode(size_t)958 std::unique_ptr<InputBuffers> toArrayMode(size_t) final { 959 return nullptr; 960 } 961 isArrayMode()962 bool isArrayMode() const final { return true; } 963 getArray(Vector<sp<MediaCodecBuffer>> * array)964 void getArray(Vector<sp<MediaCodecBuffer>> *array) const final { 965 array->clear(); 966 } 967 numClientBuffers()968 size_t numClientBuffers() const final { 969 return 0u; 970 } 971 972 protected: createNewBuffer()973 sp<Codec2Buffer> createNewBuffer() override { 974 return nullptr; 975 } 976 }; 977 978 class OutputBuffersArray : public OutputBuffers { 979 public: 980 OutputBuffersArray(const char *componentName, const char *name = "Output[N]") OutputBuffers(componentName,name)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 isArrayMode()999 bool isArrayMode() const final { return true; } 1000 toArrayMode(size_t)1001 std::unique_ptr<OutputBuffersArray> toArrayMode(size_t) final { 1002 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 1022 size_t numClientBuffers() const final; 1023 1024 /** 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 1032 /** 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); 1039 1040 /** 1041 * Transfer the SkipCutBuffer and the output stash from another 1042 * OutputBuffers. 1043 */ 1044 void transferFrom(OutputBuffers* source); 1045 1046 private: 1047 BuffersArrayImpl mImpl; 1048 std::function<sp<Codec2Buffer>()> mAlloc; 1049 }; 1050 1051 class FlexOutputBuffers : public OutputBuffers { 1052 public: 1053 FlexOutputBuffers(const char *componentName, const char *name = "Output[]") OutputBuffers(componentName,name)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 1074 std::unique_ptr<OutputBuffersArray> toArrayMode(size_t size) override; 1075 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 /** 1088 * 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. 1092 * 1093 * \return a function that allocates appropriate Codec2Buffer object, 1094 * which can copy() from C2Buffers. 1095 */ 1096 virtual std::function<sp<Codec2Buffer>()> getAlloc() = 0; 1097 1098 private: 1099 FlexBuffersImpl mImpl; 1100 }; 1101 1102 class LinearOutputBuffers : public FlexOutputBuffers { 1103 public: 1104 LinearOutputBuffers(const char *componentName, const char *name = "1D-Output") FlexOutputBuffers(componentName,name)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 1112 std::function<sp<Codec2Buffer>()> getAlloc() override; 1113 }; 1114 1115 class GraphicOutputBuffers : public FlexOutputBuffers { 1116 public: 1117 GraphicOutputBuffers(const char *componentName, const char *name = "2D-Output") FlexOutputBuffers(componentName,name)1118 : FlexOutputBuffers(componentName, name) { } 1119 1120 sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override; 1121 1122 std::function<sp<Codec2Buffer>()> getAlloc() override; 1123 }; 1124 1125 class RawGraphicOutputBuffers : public FlexOutputBuffers { 1126 public: 1127 RawGraphicOutputBuffers(const char *componentName, const char *name = "2D-BB-Output"); 1128 ~RawGraphicOutputBuffers() override = default; 1129 1130 sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override; 1131 1132 std::function<sp<Codec2Buffer>()> getAlloc() override; 1133 1134 private: 1135 std::shared_ptr<LocalBufferPool> mLocalBufferPool; 1136 }; 1137 1138 } // namespace android 1139 1140 #endif // CCODEC_BUFFERS_H_ 1141