aosp12/external/libhevc/encoder/fixed_point_error_bits.c

249 lines
9.3 KiB
C

/******************************************************************************
*
* 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 fixed_point_error_bits.c
*
* \brief
* This file contain error bits processing functions
*
* \date
* 15/02/2012
*
* \author
* ittiam
*
******************************************************************************
*/
/*****************************************************************************/
/* File Includes */
/*****************************************************************************/
/* System include files */
#include <stdio.h>
/* User include files */
#include "ittiam_datatypes.h"
#include "rc_common.h"
#include "rc_cntrl_param.h"
#include "var_q_operator.h"
#include "mem_req_and_acq.h"
#include "fixed_point_error_bits.h"
/*i4_max_tgt_frm_rate and i4_tgt_frm_rate hold same value so removing one*/
typedef struct error_bits_t
{
/* WORD32 i4_max_tgt_frm_rate; */ /*Max tgt frm rate so that dynamic change infrm rate can be handled */
WORD32 i4_accum_frm_rate; /* Cur frm rate */
WORD32 i4_tgt_frm_rate; /* tgt frame rate*/
WORD32 i4_tgt_frm_rate_incr; /* tgt frm rate increment */
UWORD8 u1_compute_error_bits; /* flag to indicate 1 second is up*/
WORD32 i4_accum_bitrate; /* Bitrate/frame rate value added over a period*/
WORD32 i4_bitrate; /* bitrate */
} error_bits_t;
#if NON_STEADSTATE_CODE
WORD32 error_bits_num_fill_use_free_memtab(
error_bits_t **pps_error_bits, itt_memtab_t *ps_memtab, ITT_FUNC_TYPE_E e_func_type)
{
WORD32 i4_mem_tab_idx = 0;
static error_bits_t s_error_bits_temp;
/* Hack for al alloc, during which we dont have any state memory.
Dereferencing can cause issues */
if(e_func_type == GET_NUM_MEMTAB || e_func_type == FILL_MEMTAB)
(*pps_error_bits) = &s_error_bits_temp;
/*for src rate control state structure*/
if(e_func_type != GET_NUM_MEMTAB)
{
fill_memtab(
&ps_memtab[i4_mem_tab_idx], sizeof(error_bits_t), MEM_TAB_ALIGNMENT, PERSISTENT, DDR);
use_or_fill_base(&ps_memtab[0], (void **)pps_error_bits, e_func_type);
}
i4_mem_tab_idx++;
return (i4_mem_tab_idx);
}
/* ******************************************************************************/
/**
* @brief Calculates the error bits due to fixed point divisions
*
* @param ps_error_bits
* @param i4_tgt_frm_rate
* @param i4_bitrate
*/
/* ******************************************************************************/
void init_error_bits(error_bits_t *ps_error_bits, WORD32 i4_tgt_frm_rate, WORD32 i4_bitrate)
{
/* This value is incremented every at the end of every VOP by i4_tgt_frm_rate_incr*/
/* Initializing the parameters*/
ps_error_bits->i4_accum_frm_rate = 0;
ps_error_bits->i4_tgt_frm_rate = i4_tgt_frm_rate;
/* Value by which i4_accum_frm_rate is incremented every VOP*/
ps_error_bits->i4_tgt_frm_rate_incr = 1000;
/*Compute error bits is set to 1 at the end of 1 second*/
ps_error_bits->u1_compute_error_bits = 0;
ps_error_bits->i4_tgt_frm_rate = i4_tgt_frm_rate;
ps_error_bits->i4_accum_bitrate = 0;
ps_error_bits->i4_bitrate = i4_bitrate;
}
#endif /* #if NON_STEADSTATE_CODE */
/* ******************************************************************************/
/**
* @brief Updates the error state
*
* @param ps_error_bits
*/
/* ******************************************************************************/
void update_error_bits(error_bits_t *ps_error_bits)
{
WORD32 i4_bits_per_frame;
X_PROD_Y_DIV_Z(
ps_error_bits->i4_bitrate, 1000, ps_error_bits->i4_tgt_frm_rate, i4_bits_per_frame);
if(ps_error_bits->u1_compute_error_bits == 1)
{
ps_error_bits->i4_accum_bitrate = 0;
//ps_error_bits->i4_accum_frm_rate -= ps_error_bits->i4_tgt_frm_rate;
ps_error_bits->i4_accum_frm_rate = 0;
}
/* This value is incremented every at the end of every VOP by
i4_tgt_frm_rate_incr*/
ps_error_bits->i4_accum_frm_rate += ps_error_bits->i4_tgt_frm_rate_incr;
ps_error_bits->i4_accum_bitrate += i4_bits_per_frame;
/* When current tgt frm rate is equal or greater than max tgt fram rate
1 second is up , compute the error bits */
if(ps_error_bits->i4_accum_frm_rate >= ps_error_bits->i4_tgt_frm_rate)
{
/* ps_error_bits->i4_accum_frm_rate -= ps_error_bits->i4_tgt_frm_rate; */
ps_error_bits->u1_compute_error_bits = 1;
}
else
{
ps_error_bits->u1_compute_error_bits = 0;
}
}
/* ******************************************************************************/
/**
* @brief Returns the error bits for the current frame if there are any
*
* @param ps_error_bits
*
* @return
*/
/* ******************************************************************************/
WORD32 get_error_bits(error_bits_t *ps_error_bits)
{
WORD32 i4_error_bits = 0;
/*If 1s is up calcualte error for the last 1s worth fo frames*/
if(ps_error_bits->u1_compute_error_bits == 1)
{
WORD32 i4_cur_bitrate;
WORD32 i4_cur_frame_rate = ps_error_bits->i4_accum_frm_rate;
/* For frame rates like 29.970, the current frame rate would be a multiple of
1000 and every 100 seconds 3 frames would be dropped. So the error should be
calculated based on actual frame rate. So for e.g. the iteration, there would be
30 frames and so the bits allocated would be (30/29.970)*bitrate */
X_PROD_Y_DIV_Z(
ps_error_bits->i4_bitrate,
i4_cur_frame_rate,
ps_error_bits->i4_tgt_frm_rate,
i4_cur_bitrate);
/*Error = Actual bitrate - bits_per_frame * num of frames*/
i4_error_bits = i4_cur_bitrate - ps_error_bits->i4_accum_bitrate;
}
return (i4_error_bits);
}
/* ******************************************************************************/
/**
* @brief Change the bitrate value for error bits module
*
* @param ps_error_bits
* @param i4_bitrate
*/
/* ******************************************************************************/
void change_bitrate_in_error_bits(error_bits_t *ps_error_bits, WORD32 i4_bitrate)
{
/*here accum_bitrate would have accumulated the value based on old bit rate. after one second is elapsed
* the error is calcluated based on new bit rate which would result in huge error value. to avoid this
* accum_bitrate value is recalculated assuming new bitrate.
*/
/*#ifdef DYNAMIC_RC*/
WORD32 i4_old_bits_per_frame;
WORD32 i4_new_bits_per_frame;
WORD32 i4_frame_count;
X_PROD_Y_DIV_Z(
ps_error_bits->i4_bitrate, 1000, ps_error_bits->i4_tgt_frm_rate, i4_old_bits_per_frame);
i4_frame_count = ps_error_bits->i4_accum_bitrate / i4_old_bits_per_frame;
X_PROD_Y_DIV_Z(i4_bitrate, 1000, ps_error_bits->i4_tgt_frm_rate, i4_new_bits_per_frame);
ps_error_bits->i4_accum_bitrate = i4_frame_count * i4_new_bits_per_frame;
/*#endif*/
/*change bit rate*/
ps_error_bits->i4_bitrate = i4_bitrate;
/* ps_error_bits->i4_accum_bitrate=i4_bitrate;*/
}
/* ******************************************************************************/
/**
* @brief Change the frame rate parameter for the error bits state
*
* @param ps_error_bits
* @param i4_tgt_frm_rate
*/
/* ******************************************************************************/
/*IMPLEMENTATION NOT TESTED*/
void change_frm_rate_in_error_bits(error_bits_t *ps_error_bits, WORD32 i4_tgt_frm_rate)
{
/* Value by which i4_accum_frm_rate is incremented every VOP*/
/*accum_frm_rate is used to mark one second mark so a change in frame rate could alter this mark leading
* to very high accum bitrate value. To avoid this accum_frame_rate is recalculated
* according to new value
*/
/* WORD32 i4_frame_count;*/
/* ps_error_bits->i4_accum_frm_rate=(ps_error_bits->i4_accum_frm_rate*i4_tgt_frm_rate)/ps_error_bits->i4_tgt_frm_rate);*/
if(ps_error_bits->i4_tgt_frm_rate != i4_tgt_frm_rate)
X_PROD_Y_DIV_Z(
ps_error_bits->i4_accum_frm_rate,
i4_tgt_frm_rate,
ps_error_bits->i4_tgt_frm_rate,
ps_error_bits->i4_accum_frm_rate);
/*round off the accum value to multiple of 1000*/
ps_error_bits->i4_accum_frm_rate = ps_error_bits->i4_accum_frm_rate / 1000;
ps_error_bits->i4_accum_frm_rate = ps_error_bits->i4_accum_frm_rate * 1000;
/* ps_error_bits->i4_tgt_frm_rate_incr = (ps_error_bits->i4_tgt_frm_rate
* 1000)/ i4_tgt_frm_rate;
*/
ps_error_bits->i4_tgt_frm_rate = i4_tgt_frm_rate;
}