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