portbase.cpp revision 7b94bb78335b52b812d8b4137ce80799bb6b9125
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    memset(&portparam, 0, sizeof(portparam));
30    memset(&audioparam, 0, sizeof(audioparam));
31}
32
33PortBase::PortBase()
34{
35    __PortBase();
36}
37
38PortBase::~PortBase()
39{
40    struct list *entry, *temp;
41
42    /* should've been already freed at FreeBuffer() */
43    list_foreach_safe(buffer_hdrs, entry, temp) {
44        free(entry->data); /* OMX_BUFFERHEADERTYPE */
45        __list_delete(buffer_hdrs, entry);
46    }
47
48    pthread_cond_destroy(&hdrs_wait);
49    pthread_mutex_destroy(&hdrs_lock);
50}
51
52/* end of constructor & destructor */
53
54/*
55 * accessor
56 */
57/* owner */
58void PortBase::SetOwner(OMX_COMPONENTTYPE *handle)
59{
60    owner = handle;
61}
62
63OMX_COMPONENTTYPE *PortBase::GetOwner(void)
64{
65    return owner;
66}
67
68/*
69 * component methods & helpers
70 */
71/* Get/SetParameter */
72void PortBase::SetPortParam(
73    const OMX_PARAM_PORTDEFINITIONTYPE *pComponentParameterStructure)
74{
75    memcpy(&portparam, pComponentParameterStructure, sizeof(portparam));
76}
77
78const OMX_PARAM_PORTDEFINITIONTYPE *PortBase::GetPortParam(void)
79{
80    return &portparam;
81}
82
83/* audio parameter */
84void PortBase::SetAudioPortParam(
85    const OMX_AUDIO_PARAM_PORTFORMATTYPE *pComponentParameterStructure)
86{
87    memcpy(&audioparam, pComponentParameterStructure, sizeof(audioparam));
88}
89
90const OMX_AUDIO_PARAM_PORTFORMATTYPE *PortBase::GetAudioPortParam(void)
91{
92    return &audioparam;
93}
94
95/* Use/Allocate/FreeBuffer */
96OMX_ERRORTYPE PortBase::UseBuffer(OMX_BUFFERHEADERTYPE **ppBufferHdr,
97                                  OMX_U32 nPortIndex,
98                                  OMX_PTR pAppPrivate,
99                                  OMX_U32 nSizeBytes,
100                                  OMX_U8 *pBuffer)
101{
102    OMX_BUFFERHEADERTYPE *buffer_hdr;
103    struct list *entry;
104
105    pthread_mutex_lock(&hdrs_lock);
106
107    if (portparam.bPopulated == OMX_TRUE) {
108        pthread_mutex_unlock(&hdrs_lock);
109        return OMX_ErrorNone;
110    }
111
112    buffer_hdr = (OMX_BUFFERHEADERTYPE *)calloc(1, sizeof(*buffer_hdr));
113    if (!buffer_hdr) {
114        pthread_mutex_unlock(&hdrs_lock);
115        return OMX_ErrorInsufficientResources;
116    }
117
118    entry = list_alloc(buffer_hdr);
119    if (!entry) {
120        free(buffer_hdr);
121        pthread_mutex_unlock(&hdrs_lock);
122        return OMX_ErrorInsufficientResources;
123    }
124
125    ComponentBase::SetTypeHeader(buffer_hdr, sizeof(*buffer_hdr));
126    buffer_hdr->pBuffer = pBuffer;
127    buffer_hdr->nAllocLen = nSizeBytes;
128    buffer_hdr->pAppPrivate = pAppPrivate;
129    if (portparam.eDir == OMX_DirInput) {
130        buffer_hdr->nInputPortIndex = nPortIndex;
131        buffer_hdr->nOutputPortIndex = 0x7fffffff;
132        buffer_hdr->pInputPortPrivate = this;
133        buffer_hdr->pOutputPortPrivate = NULL;
134    }
135    else {
136        buffer_hdr->nOutputPortIndex = nPortIndex;
137        buffer_hdr->nInputPortIndex = 0x7fffffff;
138        buffer_hdr->pOutputPortPrivate = this;
139        buffer_hdr->pInputPortPrivate = NULL;
140    }
141
142    buffer_hdrs = __list_add_tail(buffer_hdrs, entry);
143    nr_buffer_hdrs++;
144
145    if (nr_buffer_hdrs >= portparam.nBufferCountActual) {
146        portparam.bPopulated = OMX_TRUE;
147        buffer_hdrs_completion = true;
148        pthread_cond_signal(&hdrs_wait);
149    }
150
151    *ppBufferHdr = buffer_hdr;
152
153    pthread_mutex_unlock(&hdrs_lock);
154    return OMX_ErrorNone;
155}
156
157OMX_ERRORTYPE PortBase::AllocateBuffer(OMX_BUFFERHEADERTYPE **ppBuffer,
158                                       OMX_U32 nPortIndex,
159                                       OMX_PTR pAppPrivate,
160                                       OMX_U32 nSizeBytes)
161{
162    OMX_BUFFERHEADERTYPE *buffer_hdr;
163    struct list *entry;
164
165    pthread_mutex_lock(&hdrs_lock);
166    if (portparam.bPopulated == OMX_TRUE) {
167        pthread_mutex_unlock(&hdrs_lock);
168        return OMX_ErrorNone;
169    }
170
171    buffer_hdr = (OMX_BUFFERHEADERTYPE *)
172        calloc(1, sizeof(*buffer_hdr) + nSizeBytes);
173    if (!buffer_hdr) {
174        pthread_mutex_unlock(&hdrs_lock);
175        return OMX_ErrorInsufficientResources;
176    }
177
178    entry = list_alloc(buffer_hdr);
179    if (!entry) {
180        free(buffer_hdr);
181        pthread_mutex_unlock(&hdrs_lock);
182        return OMX_ErrorInsufficientResources;
183    }
184
185    ComponentBase::SetTypeHeader(buffer_hdr, sizeof(*buffer_hdr));
186    buffer_hdr->pBuffer = (OMX_U8 *)buffer_hdr + sizeof(*buffer_hdr);
187    buffer_hdr->nAllocLen = nSizeBytes;
188    buffer_hdr->pAppPrivate = pAppPrivate;
189    if (portparam.eDir == OMX_DirInput) {
190        buffer_hdr->nInputPortIndex = nPortIndex;
191        buffer_hdr->nOutputPortIndex = (OMX_U32)-1;
192        buffer_hdr->pInputPortPrivate = this;
193        buffer_hdr->pOutputPortPrivate = NULL;
194    }
195    else {
196        buffer_hdr->nOutputPortIndex = nPortIndex;
197        buffer_hdr->nInputPortIndex = (OMX_U32)-1;
198        buffer_hdr->pOutputPortPrivate = this;
199        buffer_hdr->pInputPortPrivate = NULL;
200    }
201
202    buffer_hdrs = __list_add_tail(buffer_hdrs, entry);
203    nr_buffer_hdrs++;
204
205    if (nr_buffer_hdrs == portparam.nBufferCountActual) {
206        portparam.bPopulated = OMX_TRUE;
207        buffer_hdrs_completion = true;
208        pthread_cond_signal(&hdrs_wait);
209    }
210
211    *ppBuffer = buffer_hdr;
212
213    pthread_mutex_unlock(&hdrs_lock);
214    return OMX_ErrorNone;
215}
216
217OMX_ERRORTYPE PortBase::FreeBuffer(OMX_U32 nPortIndex,
218                                   OMX_BUFFERHEADERTYPE *pBuffer)
219{
220    struct list *entry;
221    OMX_ERRORTYPE ret;
222
223    pthread_mutex_lock(&hdrs_lock);
224    entry = list_find(buffer_hdrs, pBuffer);
225
226    if (!entry) {
227        pthread_mutex_unlock(&hdrs_lock);
228        return OMX_ErrorNone;
229    }
230
231    if (entry->data != pBuffer) {
232        pthread_mutex_unlock(&hdrs_lock);
233        return OMX_ErrorBadParameter;
234    }
235
236    ret = ComponentBase::CheckTypeHeader(pBuffer, sizeof(*pBuffer));
237    if (ret != OMX_ErrorNone) {
238        pthread_mutex_unlock(&hdrs_lock);
239        return ret;
240    }
241
242    buffer_hdrs = __list_delete(buffer_hdrs, entry);
243    nr_buffer_hdrs--;
244
245    portparam.bPopulated = OMX_FALSE;
246    if (!nr_buffer_hdrs) {
247        buffer_hdrs_completion = true;
248        pthread_cond_signal(&hdrs_wait);
249    }
250
251    free(pBuffer);
252
253    pthread_mutex_unlock(&hdrs_lock);
254    return OMX_ErrorNone;
255}
256
257void PortBase::WaitPortBufferCompletion(void)
258{
259    pthread_mutex_lock(&hdrs_lock);
260    if (!buffer_hdrs_completion)
261        pthread_cond_wait(&hdrs_wait, &hdrs_lock);
262    buffer_hdrs_completion = !buffer_hdrs_completion;
263    pthread_mutex_unlock(&hdrs_lock);
264}
265
266/* end of component methods & helpers */
267
268/* end of PortBase */
269