1 /* 2 * Copyright (C) 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 SIMPLE_C2_COMPONENT_H_ 18 #define SIMPLE_C2_COMPONENT_H_ 19 20 #include <list> 21 #include <unordered_map> 22 23 #include <C2Component.h> 24 25 #include <media/stagefright/foundation/AHandler.h> 26 #include <media/stagefright/foundation/ALooper.h> 27 #include <media/stagefright/foundation/Mutexed.h> 28 29 namespace android { 30 31 class SimpleC2Component 32 : public C2Component, public std::enable_shared_from_this<SimpleC2Component> { 33 public: 34 explicit SimpleC2Component( 35 const std::shared_ptr<C2ComponentInterface> &intf); 36 virtual ~SimpleC2Component(); 37 38 // C2Component 39 // From C2Component 40 virtual c2_status_t setListener_vb( 41 const std::shared_ptr<Listener> &listener, c2_blocking_t mayBlock) override; 42 virtual c2_status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override; 43 virtual c2_status_t announce_nb(const std::vector<C2WorkOutline> &items) override; 44 virtual c2_status_t flush_sm( 45 flush_mode_t mode, std::list<std::unique_ptr<C2Work>>* const flushedWork) override; 46 virtual c2_status_t drain_nb(drain_mode_t mode) override; 47 virtual c2_status_t start() override; 48 virtual c2_status_t stop() override; 49 virtual c2_status_t reset() override; 50 virtual c2_status_t release() override; 51 virtual std::shared_ptr<C2ComponentInterface> intf() override; 52 53 // for handler 54 bool processQueue(); 55 56 protected: 57 /** 58 * Initialize internal states of the component according to the config set 59 * in the interface. 60 * 61 * This method is called during start(), but only at the first invocation or 62 * after reset(). 63 */ 64 virtual c2_status_t onInit() = 0; 65 66 /** 67 * Stop the component. 68 */ 69 virtual c2_status_t onStop() = 0; 70 71 /** 72 * Reset the component. 73 */ 74 virtual void onReset() = 0; 75 76 /** 77 * Release the component. 78 */ 79 virtual void onRelease() = 0; 80 81 /** 82 * Flush the component. 83 */ 84 virtual c2_status_t onFlush_sm() = 0; 85 86 /** 87 * Process the given work and finish pending work using finish(). 88 * 89 * \param[in,out] work the work to process 90 * \param[in] pool the pool to use for allocating output blocks. 91 */ 92 virtual void process( 93 const std::unique_ptr<C2Work> &work, 94 const std::shared_ptr<C2BlockPool> &pool) = 0; 95 96 /** 97 * Drain the component and finish pending work using finish(). 98 * 99 * \param[in] drainMode mode of drain. 100 * \param[in] pool the pool to use for allocating output blocks. 101 * 102 * \retval C2_OK The component has drained all pending output 103 * work. 104 * \retval C2_OMITTED Unsupported mode (e.g. DRAIN_CHAIN) 105 */ 106 virtual c2_status_t drain( 107 uint32_t drainMode, 108 const std::shared_ptr<C2BlockPool> &pool) = 0; 109 110 // for derived classes 111 /** 112 * Finish pending work. 113 * 114 * This method will retrieve the pending work according to |frameIndex| and 115 * feed the work into |fillWork| function. |fillWork| must be 116 * "non-blocking". Once |fillWork| returns the filled work will be returned 117 * to the client. 118 * 119 * \param[in] frameIndex the index of the pending work 120 * \param[in] fillWork the function to fill the retrieved work. 121 */ 122 void finish(uint64_t frameIndex, std::function<void(const std::unique_ptr<C2Work> &)> fillWork); 123 124 /** 125 * Clone pending or current work and send the work back to client. 126 * 127 * This method will retrieve and clone the pending or current work according 128 * to |frameIndex| and feed the work into |fillWork| function. |fillWork| 129 * must be "non-blocking". Once |fillWork| returns the filled work will be 130 * returned to the client. 131 * 132 * \param[in] frameIndex the index of the work 133 * \param[in] currentWork the current work under processing 134 * \param[in] fillWork the function to fill the retrieved work. 135 */ 136 void cloneAndSend( 137 uint64_t frameIndex, 138 const std::unique_ptr<C2Work> ¤tWork, 139 std::function<void(const std::unique_ptr<C2Work> &)> fillWork); 140 141 142 std::shared_ptr<C2Buffer> createLinearBuffer( 143 const std::shared_ptr<C2LinearBlock> &block); 144 145 std::shared_ptr<C2Buffer> createLinearBuffer( 146 const std::shared_ptr<C2LinearBlock> &block, size_t offset, size_t size); 147 148 std::shared_ptr<C2Buffer> createGraphicBuffer( 149 const std::shared_ptr<C2GraphicBlock> &block); 150 151 std::shared_ptr<C2Buffer> createGraphicBuffer( 152 const std::shared_ptr<C2GraphicBlock> &block, 153 const C2Rect &crop); 154 155 static constexpr uint32_t NO_DRAIN = ~0u; 156 157 C2ReadView mDummyReadView; 158 159 private: 160 const std::shared_ptr<C2ComponentInterface> mIntf; 161 162 class WorkHandler : public AHandler { 163 public: 164 enum { 165 kWhatProcess, 166 kWhatInit, 167 kWhatStart, 168 kWhatStop, 169 kWhatReset, 170 kWhatRelease, 171 }; 172 173 WorkHandler(); 174 ~WorkHandler() override = default; 175 176 void setComponent(const std::shared_ptr<SimpleC2Component> &thiz); 177 178 protected: 179 void onMessageReceived(const sp<AMessage> &msg) override; 180 181 private: 182 std::weak_ptr<SimpleC2Component> mThiz; 183 bool mRunning; 184 }; 185 186 enum { 187 UNINITIALIZED, 188 STOPPED, 189 RUNNING, 190 }; 191 192 struct ExecState { ExecStateExecState193 ExecState() : mState(UNINITIALIZED) {} 194 195 int mState; 196 std::shared_ptr<C2Component::Listener> mListener; 197 }; 198 Mutexed<ExecState> mExecState; 199 200 sp<ALooper> mLooper; 201 sp<WorkHandler> mHandler; 202 203 class WorkQueue { 204 public: 205 typedef std::unordered_map<uint64_t, std::unique_ptr<C2Work>> PendingWork; 206 WorkQueue()207 inline WorkQueue() : mFlush(false), mGeneration(0ul) {} 208 generation()209 inline uint64_t generation() const { return mGeneration; } incGeneration()210 inline void incGeneration() { ++mGeneration; mFlush = true; } 211 212 std::unique_ptr<C2Work> pop_front(); 213 void push_back(std::unique_ptr<C2Work> work); 214 bool empty() const; 215 uint32_t drainMode() const; 216 void markDrain(uint32_t drainMode); popPendingFlush()217 inline bool popPendingFlush() { 218 bool flush = mFlush; 219 mFlush = false; 220 return flush; 221 } 222 void clear(); pending()223 PendingWork &pending() { return mPendingWork; } 224 225 private: 226 struct Entry { 227 std::unique_ptr<C2Work> work; 228 uint32_t drainMode; 229 }; 230 231 bool mFlush; 232 uint64_t mGeneration; 233 std::list<Entry> mQueue; 234 PendingWork mPendingWork; 235 }; 236 Mutexed<WorkQueue> mWorkQueue; 237 238 class BlockingBlockPool; 239 std::shared_ptr<BlockingBlockPool> mOutputBlockPool; 240 241 SimpleC2Component() = delete; 242 }; 243 244 } // namespace android 245 246 #endif // SIMPLE_C2_COMPONENT_H_ 247