summaryrefslogtreecommitdiffstats
path: root/encoder/irc_cbr_buffer_control.c
diff options
context:
space:
mode:
Diffstat (limited to 'encoder/irc_cbr_buffer_control.c')
-rwxr-xr-xencoder/irc_cbr_buffer_control.c653
1 files changed, 653 insertions, 0 deletions
diff --git a/encoder/irc_cbr_buffer_control.c b/encoder/irc_cbr_buffer_control.c
new file mode 100755
index 0000000..c179a28
--- /dev/null
+++ b/encoder/irc_cbr_buffer_control.c
@@ -0,0 +1,653 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2015 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 Includes */
+/*****************************************************************************/
+
+/* System include files */
+#include <stdio.h>
+
+/* User include files */
+#include "irc_datatypes.h"
+#include "irc_cntrl_param.h"
+#include "irc_common.h"
+#include "irc_mem_req_and_acq.h"
+#include "irc_fixed_point_error_bits.h"
+#include "irc_cbr_buffer_control.h"
+#include "irc_trace_support.h"
+
+typedef struct cbr_buffer_t
+{
+ /* Buffer size = Delay * Bitrate*/
+ WORD32 i4_buffer_size;
+
+ /* Constant drain rate */
+ WORD32 i4_drain_bits_per_frame[MAX_NUM_DRAIN_RATES];
+
+ /* Encoder Buffer Fullness */
+ WORD32 i4_ebf;
+
+ /* Upper threshold of the Buffer */
+ WORD32 i4_upr_thr[MAX_PIC_TYPE];
+
+ /* Lower threshold of the Buffer */
+ WORD32 i4_low_thr[MAX_PIC_TYPE];
+
+ /* Stuffing threshold equal to error bits per second in the drain bits
+ * fixed point computation */
+ WORD32 i4_stuffing_threshold;
+
+ /* For error due to bits per frame calculation */
+ error_bits_handle aps_bpf_error_bits[MAX_NUM_DRAIN_RATES];
+
+ /* Whether the buffer model is used for CBR or VBR streaming */
+ WORD32 i4_is_cbr_mode;
+
+ /* Input parameters stored for initialization */
+ WORD32 ai4_bit_rate[MAX_NUM_DRAIN_RATES];
+
+ WORD32 i4_max_delay;
+
+ WORD32 ai4_num_pics_in_delay_period[MAX_PIC_TYPE];
+
+ WORD32 i4_tgt_frm_rate;
+
+ UWORD32 u4_max_vbv_buf_size;
+
+} cbr_buffer_t;
+
+WORD32 irc_cbr_buffer_num_fill_use_free_memtab(cbr_buffer_t **pps_cbr_buffer,
+ itt_memtab_t *ps_memtab,
+ ITT_FUNC_TYPE_E e_func_type)
+{
+ WORD32 i4_mem_tab_idx = 0, i;
+ static cbr_buffer_t s_cbr_buffer_temp;
+
+ /*
+ * Hack for all alloc, during which we don't have any state memory.
+ * Dereferencing can cause issues
+ */
+ if(e_func_type == GET_NUM_MEMTAB || e_func_type == FILL_MEMTAB)
+ (*pps_cbr_buffer) = &s_cbr_buffer_temp;
+
+ if(e_func_type != GET_NUM_MEMTAB)
+ {
+ fill_memtab(&ps_memtab[i4_mem_tab_idx], sizeof(cbr_buffer_t),
+ ALIGN_128_BYTE, PERSISTENT, DDR);
+ use_or_fill_base(&ps_memtab[0], (void**)pps_cbr_buffer, e_func_type);
+ }
+ i4_mem_tab_idx++;
+
+ for(i = 0; i < MAX_NUM_DRAIN_RATES; i++)
+ {
+ i4_mem_tab_idx += irc_error_bits_num_fill_use_free_memtab(
+ &pps_cbr_buffer[0]->aps_bpf_error_bits[i],
+ &ps_memtab[i4_mem_tab_idx], e_func_type);
+ }
+ return (i4_mem_tab_idx);
+}
+
+/******************************************************************************
+ * @brief Initialize the CBR VBV buffer state.
+ * This could however be used for VBR streaming VBV also
+ *
+ ******************************************************************************/
+void irc_init_cbr_buffer(cbr_buffer_t *ps_cbr_buffer,
+ WORD32 i4_buffer_delay,
+ WORD32 i4_tgt_frm_rate,
+ WORD32 *i4_bit_rate,
+ UWORD32 *u4_num_pics_in_delay_prd,
+ UWORD32 u4_vbv_buf_size)
+{
+ WORD32 i4_i, i4_bits_per_frm[MAX_NUM_DRAIN_RATES];
+ int i;
+
+ for(i = 0; i < MAX_NUM_DRAIN_RATES; i++)
+ {
+ X_PROD_Y_DIV_Z(i4_bit_rate[i], 1000, i4_tgt_frm_rate,
+ i4_bits_per_frm[i]);
+ /* Drain rate = bitrate/(framerate/1000) */
+ ps_cbr_buffer->i4_drain_bits_per_frame[i] = i4_bits_per_frm[i];
+ /* Initialize the bits per frame error bits calculation */
+ irc_init_error_bits(ps_cbr_buffer->aps_bpf_error_bits[i],
+ i4_tgt_frm_rate, i4_bit_rate[i]);
+ }
+
+ /* Bitrate * delay = buffer size, divide by 1000 as delay is in ms*/
+ /* This would mean CBR mode */
+ if(i4_bit_rate[0] == i4_bit_rate[1])
+ {
+ X_PROD_Y_DIV_Z(i4_bit_rate[0], i4_buffer_delay, 1000,
+ ps_cbr_buffer->i4_buffer_size);
+ ps_cbr_buffer->i4_is_cbr_mode = 1;
+ }
+ else
+ {
+ /* VBR streaming case which has different drain rates for I and P */
+ ps_cbr_buffer->i4_buffer_size = u4_num_pics_in_delay_prd[0]
+ * ps_cbr_buffer->i4_drain_bits_per_frame[0]
+ + u4_num_pics_in_delay_prd[1]
+ * ps_cbr_buffer->i4_drain_bits_per_frame[1];
+
+ ps_cbr_buffer->i4_is_cbr_mode = 0;
+ }
+
+ if(ps_cbr_buffer->i4_buffer_size > (WORD32)u4_vbv_buf_size)
+ {
+ ps_cbr_buffer->i4_buffer_size = u4_vbv_buf_size;
+ }
+
+ /* Initially Encoder buffer fullness is zero */
+ ps_cbr_buffer->i4_ebf = 0;
+
+ /* tgt_frame_rate is divided by 1000 because, an approximate value is fine
+ * as this is just a threshold below which stuffing is done to avoid buffer
+ * underflow due to fixed point error in drain rate
+ */
+ ps_cbr_buffer->i4_stuffing_threshold = (i4_bit_rate[0]
+ - (i4_bits_per_frm[0] * (i4_tgt_frm_rate / 1000)));
+
+ for(i4_i = 0; i4_i < MAX_PIC_TYPE; i4_i++)
+ {
+ /*
+ * Upper threshold for
+ * I frame = 1 * bits per frame
+ * P Frame = 4 * bits per frame.
+ * The threshold for I frame is only 1 * bits per frame as the threshold
+ * should only account for error in estimated bits.
+ * In P frame it should account for difference bets bits consumed by
+ * I(Scene change) and P frame I to P complexity is assumed to be 5.
+ */
+ WORD32 i4_index;
+ i4_index = i4_i > 0 ? 1 : 0;
+ ps_cbr_buffer->i4_upr_thr[i4_i] = ps_cbr_buffer->i4_buffer_size
+ - (ps_cbr_buffer->i4_buffer_size >> 3);
+
+ /*
+ * For both I and P frame Lower threshold is equal to drain rate.Even if
+ * the encoder consumes zero bits it should have enough bits to drain
+ */
+ ps_cbr_buffer->i4_low_thr[i4_i] = i4_bits_per_frm[i4_index];
+ }
+
+ /* Storing the input parameters for using it for change functions */
+ for(i = 0; i < MAX_NUM_DRAIN_RATES; i++)
+ {
+ ps_cbr_buffer->ai4_bit_rate[i] = i4_bit_rate[i];
+ }
+
+ for(i = 0; i < MAX_PIC_TYPE; i++)
+ {
+ ps_cbr_buffer->ai4_num_pics_in_delay_period[i] =
+ u4_num_pics_in_delay_prd[i];
+ }
+ ps_cbr_buffer->i4_tgt_frm_rate = i4_tgt_frm_rate;
+ ps_cbr_buffer->i4_max_delay = i4_buffer_delay;
+ ps_cbr_buffer->u4_max_vbv_buf_size = u4_vbv_buf_size;
+}
+
+/******************************************************************************
+ * @brief Condition check for constraining the number of bits allocated based on
+ * bufer size
+ ******************************************************************************/
+WORD32 irc_cbr_buffer_constraint_check(cbr_buffer_t *ps_cbr_buffer,
+ WORD32 i4_tgt_bits,
+ picture_type_e e_pic_type)
+{
+ WORD32 i4_max_tgt_bits, i4_min_tgt_bits;
+ WORD32 i4_drain_bits_per_frame = (e_pic_type == I_PIC) ?
+ ps_cbr_buffer->i4_drain_bits_per_frame[0] :
+ ps_cbr_buffer->i4_drain_bits_per_frame[1];
+
+ /* Max tgt bits = Upper threshold - current encoder buffer fullness */
+ i4_max_tgt_bits = ps_cbr_buffer->i4_upr_thr[e_pic_type]
+ - ps_cbr_buffer->i4_ebf;
+ /* Max tgt bits cannot be negative */
+ if(i4_max_tgt_bits < 0)
+ i4_max_tgt_bits = 0;
+
+ /*
+ * Min tgt bits , least number of bits in the Encoder after
+ * draining such that it is greater than lower threshold
+ */
+ i4_min_tgt_bits = ps_cbr_buffer->i4_low_thr[e_pic_type]
+ - (ps_cbr_buffer->i4_ebf - i4_drain_bits_per_frame);
+ /* Min tgt bits cannot be negative */
+ if(i4_min_tgt_bits < 0)
+ i4_min_tgt_bits = 0;
+
+ /* Current tgt bits should be between max and min tgt bits */
+ CLIP(i4_tgt_bits, i4_max_tgt_bits, i4_min_tgt_bits);
+ return i4_tgt_bits;
+}
+
+/* *****************************************************************************
+ * @brief constaints the bit allocation based on buffer size
+ *
+ ******************************************************************************/
+WORD32 irc_vbr_stream_buffer_constraint_check(cbr_buffer_t *ps_cbr_buffer,
+ WORD32 i4_tgt_bits,
+ picture_type_e e_pic_type)
+{
+ WORD32 i4_max_tgt_bits;
+
+ /* Max tgt bits = Upper threshold - current encoder buffer fullness */
+ i4_max_tgt_bits = ps_cbr_buffer->i4_upr_thr[e_pic_type]
+ - ps_cbr_buffer->i4_ebf;
+
+ /* Max tgt bits cannot be negative */
+ if(i4_max_tgt_bits < 0)
+ i4_max_tgt_bits = 0;
+
+ if(i4_tgt_bits > i4_max_tgt_bits)
+ i4_tgt_bits = i4_max_tgt_bits;
+
+ return i4_tgt_bits;
+}
+
+/* *****************************************************************************
+ * @brief Verifies the buffer state and returns whether it is overflowing,
+ * underflowing or normal
+ *
+ ******************************************************************************/
+vbv_buf_status_e irc_get_cbr_buffer_status(cbr_buffer_t *ps_cbr_buffer,
+ WORD32 i4_tot_consumed_bits,
+ WORD32 *pi4_num_bits_to_prevent_overflow,
+ picture_type_e e_pic_type)
+{
+ vbv_buf_status_e e_buf_status;
+ WORD32 i4_cur_enc_buf;
+ WORD32 i4_error_bits = (e_pic_type == I_PIC) ?
+ irc_get_error_bits(ps_cbr_buffer
+ ->aps_bpf_error_bits[0]) :
+ irc_get_error_bits(ps_cbr_buffer
+ ->aps_bpf_error_bits[1]);
+
+ WORD32 i4_drain_bits_per_frame = (e_pic_type == I_PIC) ?
+ ps_cbr_buffer->i4_drain_bits_per_frame[0] :
+ ps_cbr_buffer->i4_drain_bits_per_frame[1];
+
+ /* Add the tot consumed bits to the Encoder Buffer*/
+ i4_cur_enc_buf = ps_cbr_buffer->i4_ebf + i4_tot_consumed_bits;
+
+ /* If the Encoder exceeds the Buffer Size signal an Overflow*/
+ if(i4_cur_enc_buf > ps_cbr_buffer->i4_buffer_size)
+ {
+ e_buf_status = VBV_OVERFLOW;
+ i4_cur_enc_buf = ps_cbr_buffer->i4_buffer_size;
+ }
+ else
+ {
+ /*
+ * Subtract the constant drain bits and error bits due to fixed point
+ * implementation
+ */
+ i4_cur_enc_buf -= (i4_drain_bits_per_frame + i4_error_bits);
+
+ /*
+ * If the buffer is less than stuffing threshold an Underflow is
+ * signaled else its NORMAL
+ */
+ if(i4_cur_enc_buf < ps_cbr_buffer->i4_stuffing_threshold)
+ {
+ e_buf_status = VBV_UNDERFLOW;
+ }
+ else
+ {
+ e_buf_status = VBV_NORMAL;
+ }
+
+ if(i4_cur_enc_buf < 0)
+ i4_cur_enc_buf = 0;
+ }
+
+ /*
+ * The RC lib models the encoder buffer, but the VBV buffer characterizes
+ * the decoder buffer
+ */
+ if(e_buf_status == VBV_OVERFLOW)
+ {
+ e_buf_status = VBV_UNDERFLOW;
+ }
+ else if(e_buf_status == VBV_UNDERFLOW)
+ {
+ e_buf_status = VBV_OVERFLOW;
+ }
+
+ pi4_num_bits_to_prevent_overflow[0] = (ps_cbr_buffer->i4_buffer_size
+ - i4_cur_enc_buf);
+
+ return e_buf_status;
+}
+
+/*******************************************************************************
+ * @brief Based on the bits consumed the buffer model is updated
+ ******************************************************************************/
+void irc_update_cbr_buffer(cbr_buffer_t *ps_cbr_buffer,
+ WORD32 i4_tot_consumed_bits,
+ picture_type_e e_pic_type)
+{
+ WORD32 i4_error_bits = (e_pic_type == I_PIC) ?
+ irc_get_error_bits(ps_cbr_buffer->
+ aps_bpf_error_bits[0]) :
+ irc_get_error_bits( ps_cbr_buffer->
+ aps_bpf_error_bits[1]);
+
+ WORD32 i4_drain_bits_per_frame = (e_pic_type == I_PIC) ?
+ ps_cbr_buffer->i4_drain_bits_per_frame[0] :
+ ps_cbr_buffer->i4_drain_bits_per_frame[1];
+
+ /* Update the Encoder buffer with the total consumed bits*/
+ ps_cbr_buffer->i4_ebf += i4_tot_consumed_bits;
+
+ /*
+ * Subtract the drain bits and error bits due to fixed point
+ * implementation
+ */
+ ps_cbr_buffer->i4_ebf -= (i4_drain_bits_per_frame + i4_error_bits);
+
+ if(ps_cbr_buffer->i4_ebf < 0)
+ ps_cbr_buffer->i4_ebf = 0;
+
+ /*SS - Fix for lack of stuffing*/
+ if(ps_cbr_buffer->i4_ebf > ps_cbr_buffer->i4_buffer_size)
+ {
+ trace_printf(
+ (const WORD8*)"Error: Should not be coming here with stuffing\n");
+ ps_cbr_buffer->i4_ebf = ps_cbr_buffer->i4_buffer_size;
+ }
+}
+
+/*******************************************************************************
+ * @brief If the buffer underflows then return the number of bits to prevent
+ * underflow
+ *
+ ******************************************************************************/
+WORD32 irc_get_cbr_bits_to_stuff(cbr_buffer_t *ps_cbr_buffer,
+ WORD32 i4_tot_consumed_bits,
+ picture_type_e e_pic_type)
+{
+ WORD32 i4_bits_to_stuff;
+ WORD32 i4_error_bits = (e_pic_type == I_PIC) ?
+ irc_get_error_bits(ps_cbr_buffer
+ ->aps_bpf_error_bits[0]) :
+ irc_get_error_bits(ps_cbr_buffer
+ ->aps_bpf_error_bits[1]);
+
+ WORD32 i4_drain_bits_per_frame = (e_pic_type == I_PIC) ?
+ ps_cbr_buffer->i4_drain_bits_per_frame[0] :
+ ps_cbr_buffer->i4_drain_bits_per_frame[1];
+
+ /*
+ * Stuffing bits got from the following equation
+ * Stuffing_threshold = ebf + tcb - drain bits - error bits + stuff_bits
+ */
+ i4_bits_to_stuff = i4_drain_bits_per_frame + i4_error_bits
+ + ps_cbr_buffer->i4_stuffing_threshold
+ - (ps_cbr_buffer->i4_ebf + i4_tot_consumed_bits);
+
+ return i4_bits_to_stuff;
+}
+
+/*******************************************************************************
+ * @brief Update the state for change in number of pics in the delay period
+ *
+ ******************************************************************************/
+void irc_change_cbr_vbv_num_pics_in_delay_period(cbr_buffer_t *ps_cbr_buffer,
+ UWORD32 *u4_num_pics_in_delay_prd)
+{
+ WORD32 i;
+
+ if(!ps_cbr_buffer->i4_is_cbr_mode)
+ {
+ ps_cbr_buffer->i4_buffer_size =
+ u4_num_pics_in_delay_prd[0]
+ * ps_cbr_buffer->i4_drain_bits_per_frame[0]
+ + u4_num_pics_in_delay_prd[1]
+ * ps_cbr_buffer->i4_drain_bits_per_frame[1];
+
+ if(ps_cbr_buffer->i4_buffer_size
+ > (WORD32)ps_cbr_buffer->u4_max_vbv_buf_size)
+ {
+ ps_cbr_buffer->i4_buffer_size = ps_cbr_buffer->u4_max_vbv_buf_size;
+ }
+ for(i = 0; i < MAX_PIC_TYPE; i++)
+ {
+ ps_cbr_buffer->i4_upr_thr[i] = ps_cbr_buffer->i4_buffer_size
+ - (ps_cbr_buffer->i4_buffer_size >> 3);
+ }
+
+ /* Re-initialize the number of pics in delay period */
+ for(i = 0; i < MAX_PIC_TYPE; i++)
+ {
+ ps_cbr_buffer->ai4_num_pics_in_delay_period[i] =
+ u4_num_pics_in_delay_prd[i];
+ }
+ }
+}
+
+/******************************************************************************
+ * @brief update the state for change in target frame rate
+ *
+ ******************************************************************************/
+void irc_change_cbr_vbv_tgt_frame_rate(cbr_buffer_t *ps_cbr_buffer,
+ WORD32 i4_tgt_frm_rate)
+{
+ WORD32 i4_i, i4_bits_per_frm[MAX_NUM_DRAIN_RATES];
+ int i;
+
+ for(i = 0; i < MAX_NUM_DRAIN_RATES; i++)
+ {
+ X_PROD_Y_DIV_Z(ps_cbr_buffer->ai4_bit_rate[i], 1000, i4_tgt_frm_rate,
+ i4_bits_per_frm[i]);
+ /* Drain rate = bitrate/(framerate/1000) */
+ ps_cbr_buffer->i4_drain_bits_per_frame[i] = i4_bits_per_frm[i];
+ /* Initialize the bits per frame error bits calculation */
+ irc_change_frm_rate_in_error_bits(ps_cbr_buffer->aps_bpf_error_bits[i],
+ i4_tgt_frm_rate);
+ }
+
+ /* Bitrate * delay = buffer size, divide by 1000 as delay is in ms*/
+ if(!ps_cbr_buffer->i4_is_cbr_mode)
+ {
+ /* VBR streaming case which has different drain rates for I and P */
+ ps_cbr_buffer->i4_buffer_size =
+ ps_cbr_buffer->ai4_num_pics_in_delay_period[0]
+ * ps_cbr_buffer->i4_drain_bits_per_frame[0]
+ + ps_cbr_buffer->ai4_num_pics_in_delay_period[1]
+ * ps_cbr_buffer->i4_drain_bits_per_frame[1];
+ }
+
+ if(ps_cbr_buffer->i4_buffer_size
+ > (WORD32)ps_cbr_buffer->u4_max_vbv_buf_size)
+ {
+ ps_cbr_buffer->i4_buffer_size = ps_cbr_buffer->u4_max_vbv_buf_size;
+ }
+
+ /*
+ * Tgt_frame_rate is divided by 1000 because an approximate value is fine as
+ * this is just a threshold below which stuffing is done to avoid buffer
+ * underflow due to fixed point error in drain rate
+ */
+ ps_cbr_buffer->i4_stuffing_threshold = (ps_cbr_buffer->ai4_bit_rate[0]
+ - (i4_bits_per_frm[0] * (i4_tgt_frm_rate / 1000)));
+
+ for(i4_i = 0; i4_i < MAX_PIC_TYPE; i4_i++)
+ {
+ /*
+ * Upper threshold for
+ * I frame = 1 * bits per frame
+ * P Frame = 4 * bits per frame.
+ * The threshold for I frame is only 1 * bits per frame as the threshold should
+ * only account for error in estimated bits.
+ * In P frame it should account for difference bets bits consumed by I(Scene change)
+ * and P frame I to P complexity is assumed to be 5.
+ */
+ WORD32 i4_index;
+ i4_index = i4_i > 0 ? 1 : 0;
+ ps_cbr_buffer->i4_upr_thr[i4_i] = ps_cbr_buffer->i4_buffer_size
+ - (ps_cbr_buffer->i4_buffer_size >> 3);
+
+ /*
+ * For both I and P frame Lower threshold is equal to drain rate.
+ * Even if the encoder consumes zero bits it should have enough bits to
+ * drain
+ */
+ ps_cbr_buffer->i4_low_thr[i4_i] = i4_bits_per_frm[i4_index];
+ }
+
+ /* Storing the input parameters for using it for change functions */
+ ps_cbr_buffer->i4_tgt_frm_rate = i4_tgt_frm_rate;
+}
+
+/*******************************************************************************
+ * @brief Change the state for change in bit rate
+ *
+ ******************************************************************************/
+void irc_change_cbr_vbv_bit_rate(cbr_buffer_t *ps_cbr_buffer,
+ WORD32 *i4_bit_rate)
+{
+ WORD32 i4_i, i4_bits_per_frm[MAX_NUM_DRAIN_RATES];
+ int i;
+
+ for(i = 0; i < MAX_NUM_DRAIN_RATES; i++)
+ {
+ X_PROD_Y_DIV_Z(i4_bit_rate[i], 1000, ps_cbr_buffer->i4_tgt_frm_rate,
+ i4_bits_per_frm[i]);
+ /* Drain rate = bitrate/(framerate/1000) */
+ ps_cbr_buffer->i4_drain_bits_per_frame[i] = i4_bits_per_frm[i];
+ /* Initialize the bits per frame error bits calculation */
+ irc_change_bitrate_in_error_bits(ps_cbr_buffer->aps_bpf_error_bits[i],
+ i4_bit_rate[i]);
+ }
+
+ /* Bitrate * delay = buffer size, divide by 1000 as delay is in ms*/
+ if(i4_bit_rate[0] == i4_bit_rate[1]) /* This would mean CBR mode */
+ {
+ X_PROD_Y_DIV_Z(i4_bit_rate[0], ps_cbr_buffer->i4_max_delay, 1000,
+ ps_cbr_buffer->i4_buffer_size);
+ ps_cbr_buffer->i4_is_cbr_mode = 1;
+ }
+ else
+ {
+ /* VBR streaming case which has different drain rates for I and P */
+ ps_cbr_buffer->i4_buffer_size =
+ ps_cbr_buffer->ai4_num_pics_in_delay_period[0]
+ * ps_cbr_buffer->i4_drain_bits_per_frame[0]
+ + ps_cbr_buffer->ai4_num_pics_in_delay_period[1]
+ * ps_cbr_buffer->i4_drain_bits_per_frame[1];
+
+ ps_cbr_buffer->i4_is_cbr_mode = 0;
+ }
+
+ if(ps_cbr_buffer->i4_buffer_size
+ > (WORD32)ps_cbr_buffer->u4_max_vbv_buf_size)
+ {
+ ps_cbr_buffer->i4_buffer_size = ps_cbr_buffer->u4_max_vbv_buf_size;
+ }
+
+ /*
+ * tgt_frame_rate is divided by 1000 because
+ * an approximate value is fine as this is just a threshold below which
+ * stuffing is done to avoid buffer underflow due to fixed point
+ * error in drain rate
+ */
+ ps_cbr_buffer->i4_stuffing_threshold = (i4_bit_rate[0]
+ - (i4_bits_per_frm[0]
+ * (ps_cbr_buffer->i4_tgt_frm_rate / 1000)));
+
+ for(i4_i = 0; i4_i < MAX_PIC_TYPE; i4_i++)
+ {
+ /*
+ * Upper threshold for
+ * I frame = 1 * bits per frame
+ * P Frame = 4 * bits per frame.
+ * The threshold for I frame is only 1 * bits per frame as the threshold
+ * should only account for error in estimated bits.
+ * In P frame it should account for difference bets bits consumed by
+ * I(Scene change) and P frame I to P complexity is assumed to be 5.
+ */
+
+ WORD32 i4_index;
+ i4_index = i4_i > 0 ? 1 : 0;
+ ps_cbr_buffer->i4_upr_thr[i4_i] = ps_cbr_buffer->i4_buffer_size
+ - (ps_cbr_buffer->i4_buffer_size >> 3);
+
+ /* For both I and P frame Lower threshold is equal to drain rate.
+ * Even if the encoder consumes zero bits it should have enough bits to
+ * drain
+ */
+ ps_cbr_buffer->i4_low_thr[i4_i] = i4_bits_per_frm[i4_index];
+ }
+
+ /* Storing the input parameters for using it for change functions */
+ for(i = 0; i < MAX_NUM_DRAIN_RATES; i++)
+ {
+ ps_cbr_buffer->ai4_bit_rate[i] = i4_bit_rate[i];
+ }
+}
+
+void irc_change_cbr_buffer_delay(cbr_buffer_t *ps_cbr_buffer,
+ WORD32 i4_buffer_delay)
+{
+ WORD32 i4_i;
+
+ /* Bitrate * delay = buffer size, divide by 1000 as delay is in ms*/
+ if(ps_cbr_buffer->i4_is_cbr_mode)
+ {
+ X_PROD_Y_DIV_Z(ps_cbr_buffer->ai4_bit_rate[0], i4_buffer_delay, 1000,
+ ps_cbr_buffer->i4_buffer_size);
+ }
+
+ if(ps_cbr_buffer->i4_buffer_size
+ > (WORD32)ps_cbr_buffer->u4_max_vbv_buf_size)
+ {
+ ps_cbr_buffer->i4_buffer_size = ps_cbr_buffer->u4_max_vbv_buf_size;
+ }
+
+ for(i4_i = 0; i4_i < MAX_PIC_TYPE; i4_i++)
+ {
+ /*
+ * Upper threshold for
+ * I frame = 1 * bits per frame
+ * P Frame = 4 * bits per frame.
+ * The threshold for I frame is only 1 * bits per frame as the threshold
+ * should only account for error in estimated bits.
+ * In P frame it should account for difference bets bits consumed by I
+ * (Scene change) and P frame I to P complexity is assumed to be 5.
+ */
+ ps_cbr_buffer->i4_upr_thr[i4_i] = ps_cbr_buffer->i4_buffer_size
+ - (ps_cbr_buffer->i4_buffer_size >> 3);
+ }
+
+ /* Storing the input parameters for using it for change functions */
+ ps_cbr_buffer->i4_max_delay = i4_buffer_delay;
+}
+
+WORD32 irc_get_cbr_buffer_delay(cbr_buffer_t *ps_cbr_buffer)
+{
+ return (ps_cbr_buffer->i4_max_delay);
+}
+
+WORD32 irc_get_cbr_buffer_size(cbr_buffer_t *ps_cbr_buffer)
+{
+ return (ps_cbr_buffer->i4_buffer_size);
+}