summaryrefslogtreecommitdiffstats
path: root/encoder/ih264e_utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'encoder/ih264e_utils.c')
-rw-r--r--encoder/ih264e_utils.c559
1 files changed, 426 insertions, 133 deletions
diff --git a/encoder/ih264e_utils.c b/encoder/ih264e_utils.c
index 3657f33..74fd001 100644
--- a/encoder/ih264e_utils.c
+++ b/encoder/ih264e_utils.c
@@ -68,8 +68,8 @@
#include "ih264_defs.h"
#include "ih264_size_defs.h"
#include "ime_distortion_metrics.h"
+#include "ime_defs.h"
#include "ime_structs.h"
-#include "ih264_defs.h"
#include "ih264_error.h"
#include "ih264_structs.h"
#include "ih264_trans_quant_itrans_iquant.h"
@@ -78,6 +78,7 @@
#include "ih264_padding.h"
#include "ih264_intra_pred_filters.h"
#include "ih264_deblk_edge_filters.h"
+#include "ih264_cabac_tables.h"
#include "ih264_macros.h"
#include "ih264_common_tables.h"
#include "ih264_debug.h"
@@ -91,7 +92,9 @@
#include "irc_cntrl_param.h"
#include "irc_frame_info_collector.h"
#include "ih264e_rate_control.h"
+#include "ih264e_cabac_structs.h"
#include "ih264e_structs.h"
+#include "ih264e_cabac.h"
#include "ih264e_utils.h"
#include "ih264e_config.h"
#include "ih264e_statistics.h"
@@ -99,9 +102,7 @@
#include "ih264_list.h"
#include "ih264e_encode_header.h"
#include "ih264e_me.h"
-#include "ime_defs.h"
#include "ime.h"
-#include "ih264e_rate_control.h"
#include "ih264e_core_coding.h"
#include "ih264e_rc_mem_interface.h"
#include "ih264e_time_stamp.h"
@@ -116,6 +117,235 @@
/*****************************************************************************/
/**
+ *******************************************************************************
+ *
+ * @brief
+ * Queues the current buffer, gets back a another buffer for encoding with corrent
+ * picture type
+ *
+ * @par Description:
+ * This function performs 3 distinct but related functions.
+ * 1) Maintains an input queue [Note the the term queue donot imply a
+ * first-in first-out logic here] that queues input and dequeues them so
+ * that input frames can be encoded at any predetermined encoding order
+ * 2) Uses RC library to decide which frame must be encoded in current pass
+ * and which picture type it must be encoded to.
+ * 3) Uses RC library to decide the QP at which current frame has to be
+ * encoded
+ * 4) Determines if the current picture must be encoded or not based on
+ * PRE-ENC skip
+ *
+ * Input queue is used for storing input buffers till they are used for
+ * encoding. This queue is maintained at ps_codec->as_inp_list. Whenever a
+ * valid input comes, it is added to the end of queue. This same input is
+ * added to RC queue using the identifier as ps_codec->i4_pic_cnt. Hence any
+ * pic from RC can be located in the input queue easily.
+ *
+ * The dequeue operation does not start till we have ps_codec->s_cfg.u4_max_num_bframes
+ * frames in the queue. THis is done in order to ensure that once output starts
+ * we will have a constant stream of output with no gaps.
+ *
+ * THe output frame order is governed by RC library. When ever we dequeue a
+ * buffer from RC library, it ensures that we will get them in encoding order
+ * With the output of RC library, we can use the picture id to dequeue the
+ * corresponding buffer from input queue and encode it.
+ *
+ * Condition at the end of stream.
+ * -------------------------------
+ * At the last valid buffer from the app, we will get ps_ive_ip->u4_is_last
+ * to be set. This will the given to lib when appropriate input buffer is
+ * given to encoding.
+ *
+ * Since we have to output is not in sync with input, we will have frames to
+ * encode even after we recive the last vaild input buffer. Hence we have to
+ * make sure that we donot queue any new buffers once we get the flag [It may
+ * mess up GOP ?]. This is acheived by setting ps_codec->i4_last_inp_buff_received
+ * to act as a permenent marker for last frame recived [This may not be needed,
+ * because in our current app, all buffers after the last are marked as last.
+ * But can we rely on that?] . Hence after this flgag is set no new buffers are
+ * queued.
+ *
+ * @param[in] ps_codec
+ * Pointer to codec descriptor
+ *
+ * @param[in] ps_ive_ip
+ * Current input buffer to the encoder
+ *
+ * @param[out] ps_inp
+ * Buffer to be encoded in the current pass
+ *
+ * @returns
+ * Flag indicating if we have a pre-enc skip or not
+ *
+ * @remarks
+ * TODO (bpic)
+ * The check for null ans is last is redudent.
+ * Need to see if we can remove it
+ *
+ *******************************************************************************
+ */
+WORD32 ih264e_input_queue_update(codec_t *ps_codec,
+ ive_video_encode_ip_t *ps_ive_ip,
+ inp_buf_t *ps_enc_buff)
+{
+
+ inp_buf_t *ps_inp_buf;
+ picture_type_e e_pictype;
+ WORD32 i4_skip;
+ UWORD32 ctxt_sel, u4_pic_id, u4_pic_disp_id;
+ UWORD8 u1_frame_qp;
+ UWORD32 max_frame_bits = 0x7FFFFFFF;
+
+ /* Mark that the last input frame has been received */
+ if (ps_ive_ip->u4_is_last == 1)
+ {
+ ps_codec->i4_last_inp_buff_received = 1;
+ }
+
+ if (ps_ive_ip->s_inp_buf.apv_bufs[0] == NULL
+ && !ps_codec->i4_last_inp_buff_received)
+ {
+ ps_enc_buff->s_raw_buf.apv_bufs[0] = NULL;
+ return 0;
+ }
+
+ /***************************************************************************
+ * Check for pre enc skip
+ * When src and target frame rates donot match, we skip some frames to
+ * maintain the relation ship between them
+ **************************************************************************/
+ {
+ WORD32 skip_src;
+
+ skip_src = ih264e_update_rc_framerates(
+ ps_codec->s_rate_control.pps_rate_control_api,
+ ps_codec->s_rate_control.pps_pd_frm_rate,
+ ps_codec->s_rate_control.pps_time_stamp,
+ ps_codec->s_rate_control.pps_frame_time);
+
+ if (skip_src) return 1;
+ }
+
+ /***************************************************************************
+ *Queue the input to the queue
+ **************************************************************************/
+ ps_inp_buf = &(ps_codec->as_inp_list[ps_codec->i4_pic_cnt
+ % MAX_NUM_BFRAMES]);
+
+ /* copy input info. to internal structure */
+ ps_inp_buf->s_raw_buf = ps_ive_ip->s_inp_buf;
+ ps_inp_buf->u4_timestamp_low = ps_ive_ip->u4_timestamp_low;
+ ps_inp_buf->u4_timestamp_high = ps_ive_ip->u4_timestamp_high;
+ ps_inp_buf->u4_is_last = ps_ive_ip->u4_is_last;
+ ps_inp_buf->pv_mb_info = ps_ive_ip->pv_mb_info;
+ ps_inp_buf->u4_mb_info_type = ps_ive_ip->u4_mb_info_type;
+ ps_inp_buf->pv_pic_info = ps_ive_ip->pv_pic_info;
+ ps_inp_buf->u4_pic_info_type = ps_ive_ip->u4_pic_info_type;
+
+ /***************************************************************************
+ * Now we should add the picture to RC stack here
+ **************************************************************************/
+ irc_add_picture_to_stack(ps_codec->s_rate_control.pps_rate_control_api,
+ ps_codec->i4_pic_cnt);
+
+ /*
+ * Rc has a problem with this delayed processing
+ */
+ if (ps_codec->i4_encode_api_call_cnt
+ < (WORD32)(ps_codec->s_cfg.u4_num_bframes))
+ {
+ ps_enc_buff->s_raw_buf.apv_bufs[0] = NULL;
+ return 0;
+ }
+
+ /***************************************************************************
+ * Get a new pic to encode
+ **************************************************************************/
+
+ /*
+ * If a frame is forced, apply it
+ * We cannot force an I frame for first frame
+ */
+ if ((ps_codec->i4_frame_num > 0)&&
+ ((ps_codec->force_curr_frame_type == IV_I_FRAME)||
+ (ps_codec->force_curr_frame_type == IV_IDR_FRAME)))
+ {
+ irc_force_I_frame(ps_codec->s_rate_control.pps_rate_control_api);
+ }
+
+ /* Query the picture_type */
+ e_pictype = ih264e_rc_get_picture_details(
+ ps_codec->s_rate_control.pps_rate_control_api, (WORD32 *)(&u4_pic_id),
+ (WORD32 *)(&u4_pic_disp_id));
+
+ switch (e_pictype)
+ {
+ case I_PIC:
+ ps_codec->pic_type = PIC_I;
+ break;
+ case P_PIC:
+ ps_codec->pic_type = PIC_P;
+ break;
+ case B_PIC:
+ ps_codec->pic_type = PIC_B;
+ break;
+ default:
+ ps_codec->pic_type = PIC_NA;
+ ps_enc_buff->s_raw_buf.apv_bufs[0] = NULL;
+ return 0;
+ }
+
+
+ ps_codec->pic_type = ( (u4_pic_id % ps_codec->s_cfg.u4_idr_frm_interval) ||
+ (ps_codec->force_curr_frame_type != IV_IDR_FRAME) ) ?
+ ps_codec->pic_type : PIC_IDR;
+
+ ps_codec->force_curr_frame_type = IV_NA_FRAME;
+
+ /* Get current frame Qp */
+ u1_frame_qp = (UWORD8)irc_get_frame_level_qp(
+ ps_codec->s_rate_control.pps_rate_control_api, e_pictype,
+ max_frame_bits);
+ ps_codec->u4_frame_qp = gau1_mpeg2_to_h264_qmap[u1_frame_qp];
+
+ /*
+ * copy the pic id to poc because the display order is assumed to be same
+ * as input order
+ */
+ ps_codec->i4_poc = u4_pic_id;
+
+ /***************************************************************************
+ * Now retrieve the correct picture from the queue
+ **************************************************************************/
+
+ /* Mark the skip flag */
+ i4_skip = 0;
+ ctxt_sel = ps_codec->i4_encode_api_call_cnt & 0x01;
+ ps_codec->s_rate_control.pre_encode_skip[ctxt_sel] = i4_skip;
+
+ /* Get a buffer to encode */
+ ps_inp_buf = &(ps_codec->as_inp_list[u4_pic_id % MAX_NUM_BFRAMES]);
+
+ /* copy dequeued input to output */
+ ps_enc_buff->s_raw_buf = ps_inp_buf->s_raw_buf;
+ ps_enc_buff->u4_timestamp_low = ps_inp_buf->u4_timestamp_low;
+ ps_enc_buff->u4_timestamp_high = ps_inp_buf->u4_timestamp_high;
+ ps_enc_buff->u4_is_last = ps_inp_buf->u4_is_last;
+ ps_enc_buff->pv_mb_info = ps_inp_buf->pv_mb_info;
+ ps_enc_buff->u4_mb_info_type = ps_inp_buf->u4_mb_info_type;
+ ps_enc_buff->pv_pic_info = ps_inp_buf->pv_pic_info;
+ ps_enc_buff->u4_pic_info_type = ps_inp_buf->u4_pic_info_type;
+
+ if (ps_enc_buff->u4_is_last)
+ {
+ ps_codec->pic_type = PIC_NA;
+ }
+
+ /* Return the buffer status */
+ return (0);
+}
+
+/**
*******************************************************************************
*
* @brief
@@ -331,7 +561,7 @@ WORD32 ih264e_get_total_pic_buf_size(WORD32 pic_size,
WORD32 num_samples;
WORD32 max_num_bufs;
WORD32 pad = MAX(horz_pad, vert_pad);
- UNUSED(pic_size);
+
/*
* If num_ref_frames and num_reorder_frmaes is specified
* Use minimum value
@@ -343,6 +573,7 @@ WORD32 ih264e_get_total_pic_buf_size(WORD32 pic_size,
/* Maximum number of luma samples in a picture at given level */
num_luma_samples = gai4_ih264_max_luma_pic_size[lvl_idx];
+ num_luma_samples = MAX(num_luma_samples, pic_size);
/* Account for chroma */
num_samples = num_luma_samples * 3 / 2;
@@ -1002,8 +1233,9 @@ IH264E_ERROR_T ih264e_codec_init(codec_t *ps_codec)
ps_codec->s_cfg.u4_target_bitrate,
ps_codec->s_cfg.u4_max_bitrate,
ps_codec->s_cfg.u4_vbv_buffer_delay,
- ps_codec->s_cfg.u4_i_frm_interval, au1_init_qp,
- H264_ALLOC_INTER_FRM_INTV, au1_min_max_qp,
+ ps_codec->s_cfg.u4_i_frm_interval,
+ ps_codec->s_cfg.u4_num_bframes + 1, au1_init_qp,
+ ps_codec->s_cfg.u4_num_bframes + 2 , au1_min_max_qp,
ps_codec->s_cfg.u4_max_level);
}
@@ -1020,6 +1252,11 @@ IH264E_ERROR_T ih264e_codec_init(codec_t *ps_codec)
DEBUG_HISTOGRAM_INIT();
+
+ /* Init dependecy vars */
+ ps_codec->i4_last_inp_buff_received = 0;
+
+
return IH264E_SUCCESS;
}
@@ -1067,7 +1304,8 @@ IH264E_ERROR_T ih264e_pic_init(codec_t *ps_codec, inp_buf_t *ps_inp_buf)
UWORD8 *pu1_cur_pic_luma, *pu1_cur_pic_chroma;
/* ref buffer set */
- pic_buf_t *ps_ref_pic;
+ pic_buf_t *aps_ref_pic[MAX_REF_PIC_CNT] = {NULL, NULL};
+ mv_buf_t *aps_mv_buf[MAX_REF_PIC_CNT] = {NULL, NULL};
WORD32 ref_set_id;
/* pic time stamp */
@@ -1080,9 +1318,6 @@ IH264E_ERROR_T ih264e_pic_init(codec_t *ps_codec, inp_buf_t *ps_inp_buf)
/* curr pic type */
PIC_TYPE_T *pic_type = &ps_codec->pic_type;
- /* should src be skipped */
- WORD32 *skip_src = &ps_codec->s_rate_control.pre_encode_skip[ctxt_sel];
-
/* Diamond search Iteration Max Cnt */
UWORD32 u4_num_layers =
(ps_codec->s_cfg.u4_enc_speed_preset == IVE_FASTEST) ?
@@ -1094,62 +1329,52 @@ IH264E_ERROR_T ih264e_pic_init(codec_t *ps_codec, inp_buf_t *ps_inp_buf)
/********************************************************************/
/* INITIALIZE CODEC CONTEXT */
/********************************************************************/
-
- /* pre enc rc call */
- *skip_src = ih264e_set_rc_pic_params(ps_codec,
- ps_codec->i4_encode_api_call_cnt,
- (WORD32 *) pic_type);
- if (*skip_src == 1)
+ /* slice_type */
+ if ((PIC_I == *pic_type) || (PIC_IDR == *pic_type))
{
- ps_codec->as_process[ctxt_sel * MAX_PROCESS_THREADS].s_inp_buf =
- *ps_inp_buf;
-
- /* inform output bytes generated as zero */
- ps_codec->as_out_buf[ctxt_sel].s_bits_buf.u4_bytes = 0;
-
- return error_status;
+ ps_codec->i4_slice_type = ISLICE;
}
-
- /********************************************************************/
- /* Alternate reference frame */
- /********************************************************************/
- if (ps_codec->s_cfg.u4_enable_alt_ref)
+ else if (PIC_P == *pic_type)
{
- if (PIC_IDR == *pic_type || PIC_I == *pic_type)
- {
- ps_codec->u4_is_curr_frm_ref = 1;
- }
- else
- {
- ps_codec->u4_is_curr_frm_ref = 1;
- if(ps_codec->i4_encode_api_call_cnt % (ps_codec->s_cfg.u4_enable_alt_ref + 1))
- ps_codec->u4_is_curr_frm_ref = 0;
- }
-
- if ((ps_codec->u4_is_curr_frm_ref == 1) || (ps_codec->i4_frame_num < 0))
- {
- ps_codec->i4_frame_num++;
- }
+ ps_codec->i4_slice_type = PSLICE;
}
- else
+ else if(PIC_B == *pic_type)
{
- ps_codec->u4_is_curr_frm_ref = 1;
-
- ps_codec->i4_frame_num++;
+ ps_codec->i4_slice_type = BSLICE;
}
- /* slice_type */
- ps_codec->i4_slice_type = PSLICE;
- if ((PIC_I == *pic_type) || (PIC_IDR == *pic_type))
+ /***************************************************************************
+ * Set up variables for sending frame number, poc and reference
+ * a) Set up alt ref too
+ **************************************************************************/
+
+ /* In case of alt ref and B pics we will have non reference frame in stream */
+ if (ps_codec->s_cfg.u4_enable_alt_ref || ps_codec->s_cfg.u4_num_bframes)
{
- ps_codec->i4_slice_type = ISLICE;
+ ps_codec->i4_non_ref_frames_in_stream = 1;
}
- else if (PIC_P == *pic_type)
+
+ /* Check and set if the current frame is reference or not */
+ ps_codec->u4_is_curr_frm_ref = 0;
+
+ /* This frame is reference if its not a B pic, pending approval from alt ref */
+ ps_codec->u4_is_curr_frm_ref = (*pic_type != PIC_B);
+
+ /* In case if its a P pic, we will decide according to alt ref also */
+ if (ps_codec->s_cfg.u4_enable_alt_ref && (*pic_type == PIC_P)
+ && (ps_codec->i4_pic_cnt
+ % (ps_codec->s_cfg.u4_enable_alt_ref + 1)))
{
- ps_codec->i4_slice_type = PSLICE;
+ ps_codec->u4_is_curr_frm_ref = 0;
}
+ /*
+ * Override everything in case of IDR
+ * Note that in case of IDR, at this point ps_codec->u4_is_curr_frm_ref must
+ * be 1
+ */
+
/* is this an IDR pic */
ps_codec->u4_is_idr = 0;
@@ -1165,6 +1390,10 @@ IH264E_ERROR_T ih264e_pic_init(codec_t *ps_codec, inp_buf_t *ps_inp_buf)
ps_codec->i4_idr_pic_id++;
}
+ /***************************************************************************
+ * Set up Deblock
+ **************************************************************************/
+
/* set deblock disable flags based on disable deblock level */
ps_codec->i4_disable_deblk_pic = 1;
@@ -1235,93 +1464,132 @@ IH264E_ERROR_T ih264e_pic_init(codec_t *ps_codec, inp_buf_t *ps_inp_buf)
ih264e_populate_pps(ps_codec, ps_pps);
}
- /* Reference and MV bank Buffer Manager */
+ /***************************************************************************
+ * Reference and MV bank Buffer Manager
+ * Here we will
+ * 1) Find the correct ref pics for the current frame
+ * 2) Free the ref pic that is not going to be used anywhere
+ * 3) Find a free buff from the list and assign it as the recon of
+ * current frame
+ *
+ * 1) Finding correct ref pic
+ * All pics needed for future are arranged in a picture list called
+ * ps_codec->as_ref_set. Each picture in this will have a pic buffer and
+ * MV buffer that is marked appropriately as BUF_MGR_REF, BUF_MGR_IO or
+ * BUF_MGR_CODEC. Also the pic_cnt and poc will also be present.
+ * Hence to find the ref pic we will loop through the list and find
+ * 2 pictures with maximum i4_pic_cnt .
+ *
+ * note that i4_pic_cnt == -1 is used to filter uninit ref pics.
+ * Now since we only have max two ref pics, we will always find max 2
+ * ref pics.
+
+ *
+ * 2) 3) Self explanatory
+ ***************************************************************************/
{
- /* min pic cnt among the list of pics stored in ref list */
- WORD32 min_pic_cnt;
+ /* Search for buffs with maximum pic cnt */
- /* max pic cnt among the list of pics stored in ref list */
- WORD32 max_pic_cnt;
+ WORD32 max_pic_cnt[] = { -1, -1 };
- /* temp var */
- WORD32 i;
+ mv_buf_t *ps_mv_buf_to_free[] = { NULL, NULL };
- ps_ref_pic = NULL;
+ /* temp var */
+ WORD32 i, buf_status;
- /* get reference picture when necessary */
- /* Only nearest picture encoded (max pic cnt) is used as reference */
- if ((*pic_type != PIC_IDR) && (*pic_type != PIC_I))
+ for (i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
{
- max_pic_cnt = ps_codec->as_ref_set[0].i4_pic_cnt;
+ if (ps_codec->as_ref_set[i].i4_pic_cnt == -1)
+ continue;
+
+ buf_status = ih264_buf_mgr_get_status(
+ ps_codec->pv_ref_buf_mgr,
+ ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id);
+
+ /* Ideally we should look for buffer status of MV BUFF also. But since
+ * the correponding MV buffs also will be at the same state. It dosent
+ * matter as of now. But the check will make the logic better */
+ if ((max_pic_cnt[0] < ps_codec->as_ref_set[i].i4_pic_cnt)
+ && (buf_status & BUF_MGR_REF))
+ {
+ if (max_pic_cnt[1] < ps_codec->as_ref_set[i].i4_pic_cnt)
+ {
+ max_pic_cnt[0] = max_pic_cnt[1];
+ aps_ref_pic[0] = aps_ref_pic[1];
+ aps_mv_buf[0] = aps_mv_buf[1];
- ps_ref_pic = ps_codec->as_ref_set[0].ps_pic_buf;
+ ps_mv_buf_to_free[0] = ps_mv_buf_to_free[1];
- /* loop through to get the max pic cnt among the list of pics stored in ref list */
- for (i = 1; i < ps_codec->i4_ref_buf_cnt; i++)
- {
- if (max_pic_cnt < ps_codec->as_ref_set[i].i4_pic_cnt)
+ max_pic_cnt[1] = ps_codec->as_ref_set[i].i4_pic_cnt;
+ aps_ref_pic[1] = ps_codec->as_ref_set[i].ps_pic_buf;
+ aps_mv_buf[1] = ps_codec->as_ref_set[i].ps_mv_buf;
+ ps_mv_buf_to_free[1] = ps_codec->as_ref_set[i].ps_mv_buf;
+
+ }
+ else
{
- max_pic_cnt = ps_codec->as_ref_set[i].i4_pic_cnt;
- ps_ref_pic = ps_codec->as_ref_set[i].ps_pic_buf;
+ max_pic_cnt[0] = ps_codec->as_ref_set[i].i4_pic_cnt;
+ aps_ref_pic[0] = ps_codec->as_ref_set[i].ps_pic_buf;
+ aps_mv_buf[0] = ps_codec->as_ref_set[i].ps_mv_buf;
+ ps_mv_buf_to_free[0] = ps_codec->as_ref_set[i].ps_mv_buf;
}
}
}
- /* get a location at which the curr pic info can be stored for future reference */
- ref_set_id = -1;
-
- for (i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
+ /*
+ * Now if the current picture is I or P, we discard the back ref pic and
+ * assign forward ref as backward ref
+ */
+ if (*pic_type != PIC_B)
{
- if (-1 == ps_codec->as_ref_set[i].i4_pic_cnt)
+ if (ps_mv_buf_to_free[0])
{
- ref_set_id = i;
- break;
- }
- }
+ /* release this frame from reference list */
+ ih264_buf_mgr_release(ps_codec->pv_mv_buf_mgr,
+ ps_mv_buf_to_free[0]->i4_buf_id,
+ BUF_MGR_REF);
- /* If all the entries in the ref_set array are filled, then remove the entry with least pic_cnt */
- if (ref_set_id == -1)
- {
- /* pic info */
- pic_buf_t *ps_cur_pic;
-
- /* mv info */
- mv_buf_t *ps_cur_mv_buf;
-
- ref_set_id = 0;
- min_pic_cnt = ps_codec->as_ref_set[0].i4_pic_cnt;
-
- /* loop through to get the min pic cnt among the list of pics stored in ref list */
- for (i = 1; i < ps_codec->i4_ref_buf_cnt; i++)
- {
- if (min_pic_cnt > ps_codec->as_ref_set[i].i4_pic_cnt)
- {
- min_pic_cnt = ps_codec->as_ref_set[i].i4_pic_cnt;
- ref_set_id = i;
- }
+ ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr,
+ aps_ref_pic[0]->i4_buf_id, BUF_MGR_REF);
}
- ps_cur_pic = ps_codec->as_ref_set[ref_set_id].ps_pic_buf;
-
- ps_cur_mv_buf = ps_codec->as_ref_set[ref_set_id].ps_mv_buf;
+ max_pic_cnt[0] = max_pic_cnt[1];
+ aps_ref_pic[0] = aps_ref_pic[1];
+ aps_mv_buf[0] = aps_mv_buf[1];
- /* release this frame from reference list */
- ih264_buf_mgr_release(ps_codec->pv_mv_buf_mgr,
- ps_cur_mv_buf->i4_buf_id, BUF_MGR_REF);
-
- ih264_buf_mgr_release(ps_codec->pv_ref_buf_mgr,
- ps_cur_pic->i4_buf_id, BUF_MGR_REF);
+ /* Dummy */
+ max_pic_cnt[1] = -1;
}
- if (ps_codec->s_cfg.u4_enable_recon)
+ /*
+ * Mark all reference pic with unused buffers to be free
+ * We need this step since each one, ie ref, recon io etc only unset their
+ * respective flags. Hence we need to combine togather and mark the ref set
+ * accordingly
+ */
+ ref_set_id = -1;
+ for (i = 0; i < ps_codec->i4_ref_buf_cnt; i++)
{
- ret = ih264_buf_mgr_check_free((buf_mgr_t *)ps_codec->pv_ref_buf_mgr);
+ if (ps_codec->as_ref_set[i].i4_pic_cnt == -1)
+ {
+ ref_set_id = i;
+ continue;
+ }
- if (ret != IH264_SUCCESS)
+ buf_status = ih264_buf_mgr_get_status(
+ ps_codec->pv_ref_buf_mgr,
+ ps_codec->as_ref_set[i].ps_pic_buf->i4_buf_id);
+
+ if ((buf_status & (BUF_MGR_REF | BUF_MGR_CODEC | BUF_MGR_IO)) == 0)
{
- return IH264E_NO_FREE_RECONBUF;
+ ps_codec->as_ref_set[i].i4_pic_cnt = -1;
+ ps_codec->as_ref_set[i].i4_poc = 32768;
+
+ ref_set_id = i;
}
}
+ /* An asssert failure here means we donot have any free buffs */
+ ASSERT(ref_set_id >= 0);
}
{
@@ -1353,7 +1621,6 @@ IH264E_ERROR_T ih264e_pic_init(codec_t *ps_codec, inp_buf_t *ps_inp_buf)
* and getting a buffer id to free
*/
ps_mv_buf->i4_abs_poc = ps_codec->i4_abs_pic_order_cnt;
-
ps_mv_buf->i4_buf_id = cur_mv_bank_buf_id;
}
@@ -1375,7 +1642,7 @@ IH264E_ERROR_T ih264e_pic_init(codec_t *ps_codec, inp_buf_t *ps_inp_buf)
}
/* mark the buffer as needed for reference if the curr pic is available for ref */
- if (1 == ps_codec->u4_is_curr_frm_ref)
+ if (ps_codec->u4_is_curr_frm_ref)
{
ih264_buf_mgr_set_status(ps_codec->pv_ref_buf_mgr, cur_pic_buf_id,
BUF_MGR_REF);
@@ -1392,7 +1659,7 @@ IH264E_ERROR_T ih264e_pic_init(codec_t *ps_codec, inp_buf_t *ps_inp_buf)
ps_cur_pic->u4_timestamp_high = ps_inp_buf->u4_timestamp_high;
ps_cur_pic->u4_timestamp_low = ps_inp_buf->u4_timestamp_low;
- ps_cur_pic->i4_abs_poc = ps_codec->i4_abs_pic_order_cnt;
+ ps_cur_pic->i4_abs_poc = ps_codec->i4_poc;
ps_cur_pic->i4_poc_lsb = ps_codec->i4_pic_order_cnt_lsb;
ps_cur_pic->i4_buf_id = cur_pic_buf_id;
@@ -1401,18 +1668,17 @@ IH264E_ERROR_T ih264e_pic_init(codec_t *ps_codec, inp_buf_t *ps_inp_buf)
pu1_cur_pic_chroma = ps_cur_pic->pu1_chroma;
}
- /* in case the current picture is used for reference then add it to the reference set */
- if (ps_codec->u4_is_curr_frm_ref
- && ((*pic_type == PIC_IDR) || (*pic_type == PIC_I)
- || (*pic_type == PIC_P)))
+ /*
+ * Add the current picture to ref list independent of the fact that it is used
+ * as reference or not. This is because, now recon is not in sync with output
+ * hence we may need the current recon after some delay. By adding it to ref list
+ * we can retrieve the recon any time we want. The information that it is used
+ * for ref can still be found by checking the buffer status of pic buf.
+ */
{
ps_codec->as_ref_set[ref_set_id].i4_pic_cnt = ps_codec->i4_pic_cnt;
-
- /* TODO: Currently pic_cnt and poc are same - Once frame drops are introduced change appropriately */
- ps_codec->as_ref_set[ref_set_id].i4_poc = ps_codec->i4_pic_cnt;
-
+ ps_codec->as_ref_set[ref_set_id].i4_poc = ps_codec->i4_poc;
ps_codec->as_ref_set[ref_set_id].ps_mv_buf = ps_mv_buf;
-
ps_codec->as_ref_set[ref_set_id].ps_pic_buf = ps_cur_pic;
}
@@ -1592,16 +1858,37 @@ IH264E_ERROR_T ih264e_pic_init(codec_t *ps_codec, inp_buf_t *ps_inp_buf)
/* Pointer to current pictures mv buffers */
ps_proc->ps_cur_mv_buf = ps_mv_buf;
- /* pointer to ref picture */
- ps_proc->ps_ref_pic = ps_ref_pic;
+ /*
+ * pointer to ref picture
+ * 0 : Temporal back reference
+ * 1 : Temporal forward reference
+ */
+ ps_proc->aps_ref_pic[PRED_L0] = aps_ref_pic[PRED_L0];
+ ps_proc->aps_ref_pic[PRED_L1] = aps_ref_pic[PRED_L1];
+ if (ps_codec->pic_type == PIC_B)
+ {
+ ps_proc->aps_mv_buf[PRED_L0] = aps_mv_buf[PRED_L0];
+ ps_proc->aps_mv_buf[PRED_L1] = aps_mv_buf[PRED_L1];
+ }
+ else
+ {
+ /*
+ * Else is dummy since for non B pic we does not need this
+ * But an assignment here will help in not having a segfault
+ * when we calcualte colpic in P slices
+ */
+ ps_proc->aps_mv_buf[PRED_L0] = ps_mv_buf;
+ ps_proc->aps_mv_buf[PRED_L1] = ps_mv_buf;
+ }
if ((*pic_type != PIC_IDR) && (*pic_type != PIC_I))
{
- /* ref pointer luma */
- ps_proc->pu1_ref_buf_luma_base = ps_ref_pic->pu1_luma;
+ /* temporal back an forward ref pointer luma and chroma */
+ ps_proc->apu1_ref_buf_luma_base[PRED_L0] = aps_ref_pic[PRED_L0]->pu1_luma;
+ ps_proc->apu1_ref_buf_chroma_base[PRED_L0] = aps_ref_pic[PRED_L0]->pu1_chroma;
- /* ref pointer chroma */
- ps_proc->pu1_ref_buf_chroma_base = ps_ref_pic->pu1_chroma;
+ ps_proc->apu1_ref_buf_luma_base[PRED_L1] = aps_ref_pic[PRED_L1]->pu1_luma;
+ ps_proc->apu1_ref_buf_chroma_base[PRED_L1] = aps_ref_pic[PRED_L1]->pu1_chroma;
}
/* Structure for current input buffer */
@@ -1649,6 +1936,9 @@ IH264E_ERROR_T ih264e_pic_init(codec_t *ps_codec, inp_buf_t *ps_inp_buf)
/* slice hdr base */
ps_entropy->ps_slice_hdr_base = ps_proc->ps_slice_hdr_base;
+ /* Abs poc */
+ ps_entropy->i4_abs_pic_order_cnt = ps_proc->ps_codec->i4_poc;
+
/* initialize entropy map */
if (i == j)
{
@@ -1656,6 +1946,9 @@ IH264E_ERROR_T ih264e_pic_init(codec_t *ps_codec, inp_buf_t *ps_inp_buf)
memset(ps_entropy->pu1_entropy_map - ps_proc->i4_wd_mbs, 1, ps_proc->i4_wd_mbs);
/* row 0 to ht in mbs */
memset(ps_entropy->pu1_entropy_map, 0, ps_proc->i4_wd_mbs * ps_proc->i4_ht_mbs);
+
+ /* intialize cabac tables */
+ ih264e_init_cabac_table(ps_entropy);
}
/* wd in mbs */
@@ -1751,7 +2044,7 @@ IH264E_ERROR_T ih264e_pic_init(codec_t *ps_codec, inp_buf_t *ps_inp_buf)
/* qp */
ps_me_ctxt->u1_mb_qp = ps_codec->u4_frame_qp;
- if ((i == 0) && (0 == ps_codec->i4_pic_cnt))
+ if ((i == j) && (0 == ps_codec->i4_poc))
{
/* init mv bits tables */
ih264e_init_mv_bits(ps_me_ctxt);