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 */
ih264_buf_mgr_size(void)79 WORD32 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 */
ih264_buf_mgr_lock(buf_mgr_t * ps_buf_mgr)107 IH264_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 
ih264_buf_mgr_unlock(buf_mgr_t * ps_buf_mgr)137 IH264_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 */
ih264_buf_mgr_yield(buf_mgr_t * ps_buf_mgr)170 IH264_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 */
ih264_buf_mgr_free(buf_mgr_t * ps_buf_mgr)206 IH264_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 
ih264_buf_mgr_init(void * pv_buf)237 void *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 * @brief
268 *      Buffer manager reset function.
269 *
270 * @par Description:
271 *    resets the buffer manager structure
272 *
273 * @param[in] ps_buf_mgr
274 *  Pointer to the buffer manager
275 *
276 * @returns
277 *
278 * @remarks
279 *  None
280 *
281 *******************************************************************************
282 */
ih264_buf_mgr_reset(void * pv_buf_mgr)283 void ih264_buf_mgr_reset(void *pv_buf_mgr)
284 {
285     WORD32 id;
286     buf_mgr_t *ps_buf_mgr;
287 
288     ps_buf_mgr = (buf_mgr_t *) pv_buf_mgr;
289 
290     for(id = 0; id < BUF_MGR_MAX_CNT; id++)
291     {
292         ps_buf_mgr->au4_status[id] = 0;
293     }
294 
295     return;
296 }
297 
298 /**
299 *******************************************************************************
300 *
301 * @brief
302 *       Adds and increments the buffer and buffer count.
303 *
304 * @par Description:
305 *     Adds a buffer to the buffer manager if it is not already  present and
306 *   increments the  active buffer count
307 *
308 * @param[in] ps_buf_mgr
309 *  Pointer to the buffer manager
310 *
311 * @param[in] pv_ptr
312 *  Pointer to the buffer to be added
313 *
314 * @returns  Returns 0 on success, -1 otherwise
315 *
316 * @remarks
317 *  None
318 *
319 *******************************************************************************
320 */
ih264_buf_mgr_add(buf_mgr_t * ps_buf_mgr,void * pv_ptr,WORD32 buf_id)321 IH264_ERROR_T ih264_buf_mgr_add(buf_mgr_t *ps_buf_mgr,
322                                 void *pv_ptr,
323                                 WORD32 buf_id)
324 {
325 
326     IH264_ERROR_T ret = IH264_SUCCESS;
327     ret = ih264_buf_mgr_lock(ps_buf_mgr);
328     RETURN_IF((ret != IH264_SUCCESS), ret);
329 
330     /* Check if buffer ID is within allowed range */
331     if(buf_id >= ps_buf_mgr->i4_max_buf_cnt)
332     {
333         ret = ih264_buf_mgr_unlock(ps_buf_mgr);
334         RETURN_IF((ret != IH264_SUCCESS), ret);
335 
336         return IH264_FAIL;
337     }
338 
339     /* Check if the current ID is being used to hold some other buffer */
340     if((ps_buf_mgr->apv_ptr[buf_id] != NULL) &&
341        (ps_buf_mgr->apv_ptr[buf_id] !=pv_ptr))
342     {
343         ret = ih264_buf_mgr_unlock(ps_buf_mgr);
344         RETURN_IF((ret != IH264_SUCCESS), ret);
345 
346         return IH264_FAIL;
347     }
348     ps_buf_mgr->apv_ptr[buf_id] = pv_ptr;
349     ps_buf_mgr->i4_active_buf_cnt++;
350 
351     ret = ih264_buf_mgr_unlock(ps_buf_mgr);
352     RETURN_IF((ret != IH264_SUCCESS), ret);
353 
354     return ret;
355 }
356 
357 /**
358 *******************************************************************************
359 *
360 * @brief
361 *   Gets the next free buffer.
362 *
363 * @par Description:
364 *     Returns the next free buffer available and sets the  corresponding status
365 *   to DEC
366 *
367 * @param[in] ps_buf_mgr
368 *  Pointer to the buffer manager
369 *
370 * @param[in] pi4_buf_id
371 *  Pointer to the id of the free buffer
372 *
373 * @returns  Pointer to the free buffer
374 *
375 * @remarks
376 *  None
377 *
378 *******************************************************************************
379 */
ih264_buf_mgr_get_next_free(buf_mgr_t * ps_buf_mgr,WORD32 * pi4_buf_id)380 void* ih264_buf_mgr_get_next_free(buf_mgr_t *ps_buf_mgr, WORD32 *pi4_buf_id)
381 {
382     WORD32 id;
383     void *pv_ret_ptr;
384     IH264_ERROR_T ret = IH264_SUCCESS;
385     ret = ih264_buf_mgr_lock(ps_buf_mgr);
386     RETURN_IF((ret != IH264_SUCCESS), NULL);
387 
388     pv_ret_ptr = NULL;
389     for(id = 0; id < ps_buf_mgr->i4_active_buf_cnt; id++)
390     {
391         /* Check if the buffer is non-null and status is zero */
392         if((ps_buf_mgr->au4_status[id] == 0) && (ps_buf_mgr->apv_ptr[id]))
393         {
394             *pi4_buf_id = id;
395             /* DEC is set to 1 */
396             ps_buf_mgr->au4_status[id] = 1;
397             pv_ret_ptr = ps_buf_mgr->apv_ptr[id];
398             break;
399         }
400     }
401     ret = ih264_buf_mgr_unlock(ps_buf_mgr);
402     RETURN_IF((ret != IH264_SUCCESS), NULL);
403 
404     return pv_ret_ptr;
405 }
406 
407 
408 /**
409 *******************************************************************************
410 *
411 * @brief
412 *      Checks the buffer manager for free buffers available.
413 *
414 * @par Description:
415 *  Checks if there are any free buffers available
416 *
417 * @param[in] ps_buf_mgr
418 *  Pointer to the buffer manager
419 *
420 * @returns  Returns 0 if available, -1 otherwise
421 *
422 * @remarks
423 *  None
424 *
425 *******************************************************************************
426 */
ih264_buf_mgr_check_free(buf_mgr_t * ps_buf_mgr)427 IH264_ERROR_T ih264_buf_mgr_check_free(buf_mgr_t *ps_buf_mgr)
428 {
429     WORD32 id;
430     IH264_ERROR_T ret = IH264_SUCCESS;
431     IH264_ERROR_T rettmp = IH264_SUCCESS;
432     rettmp = ih264_buf_mgr_lock(ps_buf_mgr);
433     RETURN_IF((rettmp != IH264_SUCCESS), ret);
434 
435     ret = IH264_FAIL;
436     for(id = 0; id < ps_buf_mgr->i4_active_buf_cnt; id++)
437     {
438         if((ps_buf_mgr->au4_status[id] == 0) &&
439            (ps_buf_mgr->apv_ptr[id]))
440         {
441             ret = IH264_SUCCESS;
442             break;
443         }
444     }
445     rettmp = ih264_buf_mgr_unlock(ps_buf_mgr);
446     RETURN_IF((rettmp != IH264_SUCCESS), ret);
447 
448     return ret;
449 
450 }
451 
452 
453 /**
454 *******************************************************************************
455 *
456 * @brief
457 *       Resets the status bits.
458 *
459 * @par Description:
460 *     resets the status bits that the mask contains (status  corresponding to
461 *    the id)
462 *
463 * @param[in] ps_buf_mgr
464 *  Pointer to the buffer manager
465 *
466 * @param[in] buf_id
467 *  ID of the buffer status to be released
468 *
469 * @param[in] mask
470 *  Contains the bits that are to be reset
471 *
472 * @returns  0 if success, -1 otherwise
473 *
474 * @remarks
475 *  None
476 *
477 *******************************************************************************
478 */
ih264_buf_mgr_release(buf_mgr_t * ps_buf_mgr,WORD32 buf_id,UWORD32 mask)479 IH264_ERROR_T ih264_buf_mgr_release(buf_mgr_t *ps_buf_mgr,
480                                     WORD32 buf_id,
481                                     UWORD32 mask)
482 {
483     IH264_ERROR_T ret = IH264_SUCCESS;
484     ret = ih264_buf_mgr_lock(ps_buf_mgr);
485     RETURN_IF((ret != IH264_SUCCESS), ret);
486 
487 
488     /* If the given id is pointing to an id which is not yet added */
489     if(buf_id >= ps_buf_mgr->i4_active_buf_cnt)
490     {
491         ret = ih264_buf_mgr_unlock(ps_buf_mgr);
492         RETURN_IF((ret != IH264_SUCCESS), ret);
493         return IH264_FAIL;
494     }
495 
496     ps_buf_mgr->au4_status[buf_id] &= ~mask;
497 
498 
499 /*     If both the REF and DISP are zero, DEC is set to zero */
500     if(ps_buf_mgr->au4_status[buf_id] == 1)
501     {
502         ps_buf_mgr->au4_status[buf_id] = 0;
503     }
504 
505 
506     ret = ih264_buf_mgr_unlock(ps_buf_mgr);
507     RETURN_IF((ret != IH264_SUCCESS), ret);
508 
509     return ret;
510 }
511 
512 
513 /**
514 *******************************************************************************
515 *
516 * @brief
517 *      Sets the status bit.
518 *
519 * @par Description:
520 *     sets the status bits that the mask contains (status  corresponding to the
521 *    id)
522 *
523 *
524 * @param[in] ps_buf_mgr
525 *  Pointer to the buffer manager
526 *
527 * @param[in] buf_id
528 *  ID of the buffer whose status needs to be modified
529 *
530 *
531 * @param[in] mask
532 *  Contains the bits that are to be set
533 *
534 * @returns  0 if success, -1 otherwise
535 *
536 * @remarks
537 *  None
538 *
539 *******************************************************************************
540 */
ih264_buf_mgr_set_status(buf_mgr_t * ps_buf_mgr,WORD32 buf_id,UWORD32 mask)541 IH264_ERROR_T ih264_buf_mgr_set_status(buf_mgr_t *ps_buf_mgr,
542                                        WORD32 buf_id,
543                                        UWORD32 mask)
544 {
545     IH264_ERROR_T ret = IH264_SUCCESS;
546     ret = ih264_buf_mgr_lock(ps_buf_mgr);
547     RETURN_IF((ret != IH264_SUCCESS), ret);
548 
549     if(buf_id >= ps_buf_mgr->i4_active_buf_cnt)
550     {
551         ret = ih264_buf_mgr_unlock(ps_buf_mgr);
552         RETURN_IF((ret != IH264_SUCCESS), ret);
553         return IH264_FAIL;
554     }
555 
556 
557     if((ps_buf_mgr->au4_status[buf_id] & mask) != 0)
558     {
559         ret = ih264_buf_mgr_unlock(ps_buf_mgr);
560         RETURN_IF((ret != IH264_SUCCESS), ret);
561         return IH264_FAIL;
562     }
563 
564     ps_buf_mgr->au4_status[buf_id] |= mask;
565     ret = ih264_buf_mgr_unlock(ps_buf_mgr);
566     RETURN_IF((ret != IH264_SUCCESS), ret);
567 
568     return ret;
569 }
570 
571 
572 /**
573 *******************************************************************************
574 *
575 * @brief
576 *   Returns the status of the buffer.
577 *
578 * @par Description:
579 *  Returns the status of the buffer corresponding to the id
580 *
581 * @param[in] ps_buf_mgr
582 *  Pointer to the buffer manager
583 *
584 * @param[in] buf_id
585 *  ID of the buffer status required
586 *
587 * @returns  Status of the buffer corresponding to the id
588 *
589 * @remarks
590 *  None
591 *
592 *******************************************************************************
593 */
ih264_buf_mgr_get_status(buf_mgr_t * ps_buf_mgr,WORD32 buf_id)594 WORD32 ih264_buf_mgr_get_status( buf_mgr_t *ps_buf_mgr, WORD32 buf_id )
595 {
596     IH264_ERROR_T ret = IH264_SUCCESS;
597     UWORD32 status;
598 
599     ret = ih264_buf_mgr_lock(ps_buf_mgr);
600     RETURN_IF((ret != IH264_SUCCESS), ret);
601 
602     status = ps_buf_mgr->au4_status[buf_id];
603 
604     ret = ih264_buf_mgr_unlock(ps_buf_mgr);
605     RETURN_IF((ret != IH264_SUCCESS), ret);
606 
607     return status;
608 }
609 
610 
611 /**
612 *******************************************************************************
613 *
614 * @brief
615 *      Gets the buffer from the buffer manager
616 *
617 * @par Description:
618 *        Returns the pointer to the buffer corresponding to the id
619 *
620 * @param[in] ps_buf_mgr
621 *  Pointer to the buffer manager
622 *
623 * @param[in] buf_id
624 *  ID of the buffer required
625 *
626 * @returns  Pointer to the buffer required
627 *
628 * @remarks
629 *  None
630 *
631 *******************************************************************************
632 */
ih264_buf_mgr_get_buf(buf_mgr_t * ps_buf_mgr,WORD32 buf_id)633 void* ih264_buf_mgr_get_buf(buf_mgr_t *ps_buf_mgr, WORD32 buf_id)
634 {
635     IH264_ERROR_T ret = IH264_SUCCESS;
636     void *pv_buf;
637     ret = ih264_buf_mgr_lock(ps_buf_mgr);
638     RETURN_IF((ret != IH264_SUCCESS), NULL);
639 
640     pv_buf = ps_buf_mgr->apv_ptr[buf_id];
641 
642     ret = ih264_buf_mgr_unlock(ps_buf_mgr);
643     RETURN_IF((ret != IH264_SUCCESS), NULL);
644 
645     return pv_buf;
646 }
647 
648 
649 /**
650 *******************************************************************************
651 *
652 * @brief
653 *  Gets the buffer id from the buffer manager if the buffer is added to the
654 *  buffer manager
655 *
656 * @par Description:
657 *  Returns the buffer id corresponding to the given buffer if it exists
658 *
659 * @param[in] ps_buf_mgr
660 *  Pointer to the buffer manager
661 *
662 * @param[in] pv_buf
663 *  Pointer to the buffer
664 *
665 * @returns  Buffer id if exists, else -1
666 *
667 * @remarks
668 *  None
669 *
670 *******************************************************************************
671 */
ih264_buf_mgr_get_bufid(buf_mgr_t * ps_buf_mgr,void * pv_buf)672 WORD32 ih264_buf_mgr_get_bufid(buf_mgr_t *ps_buf_mgr, void *pv_buf)
673 {
674     WORD32 id;
675     WORD32 buf_id = -1;
676     IH264_ERROR_T ret = IH264_SUCCESS;
677     ret = ih264_buf_mgr_lock(ps_buf_mgr);
678     RETURN_IF((ret != IH264_SUCCESS), ret);
679 
680     for(id = 0; id < ps_buf_mgr->i4_active_buf_cnt; id++)
681     {
682         if(ps_buf_mgr->apv_ptr[id] == pv_buf)
683         {
684             buf_id = id;
685             break;
686         }
687     }
688     ret = ih264_buf_mgr_unlock(ps_buf_mgr);
689     RETURN_IF((ret != IH264_SUCCESS), ret);
690 
691     return buf_id;
692 }
693 
694 
695 /**
696 *******************************************************************************
697 *
698 * @brief
699 *        Gets the no.of active buffer
700 *
701 * @par Description:
702 *      Return the number of active buffers in the buffer manager
703 *
704 * @param[in] ps_buf_mgr
705 *  Pointer to the buffer manager
706 *
707 * @returns  number of active buffers
708 *
709 * @remarks
710 *  None
711 *
712 *******************************************************************************
713 */
ih264_buf_mgr_get_num_active_buf(buf_mgr_t * ps_buf_mgr)714 UWORD32 ih264_buf_mgr_get_num_active_buf(buf_mgr_t *ps_buf_mgr)
715 {
716     UWORD32 u4_buf_cnt;
717     IH264_ERROR_T ret = IH264_SUCCESS;
718 
719     u4_buf_cnt = 0;
720 
721     ret = ih264_buf_mgr_lock(ps_buf_mgr);
722     RETURN_IF((ret != IH264_SUCCESS), ret);
723     u4_buf_cnt = ps_buf_mgr->i4_active_buf_cnt;
724 
725     ret = ih264_buf_mgr_unlock(ps_buf_mgr);
726     RETURN_IF((ret != IH264_SUCCESS), ret);
727 
728     return u4_buf_cnt;
729 }
730