portbase.cpp revision cd27ef4881e3b8c9b1ff51a320d84ef71f522e90
1/*
2 * Copyright (C) 2009 Wind River Systems.
3 */
4
5#include <stdlib.h>
6#include <string.h>
7
8#include <OMX_Core.h>
9#include <OMX_Component.h>
10
11#include <portbase.h>
12#include <componentbase.h>
13
14#define LOG_TAG "portbase"
15#include <log.h>
16
17/*
18 * constructor & destructor
19 */
20void PortBase::__PortBase(void)
21{
22    buffer_hdrs = NULL;
23    nr_buffer_hdrs = 0;
24    buffer_hdrs_completion = false;
25
26    pthread_mutex_init(&hdrs_lock, NULL);
27    pthread_cond_init(&hdrs_wait, NULL);
28
29    __queue_init(&bufferq);
30    pthread_mutex_init(&bufferq_lock, NULL);
31
32    memset(&portparam, 0, sizeof(portparam));
33    memset(&audioparam, 0, sizeof(audioparam));
34
35    owner = NULL;
36    appdata = NULL;
37    callbacks = NULL;
38}
39
40PortBase::PortBase()
41{
42    __PortBase();
43}
44
45PortBase::~PortBase()
46{
47    struct list *entry, *temp;
48
49    /* should've been already freed at FreeBuffer() */
50    list_foreach_safe(buffer_hdrs, entry, temp) {
51        free(entry->data); /* OMX_BUFFERHEADERTYPE */
52        __list_delete(buffer_hdrs, entry);
53    }
54
55    pthread_cond_destroy(&hdrs_wait);
56    pthread_mutex_destroy(&hdrs_lock);
57
58    /* should've been already freed at buffer processing */
59    queue_free_all(&bufferq);
60    pthread_mutex_destroy(&bufferq_lock);
61}
62
63/* end of constructor & destructor */
64
65/*
66 * accessor
67 */
68/* owner */
69void PortBase::SetOwner(OMX_COMPONENTTYPE *handle)
70{
71    owner = handle;
72}
73
74OMX_COMPONENTTYPE *PortBase::GetOwner(void)
75{
76    return owner;
77}
78
79OMX_ERRORTYPE PortBase::SetCallbacks(OMX_HANDLETYPE hComponent,
80                                     OMX_CALLBACKTYPE *pCallbacks,
81                                     OMX_PTR pAppData)
82{
83    if (owner != hComponent)
84        return OMX_ErrorBadParameter;
85
86    appdata = pAppData;
87    callbacks = pCallbacks;
88
89    return OMX_ErrorNone;
90}
91
92/* end of accessor */
93
94/*
95 * component methods & helpers
96 */
97/* Get/SetParameter */
98void PortBase::SetPortParam(
99    const OMX_PARAM_PORTDEFINITIONTYPE *pComponentParameterStructure)
100{
101    memcpy(&portparam, pComponentParameterStructure, sizeof(portparam));
102}
103
104const OMX_PARAM_PORTDEFINITIONTYPE *PortBase::GetPortParam(void)
105{
106    return &portparam;
107}
108
109/* audio parameter */
110void PortBase::SetAudioPortParam(
111    const OMX_AUDIO_PARAM_PORTFORMATTYPE *pComponentParameterStructure)
112{
113    memcpy(&audioparam, pComponentParameterStructure, sizeof(audioparam));
114}
115
116const OMX_AUDIO_PARAM_PORTFORMATTYPE *PortBase::GetAudioPortParam(void)
117{
118    return &audioparam;
119}
120
121/* Use/Allocate/FreeBuffer */
122OMX_ERRORTYPE PortBase::UseBuffer(OMX_BUFFERHEADERTYPE **ppBufferHdr,
123                                  OMX_U32 nPortIndex,
124                                  OMX_PTR pAppPrivate,
125                                  OMX_U32 nSizeBytes,
126                                  OMX_U8 *pBuffer)
127{
128    OMX_BUFFERHEADERTYPE *buffer_hdr;
129    struct list *entry;
130    OMX_STATETYPE state;
131
132    state = GetOwnerState();
133    if (state != OMX_StateLoaded)
134        return OMX_ErrorIncorrectStateOperation;
135
136    pthread_mutex_lock(&hdrs_lock);
137
138    if (portparam.bPopulated == OMX_TRUE) {
139        pthread_mutex_unlock(&hdrs_lock);
140        return OMX_ErrorNone;
141    }
142
143    buffer_hdr = (OMX_BUFFERHEADERTYPE *)calloc(1, sizeof(*buffer_hdr));
144    if (!buffer_hdr) {
145        pthread_mutex_unlock(&hdrs_lock);
146        return OMX_ErrorInsufficientResources;
147    }
148
149    entry = list_alloc(buffer_hdr);
150    if (!entry) {
151        free(buffer_hdr);
152        pthread_mutex_unlock(&hdrs_lock);
153        return OMX_ErrorInsufficientResources;
154    }
155
156    ComponentBase::SetTypeHeader(buffer_hdr, sizeof(*buffer_hdr));
157    buffer_hdr->pBuffer = pBuffer;
158    buffer_hdr->nAllocLen = nSizeBytes;
159    buffer_hdr->pAppPrivate = pAppPrivate;
160    if (portparam.eDir == OMX_DirInput) {
161        buffer_hdr->nInputPortIndex = nPortIndex;
162        buffer_hdr->nOutputPortIndex = 0x7fffffff;
163        buffer_hdr->pInputPortPrivate = this;
164        buffer_hdr->pOutputPortPrivate = NULL;
165    }
166    else {
167        buffer_hdr->nOutputPortIndex = nPortIndex;
168        buffer_hdr->nInputPortIndex = 0x7fffffff;
169        buffer_hdr->pOutputPortPrivate = this;
170        buffer_hdr->pInputPortPrivate = NULL;
171    }
172
173    buffer_hdrs = __list_add_tail(buffer_hdrs, entry);
174    nr_buffer_hdrs++;
175
176    if (nr_buffer_hdrs >= portparam.nBufferCountActual) {
177        portparam.bPopulated = OMX_TRUE;
178        buffer_hdrs_completion = true;
179        pthread_cond_signal(&hdrs_wait);
180    }
181
182    *ppBufferHdr = buffer_hdr;
183
184    pthread_mutex_unlock(&hdrs_lock);
185    return OMX_ErrorNone;
186}
187
188OMX_ERRORTYPE PortBase::AllocateBuffer(OMX_BUFFERHEADERTYPE **ppBuffer,
189                                       OMX_U32 nPortIndex,
190                                       OMX_PTR pAppPrivate,
191                                       OMX_U32 nSizeBytes)
192{
193    OMX_BUFFERHEADERTYPE *buffer_hdr;
194    struct list *entry;
195    OMX_STATETYPE state;
196
197    state = GetOwnerState();
198    if (state != OMX_StateLoaded)
199        return OMX_ErrorIncorrectStateOperation;
200
201    pthread_mutex_lock(&hdrs_lock);
202    if (portparam.bPopulated == OMX_TRUE) {
203        pthread_mutex_unlock(&hdrs_lock);
204        return OMX_ErrorNone;
205    }
206
207    buffer_hdr = (OMX_BUFFERHEADERTYPE *)
208        calloc(1, sizeof(*buffer_hdr) + nSizeBytes);
209    if (!buffer_hdr) {
210        pthread_mutex_unlock(&hdrs_lock);
211        return OMX_ErrorInsufficientResources;
212    }
213
214    entry = list_alloc(buffer_hdr);
215    if (!entry) {
216        free(buffer_hdr);
217        pthread_mutex_unlock(&hdrs_lock);
218        return OMX_ErrorInsufficientResources;
219    }
220
221    ComponentBase::SetTypeHeader(buffer_hdr, sizeof(*buffer_hdr));
222    buffer_hdr->pBuffer = (OMX_U8 *)buffer_hdr + sizeof(*buffer_hdr);
223    buffer_hdr->nAllocLen = nSizeBytes;
224    buffer_hdr->pAppPrivate = pAppPrivate;
225    if (portparam.eDir == OMX_DirInput) {
226        buffer_hdr->nInputPortIndex = nPortIndex;
227        buffer_hdr->nOutputPortIndex = (OMX_U32)-1;
228        buffer_hdr->pInputPortPrivate = this;
229        buffer_hdr->pOutputPortPrivate = NULL;
230    }
231    else {
232        buffer_hdr->nOutputPortIndex = nPortIndex;
233        buffer_hdr->nInputPortIndex = (OMX_U32)-1;
234        buffer_hdr->pOutputPortPrivate = this;
235        buffer_hdr->pInputPortPrivate = NULL;
236    }
237
238    buffer_hdrs = __list_add_tail(buffer_hdrs, entry);
239    nr_buffer_hdrs++;
240
241    if (nr_buffer_hdrs == portparam.nBufferCountActual) {
242        portparam.bPopulated = OMX_TRUE;
243        buffer_hdrs_completion = true;
244        pthread_cond_signal(&hdrs_wait);
245    }
246
247    *ppBuffer = buffer_hdr;
248
249    pthread_mutex_unlock(&hdrs_lock);
250    return OMX_ErrorNone;
251}
252
253OMX_ERRORTYPE PortBase::FreeBuffer(OMX_U32 nPortIndex,
254                                   OMX_BUFFERHEADERTYPE *pBuffer)
255{
256    struct list *entry;
257    OMX_STATETYPE state;
258    OMX_ERRORTYPE ret;
259
260    state = GetOwnerState();
261    if (state != OMX_StateLoaded)
262        return OMX_ErrorIncorrectStateOperation;
263
264    pthread_mutex_lock(&hdrs_lock);
265    entry = list_find(buffer_hdrs, pBuffer);
266
267    if (!entry) {
268        pthread_mutex_unlock(&hdrs_lock);
269        return OMX_ErrorNone;
270    }
271
272    if (entry->data != pBuffer) {
273        pthread_mutex_unlock(&hdrs_lock);
274        return OMX_ErrorBadParameter;
275    }
276
277    ret = ComponentBase::CheckTypeHeader(pBuffer, sizeof(*pBuffer));
278    if (ret != OMX_ErrorNone) {
279        pthread_mutex_unlock(&hdrs_lock);
280        return ret;
281    }
282
283    buffer_hdrs = __list_delete(buffer_hdrs, entry);
284    nr_buffer_hdrs--;
285
286    portparam.bPopulated = OMX_FALSE;
287    if (!nr_buffer_hdrs) {
288        buffer_hdrs_completion = true;
289        pthread_cond_signal(&hdrs_wait);
290    }
291
292    free(pBuffer);
293
294    pthread_mutex_unlock(&hdrs_lock);
295    return OMX_ErrorNone;
296}
297
298void PortBase::WaitPortBufferCompletion(void)
299{
300    pthread_mutex_lock(&hdrs_lock);
301    if (!buffer_hdrs_completion)
302        pthread_cond_wait(&hdrs_wait, &hdrs_lock);
303    buffer_hdrs_completion = !buffer_hdrs_completion;
304    pthread_mutex_unlock(&hdrs_lock);
305}
306
307    /* Empty/FillThisBuffer */
308OMX_ERRORTYPE PortBase::PushThisBuffer(OMX_BUFFERHEADERTYPE *pBuffer)
309{
310    int ret;
311
312    pthread_mutex_lock(&bufferq_lock);
313    ret = queue_push_tail(&bufferq, pBuffer);
314    pthread_mutex_unlock(&bufferq_lock);
315
316    if (ret)
317        return OMX_ErrorInsufficientResources;
318
319    return OMX_ErrorNone;
320}
321
322OMX_BUFFERHEADERTYPE *PortBase::PopBuffer(void)
323{
324    OMX_BUFFERHEADERTYPE *buffer;
325
326    pthread_mutex_lock(&bufferq_lock);
327    buffer = (OMX_BUFFERHEADERTYPE *)queue_pop_head(&bufferq);
328    pthread_mutex_unlock(&bufferq_lock);
329
330    return buffer;
331}
332
333OMX_U32 PortBase::BufferQueueLength(void)
334{
335    OMX_U32 length;
336
337    pthread_mutex_lock(&bufferq_lock);
338    length = queue_length(&bufferq);
339    pthread_mutex_unlock(&bufferq_lock);
340
341    return length;
342}
343
344OMX_ERRORTYPE PortBase::ReturnThisBuffer(OMX_BUFFERHEADERTYPE *pBuffer)
345{
346    /*
347     * Todo
348     *   Empty/FillThisBufferDone event
349     */
350
351    return OMX_ErrorNone;
352}
353
354OMX_STATETYPE PortBase::GetOwnerState(void)
355{
356    OMX_STATETYPE state = OMX_StateInvalid;
357
358    if (owner) {
359        ComponentBase *cbase;
360        cbase = static_cast<ComponentBase *>(owner->pComponentPrivate);
361        if (!cbase)
362            return state;
363
364        cbase->CBaseGetState((void *)owner, &state);
365    }
366
367    return state;
368}
369
370/* end of component methods & helpers */
371
372/* end of PortBase */
373