| Wonsik Kim | 469c834 | 2019-04-11 16:46:09 -0700 | [diff] [blame^] | 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 | #include "SkipCutBuffer.h" | 
 | 29 |  | 
 | 30 | namespace android { | 
 | 31 |  | 
 | 32 | constexpr size_t kLinearBufferSize = 1048576; | 
 | 33 | // This can fit 4K RGBA frame, and most likely client won't need more than this. | 
 | 34 | constexpr size_t kMaxLinearBufferSize = 3840 * 2160 * 4; | 
 | 35 |  | 
 | 36 | /** | 
 | 37 |  * Base class for representation of buffers at one port. | 
 | 38 |  */ | 
 | 39 | class CCodecBuffers { | 
 | 40 | public: | 
 | 41 |     CCodecBuffers(const char *componentName, const char *name = "Buffers") | 
 | 42 |         : mComponentName(componentName), | 
 | 43 |           mChannelName(std::string(componentName) + ":" + name), | 
 | 44 |           mName(mChannelName.c_str()) { | 
 | 45 |     } | 
 | 46 |     virtual ~CCodecBuffers() = default; | 
 | 47 |  | 
 | 48 |     /** | 
 | 49 |      * Set format for MediaCodec-facing buffers. | 
 | 50 |      */ | 
 | 51 |     void setFormat(const sp<AMessage> &format); | 
 | 52 |  | 
 | 53 |     /** | 
 | 54 |      * Return a copy of current format. | 
 | 55 |      */ | 
 | 56 |     sp<AMessage> dupFormat(); | 
 | 57 |  | 
 | 58 |     /** | 
 | 59 |      * Returns true if the buffers are operating under array mode. | 
 | 60 |      */ | 
 | 61 |     virtual bool isArrayMode() const { return false; } | 
 | 62 |  | 
 | 63 |     /** | 
 | 64 |      * Fills the vector with MediaCodecBuffer's if in array mode; otherwise, | 
 | 65 |      * no-op. | 
 | 66 |      */ | 
 | 67 |     virtual void getArray(Vector<sp<MediaCodecBuffer>> *) const {} | 
 | 68 |  | 
 | 69 |     /** | 
 | 70 |      * Return number of buffers the client owns. | 
 | 71 |      */ | 
 | 72 |     virtual size_t numClientBuffers() const = 0; | 
 | 73 |  | 
 | 74 |     /** | 
 | 75 |      * Examine image data from the buffer and update the format if necessary. | 
 | 76 |      */ | 
 | 77 |     void handleImageData(const sp<Codec2Buffer> &buffer); | 
 | 78 |  | 
 | 79 | protected: | 
 | 80 |     std::string mComponentName; ///< name of component for debugging | 
 | 81 |     std::string mChannelName; ///< name of channel for debugging | 
 | 82 |     const char *mName; ///< C-string version of channel name | 
 | 83 |     // Format to be used for creating MediaCodec-facing buffers. | 
 | 84 |     sp<AMessage> mFormat; | 
 | 85 |  | 
 | 86 | private: | 
 | 87 |     DISALLOW_EVIL_CONSTRUCTORS(CCodecBuffers); | 
 | 88 | }; | 
 | 89 |  | 
 | 90 | class InputBuffers : public CCodecBuffers { | 
 | 91 | public: | 
 | 92 |     InputBuffers(const char *componentName, const char *name = "Input[]") | 
 | 93 |         : CCodecBuffers(componentName, name) { } | 
 | 94 |     virtual ~InputBuffers() = default; | 
 | 95 |  | 
 | 96 |     /** | 
 | 97 |      * Set a block pool to obtain input memory blocks. | 
 | 98 |      */ | 
 | 99 |     void setPool(const std::shared_ptr<C2BlockPool> &pool) { mPool = pool; } | 
 | 100 |  | 
 | 101 |     /** | 
 | 102 |      * Get a new MediaCodecBuffer for input and its corresponding index. | 
 | 103 |      * Returns false if no new buffer can be obtained at the moment. | 
 | 104 |      */ | 
 | 105 |     virtual bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) = 0; | 
 | 106 |  | 
 | 107 |     /** | 
 | 108 |      * Release the buffer obtained from requestNewBuffer() and get the | 
 | 109 |      * associated C2Buffer object back. Returns true if the buffer was on file | 
 | 110 |      * and released successfully. | 
 | 111 |      */ | 
 | 112 |     virtual bool releaseBuffer( | 
 | 113 |             const sp<MediaCodecBuffer> &buffer, | 
 | 114 |             std::shared_ptr<C2Buffer> *c2buffer, | 
 | 115 |             bool release) = 0; | 
 | 116 |  | 
 | 117 |     /** | 
 | 118 |      * Release the buffer that is no longer used by the codec process. Return | 
 | 119 |      * true if and only if the buffer was on file and released successfully. | 
 | 120 |      */ | 
 | 121 |     virtual bool expireComponentBuffer( | 
 | 122 |             const std::shared_ptr<C2Buffer> &c2buffer) = 0; | 
 | 123 |  | 
 | 124 |     /** | 
 | 125 |      * Flush internal state. After this call, no index or buffer previously | 
 | 126 |      * returned from requestNewBuffer() is valid. | 
 | 127 |      */ | 
 | 128 |     virtual void flush() = 0; | 
 | 129 |  | 
 | 130 |     /** | 
 | 131 |      * Return array-backed version of input buffers. The returned object | 
 | 132 |      * shall retain the internal state so that it will honor index and | 
 | 133 |      * buffer from previous calls of requestNewBuffer(). | 
 | 134 |      */ | 
 | 135 |     virtual std::unique_ptr<InputBuffers> toArrayMode(size_t size) = 0; | 
 | 136 |  | 
 | 137 | protected: | 
 | 138 |     // Pool to obtain blocks for input buffers. | 
 | 139 |     std::shared_ptr<C2BlockPool> mPool; | 
 | 140 |  | 
 | 141 | private: | 
 | 142 |     DISALLOW_EVIL_CONSTRUCTORS(InputBuffers); | 
 | 143 | }; | 
 | 144 |  | 
 | 145 | class OutputBuffers : public CCodecBuffers { | 
 | 146 | public: | 
 | 147 |     OutputBuffers(const char *componentName, const char *name = "Output") | 
 | 148 |         : CCodecBuffers(componentName, name) { } | 
 | 149 |     virtual ~OutputBuffers() = default; | 
 | 150 |  | 
 | 151 |     /** | 
 | 152 |      * Register output C2Buffer from the component and obtain corresponding | 
 | 153 |      * index and MediaCodecBuffer object. Returns false if registration | 
 | 154 |      * fails. | 
 | 155 |      */ | 
 | 156 |     virtual status_t registerBuffer( | 
 | 157 |             const std::shared_ptr<C2Buffer> &buffer, | 
 | 158 |             size_t *index, | 
 | 159 |             sp<MediaCodecBuffer> *clientBuffer) = 0; | 
 | 160 |  | 
 | 161 |     /** | 
 | 162 |      * Register codec specific data as a buffer to be consistent with | 
 | 163 |      * MediaCodec behavior. | 
 | 164 |      */ | 
 | 165 |     virtual status_t registerCsd( | 
 | 166 |             const C2StreamInitDataInfo::output * /* csd */, | 
 | 167 |             size_t * /* index */, | 
 | 168 |             sp<MediaCodecBuffer> * /* clientBuffer */) = 0; | 
 | 169 |  | 
 | 170 |     /** | 
 | 171 |      * Release the buffer obtained from registerBuffer() and get the | 
 | 172 |      * associated C2Buffer object back. Returns true if the buffer was on file | 
 | 173 |      * and released successfully. | 
 | 174 |      */ | 
 | 175 |     virtual bool releaseBuffer( | 
 | 176 |             const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) = 0; | 
 | 177 |  | 
 | 178 |     /** | 
 | 179 |      * Flush internal state. After this call, no index or buffer previously | 
 | 180 |      * returned from registerBuffer() is valid. | 
 | 181 |      */ | 
 | 182 |     virtual void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) = 0; | 
 | 183 |  | 
 | 184 |     /** | 
 | 185 |      * Return array-backed version of output buffers. The returned object | 
 | 186 |      * shall retain the internal state so that it will honor index and | 
 | 187 |      * buffer from previous calls of registerBuffer(). | 
 | 188 |      */ | 
 | 189 |     virtual std::unique_ptr<OutputBuffers> toArrayMode(size_t size) = 0; | 
 | 190 |  | 
 | 191 |     /** | 
 | 192 |      * Initialize SkipCutBuffer object. | 
 | 193 |      */ | 
 | 194 |     void initSkipCutBuffer( | 
 | 195 |             int32_t delay, int32_t padding, int32_t sampleRate, int32_t channelCount); | 
 | 196 |  | 
 | 197 |     /** | 
 | 198 |      * Update the SkipCutBuffer object. No-op if it's never initialized. | 
 | 199 |      */ | 
 | 200 |     void updateSkipCutBuffer(int32_t sampleRate, int32_t channelCount); | 
 | 201 |  | 
 | 202 |     /** | 
 | 203 |      * Submit buffer to SkipCutBuffer object, if initialized. | 
 | 204 |      */ | 
 | 205 |     void submit(const sp<MediaCodecBuffer> &buffer); | 
 | 206 |  | 
 | 207 |     /** | 
 | 208 |      * Transfer SkipCutBuffer object to the other Buffers object. | 
 | 209 |      */ | 
 | 210 |     void transferSkipCutBuffer(const sp<SkipCutBuffer> &scb); | 
 | 211 |  | 
 | 212 | protected: | 
 | 213 |     sp<SkipCutBuffer> mSkipCutBuffer; | 
 | 214 |  | 
 | 215 | private: | 
 | 216 |     int32_t mDelay; | 
 | 217 |     int32_t mPadding; | 
 | 218 |     int32_t mSampleRate; | 
 | 219 |  | 
 | 220 |     void setSkipCutBuffer(int32_t skip, int32_t cut, int32_t channelCount); | 
 | 221 |  | 
 | 222 |     DISALLOW_EVIL_CONSTRUCTORS(OutputBuffers); | 
 | 223 | }; | 
 | 224 |  | 
 | 225 | /** | 
 | 226 |  * Simple local buffer pool backed by std::vector. | 
 | 227 |  */ | 
 | 228 | class LocalBufferPool : public std::enable_shared_from_this<LocalBufferPool> { | 
 | 229 | public: | 
 | 230 |     /** | 
 | 231 |      * Create a new LocalBufferPool object. | 
 | 232 |      * | 
 | 233 |      * \param poolCapacity  max total size of buffers managed by this pool. | 
 | 234 |      * | 
 | 235 |      * \return  a newly created pool object. | 
 | 236 |      */ | 
 | 237 |     static std::shared_ptr<LocalBufferPool> Create(size_t poolCapacity); | 
 | 238 |  | 
 | 239 |     /** | 
 | 240 |      * Return an ABuffer object whose size is at least |capacity|. | 
 | 241 |      * | 
 | 242 |      * \param   capacity  requested capacity | 
 | 243 |      * \return  nullptr if the pool capacity is reached | 
 | 244 |      *          an ABuffer object otherwise. | 
 | 245 |      */ | 
 | 246 |     sp<ABuffer> newBuffer(size_t capacity); | 
 | 247 |  | 
 | 248 | private: | 
 | 249 |     /** | 
 | 250 |      * ABuffer backed by std::vector. | 
 | 251 |      */ | 
 | 252 |     class VectorBuffer : public ::android::ABuffer { | 
 | 253 |     public: | 
 | 254 |         /** | 
 | 255 |          * Construct a VectorBuffer by taking the ownership of supplied vector. | 
 | 256 |          * | 
 | 257 |          * \param vec   backing vector of the buffer. this object takes | 
 | 258 |          *              ownership at construction. | 
 | 259 |          * \param pool  a LocalBufferPool object to return the vector at | 
 | 260 |          *              destruction. | 
 | 261 |          */ | 
 | 262 |         VectorBuffer(std::vector<uint8_t> &&vec, const std::shared_ptr<LocalBufferPool> &pool); | 
 | 263 |  | 
 | 264 |         ~VectorBuffer() override; | 
 | 265 |  | 
 | 266 |     private: | 
 | 267 |         std::vector<uint8_t> mVec; | 
 | 268 |         std::weak_ptr<LocalBufferPool> mPool; | 
 | 269 |     }; | 
 | 270 |  | 
 | 271 |     Mutex mMutex; | 
 | 272 |     size_t mPoolCapacity; | 
 | 273 |     size_t mUsedSize; | 
 | 274 |     std::list<std::vector<uint8_t>> mPool; | 
 | 275 |  | 
 | 276 |     /** | 
 | 277 |      * Private constructor to prevent constructing non-managed LocalBufferPool. | 
 | 278 |      */ | 
 | 279 |     explicit LocalBufferPool(size_t poolCapacity) | 
 | 280 |         : mPoolCapacity(poolCapacity), mUsedSize(0) { | 
 | 281 |     } | 
 | 282 |  | 
 | 283 |     /** | 
 | 284 |      * Take back the ownership of vec from the destructed VectorBuffer and put | 
 | 285 |      * it in front of the pool. | 
 | 286 |      */ | 
 | 287 |     void returnVector(std::vector<uint8_t> &&vec); | 
 | 288 |  | 
 | 289 |     DISALLOW_EVIL_CONSTRUCTORS(LocalBufferPool); | 
 | 290 | }; | 
 | 291 |  | 
 | 292 | class BuffersArrayImpl; | 
 | 293 |  | 
 | 294 | /** | 
 | 295 |  * Flexible buffer slots implementation. | 
 | 296 |  */ | 
 | 297 | class FlexBuffersImpl { | 
 | 298 | public: | 
 | 299 |     FlexBuffersImpl(const char *name) | 
 | 300 |         : mImplName(std::string(name) + ".Impl"), | 
 | 301 |           mName(mImplName.c_str()) { } | 
 | 302 |  | 
 | 303 |     /** | 
 | 304 |      * Assign an empty slot for a buffer and return the index. If there's no | 
 | 305 |      * empty slot, just add one at the end and return it. | 
 | 306 |      * | 
 | 307 |      * \param buffer[in]  a new buffer to assign a slot. | 
 | 308 |      * \return            index of the assigned slot. | 
 | 309 |      */ | 
 | 310 |     size_t assignSlot(const sp<Codec2Buffer> &buffer); | 
 | 311 |  | 
 | 312 |     /** | 
 | 313 |      * Release the slot from the client, and get the C2Buffer object back from | 
 | 314 |      * the previously assigned buffer. Note that the slot is not completely free | 
 | 315 |      * until the returned C2Buffer object is freed. | 
 | 316 |      * | 
 | 317 |      * \param   buffer[in]        the buffer previously assigned a slot. | 
 | 318 |      * \param   c2buffer[in,out]  pointer to C2Buffer to be populated. Ignored | 
 | 319 |      *                            if null. | 
 | 320 |      * \return  true  if the buffer is successfully released from a slot | 
 | 321 |      *          false otherwise | 
 | 322 |      */ | 
 | 323 |     bool releaseSlot( | 
 | 324 |             const sp<MediaCodecBuffer> &buffer, | 
 | 325 |             std::shared_ptr<C2Buffer> *c2buffer, | 
 | 326 |             bool release); | 
 | 327 |  | 
 | 328 |     /** | 
 | 329 |      * Expire the C2Buffer object in the slot. | 
 | 330 |      * | 
 | 331 |      * \param   c2buffer[in]  C2Buffer object which the component released. | 
 | 332 |      * \return  true  if the buffer is found in one of the slots and | 
 | 333 |      *                successfully released | 
 | 334 |      *          false otherwise | 
 | 335 |      */ | 
 | 336 |     bool expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer); | 
 | 337 |  | 
 | 338 |     /** | 
 | 339 |      * The client abandoned all known buffers, so reclaim the ownership. | 
 | 340 |      */ | 
 | 341 |     void flush(); | 
 | 342 |  | 
 | 343 |     /** | 
 | 344 |      * Return the number of buffers that are sent to the client but not released | 
 | 345 |      * yet. | 
 | 346 |      */ | 
 | 347 |     size_t numClientBuffers() const; | 
 | 348 |  | 
 | 349 | private: | 
 | 350 |     friend class BuffersArrayImpl; | 
 | 351 |  | 
 | 352 |     std::string mImplName; ///< name for debugging | 
 | 353 |     const char *mName; ///< C-string version of name | 
 | 354 |  | 
 | 355 |     struct Entry { | 
 | 356 |         sp<Codec2Buffer> clientBuffer; | 
 | 357 |         std::weak_ptr<C2Buffer> compBuffer; | 
 | 358 |     }; | 
 | 359 |     std::vector<Entry> mBuffers; | 
 | 360 | }; | 
 | 361 |  | 
 | 362 | /** | 
 | 363 |  * Static buffer slots implementation based on a fixed-size array. | 
 | 364 |  */ | 
 | 365 | class BuffersArrayImpl { | 
 | 366 | public: | 
 | 367 |     BuffersArrayImpl() | 
 | 368 |         : mImplName("BuffersArrayImpl"), | 
 | 369 |           mName(mImplName.c_str()) { } | 
 | 370 |  | 
 | 371 |     /** | 
 | 372 |      * Initialize buffer array from the original |impl|. The buffers known by | 
 | 373 |      * the client is preserved, and the empty slots are populated so that the | 
 | 374 |      * array size is at least |minSize|. | 
 | 375 |      * | 
 | 376 |      * \param impl[in]      FlexBuffersImpl object used so far. | 
 | 377 |      * \param minSize[in]   minimum size of the buffer array. | 
 | 378 |      * \param allocate[in]  function to allocate a client buffer for an empty slot. | 
 | 379 |      */ | 
 | 380 |     void initialize( | 
 | 381 |             const FlexBuffersImpl &impl, | 
 | 382 |             size_t minSize, | 
 | 383 |             std::function<sp<Codec2Buffer>()> allocate); | 
 | 384 |  | 
 | 385 |     /** | 
 | 386 |      * Grab a buffer from the underlying array which matches the criteria. | 
 | 387 |      * | 
 | 388 |      * \param index[out]    index of the slot. | 
 | 389 |      * \param buffer[out]   the matching buffer. | 
 | 390 |      * \param match[in]     a function to test whether the buffer matches the | 
 | 391 |      *                      criteria or not. | 
 | 392 |      * \return OK           if successful, | 
 | 393 |      *         WOULD_BLOCK  if slots are being used, | 
 | 394 |      *         NO_MEMORY    if no slot matches the criteria, even though it's | 
 | 395 |      *                      available | 
 | 396 |      */ | 
 | 397 |     status_t grabBuffer( | 
 | 398 |             size_t *index, | 
 | 399 |             sp<Codec2Buffer> *buffer, | 
 | 400 |             std::function<bool(const sp<Codec2Buffer> &)> match = | 
 | 401 |                 [](const sp<Codec2Buffer> &) { return true; }); | 
 | 402 |  | 
 | 403 |     /** | 
 | 404 |      * Return the buffer from the client, and get the C2Buffer object back from | 
 | 405 |      * the buffer. Note that the slot is not completely free until the returned | 
 | 406 |      * C2Buffer object is freed. | 
 | 407 |      * | 
 | 408 |      * \param   buffer[in]        the buffer previously grabbed. | 
 | 409 |      * \param   c2buffer[in,out]  pointer to C2Buffer to be populated. Ignored | 
 | 410 |      *                            if null. | 
 | 411 |      * \return  true  if the buffer is successfully returned | 
 | 412 |      *          false otherwise | 
 | 413 |      */ | 
 | 414 |     bool returnBuffer( | 
 | 415 |             const sp<MediaCodecBuffer> &buffer, | 
 | 416 |             std::shared_ptr<C2Buffer> *c2buffer, | 
 | 417 |             bool release); | 
 | 418 |  | 
 | 419 |     /** | 
 | 420 |      * Expire the C2Buffer object in the slot. | 
 | 421 |      * | 
 | 422 |      * \param   c2buffer[in]  C2Buffer object which the component released. | 
 | 423 |      * \return  true  if the buffer is found in one of the slots and | 
 | 424 |      *                successfully released | 
 | 425 |      *          false otherwise | 
 | 426 |      */ | 
 | 427 |     bool expireComponentBuffer(const std::shared_ptr<C2Buffer> &c2buffer); | 
 | 428 |  | 
 | 429 |     /** | 
 | 430 |      * Populate |array| with the underlying buffer array. | 
 | 431 |      * | 
 | 432 |      * \param array[out]  an array to be filled with the underlying buffer array. | 
 | 433 |      */ | 
 | 434 |     void getArray(Vector<sp<MediaCodecBuffer>> *array) const; | 
 | 435 |  | 
 | 436 |     /** | 
 | 437 |      * The client abandoned all known buffers, so reclaim the ownership. | 
 | 438 |      */ | 
 | 439 |     void flush(); | 
 | 440 |  | 
 | 441 |     /** | 
 | 442 |      * Reallocate the array with the given allocation function. | 
 | 443 |      * | 
 | 444 |      * \param alloc[in] the allocation function for client buffers. | 
 | 445 |      */ | 
 | 446 |     void realloc(std::function<sp<Codec2Buffer>()> alloc); | 
 | 447 |  | 
 | 448 |     /** | 
 | 449 |      * Return the number of buffers that are sent to the client but not released | 
 | 450 |      * yet. | 
 | 451 |      */ | 
 | 452 |     size_t numClientBuffers() const; | 
 | 453 |  | 
 | 454 | private: | 
 | 455 |     std::string mImplName; ///< name for debugging | 
 | 456 |     const char *mName; ///< C-string version of name | 
 | 457 |  | 
 | 458 |     struct Entry { | 
 | 459 |         const sp<Codec2Buffer> clientBuffer; | 
 | 460 |         std::weak_ptr<C2Buffer> compBuffer; | 
 | 461 |         bool ownedByClient; | 
 | 462 |     }; | 
 | 463 |     std::vector<Entry> mBuffers; | 
 | 464 | }; | 
 | 465 |  | 
 | 466 | class InputBuffersArray : public InputBuffers { | 
 | 467 | public: | 
 | 468 |     InputBuffersArray(const char *componentName, const char *name = "Input[N]") | 
 | 469 |         : InputBuffers(componentName, name) { } | 
 | 470 |     ~InputBuffersArray() override = default; | 
 | 471 |  | 
 | 472 |     /** | 
 | 473 |      * Initialize this object from the non-array state. We keep existing slots | 
 | 474 |      * at the same index, and for empty slots we allocate client buffers with | 
 | 475 |      * the given allocate function. If the number of slots is less than minSize, | 
 | 476 |      * we fill the array to the minimum size. | 
 | 477 |      * | 
 | 478 |      * \param impl[in]      existing non-array state | 
 | 479 |      * \param minSize[in]   minimum size of the array | 
 | 480 |      * \param allocate[in]  allocate function to fill empty slots | 
 | 481 |      */ | 
 | 482 |     void initialize( | 
 | 483 |             const FlexBuffersImpl &impl, | 
 | 484 |             size_t minSize, | 
 | 485 |             std::function<sp<Codec2Buffer>()> allocate); | 
 | 486 |  | 
 | 487 |     bool isArrayMode() const final { return true; } | 
 | 488 |  | 
 | 489 |     std::unique_ptr<InputBuffers> toArrayMode(size_t) final { | 
 | 490 |         return nullptr; | 
 | 491 |     } | 
 | 492 |  | 
 | 493 |     void getArray(Vector<sp<MediaCodecBuffer>> *array) const final; | 
 | 494 |  | 
 | 495 |     bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override; | 
 | 496 |  | 
 | 497 |     bool releaseBuffer( | 
 | 498 |             const sp<MediaCodecBuffer> &buffer, | 
 | 499 |             std::shared_ptr<C2Buffer> *c2buffer, | 
 | 500 |             bool release) override; | 
 | 501 |  | 
 | 502 |     bool expireComponentBuffer( | 
 | 503 |             const std::shared_ptr<C2Buffer> &c2buffer) override; | 
 | 504 |  | 
 | 505 |     void flush() override; | 
 | 506 |  | 
 | 507 |     size_t numClientBuffers() const final; | 
 | 508 |  | 
 | 509 | private: | 
 | 510 |     BuffersArrayImpl mImpl; | 
 | 511 | }; | 
 | 512 |  | 
 | 513 | class LinearInputBuffers : public InputBuffers { | 
 | 514 | public: | 
 | 515 |     LinearInputBuffers(const char *componentName, const char *name = "1D-Input") | 
 | 516 |         : InputBuffers(componentName, name), | 
 | 517 |           mImpl(mName) { } | 
 | 518 |     ~LinearInputBuffers() override = default; | 
 | 519 |  | 
 | 520 |     bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override; | 
 | 521 |  | 
 | 522 |     bool releaseBuffer( | 
 | 523 |             const sp<MediaCodecBuffer> &buffer, | 
 | 524 |             std::shared_ptr<C2Buffer> *c2buffer, | 
 | 525 |             bool release) override; | 
 | 526 |  | 
 | 527 |     bool expireComponentBuffer( | 
 | 528 |             const std::shared_ptr<C2Buffer> &c2buffer) override; | 
 | 529 |  | 
 | 530 |     void flush() override; | 
 | 531 |  | 
 | 532 |     std::unique_ptr<InputBuffers> toArrayMode(size_t size) final; | 
 | 533 |  | 
 | 534 |     size_t numClientBuffers() const final; | 
 | 535 |  | 
 | 536 |     /** | 
 | 537 |      * Allocate a client buffer with the given size. This method may be | 
 | 538 |      * overridden to support different kind of linear buffers (e.g. encrypted). | 
 | 539 |      */ | 
 | 540 |     virtual sp<Codec2Buffer> alloc(size_t size); | 
 | 541 |  | 
 | 542 | private: | 
 | 543 |     FlexBuffersImpl mImpl; | 
 | 544 | }; | 
 | 545 |  | 
 | 546 | class EncryptedLinearInputBuffers : public LinearInputBuffers { | 
 | 547 | public: | 
 | 548 |     EncryptedLinearInputBuffers( | 
 | 549 |             bool secure, | 
 | 550 |             const sp<MemoryDealer> &dealer, | 
 | 551 |             const sp<ICrypto> &crypto, | 
 | 552 |             int32_t heapSeqNum, | 
 | 553 |             size_t capacity, | 
 | 554 |             size_t numInputSlots, | 
 | 555 |             const char *componentName, const char *name = "EncryptedInput"); | 
 | 556 |  | 
 | 557 |     ~EncryptedLinearInputBuffers() override = default; | 
 | 558 |  | 
 | 559 |     sp<Codec2Buffer> alloc(size_t size) override; | 
 | 560 |  | 
 | 561 | private: | 
 | 562 |     C2MemoryUsage mUsage; | 
 | 563 |     sp<MemoryDealer> mDealer; | 
 | 564 |     sp<ICrypto> mCrypto; | 
 | 565 |     int32_t mHeapSeqNum; | 
 | 566 |     struct Entry { | 
 | 567 |         std::weak_ptr<C2LinearBlock> block; | 
 | 568 |         sp<IMemory> memory; | 
 | 569 |     }; | 
 | 570 |     std::vector<Entry> mMemoryVector; | 
 | 571 | }; | 
 | 572 |  | 
 | 573 | class GraphicMetadataInputBuffers : public InputBuffers { | 
 | 574 | public: | 
 | 575 |     GraphicMetadataInputBuffers(const char *componentName, const char *name = "2D-MetaInput"); | 
 | 576 |     ~GraphicMetadataInputBuffers() override = default; | 
 | 577 |  | 
 | 578 |     bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override; | 
 | 579 |  | 
 | 580 |     bool releaseBuffer( | 
 | 581 |             const sp<MediaCodecBuffer> &buffer, | 
 | 582 |             std::shared_ptr<C2Buffer> *c2buffer, | 
 | 583 |             bool release) override; | 
 | 584 |  | 
 | 585 |     bool expireComponentBuffer( | 
 | 586 |             const std::shared_ptr<C2Buffer> &c2buffer) override; | 
 | 587 |  | 
 | 588 |     void flush() override; | 
 | 589 |  | 
 | 590 |     std::unique_ptr<InputBuffers> toArrayMode(size_t size) final; | 
 | 591 |  | 
 | 592 |     size_t numClientBuffers() const final; | 
 | 593 |  | 
 | 594 | private: | 
 | 595 |     FlexBuffersImpl mImpl; | 
 | 596 |     std::shared_ptr<C2AllocatorStore> mStore; | 
 | 597 | }; | 
 | 598 |  | 
 | 599 | class GraphicInputBuffers : public InputBuffers { | 
 | 600 | public: | 
 | 601 |     GraphicInputBuffers( | 
 | 602 |             size_t numInputSlots, const char *componentName, const char *name = "2D-BB-Input"); | 
 | 603 |     ~GraphicInputBuffers() override = default; | 
 | 604 |  | 
 | 605 |     bool requestNewBuffer(size_t *index, sp<MediaCodecBuffer> *buffer) override; | 
 | 606 |  | 
 | 607 |     bool releaseBuffer( | 
 | 608 |             const sp<MediaCodecBuffer> &buffer, | 
 | 609 |             std::shared_ptr<C2Buffer> *c2buffer, | 
 | 610 |             bool release) override; | 
 | 611 |  | 
 | 612 |     bool expireComponentBuffer( | 
 | 613 |             const std::shared_ptr<C2Buffer> &c2buffer) override; | 
 | 614 |  | 
 | 615 |     void flush() override; | 
 | 616 |  | 
 | 617 |     std::unique_ptr<InputBuffers> toArrayMode( | 
 | 618 |             size_t size) final; | 
 | 619 |  | 
 | 620 |     size_t numClientBuffers() const final; | 
 | 621 |  | 
 | 622 | private: | 
 | 623 |     FlexBuffersImpl mImpl; | 
 | 624 |     std::shared_ptr<LocalBufferPool> mLocalBufferPool; | 
 | 625 | }; | 
 | 626 |  | 
 | 627 | class DummyInputBuffers : public InputBuffers { | 
 | 628 | public: | 
 | 629 |     DummyInputBuffers(const char *componentName, const char *name = "2D-Input") | 
 | 630 |         : InputBuffers(componentName, name) { } | 
 | 631 |     ~DummyInputBuffers() override = default; | 
 | 632 |  | 
 | 633 |     bool requestNewBuffer(size_t *, sp<MediaCodecBuffer> *) override { | 
 | 634 |         return false; | 
 | 635 |     } | 
 | 636 |  | 
 | 637 |     bool releaseBuffer( | 
 | 638 |             const sp<MediaCodecBuffer> &, std::shared_ptr<C2Buffer> *, bool) override { | 
 | 639 |         return false; | 
 | 640 |     } | 
 | 641 |  | 
 | 642 |     bool expireComponentBuffer(const std::shared_ptr<C2Buffer> &) override { | 
 | 643 |         return false; | 
 | 644 |     } | 
 | 645 |     void flush() override { | 
 | 646 |     } | 
 | 647 |  | 
 | 648 |     std::unique_ptr<InputBuffers> toArrayMode(size_t) final { | 
 | 649 |         return nullptr; | 
 | 650 |     } | 
 | 651 |  | 
 | 652 |     bool isArrayMode() const final { return true; } | 
 | 653 |  | 
 | 654 |     void getArray(Vector<sp<MediaCodecBuffer>> *array) const final { | 
 | 655 |         array->clear(); | 
 | 656 |     } | 
 | 657 |  | 
 | 658 |     size_t numClientBuffers() const final { | 
 | 659 |         return 0u; | 
 | 660 |     } | 
 | 661 | }; | 
 | 662 |  | 
 | 663 | class OutputBuffersArray : public OutputBuffers { | 
 | 664 | public: | 
 | 665 |     OutputBuffersArray(const char *componentName, const char *name = "Output[N]") | 
 | 666 |         : OutputBuffers(componentName, name) { } | 
 | 667 |     ~OutputBuffersArray() override = default; | 
 | 668 |  | 
 | 669 |     /** | 
 | 670 |      * Initialize this object from the non-array state. We keep existing slots | 
 | 671 |      * at the same index, and for empty slots we allocate client buffers with | 
 | 672 |      * the given allocate function. If the number of slots is less than minSize, | 
 | 673 |      * we fill the array to the minimum size. | 
 | 674 |      * | 
 | 675 |      * \param impl[in]      existing non-array state | 
 | 676 |      * \param minSize[in]   minimum size of the array | 
 | 677 |      * \param allocate[in]  allocate function to fill empty slots | 
 | 678 |      */ | 
 | 679 |     void initialize( | 
 | 680 |             const FlexBuffersImpl &impl, | 
 | 681 |             size_t minSize, | 
 | 682 |             std::function<sp<Codec2Buffer>()> allocate); | 
 | 683 |  | 
 | 684 |     bool isArrayMode() const final { return true; } | 
 | 685 |  | 
 | 686 |     std::unique_ptr<OutputBuffers> toArrayMode(size_t) final { | 
 | 687 |         return nullptr; | 
 | 688 |     } | 
 | 689 |  | 
 | 690 |     status_t registerBuffer( | 
 | 691 |             const std::shared_ptr<C2Buffer> &buffer, | 
 | 692 |             size_t *index, | 
 | 693 |             sp<MediaCodecBuffer> *clientBuffer) final; | 
 | 694 |  | 
 | 695 |     status_t registerCsd( | 
 | 696 |             const C2StreamInitDataInfo::output *csd, | 
 | 697 |             size_t *index, | 
 | 698 |             sp<MediaCodecBuffer> *clientBuffer) final; | 
 | 699 |  | 
 | 700 |     bool releaseBuffer( | 
 | 701 |             const sp<MediaCodecBuffer> &buffer, std::shared_ptr<C2Buffer> *c2buffer) override; | 
 | 702 |  | 
 | 703 |     void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork) override; | 
 | 704 |  | 
 | 705 |     void getArray(Vector<sp<MediaCodecBuffer>> *array) const final; | 
 | 706 |  | 
 | 707 |     /** | 
 | 708 |      * Reallocate the array, filled with buffers with the same size as given | 
 | 709 |      * buffer. | 
 | 710 |      * | 
 | 711 |      * \param c2buffer[in] the reference buffer | 
 | 712 |      */ | 
 | 713 |     void realloc(const std::shared_ptr<C2Buffer> &c2buffer); | 
 | 714 |  | 
 | 715 |     size_t numClientBuffers() const final; | 
 | 716 |  | 
 | 717 | private: | 
 | 718 |     BuffersArrayImpl mImpl; | 
 | 719 | }; | 
 | 720 |  | 
 | 721 | class FlexOutputBuffers : public OutputBuffers { | 
 | 722 | public: | 
 | 723 |     FlexOutputBuffers(const char *componentName, const char *name = "Output[]") | 
 | 724 |         : OutputBuffers(componentName, name), | 
 | 725 |           mImpl(mName) { } | 
 | 726 |  | 
 | 727 |     status_t registerBuffer( | 
 | 728 |             const std::shared_ptr<C2Buffer> &buffer, | 
 | 729 |             size_t *index, | 
 | 730 |             sp<MediaCodecBuffer> *clientBuffer) override; | 
 | 731 |  | 
 | 732 |     status_t registerCsd( | 
 | 733 |             const C2StreamInitDataInfo::output *csd, | 
 | 734 |             size_t *index, | 
 | 735 |             sp<MediaCodecBuffer> *clientBuffer) final; | 
 | 736 |  | 
 | 737 |     bool releaseBuffer( | 
 | 738 |             const sp<MediaCodecBuffer> &buffer, | 
 | 739 |             std::shared_ptr<C2Buffer> *c2buffer) override; | 
 | 740 |  | 
 | 741 |     void flush( | 
 | 742 |             const std::list<std::unique_ptr<C2Work>> &flushedWork) override; | 
 | 743 |  | 
 | 744 |     std::unique_ptr<OutputBuffers> toArrayMode(size_t size) override; | 
 | 745 |  | 
 | 746 |     size_t numClientBuffers() const final; | 
 | 747 |  | 
 | 748 |     /** | 
 | 749 |      * Return an appropriate Codec2Buffer object for the type of buffers. | 
 | 750 |      * | 
 | 751 |      * \param buffer  C2Buffer object to wrap. | 
 | 752 |      * | 
 | 753 |      * \return  appropriate Codec2Buffer object to wrap |buffer|. | 
 | 754 |      */ | 
 | 755 |     virtual sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) = 0; | 
 | 756 |  | 
 | 757 |     /** | 
 | 758 |      * Return an appropriate Codec2Buffer object for the type of buffers, to be | 
 | 759 |      * used as an empty array buffer. | 
 | 760 |      * | 
 | 761 |      * \return  appropriate Codec2Buffer object which can copy() from C2Buffers. | 
 | 762 |      */ | 
 | 763 |     virtual sp<Codec2Buffer> allocateArrayBuffer() = 0; | 
 | 764 |  | 
 | 765 | private: | 
 | 766 |     FlexBuffersImpl mImpl; | 
 | 767 | }; | 
 | 768 |  | 
 | 769 | class LinearOutputBuffers : public FlexOutputBuffers { | 
 | 770 | public: | 
 | 771 |     LinearOutputBuffers(const char *componentName, const char *name = "1D-Output") | 
 | 772 |         : FlexOutputBuffers(componentName, name) { } | 
 | 773 |  | 
 | 774 |     void flush( | 
 | 775 |             const std::list<std::unique_ptr<C2Work>> &flushedWork) override; | 
 | 776 |  | 
 | 777 |     sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override; | 
 | 778 |  | 
 | 779 |     sp<Codec2Buffer> allocateArrayBuffer() override; | 
 | 780 | }; | 
 | 781 |  | 
 | 782 | class GraphicOutputBuffers : public FlexOutputBuffers { | 
 | 783 | public: | 
 | 784 |     GraphicOutputBuffers(const char *componentName, const char *name = "2D-Output") | 
 | 785 |         : FlexOutputBuffers(componentName, name) { } | 
 | 786 |  | 
 | 787 |     sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override; | 
 | 788 |  | 
 | 789 |     sp<Codec2Buffer> allocateArrayBuffer() override; | 
 | 790 | }; | 
 | 791 |  | 
 | 792 | class RawGraphicOutputBuffers : public FlexOutputBuffers { | 
 | 793 | public: | 
 | 794 |     RawGraphicOutputBuffers( | 
 | 795 |             size_t numOutputSlots, const char *componentName, const char *name = "2D-BB-Output"); | 
 | 796 |     ~RawGraphicOutputBuffers() override = default; | 
 | 797 |  | 
 | 798 |     sp<Codec2Buffer> wrap(const std::shared_ptr<C2Buffer> &buffer) override; | 
 | 799 |  | 
 | 800 |     sp<Codec2Buffer> allocateArrayBuffer() override; | 
 | 801 |  | 
 | 802 | private: | 
 | 803 |     std::shared_ptr<LocalBufferPool> mLocalBufferPool; | 
 | 804 | }; | 
 | 805 |  | 
 | 806 | }  // namespace android | 
 | 807 |  | 
 | 808 | #endif  // CCODEC_BUFFERS_H_ |