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