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