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 #include <C2Config.h>
25 
26 #include <media/stagefright/foundation/AHandler.h>
27 #include <media/stagefright/foundation/ALooper.h>
28 #include <media/stagefright/foundation/Mutexed.h>
29 
30 struct C2ColorAspectsStruct;
31 
32 namespace android {
33 
34 typedef enum {
35     CONV_FORMAT_I420,
36     CONV_FORMAT_I422,
37     CONV_FORMAT_I444,
38 } CONV_FORMAT_T;
39 
40 void convertYUV420Planar8ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint8_t *srcY,
41                                 const uint8_t *srcU, const uint8_t *srcV, size_t srcYStride,
42                                 size_t srcUStride, size_t srcVStride, size_t dstYStride,
43                                 size_t dstUStride, size_t dstVStride, uint32_t width,
44                                 uint32_t height, bool isMonochrome = false);
45 
46 void convertYUV420Planar16ToY410OrRGBA1010102(
47         uint32_t *dst, const uint16_t *srcY,
48         const uint16_t *srcU, const uint16_t *srcV,
49         size_t srcYStride, size_t srcUStride,
50         size_t srcVStride, size_t dstStride, size_t width, size_t height,
51         std::shared_ptr<const C2ColorAspectsStruct> aspects = nullptr);
52 
53 void convertYUV420Planar16ToYV12(uint8_t *dstY, uint8_t *dstU, uint8_t *dstV, const uint16_t *srcY,
54                                  const uint16_t *srcU, const uint16_t *srcV, size_t srcYStride,
55                                  size_t srcUStride, size_t srcVStride, size_t dstYStride,
56                                  size_t dstUVStride, size_t width, size_t height,
57                                  bool isMonochrome = false);
58 
59 void convertYUV420Planar16ToP010(uint16_t *dstY, uint16_t *dstUV, const uint16_t *srcY,
60                                  const uint16_t *srcU, const uint16_t *srcV, size_t srcYStride,
61                                  size_t srcUStride, size_t srcVStride, size_t dstYStride,
62                                  size_t dstUVStride, size_t width, size_t height,
63                                  bool isMonochrome = false);
64 
65 void convertP010ToYUV420Planar16(uint16_t *dstY, uint16_t *dstU, uint16_t *dstV,
66                                  const uint16_t *srcY, const uint16_t *srcUV,
67                                  size_t srcYStride, size_t srcUVStride, size_t dstYStride,
68                                  size_t dstUStride, size_t dstVStride, size_t width,
69                                  size_t height, bool isMonochrome = false);
70 
71 void convertRGBA1010102ToYUV420Planar16(uint16_t* dstY, uint16_t* dstU, uint16_t* dstV,
72                                         const uint32_t* srcRGBA, size_t srcRGBStride, size_t width,
73                                         size_t height, C2Color::matrix_t colorMatrix,
74                                         C2Color::range_t colorRange);
75 void convertPlanar16ToY410OrRGBA1010102(uint8_t* dst, const uint16_t* srcY, const uint16_t* srcU,
76                                         const uint16_t* srcV, size_t srcYStride, size_t srcUStride,
77                                         size_t srcVStride, size_t dstStride, size_t width,
78                                         size_t height,
79                                         std::shared_ptr<const C2ColorAspectsStruct> aspects,
80                                         CONV_FORMAT_T format);
81 
82 void convertPlanar16ToP010(uint16_t* dstY, uint16_t* dstUV, const uint16_t* srcY,
83                            const uint16_t* srcU, const uint16_t* srcV, size_t srcYStride,
84                            size_t srcUStride, size_t srcVStride, size_t dstYStride,
85                            size_t dstUStride, size_t dstVStride, size_t width, size_t height,
86                            bool isMonochrome, CONV_FORMAT_T format, uint16_t* tmpFrameBuffer,
87                            size_t tmpFrameBufferSize);
88 void convertPlanar16ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV, const uint16_t* srcY,
89                            const uint16_t* srcU, const uint16_t* srcV, size_t srcYStride,
90                            size_t srcUStride, size_t srcVStride, size_t dstYStride,
91                            size_t dstUStride, size_t dstVStride, size_t width, size_t height,
92                            bool isMonochrome, CONV_FORMAT_T format, uint16_t* tmpFrameBuffer,
93                            size_t tmpFrameBufferSize);
94 void convertPlanar8ToYV12(uint8_t* dstY, uint8_t* dstU, uint8_t* dstV, const uint8_t* srcY,
95                           const uint8_t* srcU, const uint8_t* srcV, size_t srcYStride,
96                           size_t srcUStride, size_t srcVStride, size_t dstYStride,
97                           size_t dstUStride, size_t dstVStride, uint32_t width, uint32_t height,
98                           bool isMonochrome, CONV_FORMAT_T format);
99 
100 class SimpleC2Component
101         : public C2Component, public std::enable_shared_from_this<SimpleC2Component> {
102 public:
103     explicit SimpleC2Component(
104             const std::shared_ptr<C2ComponentInterface> &intf);
105     virtual ~SimpleC2Component();
106 
107     // C2Component
108     // From C2Component
109     virtual c2_status_t setListener_vb(
110             const std::shared_ptr<Listener> &listener, c2_blocking_t mayBlock) override;
111     virtual c2_status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) override;
112     virtual c2_status_t announce_nb(const std::vector<C2WorkOutline> &items) override;
113     virtual c2_status_t flush_sm(
114             flush_mode_t mode, std::list<std::unique_ptr<C2Work>>* const flushedWork) override;
115     virtual c2_status_t drain_nb(drain_mode_t mode) override;
116     virtual c2_status_t start() override;
117     virtual c2_status_t stop() override;
118     virtual c2_status_t reset() override;
119     virtual c2_status_t release() override;
120     virtual std::shared_ptr<C2ComponentInterface> intf() override;
121 
122     // for handler
123     bool processQueue();
124 
125 protected:
126     /**
127      * Initialize internal states of the component according to the config set
128      * in the interface.
129      *
130      * This method is called during start(), but only at the first invocation or
131      * after reset().
132      */
133     virtual c2_status_t onInit() = 0;
134 
135     /**
136      * Stop the component.
137      */
138     virtual c2_status_t onStop() = 0;
139 
140     /**
141      * Reset the component.
142      */
143     virtual void onReset() = 0;
144 
145     /**
146      * Release the component.
147      */
148     virtual void onRelease() = 0;
149 
150     /**
151      * Flush the component.
152      */
153     virtual c2_status_t onFlush_sm() = 0;
154 
155     /**
156      * Process the given work and finish pending work using finish().
157      *
158      * \param[in,out]   work    the work to process
159      * \param[in]       pool    the pool to use for allocating output blocks.
160      */
161     virtual void process(
162             const std::unique_ptr<C2Work> &work,
163             const std::shared_ptr<C2BlockPool> &pool) = 0;
164 
165     /**
166      * Drain the component and finish pending work using finish().
167      *
168      * \param[in]   drainMode   mode of drain.
169      * \param[in]   pool        the pool to use for allocating output blocks.
170      *
171      * \retval C2_OK            The component has drained all pending output
172      *                          work.
173      * \retval C2_OMITTED       Unsupported mode (e.g. DRAIN_CHAIN)
174      */
175     virtual c2_status_t drain(
176             uint32_t drainMode,
177             const std::shared_ptr<C2BlockPool> &pool) = 0;
178 
179     // for derived classes
180     /**
181      * Finish pending work.
182      *
183      * This method will retrieve the pending work according to |frameIndex| and
184      * feed the work into |fillWork| function. |fillWork| must be
185      * "non-blocking". Once |fillWork| returns the filled work will be returned
186      * to the client.
187      *
188      * \param[in]   frameIndex    the index of the pending work
189      * \param[in]   fillWork      the function to fill the retrieved work.
190      */
191     void finish(uint64_t frameIndex, std::function<void(const std::unique_ptr<C2Work> &)> fillWork);
192 
193     /**
194      * Clone pending or current work and send the work back to client.
195      *
196      * This method will retrieve and clone the pending or current work according
197      * to |frameIndex| and feed the work into |fillWork| function. |fillWork|
198      * must be "non-blocking". Once |fillWork| returns the filled work will be
199      * returned to the client.
200      *
201      * \param[in]   frameIndex    the index of the work
202      * \param[in]   currentWork   the current work under processing
203      * \param[in]   fillWork      the function to fill the retrieved work.
204      */
205     void cloneAndSend(
206             uint64_t frameIndex,
207             const std::unique_ptr<C2Work> &currentWork,
208             std::function<void(const std::unique_ptr<C2Work> &)> fillWork);
209 
210 
211     std::shared_ptr<C2Buffer> createLinearBuffer(
212             const std::shared_ptr<C2LinearBlock> &block, size_t offset, size_t size);
213 
214     std::shared_ptr<C2Buffer> createGraphicBuffer(
215             const std::shared_ptr<C2GraphicBlock> &block,
216             const C2Rect &crop);
217 
218     static constexpr uint32_t NO_DRAIN = ~0u;
219 
220     C2ReadView mDummyReadView;
221     int getHalPixelFormatForBitDepth10(bool allowRGBA1010102);
222 
223 private:
224     const std::shared_ptr<C2ComponentInterface> mIntf;
225 
226     class WorkHandler : public AHandler {
227     public:
228         enum {
229             kWhatProcess,
230             kWhatInit,
231             kWhatStart,
232             kWhatStop,
233             kWhatReset,
234             kWhatRelease,
235         };
236 
237         WorkHandler();
238         ~WorkHandler() override = default;
239 
240         void setComponent(const std::shared_ptr<SimpleC2Component> &thiz);
241 
242     protected:
243         void onMessageReceived(const sp<AMessage> &msg) override;
244 
245     private:
246         std::weak_ptr<SimpleC2Component> mThiz;
247         bool mRunning;
248     };
249 
250     enum {
251         UNINITIALIZED,
252         STOPPED,
253         RUNNING,
254     };
255 
256     struct ExecState {
ExecStateExecState257         ExecState() : mState(UNINITIALIZED) {}
258 
259         int mState;
260         std::shared_ptr<C2Component::Listener> mListener;
261     };
262     Mutexed<ExecState> mExecState;
263 
264     sp<ALooper> mLooper;
265     sp<WorkHandler> mHandler;
266 
267     class WorkQueue {
268     public:
269         typedef std::unordered_map<uint64_t, std::unique_ptr<C2Work>> PendingWork;
270 
WorkQueue()271         inline WorkQueue() : mFlush(false), mGeneration(0ul) {}
272 
generation()273         inline uint64_t generation() const { return mGeneration; }
incGeneration()274         inline void incGeneration() { ++mGeneration; mFlush = true; }
275 
276         std::unique_ptr<C2Work> pop_front();
277         void push_back(std::unique_ptr<C2Work> work);
278         bool empty() const;
279         uint32_t drainMode() const;
280         void markDrain(uint32_t drainMode);
popPendingFlush()281         inline bool popPendingFlush() {
282             bool flush = mFlush;
283             mFlush = false;
284             return flush;
285         }
286         void clear();
pending()287         PendingWork &pending() { return mPendingWork; }
288 
289     private:
290         struct Entry {
291             std::unique_ptr<C2Work> work;
292             uint32_t drainMode;
293         };
294 
295         bool mFlush;
296         uint64_t mGeneration;
297         std::list<Entry> mQueue;
298         PendingWork mPendingWork;
299     };
300     Mutexed<WorkQueue> mWorkQueue;
301 
302     class BlockingBlockPool;
303     std::shared_ptr<BlockingBlockPool> mOutputBlockPool;
304 
305     std::vector<int> mBitDepth10HalPixelFormats;
306     SimpleC2Component() = delete;
307 };
308 
309 }  // namespace android
310 
311 #endif  // SIMPLE_C2_COMPONENT_H_
312