1/*
2 * Copyright (C) 2011 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*************************************************************************
18* @file   VideoEditorBuffer.c
19* @brief  StageFright shell Buffer
20*************************************************************************
21*/
22#undef M4OSA_TRACE_LEVEL
23#define M4OSA_TRACE_LEVEL 1
24
25#include "VideoEditorBuffer.h"
26#include "utils/Log.h"
27
28#define VIDEOEDITOR_BUFFEPOOL_MAX_NAME_SIZE 40
29
30#define VIDEOEDITOR_SAFE_FREE(p) \
31{ \
32    if(M4OSA_NULL != p) \
33    { \
34        free(p); \
35        p = M4OSA_NULL; \
36    } \
37}
38
39/**
40 ************************************************************************
41 M4OSA_ERR VIDEOEDITOR_BUFFER_allocatePool(VIDEOEDITOR_BUFFER_Pool** ppool,
42 *                                         M4OSA_UInt32 nbBuffers)
43 * @brief   Allocate a pool of nbBuffers buffers
44 *
45 * @param   ppool      : IN The buffer pool to create
46 * @param   nbBuffers  : IN The number of buffers in the pool
47 * @param   poolName   : IN a name given to the pool
48 * @return  Error code
49 ************************************************************************
50*/
51M4OSA_ERR VIDEOEDITOR_BUFFER_allocatePool(VIDEOEDITOR_BUFFER_Pool** ppool,
52        M4OSA_UInt32 nbBuffers, M4OSA_Char* poolName)
53{
54    M4OSA_ERR lerr = M4NO_ERROR;
55    VIDEOEDITOR_BUFFER_Pool* pool;
56    M4OSA_UInt32 index;
57
58    ALOGV("VIDEOEDITOR_BUFFER_allocatePool : ppool = 0x%x nbBuffers = %d ",
59        ppool, nbBuffers);
60
61    pool = M4OSA_NULL;
62    pool = (VIDEOEDITOR_BUFFER_Pool*)M4OSA_32bitAlignedMalloc(
63            sizeof(VIDEOEDITOR_BUFFER_Pool), VIDEOEDITOR_BUFFER_EXTERNAL,
64            (M4OSA_Char*)("VIDEOEDITOR_BUFFER_allocatePool: pool"));
65    if (M4OSA_NULL == pool)
66    {
67        lerr = M4ERR_ALLOC;
68        goto VIDEOEDITOR_BUFFER_allocatePool_Cleanup;
69    }
70
71    ALOGV("VIDEOEDITOR_BUFFER_allocatePool : Allocating Pool buffers");
72    pool->pNXPBuffer = M4OSA_NULL;
73    pool->pNXPBuffer = (VIDEOEDITOR_BUFFER_Buffer*)M4OSA_32bitAlignedMalloc(
74                            sizeof(VIDEOEDITOR_BUFFER_Buffer)*nbBuffers,
75                            VIDEOEDITOR_BUFFER_EXTERNAL,
76                            (M4OSA_Char*)("BUFFER_allocatePool: pNXPBuffer"));
77    if(M4OSA_NULL == pool->pNXPBuffer)
78    {
79        lerr = M4ERR_ALLOC;
80        goto VIDEOEDITOR_BUFFER_allocatePool_Cleanup;
81    }
82
83    for (index = 0; index < nbBuffers; index++)
84    {
85        pool->pNXPBuffer[index].pData = M4OSA_NULL;
86    }
87
88    ALOGV("VIDEOEDITOR_BUFFER_allocatePool : Allocating Pool name buffer");
89    pool->poolName = M4OSA_NULL;
90    pool->poolName = (M4OSA_Char*)M4OSA_32bitAlignedMalloc(
91        VIDEOEDITOR_BUFFEPOOL_MAX_NAME_SIZE,VIDEOEDITOR_BUFFER_EXTERNAL,
92        (M4OSA_Char*)("VIDEOEDITOR_BUFFER_allocatePool: poolname"));
93    if(pool->poolName == M4OSA_NULL)
94    {
95        lerr = M4ERR_ALLOC;
96        goto VIDEOEDITOR_BUFFER_allocatePool_Cleanup;
97    }
98
99    ALOGV("VIDEOEDITOR_BUFFER_allocatePool : Assigning Pool name buffer");
100
101    memset((void *)pool->poolName, 0,VIDEOEDITOR_BUFFEPOOL_MAX_NAME_SIZE);
102    memcpy((void *)pool->poolName, (void *)poolName,
103        VIDEOEDITOR_BUFFEPOOL_MAX_NAME_SIZE-1);
104
105    pool->NB = nbBuffers;
106
107VIDEOEDITOR_BUFFER_allocatePool_Cleanup:
108    if(M4NO_ERROR != lerr)
109    {
110        VIDEOEDITOR_SAFE_FREE(pool->pNXPBuffer);
111        VIDEOEDITOR_SAFE_FREE(pool->poolName);
112        VIDEOEDITOR_SAFE_FREE(pool);
113    }
114    *ppool = pool;
115    ALOGV("VIDEOEDITOR_BUFFER_allocatePool END");
116
117    return lerr;
118}
119
120/**
121 ************************************************************************
122 M4OSA_ERR VIDEOEDITOR_BUFFER_freePool(VIDEOEDITOR_BUFFER_Pool* ppool)
123 * @brief   Deallocate a buffer pool
124 *
125 * @param   ppool      : IN The buffer pool to free
126 * @return  Error code
127 ************************************************************************
128*/
129M4OSA_ERR VIDEOEDITOR_BUFFER_freePool(VIDEOEDITOR_BUFFER_Pool* ppool)
130{
131    M4OSA_ERR err;
132    M4OSA_UInt32  j = 0;
133
134    ALOGV("VIDEOEDITOR_BUFFER_freePool : ppool = 0x%x", ppool);
135
136    err = M4NO_ERROR;
137
138    for (j = 0; j < ppool->NB; j++)
139    {
140        if(M4OSA_NULL != ppool->pNXPBuffer[j].pData)
141        {
142            free(ppool->pNXPBuffer[j].pData);
143            ppool->pNXPBuffer[j].pData = M4OSA_NULL;
144        }
145    }
146
147    if(ppool != M4OSA_NULL)
148    {
149        SAFE_FREE(ppool->pNXPBuffer);
150        SAFE_FREE(ppool->poolName);
151        SAFE_FREE(ppool);
152    }
153
154    return(err);
155}
156
157/**
158 ************************************************************************
159 M4OSA_ERR VIDEOEDITOR_BUFFER_getBuffer(VIDEOEDITOR_BUFFER_Pool* ppool,
160 *         VIDEOEDITOR_BUFFER_Buffer** pNXPBuffer)
161 * @brief   Returns a buffer in a given state
162 *
163 * @param   ppool      : IN The buffer pool
164 * @param   desiredState : IN The buffer state
165 * @param   pNXPBuffer : IN The selected buffer
166 * @return  Error code
167 ************************************************************************
168*/
169M4OSA_ERR VIDEOEDITOR_BUFFER_getBuffer(VIDEOEDITOR_BUFFER_Pool* ppool,
170        VIDEOEDITOR_BUFFER_State desiredState,
171        VIDEOEDITOR_BUFFER_Buffer** pNXPBuffer)
172{
173    M4OSA_ERR err = M4NO_ERROR;
174    M4OSA_Bool bFound = M4OSA_FALSE;
175    M4OSA_UInt32 i, ibuf;
176
177    ALOGV("VIDEOEDITOR_BUFFER_getBuffer from %s in state=%d",
178        ppool->poolName, desiredState);
179
180    ibuf = 0;
181
182    for (i=0; i < ppool->NB; i++)
183    {
184        bFound = (ppool->pNXPBuffer[i].state == desiredState);
185        if (bFound)
186        {
187            ibuf = i;
188            break;
189        }
190    }
191
192    if(!bFound)
193    {
194        ALOGV("VIDEOEDITOR_BUFFER_getBuffer No buffer available in state %d",
195            desiredState);
196        *pNXPBuffer = M4OSA_NULL;
197        return M4ERR_NO_BUFFER_AVAILABLE;
198    }
199
200    /* case where a buffer has been found */
201    *pNXPBuffer = &(ppool->pNXPBuffer[ibuf]);
202
203    ALOGV("VIDEOEDITOR_BUFFER_getBuffer: idx = %d", ibuf);
204
205    return(err);
206}
207
208M4OSA_ERR VIDEOEDITOR_BUFFER_initPoolBuffers(VIDEOEDITOR_BUFFER_Pool* pool,
209    M4OSA_UInt32 lSize)
210{
211    M4OSA_ERR     err = M4NO_ERROR;
212    M4OSA_UInt32  index, j;
213
214    /**
215     * Initialize all the buffers in the pool */
216    for(index = 0; index < pool->NB; index++)
217    {
218        pool->pNXPBuffer[index].pData = M4OSA_NULL;
219        pool->pNXPBuffer[index].pData = (M4OSA_Void*)M4OSA_32bitAlignedMalloc(
220            lSize, VIDEOEDITOR_BUFFER_EXTERNAL,
221            (M4OSA_Char*)("BUFFER_initPoolBuffers: Buffer data"));
222        if(M4OSA_NULL == pool->pNXPBuffer[index].pData)
223        {
224            for (j = 0; j < index; j++)
225            {
226                if(M4OSA_NULL != pool->pNXPBuffer[j].pData)
227                {
228                    free(pool->pNXPBuffer[j].pData);
229                    pool->pNXPBuffer[j].pData = M4OSA_NULL;
230                }
231            }
232            err = M4ERR_ALLOC;
233            return err;
234        }
235        pool->pNXPBuffer[index].size = 0;
236        pool->pNXPBuffer[index].state = VIDEOEDITOR_BUFFER_kEmpty;
237        pool->pNXPBuffer[index].idx = index;
238        pool->pNXPBuffer[index].buffCTS = -1;
239    }
240    return err;
241}
242
243M4OSA_ERR VIDEOEDITOR_BUFFER_getOldestBuffer(VIDEOEDITOR_BUFFER_Pool *pool,
244        VIDEOEDITOR_BUFFER_State desiredState,
245        VIDEOEDITOR_BUFFER_Buffer** pNXPBuffer)
246{
247    M4OSA_ERR     err = M4NO_ERROR;
248    M4OSA_UInt32  index, j;
249    M4_MediaTime  candidateTimeStamp = (M4_MediaTime)0x7ffffff;
250    M4OSA_Bool    bFound = M4OSA_FALSE;
251
252    *pNXPBuffer = M4OSA_NULL;
253    for(index = 0; index< pool->NB; index++)
254    {
255        if(pool->pNXPBuffer[index].state == desiredState)
256        {
257            if(pool->pNXPBuffer[index].buffCTS <= candidateTimeStamp)
258            {
259                bFound = M4OSA_TRUE;
260                candidateTimeStamp = pool->pNXPBuffer[index].buffCTS;
261                    *pNXPBuffer = &(pool->pNXPBuffer[index]);
262            }
263        }
264    }
265    if(M4OSA_FALSE == bFound)
266    {
267        ALOGV("VIDEOEDITOR_BUFFER_getOldestBuffer WARNING no buffer available");
268        err = M4ERR_NO_BUFFER_AVAILABLE;
269    }
270    return err;
271}
272