1 // Copyright 2017 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef ANDROID_C2_VDA_COMPONENT_H 6 #define ANDROID_C2_VDA_COMPONENT_H 7 8 #include <C2VDACommon.h> 9 #include <VideoDecodeAcceleratorAdaptor.h> 10 11 #include <rect.h> 12 #include <size.h> 13 #include <video_codecs.h> 14 #include <video_decode_accelerator.h> 15 16 #include <C2Component.h> 17 #include <C2Config.h> 18 #include <C2Enum.h> 19 #include <C2Param.h> 20 #include <C2ParamDef.h> 21 #include <SimpleC2Interface.h> 22 #include <util/C2InterfaceHelper.h> 23 24 #include <base/macros.h> 25 #include <base/memory/ref_counted.h> 26 #include <base/single_thread_task_runner.h> 27 #include <base/synchronization/waitable_event.h> 28 #include <base/threading/thread.h> 29 30 #include <atomic> 31 #include <deque> 32 #include <map> 33 #include <mutex> 34 #include <queue> 35 #include <unordered_map> 36 37 namespace android { 38 39 class C2VDAComponent : public C2Component, 40 public VideoDecodeAcceleratorAdaptor::Client, 41 public std::enable_shared_from_this<C2VDAComponent> { 42 public: 43 class IntfImpl : public C2InterfaceHelper { 44 public: 45 IntfImpl(C2String name, const std::shared_ptr<C2ReflectorHelper>& helper); 46 47 // interfaces for C2VDAComponent status()48 c2_status_t status() const { return mInitStatus; } getCodecProfile()49 media::VideoCodecProfile getCodecProfile() const { return mCodecProfile; } getBlockPoolId()50 C2BlockPool::local_id_t getBlockPoolId() const { return mOutputBlockPoolIds->m.values[0]; } getInputCodec()51 InputCodec getInputCodec() const { return mInputCodec; } 52 53 private: 54 // Configurable parameter setters. 55 static C2R ProfileLevelSetter(bool mayBlock, C2P<C2StreamProfileLevelInfo::input>& info); 56 57 static C2R SizeSetter(bool mayBlock, C2P<C2StreamPictureSizeInfo::output>& videoSize); 58 59 template <typename T> 60 static C2R DefaultColorAspectsSetter(bool mayBlock, C2P<T>& def); 61 62 static C2R MergedColorAspectsSetter(bool mayBlock, 63 C2P<C2StreamColorAspectsInfo::output>& merged, 64 const C2P<C2StreamColorAspectsTuning::output>& def, 65 const C2P<C2StreamColorAspectsInfo::input>& coded); 66 67 // The input format kind; should be C2FormatCompressed. 68 std::shared_ptr<C2StreamBufferTypeSetting::input> mInputFormat; 69 // The output format kind; should be C2FormatVideo. 70 std::shared_ptr<C2StreamBufferTypeSetting::output> mOutputFormat; 71 // The MIME type of input port. 72 std::shared_ptr<C2PortMediaTypeSetting::input> mInputMediaType; 73 // The MIME type of output port; should be MEDIA_MIMETYPE_VIDEO_RAW. 74 std::shared_ptr<C2PortMediaTypeSetting::output> mOutputMediaType; 75 // The input codec profile and level. For now configuring this parameter is useless since 76 // the component always uses fixed codec profile to initialize accelerator. It is only used 77 // for the client to query supported profile and level values. 78 // TODO: use configured profile/level to initialize accelerator. 79 std::shared_ptr<C2StreamProfileLevelInfo::input> mProfileLevel; 80 // Decoded video size for output. 81 std::shared_ptr<C2StreamPictureSizeInfo::output> mSize; 82 // Maximum size of one input buffer. 83 std::shared_ptr<C2StreamMaxBufferSizeInfo::input> mMaxInputSize; 84 // The suggested usage of input buffer allocator ID. 85 std::shared_ptr<C2PortAllocatorsTuning::input> mInputAllocatorIds; 86 // The suggested usage of output buffer allocator ID. 87 std::shared_ptr<C2PortAllocatorsTuning::output> mOutputAllocatorIds; 88 // The suggested usage of output buffer allocator ID with surface. 89 std::shared_ptr<C2PortSurfaceAllocatorTuning::output> mOutputSurfaceAllocatorId; 90 // Compnent uses this ID to fetch corresponding output block pool from platform. 91 std::shared_ptr<C2PortBlockPoolsTuning::output> mOutputBlockPoolIds; 92 // The color aspects parsed from input bitstream. This parameter should be configured by 93 // component while decoding. 94 std::shared_ptr<C2StreamColorAspectsInfo::input> mCodedColorAspects; 95 // The default color aspects specified by requested output format. This parameter should be 96 // configured by client. 97 std::shared_ptr<C2StreamColorAspectsTuning::output> mDefaultColorAspects; 98 // The combined color aspects by |mCodedColorAspects| and |mDefaultColorAspects|, and the 99 // former has higher priority. This parameter is used for component to provide color aspects 100 // as C2Info in decoded output buffers. 101 std::shared_ptr<C2StreamColorAspectsInfo::output> mColorAspects; 102 103 c2_status_t mInitStatus; 104 media::VideoCodecProfile mCodecProfile; 105 InputCodec mInputCodec; 106 }; 107 108 C2VDAComponent(C2String name, c2_node_id_t id, 109 const std::shared_ptr<C2ReflectorHelper>& helper); 110 virtual ~C2VDAComponent() override; 111 112 // Implementation of C2Component interface 113 virtual c2_status_t setListener_vb(const std::shared_ptr<Listener>& listener, 114 c2_blocking_t mayBlock) override; 115 virtual c2_status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override; 116 virtual c2_status_t announce_nb(const std::vector<C2WorkOutline>& items) override; 117 virtual c2_status_t flush_sm(flush_mode_t mode, 118 std::list<std::unique_ptr<C2Work>>* const flushedWork) override; 119 virtual c2_status_t drain_nb(drain_mode_t mode) override; 120 virtual c2_status_t start() override; 121 virtual c2_status_t stop() override; 122 virtual c2_status_t reset() override; 123 virtual c2_status_t release() override; 124 virtual std::shared_ptr<C2ComponentInterface> intf() override; 125 126 // Implementation of VideDecodeAcceleratorAdaptor::Client interface 127 virtual void providePictureBuffers(uint32_t minNumBuffers, 128 const media::Size& codedSize) override; 129 virtual void dismissPictureBuffer(int32_t pictureBufferId) override; 130 virtual void pictureReady(int32_t pictureBufferId, int32_t bitstreamId, 131 const media::Rect& cropRect) override; 132 virtual void notifyEndOfBitstreamBuffer(int32_t bitstreamId) override; 133 virtual void notifyFlushDone() override; 134 virtual void notifyResetDone() override; 135 virtual void notifyError(VideoDecodeAcceleratorAdaptor::Result error) override; 136 137 private: 138 // The state machine enumeration on parent thread. 139 enum class State : int32_t { 140 // The initial state of component. State will change to LOADED after the component is 141 // created. 142 UNLOADED, 143 // The component is stopped. State will change to RUNNING when start() is called by 144 // framework. 145 LOADED, 146 // The component is running, State will change to LOADED when stop() or reset() is called by 147 // framework. 148 RUNNING, 149 // The component is in error state. 150 ERROR, 151 }; 152 // The state machine enumeration on component thread. 153 enum class ComponentState : int32_t { 154 // This is the initial state until VDA initialization returns successfully. 155 UNINITIALIZED, 156 // VDA initialization returns successfully. VDA is ready to make progress. 157 STARTED, 158 // onDrain() is called. VDA is draining. Component will hold on queueing works until 159 // onDrainDone(). 160 DRAINING, 161 // onFlush() is called. VDA is flushing. State will change to STARTED after onFlushDone(). 162 FLUSHING, 163 // onStop() is called. VDA is shutting down. State will change to UNINITIALIZED after 164 // onStopDone(). 165 STOPPING, 166 // onError() is called. 167 ERROR, 168 }; 169 170 // This constant is used to tell apart from drain_mode_t enumerations in C2Component.h, which 171 // means no drain request. 172 // Note: this value must be different than all enumerations in drain_mode_t. 173 static constexpr uint32_t NO_DRAIN = ~0u; 174 175 // Internal struct for work queue. 176 struct WorkEntry { 177 std::unique_ptr<C2Work> mWork; 178 uint32_t mDrainMode = NO_DRAIN; 179 }; 180 181 // Internal struct to keep the information of a specific graphic block. 182 struct GraphicBlockInfo { 183 enum class State { 184 OWNED_BY_COMPONENT, // Owned by this component. 185 OWNED_BY_ACCELERATOR, // Owned by video decode accelerator. 186 OWNED_BY_CLIENT, // Owned by client. 187 }; 188 189 // The ID of this block used for accelerator. 190 int32_t mBlockId = -1; 191 // The ID of this block used in block pool. It indicates slot index for bufferqueue-backed 192 // block pool, and buffer ID of BufferPoolData for bufferpool block pool. 193 uint32_t mPoolId = 0; 194 State mState = State::OWNED_BY_COMPONENT; 195 // Graphic block buffer allocated from allocator. The graphic block should be owned until 196 // it is passed to client. 197 std::shared_ptr<C2GraphicBlock> mGraphicBlock; 198 // HAL pixel format used while importing to VDA. 199 HalPixelFormat mPixelFormat; 200 // The handle dupped from graphic block for importing to VDA. 201 ::base::ScopedFD mHandle; 202 // VideoFramePlane information for importing to VDA. 203 std::vector<VideoFramePlane> mPlanes; 204 }; 205 206 struct VideoFormat { 207 HalPixelFormat mPixelFormat = HalPixelFormat::UNKNOWN; 208 uint32_t mMinNumBuffers = 0; 209 media::Size mCodedSize; 210 media::Rect mVisibleRect; 211 VideoFormatVideoFormat212 VideoFormat() {} 213 VideoFormat(HalPixelFormat pixelFormat, uint32_t minNumBuffers, media::Size codedSize, 214 media::Rect visibleRect); 215 }; 216 217 // Internal struct for the information of output buffer returned from the accelerator. 218 struct OutputBufferInfo { 219 int32_t mBitstreamId; 220 int32_t mBlockId; 221 }; 222 223 // These tasks should be run on the component thread |mThread|. 224 void onDestroy(); 225 void onStart(media::VideoCodecProfile profile, ::base::WaitableEvent* done); 226 void onQueueWork(std::unique_ptr<C2Work> work); 227 void onDequeueWork(); 228 void onInputBufferDone(int32_t bitstreamId); 229 void onOutputBufferDone(int32_t pictureBufferId, int32_t bitstreamId); 230 void onDrain(uint32_t drainMode); 231 void onDrainDone(); 232 void onFlush(); 233 void onStop(::base::WaitableEvent* done); 234 void onResetDone(); 235 void onFlushDone(); 236 void onStopDone(); 237 void onOutputFormatChanged(std::unique_ptr<VideoFormat> format); 238 void onVisibleRectChanged(const media::Rect& cropRect); 239 void onOutputBufferReturned(std::shared_ptr<C2GraphicBlock> block, uint32_t poolId); 240 void onSurfaceChanged(); 241 242 // Send input buffer to accelerator with specified bitstream id. 243 void sendInputBufferToAccelerator(const C2ConstLinearBlock& input, int32_t bitstreamId); 244 // Send output buffer to accelerator. If |passToAccelerator|, change the ownership to 245 // OWNED_BY_ACCELERATOR of this buffer. 246 void sendOutputBufferToAccelerator(GraphicBlockInfo* info, bool passToAccelerator); 247 // Set crop rectangle infomation to output format. 248 void setOutputFormatCrop(const media::Rect& cropRect); 249 // Helper function to get the specified GraphicBlockInfo object by its id. 250 GraphicBlockInfo* getGraphicBlockById(int32_t blockId); 251 // Helper function to get the specified GraphicBlockInfo object by its pool id. 252 GraphicBlockInfo* getGraphicBlockByPoolId(uint32_t poolId); 253 // Helper function to find the work iterator in |mPendingWorks| by bitstream id. 254 std::deque<std::unique_ptr<C2Work>>::iterator findPendingWorkByBitstreamId(int32_t bitstreamId); 255 // Helper function to get the specified work in |mPendingWorks| by bitstream id. 256 C2Work* getPendingWorkByBitstreamId(int32_t bitstreamId); 257 // Try to apply the output format change. 258 void tryChangeOutputFormat(); 259 // Allocate output buffers (graphic blocks) from block allocator. 260 c2_status_t allocateBuffersFromBlockAllocator(const media::Size& size, uint32_t pixelFormat); 261 // Append allocated buffer (graphic block) to |mGraphicBlocks|. 262 void appendOutputBuffer(std::shared_ptr<C2GraphicBlock> block, uint32_t poolId); 263 // Append allocated buffer (graphic block) to |mGraphicBlocks| in secure mode. 264 void appendSecureOutputBuffer(std::shared_ptr<C2GraphicBlock> block, uint32_t poolId); 265 // Parse coded color aspects from bitstream and configs parameter if applicable. 266 bool parseCodedColorAspects(const C2ConstLinearBlock& input); 267 // Update color aspects for current output buffer. 268 c2_status_t updateColorAspects(); 269 // Dequeue |mPendingBuffersToWork| to put output buffer to corresponding work and report if 270 // finished as many as possible. If |dropIfUnavailable|, drop all pending existing frames 271 // without blocking. 272 void sendOutputBufferToWorkIfAny(bool dropIfUnavailable); 273 // Update |mUndequeuedBlockIds| FIFO by pushing |blockId|. 274 void updateUndequeuedBlockIds(int32_t blockId); 275 276 // Check if the corresponding work is finished by |bitstreamId|. If yes, make onWorkDone call to 277 // listener and erase the work from |mPendingWorks|. 278 void reportWorkIfFinished(int32_t bitstreamId); 279 // Make onWorkDone call to listener for reporting EOS work in |mPendingWorks|. 280 void reportEOSWork(); 281 // Abandon all works in |mPendingWorks| and |mAbandonedWorks|. 282 void reportAbandonedWorks(); 283 // Make onError call to listener for reporting errors. 284 void reportError(c2_status_t error); 285 // Helper function to determine if the work is finished. 286 bool isWorkDone(const C2Work* work) const; 287 288 // Start dequeue thread, return true on success. If |resetBuffersInClient|, reset the counter 289 // |mBuffersInClient| on start. 290 bool startDequeueThread(const media::Size& size, uint32_t pixelFormat, 291 std::shared_ptr<C2BlockPool> blockPool, bool resetBuffersInClient); 292 // Stop dequeue thread. 293 void stopDequeueThread(); 294 // The rountine task running on dequeue thread. 295 void dequeueThreadLoop(const media::Size& size, uint32_t pixelFormat, 296 std::shared_ptr<C2BlockPool> blockPool); 297 298 // The pointer of component interface implementation. 299 std::shared_ptr<IntfImpl> mIntfImpl; 300 // The pointer of component interface. 301 const std::shared_ptr<C2ComponentInterface> mIntf; 302 // The pointer of component listener. 303 std::shared_ptr<Listener> mListener; 304 305 // The main component thread. 306 ::base::Thread mThread; 307 // The task runner on component thread. 308 scoped_refptr<::base::SingleThreadTaskRunner> mTaskRunner; 309 310 // The dequeue buffer loop thread. 311 ::base::Thread mDequeueThread; 312 // The stop signal for dequeue loop which should be atomic (toggled by main thread). 313 std::atomic<bool> mDequeueLoopStop; 314 // The count of buffers owned by client which should be atomic. 315 std::atomic<uint32_t> mBuffersInClient; 316 317 // The following members should be utilized on component thread |mThread|. 318 319 // The initialization result retrieved from VDA. 320 VideoDecodeAcceleratorAdaptor::Result mVDAInitResult; 321 // The pointer of VideoDecodeAcceleratorAdaptor. 322 std::unique_ptr<VideoDecodeAcceleratorAdaptor> mVDAAdaptor; 323 // The done event pointer of stop procedure. It should be restored in onStop() and signaled in 324 // onStopDone(). 325 ::base::WaitableEvent* mStopDoneEvent; 326 // The state machine on component thread. 327 ComponentState mComponentState; 328 // The indicator of draining with EOS. This should be always set along with component going to 329 // DRAINING state, and will be unset either after reportEOSWork() (EOS is outputted), or 330 // reportAbandonedWorks() (drain is cancelled and works are abandoned). 331 bool mPendingOutputEOS; 332 // The vector of storing allocated output graphic block information. 333 std::vector<GraphicBlockInfo> mGraphicBlocks; 334 // The work queue. Works are queued along with drain mode from component API queue_nb and 335 // dequeued by the decode process of component. 336 std::queue<WorkEntry> mQueue; 337 // Store all pending works. The dequeued works are placed here until they are finished and then 338 // sent out by onWorkDone call to listener. 339 std::deque<std::unique_ptr<C2Work>> mPendingWorks; 340 // Store all abandoned works. When component gets flushed/stopped, remaining works in queue are 341 // dumped here and sent out by onWorkDone call to listener after flush/stop is finished. 342 std::vector<std::unique_ptr<C2Work>> mAbandonedWorks; 343 // Store the visible rect provided from VDA. If this is changed, component should issue a 344 // visible size change event. 345 media::Rect mRequestedVisibleRect; 346 // The current output format. 347 VideoFormat mOutputFormat; 348 // The pending output format. We need to wait until all buffers are returned back to apply the 349 // format change. 350 std::unique_ptr<VideoFormat> mPendingOutputFormat; 351 // The color aspects parameter for current decoded output buffers. 352 std::shared_ptr<C2StreamColorAspectsInfo::output> mCurrentColorAspects; 353 // The flag of pending color aspects change. This should be set once we have parsed color 354 // aspects from bitstream by parseCodedColorAspects(), at the same time recorded input frame 355 // index into |mPendingColorAspectsChangeFrameIndex|. 356 // When this flag is true and the corresponding frame index is not less than 357 // |mPendingColorAspectsChangeFrameIndex| for the output buffer in onOutputBufferDone(), update 358 // |mCurrentColorAspects| from component interface and reset the flag. 359 bool mPendingColorAspectsChange; 360 // The record of frame index to update color aspects. Details as above. 361 uint64_t mPendingColorAspectsChangeFrameIndex; 362 // The record of bitstream and block ID of pending output buffers returned from accelerator. 363 std::deque<OutputBufferInfo> mPendingBuffersToWork; 364 // A FIFO queue to record the block IDs which are currently undequequed for display. The size 365 // of this queue will be equal to the minimum number of undequeued buffers. 366 std::deque<int32_t> mUndequeuedBlockIds; 367 368 // The indicator of whether component is in secure mode. 369 bool mSecureMode; 370 371 // The following members should be utilized on parent thread. 372 373 // The input codec profile which is configured in component interface. 374 media::VideoCodecProfile mCodecProfile; 375 // The state machine on parent thread which should be atomic. 376 std::atomic<State> mState; 377 // The mutex lock to synchronize start/stop/reset/release calls. 378 std::mutex mStartStopLock; 379 380 // The WeakPtrFactory for getting weak pointer of this. 381 ::base::WeakPtrFactory<C2VDAComponent> mWeakThisFactory; 382 383 DISALLOW_COPY_AND_ASSIGN(C2VDAComponent); 384 }; 385 386 } // namespace android 387 388 #endif // ANDROID_C2_VDA_COMPONENT_H 389