1 /*
2  * Copyright 2023 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 CODEC2_COMMON_MULTI_ACCESSUNIT_HELPER_H
18 #define CODEC2_COMMON_MULTI_ACCESSUNIT_HELPER_H
19 
20 #include <hidl/Status.h>
21 #include <hwbinder/IBinder.h>
22 
23 #include <C2Config.h>
24 #include <util/C2InterfaceHelper.h>
25 #include <C2Buffer.h>
26 #include <C2.h>
27 
28 #include <set>
29 #include <memory>
30 #include <mutex>
31 
32 namespace android {
33 
34 struct MultiAccessUnitHelper;
35 
36 struct MultiAccessUnitInterface : public C2InterfaceHelper {
37     explicit MultiAccessUnitInterface(
38             const std::shared_ptr<C2ComponentInterface>& interface,
39             std::shared_ptr<C2ReflectorHelper> helper);
40 
41     bool isParamSupported(C2Param::Index index);
42     C2LargeFrame::output getLargeFrameParam() const;
43     C2Component::kind_t kind() const;
44     bool isValidField(const C2ParamField &field) const;
45 
46 protected:
47     bool getDecoderSampleRateAndChannelCount(
48             uint32_t * const sampleRate_, uint32_t * const channelCount_) const;
49     bool getMaxInputSize(C2StreamMaxBufferSizeInfo::input* const maxInputSize) const;
50     const std::shared_ptr<C2ComponentInterface> mC2ComponentIntf;
51     std::shared_ptr<C2LargeFrame::output> mLargeFrameParams;
52     C2ComponentKindSetting mKind;
53     std::set<C2Param::Index> mSupportedParamIndexSet;
54     std::vector<C2ParamField> mParamFields;
55 
56     friend struct MultiAccessUnitHelper;
57 };
58 
59 struct MultiAccessUnitHelper {
60 public:
61     MultiAccessUnitHelper(
62             const std::shared_ptr<MultiAccessUnitInterface>& intf,
63             std::shared_ptr<C2BlockPool> &linearPool);
64 
65     virtual ~MultiAccessUnitHelper();
66 
67     static bool isEnabledOnPlatform();
68 
69     /*
70      * Scatters the incoming linear buffer into access-unit sized buffers
71      * based on the access-unit info.
72      */
73     c2_status_t scatter(
74             std::list<std::unique_ptr<C2Work>> &c2workItems,
75             std::list<std::list<std::unique_ptr<C2Work>>> * const processedWork);
76 
77     /*
78      * Gathers different access-units into a single buffer based on the scatter list
79      * and the configured max and threshold sizes. This also generates the associated
80      * access-unit information and attach it with the final result.
81      */
82     c2_status_t gather(
83             std::list<std::unique_ptr<C2Work>> &c2workItems,
84             std::list<std::unique_ptr<C2Work>> * const processedWork);
85 
86     /*
87      * Flushes the codec and generated the list of flushed buffers.
88      */
89     c2_status_t flush(
90             std::list<std::unique_ptr<C2Work>> * const c2flushedWorks);
91 
92     /*
93      * Gets all the pending buffers under generation in c2workItems.
94      */
95     c2_status_t error(std::list<std::unique_ptr<C2Work>> * const c2workItems);
96 
97     /*
98      * Get the interface object of this handler.
99      */
100     std::shared_ptr<MultiAccessUnitInterface> getInterface();
101 
102     /*
103      * Gets the status of the object. This really is to make sure that
104      * all the allocators are configured properly within the handler.
105      */
106     bool getStatus();
107 
108     /*
109      * Resets the structures inside the handler.
110      */
111     void reset();
112 
113 protected:
114 
115     struct MultiAccessUnitInfo {
116         /*
117          * From the input
118          * Ordinal of the input frame
119          */
120         C2WorkOrdinalStruct inOrdinal;
121 
122         /*
123          * Frame indexes of the scattered buffers
124          */
125         std::set<uint64_t> mComponentFrameIds;
126 
127         /*
128          * For the output
129          * Current output block.
130          */
131         std::shared_ptr<C2LinearBlock> mBlock;
132 
133         /*
134          * Write view of current block
135          */
136         std::shared_ptr<C2WriteView> mWview;
137 
138         /*
139          * C2Info related to the current mBlock
140          */
141         std::vector<std::shared_ptr<const C2Info>> mInfos;
142 
143         /*
144          * Vector for holding config updates from the wrapper
145          */
146         std::vector<std::unique_ptr<C2Param>> mConfigUpdate;
147 
148         /*
149          * C2AccessUnitInfos for the current buffer
150          */
151         std::vector<C2AccessUnitInfosStruct> mAccessUnitInfos;
152 
153         /*
154          * Current tuning used to process this input work
155          */
156         C2LargeFrame::output mLargeFrameTuning;
157 
158         /*
159          * Current output C2Work being processed
160          */
161         std::unique_ptr<C2Work> mLargeWork;
162 
163         /*
164          * For holding a reference to the incoming buffer
165          */
166         std::vector<std::shared_ptr<C2Buffer>> mInputC2Ref;
167 
MultiAccessUnitInfoMultiAccessUnitHelper::MultiAccessUnitInfo168         MultiAccessUnitInfo(C2WorkOrdinalStruct ordinal):inOrdinal(ordinal) {
169 
170         }
171 
172         /*
173          * Resets this frame
174          */
175         void reset();
176     };
177 
178     /*
179      * Reconfigure helper
180      */
181     bool tryReconfigure(const std::unique_ptr<C2Param> &p);
182 
183     /*
184      * Creates a linear block to be used with work
185      */
186     c2_status_t createLinearBlock(MultiAccessUnitInfo &frame);
187 
188     /*
189      * Processes worklets from the component
190      */
191     c2_status_t processWorklets(MultiAccessUnitInfo &frame,
192                 std::unique_ptr<C2Work> &work,
193                 const std::function <void(std::unique_ptr<C2Work>&)> &addWork);
194 
195     /*
196      * Finalizes the work to be send out.
197      */
198     c2_status_t finalizeWork(MultiAccessUnitInfo &frame,
199             uint32_t flags = 0, bool forceComplete = false);
200 
201     /*
202      * Merges different access unit infos if possible
203      */
204     void mergeAccessUnitInfo(MultiAccessUnitInfo &frame,
205             uint32_t flags,
206             uint32_t size,
207             int64_t timestamp);
208 
209     // Flag to allow dynamic on/off settings on this helper.
210     // Once enabled and buffers in transit, it is not possible
211     // to turn this module off by setting the max output value
212     // to 0. This is because the skip cut buffer expects the
213     // metadata to be always present along with a valid buffer.
214     // This flag is used to monitor that state of this module.
215     bool mMultiAccessOnOffAllowed;
216 
217     bool mInit;
218 
219     // Interface of this module
220     std::shared_ptr<MultiAccessUnitInterface> mInterface;
221     // Local pool id used for output buffer allocation
222     C2BlockPool::local_id_t mBlockPoolId;
223     // C2Blockpool for output buffer allocation
224     std::shared_ptr<C2BlockPool> mLinearPool;
225     // FrameIndex for the current outgoing work
226     std::atomic_uint64_t mFrameIndex;
227     // Mutex to protect mFrameHolder
228     std::mutex mLock;
229     // List of Infos that contains the input and
230     // output work and buffer objects
231     std::list<MultiAccessUnitInfo> mFrameHolder;
232 };
233 
234 }  // namespace android
235 
236 #endif  // CODEC2_COMMON_MULTI_ACCESSUNIT_HELPER_H
237