1 /*
2  * Copyright (C) 2016 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 C2COMPONENT_H_
18 
19 #define C2COMPONENT_H_
20 
21 #include <stdbool.h>
22 #include <stdint.h>
23 
24 #include <list>
25 #include <memory>
26 #include <vector>
27 #include <functional>
28 
29 #include <C2Enum.h>
30 #include <C2Param.h>
31 #include <C2Work.h>
32 
33 /// \defgroup components Components
34 /// @{
35 
36 struct C2FieldSupportedValuesQuery {
37     enum type_t : uint32_t {
38         POSSIBLE, ///< query all possible values regardless of other settings
39         CURRENT,  ///< query currently possible values given dependent settings
40     };
41 
42 private:
43     C2ParamField _mField;
44     type_t _mType;
45 public:
46     c2_status_t status;
47     C2FieldSupportedValues values;
48 
C2FieldSupportedValuesQueryC2FieldSupportedValuesQuery49     C2FieldSupportedValuesQuery(const C2ParamField &field_, type_t type_)
50         : _mField(field_), _mType(type_), status(C2_NO_INIT) { }
51 
52     static C2FieldSupportedValuesQuery
CurrentC2FieldSupportedValuesQuery53     Current(const C2ParamField &field_) {
54         return C2FieldSupportedValuesQuery(field_, CURRENT);
55     }
56 
57     static C2FieldSupportedValuesQuery
PossibleC2FieldSupportedValuesQuery58     Possible(const C2ParamField &field_) {
59         return C2FieldSupportedValuesQuery(field_, POSSIBLE);
60     }
61 
fieldC2FieldSupportedValuesQuery62     inline C2ParamField field() const { return _mField; };
63 
typeC2FieldSupportedValuesQuery64     inline type_t type() const { return _mType; }
65 };
66 
67 /**
68  * Component interface object. This object contains all of the configuration of a potential or
69  * actual component. It can be created and used independently of an actual C2Component instance to
70  * query support and parameters for various component settings and configurations for a potential
71  * component. Actual components also expose this interface.
72  */
73 
74 class C2ComponentInterface {
75 public:
76     // ALWAYS AVAILABLE METHODS
77     // =============================================================================================
78 
79     /**
80      * Returns the name of this component or component interface object.
81      * This is a unique name for this component or component interface 'class'; however, multiple
82      * instances of this component SHALL have the same name.
83      *
84      * When attached to a component, this method MUST be supported in any component state.
85      * This call does not change the state nor the internal configuration of the component.
86      *
87      * This method MUST be "non-blocking" and return within 1ms.
88      *
89      * \return the name of this component or component interface object.
90      * \retval an empty string if there was not enough memory to allocate the actual name.
91      */
92     virtual C2String getName() const = 0;
93 
94     /**
95      * Returns a unique ID for this component or interface object.
96      * This ID is used as work targets, unique work IDs, and when configuring tunneling.
97      *
98      * When attached to a component, this method MUST be supported in any component state.
99      * This call does not change the state nor the internal configuration of the component.
100      *
101      * This method MUST be "non-blocking" and return within 1ms.
102      *
103      * \return a unique node ID for this component or component interface instance.
104      */
105     virtual c2_node_id_t getId() const = 0;
106 
107     /**
108      * Queries a set of parameters from the component or interface object.
109      * Querying is performed at best effort: the component SHALL query all supported parameters and
110      * skip unsupported ones, heap allocated parameters that could not be allocated or parameters
111      * that could not be queried without blocking. Any errors are communicated in the return value.
112      * Additionally, preallocated (e.g. stack) parameters that could not be queried are invalidated.
113      * Invalid or blocking parameters to be allocated on the heap are omitted from the result.
114      *
115      * \note Parameter values do not depend on the order of query.
116      *
117      * \todo This method cannot be used to query info-buffers. Is that a problem?
118      *
119      * When attached to a component, this method MUST be supported in any component state except
120      * released.
121      * This call does not change the state nor the internal configuration of the component.
122      *
123      * This method has a variable blocking behavior based on state.
124      * In the stopped state this method MUST be "non-blocking" and return within 1ms.
125      * In the running states this method may be momentarily blocking, but MUST return within 5ms.
126      *
127      * \param[in,out] stackParams  a list of params queried. These are initialized specific to each
128      *                             setting; e.g. size and index are set and rest of the members are
129      *                             cleared.
130      *                             \note Flexible settings that are of incorrect size will be
131      *                             invalidated.
132      * \param[in] heapParamIndices a vector of param indices for params to be queried and returned
133      *                             on the heap. These parameters will be returned in heapParams.
134      *                             Unsupported param indices will be ignored.
135      * \param[in] mayBlock         if true (C2_MAY_BLOCK), implementation may momentarily block.
136      *                             Otherwise (C2_DONT_BLOCK), it must be "non-blocking".
137      * \param[out] heapParams      a list of params where to which the supported heap parameters
138      *                             will be appended in the order they appear in heapParamIndices.
139      *
140      * \retval C2_OK        all parameters could be queried
141      * \retval C2_BAD_INDEX all supported parameters could be queried, but some parameters were not
142      *                      supported
143      * \retval C2_BAD_STATE when called in the released component state (user error)
144      *                      (this error code is only allowed for interfaces connected to components)
145      * \retval C2_NO_MEMORY could not allocate memory for a supported parameter
146      * \retval C2_BLOCKING  the operation must block to complete but mayBlock is false
147      *                      (this error code is only allowed for interfaces connected to components)
148      * \retval C2_TIMED_OUT could not query the parameters within the time limit (unexpected)
149      *                      (this error code is only allowed for interfaces connected to components
150      *                      in the running state)
151      * \retval C2_CORRUPTED some unknown error prevented the querying of the parameters
152      *                      (unexpected)
153      *                      (this error code is only allowed for interfaces connected to components)
154      */
155     virtual c2_status_t query_vb(
156         const std::vector<C2Param*> &stackParams,
157         const std::vector<C2Param::Index> &heapParamIndices,
158         c2_blocking_t mayBlock,
159         std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0;
160 
161     /**
162      * Sets a set of parameters for the component or interface object.
163      *
164      * Tuning is performed at best effort: the component SHALL process the configuration updates in
165      * the order they appear in |params|. If any parameter update fails, the component shall
166      * communicate the failure in the return value and in |failures|, and still process the
167      * remaining parameters. Unsupported parameters are skipped, though they are communicated in
168      * ther return value. Most parameters are updated at best effort - such that even if client
169      * specifies an unsupported value for a field, the closest supported value is used. On the
170      * other hand, strict parameters only accept specific values for their fields, and if the client
171      * specifies an unsupported value, the parameter setting shall fail for that field.
172      * If the client tries to change the value of a field that requires momentary blocking without
173      * setting |mayBlock| to C2_MAY_BLOCK, that parameter shall also be skipped and a specific
174      * return value shall be used. Final values for all parameters set are propagated back to the
175      * caller in |params|.
176      *
177      * \note Parameter tuning DOES depend on the order of the tuning parameters. E.g. some parameter
178      * update may allow some subsequent values for further parameter updates.
179      *
180      * When attached to a component, this method MUST be supported in any component state except
181      * released.
182      *
183      * This method has a variable blocking behavior based on state.
184      * In the stopped state this method MUST be "non-blocking" and return within 1ms.
185      * In the running states this method may be momentarily blocking, but MUST return within 5ms.
186      *
187      * \param[in,out] params a list of parameter updates. These will be updated to the actual
188      *                       parameter values after the updates (this is because tuning is performed
189      *                       at best effort).
190      *                       \todo params that could not be updated are not marked here, so are
191      *                       confusing - are they "existing" values or intended to be configured
192      *                       values?
193      * \param[in] mayBlock   if true (C2_MAY_BLOCK), implementation may momentarily block.
194      *                       Otherwise (C2_DONT_BLOCK), it must be "non-blocking".
195      * \param[out] failures  a list of parameter failures and optional guidance
196      *
197      * \retval C2_OK        all parameters could be updated successfully
198      * \retval C2_BAD_INDEX all supported parameters could be updated successfully, but some
199      *                      parameters were not supported
200      * \retval C2_BAD_VALUE some supported parameters could not be updated successfully because
201      *                      they contained unsupported values. These are returned in |failures|.
202      * \retval C2_BAD_STATE when called in the released component state (user error)
203      *                      (this error code is only allowed for interfaces connected to components)
204      * \retval C2_NO_MEMORY some supported parameters could not be updated successfully because
205      *                      they contained unsupported values, but could not allocate a failure
206      *                      object for them.
207      * \retval C2_TIMED_OUT could not set the parameters within the time limit (unexpected)
208      *                      (this error code is only allowed for interfaces connected to components
209      *                      in the running state)
210      * \retval C2_BLOCKING  the operation must block to complete but mayBlock is false
211      *                      (this error code is only allowed for interfaces connected to components)
212      * \retval C2_CORRUPTED some unknown error prevented the update of the parameters
213      *                      (unexpected)
214      *                      (this error code is only allowed for interfaces connected to components)
215      */
216     virtual c2_status_t config_vb(
217             const std::vector<C2Param*> &params,
218             c2_blocking_t mayBlock,
219             std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
220 
221     // TUNNELING
222     // =============================================================================================
223 
224     /**
225      * Creates a tunnel from this component to the target component.
226      *
227      * If the component is successfully created, subsequent work items queued may include a
228      * tunneled path between these components.
229      *
230      * When attached to a component, this method MUST be supported in any component state except
231      * released.
232      *
233      * This method may be momentarily blocking, but MUST return within 5ms.
234      *
235      * \retval C2_OK        the tunnel was successfully created
236      * \retval C2_BAD_INDEX the target component does not exist
237      * \retval C2_DUPLICATE the tunnel already exists
238      * \retval C2_OMITTED   tunneling is not supported by this component
239      * \retval C2_CANNOT_DO the specific tunnel is not supported
240      * \retval C2_BAD_STATE when called in the released component state (user error)
241      *                      (this error code is only allowed for interfaces connected to components)
242      *
243      * \retval C2_TIMED_OUT could not create the tunnel within the time limit (unexpected)
244      * \retval C2_CORRUPTED some unknown error prevented the creation of the tunnel (unexpected)
245      *                      (this error code is only allowed for interfaces connected to components)
246      */
247     virtual c2_status_t createTunnel_sm(c2_node_id_t targetComponent) = 0;
248 
249     /**
250      * Releases a tunnel from this component to the target component.
251      *
252      * The release of a tunnel is delayed while there are pending work items for the tunnel.
253      * After releasing a tunnel, subsequent work items queued MUST NOT include a tunneled
254      * path between these components.
255      *
256      * When attached to a component, this method MUST be supported in any component state except
257      * released.
258      *
259      * This method may be momentarily blocking, but MUST return within 5ms.
260      *
261      * \retval C2_OK        the tunnel was marked for release successfully
262      * \retval C2_BAD_INDEX the target component does not exist
263      * \retval C2_NOT_FOUND the tunnel does not exist
264      * \retval C2_OMITTED   tunneling is not supported by this component
265      * \retval C2_BAD_STATE when called in the released component state (user error)
266      *                      (this error code is only allowed for interfaces connected to components)
267      *
268      * \retval C2_TIMED_OUT could not mark the tunnel for release within the time limit (unexpected)
269      * \retval C2_CORRUPTED some unknown error prevented the release of the tunnel (unexpected)
270      *                      (this error code is only allowed for interfaces connected to components)
271      */
272     virtual c2_status_t releaseTunnel_sm(c2_node_id_t targetComponent) = 0;
273 
274     // REFLECTION MECHANISM (USED FOR EXTENSION)
275     // =============================================================================================
276 
277     /**
278      * Returns the set of supported parameters.
279      *
280      * When attached to a component, this method MUST be supported in any component state except
281      * released.
282      *
283      * This method MUST be "non-blocking" and return within 1ms.
284      *
285      * \param[out] params a vector of supported parameters will be appended to this vector.
286      *
287      * \retval C2_OK        the operation completed successfully.
288      * \retval C2_BAD_STATE when called in the released component state (user error)
289      *                      (this error code is only allowed for interfaces connected to components)
290      * \retval C2_NO_MEMORY not enough memory to complete this method.
291      */
292     virtual c2_status_t querySupportedParams_nb(
293             std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const = 0;
294 
295     /**
296      * Retrieves the supported values for the queried fields.
297      *
298      * Client SHALL set the parameter-field specifier and the type of supported values query (e.g.
299      * currently supported values, or potential supported values) in fields.
300      * Upon return the component SHALL fill in the supported values for the fields listed as well
301      * as a status for each field. Component shall process all fields queried even if some queries
302      * fail.
303      *
304      * When attached to a component, this method MUST be supported in any component state except
305      * released.
306      *
307      * This method has a variable blocking behavior based on state.
308      * In the stopped state this method MUST be "non-blocking" and return within 1ms.
309      * In the running states this method may be momentarily blocking, but MUST return within 5ms.
310      *
311      * \param[in out] fields a vector of fields descriptor structures.
312      * \param[in] mayBlock   if true (C2_MAY_BLOCK), implementation may momentarily block.
313      *                       Otherwise (C2_DONT_BLOCK), it must be "non-blocking".
314      *
315      * \retval C2_OK        the operation completed successfully.
316      * \retval C2_BAD_STATE when called in the released component state (user error)
317      *                      (this error code is only allowed for interfaces connected to components)
318      * \retval C2_BAD_INDEX at least one field was not recognized as a component field
319      * \retval C2_TIMED_OUT could not query supported values within the time limit (unexpected)
320      *                      (this error code is only allowed for interfaces connected to components
321      *                      in the running state)
322      * \retval C2_BLOCKING  the operation must block to complete but mayBlock is false
323      *                      (this error code is only allowed for interfaces connected to components)
324      * \retval C2_CORRUPTED some unknown error prevented the operation from completing (unexpected)
325      *                      (this error code is only allowed for interfaces connected to components)
326      */
327     virtual c2_status_t querySupportedValues_vb(
328             std::vector<C2FieldSupportedValuesQuery> &fields, c2_blocking_t mayBlock) const = 0;
329 
330     virtual ~C2ComponentInterface() = default;
331 };
332 
333 class C2Component {
334 public:
335     class Listener {
336     public:
337         virtual void onWorkDone_nb(std::weak_ptr<C2Component> component,
338                                 std::list<std::unique_ptr<C2Work>> workItems) = 0;
339 
340         virtual void onTripped_nb(std::weak_ptr<C2Component> component,
341                                std::vector<std::shared_ptr<C2SettingResult>> settingResult) = 0;
342 
343         virtual void onError_nb(std::weak_ptr<C2Component> component,
344                              uint32_t errorCode) = 0;
345 
346         // virtual void onTunnelReleased(<from>, <to>) = 0;
347 
348         // virtual void onComponentReleased(<id>) = 0;
349 
350         virtual ~Listener() = default;
351     };
352 
353     /**
354      * Sets the listener for this component
355      *
356      * This method MUST be supported in all states except released.
357      * The listener can only be set to non-null value in stopped state (that does not include
358      * tripped or error). It can be set to nullptr in both stopped and running states.
359      * Components only use the listener in running state.
360      *
361      * If listener is nullptr, the component SHALL guarantee that no more listener callbacks are
362      * done to the original listener once this method returns. (Any pending listener callbacks will
363      * need to be completed during this call - hence this call may be temporarily blocking.)
364      *
365      * This method has a variable blocking behavior based on state.
366      * In the stopped state this method MUST be "non-blocking" and return within 1ms.
367      * In the running states this method may be momentarily blocking, but MUST return within 5ms.
368      *
369      * Component SHALL handle listener notifications from the same thread (the thread used is
370      * at the component's discretion.)
371      *
372      * \note This could also be accomplished by passing a weak_ptr to a component-specific listener
373      * here and requiring the client to always promote the weak_ptr before any callback. This would
374      * put the burden on the client to clear the listener - wait for its deletion - at which point
375      * it is guaranteed that no more listener callbacks will occur.
376      *
377      * \param[in] listener the component listener object
378      * \param[in] mayBlock if true (C2_MAY_BLOCK), implementation may momentarily block.
379      *                     Otherwise (C2_DONT_BLOCK), it must be "non-blocking".
380      *
381      * \retval C2_BAD_STATE attempting to change the listener in the running state to a non-null
382      *                      value (user error), or called in the released state
383      * \retval C2_BLOCKING  the operation must block to complete but mayBlock is false
384      * \retval C2_OK        listener was updated successfully.
385      */
386     virtual c2_status_t setListener_vb(
387             const std::shared_ptr<Listener> &listener, c2_blocking_t mayBlock) = 0;
388 
389     /// component domain (e.g. audio or video)
390     enum domain_t : uint32_t;
391 
392     /// component kind (e.g. encoder, decoder or filter)
393     enum kind_t : uint32_t;
394 
395     /// component rank. This number is used to determine component ordering (the lower the sooner)
396     /// in the component list.
397     typedef uint32_t rank_t;
398 
399     /// component attributes
400     enum attrib_t : uint64_t;
401 
402     /**
403      * Information about a component.
404      */
405     struct Traits {
406     // public:
407         C2String name; ///< name of the component
408         domain_t domain; ///< component domain
409         kind_t kind; ///< component kind
410         rank_t rank; ///< component rank
411         C2String mediaType; ///< media type supported by the component
412         C2String owner; ///< name of the component store owning this component
413 
414         /**
415          * name alias(es) for backward compatibility.
416          * \note Multiple components can have the same alias as long as their media-type differs.
417          */
418         std::vector<C2StringLiteral> aliases; ///< name aliases for backward compatibility
419     };
420 
421     // METHODS AVAILABLE WHEN RUNNING
422     // =============================================================================================
423 
424     /**
425      * Queues up work for the component.
426      *
427      * This method MUST be supported in running (including tripped and error) states.
428      *
429      * This method MUST be "non-blocking" and return within 1 ms
430      *
431      * It is acceptable for this method to return OK and return an error value using the
432      * onWorkDone() callback.
433      *
434      * \retval C2_OK        the work was successfully queued
435      * \retval C2_BAD_INDEX some component(s) in the work do(es) not exist
436      * \retval C2_CANNOT_DO the components are not tunneled
437      * \retval C2_BAD_STATE when called in the stopped or released state (user error)
438      *
439      * \retval C2_NO_MEMORY not enough memory to queue the work
440      * \retval C2_CORRUPTED some unknown error prevented queuing the work (unexpected)
441      */
442     virtual c2_status_t queue_nb(std::list<std::unique_ptr<C2Work>>* const items) = 0;
443 
444     /**
445      * Announces a work to be queued later for the component. This reserves a slot for the queue
446      * to ensure correct work ordering even if the work is queued later.
447      *
448      * This method MUST be supported in running (including tripped and error) states.
449      *
450      * This method MUST be "non-blocking" and return within 1 ms
451      *
452      * \retval C2_OK        the work announcement has been successfully recorded
453      * \retval C2_BAD_INDEX some component(s) in the work outline do(es) not exist
454      * \retval C2_CANNOT_DO the componentes are not tunneled
455      * \retval C2_BAD_STATE when called in the stopped or released state (user error)
456      *
457      * \retval C2_NO_MEMORY not enough memory to record the work announcement
458      * \retval C2_CORRUPTED some unknown error prevented recording the announcement (unexpected)
459      *
460      * \todo Can this be rolled into queue_nb?
461      * \todo Expose next work item for each component to detect stalls
462      */
463     virtual c2_status_t announce_nb(const std::vector<C2WorkOutline> &items) = 0;
464 
465     enum flush_mode_t : uint32_t {
466         /// flush work from this component only
467         FLUSH_COMPONENT,
468 
469         /// flush work from this component and all components connected downstream from it via
470         /// tunneling
471         FLUSH_CHAIN = (1 << 16),
472     };
473 
474     /**
475      * Discards and abandons any pending work for the component, and optionally any component
476      * downstream.
477      *
478      * \todo define this: we could flush all work before last item queued for component across all
479      *                    components linked to this; flush only work items that are queued to this
480      *                    component
481      * \todo return work # of last flushed item; or all flushed (but not returned items)
482      * \todo we could make flush take a work item and flush all work before/after that item to allow
483      *       TBD (slicing/seek?)
484      * \todo we could simply take a list of numbers and flush those... this is bad for decoders
485      *       also, what would happen to fine grade references?
486      *
487      * This method MUST be supported in running (including tripped and error) states.
488      *
489      * This method may be momentarily blocking, but must return within 5ms.
490      *
491      * Work that could be immediately abandoned/discarded SHALL be returned in |flushedWork|; this
492      * can be done in an arbitrary order.
493      *
494      * Work that could not be abandoned or discarded immediately SHALL be marked to be
495      * discarded at the earliest opportunity, and SHALL be returned via the onWorkDone() callback.
496      * This shall be completed within 500ms.
497      *
498      * \param mode flush mode
499      *
500      * \retval C2_OK        the component has been successfully flushed
501      * \retval C2_BAD_STATE when called in the stopped or released state (user error)
502      * \retval C2_TIMED_OUT the flush could not be completed within the time limit (unexpected)
503      * \retval C2_CORRUPTED some unknown error prevented flushing from completion (unexpected)
504      */
505     virtual c2_status_t flush_sm(flush_mode_t mode, std::list<std::unique_ptr<C2Work>>* const flushedWork) = 0;
506 
507     enum drain_mode_t : uint32_t {
508         /// drain component only and add an "end-of-stream" marker. Component shall process all
509         /// queued work and complete the current stream. If new input is received, it shall start
510         /// a new stream. \todo define what a stream is.
511         DRAIN_COMPONENT_WITH_EOS,
512         /// drain component without setting "end-of-stream" marker. Component shall process all
513         /// queued work but shall expect more work items for the same stream.
514         DRAIN_COMPONENT_NO_EOS = (1 << 0),
515 
516         /// marks the last work item with a persistent "end-of-stream" marker that will drain
517         /// downstream components
518         /// \todo this may confuse work-ordering downstream
519         DRAIN_CHAIN = (1 << 16),
520 
521         /**
522          * \todo define this; we could place EOS to all upstream components, just this component, or
523          *       all upstream and downstream component.
524          * \todo should EOS carry over to downstream components?
525          */
526     };
527 
528     /**
529      * Drains the component, and optionally downstream components. This is a signalling method;
530      * as such it does not wait for any work completion.
531      *
532      * Marks last work item as "drain-till-here", so component is notified not to wait for further
533      * work before it processes work already queued. This method can also used to set the
534      * end-of-stream flag after work has been queued. Client can continue to queue further work
535      * immediately after this method returns.
536      *
537      * This method MUST be supported in running (including tripped) states.
538      *
539      * This method MUST be "non-blocking" and return within 1ms.
540      *
541      * Work that is completed SHALL be returned via the onWorkDone() callback.
542      *
543      * \param mode drain mode
544      *
545      * \retval C2_OK        the drain request has been successfully recorded
546      * \retval C2_BAD_STATE when called in the stopped or released state (user error)
547      * \retval C2_BAD_VALUE the drain mode is not supported by the component
548      *                      \todo define supported modes discovery
549      * \retval C2_TIMED_OUT the flush could not be completed within the time limit (unexpected)
550      * \retval C2_CORRUPTED some unknown error prevented flushing from completion (unexpected)
551      */
552     virtual c2_status_t drain_nb(drain_mode_t mode) = 0;
553 
554     // STATE CHANGE METHODS
555     // =============================================================================================
556 
557     /**
558      * Starts the component.
559      *
560      * This method MUST be supported in stopped state, as well as during the tripped state.
561      *
562      * If the return value is C2_OK, the component shall be in the running state.
563      * If the return value is C2_BAD_STATE or C2_DUPLICATE, no state change is expected as a
564      * response to this call.
565      * Otherwise, the component shall be in the stopped state.
566      *
567      * \note If a component is in the tripped state and start() is called while the component
568      * configuration still results in a trip, start shall succeed and a new onTripped callback
569      * should be used to communicate the configuration conflict that results in the new trip.
570      *
571      * \todo This method MUST return within 500ms. Seems this should be able to return quickly, as
572      * there are no immediate guarantees. Though there are guarantees for responsiveness immediately
573      * after start returns.
574      *
575      * \retval C2_OK        the component has started (or resumed) successfully
576      * \retval C2_DUPLICATE when called during another start call from another thread
577      * \retval C2_BAD_STATE when called in any state other than the stopped state or tripped state,
578      *                      including when called during another state change call from another
579      *                      thread (user error)
580      * \retval C2_NO_MEMORY not enough memory to start the component
581      * \retval C2_TIMED_OUT the component could not be started within the time limit (unexpected)
582      * \retval C2_CORRUPTED some unknown error prevented starting the component (unexpected)
583      */
584     virtual c2_status_t start() = 0;
585 
586     /**
587      * Stops the component.
588      *
589      * This method MUST be supported in running (including tripped) state.
590      *
591      * This method MUST return withing 500ms.
592      *
593      * Upon this call, all pending work SHALL be abandoned and all buffer references SHALL be
594      * released.
595      * If the return value is C2_BAD_STATE or C2_DUPLICATE, no state change is expected as a
596      * response to this call.
597      * For all other return values, the component shall be in the stopped state.
598      *
599      * \todo should this return completed work, since client will just free it? Perhaps just to
600      * verify accounting.
601      *
602      * This does not alter any settings and tunings that may have resulted in a tripped state.
603      * (Is this material given the definition? Perhaps in case we want to start again.)
604      *
605      * \retval C2_OK        the component has started successfully
606      * \retval C2_DUPLICATE when called during another stop call from another thread
607      * \retval C2_BAD_STATE when called in any state other than the running state, including when
608      *                      called during another state change call from another thread (user error)
609      * \retval C2_TIMED_OUT the component could not be stopped within the time limit (unexpected)
610      * \retval C2_CORRUPTED some unknown error prevented stopping the component (unexpected)
611      */
612     virtual c2_status_t stop() = 0;
613 
614     /**
615      * Resets the component.
616      *
617      * This method MUST be supported in all (including tripped) states other than released.
618      *
619      * This method MUST be supported during any other blocking call.
620      *
621      * This method MUST return withing 500ms.
622      *
623      * After this call returns all work SHALL be abandoned, all buffer references SHALL be released.
624      * If the return value is C2_BAD_STATE or C2_DUPLICATE, no state change is expected as a
625      * response to this call.
626      * For all other return values, the component shall be in the stopped state.
627      *
628      * \todo should this return completed work, since client will just free it? Also, if it unblocks
629      * a stop, where should completed work be returned?
630      *
631      * This brings settings back to their default - "guaranteeing" no tripped space.
632      *
633      * \todo reclaim support - it seems that since ownership is passed, this will allow reclaiming
634      * stuff.
635      *
636      * \retval C2_OK        the component has been reset
637      * \retval C2_DUPLICATE when called during another reset call from another thread
638      * \retval C2_BAD_STATE when called in the released state
639      * \retval C2_TIMED_OUT the component could not be reset within the time limit (unexpected)
640      * \retval C2_CORRUPTED some unknown error prevented resetting the component (unexpected)
641      */
642     virtual c2_status_t reset() = 0;
643 
644     /**
645      * Releases the component.
646      *
647      * This method MUST be supported in stopped state.
648      *
649      * This method MUST return withing 500ms. Upon return all references shall be abandoned.
650      *
651      * \retval C2_OK        the component has been released
652      * \retval C2_DUPLICATE the component is already released
653      * \retval C2_BAD_STATE the component is running
654      * \retval C2_TIMED_OUT the component could not be released within the time limit (unexpected)
655      * \retval C2_CORRUPTED some unknown error prevented releasing the component (unexpected)
656      */
657     virtual c2_status_t release() = 0;
658 
659     /**
660      * Returns the interface for this component.
661      *
662      * \return the component interface
663      */
664     virtual std::shared_ptr<C2ComponentInterface> intf() = 0;
665 
666     virtual ~C2Component() = default;
667 };
668 
669 C2ENUM(C2Component::kind_t, uint32_t,
670     KIND_OTHER,
671     KIND_DECODER,
672     KIND_ENCODER
673 );
674 
675 C2ENUM(C2Component::domain_t, uint32_t,
676     DOMAIN_OTHER,
677     DOMAIN_VIDEO,
678     DOMAIN_AUDIO,
679     DOMAIN_IMAGE
680 );
681 
682 class C2FrameInfoParser {
683 public:
684     /**
685      * \return the content type supported by this info parser.
686      *
687      * \todo this may be redundant
688      */
689     virtual C2StringLiteral getType() const = 0;
690 
691     /**
692      * \return a vector of supported parameter indices parsed by this info parser.
693      *
694      * This method MUST be "non-blocking" and return within 1ms.
695      *
696      * \todo sticky vs. non-sticky params? this may be communicated by param-reflector.
697      */
698     virtual const std::vector<C2Param::Index> getParsedParams() const = 0;
699 
700     /**
701      * Resets this info parser. This brings this parser to its initial state after creation.
702      *
703      * This method SHALL return within 5ms.
704      *
705      * \retval C2_OK        the info parser was reset
706      * \retval C2_TIMED_OUT could not reset the parser within the time limit (unexpected)
707      * \retval C2_CORRUPTED some unknown error prevented the resetting of the parser (unexpected)
708      */
reset()709     virtual c2_status_t reset() { return C2_OK; }
710 
711     virtual c2_status_t parseFrame(C2FrameData &frame);
712 
713     virtual ~C2FrameInfoParser() = default;
714 };
715 
716 class C2AllocatorStore {
717 public:
718     typedef C2Allocator::id_t id_t;
719 
720     enum : C2Allocator::id_t {
721         DEFAULT_LINEAR,     ///< basic linear allocator type
722         DEFAULT_GRAPHIC,    ///< basic graphic allocator type
723         PLATFORM_START = 0x10,
724         VENDOR_START   = 0x100,
725         BAD_ID         = C2Allocator::BAD_ID, ///< DO NOT USE
726     };
727 
728     /**
729      * Returns the unique name of this allocator store.
730      *
731      * This method MUST be "non-blocking" and return within 1ms.
732      *
733      * \return the name of this allocator store.
734      * \retval an empty string if there was not enough memory to allocate the actual name.
735      */
736     virtual C2String getName() const = 0;
737 
738     /**
739      * Returns the set of allocators supported by this allocator store.
740      *
741      * This method MUST be "non-blocking" and return within 1ms.
742      *
743      * \retval vector of allocator information (as shared pointers)
744      * \retval an empty vector if there was not enough memory to allocate the whole vector.
745      */
746     virtual std::vector<std::shared_ptr<const C2Allocator::Traits>> listAllocators_nb() const = 0;
747 
748     /**
749      * Retrieves/creates a shared allocator object.
750      *
751      * This method MUST be return within 5ms.
752      *
753      * The allocator is created on first use, and the same allocator is returned on subsequent
754      * concurrent uses in the same process. The allocator is freed when it is no longer referenced.
755      *
756      * \param id      the ID of the allocator to create. This is defined by the store, but
757      *                the ID of the default linear and graphic allocators is formalized.
758      * \param allocator shared pointer where the created allocator is stored. Cleared on failure
759      *                  and updated on success.
760      *
761      * \retval C2_OK        the allocator was created successfully
762      * \retval C2_TIMED_OUT could not create the allocator within the time limit (unexpected)
763      * \retval C2_CORRUPTED some unknown error prevented the creation of the allocator (unexpected)
764      *
765      * \retval C2_NOT_FOUND no such allocator
766      * \retval C2_NO_MEMORY not enough memory to create the allocator
767      */
768     virtual c2_status_t fetchAllocator(id_t id, std::shared_ptr<C2Allocator>* const allocator) = 0;
769 
770     virtual ~C2AllocatorStore() = default;
771 };
772 
773 class C2ComponentStore {
774 public:
775     /**
776      * Returns the name of this component or component interface object.
777      * This is a unique name for this component or component interface 'class'; however, multiple
778      * instances of this component SHALL have the same name.
779      *
780      * This method MUST be supported in any state. This call does not change the state nor the
781      * internal states of the component.
782      *
783      * This method MUST be "non-blocking" and return within 1ms.
784      *
785      * \return the name of this component or component interface object.
786      * \retval an empty string if there was not enough memory to allocate the actual name.
787      */
788     virtual C2String getName() const = 0;
789 
790     /**
791      * Creates a component.
792      *
793      * This method SHALL return within 100ms.
794      *
795      * \param name          name of the component to create
796      * \param component     shared pointer where the created component is stored. Cleared on
797      *                      failure and updated on success.
798      *
799      * \retval C2_OK        the component was created successfully
800      * \retval C2_TIMED_OUT could not create the component within the time limit (unexpected)
801      * \retval C2_CORRUPTED some unknown error prevented the creation of the component (unexpected)
802      *
803      * \retval C2_NOT_FOUND no such component
804      * \retval C2_NO_MEMORY not enough memory to create the component
805      */
806     virtual c2_status_t createComponent(
807             C2String name, std::shared_ptr<C2Component>* const component) = 0;
808 
809     /**
810      * Creates a component interface.
811      *
812      * This method SHALL return within 100ms.
813      *
814      * \param name          name of the component interface to create
815      * \param interface     shared pointer where the created interface is stored
816      *
817      * \retval C2_OK        the component interface was created successfully
818      * \retval C2_TIMED_OUT could not create the component interface within the time limit
819      *                      (unexpected)
820      * \retval C2_CORRUPTED some unknown error prevented the creation of the component interface
821      *                      (unexpected)
822      *
823      * \retval C2_NOT_FOUND no such component interface
824      * \retval C2_NO_MEMORY not enough memory to create the component interface
825      *
826      * \todo Do we need an interface, or could this just be a component that is never started?
827      */
828     virtual c2_status_t createInterface(
829             C2String name, std::shared_ptr<C2ComponentInterface>* const interface) = 0;
830 
831     /**
832      * Returns the list of components supported by this component store.
833      *
834      * This method MUST return within 500ms.
835      *
836      * \retval vector of component information.
837      */
838     virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() = 0;
839 
840     // -------------------------------------- UTILITY METHODS --------------------------------------
841 
842     // on-demand buffer layout conversion (swizzling)
843     //
844     virtual c2_status_t copyBuffer(
845             std::shared_ptr<C2GraphicBuffer> src, std::shared_ptr<C2GraphicBuffer> dst) = 0;
846 
847     // -------------------------------------- CONFIGURATION API -----------------------------------
848     // e.g. for global settings (system-wide stride, etc.)
849 
850     /**
851      * Queries a set of system-wide parameters.
852      * Querying is performed at best effort: the store SHALL query all supported parameters and
853      * skip unsupported ones, or heap allocated parameters that could not be allocated. Any errors
854      * are communicated in the return value. Additionally, preallocated (e.g. stack) parameters that
855      * could not be queried are invalidated. Parameters to be allocated on the heap are omitted from
856      * the result.
857      *
858      * \note Parameter values do not depend on the order of query.
859      *
860      * This method may be momentarily blocking, but MUST return within 5ms.
861      *
862      * \param stackParams   a list of params queried. These are initialized specific to each
863      *                      setting; e.g. size and index are set and rest of the members are
864      *                      cleared.
865      *                      NOTE: Flexible settings that are of incorrect size will be invalidated.
866      * \param heapParamIndices a vector of param indices for params to be queried and returned on the
867      *                      heap. These parameters will be returned in heapParams. Unsupported param
868      *                      indices will be ignored.
869      * \param heapParams    a list of params where to which the supported heap parameters will be
870      *                      appended in the order they appear in heapParamIndices.
871      *
872      * \retval C2_OK        all parameters could be queried
873      * \retval C2_BAD_INDEX all supported parameters could be queried, but some parameters were not
874      *                      supported
875      * \retval C2_NO_MEMORY could not allocate memory for a supported parameter
876      * \retval C2_CORRUPTED some unknown error prevented the querying of the parameters
877      *                      (unexpected)
878      */
879     virtual c2_status_t query_sm(
880         const std::vector<C2Param*> &stackParams,
881         const std::vector<C2Param::Index> &heapParamIndices,
882         std::vector<std::unique_ptr<C2Param>>* const heapParams) const = 0;
883 
884     /**
885      * Sets a set of system-wide parameters.
886      *
887      * \note There are no settable system-wide parameters defined thus far, but may be added in the
888      * future.
889      *
890      * Tuning is performed at best effort: the store SHALL update all supported configuration at
891      * best effort (unless configured otherwise) and skip unsupported ones. Any errors are
892      * communicated in the return value and in |failures|.
893      *
894      * \note Parameter tuning DOES depend on the order of the tuning parameters. E.g. some parameter
895      * update may allow some subsequent parameter update.
896      *
897      * This method may be momentarily blocking, but MUST return within 5ms.
898      *
899      * \param params        a list of parameter updates. These will be updated to the actual
900      *                      parameter values after the updates (this is because tuning is performed
901      *                      at best effort).
902      *                      \todo params that could not be updated are not marked here, so are
903      *                      confusing - are they "existing" values or intended to be configured
904      *                      values?
905      * \param failures      a list of parameter failures
906      *
907      * \retval C2_OK        all parameters could be updated successfully
908      * \retval C2_BAD_INDEX all supported parameters could be updated successfully, but some
909      *                      parameters were not supported
910      * \retval C2_BAD_VALUE some supported parameters could not be updated successfully because
911      *                      they contained unsupported values. These are returned in |failures|.
912      * \retval C2_NO_MEMORY some supported parameters could not be updated successfully because
913      *                      they contained unsupported values, but could not allocate a failure
914      *                      object for them.
915      * \retval C2_CORRUPTED some unknown error prevented the update of the parameters
916      *                      (unexpected)
917      */
918     virtual c2_status_t config_sm(
919             const std::vector<C2Param*> &params,
920             std::vector<std::unique_ptr<C2SettingResult>>* const failures) = 0;
921 
922     // REFLECTION MECHANISM (USED FOR EXTENSION)
923     // =============================================================================================
924 
925     /**
926      * Returns the parameter reflector.
927      *
928      * This is used to describe parameter fields. This is shared for all components created by
929      * this component store.
930      *
931      * This method MUST be "non-blocking" and return within 1ms.
932      *
933      * \return a shared parameter reflector object.
934      */
935     virtual std::shared_ptr<C2ParamReflector> getParamReflector() const = 0;
936 
937     /**
938      * Returns the set of supported parameters.
939      *
940      * This method MUST be "non-blocking" and return within 1ms.
941      *
942      * \param[out] params a vector of supported parameters will be appended to this vector.
943      *
944      * \retval C2_OK        the operation completed successfully.
945      * \retval C2_NO_MEMORY not enough memory to complete this method.
946      */
947     virtual c2_status_t querySupportedParams_nb(
948             std::vector<std::shared_ptr<C2ParamDescriptor>> * const params) const = 0;
949 
950     /**
951      * Retrieves the supported values for the queried fields.
952      *
953      * Client SHALL set the parameter-field specifier and the type of supported values query (e.g.
954      * currently supported values, or potential supported values) in fields.
955      * Upon return the store SHALL fill in the supported values for the fields listed as well
956      * as a status for each field. Store shall process all fields queried even if some queries
957      * fail.
958      *
959      * This method may be momentarily blocking, but MUST return within 5ms.
960      *
961      * \param[in out] fields a vector of fields descriptor structures.
962      *
963      * \retval C2_OK        the operation completed successfully.
964      * \retval C2_BAD_INDEX at least one field was not recognized as a component store field
965      */
966     virtual c2_status_t querySupportedValues_sm(
967             std::vector<C2FieldSupportedValuesQuery> &fields) const = 0;
968 
969     virtual ~C2ComponentStore() = default;
970 };
971 
972 // ================================================================================================
973 
974 /// @}
975 
976 #endif  // C2COMPONENT_H_
977