1/******************************************************************************
2 *
3 * Copyright (C) 2015 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************
18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19*/
20/**
21*******************************************************************************
22* @file
23*  ih264_buf_mgr.c
24*
25* @brief
26*  Contains function definitions for buffer management
27*
28* @author
29*  Srinivas T
30*
31* @par List of Functions:
32*   - ih264_buf_mgr_size()
33*   - ih264_buf_mgr_lock()
34*   - ih264_buf_mgr_unlock()
35*   - ih264_buf_mgr_yield()
36*   - ih264_buf_mgr_free()
37*   - ih264_buf_mgr_init()
38*   - ih264_buf_mgr_add()
39*   - ih264_buf_mgr_get_next_free()
40*   - ih264_buf_mgr_check_free()
41*   - ih264_buf_mgr_set_status()
42*   - ih264_buf_mgr_get_status()
43*   - ih264_buf_mgr_get_buf()
44*   - ih264_buf_mgr_get_bufid()
45*   - ih264_buf_mgr_get_num_active_buf()
46*
47* @remarks
48*  None
49*
50*******************************************************************************
51*/
52#include <stdio.h>
53#include <stdlib.h>
54#include "ih264_typedefs.h"
55#include "ih264_macros.h"
56#include "ih264_defs.h"
57#include "ih264_error.h"
58#include "ih264_buf_mgr.h"
59
60#include "ithread.h"
61
62/**
63*******************************************************************************
64*
65* @brief Returns size for buf queue context. Does not include buf queue buffer
66* requirements
67*
68* @par   Description
69* Returns size for buf queue context. Does not include buf queue buffer
70* requirements. Buffer size required to store the bufs should be allocated in
71* addition to the value returned here.
72*
73* @returns Size of the buf queue context
74*
75* @remarks
76*
77*******************************************************************************
78*/
79WORD32 ih264_buf_mgr_size(void)
80{
81    WORD32 size;
82
83    size = sizeof(buf_mgr_t);
84    size += ithread_get_mutex_lock_size();
85
86    return size;
87}
88
89/**
90*******************************************************************************
91*
92* @brief
93*   Locks the buf_mgr context
94*
95* @par   Description
96*   Locks the buf_mgr context by calling ithread_mutex_lock()
97*
98* @param[in] ps_buf_mgr
99*   Job Queue context
100*
101* @returns IH264_FAIL if mutex lock fails else IH264_SUCCESS
102*
103* @remarks
104*
105*******************************************************************************
106*/
107IH264_ERROR_T ih264_buf_mgr_lock(buf_mgr_t *ps_buf_mgr)
108{
109    WORD32 retval;
110    retval = ithread_mutex_lock(ps_buf_mgr->pv_mutex);
111    if(retval)
112    {
113        return IH264_FAIL;
114    }
115    return IH264_SUCCESS;
116}
117
118/**
119*******************************************************************************
120*
121* @brief
122*   Unlocks the buf_mgr context
123*
124* @par   Description
125*   Unlocks the buf_mgr context by calling ithread_mutex_unlock()
126*
127* @param[in] ps_buf_mgr
128*   Job Queue context
129*
130* @returns IH264_FAIL if mutex unlock fails else IH264_SUCCESS
131*
132* @remarks
133*
134*******************************************************************************
135*/
136
137IH264_ERROR_T ih264_buf_mgr_unlock(buf_mgr_t *ps_buf_mgr)
138{
139    WORD32 retval;
140    retval = ithread_mutex_unlock(ps_buf_mgr->pv_mutex);
141    if(retval)
142    {
143        return IH264_FAIL;
144    }
145    return IH264_SUCCESS;
146
147}
148/**
149*******************************************************************************
150*
151* @brief
152*   Yeilds the thread
153*
154* @par   Description
155*   Unlocks the buf_mgr context by calling
156* ih264_buf_mgr_unlock(), ithread_yield() and then ih264_buf_mgr_lock()
157* buf_mgr is unlocked before to ensure the buf_mgr can be accessed by other threads
158* If unlock is not done before calling yield then no other thread can access
159* the buf_mgr functions and update buf_mgr.
160*
161* @param[in] ps_buf_mgr
162*   Job Queue context
163*
164* @returns IH264_FAIL if mutex lock unlock or yield fails else IH264_SUCCESS
165*
166* @remarks
167*
168*******************************************************************************
169*/
170IH264_ERROR_T ih264_buf_mgr_yield(buf_mgr_t *ps_buf_mgr)
171{
172
173    IH264_ERROR_T ret = IH264_SUCCESS;
174
175    IH264_ERROR_T rettmp;
176    rettmp = ih264_buf_mgr_unlock(ps_buf_mgr);
177    RETURN_IF((rettmp != IH264_SUCCESS), rettmp);
178
179    //ithread_usleep(10);
180    ithread_yield();
181
182    rettmp = ih264_buf_mgr_lock(ps_buf_mgr);
183    RETURN_IF((rettmp != IH264_SUCCESS), rettmp);
184    return ret;
185}
186
187
188/**
189*******************************************************************************
190*
191* @brief free the buf queue pointers
192*
193* @par   Description
194* Frees the buf_mgr context
195*
196* @param[in] pv_buf
197* Memoy for buf queue buffer and buf queue context
198*
199* @returns Pointer to buf queue context
200*
201* @remarks
202* Since it will be called only once by master thread this is not thread safe.
203*
204*******************************************************************************
205*/
206IH264_ERROR_T ih264_buf_mgr_free(buf_mgr_t *ps_buf_mgr)
207{
208    WORD32 ret;
209    ret = ithread_mutex_destroy(ps_buf_mgr->pv_mutex);
210
211    if(0 == ret)
212        return IH264_SUCCESS;
213    else
214        return IH264_FAIL;
215}
216/**
217*******************************************************************************
218*
219* @brief
220*      Buffer manager initialization function.
221*
222* @par Description:
223*    Initializes the buffer manager structure
224*
225* @param[in] ps_buf_mgr
226*  Pointer to the buffer manager
227*
228* @returns
229*
230* @remarks
231*  None
232*
233*******************************************************************************
234*/
235
236
237void *ih264_buf_mgr_init(void *pv_buf)
238{
239    WORD32 id;
240    UWORD8 *pu1_buf;
241    buf_mgr_t *ps_buf_mgr;
242    pu1_buf = (UWORD8 *)pv_buf;
243
244    ps_buf_mgr = (buf_mgr_t *)pu1_buf;
245    pu1_buf += sizeof(buf_mgr_t);
246
247    ps_buf_mgr->pv_mutex = pu1_buf;
248    pu1_buf += ithread_get_mutex_lock_size();
249
250    ithread_mutex_init(ps_buf_mgr->pv_mutex);
251
252    ps_buf_mgr->i4_max_buf_cnt = BUF_MGR_MAX_CNT;
253    ps_buf_mgr->i4_active_buf_cnt = 0;
254
255    for(id = 0; id < BUF_MGR_MAX_CNT; id++)
256    {
257        ps_buf_mgr->au4_status[id] = 0;
258        ps_buf_mgr->apv_ptr[id] = NULL;
259    }
260
261    return ps_buf_mgr;
262}
263
264
265/**
266*******************************************************************************
267*
268* @brief
269*       Adds and increments the buffer and buffer count.
270*
271* @par Description:
272*     Adds a buffer to the buffer manager if it is not already  present and
273*   increments the  active buffer count
274*
275* @param[in] ps_buf_mgr
276*  Pointer to the buffer manager
277*
278* @param[in] pv_ptr
279*  Pointer to the buffer to be added
280*
281* @returns  Returns 0 on success, -1 otherwise
282*
283* @remarks
284*  None
285*
286*******************************************************************************
287*/
288IH264_ERROR_T ih264_buf_mgr_add(buf_mgr_t *ps_buf_mgr,
289                                void *pv_ptr,
290                                WORD32 buf_id)
291{
292
293    IH264_ERROR_T ret = IH264_SUCCESS;
294    ret = ih264_buf_mgr_lock(ps_buf_mgr);
295    RETURN_IF((ret != IH264_SUCCESS), ret);
296
297    /* Check if buffer ID is within allowed range */
298    if(buf_id >= ps_buf_mgr->i4_max_buf_cnt)
299    {
300        ret = ih264_buf_mgr_unlock(ps_buf_mgr);
301        RETURN_IF((ret != IH264_SUCCESS), ret);
302
303        return IH264_FAIL;
304    }
305
306    /* Check if the current ID is being used to hold some other buffer */
307    if((ps_buf_mgr->apv_ptr[buf_id] != NULL) &&
308       (ps_buf_mgr->apv_ptr[buf_id] !=pv_ptr))
309    {
310        ret = ih264_buf_mgr_unlock(ps_buf_mgr);
311        RETURN_IF((ret != IH264_SUCCESS), ret);
312
313        return IH264_FAIL;
314    }
315    ps_buf_mgr->apv_ptr[buf_id] = pv_ptr;
316    ps_buf_mgr->i4_active_buf_cnt++;
317
318    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
319    RETURN_IF((ret != IH264_SUCCESS), ret);
320
321    return ret;
322}
323
324/**
325*******************************************************************************
326*
327* @brief
328*   Gets the next free buffer.
329*
330* @par Description:
331*     Returns the next free buffer available and sets the  corresponding status
332*   to DEC
333*
334* @param[in] ps_buf_mgr
335*  Pointer to the buffer manager
336*
337* @param[in] pi4_buf_id
338*  Pointer to the id of the free buffer
339*
340* @returns  Pointer to the free buffer
341*
342* @remarks
343*  None
344*
345*******************************************************************************
346*/
347void* ih264_buf_mgr_get_next_free(buf_mgr_t *ps_buf_mgr, WORD32 *pi4_buf_id)
348{
349    WORD32 id;
350    void *pv_ret_ptr;
351    IH264_ERROR_T ret = IH264_SUCCESS;
352    ret = ih264_buf_mgr_lock(ps_buf_mgr);
353    RETURN_IF((ret != IH264_SUCCESS), NULL);
354
355    pv_ret_ptr = NULL;
356    for(id = 0; id < ps_buf_mgr->i4_active_buf_cnt; id++)
357    {
358        /* Check if the buffer is non-null and status is zero */
359        if((ps_buf_mgr->au4_status[id] == 0) && (ps_buf_mgr->apv_ptr[id]))
360        {
361            *pi4_buf_id = id;
362            /* DEC is set to 1 */
363            ps_buf_mgr->au4_status[id] = 1;
364            pv_ret_ptr = ps_buf_mgr->apv_ptr[id];
365            break;
366        }
367    }
368    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
369    RETURN_IF((ret != IH264_SUCCESS), NULL);
370
371    return pv_ret_ptr;
372}
373
374
375/**
376*******************************************************************************
377*
378* @brief
379*      Checks the buffer manager for free buffers available.
380*
381* @par Description:
382*  Checks if there are any free buffers available
383*
384* @param[in] ps_buf_mgr
385*  Pointer to the buffer manager
386*
387* @returns  Returns 0 if available, -1 otherwise
388*
389* @remarks
390*  None
391*
392*******************************************************************************
393*/
394IH264_ERROR_T ih264_buf_mgr_check_free(buf_mgr_t *ps_buf_mgr)
395{
396    WORD32 id;
397    IH264_ERROR_T ret = IH264_SUCCESS;
398    IH264_ERROR_T rettmp = IH264_SUCCESS;
399    rettmp = ih264_buf_mgr_lock(ps_buf_mgr);
400    RETURN_IF((rettmp != IH264_SUCCESS), ret);
401
402    ret = IH264_FAIL;
403    for(id = 0; id < ps_buf_mgr->i4_active_buf_cnt; id++)
404    {
405        if((ps_buf_mgr->au4_status[id] == 0) &&
406           (ps_buf_mgr->apv_ptr[id]))
407        {
408            ret = IH264_SUCCESS;
409            break;
410        }
411    }
412    rettmp = ih264_buf_mgr_unlock(ps_buf_mgr);
413    RETURN_IF((rettmp != IH264_SUCCESS), ret);
414
415    return ret;
416
417}
418
419
420/**
421*******************************************************************************
422*
423* @brief
424*       Resets the status bits.
425*
426* @par Description:
427*     resets the status bits that the mask contains (status  corresponding to
428*    the id)
429*
430* @param[in] ps_buf_mgr
431*  Pointer to the buffer manager
432*
433* @param[in] buf_id
434*  ID of the buffer status to be released
435*
436* @param[in] mask
437*  Contains the bits that are to be reset
438*
439* @returns  0 if success, -1 otherwise
440*
441* @remarks
442*  None
443*
444*******************************************************************************
445*/
446IH264_ERROR_T ih264_buf_mgr_release(buf_mgr_t *ps_buf_mgr,
447                                    WORD32 buf_id,
448                                    UWORD32 mask)
449{
450    IH264_ERROR_T ret = IH264_SUCCESS;
451    ret = ih264_buf_mgr_lock(ps_buf_mgr);
452    RETURN_IF((ret != IH264_SUCCESS), ret);
453
454
455    /* If the given id is pointing to an id which is not yet added */
456    if(buf_id >= ps_buf_mgr->i4_active_buf_cnt)
457    {
458        ret = ih264_buf_mgr_unlock(ps_buf_mgr);
459        RETURN_IF((ret != IH264_SUCCESS), ret);
460        return IH264_FAIL;
461    }
462
463    ps_buf_mgr->au4_status[buf_id] &= ~mask;
464
465
466/*     If both the REF and DISP are zero, DEC is set to zero */
467    if(ps_buf_mgr->au4_status[buf_id] == 1)
468    {
469        ps_buf_mgr->au4_status[buf_id] = 0;
470    }
471
472
473    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
474    RETURN_IF((ret != IH264_SUCCESS), ret);
475
476    return ret;
477}
478
479
480/**
481*******************************************************************************
482*
483* @brief
484*      Sets the status bit.
485*
486* @par Description:
487*     sets the status bits that the mask contains (status  corresponding to the
488*    id)
489*
490*
491* @param[in] ps_buf_mgr
492*  Pointer to the buffer manager
493*
494* @param[in] buf_id
495*  ID of the buffer whose status needs to be modified
496*
497*
498* @param[in] mask
499*  Contains the bits that are to be set
500*
501* @returns  0 if success, -1 otherwise
502*
503* @remarks
504*  None
505*
506*******************************************************************************
507*/
508IH264_ERROR_T ih264_buf_mgr_set_status(buf_mgr_t *ps_buf_mgr,
509                                       WORD32 buf_id,
510                                       UWORD32 mask)
511{
512    IH264_ERROR_T ret = IH264_SUCCESS;
513    ret = ih264_buf_mgr_lock(ps_buf_mgr);
514    RETURN_IF((ret != IH264_SUCCESS), ret);
515
516    if(buf_id >= ps_buf_mgr->i4_active_buf_cnt)
517    {
518        ret = ih264_buf_mgr_unlock(ps_buf_mgr);
519        RETURN_IF((ret != IH264_SUCCESS), ret);
520        return IH264_FAIL;
521    }
522
523
524    if((ps_buf_mgr->au4_status[buf_id] & mask) != 0)
525    {
526        ret = ih264_buf_mgr_unlock(ps_buf_mgr);
527        RETURN_IF((ret != IH264_SUCCESS), ret);
528        return IH264_FAIL;
529    }
530
531    ps_buf_mgr->au4_status[buf_id] |= mask;
532    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
533    RETURN_IF((ret != IH264_SUCCESS), ret);
534
535    return ret;
536}
537
538
539/**
540*******************************************************************************
541*
542* @brief
543*   Returns the status of the buffer.
544*
545* @par Description:
546*  Returns the status of the buffer corresponding to the id
547*
548* @param[in] ps_buf_mgr
549*  Pointer to the buffer manager
550*
551* @param[in] buf_id
552*  ID of the buffer status required
553*
554* @returns  Status of the buffer corresponding to the id
555*
556* @remarks
557*  None
558*
559*******************************************************************************
560*/
561WORD32 ih264_buf_mgr_get_status( buf_mgr_t *ps_buf_mgr, WORD32 buf_id )
562{
563    IH264_ERROR_T ret = IH264_SUCCESS;
564    UWORD32 status;
565
566    ret = ih264_buf_mgr_lock(ps_buf_mgr);
567    RETURN_IF((ret != IH264_SUCCESS), ret);
568
569    status = ps_buf_mgr->au4_status[buf_id];
570
571    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
572    RETURN_IF((ret != IH264_SUCCESS), ret);
573
574    return status;
575}
576
577
578/**
579*******************************************************************************
580*
581* @brief
582*      Gets the buffer from the buffer manager
583*
584* @par Description:
585*        Returns the pointer to the buffer corresponding to the id
586*
587* @param[in] ps_buf_mgr
588*  Pointer to the buffer manager
589*
590* @param[in] buf_id
591*  ID of the buffer required
592*
593* @returns  Pointer to the buffer required
594*
595* @remarks
596*  None
597*
598*******************************************************************************
599*/
600void* ih264_buf_mgr_get_buf(buf_mgr_t *ps_buf_mgr, WORD32 buf_id)
601{
602    IH264_ERROR_T ret = IH264_SUCCESS;
603    void *pv_buf;
604    ret = ih264_buf_mgr_lock(ps_buf_mgr);
605    RETURN_IF((ret != IH264_SUCCESS), NULL);
606
607    pv_buf = ps_buf_mgr->apv_ptr[buf_id];
608
609    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
610    RETURN_IF((ret != IH264_SUCCESS), NULL);
611
612    return pv_buf;
613}
614
615
616/**
617*******************************************************************************
618*
619* @brief
620*  Gets the buffer id from the buffer manager if the buffer is added to the
621*  buffer manager
622*
623* @par Description:
624*  Returns the buffer id corresponding to the given buffer if it exists
625*
626* @param[in] ps_buf_mgr
627*  Pointer to the buffer manager
628*
629* @param[in] pv_buf
630*  Pointer to the buffer
631*
632* @returns  Buffer id if exists, else -1
633*
634* @remarks
635*  None
636*
637*******************************************************************************
638*/
639WORD32 ih264_buf_mgr_get_bufid(buf_mgr_t *ps_buf_mgr, void *pv_buf)
640{
641    WORD32 id;
642    WORD32 buf_id = -1;
643    IH264_ERROR_T ret = IH264_SUCCESS;
644    ret = ih264_buf_mgr_lock(ps_buf_mgr);
645    RETURN_IF((ret != IH264_SUCCESS), ret);
646
647    for(id = 0; id < ps_buf_mgr->i4_active_buf_cnt; id++)
648    {
649        if(ps_buf_mgr->apv_ptr[id] == pv_buf)
650        {
651            buf_id = id;
652            break;
653        }
654    }
655    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
656    RETURN_IF((ret != IH264_SUCCESS), ret);
657
658    return buf_id;
659}
660
661
662/**
663*******************************************************************************
664*
665* @brief
666*        Gets the no.of active buffer
667*
668* @par Description:
669*      Return the number of active buffers in the buffer manager
670*
671* @param[in] ps_buf_mgr
672*  Pointer to the buffer manager
673*
674* @returns  number of active buffers
675*
676* @remarks
677*  None
678*
679*******************************************************************************
680*/
681UWORD32 ih264_buf_mgr_get_num_active_buf(buf_mgr_t *ps_buf_mgr)
682{
683    UWORD32 u4_buf_cnt;
684    IH264_ERROR_T ret = IH264_SUCCESS;
685
686    u4_buf_cnt = 0;
687
688    ret = ih264_buf_mgr_lock(ps_buf_mgr);
689    RETURN_IF((ret != IH264_SUCCESS), ret);
690    u4_buf_cnt = ps_buf_mgr->i4_active_buf_cnt;
691
692    ret = ih264_buf_mgr_unlock(ps_buf_mgr);
693    RETURN_IF((ret != IH264_SUCCESS), ret);
694
695    return u4_buf_cnt;
696}
697