1/******************************************************************************
2 *
3 * Copyright (C) 2015 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************
18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19*/
20
21/****************************************************************************/
22/* File Name         : irc_rd_model.c                                       */
23/*                                                                          */
24/* Description       : Implall the Functions to Model the                   */
25/*                     Rate Distortion Behaviour of the Codec over the Last */
26/*                     Few Frames.                                          */
27/*                                                                          */
28/* List of Functions : irc_update_frame_rd_model                            */
29/*                     estimate_mpeg2_qp_for_resbits                        */
30/*                                                                          */
31/* Issues / Problems : None                                                 */
32/*                                                                          */
33/* Revision History  :                                                      */
34/*        DD MM YYYY   Author(s)       Changes (Describe the changes made)  */
35/*        21 06 2006   Sarat           Initial Version                      */
36/****************************************************************************/
37
38/* System include files */
39#include <stdarg.h>
40#include <stdlib.h>
41#include <stdio.h>
42#include <string.h>
43#include "math.h"
44
45/* User include files */
46#include "irc_datatypes.h"
47#include "irc_common.h"
48#include "irc_mem_req_and_acq.h"
49#include "irc_rd_model.h"
50#include "irc_rd_model_struct.h"
51
52
53WORD32 irc_rd_model_num_fill_use_free_memtab(rc_rd_model_t **pps_rc_rd_model,
54                                             itt_memtab_t *ps_memtab,
55                                             ITT_FUNC_TYPE_E e_func_type)
56{
57    WORD32 i4_mem_tab_idx = 0;
58    rc_rd_model_t s_rc_rd_model_temp;
59
60    /*
61     * Hack for al alloc, during which we don't have any state memory.
62     * Dereferencing can cause issues
63     */
64    if(e_func_type == GET_NUM_MEMTAB || e_func_type == FILL_MEMTAB)
65        (*pps_rc_rd_model) = &s_rc_rd_model_temp;
66
67    /*for src rate control state structure*/
68    if(e_func_type != GET_NUM_MEMTAB)
69    {
70        fill_memtab(&ps_memtab[i4_mem_tab_idx], sizeof(rc_rd_model_t),
71                    ALIGN_128_BYTE, PERSISTENT, DDR);
72        use_or_fill_base(&ps_memtab[0], (void**)pps_rc_rd_model, e_func_type);
73    }
74    i4_mem_tab_idx++;
75
76    return (i4_mem_tab_idx);
77}
78
79void irc_init_frm_rc_rd_model(rc_rd_model_t *ps_rd_model,
80                              UWORD8 u1_max_frames_modelled)
81{
82
83    ps_rd_model->u1_num_frms_in_model = 0;
84    ps_rd_model->u1_curr_frm_counter = 0;
85    ps_rd_model->u1_max_frms_to_model = u1_max_frames_modelled;
86
87    ps_rd_model->model_coeff_a_lin_wo_int = 0;
88    ps_rd_model->model_coeff_b_lin_wo_int = 0;
89    ps_rd_model->model_coeff_c_lin_wo_int = 0;
90}
91
92void irc_reset_frm_rc_rd_model(rc_rd_model_t *ps_rd_model)
93{
94    ps_rd_model->u1_num_frms_in_model = 0;
95    ps_rd_model->u1_curr_frm_counter = 0;
96
97    ps_rd_model->model_coeff_a_lin_wo_int = 0;
98    ps_rd_model->model_coeff_b_lin_wo_int = 0;
99    ps_rd_model->model_coeff_c_lin_wo_int = 0;
100}
101
102static UWORD8 find_model_coeffs(UWORD32 *pi4_res_bits,
103                                UWORD32 *pi4_sad_h264,
104                                UWORD8 *pu1_num_skips,
105                                UWORD8 *pui_avg_mpeg2_qp,
106                                UWORD8 u1_num_frms,
107                                UWORD8 u1_model_used,
108                                WORD8 *pi1_frame_index,
109                                model_coeff *pmc_model_coeff,
110                                model_coeff *pmc_model_coeff_lin,
111                                model_coeff *pmc_model_coeff_lin_wo_int,
112                                rc_rd_model_t *ps_rd_model)
113{
114    UWORD32 i;
115    UWORD8 u1_num_frms_used = 0;
116    UWORD8 u1_frm_indx;
117
118    float sum_y = 0;
119    float sum_x_y = 0;
120    float sum_x2_y = 0;
121    float sum_x = 0;
122    float sum_x2 = 0;
123    float sum_x3 = 0;
124    float sum_x4 = 0;
125
126    float x0, y0;
127    float model_coeff_a = 0.0, model_coeff_b = 0.0, model_coeff_c = 0.0;
128
129#if !(ENABLE_QUAD_RC_MODEL||ENABLE_LIN_MODEL_WITH_INTERCEPT)
130    UNUSED(pu1_num_skips);
131    UNUSED(pmc_model_coeff);
132    UNUSED(pmc_model_coeff_lin);
133#endif
134
135    for(i = 0; i < u1_num_frms; i++)
136    {
137        if(-1 == pi1_frame_index[i])
138            continue;
139
140        u1_frm_indx = (UWORD8)pi1_frame_index[i];
141
142        y0 = (float)(pi4_res_bits[u1_frm_indx]);
143        x0 = (float)(pi4_sad_h264[u1_frm_indx]
144                        / (float)pui_avg_mpeg2_qp[u1_frm_indx]);
145
146        sum_y += y0;
147        sum_x_y += x0 * y0;
148        sum_x2_y += x0 * x0 * y0;
149        sum_x += x0;
150        sum_x2 += x0 * x0;
151        sum_x3 += x0 * x0 * x0;
152        sum_x4 += x0 * x0 * x0 * x0;
153        u1_num_frms_used++;
154    }
155
156    sum_y /= u1_num_frms_used;
157    sum_x_y /= u1_num_frms_used;
158    sum_x2_y /= u1_num_frms_used;
159    sum_x /= u1_num_frms_used;
160    sum_x2 /= u1_num_frms_used;
161    sum_x3 /= u1_num_frms_used;
162    sum_x4 /= u1_num_frms_used;
163
164    {
165        UWORD8 u1_curr_frame_index;
166        UWORD8 u1_avgqp_prvfrm;
167        UWORD32 u4_prevfrm_bits, u4_prevfrm_sad;
168
169        u1_curr_frame_index = ps_rd_model->u1_curr_frm_counter;
170        if(0 == u1_curr_frame_index)
171            u1_curr_frame_index = (MAX_FRAMES_MODELLED - 1);
172        else
173            u1_curr_frame_index--;
174
175        u1_avgqp_prvfrm = ps_rd_model->pu1_avg_qp[u1_curr_frame_index];
176        u4_prevfrm_bits = ps_rd_model->pi4_res_bits[u1_curr_frame_index];
177        u4_prevfrm_sad = ps_rd_model->pi4_sad[u1_curr_frame_index];
178
179        if(0 != u4_prevfrm_sad)
180            model_coeff_a = (float)(u4_prevfrm_bits * u1_avgqp_prvfrm)
181                            / u4_prevfrm_sad;
182        else
183            model_coeff_a = 0;
184
185        model_coeff_b = 0;
186        model_coeff_c = 0;
187
188        pmc_model_coeff_lin_wo_int[0] = model_coeff_b;
189        pmc_model_coeff_lin_wo_int[1] = model_coeff_a;
190        pmc_model_coeff_lin_wo_int[2] = model_coeff_c;
191    }
192
193    return u1_model_used;
194}
195
196static void irc_update_frame_rd_model(rc_rd_model_t *ps_rd_model)
197{
198    WORD8 pi1_frame_index[MAX_FRAMES_MODELLED],
199                    pi1_frame_index_initial[MAX_FRAMES_MODELLED];
200
201    UWORD8 u1_num_skips_temp;
202    UWORD8 u1_avg_mpeg2_qp_temp, u1_min_mpeg2_qp, u1_max_mpeg2_qp;
203    UWORD8 u1_num_frms_input, u1_num_active_frames, u1_reject_frame;
204    UWORD32 u4_num_skips;
205
206    UWORD8 u1_min2_mpeg2_qp, u1_max2_mpeg2_qp;
207    UWORD8 u1_min_qp_frame_indx, u1_max_qp_frame_indx;
208    UWORD8 pu1_num_frames[MPEG2_QP_ELEM];
209    model_coeff model_coeff_array[3], model_coeff_array_lin[3],
210                    model_coeff_array_lin_wo_int[3];
211    UWORD32 i;
212    UWORD8 u1_curr_frame_index;
213
214    u1_curr_frame_index = ps_rd_model->u1_curr_frm_counter;
215
216    ps_rd_model->u1_model_used = PREV_FRAME_MODEL;
217
218    if(0 == u1_curr_frame_index)
219        u1_curr_frame_index = (MAX_FRAMES_MODELLED - 1);
220    else
221        u1_curr_frame_index--;
222
223    /************************************************************************/
224    /* Rearrange data to be fed into a Linear Regression Module             */
225    /* Module finds a,b,c such that                                         */
226    /*      y = ax + bx^2 + c                                               */
227    /************************************************************************/
228    u4_num_skips = 0;
229    u1_num_frms_input = 0;
230    memset(pu1_num_frames, 0, MPEG2_QP_ELEM);
231    memset(pi1_frame_index, -1, MAX_FRAMES_MODELLED);
232    u1_min_mpeg2_qp = MAX_MPEG2_QP;
233    u1_max_mpeg2_qp = 0;
234
235    u1_num_active_frames = ps_rd_model->u1_num_frms_in_model;
236    if(u1_num_active_frames > MAX_ACTIVE_FRAMES)
237    {
238        u1_num_active_frames = MAX_ACTIVE_FRAMES;
239    }
240
241    /************************************************************************/
242    /* Choose the set of Points to be used for MSE fit of Quadratic model   */
243    /* Points chosen are spread across the Qp range. Max of 2 points are    */
244    /* chosen for a Qp.                                                     */
245    /************************************************************************/
246    for(i = 0; i < u1_num_active_frames; i++)
247    {
248        u1_reject_frame = 0;
249        u1_num_skips_temp = ps_rd_model->pu1_num_skips[u1_curr_frame_index];
250        u1_avg_mpeg2_qp_temp = ps_rd_model->pu1_avg_qp[u1_curr_frame_index];
251
252        if((0 == u4_num_skips) && (0 != u1_num_skips_temp))
253            u1_reject_frame = 1;
254        if((1 == u4_num_skips) && (u1_num_skips_temp > 1))
255            u1_reject_frame = 1;
256        if(pu1_num_frames[u1_avg_mpeg2_qp_temp] >= 2)
257            u1_reject_frame = 1;
258
259        if(0 == i)
260            u1_reject_frame = 0;
261
262        if(0 == u1_reject_frame)
263        {
264            pi1_frame_index[u1_num_frms_input] = (WORD8)u1_curr_frame_index;
265            pu1_num_frames[u1_avg_mpeg2_qp_temp] += 1;
266
267            if(u1_min_mpeg2_qp > u1_avg_mpeg2_qp_temp)
268                u1_min_mpeg2_qp = u1_avg_mpeg2_qp_temp;
269            if(u1_max_mpeg2_qp < u1_avg_mpeg2_qp_temp)
270                u1_max_mpeg2_qp = u1_avg_mpeg2_qp_temp;
271
272            u1_num_frms_input++;
273        }
274
275        if(0 == u1_curr_frame_index)
276            u1_curr_frame_index = (MAX_FRAMES_MODELLED - 1);
277        else
278            u1_curr_frame_index--;
279    }
280
281    /************************************************************************/
282    /* Add Pivot Points to the Data set to be used for finding Quadratic    */
283    /* Model Coeffs. These will help in constraining the shape of  Quadratic*/
284    /* to adapt too much to the Local deviations.                           */
285    /************************************************************************/
286    u1_min2_mpeg2_qp = u1_min_mpeg2_qp;
287    u1_max2_mpeg2_qp = u1_max_mpeg2_qp;
288    u1_min_qp_frame_indx = INVALID_FRAME_INDEX;
289    u1_max_qp_frame_indx = INVALID_FRAME_INDEX;
290
291    /* Loop runnning over the Stored Frame Level Data
292     to find frames of MinQp and MaxQp */
293    for(; i < ps_rd_model->u1_num_frms_in_model; i++)
294    {
295        u1_num_skips_temp = ps_rd_model->pu1_num_skips[u1_curr_frame_index];
296        u1_avg_mpeg2_qp_temp = ps_rd_model->pu1_avg_qp[u1_curr_frame_index];
297
298        if(((0 == u4_num_skips) && (0 != u1_num_skips_temp))
299                        || ((1 == u4_num_skips) && (u1_num_skips_temp > 1)))
300            continue;
301
302        if(u1_min2_mpeg2_qp > u1_avg_mpeg2_qp_temp)
303        {
304            u1_min2_mpeg2_qp = u1_avg_mpeg2_qp_temp;
305            u1_min_qp_frame_indx = u1_curr_frame_index;
306        }
307        if(u1_max2_mpeg2_qp < u1_avg_mpeg2_qp_temp)
308        {
309            u1_max2_mpeg2_qp = u1_avg_mpeg2_qp_temp;
310            u1_max_qp_frame_indx = u1_curr_frame_index;
311        }
312        if(0 == u1_curr_frame_index)
313            u1_curr_frame_index = (MAX_FRAMES_MODELLED - 1);
314        else
315            u1_curr_frame_index--;
316    }
317
318    /* Add the Chosen Points to the regression data set */
319    if(INVALID_FRAME_INDEX != u1_min_qp_frame_indx)
320    {
321        pi1_frame_index[u1_num_frms_input] = (WORD8)u1_min_qp_frame_indx;
322        u1_num_frms_input++;
323    }
324    if(INVALID_FRAME_INDEX != u1_max_qp_frame_indx)
325    {
326        pi1_frame_index[u1_num_frms_input] = (WORD8)u1_max_qp_frame_indx;
327        u1_num_frms_input++;
328    }
329    memcpy(pi1_frame_index_initial, pi1_frame_index, MAX_FRAMES_MODELLED);
330
331    /***** Call the Module to Return the Coeffs for the Fed Data *****/
332    ps_rd_model->u1_model_used = find_model_coeffs(ps_rd_model->pi4_res_bits,
333                                                   ps_rd_model->pi4_sad,
334                                                   ps_rd_model->pu1_num_skips,
335                                                   ps_rd_model->pu1_avg_qp,
336                                                   u1_num_frms_input,
337                                                   ps_rd_model->u1_model_used,
338                                                   pi1_frame_index,
339                                                   model_coeff_array,
340                                                   model_coeff_array_lin,
341                                                   model_coeff_array_lin_wo_int,
342                                                   ps_rd_model);
343
344    ps_rd_model->model_coeff_b_lin_wo_int = model_coeff_array_lin_wo_int[0];
345    ps_rd_model->model_coeff_a_lin_wo_int = model_coeff_array_lin_wo_int[1];
346    ps_rd_model->model_coeff_c_lin_wo_int = model_coeff_array_lin_wo_int[2];
347}
348
349UWORD32 irc_estimate_bits_for_qp(rc_rd_model_t *ps_rd_model,
350                                 UWORD32 u4_estimated_sad,
351                                 UWORD8 u1_avg_qp)
352{
353  float fl_num_bits = 0;
354
355  fl_num_bits = ps_rd_model->model_coeff_a_lin_wo_int
356      * ((float)(u4_estimated_sad / u1_avg_qp));
357
358  return ((UWORD32)fl_num_bits);
359}
360
361UWORD8 irc_find_qp_for_target_bits(rc_rd_model_t *ps_rd_model,
362                                   UWORD32 u4_target_res_bits,
363                                   UWORD32 u4_estimated_sad,
364                                   UWORD8 u1_min_qp,
365                                   UWORD8 u1_max_qp)
366{
367    UWORD8 u1_qp;
368    float x_value = 1.0, f_qp;
369
370    ps_rd_model->u1_model_used = PREV_FRAME_MODEL;
371
372    {
373        x_value = (float)u4_target_res_bits
374                        / ps_rd_model->model_coeff_a_lin_wo_int;
375    }
376
377    if(0 != x_value)
378        f_qp = u4_estimated_sad / x_value;
379    else
380        f_qp = 255;
381
382    if(f_qp > 255)
383        f_qp = 255;
384
385    /* Truncating the QP to the Max and Min Qp values possible */
386    if(f_qp < u1_min_qp)
387        f_qp = u1_min_qp;
388    if(f_qp > u1_max_qp)
389        f_qp = u1_max_qp;
390
391    u1_qp = (UWORD8)(f_qp + 0.5);
392
393    return u1_qp;
394}
395
396void irc_add_frame_to_rd_model(rc_rd_model_t *ps_rd_model,
397                               UWORD32 i4_res_bits,
398                               UWORD8 u1_avg_mp2qp,
399                               UWORD32 i4_sad_h264,
400                               UWORD8 u1_num_skips)
401{
402    UWORD8 u1_curr_frame_index;
403    u1_curr_frame_index = ps_rd_model->u1_curr_frm_counter;
404
405    /*Insert the Present Frame Data into the RD Model State Memory*/
406    ps_rd_model->pi4_res_bits[u1_curr_frame_index] = i4_res_bits;
407    ps_rd_model->pi4_sad[u1_curr_frame_index] = i4_sad_h264;
408    ps_rd_model->pu1_num_skips[u1_curr_frame_index] = u1_num_skips;
409    ps_rd_model->pu1_avg_qp[u1_curr_frame_index] = u1_avg_mp2qp;
410
411    ps_rd_model->u1_curr_frm_counter++;
412    if(MAX_FRAMES_MODELLED == ps_rd_model->u1_curr_frm_counter)
413        ps_rd_model->u1_curr_frm_counter = 0;
414
415    if(ps_rd_model->u1_num_frms_in_model < ps_rd_model->u1_max_frms_to_model)
416    {
417        ps_rd_model->u1_num_frms_in_model++;
418    }
419    irc_update_frame_rd_model(ps_rd_model);
420}
421
422/*****************************************************************************
423 *Function Name : irc_calc_per_frm_bits
424 *Description   :
425 *Inputs        : pu2_num_pics_of_a_pic_type
426 *                  -  pointer to RC api pointer
427 *                pu2_num_pics_of_a_pic_type
428 *                  -  N1, N2,...Nk
429 *                pu1_update_pic_type_model
430 *                  -  flag which tells whether or not to update model
431 *                     coefficients of a particular pic-type
432 *                u1_num_pic_types
433 *                  - value of k
434 *                pu4_num_skip_of_a_pic_type
435 *                  - the number of skips of that pic-type. It "may" be used to
436 *                    update the model coefficients at a later point. Right now
437 *                    it is not being used at all.
438 *                u1_base_pic_type
439 *                  - base pic type index wrt which alpha & beta are calculated
440 *                pfl_gamma
441 *                  - gamma_i = beta_i / alpha_i
442 *                pfl_eta
443 *                  -
444 *                u1_curr_pic_type
445 *                  - the current pic-type for which the targetted bits need to
446 *                    be computed
447 *                u4_bits_for_sub_gop
448 *                 - the number of bits to be consumed for the remaining part of
449 *                   sub-gop
450 *                u4_curr_estimated_sad
451 *                 -
452 *                pu1_curr_pic_type_qp
453 *                  -  output of this function
454 *****************************************************************************/
455
456WORD32 irc_calc_per_frm_bits(rc_rd_model_t *ps_rd_model,
457                             UWORD16 *pu2_num_pics_of_a_pic_type,
458                             UWORD8 *pu1_update_pic_type_model,
459                             UWORD8 u1_num_pic_types,
460                             UWORD32 *pu4_num_skip_of_a_pic_type,
461                             UWORD8 u1_base_pic_type,
462                             float *pfl_gamma,
463                             float *pfl_eta,
464                             UWORD8 u1_curr_pic_type,
465                             UWORD32 u4_bits_for_sub_gop,
466                             UWORD32 u4_curr_estimated_sad,
467                             UWORD8 *pu1_curr_pic_type_qp)
468{
469    WORD32 i4_per_frm_bits_Ti;
470    UWORD8 u1_i;
471    rc_rd_model_t *ps_rd_model_of_pic_type;
472
473    UNUSED(pu4_num_skip_of_a_pic_type);
474    UNUSED(u1_base_pic_type);
475
476    /* First part of this function updates all the model coefficients */
477    /*for all the pic-types */
478    {
479        for(u1_i = 0; u1_i < u1_num_pic_types; u1_i++)
480        {
481            if((0 != pu2_num_pics_of_a_pic_type[u1_i])
482                            && (1 == pu1_update_pic_type_model[u1_i]))
483            {
484                irc_update_frame_rd_model(&ps_rd_model[u1_i]);
485            }
486        }
487    }
488
489    /*
490     * The second part of this function deals with solving the
491     * equation using all the pic-types models
492     */
493    {
494        UWORD8 u1_combined_model_used;
495
496        /* solve the equation */
497        {
498            model_coeff eff_A;
499            float fl_sad_by_qp_base;
500            float fl_sad_by_qp_curr_frm = 1.0;
501            float fl_qp_curr_frm;
502            float fl_bits_for_curr_frm = 0;
503
504
505
506            /* If the combined chosen model is linear model without an intercept */
507
508            u1_combined_model_used = PREV_FRAME_MODEL;
509            {
510                eff_A = 0.0;
511
512                for(u1_i = 0; u1_i < u1_num_pic_types; u1_i++)
513                {
514                    ps_rd_model_of_pic_type = ps_rd_model + u1_i;
515
516                    eff_A += ((pfl_eta[u1_i]
517                               + pu2_num_pics_of_a_pic_type[u1_i]- 1)
518                               * ps_rd_model_of_pic_type->model_coeff_a_lin_wo_int
519                               * pfl_gamma[u1_i]);
520                }
521
522                fl_sad_by_qp_base = u4_bits_for_sub_gop / eff_A;
523
524                fl_sad_by_qp_curr_frm = fl_sad_by_qp_base
525                                * pfl_gamma[u1_curr_pic_type]
526                                * pfl_eta[u1_curr_pic_type];
527
528                ps_rd_model_of_pic_type = ps_rd_model + u1_curr_pic_type;
529
530                fl_bits_for_curr_frm =
531                                ps_rd_model_of_pic_type->model_coeff_a_lin_wo_int
532                                                * fl_sad_by_qp_curr_frm;
533            }
534
535            /*
536             * Store the model that was finally used to calculate Qp.
537             * This is so that the same model is used in further calculations
538             * for this picture.
539             */
540            ps_rd_model_of_pic_type = ps_rd_model + u1_curr_pic_type;
541            ps_rd_model_of_pic_type->u1_model_used = u1_combined_model_used;
542
543            i4_per_frm_bits_Ti = (WORD32)(fl_bits_for_curr_frm + 0.5);
544
545            if(fl_sad_by_qp_curr_frm > 0)
546                fl_qp_curr_frm = (float)u4_curr_estimated_sad
547                                / fl_sad_by_qp_curr_frm;
548            else
549                fl_qp_curr_frm = 255;
550
551            if(fl_qp_curr_frm > 255)
552                fl_qp_curr_frm = 255;
553
554            *pu1_curr_pic_type_qp = (fl_qp_curr_frm + 0.5);
555
556        }
557    }
558    return (i4_per_frm_bits_Ti);
559}
560
561model_coeff irc_get_linear_coefficient(rc_rd_model_t *ps_rd_model)
562{
563    return (ps_rd_model->model_coeff_a_lin_wo_int);
564}
565
566
567