summaryrefslogtreecommitdiffstats
path: root/common/ihevc_dpb_mgr.c
diff options
context:
space:
mode:
Diffstat (limited to 'common/ihevc_dpb_mgr.c')
-rw-r--r--common/ihevc_dpb_mgr.c506
1 files changed, 506 insertions, 0 deletions
diff --git a/common/ihevc_dpb_mgr.c b/common/ihevc_dpb_mgr.c
new file mode 100644
index 0000000..7a2e032
--- /dev/null
+++ b/common/ihevc_dpb_mgr.c
@@ -0,0 +1,506 @@
+/******************************************************************************
+*
+* Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore
+*
+* 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.
+*
+******************************************************************************/
+/**
+ *******************************************************************************
+ * @file
+ * ihevc_dpb_mgr.c
+ *
+ * @brief
+ * Function definitions used for decoded picture buffer management
+ *
+ * @author
+ * Srinivas T
+ *
+ * @par List of Functions:
+ * - ihevc_dpb_mgr_init()
+ * - ihevc_dpb_mgr_del_lt()
+ * - ihevc_dpb_mgr_insert_lt()
+ * - ihevc_dpb_mgr_del_st_or_make_lt()
+ * - ihevc_dpb_mgr_insert_st()
+ * - ihevc_dpb_mgr_reset()
+ * - ihevc_dpb_mgr_release_pics()
+ *
+ * @remarks
+ * None
+ *
+ *******************************************************************************
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "ihevc_typedefs.h"
+#include "ihevc_defs.h"
+#include "ihevc_macros.h"
+#include "ihevc_func_selector.h"
+#include "ihevc_structs.h"
+#include "ihevc_buf_mgr.h"
+#include "ihevc_dpb_mgr.h"
+
+/**
+ *******************************************************************************
+ *
+ * @brief
+ * DPB manager initializer
+ *
+ * @par Description:
+ * Initialises the DPB manager structure
+ *
+ * @param[in] ps_dpb_mgr
+ * Pointer to the DPB manager structure
+ *
+ * @returns
+ *
+ * @remarks
+ *
+ *
+ *******************************************************************************
+ */
+
+void ihevc_dpb_mgr_init(dpb_mgr_t *ps_dpb_mgr)
+{
+ UWORD32 i;
+ dpb_info_t *ps_dpb_info = ps_dpb_mgr->as_dpb_info;
+ for(i = 0; i < MAX_DPB_BUFS; i++)
+ {
+ ps_dpb_info[i].ps_prev_dpb = NULL;
+ ps_dpb_info[i].ps_pic_buf = NULL;
+
+ }
+
+ ps_dpb_mgr->u1_num_ref_bufs = 0;
+ ps_dpb_mgr->ps_dpb_head = NULL;
+
+}
+
+
+/**
+ *******************************************************************************
+ *
+ * @brief
+ * Adds a reference picture into the linked list
+ *
+ * @par Description:
+ * Adds the reference buffer with the given buffer id into the DPB manager
+ *
+ *
+ * @param[in] ps_dpb_mgr
+ * Pointer to the DPB manager structure
+ *
+ * @param[in] ps_picBuf
+ * Pointer to the picture buffer
+ *
+ * @param[in] buf_id
+ * buffer id of the picture buffer
+ *
+ * @returns 0 if successful, -1 otherwise
+ *
+ * @remarks
+ *
+ *
+ *******************************************************************************
+ */
+
+WORD32 ihevc_dpb_mgr_insert_ref(dpb_mgr_t *ps_dpb_mgr,
+ pic_buf_t *ps_pic_buf,
+ WORD32 buf_id)
+{
+ int i;
+ dpb_info_t *ps_dpb_info;
+
+ ps_dpb_info = ps_dpb_mgr->as_dpb_info;
+
+ /* Return error if buffer is already present in the DPB */
+ for(i = 0; i < MAX_DPB_BUFS; i++)
+ {
+ if((ps_dpb_info[i].ps_pic_buf == ps_pic_buf)
+ && (ps_dpb_info[i].ps_pic_buf->u1_used_as_ref))
+ {
+ return (-1);
+ }
+
+
+ }
+
+ /* Find an unused DPB location */
+ for(i = 0; i < MAX_DPB_BUFS; i++)
+ {
+ if(NULL == ps_dpb_info[i].ps_pic_buf)
+ {
+ break;
+ }
+ }
+ if(i == MAX_DPB_BUFS)
+ {
+ return (-1);
+ }
+
+ /* Create DPB info */
+ ps_dpb_info[i].ps_pic_buf = ps_pic_buf;
+ ps_dpb_info[i].ps_prev_dpb = ps_dpb_mgr->ps_dpb_head;
+ ps_dpb_info[i].ps_pic_buf->u1_buf_id = buf_id;
+ ps_dpb_info[i].ps_pic_buf->u1_used_as_ref = SHORT_TERM_REF;
+
+ /* update the head node of linked list to point to the current picture */
+ ps_dpb_mgr->ps_dpb_head = ps_dpb_info + i;
+
+ /* Increment Short term buffer count */
+ ps_dpb_mgr->u1_num_ref_bufs++;
+
+ return 0;
+}
+
+/**
+ *******************************************************************************
+ *
+ * @brief
+ * Deletes a reference buffer from the dpb manager
+ *
+ * @par Description:
+ * Delete short term reference with a given POC from the linked
+ * list
+ *
+ * @param[in] ps_dpb_mgr
+ * Pointer to DPB Manager structure
+ *
+ * @param[in] ps_buf_mgr
+ * Pointer to buffer manager structure
+ *
+ * @param[in] u4_abs_poc
+ * Node's absolute poc
+ *
+ *
+ * @returns 0 if successful, -1 otherwise
+ *
+ * @remarks
+ *
+ *
+ *******************************************************************************
+ */
+
+void ihevc_dpb_mgr_del_ref(dpb_mgr_t *ps_dpb_mgr,
+ buf_mgr_t *ps_buf_mgr,
+ WORD32 i4_abs_poc)
+{
+ int i;
+ dpb_info_t *ps_next_dpb;
+
+ dpb_info_t *ps_unmark_node;
+ UWORD8 u1_del_node;
+ UNUSED(u1_del_node);
+ u1_del_node = 0;
+
+ /* Find the node with matching absolute POC */
+ ps_next_dpb = ps_dpb_mgr->ps_dpb_head;
+ if(ps_next_dpb->ps_pic_buf->i4_abs_poc == i4_abs_poc)
+ {
+ ps_unmark_node = ps_next_dpb;
+ }
+ else
+ {
+ for(i = 1; i < ps_dpb_mgr->u1_num_ref_bufs; i++)
+ {
+ if(ps_next_dpb->ps_prev_dpb->ps_pic_buf->i4_abs_poc == i4_abs_poc)
+ break;
+ ps_next_dpb = ps_next_dpb->ps_prev_dpb;
+ }
+
+ if(i == ps_dpb_mgr->u1_num_ref_bufs)
+ {
+ return;
+ }
+ else
+ ps_unmark_node = ps_next_dpb->ps_prev_dpb;
+ }
+
+ if(ps_unmark_node == ps_dpb_mgr->ps_dpb_head)
+ {
+ ps_dpb_mgr->ps_dpb_head = ps_unmark_node->ps_prev_dpb;
+ }
+ else
+ {
+ ps_next_dpb->ps_prev_dpb = ps_unmark_node->ps_prev_dpb; //update link
+ ps_unmark_node->ps_prev_dpb = NULL;
+ }
+ ps_dpb_mgr->u1_num_ref_bufs--; //decrement buffer count
+
+ /* Release the physical buffer */
+ ihevc_buf_mgr_release((buf_mgr_t *)ps_buf_mgr, ps_unmark_node->ps_pic_buf->u1_buf_id,
+ BUF_MGR_REF);
+ ps_unmark_node->ps_prev_dpb = NULL;
+ ps_unmark_node->ps_pic_buf = NULL;
+}
+
+
+/**
+ *******************************************************************************
+ *
+ * @brief
+ * Gets a buffer with abs_poc closest to the current poc
+ *
+ * @par Description:
+ * Returns the pointer to the picture buffer whose poc is equal to abs_poc
+ *
+ * @param[in] ps_dpb_mgr
+ * Pointer to DPB Manager structure
+ *
+ * @param[out] ps_pic_buf
+ * Pointer to picture buffer
+
+ * @param[in] abs_poc
+ * poc of the buffer to be returned
+ *
+ * @returns
+ * 0 if successful, pic_buf otherwise
+ * @remarks
+ *
+ *
+ *******************************************************************************
+ */
+pic_buf_t* ihevc_dpb_mgr_get_ref_by_nearest_poc(dpb_mgr_t *ps_dpb_mgr, WORD32 cur_abs_poc)
+{
+ WORD32 i;
+ WORD32 min_diff = 0x7FFFFFFF;
+ pic_buf_t *ps_pic_buf = NULL;
+
+ for(i = 0; i < MAX_DPB_BUFS; i++)
+ {
+ if((ps_dpb_mgr->as_dpb_info[i].ps_pic_buf) &&
+ (ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->u1_used_as_ref != UNUSED_FOR_REF))
+ {
+ WORD32 poc_diff = cur_abs_poc - ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->i4_abs_poc;
+ if((poc_diff > 0) && (poc_diff < min_diff))
+ {
+ min_diff = poc_diff;
+ ps_pic_buf = ps_dpb_mgr->as_dpb_info[i].ps_pic_buf;
+ }
+ }
+ }
+
+ if(NULL == ps_pic_buf)
+ {
+ min_diff = 0x7FFFFFFF;
+ for(i = 0; i < MAX_DPB_BUFS; i++)
+ {
+ if((ps_dpb_mgr->as_dpb_info[i].ps_pic_buf) &&
+ (ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->u1_used_as_ref != UNUSED_FOR_REF))
+ {
+ WORD32 poc_diff = cur_abs_poc - ps_dpb_mgr->as_dpb_info[i].ps_pic_buf->i4_abs_poc;
+ if(ABS(poc_diff) < min_diff)
+ {
+ min_diff = ABS(poc_diff);
+ ps_pic_buf = ps_dpb_mgr->as_dpb_info[i].ps_pic_buf;
+ }
+ }
+ }
+ }
+
+ return ps_pic_buf;
+}
+
+
+/**
+ *******************************************************************************
+ *
+ * @brief
+ * Gets a buffer with abs_poc
+ *
+ * @par Description:
+ * Returns the pointer to the picture buffer whose poc is equal to abs_poc
+ *
+ * @param[in] ps_dpb_mgr
+ * Pointer to DPB Manager structure
+ *
+ * @param[out] ps_pic_buf
+ * Pointer to picture buffer
+
+ * @param[in] abs_poc
+ * poc of the buffer to be returned
+ *
+ * @returns
+ * 0 if successful, pic_buf otherwise
+ * @remarks
+ *
+ *
+ *******************************************************************************
+ */
+pic_buf_t* ihevc_dpb_mgr_get_ref_by_poc(dpb_mgr_t *ps_dpb_mgr, WORD32 abs_poc)
+{
+ UWORD32 i;
+ dpb_info_t *ps_next_ref;
+ pic_buf_t *ps_pic_buf = NULL;
+
+
+ ps_next_ref = ps_dpb_mgr->ps_dpb_head;
+ for(i = 0; i < ps_dpb_mgr->u1_num_ref_bufs; i++)
+ {
+ if(ps_next_ref->ps_pic_buf->i4_abs_poc == abs_poc)
+ {
+ ps_pic_buf = ps_next_ref->ps_pic_buf;
+ break;
+ }
+
+ ps_next_ref = ps_next_ref->ps_prev_dpb;
+ }
+
+ if(i == ps_dpb_mgr->u1_num_ref_bufs)
+ {
+ ps_pic_buf = NULL;
+ }
+
+ return ps_pic_buf;
+}
+
+/**
+ *******************************************************************************
+ *
+ * @brief
+ * Gets a buffer with poc_lsb
+ *
+ * @par Description:
+ * Returns the pointer to the picture buffer whose poc is equal to poc_lsb
+ *
+ * @param[in] ps_dpb_mgr
+ * Pointer to DPB Manager structure
+ *
+ * @param[out] ps_pic_buf
+ * Pointer to picture buffer
+
+ * @param[in] poc_lsb
+ * poc_lsb of the buffer to be returned
+ *
+ * @returns
+ * 0 if successful, pic_buf otherwise
+ * @remarks
+ *
+ *
+ *******************************************************************************
+ */
+
+pic_buf_t* ihevc_dpb_mgr_get_ref_by_poc_lsb(dpb_mgr_t *ps_dpb_mgr, WORD32 poc_lsb)
+{
+ pic_buf_t *ps_pic_buf = NULL;
+ UWORD32 i;
+ dpb_info_t *ps_next_ref;
+
+ ps_next_ref = ps_dpb_mgr->ps_dpb_head;
+ for(i = 0; i < ps_dpb_mgr->u1_num_ref_bufs; i++)
+ {
+ if(ps_next_ref->ps_pic_buf->i4_poc_lsb == poc_lsb)
+ {
+ ps_pic_buf = ps_next_ref->ps_pic_buf;
+ break;
+ }
+
+ ps_next_ref = ps_next_ref->ps_prev_dpb;
+ }
+
+ if(i == ps_dpb_mgr->u1_num_ref_bufs)
+ {
+ ps_pic_buf = NULL;
+ }
+
+ return ps_pic_buf;
+}
+
+
+/**
+ *******************************************************************************
+ *
+ * @brief
+ * Resets the DPB manager
+ *
+ * @par Description:
+ * Re-initialises the DPB manager structure
+ *
+ * @param[in] ps_dpb_mgr
+ * Pointer to DPB Manager structure
+ *
+ * @param[in] ps_buf_mgr
+ * Pointer to buffer manager structure
+ *
+ * @returns
+ *
+ * @remarks
+ *
+ *
+ *******************************************************************************
+ */
+
+void ihevc_dpb_mgr_reset(dpb_mgr_t *ps_dpb_mgr, buf_mgr_t *ps_buf_mgr)
+{
+ int i;
+ dpb_info_t *ps_dpb_info;
+
+ ps_dpb_info = ps_dpb_mgr->as_dpb_info;
+
+ for(i = 0; i < MAX_DPB_BUFS; i++)
+ {
+ if(ps_dpb_info[i].ps_pic_buf->u1_used_as_ref)
+ {
+ ps_dpb_info[i].ps_pic_buf->u1_used_as_ref = UNUSED_FOR_REF;
+ ps_dpb_info[i].ps_prev_dpb = NULL;
+ //Release physical buffer
+ ihevc_buf_mgr_release(ps_buf_mgr, ps_dpb_info[i].ps_pic_buf->u1_buf_id,
+ BUF_MGR_REF);
+
+ ps_dpb_info[i].ps_pic_buf = NULL;
+ }
+ }
+ ps_dpb_mgr->u1_num_ref_bufs = 0;
+ ps_dpb_mgr->ps_dpb_head = NULL;
+
+}
+
+/**
+ *******************************************************************************
+ *
+ * @brief
+ * deletes all pictures from DPB
+ *
+ * @par Description:
+ * Deletes all pictures present in the DPB manager
+ *
+ * @param[in] ps_buf_mgr
+ * Pointer to buffer manager structure
+ *
+ * @param[in] u1_disp_bufs
+ * Number of buffers to be deleted
+ *
+ * @returns
+ *
+ * @remarks
+ *
+ *
+ *******************************************************************************
+ */
+
+void ihevc_dpb_mgr_release_pics(buf_mgr_t *ps_buf_mgr, UWORD8 u1_disp_bufs)
+{
+ WORD8 i;
+ UWORD32 buf_status;
+
+ for(i = 0; i < u1_disp_bufs; i++)
+ {
+ buf_status = ihevc_buf_mgr_get_status(ps_buf_mgr, i);
+ if(0 != buf_status)
+ {
+ ihevc_buf_mgr_release((buf_mgr_t *)ps_buf_mgr, i, BUF_MGR_REF);
+ }
+ }
+}