/****************************************************************************** * * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ***************************************************************************** * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore */ /** ****************************************************************************** * @file * ihevce_buffer_que.c * * @brief * This file contains all the functions related to Buffer Queue manager * * @author * ittiam * * @par List of Functions: * ihevce_buff_que_get_mem_recs * ihevce_buff_que_get_num_mem_recs * ihevce_buff_que_init * ihevce_buff_que_get_free_buf * ihevce_buff_que_get_next_buf * ihevce_buff_que_get_next_reorder_buf * ihevce_buff_que_set_buf_prod * ihevce_buff_que_rel_buf * ihevce_buff_que_get_active_bufs * ihevce_buff_que_set_reorder_buf * ****************************************************************************** */ /*****************************************************************************/ /* File Includes */ /*****************************************************************************/ /* System Include Files */ #include #include #include #include #include /* User Include Files */ #include "ihevc_typedefs.h" #include "itt_video_api.h" #include "ihevce_buffer_que_interface.h" #include "ihevce_buffer_que_private.h" /*****************************************************************************/ /* Function Definitions */ /*****************************************************************************/ /*! ************************************************************************ * \brief * return number of records used by Buffer Que manager. ************************************************************************ */ WORD32 ihevce_buff_que_get_num_mem_recs(void) { return (NUM_BUFFER_QUE_MEM_RECS); } /*! ************************************************************************ * \brief * return each record attributes of Buffer Que manager ************************************************************************ */ WORD32 ihevce_buff_que_get_mem_recs( iv_mem_rec_t *ps_mem_tab, WORD32 max_num_bufs_in_que, WORD32 i4_mem_space) { /* Que manager state structure */ ps_mem_tab[BUFFER_QUE_CTXT].i4_mem_size = sizeof(buf_que_t); ps_mem_tab[BUFFER_QUE_CTXT].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space; ps_mem_tab[BUFFER_QUE_CTXT].i4_mem_alignment = 8; /* number of users memory */ ps_mem_tab[BUFFER_QUE_NUM_USER_MEM].i4_mem_size = (sizeof(WORD32) * max_num_bufs_in_que); ps_mem_tab[BUFFER_QUE_NUM_USER_MEM].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space; ps_mem_tab[BUFFER_QUE_NUM_USER_MEM].i4_mem_alignment = 8; /* Produced status memory */ ps_mem_tab[BUFFER_QUE_PROD_STS_MEM].i4_mem_size = (sizeof(WORD32) * max_num_bufs_in_que); ps_mem_tab[BUFFER_QUE_PROD_STS_MEM].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space; ps_mem_tab[BUFFER_QUE_PROD_STS_MEM].i4_mem_alignment = 8; /* Encode sequence memory */ ps_mem_tab[BUFFER_QUE_ENC_SEQ_MEM].i4_mem_size = (sizeof(UWORD32) * max_num_bufs_in_que); ps_mem_tab[BUFFER_QUE_ENC_SEQ_MEM].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space; ps_mem_tab[BUFFER_QUE_ENC_SEQ_MEM].i4_mem_alignment = 8; /* Queued sequence memory */ ps_mem_tab[BUFFER_QUE_QUED_SEQ_MEM].i4_mem_size = (sizeof(UWORD32) * max_num_bufs_in_que); ps_mem_tab[BUFFER_QUE_QUED_SEQ_MEM].e_mem_type = (IV_MEM_TYPE_T)i4_mem_space; ps_mem_tab[BUFFER_QUE_QUED_SEQ_MEM].i4_mem_alignment = 8; return (NUM_BUFFER_QUE_MEM_RECS); } /*! ************************************************************************ * \brief * Intialization for Buffer Que manager state structure ************************************************************************ */ void *ihevce_buff_que_init(iv_mem_rec_t *ps_mem_tab, WORD32 num_bufs_in_que, void **ppv_buff_ptrs) { buf_que_t *ps_buf_que; WORD32 i; /* que manager state structure */ ps_buf_que = (buf_que_t *)ps_mem_tab[BUFFER_QUE_CTXT].pv_base; /* buffer status memory init */ ps_buf_que->pi4_num_users = (WORD32 *)ps_mem_tab[BUFFER_QUE_NUM_USER_MEM].pv_base; ps_buf_que->pi4_produced_sts = (WORD32 *)ps_mem_tab[BUFFER_QUE_PROD_STS_MEM].pv_base; ps_buf_que->pu4_enc_seq = (UWORD32 *)ps_mem_tab[BUFFER_QUE_ENC_SEQ_MEM].pv_base; ps_buf_que->pu4_que_seq = (UWORD32 *)ps_mem_tab[BUFFER_QUE_QUED_SEQ_MEM].pv_base; /* reset the state structure variables */ ps_buf_que->i4_num_bufs = num_bufs_in_que; ps_buf_que->i4_num_active_bufs = 0; ps_buf_que->u4_last_prod = 0; ps_buf_que->u4_last_cons = 0; ps_buf_que->u4_next_disp_seq = 0; ps_buf_que->u4_last_disp_seq = 0; ps_buf_que->ppv_buff_ptrs = ppv_buff_ptrs; /* init all the buffer status to default values */ for(i = 0; i < ps_buf_que->i4_num_bufs; i++) { ps_buf_que->pi4_num_users[i] = 0; ps_buf_que->pi4_produced_sts[i] = 0; ps_buf_que->pu4_enc_seq[i] = UINT32_MAX; ps_buf_que->pu4_que_seq[i] = UINT32_MAX; } return ((void *)ps_buf_que); } /*! ************************************************************************** * \brief * This function gets the next free buffer. This function is called by the * Producer to get a free buffer ************************************************************************** */ void *ihevce_buff_que_get_free_buf(void *pv_buf_que, WORD32 *pi4_id) { buf_que_t *ps_buf_que; WORD32 i; WORD32 num_bufs; ps_buf_que = (buf_que_t *)pv_buf_que; num_bufs = ps_buf_que->i4_num_bufs; /* loop unitl a free buffer is found */ for(i = 0; i < num_bufs; i++) { if((ps_buf_que->pi4_num_users[i] == 0) && (ps_buf_que->pi4_produced_sts[i] == 0)) { *(pi4_id) = i; ps_buf_que->pi4_num_users[i] = 1; ps_buf_que->pu4_que_seq[i] = ps_buf_que->u4_last_prod; ps_buf_que->u4_last_prod += 1; return (ps_buf_que->ppv_buff_ptrs[i]); } } return (NULL); } /*! ************************************************************************** * \brief * This function gets the next buffer in Que . This function will be called by * consumer to get the next buffer in Queued order. ************************************************************************** */ void *ihevce_buff_que_get_next_buf(void *pv_buf_que, WORD32 *pi4_id) { buf_que_t *ps_buf_que; WORD32 i; UWORD32 next_qued_seq; ps_buf_que = (buf_que_t *)pv_buf_que; /* get the next queued buffer to be sent */ next_qued_seq = ps_buf_que->u4_last_cons; /* check for matching index */ for(i = 0; i < ps_buf_que->i4_num_bufs; i++) { if(next_qued_seq == ps_buf_que->pu4_que_seq[i]) { if(1 == ps_buf_que->pi4_produced_sts[i]) { *(pi4_id) = i; ps_buf_que->u4_last_cons += 1; return (ps_buf_que->ppv_buff_ptrs[i]); } else { break; } } } /* Buffer not ready for Consumption */ return (NULL); } /*! ************************************************************************** * \brief * This function gives the buffer curresponding to the id passed ************************************************************************** */ void *ihevce_buff_que_get_buf(void *pv_buf_que, WORD32 i4_id) { buf_que_t *ps_buf_que; ps_buf_que = (buf_que_t *)pv_buf_que; if(i4_id >= ps_buf_que->i4_num_bufs) return (NULL); return (ps_buf_que->ppv_buff_ptrs[i4_id]); } /*! ************************************************************************** * \brief * This function gets the next buffer for in reordered order. This function * will be called by consumer to get the next buffer in reordered order ************************************************************************** */ void *ihevce_buff_que_get_next_reorder_buf(void *pv_buf_que, WORD32 *pi4_id) { buf_que_t *ps_buf_que; WORD32 i; UWORD32 next_disp_seq; ps_buf_que = (buf_que_t *)pv_buf_que; /* get the next reordered buffer to be sent */ next_disp_seq = ps_buf_que->u4_last_disp_seq; /* check for matching index */ for(i = 0; i < ps_buf_que->i4_num_bufs; i++) { if(next_disp_seq == ps_buf_que->pu4_enc_seq[i]) { *(pi4_id) = i; ps_buf_que->u4_last_disp_seq += 1; return (ps_buf_que->ppv_buff_ptrs[i]); } } /* Buffer not ready for Consumption */ return (NULL); } /*! ************************************************************************** * \brief * This function sets the buffer as produced. This function will be called * by Producer to say that buffer is ready for consumption. ************************************************************************** */ WORD32 ihevce_buff_que_set_buf_prod(void *pv_buf_que, WORD32 buf_id, WORD32 num_users) { buf_que_t *ps_buf_que; ps_buf_que = (buf_que_t *)pv_buf_que; if(buf_id < ps_buf_que->i4_num_bufs) { if(ps_buf_que->pi4_produced_sts[buf_id] == 0) { ps_buf_que->pi4_num_users[buf_id] += num_users; ps_buf_que->i4_num_active_bufs += 1; ps_buf_que->pi4_produced_sts[buf_id] = 1; return 0; } else { /* Buffer is already marked as Produced */ return (-1); } } else { /* Unable to recognize the Buffer ID */ return (-1); } return (-1); } /*! ************************************************************************** * \brief * This function decrements number of users. If Number of users are Zero, * then active Buffers in list gets decremented and this buffer is marked * unused. ************************************************************************** */ WORD32 ihevce_buff_que_rel_buf(void *pv_buf_que, WORD32 buf_id) { buf_que_t *ps_buf_que; WORD32 i; ps_buf_que = (buf_que_t *)pv_buf_que; i = buf_id; /* check if the buf id is less than max num buffers */ if(i < ps_buf_que->i4_num_bufs) { if(ps_buf_que->pi4_produced_sts[i] > 0) { /* decrease the number of users */ ps_buf_que->pi4_num_users[i] -= 1; if(ps_buf_que->pi4_num_users[i] == 0) { if(0 == ps_buf_que->i4_num_active_bufs) { return (-1); } ps_buf_que->i4_num_active_bufs -= 1; ps_buf_que->pi4_produced_sts[i] = 0; } return 0; } else { /* Illeagal release of Buffer, No one is using it */ return (-1); } } /* Unable to recognize the Buffer ID */ return (-1); } /*! ************************************************************************** * \brief * This function gets number of active buffers. ************************************************************************** */ WORD32 ihevce_buff_que_get_active_bufs(void *pv_buf_que) { buf_que_t *ps_buf_que; ps_buf_que = (buf_que_t *)pv_buf_que; return (ps_buf_que->i4_num_active_bufs); } /*! ************************************************************************** * \brief * This function sets the reorder number for given buffer. * this will set the order for the consumer who is consuming in reorder order ************************************************************************** */ WORD32 ihevce_buff_que_set_reorder_buf(void *pv_buf_que, WORD32 buf_id) { buf_que_t *ps_buf_que; ps_buf_que = (buf_que_t *)pv_buf_que; if(buf_id < ps_buf_que->i4_num_bufs) { WORD32 next_disp_seq = ps_buf_que->u4_next_disp_seq; /* increment the seq number */ ps_buf_que->u4_next_disp_seq++; /* set the reorder number to the corresponding id */ ps_buf_que->pu4_enc_seq[buf_id] = next_disp_seq; return 0; } else { /* invalid buffer id */ return (-1); } return (-1); }