1 /* 2 * Copyright 2017, 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_BUFFER_CHANNEL_H_ 18 19 #define CCODEC_BUFFER_CHANNEL_H_ 20 21 #include <map> 22 #include <memory> 23 #include <vector> 24 25 #include <C2Buffer.h> 26 #include <C2Component.h> 27 #include <Codec2Mapper.h> 28 29 #include <codec2/hidl/client.h> 30 #include <media/stagefright/foundation/Mutexed.h> 31 #include <media/stagefright/CodecBase.h> 32 #include <media/ICrypto.h> 33 34 #include "CCodecBuffers.h" 35 #include "InputSurfaceWrapper.h" 36 #include "PipelineWatcher.h" 37 38 namespace android { 39 40 class MemoryDealer; 41 42 class CCodecCallback { 43 public: 44 virtual ~CCodecCallback() = default; 45 virtual void onError(status_t err, enum ActionCode actionCode) = 0; 46 virtual void onOutputFramesRendered(int64_t mediaTimeUs, nsecs_t renderTimeNs) = 0; 47 virtual void onOutputBuffersChanged() = 0; 48 }; 49 50 /** 51 * BufferChannelBase implementation for CCodec. 52 */ 53 class CCodecBufferChannel 54 : public BufferChannelBase, public std::enable_shared_from_this<CCodecBufferChannel> { 55 public: 56 explicit CCodecBufferChannel(const std::shared_ptr<CCodecCallback> &callback); 57 virtual ~CCodecBufferChannel(); 58 59 // BufferChannelBase interface 60 virtual status_t queueInputBuffer(const sp<MediaCodecBuffer> &buffer) override; 61 virtual status_t queueSecureInputBuffer( 62 const sp<MediaCodecBuffer> &buffer, 63 bool secure, 64 const uint8_t *key, 65 const uint8_t *iv, 66 CryptoPlugin::Mode mode, 67 CryptoPlugin::Pattern pattern, 68 const CryptoPlugin::SubSample *subSamples, 69 size_t numSubSamples, 70 AString *errorDetailMsg) override; 71 virtual status_t renderOutputBuffer( 72 const sp<MediaCodecBuffer> &buffer, int64_t timestampNs) override; 73 virtual status_t discardBuffer(const sp<MediaCodecBuffer> &buffer) override; 74 virtual void getInputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override; 75 virtual void getOutputBufferArray(Vector<sp<MediaCodecBuffer>> *array) override; 76 77 // Methods below are interface for CCodec to use. 78 79 /** 80 * Set the component object for buffer processing. 81 */ 82 void setComponent(const std::shared_ptr<Codec2Client::Component> &component); 83 84 /** 85 * Set output graphic surface for rendering. 86 */ 87 status_t setSurface(const sp<Surface> &surface); 88 89 /** 90 * Set GraphicBufferSource object from which the component extracts input 91 * buffers. 92 */ 93 status_t setInputSurface(const std::shared_ptr<InputSurfaceWrapper> &surface); 94 95 /** 96 * Signal EOS to input surface. 97 */ 98 status_t signalEndOfInputStream(); 99 100 /** 101 * Set parameters. 102 */ 103 status_t setParameters(std::vector<std::unique_ptr<C2Param>> ¶ms); 104 105 /** 106 * Start queueing buffers to the component. This object should never queue 107 * buffers before this call has completed. 108 */ 109 status_t start(const sp<AMessage> &inputFormat, const sp<AMessage> &outputFormat); 110 111 /** 112 * Request initial input buffers to be filled by client. 113 */ 114 status_t requestInitialInputBuffers(); 115 116 /** 117 * Stop queueing buffers to the component. This object should never queue 118 * buffers after this call, until start() is called. 119 */ 120 void stop(); 121 122 void flush(const std::list<std::unique_ptr<C2Work>> &flushedWork); 123 124 /** 125 * Notify input client about work done. 126 * 127 * @param workItems finished work item. 128 * @param outputFormat new output format if it has changed, otherwise nullptr 129 * @param initData new init data (CSD) if it has changed, otherwise nullptr 130 */ 131 void onWorkDone( 132 std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat, 133 const C2StreamInitDataInfo::output *initData); 134 135 /** 136 * Make an input buffer available for the client as it is no longer needed 137 * by the codec. 138 * 139 * @param frameIndex The index of input work 140 * @param arrayIndex The index of buffer in the input work buffers. 141 */ 142 void onInputBufferDone(uint64_t frameIndex, size_t arrayIndex); 143 144 PipelineWatcher::Clock::duration elapsed(); 145 146 enum MetaMode { 147 MODE_NONE, 148 MODE_ANW, 149 }; 150 151 void setMetaMode(MetaMode mode); 152 153 private: 154 class QueueGuard; 155 156 /** 157 * Special mutex-like object with the following properties: 158 * 159 * - At STOPPED state (initial, or after stop()) 160 * - QueueGuard object gets created at STOPPED state, and the client is 161 * supposed to return immediately. 162 * - At RUNNING state (after start()) 163 * - Each QueueGuard object 164 */ 165 class QueueSync { 166 public: 167 /** 168 * At construction the sync object is in STOPPED state. 169 */ QueueSync()170 inline QueueSync() {} 171 ~QueueSync() = default; 172 173 /** 174 * Transition to RUNNING state when stopped. No-op if already in RUNNING 175 * state. 176 */ 177 void start(); 178 179 /** 180 * At RUNNING state, wait until all QueueGuard object created during 181 * RUNNING state are destroyed, and then transition to STOPPED state. 182 * No-op if already in STOPPED state. 183 */ 184 void stop(); 185 186 private: 187 Mutex mGuardLock; 188 189 struct Counter { CounterCounter190 inline Counter() : value(-1) {} 191 int32_t value; 192 Condition cond; 193 }; 194 Mutexed<Counter> mCount; 195 196 friend class CCodecBufferChannel::QueueGuard; 197 }; 198 199 class QueueGuard { 200 public: 201 QueueGuard(QueueSync &sync); 202 ~QueueGuard(); isRunning()203 inline bool isRunning() { return mRunning; } 204 205 private: 206 QueueSync &mSync; 207 bool mRunning; 208 }; 209 210 void feedInputBufferIfAvailable(); 211 void feedInputBufferIfAvailableInternal(); 212 status_t queueInputBufferInternal(sp<MediaCodecBuffer> buffer); 213 bool handleWork( 214 std::unique_ptr<C2Work> work, const sp<AMessage> &outputFormat, 215 const C2StreamInitDataInfo::output *initData); 216 void sendOutputBuffers(); 217 218 QueueSync mSync; 219 sp<MemoryDealer> mDealer; 220 sp<IMemory> mDecryptDestination; 221 int32_t mHeapSeqNum; 222 223 std::shared_ptr<Codec2Client::Component> mComponent; 224 std::string mComponentName; ///< component name for debugging 225 const char *mName; ///< C-string version of component name 226 std::shared_ptr<CCodecCallback> mCCodecCallback; 227 std::shared_ptr<C2BlockPool> mInputAllocator; 228 QueueSync mQueueSync; 229 std::vector<std::unique_ptr<C2Param>> mParamsToBeSet; 230 231 struct Input { 232 Input(); 233 234 std::unique_ptr<InputBuffers> buffers; 235 size_t numSlots; 236 FlexBuffersImpl extraBuffers; 237 size_t numExtraSlots; 238 uint32_t inputDelay; 239 uint32_t pipelineDelay; 240 }; 241 Mutexed<Input> mInput; 242 struct Output { 243 std::unique_ptr<OutputBuffers> buffers; 244 size_t numSlots; 245 uint32_t outputDelay; 246 }; 247 Mutexed<Output> mOutput; 248 Mutexed<std::list<sp<ABuffer>>> mFlushedConfigs; 249 250 std::atomic_uint64_t mFrameIndex; 251 std::atomic_uint64_t mFirstValidFrameIndex; 252 253 sp<MemoryDealer> makeMemoryDealer(size_t heapSize); 254 255 struct OutputSurface { 256 sp<Surface> surface; 257 uint32_t generation; 258 int maxDequeueBuffers; 259 }; 260 Mutexed<OutputSurface> mOutputSurface; 261 262 struct BlockPools { 263 C2Allocator::id_t inputAllocatorId; 264 std::shared_ptr<C2BlockPool> inputPool; 265 C2Allocator::id_t outputAllocatorId; 266 C2BlockPool::local_id_t outputPoolId; 267 std::shared_ptr<Codec2Client::Configurable> outputPoolIntf; 268 }; 269 Mutexed<BlockPools> mBlockPools; 270 271 std::shared_ptr<InputSurfaceWrapper> mInputSurface; 272 273 MetaMode mMetaMode; 274 275 Mutexed<PipelineWatcher> mPipelineWatcher; 276 277 class ReorderStash { 278 public: 279 struct Entry { EntryEntry280 inline Entry() : buffer(nullptr), timestamp(0), flags(0), ordinal({0, 0, 0}) {} EntryEntry281 inline Entry( 282 const std::shared_ptr<C2Buffer> &b, 283 int64_t t, 284 int32_t f, 285 const C2WorkOrdinalStruct &o) 286 : buffer(b), timestamp(t), flags(f), ordinal(o) {} 287 std::shared_ptr<C2Buffer> buffer; 288 int64_t timestamp; 289 int32_t flags; 290 C2WorkOrdinalStruct ordinal; 291 }; 292 293 ReorderStash(); 294 295 void clear(); 296 void flush(); 297 void setDepth(uint32_t depth); 298 void setKey(C2Config::ordinal_key_t key); 299 bool pop(Entry *entry); 300 void emplace( 301 const std::shared_ptr<C2Buffer> &buffer, 302 int64_t timestamp, 303 int32_t flags, 304 const C2WorkOrdinalStruct &ordinal); 305 void defer(const Entry &entry); 306 bool hasPending() const; depth()307 uint32_t depth() const { return mDepth; } 308 309 private: 310 std::list<Entry> mPending; 311 std::list<Entry> mStash; 312 uint32_t mDepth; 313 C2Config::ordinal_key_t mKey; 314 315 bool less(const C2WorkOrdinalStruct &o1, const C2WorkOrdinalStruct &o2); 316 }; 317 Mutexed<ReorderStash> mReorderStash; 318 319 std::atomic_bool mInputMetEos; 320 std::once_flag mRenderWarningFlag; 321 hasCryptoOrDescrambler()322 inline bool hasCryptoOrDescrambler() { 323 return mCrypto != nullptr || mDescrambler != nullptr; 324 } 325 }; 326 327 // Conversion of a c2_status_t value to a status_t value may depend on the 328 // operation that returns the c2_status_t value. 329 enum c2_operation_t { 330 C2_OPERATION_NONE, 331 C2_OPERATION_Component_connectToOmxInputSurface, 332 C2_OPERATION_Component_createBlockPool, 333 C2_OPERATION_Component_destroyBlockPool, 334 C2_OPERATION_Component_disconnectFromInputSurface, 335 C2_OPERATION_Component_drain, 336 C2_OPERATION_Component_flush, 337 C2_OPERATION_Component_queue, 338 C2_OPERATION_Component_release, 339 C2_OPERATION_Component_reset, 340 C2_OPERATION_Component_setOutputSurface, 341 C2_OPERATION_Component_start, 342 C2_OPERATION_Component_stop, 343 C2_OPERATION_ComponentStore_copyBuffer, 344 C2_OPERATION_ComponentStore_createComponent, 345 C2_OPERATION_ComponentStore_createInputSurface, 346 C2_OPERATION_ComponentStore_createInterface, 347 C2_OPERATION_Configurable_config, 348 C2_OPERATION_Configurable_query, 349 C2_OPERATION_Configurable_querySupportedParams, 350 C2_OPERATION_Configurable_querySupportedValues, 351 C2_OPERATION_InputSurface_connectToComponent, 352 C2_OPERATION_InputSurfaceConnection_disconnect, 353 }; 354 355 status_t toStatusT(c2_status_t c2s, c2_operation_t c2op = C2_OPERATION_NONE); 356 357 } // namespace android 358 359 #endif // CCODEC_BUFFER_CHANNEL_H_ 360