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