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