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