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> &currentWork,
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:
WorkQueue()205         inline WorkQueue() : mFlush(false), mGeneration(0ul) {}
206 
generation()207         inline uint64_t generation() const { return mGeneration; }
incGeneration()208         inline void incGeneration() { ++mGeneration; mFlush = true; }
209 
210         std::unique_ptr<C2Work> pop_front();
211         void push_back(std::unique_ptr<C2Work> work);
212         bool empty() const;
213         uint32_t drainMode() const;
214         void markDrain(uint32_t drainMode);
popPendingFlush()215         inline bool popPendingFlush() {
216             bool flush = mFlush;
217             mFlush = false;
218             return flush;
219         }
220         void clear();
221 
222     private:
223         struct Entry {
224             std::unique_ptr<C2Work> work;
225             uint32_t drainMode;
226         };
227 
228         bool mFlush;
229         uint64_t mGeneration;
230         std::list<Entry> mQueue;
231     };
232     Mutexed<WorkQueue> mWorkQueue;
233 
234     typedef std::unordered_map<uint64_t, std::unique_ptr<C2Work>> PendingWork;
235     Mutexed<PendingWork> mPendingWork;
236 
237     std::shared_ptr<C2BlockPool> mOutputBlockPool;
238 
239     SimpleC2Component() = delete;
240 };
241 
242 }  // namespace android
243 
244 #endif  // SIMPLE_C2_COMPONENT_H_
245