1/*
2 * componentbase.h, component base class
3 *
4 * Copyright (c) 2009-2010 Wind River Systems, Inc.
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19#ifndef __COMPONENTBASE_H
20#define __COMPONENTBASE_H
21
22#include <OMX_Core.h>
23#include <OMX_Component.h>
24#include <OMX_IntelIndexExt.h>
25#include <cmodule.h>
26#include <portbase.h>
27
28#include <queue.h>
29#include <workqueue.h>
30
31/* retain buffers */
32typedef enum buffer_retain_e {
33    BUFFER_RETAIN_NOT_RETAIN = 0,
34    BUFFER_RETAIN_GETAGAIN,
35    BUFFER_RETAIN_ACCUMULATE,
36    BUFFER_RETAIN_OVERRIDDEN,
37    BUFFER_RETAIN_CACHE,
38} buffer_retain_t;
39
40/* ProcessCmdWork */
41struct cmd_s {
42    OMX_COMMANDTYPE cmd;
43    OMX_U32 param1;
44    OMX_PTR cmddata;
45};
46
47class CmdHandlerInterface
48{
49public:
50    virtual ~CmdHandlerInterface() {};
51    virtual void CmdHandler(struct cmd_s *cmd) = 0;
52};
53
54class CmdProcessWork : public WorkableInterface
55{
56public:
57    CmdProcessWork(CmdHandlerInterface *ci);
58    ~CmdProcessWork();
59
60    OMX_ERRORTYPE PushCmdQueue(struct cmd_s *cmd);
61
62private:
63    struct cmd_s *PopCmdQueue(void);
64
65    virtual void Work(void); /* call ci->CmdHandler() */
66
67    WorkQueue *workq;
68
69    struct queue q;
70    pthread_mutex_t lock;
71
72    CmdHandlerInterface *ci; /* to run ComponentBase::CmdHandler() */
73};
74
75class ComponentBase : public CmdHandlerInterface, public WorkableInterface
76{
77public:
78    /*
79     * constructor & destructor
80     */
81    ComponentBase();
82    ComponentBase(const OMX_STRING name);
83    virtual ~ComponentBase();
84
85    /*
86     * accessor
87     */
88    /* name */
89    void SetName(const OMX_STRING name);
90    OMX_STRING GetName(void);
91
92    /* working role */
93    OMX_STRING GetWorkingRole(void);
94
95    /* cmodule */
96    void SetCModule(CModule *cmodule);
97    CModule *GetCModule(void);
98
99    /* end of accessor */
100
101    /*
102     * core methods & helpers
103     */
104    /* roles */
105    OMX_ERRORTYPE SetRolesOfComponent(OMX_U32 nr_roles, const OMX_U8 **roles);
106
107    /* GetHandle & FreeHandle */
108    OMX_ERRORTYPE GetHandle(OMX_HANDLETYPE* pHandle,
109                            OMX_PTR pAppData,
110                            OMX_CALLBACKTYPE *pCallBacks);
111    OMX_ERRORTYPE FreeHandle(OMX_HANDLETYPE hComponent);
112
113    /* end of core methods & helpers */
114
115    /*
116     * component methods & helpers
117     */
118
119    static OMX_ERRORTYPE SendCommand(
120        OMX_IN  OMX_HANDLETYPE hComponent,
121        OMX_IN  OMX_COMMANDTYPE Cmd,
122        OMX_IN  OMX_U32 nParam1,
123        OMX_IN  OMX_PTR pCmdData);
124    OMX_ERRORTYPE CBaseSendCommand(
125        OMX_IN  OMX_HANDLETYPE hComponent,
126        OMX_IN  OMX_COMMANDTYPE Cmd,
127        OMX_IN  OMX_U32 nParam1,
128        OMX_IN  OMX_PTR pCmdData);
129
130    static OMX_ERRORTYPE GetParameter(
131        OMX_IN  OMX_HANDLETYPE hComponent,
132        OMX_IN  OMX_INDEXTYPE nParamIndex,
133        OMX_INOUT OMX_PTR pComponentParameterStructure);
134    OMX_ERRORTYPE CBaseGetParameter(
135        OMX_IN  OMX_HANDLETYPE hComponent,
136        OMX_IN  OMX_INDEXTYPE nParamIndex,
137        OMX_INOUT OMX_PTR pComponentParameterStructure);
138
139    static OMX_ERRORTYPE SetParameter(
140        OMX_IN  OMX_HANDLETYPE hComponent,
141        OMX_IN  OMX_INDEXTYPE nIndex,
142        OMX_IN  OMX_PTR pComponentParameterStructure);
143    OMX_ERRORTYPE CBaseSetParameter(
144        OMX_IN  OMX_HANDLETYPE hComponent,
145        OMX_IN  OMX_INDEXTYPE nIndex,
146        OMX_IN  OMX_PTR pComponentParameterStructure);
147
148    static OMX_ERRORTYPE GetConfig(
149        OMX_IN  OMX_HANDLETYPE hComponent,
150        OMX_IN  OMX_INDEXTYPE nIndex,
151        OMX_INOUT OMX_PTR pComponentConfigStructure);
152    OMX_ERRORTYPE CBaseGetConfig(
153        OMX_IN  OMX_HANDLETYPE hComponent,
154        OMX_IN  OMX_INDEXTYPE nIndex,
155        OMX_INOUT OMX_PTR pComponentConfigStructure);
156
157    static OMX_ERRORTYPE SetConfig(
158        OMX_IN  OMX_HANDLETYPE hComponent,
159        OMX_IN  OMX_INDEXTYPE nIndex,
160        OMX_IN  OMX_PTR pComponentConfigStructure);
161    OMX_ERRORTYPE CBaseSetConfig(
162        OMX_IN  OMX_HANDLETYPE hComponent,
163        OMX_IN  OMX_INDEXTYPE nIndex,
164        OMX_IN  OMX_PTR pComponentConfigStructure);
165
166    static OMX_ERRORTYPE GetExtensionIndex(
167        OMX_IN  OMX_HANDLETYPE hComponent,
168        OMX_IN  OMX_STRING cParameterName,
169        OMX_OUT OMX_INDEXTYPE* pIndexType);
170    OMX_ERRORTYPE CBaseGetExtensionIndex(
171        OMX_IN  OMX_HANDLETYPE hComponent,
172        OMX_IN  OMX_STRING cParameterName,
173        OMX_OUT OMX_INDEXTYPE* pIndexType);
174
175    static OMX_ERRORTYPE GetState(
176        OMX_IN  OMX_HANDLETYPE hComponent,
177        OMX_OUT OMX_STATETYPE* pState);
178    OMX_ERRORTYPE CBaseGetState(
179        OMX_IN  OMX_HANDLETYPE hComponent,
180        OMX_OUT OMX_STATETYPE* pState);
181
182    static OMX_ERRORTYPE UseBuffer(
183        OMX_IN OMX_HANDLETYPE hComponent,
184        OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
185        OMX_IN OMX_U32 nPortIndex,
186        OMX_IN OMX_PTR pAppPrivate,
187        OMX_IN OMX_U32 nSizeBytes,
188        OMX_IN OMX_U8* pBuffer);
189    OMX_ERRORTYPE CBaseUseBuffer(
190        OMX_IN OMX_HANDLETYPE hComponent,
191        OMX_INOUT OMX_BUFFERHEADERTYPE** ppBufferHdr,
192        OMX_IN OMX_U32 nPortIndex,
193        OMX_IN OMX_PTR pAppPrivate,
194        OMX_IN OMX_U32 nSizeBytes,
195        OMX_IN OMX_U8* pBuffer);
196
197    static OMX_ERRORTYPE AllocateBuffer(
198        OMX_IN OMX_HANDLETYPE hComponent,
199        OMX_INOUT OMX_BUFFERHEADERTYPE** ppBuffer,
200        OMX_IN OMX_U32 nPortIndex,
201        OMX_IN OMX_PTR pAppPrivate,
202        OMX_IN OMX_U32 nSizeBytes);
203    OMX_ERRORTYPE CBaseAllocateBuffer(
204        OMX_IN OMX_HANDLETYPE hComponent,
205        OMX_INOUT OMX_BUFFERHEADERTYPE** ppBuffer,
206        OMX_IN OMX_U32 nPortIndex,
207        OMX_IN OMX_PTR pAppPrivate,
208        OMX_IN OMX_U32 nSizeBytes);
209
210    static OMX_ERRORTYPE FreeBuffer(
211        OMX_IN  OMX_HANDLETYPE hComponent,
212        OMX_IN  OMX_U32 nPortIndex,
213        OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer);
214    OMX_ERRORTYPE CBaseFreeBuffer(
215        OMX_IN  OMX_HANDLETYPE hComponent,
216        OMX_IN  OMX_U32 nPortIndex,
217        OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer);
218
219    static OMX_ERRORTYPE EmptyThisBuffer(
220        OMX_IN  OMX_HANDLETYPE hComponent,
221        OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer);
222    OMX_ERRORTYPE CBaseEmptyThisBuffer(
223        OMX_IN  OMX_HANDLETYPE hComponent,
224        OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer);
225
226    static OMX_ERRORTYPE FillThisBuffer(
227        OMX_IN  OMX_HANDLETYPE hComponent,
228        OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer);
229    OMX_ERRORTYPE CBaseFillThisBuffer(
230        OMX_IN  OMX_HANDLETYPE hComponent,
231        OMX_IN  OMX_BUFFERHEADERTYPE* pBuffer);
232
233    static OMX_ERRORTYPE SetCallbacks(
234        OMX_IN  OMX_HANDLETYPE hComponent,
235        OMX_IN  OMX_CALLBACKTYPE* pCallbacks,
236        OMX_IN  OMX_PTR pAppData);
237    OMX_ERRORTYPE CBaseSetCallbacks(
238        OMX_IN  OMX_HANDLETYPE hComponent,
239        OMX_IN  OMX_CALLBACKTYPE* pCallbacks,
240        OMX_IN  OMX_PTR pAppData);
241
242    static OMX_ERRORTYPE ComponentRoleEnum(
243        OMX_IN OMX_HANDLETYPE hComponent,
244        OMX_OUT OMX_U8 *cRole,
245        OMX_IN OMX_U32 nIndex);
246    OMX_ERRORTYPE CBaseComponentRoleEnum(
247        OMX_IN OMX_HANDLETYPE hComponent,
248        OMX_OUT OMX_U8 *cRole,
249        OMX_IN OMX_U32 nIndex);
250
251    /* end of component methods & helpers */
252
253    /*
254     * omx header manipuation
255     */
256    static void SetTypeHeader(OMX_PTR type, OMX_U32 size);
257    static OMX_ERRORTYPE CheckTypeHeader(const OMX_PTR type, OMX_U32 size);
258
259    /* end of omx header manipuation */
260
261    /*
262     * helper method for queury_roles()
263     */
264    static OMX_ERRORTYPE QueryRolesHelper(OMX_U32 nr_comp_roles,
265                                          const OMX_U8 **comp_roles,
266                                          OMX_U32 *nr_roles, OMX_U8 **roles);
267
268    /* end of helper method for queury_roles() */
269
270protected:
271    /* helpers for derived class */
272    const OMX_COMPONENTTYPE *GetComponentHandle(void);
273#if 0
274    void DumpBuffer(const OMX_BUFFERHEADERTYPE *bufferheader, bool dumpdata);
275#endif
276    /* check if all port has own pending buffer */
277    virtual bool IsAllBufferAvailable(void);
278
279    /* end of helpers for derived class */
280
281    /* ports */
282    /*
283     * allocated with derived port classes by derived component classes
284     */
285    PortBase **ports;
286    OMX_U32 nr_ports;
287    OMX_PORT_PARAM_TYPE portparam;
288
289    /* ports big lock, must be held when accessing all ports at one time */
290    pthread_mutex_t ports_block;
291
292    /* adaptive playback param */
293    OMX_BOOL mEnableAdaptivePlayback;
294private:
295    /* common routines for constructor */
296    void __ComponentBase(void);
297
298    /*
299     * core methods & helpers
300     */
301    /* called in GetHandle (nr_roles == 1) or SetParameter(ComponentRole) */
302    OMX_ERRORTYPE SetWorkingRole(const OMX_STRING role);
303    /* called int FreeHandle() */
304    OMX_ERRORTYPE FreePorts(void);
305
306    /* end of core methods & helpers */
307
308    /*
309     * component methods & helpers
310     */
311    /* SendCommand */
312    /* implement CmdHandlerInterface */
313    virtual void CmdHandler(struct cmd_s *cmd);
314
315    /* SendCommand:OMX_CommandStateSet */
316    /* called in CmdHandler() thread context or by component itself */
317    void TransState(OMX_STATETYPE transition);
318    inline OMX_ERRORTYPE TransStateToLoaded(OMX_STATETYPE current);
319    inline OMX_ERRORTYPE TransStateToIdle(OMX_STATETYPE current);
320    inline OMX_ERRORTYPE TransStateToExecuting(OMX_STATETYPE current);
321    inline OMX_ERRORTYPE TransStateToPause(OMX_STATETYPE current);
322    inline OMX_ERRORTYPE TransStateToWaitForResources(OMX_STATETYPE current);
323    inline OMX_ERRORTYPE TransStateToInvalid(OMX_STATETYPE current);
324
325    /* called in TransStateToIdle(Loaded) */
326    OMX_ERRORTYPE ApplyWorkingRole(void);
327    /* called in ApplyWorkingRole() */
328    OMX_ERRORTYPE AllocatePorts(void);
329    /* allocate specific port type derived from portbase */
330    virtual OMX_ERRORTYPE ComponentAllocatePorts(void) = 0;
331
332    /* SendCommand:OMX_CommandMarkBuffer */
333    /* called in CmdHandler() thread context */
334    void PushThisMark(OMX_U32 portindex, OMX_MARKTYPE *mark);
335    /* SendCommand:OMX_CommandFlush (notify:1) or other parts (notify:0) */
336    void FlushPort(OMX_U32 port_index, bool notify);
337    /* SendCommand:OMX_CommandPortDisable/Enable */
338    /* state: PortBase::OMX_PortEnabled/Disabled */
339    void TransStatePort(OMX_U32 port_index, OMX_U8 state);
340
341    /* Get/SetParameter */
342    virtual OMX_ERRORTYPE
343        ComponentGetParameter(OMX_INDEXTYPE nParamIndex,
344                              OMX_PTR pComponentParameterStructure) = 0;
345    virtual OMX_ERRORTYPE
346        ComponentSetParameter(OMX_INDEXTYPE nIndex,
347                              OMX_PTR pComponentParameterStructure) = 0;
348
349    /* Get/SetConfig */
350    virtual OMX_ERRORTYPE
351        ComponentGetConfig(OMX_INDEXTYPE nIndex,
352                           OMX_PTR pComponentConfigStructure) = 0;
353    virtual OMX_ERRORTYPE
354        ComponentSetConfig(OMX_INDEXTYPE nIndex,
355                           OMX_PTR pComponentConfigStructure) = 0;
356
357    /* buffer processing */
358    /* implement WorkableInterface */
359    virtual void Work(void); /* handle this->ports, hold ports_block */
360
361    /* called in Work() after ProcessorProcess() */
362    void PostProcessBuffers(OMX_BUFFERHEADERTYPE ***buffers,
363                            const buffer_retain_t *retain);
364    void SourcePostProcessBuffers(OMX_BUFFERHEADERTYPE ***buffers);
365    void FilterPostProcessBuffers(OMX_BUFFERHEADERTYPE ***buffers,
366                                  const buffer_retain_t *retain);
367    void SinkPostProcessBuffers();
368
369    /* processor callbacks */
370    /* TransState */
371    virtual OMX_ERRORTYPE ProcessorInit(void);  /* Loaded to Idle */
372    virtual OMX_ERRORTYPE ProcessorDeinit(void);/* Idle to Loaded */
373    virtual OMX_ERRORTYPE ProcessorStart(void); /* Idle to Executing/Pause */
374    virtual OMX_ERRORTYPE ProcessorReset(void); /* Reset */
375    virtual OMX_ERRORTYPE ProcessorStop(void);  /* Executing/Pause to Idle */
376    virtual OMX_ERRORTYPE ProcessorPause(void); /* Executing to Pause */
377    virtual OMX_ERRORTYPE ProcessorResume(void);/* Pause to Executing */
378    virtual OMX_ERRORTYPE ProcessorFlush(OMX_U32 port_index); /* Flush */
379    virtual OMX_ERRORTYPE ProcessorPreFillBuffer(OMX_BUFFERHEADERTYPE* buffer);
380    virtual OMX_ERRORTYPE ProcessorPreEmptyBuffer(OMX_BUFFERHEADERTYPE* buffer);
381
382    /* invoked when buffer is to be freed */
383    virtual OMX_ERRORTYPE ProcessorPreFreeBuffer(OMX_U32 nPortIndex, OMX_BUFFERHEADERTYPE* pBuffer);
384    /* Work */
385    virtual OMX_ERRORTYPE ProcessorProcess(OMX_BUFFERHEADERTYPE ***pBuffers,
386                                           buffer_retain_t *retain,
387                                           OMX_U32 nr_buffers);
388    virtual OMX_ERRORTYPE ProcessorProcess(OMX_BUFFERHEADERTYPE **pBuffers,
389                                           buffer_retain_t *retain,
390                                           OMX_U32 nr_buffers);
391
392    /* end of component methods & helpers */
393
394    /* process component's commands work */
395    CmdProcessWork *cmdwork;
396
397    /* buffer processing work */
398    WorkQueue *bufferwork;
399
400    /* component variant */
401    typedef enum component_variant_e {
402        CVARIANT_NULL = 0,
403        CVARIANT_SOURCE,
404        CVARIANT_FILTER,
405        CVARIANT_SINK,
406    } component_variant_t;
407
408    component_variant_t cvariant;
409
410    /* roles */
411    OMX_U8 **roles;
412    OMX_U32 nr_roles;
413
414    OMX_STRING working_role;
415
416    /* omx standard handle */
417    /* allocated at GetHandle, freed at FreeHandle */
418    OMX_COMPONENTTYPE *handle;
419
420    /* component module */
421    CModule *cmodule;
422
423    OMX_STATETYPE state;
424
425    const static OMX_STATETYPE OMX_StateUnloaded = OMX_StateVendorStartUnused;
426
427    /* omx standard callbacks */
428    OMX_PTR appdata;
429    OMX_CALLBACKTYPE *callbacks;
430
431    /* component name */
432    char name[OMX_MAX_STRINGNAME_SIZE];
433
434    /* state lock */
435    pthread_mutex_t state_block;
436
437    OMX_U32 mMaxFrameWidth;
438    OMX_U32 mMaxFrameHeight;
439
440    /* omx specification version */
441#ifndef ANDROID
442    const static OMX_U8 OMX_SPEC_VERSION_MAJOR = 1;
443    const static OMX_U8 OMX_SPEC_VERSION_MINOR = 1;
444    const static OMX_U8 OMX_SPEC_VERSION_REVISION = 2;
445    const static OMX_U8 OMX_SPEC_VERSION_STEP = 0;
446#else
447    const static OMX_U8 OMX_SPEC_VERSION_MAJOR = 1;
448    const static OMX_U8 OMX_SPEC_VERSION_MINOR = 0;
449    const static OMX_U8 OMX_SPEC_VERSION_REVISION = 0;
450    const static OMX_U8 OMX_SPEC_VERSION_STEP = 0;
451#endif
452
453    const static OMX_U32 OMX_SPEC_VERSION = 0
454        | (OMX_SPEC_VERSION_MAJOR << 0)
455        | (OMX_SPEC_VERSION_MINOR << 8)
456        | (OMX_SPEC_VERSION_REVISION << 16)
457        | (OMX_SPEC_VERSION_STEP << 24);
458};
459
460#endif /* __COMPONENTBASE_H */
461