1 /*
2  * Copyright 2018 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_HIDL_CLIENT_H
18 #define CODEC2_HIDL_CLIENT_H
19 
20 #include <gui/IGraphicBufferProducer.h>
21 #include <codec2/hidl/1.0/ClientBlockHelper.h>
22 #include <C2PlatformSupport.h>
23 #include <C2Component.h>
24 #include <C2Buffer.h>
25 #include <C2Param.h>
26 #include <C2.h>
27 
28 #include <hidl/HidlSupport.h>
29 #include <utils/StrongPointer.h>
30 
31 #include <functional>
32 #include <map>
33 #include <memory>
34 #include <mutex>
35 
36 /**
37  * This file contains minimal interfaces for the framework to access Codec2.0.
38  *
39  * Codec2Client is the main class that contains the following inner classes:
40  * - Listener
41  * - Configurable
42  * - Interface
43  * - Component
44  *
45  * Classes in Codec2Client, interfaces in Codec2.0, and  HIDL interfaces are
46  * related as follows:
47  * - Codec2Client <==> C2ComponentStore <==> IComponentStore
48  * - Codec2Client::Listener <==> C2Component::Listener <==> IComponentListener
49  * - Codec2Client::Configurable <==> [No equivalent] <==> IConfigurable
50  * - Codec2Client::Interface <==> C2ComponentInterface <==> IComponentInterface
51  * - Codec2Client::Component <==> C2Component <==> IComponent
52  *
53  * The entry point is Codec2Client::CreateFromService(), which creates a
54  * Codec2Client object. From Codec2Client, Interface and Component objects can
55  * be created by calling createComponent() and createInterface().
56  *
57  * createComponent() takes a Listener object, which must be implemented by the
58  * user.
59  *
60  * At the present, createBlockPool() is the only method that yields a
61  * Configurable object. Note, however, that Interface, Component and
62  * Codec2Client are all subclasses of Configurable.
63  */
64 
65 // Forward declaration of relevant HIDL interfaces
66 
67 namespace android::hardware::media::c2::V1_0 {
68 struct IConfigurable;
69 struct IComponent;
70 struct IComponentInterface;
71 struct IComponentStore;
72 struct IInputSink;
73 struct IInputSurface;
74 struct IInputSurfaceConnection;
75 }  // namespace android::hardware::media::c2::V1_0
76 
77 namespace android::hardware::media::bufferpool::V2_0 {
78 struct IClientManager;
79 }  // namespace android::hardware::media::bufferpool::V2_0
80 
81 namespace android::hardware::graphics::bufferqueue::V1_0 {
82 struct IGraphicBufferProducer;
83 }  // android::hardware::graphics::bufferqueue::V1_0
84 
85 namespace android::hardware::media::omx::V1_0 {
86 struct IGraphicBufferSource;
87 }  // namespace android::hardware::media::omx::V1_0
88 
89 namespace android {
90 
91 // This class is supposed to be called Codec2Client::Configurable, but forward
92 // declaration of an inner class is not possible.
93 struct Codec2ConfigurableClient {
94 
95     typedef ::android::hardware::media::c2::V1_0::IConfigurable Base;
96 
97     const C2String& getName() const;
98 
99     c2_status_t query(
100             const std::vector<C2Param*>& stackParams,
101             const std::vector<C2Param::Index> &heapParamIndices,
102             c2_blocking_t mayBlock,
103             std::vector<std::unique_ptr<C2Param>>* const heapParams) const;
104 
105     c2_status_t config(
106             const std::vector<C2Param*> &params,
107             c2_blocking_t mayBlock,
108             std::vector<std::unique_ptr<C2SettingResult>>* const failures);
109 
110     c2_status_t querySupportedParams(
111             std::vector<std::shared_ptr<C2ParamDescriptor>>* const params
112             ) const;
113 
114     c2_status_t querySupportedValues(
115             std::vector<C2FieldSupportedValuesQuery>& fields,
116             c2_blocking_t mayBlock) const;
117 
118     // base cannot be null.
119     Codec2ConfigurableClient(const sp<Base>& base);
120 
121 protected:
122     sp<Base> mBase;
123     C2String mName;
124 
125     friend struct Codec2Client;
126 };
127 
128 struct Codec2Client : public Codec2ConfigurableClient {
129 
130     typedef ::android::hardware::media::c2::V1_0::IComponentStore Base;
131 
132     struct Listener;
133 
134     typedef Codec2ConfigurableClient Configurable;
135 
136     struct Component;
137 
138     struct Interface;
139 
140     struct InputSurface;
141 
142     struct InputSurfaceConnection;
143 
144     typedef Codec2Client Store;
145 
146     sp<Base> const& getBase() const;
147 
148     std::string const& getServiceName() const;
149 
150     c2_status_t createComponent(
151             C2String const& name,
152             std::shared_ptr<Listener> const& listener,
153             std::shared_ptr<Component>* const component);
154 
155     c2_status_t createInterface(
156             C2String const& name,
157             std::shared_ptr<Interface>* const interface);
158 
159     c2_status_t createInputSurface(
160             std::shared_ptr<InputSurface>* const inputSurface);
161 
162     std::vector<C2Component::Traits> const& listComponents() const;
163 
164     c2_status_t copyBuffer(
165             std::shared_ptr<C2Buffer> const& src,
166             std::shared_ptr<C2Buffer> const& dst);
167 
168     std::shared_ptr<C2ParamReflector> getParamReflector();
169 
170     // Returns the list of IComponentStore service names that are available on
171     // the device. This list is specified at the build time in manifest files.
172     // Note: A software service will have "_software" as a suffix.
173     static std::vector<std::string> const& GetServiceNames();
174 
175     // Create a service with a given service name.
176     static std::shared_ptr<Codec2Client> CreateFromService(char const* name);
177 
178     // Get clients to all services.
179     static std::vector<std::shared_ptr<Codec2Client>> CreateFromAllServices();
180 
181     // Try to create a component with a given name from all known
182     // IComponentStore services. numberOfAttempts determines the number of times
183     // to retry the HIDL call if the transaction fails.
184     static std::shared_ptr<Component> CreateComponentByName(
185             char const* componentName,
186             std::shared_ptr<Listener> const& listener,
187             std::shared_ptr<Codec2Client>* owner = nullptr,
188             size_t numberOfAttempts = 10);
189 
190     // Try to create a component interface with a given name from all known
191     // IComponentStore services. numberOfAttempts determines the number of times
192     // to retry the HIDL call if the transaction fails.
193     static std::shared_ptr<Interface> CreateInterfaceByName(
194             char const* interfaceName,
195             std::shared_ptr<Codec2Client>* owner = nullptr,
196             size_t numberOfAttempts = 10);
197 
198     // List traits from all known IComponentStore services.
199     static std::vector<C2Component::Traits> const& ListComponents();
200 
201     // Create an input surface.
202     static std::shared_ptr<InputSurface> CreateInputSurface(
203             char const* serviceName = nullptr);
204 
205     // base cannot be null.
206     Codec2Client(sp<Base> const& base, size_t serviceIndex);
207 
208 protected:
209     sp<Base> mBase;
210 
211     // Finds the first store where the predicate returns C2_OK and returns the
212     // last predicate result. The predicate will be tried on all stores. The
213     // function will return C2_OK the first time the predicate returns C2_OK,
214     // or it will return the value from the last time that predicate is tried.
215     // (The latter case corresponds to a failure on every store.) The order of
216     // the stores to try is the same as the return value of GetServiceNames().
217     //
218     // key is used to remember the last store with which the predicate last
219     // succeeded. If the last successful store is cached, it will be tried
220     // first before all the stores are tried. Note that the last successful
221     // store will be tried twice---first before all the stores, and another time
222     // with all the stores.
223     //
224     // If an attempt to evaluate the predicate results in a transaction failure,
225     // repeated attempts will be made until the predicate returns without a
226     // transaction failure or numberOfAttempts attempts have been made.
227     static c2_status_t ForAllServices(
228             const std::string& key,
229             size_t numberOfAttempts,
230             std::function<c2_status_t(std::shared_ptr<Codec2Client> const&)>
231                 predicate);
232 
233     size_t mServiceIndex;
234     mutable std::vector<C2Component::Traits> mTraitsList;
235 
236     sp<::android::hardware::media::bufferpool::V2_0::IClientManager>
237             mHostPoolManager;
238 
239     static std::shared_ptr<Codec2Client> _CreateFromIndex(size_t index);
240 
241     std::vector<C2Component::Traits> _listComponents(bool* success) const;
242 
243     class Cache;
244 };
245 
246 struct Codec2Client::Interface : public Codec2Client::Configurable {
247 
248     typedef ::android::hardware::media::c2::V1_0::IComponentInterface Base;
249 
250     Interface(const sp<Base>& base);
251 
252 protected:
253     sp<Base> mBase;
254 };
255 
256 struct Codec2Client::Listener {
257 
258     // This is called when the component produces some output.
259     virtual void onWorkDone(
260             const std::weak_ptr<Component>& comp,
261             std::list<std::unique_ptr<C2Work>>& workItems) = 0;
262 
263     // This is called when the component goes into a tripped state.
264     virtual void onTripped(
265             const std::weak_ptr<Component>& comp,
266             const std::vector<std::shared_ptr<C2SettingResult>>& settingResults
267             ) = 0;
268 
269     // This is called when the component encounters an error.
270     virtual void onError(
271             const std::weak_ptr<Component>& comp,
272             uint32_t errorCode) = 0;
273 
274     // This is called when the process that hosts the component shuts down
275     // unexpectedly.
276     virtual void onDeath(
277             const std::weak_ptr<Component>& comp) = 0;
278 
279     // This is called when an input buffer is no longer in use by the codec.
280     // Input buffers that have been returned by onWorkDone() or flush() will not
281     // trigger a call to this function.
282     virtual void onInputBufferDone(
283             uint64_t frameIndex, size_t arrayIndex) = 0;
284 
285     // This is called when the component becomes aware of a frame being
286     // rendered.
287     virtual void onFrameRendered(
288             uint64_t bufferQueueId,
289             int32_t slotId,
290             int64_t timestampNs) = 0;
291 
292     virtual ~Listener();
293 
294 };
295 
296 struct Codec2Client::Component : public Codec2Client::Configurable {
297 
298     typedef ::android::hardware::media::c2::V1_0::IComponent Base;
299 
300     c2_status_t createBlockPool(
301             C2Allocator::id_t id,
302             C2BlockPool::local_id_t* blockPoolId,
303             std::shared_ptr<Configurable>* configurable);
304 
305     c2_status_t destroyBlockPool(
306             C2BlockPool::local_id_t localId);
307 
308     c2_status_t queue(
309             std::list<std::unique_ptr<C2Work>>* const items);
310 
311     c2_status_t flush(
312             C2Component::flush_mode_t mode,
313             std::list<std::unique_ptr<C2Work>>* const flushedWork);
314 
315     c2_status_t drain(C2Component::drain_mode_t mode);
316 
317     c2_status_t start();
318 
319     c2_status_t stop();
320 
321     c2_status_t reset();
322 
323     c2_status_t release();
324 
325     typedef ::android::
326             IGraphicBufferProducer IGraphicBufferProducer;
327     typedef IGraphicBufferProducer::
328             QueueBufferInput QueueBufferInput;
329     typedef IGraphicBufferProducer::
330             QueueBufferOutput QueueBufferOutput;
331 
332     typedef ::android::hardware::graphics::bufferqueue::V1_0::
333             IGraphicBufferProducer HGraphicBufferProducer1;
334     typedef ::android::hardware::graphics::bufferqueue::V2_0::
335             IGraphicBufferProducer HGraphicBufferProducer2;
336     typedef ::android::hardware::media::omx::V1_0::
337             IGraphicBufferSource HGraphicBufferSource;
338 
339     // Set the output surface to be used with a blockpool previously created by
340     // createBlockPool().
341     c2_status_t setOutputSurface(
342             C2BlockPool::local_id_t blockPoolId,
343             const sp<IGraphicBufferProducer>& surface,
344             uint32_t generation);
345 
346     // Extract a slot number from of the block, then call
347     // IGraphicBufferProducer::queueBuffer().
348     //
349     // If the output surface has not been set, NO_INIT will be returned.
350     //
351     // If the block does not come from a bufferqueue-based blockpool,
352     // attachBuffer() will be called, followed by queueBuffer().
353     //
354     // If the block has a bqId that does not match the id of the output surface,
355     // DEAD_OBJECT will be returned.
356     //
357     // If the call to queueBuffer() is successful but the block cannot be
358     // associated to the output surface for automatic cancellation upon
359     // destruction, UNKNOWN_ERROR will be returned.
360     //
361     // Otherwise, the return value from queueBuffer() will be returned.
362     status_t queueToOutputSurface(
363             const C2ConstGraphicBlock& block,
364             const QueueBufferInput& input,
365             QueueBufferOutput* output);
366 
367     // Connect to a given InputSurface.
368     c2_status_t connectToInputSurface(
369             const std::shared_ptr<InputSurface>& inputSurface,
370             std::shared_ptr<InputSurfaceConnection>* connection);
371 
372     c2_status_t connectToOmxInputSurface(
373             const sp<HGraphicBufferProducer1>& producer,
374             const sp<HGraphicBufferSource>& source,
375             std::shared_ptr<InputSurfaceConnection>* connection);
376 
377     c2_status_t disconnectFromInputSurface();
378 
379     // base cannot be null.
380     Component(const sp<Base>& base);
381 
382     ~Component();
383 
384 protected:
385     sp<Base> mBase;
386 
387     ::android::hardware::media::c2::V1_0::utils::DefaultBufferPoolSender
388             mBufferPoolSender;
389 
390     ::android::hardware::media::c2::V1_0::utils::OutputBufferQueue
391             mOutputBufferQueue;
392 
393     static c2_status_t setDeathListener(
394             const std::shared_ptr<Component>& component,
395             const std::shared_ptr<Listener>& listener);
396     sp<::android::hardware::hidl_death_recipient> mDeathRecipient;
397 
398     friend struct Codec2Client;
399 
400     struct HidlListener;
401     void handleOnWorkDone(const std::list<std::unique_ptr<C2Work>> &workItems);
402 
403 };
404 
405 struct Codec2Client::InputSurface : public Codec2Client::Configurable {
406 public:
407     typedef ::android::hardware::media::c2::V1_0::IInputSurface Base;
408 
409     typedef ::android::hardware::media::c2::V1_0::IInputSurfaceConnection
410             ConnectionBase;
411 
412     typedef Codec2Client::InputSurfaceConnection Connection;
413 
414     typedef ::android::IGraphicBufferProducer IGraphicBufferProducer;
415 
416     sp<IGraphicBufferProducer> getGraphicBufferProducer() const;
417 
418     // Return the underlying IInputSurface.
419     sp<Base> getHalInterface() const;
420 
421     // base cannot be null.
422     InputSurface(const sp<Base>& base);
423 
424 protected:
425     sp<Base> mBase;
426 
427     sp<IGraphicBufferProducer> mGraphicBufferProducer;
428 
429     friend struct Codec2Client;
430     friend struct Component;
431 };
432 
433 struct Codec2Client::InputSurfaceConnection : public Codec2Client::Configurable {
434 
435     typedef ::android::hardware::media::c2::V1_0::IInputSurfaceConnection Base;
436 
437     c2_status_t disconnect();
438 
439     // base cannot be null.
440     InputSurfaceConnection(const sp<Base>& base);
441 
442 protected:
443     sp<Base> mBase;
444 
445     friend struct Codec2Client::InputSurface;
446 };
447 
448 }  // namespace android
449 
450 #endif  // CODEC2_HIDL_CLIENT_H
451 
452