xref: /OK3568_Linux_fs/external/camera_engine_rkaiq/rkaiq/common/media_buffer/media_buffer_pool.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2  *
3  * Copyright 2007, Silicon Image, Inc.  All rights reserved.
4  * No part of this work may be reproduced, modified, distributed, transmitted,
5  * transcribed, or translated into any language or computer format, in any form
6  * or by any means without written permission of: Silicon Image, Inc., 1060
7  * East Arques Avenue, Sunnyvale, California 94085
8  *
9  *****************************************************************************/
10 /**
11  * @file media_buffer_pool.c
12  *
13  * @brief
14  *          Buffer Pool implementation
15  *
16  * <pre>
17  *
18  *   Principal Author: Joerg Detert
19  *   Creation date:    Feb 28, 2008
20  *
21  * </pre>
22  *
23  *****************************************************************************/
24 
25 #include <string.h>
26 
27 #include "media_buffer_pool.h"
28 
29 
30 
31 #define MEDIA_BUF_ALIGN(buf, align) (((buf)+((align)-1U)) & ~((align)-1U))
32 
33 
34 /******************************************************************************
35  * MediaBufPoolGetSize
36  *****************************************************************************/
MediaBufPoolGetSize(MediaBufPoolConfig_t * pPoolConfig)37 RESULT MediaBufPoolGetSize(MediaBufPoolConfig_t* pPoolConfig)
38 {
39     RESULT  ret = RET_SUCCESS;
40 
41     if(pPoolConfig == NULL)
42     {
43         return RET_WRONG_HANDLE;
44     }
45 
46     if(pPoolConfig->bufNum > pPoolConfig->maxBufNum)
47     {
48         return RET_WRONG_CONFIG;
49     }
50 
51     /* size of extra metadata */
52     pPoolConfig->metaDataMemSize = pPoolConfig->maxBufNum * pPoolConfig->metaDataSizeMediaBuf;
53 
54     /* size of media buffer array */
55     pPoolConfig->metaDataMemSize += (uint32_t)(pPoolConfig->maxBufNum * sizeof(MediaBuffer_t));
56 
57     /* calculate size of buffer array*/
58     if(pPoolConfig->flags & (uint32_t)BUFPOOL_RINGBUFFER)
59     {
60         /* results in no gaps between buffers but an offset depending on the alignment */
61         pPoolConfig->bufMemSize = (pPoolConfig->maxBufNum * pPoolConfig->bufSize) +
62                                    pPoolConfig->bufAlign;
63 
64         /* the buffer size must be correct to the alignment otherwise we would have
65          * unaligned buffers after the first which is always aligned */
66         if((pPoolConfig->bufSize & ((uint32_t)pPoolConfig->bufAlign - 1U)) != 0U)
67         {
68             return RET_WRONG_CONFIG;
69         }
70     }
71     else
72     {
73         /* this leads to gaps between the buffers dependend on the alignment */
74         pPoolConfig->bufMemSize = pPoolConfig->maxBufNum * (pPoolConfig->bufSize +
75                                   pPoolConfig->bufAlign);
76     }
77 
78     return ret;
79 }
80 
81 
82 /******************************************************************************
83  * MediaBufPoolCreate
84  *****************************************************************************/
MediaBufPoolCreate(MediaBufPool_t * pBufPool,MediaBufPoolConfig_t * pPoolConfig,MediaBufPoolMemory_t poolMemory)85 RESULT MediaBufPoolCreate(MediaBufPool_t*       pBufPool,
86                           MediaBufPoolConfig_t* pPoolConfig,
87                           MediaBufPoolMemory_t  poolMemory)
88 {
89     uint32_t        i;
90     uint32_t        offset;
91     void*           pBuf;
92     RESULT  ret = RET_SUCCESS;
93     if(pBufPool == NULL)
94     {
95         return RET_WRONG_HANDLE;
96     }
97 
98     if((poolMemory.pMetaDataMemory  == NULL) ||
99        (poolMemory.pBufferMemory    == NULL))
100     {
101         return RET_INVALID_PARM;
102     }
103 
104     if((pPoolConfig->bufNum == 0U) || (pPoolConfig->bufSize == 0U) ||
105        (pPoolConfig->maxBufNum < pPoolConfig->bufNum))
106     {
107         return RET_WRONG_CONFIG;
108     }
109 
110     /* If buffer pool is switched to ringbuffer mode, there must not be any gap*/
111     /* between individual buffers inside static buffer pool, introduced by data*/
112     /* alignement issues (e.g. rouding up of internal buffer sizes).*/
113     /* That is, the buffer size must be a multiple of the data alignement.*/
114     if((pPoolConfig->flags & BUFPOOL_RINGBUFFER) &&
115        (pPoolConfig->bufSize % pPoolConfig->bufAlign))
116     {
117         return RET_WRONG_CONFIG;
118     }
119 
120     /* initialize buffer pool object*/
121     (void) memset(pBufPool, 0, sizeof(MediaBufPool_t));
122 
123     pBufPool->bufSize              = pPoolConfig->bufSize;
124     pBufPool->metaDataSizeMediaBuf = pPoolConfig->metaDataSizeMediaBuf;
125     pBufPool->bufNum               = pPoolConfig->bufNum;
126     pBufPool->freeBufNum           = pPoolConfig->bufNum;
127     pBufPool->maxBufNum            = pPoolConfig->maxBufNum;
128     pBufPool->poolSize             = pPoolConfig->bufNum * pPoolConfig->bufSize;
129     pBufPool->flags                = pPoolConfig->flags;
130 
131     /* The memory given by the caller is assigned to the buffer pool */
132     pBufPool->pBaseAddress = poolMemory.pMetaDataMemory;
133 
134     /* Make sure that sizes in pPoolConfig are written */
135     (void) MediaBufPoolGetSize(pPoolConfig);
136     /* initialize buffer memory to zero */
137     (void) memset(poolMemory.pMetaDataMemory, 0, (size_t) pPoolConfig->metaDataMemSize);
138 
139     /* We use the first partition of memory for the media buffer array */
140     pBufPool->pBufArray = (MediaBuffer_t*) pBufPool->pBaseAddress;
141 
142     /* The second partition of memory is used for the buffer meta data array for Media Buffers */
143     offset = (pPoolConfig->maxBufNum * sizeof(MediaBuffer_t));
144     pBufPool->pMetaDataMediaBufBase = (void*) (((ulong_t) pBufPool->pBaseAddress) + offset);
145 
146     /* The memory pointed to by pBufferMemory is used for
147      * the real buffer memory. This memory is assigned to the pointers stored in the corresponding
148      * MediaBuffer_t[]. Due to the alignment restrictions given by the user it must be kept in mind
149      * that the alignment is added. */
150     pBuf = poolMemory.pBufferMemory;
151     for(i = 0U; i < pBufPool->maxBufNum; i++)
152     {
153         /* set base address of buffer
154            (will be changed in case that buffer pool is resized) */
155         pBufPool->pBufArray[i].pBaseAddress = (uint8_t*) MEDIA_BUF_ALIGN((ulong_t)pBuf +
156                         (i * pPoolConfig->bufSize), (uint32_t)pPoolConfig->bufAlign);
157         /* set base size of buffer
158            (will be changed in case that buffer pool is resized) */
159         pBufPool->pBufArray[i].baseSize = pBufPool->bufSize;
160 
161         if ( pPoolConfig->metaDataSizeMediaBuf != 0 )
162         {
163             /* set Media Buffer meta data structure address for
164                (stays the same during lifetime of buffer pool) */
165             pBufPool->pBufArray[i].pMetaData = (void *)((ulong_t) pBufPool->pMetaDataMediaBufBase +
166                                                (i * pPoolConfig->metaDataSizeMediaBuf));
167         }
168         else
169         {
170             pBufPool->pBufArray[i].pMetaData = NULL;
171         }
172 
173         MediaBufInit(&pBufPool->pBufArray[i]);
174     }
175 
176     AtomicMutexInit();
177 
178     return ret;
179 }
180 
181 
182 /******************************************************************************
183  * MediaBufPoolDestroy
184  *****************************************************************************/
MediaBufPoolDestroy(MediaBufPool_t * pBufPool)185 RESULT MediaBufPoolDestroy(MediaBufPool_t *pBufPool)
186 {
187     DCT_ASSERT(pBufPool != NULL);
188 
189     (void) memset(pBufPool, 0, sizeof(MediaBufPool_t));
190     AtomicMutexDestory();
191     return RET_SUCCESS;
192 }
193 
194 
195 /******************************************************************************
196  * MediaBufPoolReset
197  *****************************************************************************/
MediaBufPoolReset(MediaBufPool_t * pBufPool)198 RESULT MediaBufPoolReset(MediaBufPool_t* pBufPool)
199 {
200     uint32_t i;
201 
202     DCT_ASSERT(pBufPool != NULL);
203 
204     /* reset state variables */
205     pBufPool->freeBufNum = pBufPool->bufNum;
206     pBufPool->fillLevel  = 0;
207     pBufPool->index      = 0;
208 
209     /* re-init media buffers */
210     for(i = 0U; i < pBufPool->maxBufNum; i++)
211     {
212         MediaBufInit(&pBufPool->pBufArray[i]);
213     }
214 
215     return RET_SUCCESS;
216 }
217 
218 
219 /******************************************************************************
220  * MediaBufPoolRegisterCb
221  *****************************************************************************/
MediaBufPoolRegisterCb(MediaBufPool_t * pBufPool,MediaBufPoolCbNotify_t fpCallback,void * pUserContext)222 RESULT MediaBufPoolRegisterCb(MediaBufPool_t*         pBufPool,
223                               MediaBufPoolCbNotify_t  fpCallback,
224                               void*                   pUserContext)
225 {
226     RESULT ret = RET_NOTAVAILABLE;
227     int32_t i;
228 
229     if(pBufPool == NULL)
230     {
231         return RET_WRONG_HANDLE;
232     }
233 
234     if(fpCallback == NULL)
235     {
236         return RET_INVALID_PARM;
237     }
238 
239     if(pBufPool->notify.fpCallback == NULL)
240     {
241         pBufPool->notify.fpCallback    = fpCallback;
242         pBufPool->notify.pUserContext  = pUserContext;
243         ret = RET_SUCCESS;
244     }
245 
246     return ret;
247 }
248 
249 
250 /******************************************************************************
251  * MediaBufPoolDeregisterCb
252  *****************************************************************************/
MediaBufPoolDeregisterCb(MediaBufPool_t * pBufPool,MediaBufPoolCbNotify_t fpCallback)253 RESULT MediaBufPoolDeregisterCb(MediaBufPool_t*         pBufPool,
254                                 MediaBufPoolCbNotify_t  fpCallback)
255 {
256     RESULT ret = RET_NOTAVAILABLE;
257     int32_t i;
258 
259     if(pBufPool == NULL)
260     {
261         return RET_WRONG_HANDLE;
262     }
263 
264     if(fpCallback == NULL)
265     {
266         return RET_INVALID_PARM;
267     }
268 
269     if(pBufPool->notify.fpCallback == fpCallback)
270     {
271         pBufPool->notify.fpCallback   = NULL;
272         pBufPool->notify.pUserContext = NULL;
273         ret = RET_SUCCESS;
274     }
275 
276     return ret;
277 }
278 
279 
280 
281 /******************************************************************************
282  * MediaBufPoolGetBuffer
283  *****************************************************************************/
MediaBufPoolGetBuffer(MediaBufPool_t * pBufPool)284 MediaBuffer_t* MediaBufPoolGetBuffer(MediaBufPool_t* pBufPool)
285 {
286     MediaBuffer_t *pMediaBuffer;
287 
288     DCT_ASSERT(pBufPool != NULL);
289 
290     for(;;)
291     {
292         /* if the requested number of buffers is greater than the maximum then wait*/
293         while( pBufPool->freeBufNum == 0U )
294         {
295             return  NULL;
296         }
297 
298         /* at least one buffer is free*/
299         for(;;)
300         {
301             if(!pBufPool->pBufArray[pBufPool->index].lockCount)
302             {
303                 /* adjust the resources count*/
304                 pBufPool->freeBufNum--;
305                 pBufPool->pBufArray[pBufPool->index].lockCount = 1;
306                 pBufPool->pBufArray[pBufPool->index].pOwner = pBufPool;
307                 pMediaBuffer = &pBufPool->pBufArray[pBufPool->index];
308 
309                 if(++(pBufPool->index) >= pBufPool->bufNum)
310                 {
311                     pBufPool->index = 0U;
312                 }
313 
314                 return pMediaBuffer;
315             }
316             else
317             {
318                 /* pBufPool->uiIndex points to the next buffer to be checked for a get empty request.*/
319                 /* If that buffer is locked, no media buffer is returned, because random access is*/
320                 /* not allowed in ringbuffer mode.*/
321                 if(pBufPool->flags & BUFPOOL_RINGBUFFER)
322                 {
323                     return  NULL;
324                 }
325             }
326             if(++(pBufPool->index) >= pBufPool->bufNum)
327             {
328                 pBufPool->index = 0U;
329             }
330         }
331     } /* for( ;;)*/
332 }
333 
334 
335 /******************************************************************************
336  * MediaBufPoolFreeBuffer
337  *****************************************************************************/
MediaBufPoolFreeBuffer(MediaBufPool_t * pBufPool,MediaBuffer_t * pBuf)338 void MediaBufPoolFreeBuffer(MediaBufPool_t* pBufPool, MediaBuffer_t *pBuf)
339 {
340     int32_t i;
341 
342     DCT_ASSERT(pBufPool != NULL);
343     DCT_ASSERT(pBuf != NULL);
344 
345     pBuf->lockCount = 0;
346     pBufPool->freeBufNum++;
347 
348     if(pBufPool->notify.fpCallback != NULL)
349     {
350         (pBufPool->notify.fpCallback)(pBufPool->notify.pUserContext, pBuf);
351     }
352 }
353 
354