xref: /aosp_15_r20/external/libavc/encoder/svc/isvce_sub_pic_rc.c (revision 495ae853bb871d1e5a258cb02c2cc13cde8ddb9a)
1 /******************************************************************************
2  *
3  * Copyright (C) 2022 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 *******************************************************************************
23 * @file
24 *  isvce_sub_pic_rc.c
25 *
26 * @brief
27 *  Contains functions used in sub-pic RC
28 *
29 *******************************************************************************
30 */
31 #include <stdbool.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <math.h>
35 
36 #include "ih264_typedefs.h"
37 #include "ih264_cavlc_tables.h"
38 #include "ih264_platform_macros.h"
39 #include "ithread.h"
40 #include "isvc_defs.h"
41 #include "isvc_structs.h"
42 #include "isvce_structs.h"
43 #include "isvce_defs.h"
44 #include "isvce_sub_pic_rc.h"
45 #include "isvce_sub_pic_rc_private_defs.h"
46 
47 /* Dependencies of 'irc_picture_type.h' */
48 #include "irc_mem_req_and_acq.h"
49 
50 /* Dependencies of 'irc_rate_control_api_structs' */
51 #include "irc_picture_type.h"
52 #include "irc_rd_model.h"
53 #include "irc_vbr_storage_vbv.h"
54 #include "irc_est_sad.h"
55 #include "irc_bit_allocation.h"
56 #include "irc_mb_model_based.h"
57 #include "irc_cbr_buffer_control.h"
58 #include "irc_vbr_str_prms.h"
59 #include "irc_common.h"
60 
61 #include "irc_rate_control_api_structs.h"
62 #include "irc_rate_control_api.h"
63 
64 /**
65 *******************************************************************************
66 *
67 * @brief
68 *  Returns size of buffers for storing subPicRC ctxt
69 *
70 * @returns  Size of buffers
71 *
72 *******************************************************************************
73 */
isvce_get_sub_pic_rc_ctxt_size(UWORD8 u1_num_spatial_layers,DOUBLE d_spatial_res_ratio,UWORD32 u4_wd,UWORD32 u4_ht)74 UWORD32 isvce_get_sub_pic_rc_ctxt_size(UWORD8 u1_num_spatial_layers, DOUBLE d_spatial_res_ratio,
75                                        UWORD32 u4_wd, UWORD32 u4_ht)
76 {
77     WORD32 i;
78 
79     UWORD32 u4_size = MAX_PROCESS_CTXT * sizeof(svc_sub_pic_rc_ctxt_t);
80 
81     u4_size += sizeof(sub_pic_rc_state_t);
82     u4_size += ithread_get_mutex_struct_size();
83 
84     for(i = u1_num_spatial_layers - 1; i >= 0; i--)
85     {
86         WORD32 i4_layer_wd =
87             (WORD32) ((DOUBLE) u4_wd / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - i)) +
88             0.99;
89         WORD32 i4_layer_ht =
90             ((DOUBLE) u4_ht / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - i)) + 0.99;
91         WORD32 i4_layer_mbs = (i4_layer_wd / MB_SIZE) * (i4_layer_ht / MB_SIZE);
92 
93         /* ps_mb_bits_info */
94         u4_size += i4_layer_mbs * sizeof(mb_bits_info_t);
95 
96 #if DUMP_SUB_PIC_RC_DATA
97         /* ps_mb_bits_actual */
98         u4_size += i4_layer_mbs * sizeof(mb_bits_info_t);
99 #endif
100     }
101 
102     return u4_size;
103 }
104 
isvce_sub_pic_rc_ctxt_init(isvce_codec_t * ps_codec,iv_mem_rec_t * ps_mem_rec)105 void isvce_sub_pic_rc_ctxt_init(isvce_codec_t *ps_codec, iv_mem_rec_t *ps_mem_rec)
106 {
107     sub_pic_rc_state_t *ps_sub_pic_rc_state;
108 
109     WORD32 i, j;
110 
111     DOUBLE d_spatial_res_ratio = ps_codec->s_cfg.s_svc_params.d_spatial_res_ratio;
112     UWORD8 u1_num_spatial_layers = ps_codec->s_cfg.s_svc_params.u1_num_spatial_layers;
113     UWORD32 u4_wd = ps_codec->s_cfg.u4_wd;
114     UWORD32 u4_ht = ps_codec->s_cfg.u4_ht;
115     UWORD8 *pu1_buf = ps_mem_rec->pv_base;
116     WORD64 i8_alloc_mem_size =
117         isvce_get_sub_pic_rc_ctxt_size(u1_num_spatial_layers, d_spatial_res_ratio, u4_wd, u4_ht);
118 
119     for(i = 0; i < MAX_PROCESS_CTXT; i++)
120     {
121         svc_sub_pic_rc_ctxt_t *ps_sub_pic_rc_ctxt = ps_codec->as_process[i].ps_sub_pic_rc_ctxt =
122             (svc_sub_pic_rc_ctxt_t *) pu1_buf;
123 
124         pu1_buf += sizeof(ps_sub_pic_rc_ctxt[0]);
125         i8_alloc_mem_size -= sizeof(ps_sub_pic_rc_ctxt[0]);
126 
127         if(0 == i)
128         {
129             ps_sub_pic_rc_ctxt->s_sub_pic_rc_constants.pv_state = ps_sub_pic_rc_state =
130                 (sub_pic_rc_state_t *) pu1_buf;
131             pu1_buf += sizeof(ps_sub_pic_rc_state[0]);
132             i8_alloc_mem_size -= sizeof(ps_sub_pic_rc_state[0]);
133 
134             ASSERT(i8_alloc_mem_size >= 0);
135             ASSERT(NULL != ps_codec->s_rate_control.apps_rate_control_api);
136             ASSERT(NULL != ps_codec->as_process->s_me_ctxt.pu1_mv_bits);
137 
138             ps_sub_pic_rc_state->s_svc_params = ps_codec->s_cfg.s_svc_params;
139             ps_sub_pic_rc_state->pu1_uev_codeword_to_bits_map = gau1_uev_codeword_to_bits_map;
140             ps_sub_pic_rc_state->pu1_sev_codeword_to_bits_map =
141                 ps_codec->as_process->s_me_ctxt.pu1_mv_bits;
142             ps_sub_pic_rc_state->e_rc_mode = ps_codec->s_cfg.e_rc_mode;
143 
144             ps_sub_pic_rc_state->pv_bits_accumulator_mutex = (void *) pu1_buf;
145             pu1_buf += ithread_get_mutex_struct_size();
146             i8_alloc_mem_size -= ithread_get_mutex_struct_size();
147             ithread_mutex_init(ps_sub_pic_rc_state->pv_bits_accumulator_mutex);
148 
149             for(j = u1_num_spatial_layers - 1; j >= 0; j--)
150             {
151                 sub_pic_rc_layer_state_t *ps_layer_state =
152                     &ps_sub_pic_rc_state->as_sub_pic_rc_layer_states[j];
153 
154                 WORD32 i4_layer_wd =
155                     (WORD32) ((DOUBLE) u4_wd /
156                               pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - j)) +
157                     0.99;
158                 WORD32 i4_layer_ht =
159                     ((DOUBLE) u4_ht / pow(d_spatial_res_ratio, u1_num_spatial_layers - 1 - j)) +
160                     0.99;
161                 WORD32 i4_layer_mbs = (i4_layer_wd / MB_SIZE) * (i4_layer_ht / MB_SIZE);
162 
163                 ps_layer_state->i4_wd = i4_layer_wd;
164                 ps_layer_state->i4_ht = i4_layer_ht;
165                 ps_layer_state->i4_num_mbs = i4_layer_mbs;
166                 ps_layer_state->pv_layer_rc_ctxt =
167                     ps_codec->s_rate_control.apps_rate_control_api[j];
168                 ps_layer_state->ps_mb_bits_info = (mb_bits_info_t *) pu1_buf;
169                 pu1_buf += i4_layer_mbs * sizeof(ps_layer_state->ps_mb_bits_info[0]);
170                 i8_alloc_mem_size -= i4_layer_mbs * sizeof(ps_layer_state->ps_mb_bits_info[0]);
171 
172                 ASSERT(i8_alloc_mem_size >= 0);
173 
174 #if DUMP_SUB_PIC_RC_DATA
175                 ps_layer_state->ps_mb_bits_actual = (mb_bits_info_t *) pu1_buf;
176                 pu1_buf += i4_layer_mbs * sizeof(ps_layer_state->ps_mb_bits_actual[0]);
177                 i8_alloc_mem_size -= i4_layer_mbs * sizeof(ps_layer_state->ps_mb_bits_actual[0]);
178 
179                 ASSERT(i8_alloc_mem_size >= 0);
180 
181                 {
182                     UWORD8 au1_file_path[MAX_SUB_PIC_RC_DUMP_FILE_PATH_LENGTH + 1];
183 
184                     sprintf((WORD8 *) au1_file_path, "%ssubPicRC%1d.txt", SUB_PIC_RC_DUMP_FILE_PATH,
185                             j);
186 
187                     ps_layer_state->ps_data_dump_file = fopen(au1_file_path, "w");
188 
189                     ASSERT(NULL != ps_layer_state->ps_data_dump_file);
190                 }
191 #endif
192             }
193         }
194         else
195         {
196             svc_sub_pic_rc_ctxt_t *ps_sub_pic_rc_ctxt_src =
197                 ps_codec->as_process[0].ps_sub_pic_rc_ctxt;
198             svc_sub_pic_rc_ctxt_t *ps_sub_pic_rc_ctxt_dst =
199                 ps_codec->as_process[i].ps_sub_pic_rc_ctxt;
200             sub_pic_rc_state_t *ps_proc0_state =
201                 (sub_pic_rc_state_t *) ps_sub_pic_rc_ctxt_src->s_sub_pic_rc_constants.pv_state;
202 
203             ps_sub_pic_rc_ctxt_dst->s_sub_pic_rc_constants.pv_state = ps_proc0_state;
204         }
205     }
206 }
207 
isvce_sub_pic_rc_qp_params_init(sub_pic_rc_qp_params_t * ps_qp_params,UWORD8 u1_min_qp,UWORD8 u1_max_qp)208 static FORCEINLINE void isvce_sub_pic_rc_qp_params_init(sub_pic_rc_qp_params_t *ps_qp_params,
209                                                         UWORD8 u1_min_qp, UWORD8 u1_max_qp)
210 {
211     ps_qp_params->u1_min_qp = u1_min_qp;
212     ps_qp_params->u1_max_qp = u1_max_qp;
213     ps_qp_params->pu4_qp_to_qscale_map = gau4_qp_to_qscale_map;
214     ps_qp_params->pu1_qscale_to_qp_map = gau1_qscale_to_qp_map;
215 }
216 
isvce_sub_pic_rc_ctxt_layer_init(svc_sub_pic_rc_ctxt_t * ps_sub_pic_rc_ctxt)217 void isvce_sub_pic_rc_ctxt_layer_init(svc_sub_pic_rc_ctxt_t *ps_sub_pic_rc_ctxt)
218 {
219     sub_pic_rc_layer_state_t *ps_layer_state;
220 
221     svc_sub_pic_rc_constants_t *ps_sub_pic_rc_constants =
222         &ps_sub_pic_rc_ctxt->s_sub_pic_rc_constants;
223     svc_sub_pic_rc_variables_t *ps_sub_pic_rc_variables =
224         &ps_sub_pic_rc_ctxt->s_sub_pic_rc_variables;
225     sub_pic_rc_state_t *ps_sub_pic_rc_state =
226         (sub_pic_rc_state_t *) ps_sub_pic_rc_constants->pv_state;
227 
228     UWORD8 u1_spatial_layer_id = ps_sub_pic_rc_variables->s_layer_variables.u1_spatial_layer_id;
229 
230     ps_layer_state = &ps_sub_pic_rc_state->as_sub_pic_rc_layer_states[u1_spatial_layer_id];
231 
232     memset(&ps_layer_state->s_cumulative_mb_bits, 0, sizeof(ps_layer_state->s_cumulative_mb_bits));
233     ps_layer_state->u4_num_mbs_sampled = 0;
234 
235     /* Frames with frameNum=0 are usually IDR's. RC model will be reset for IDR's.
236      */
237     /* Hence, using VBVBufSize as a proxy for estimated bits */
238     if(0 == ps_sub_pic_rc_variables->s_layer_variables.i4_frame_num)
239     {
240         ps_layer_state->u4_allocated_bits =
241             irc_get_vbv_buf_size(ps_layer_state->pv_layer_rc_ctxt) / 10.;
242     }
243     else
244     {
245         ps_layer_state->u4_allocated_bits =
246             irc_get_prev_frm_est_bits(ps_layer_state->pv_layer_rc_ctxt);
247     }
248 
249     isvce_sub_pic_rc_qp_params_init(&ps_layer_state->s_qp_params,
250                                     ps_sub_pic_rc_variables->s_layer_variables.u1_min_qp,
251                                     ps_sub_pic_rc_variables->s_layer_variables.u1_max_qp);
252 }
253 
isvce_sub_pic_rc_get_res_pred_flag_bits(svc_sub_pic_rc_variables_t * ps_sub_pic_rc_variables,sub_pic_rc_state_t * ps_sub_pic_rc_state)254 static FORCEINLINE UWORD32 isvce_sub_pic_rc_get_res_pred_flag_bits(
255     svc_sub_pic_rc_variables_t *ps_sub_pic_rc_variables, sub_pic_rc_state_t *ps_sub_pic_rc_state)
256 {
257     isvce_mb_info_t *ps_mb_info = ps_sub_pic_rc_variables->s_mb_variables.ps_mb_info;
258 
259     UNUSED(ps_sub_pic_rc_state);
260 
261     return (ENABLE_RESIDUAL_PREDICTION && !ps_mb_info->u1_is_intra);
262 }
263 
isvce_sub_pic_rc_get_cbp_bits(svc_sub_pic_rc_variables_t * ps_sub_pic_rc_variables,sub_pic_rc_state_t * ps_sub_pic_rc_state)264 static FORCEINLINE UWORD32 isvce_sub_pic_rc_get_cbp_bits(
265     svc_sub_pic_rc_variables_t *ps_sub_pic_rc_variables, sub_pic_rc_state_t *ps_sub_pic_rc_state)
266 {
267     isvce_mb_info_t *ps_mb_info = ps_sub_pic_rc_variables->s_mb_variables.ps_mb_info;
268 
269     UWORD32 u4_cbp = ps_sub_pic_rc_variables->s_mb_variables.u4_cbp;
270     bool b_use_inter_cbp_map = !ps_mb_info->u1_is_intra || ps_mb_info->u1_base_mode_flag;
271 
272     return ps_sub_pic_rc_state
273         ->pu1_uev_codeword_to_bits_map[gu1_cbp_map_tables[u4_cbp][b_use_inter_cbp_map]];
274 }
275 
isvce_sub_pic_rc_get_mb_type_bits(svc_sub_pic_rc_variables_t * ps_sub_pic_rc_variables,sub_pic_rc_state_t * ps_sub_pic_rc_state)276 static FORCEINLINE UWORD32 isvce_sub_pic_rc_get_mb_type_bits(
277     svc_sub_pic_rc_variables_t *ps_sub_pic_rc_variables, sub_pic_rc_state_t *ps_sub_pic_rc_state)
278 {
279     UWORD32 u4_mb_type;
280 
281     isvce_mb_info_t *ps_mb_info = ps_sub_pic_rc_variables->s_mb_variables.ps_mb_info;
282 
283     UWORD32 u4_cbp = ps_sub_pic_rc_variables->s_mb_variables.u4_cbp;
284     UWORD32 au4_cbps[NUM_SP_COMPONENTS] = {u4_cbp & 15, u4_cbp >> 4};
285 
286     switch(ps_mb_info->u2_mb_type)
287     {
288         case I16x16:
289         {
290             u4_mb_type = ps_mb_info->s_intra_pu.s_i16x16_mode_data.u1_mode + 1 +
291                          (au4_cbps[UV] << 2) + (au4_cbps[Y] == 15) * 12;
292 
293             break;
294         }
295         case I4x4:
296         {
297             u4_mb_type = 5 * (ps_sub_pic_rc_variables->s_layer_variables.i4_slice_type != ISLICE);
298 
299             break;
300         }
301         case P16x16:
302         {
303             u4_mb_type = 0;
304 
305             break;
306         }
307         default:
308         {
309             return 0;
310         }
311     }
312 
313     return ps_sub_pic_rc_state->pu1_uev_codeword_to_bits_map[u4_mb_type];
314 }
315 
isvce_sub_pic_rc_get_mb_pred_bits(svc_sub_pic_rc_variables_t * ps_sub_pic_rc_variables,sub_pic_rc_state_t * ps_sub_pic_rc_state)316 static FORCEINLINE UWORD32 isvce_sub_pic_rc_get_mb_pred_bits(
317     svc_sub_pic_rc_variables_t *ps_sub_pic_rc_variables, sub_pic_rc_state_t *ps_sub_pic_rc_state)
318 {
319     WORD32 i;
320 
321     isvce_mb_info_t *ps_mb_info = ps_sub_pic_rc_variables->s_mb_variables.ps_mb_info;
322 
323     UWORD32 u4_bits = 0;
324 
325     switch(ps_mb_info->u2_mb_type)
326     {
327         case I16x16:
328         {
329             /* intra_chroma_pred_mode */
330             u4_bits +=
331                 ps_sub_pic_rc_state
332                     ->pu1_uev_codeword_to_bits_map[ps_mb_info->s_intra_pu.u1_chroma_intra_mode];
333 
334             break;
335         }
336         case I4x4:
337         {
338             intra4x4_mode_data_t *ps_i4x4_mode_data = ps_mb_info->s_intra_pu.as_i4x4_mode_data;
339 
340             for(i = 0; i < MAX_TU_IN_MB; i++)
341             {
342                 /* prev_intra4x4_pred_mode_flag */
343                 u4_bits += 1;
344 
345                 /* rem_intra4x4_pred_mode */
346                 u4_bits +=
347                     3 * (ps_i4x4_mode_data[i].u1_mode != ps_i4x4_mode_data[i].u1_predicted_mode);
348             }
349 
350             /* intra_chroma_pred_mode */
351             u4_bits +=
352                 ps_sub_pic_rc_state
353                     ->pu1_uev_codeword_to_bits_map[ps_mb_info->s_intra_pu.u1_chroma_intra_mode];
354 
355             break;
356         }
357         case P16x16:
358         {
359             mv_t s_mvd;
360 
361             /* motion_prediction_flag_l0 */
362             u4_bits += USE_ILP_MV_AS_MVP;
363 
364             /* ref_idx_l0 */
365             if(2 == ps_sub_pic_rc_variables->s_layer_variables.i4_max_num_reference_frames)
366             {
367                 u4_bits += 1;
368             }
369             else if(2 < ps_sub_pic_rc_variables->s_layer_variables.i4_max_num_reference_frames)
370             {
371                 u4_bits += ps_sub_pic_rc_state->pu1_uev_codeword_to_bits_map
372                                [ps_mb_info->as_pu->as_me_info[L0].i1_ref_idx];
373             }
374 
375             /* mvd_l0 */
376             s_mvd.i2_mvx = ps_mb_info->as_pu->as_me_info[L0].s_mv.i2_mvx -
377                            ps_sub_pic_rc_variables->s_mb_variables
378                                .aps_mvps[ps_mb_info->as_pu->au1_mvp_idx[L0]]
379                                ->s_mv.i2_mvx;
380             s_mvd.i2_mvy = ps_mb_info->as_pu->as_me_info[L0].s_mv.i2_mvy -
381                            ps_sub_pic_rc_variables->s_mb_variables
382                                .aps_mvps[ps_mb_info->as_pu->au1_mvp_idx[L0]]
383                                ->s_mv.i2_mvy;
384             u4_bits += ps_sub_pic_rc_state->pu1_sev_codeword_to_bits_map[s_mvd.i2_mvx];
385             u4_bits += ps_sub_pic_rc_state->pu1_sev_codeword_to_bits_map[s_mvd.i2_mvy];
386 
387             break;
388         }
389         default:
390         {
391             break;
392         }
393     }
394 
395     return u4_bits;
396 }
397 
ihevce_svc_sub_pic_rc_set_header_bits(svc_sub_pic_rc_ctxt_t * ps_sub_pic_rc_ctxt)398 static void ihevce_svc_sub_pic_rc_set_header_bits(svc_sub_pic_rc_ctxt_t *ps_sub_pic_rc_ctxt)
399 {
400     sub_pic_rc_layer_state_t *ps_layer_state;
401     mb_bits_info_t *ps_mb_bits_info;
402 
403     UWORD32 u4_mb_idx;
404 
405     svc_sub_pic_rc_constants_t *ps_sub_pic_rc_constants =
406         &ps_sub_pic_rc_ctxt->s_sub_pic_rc_constants;
407     svc_sub_pic_rc_variables_t *ps_sub_pic_rc_variables =
408         &ps_sub_pic_rc_ctxt->s_sub_pic_rc_variables;
409     sub_pic_rc_state_t *ps_sub_pic_rc_state =
410         (sub_pic_rc_state_t *) ps_sub_pic_rc_constants->pv_state;
411     isvce_mb_info_t *ps_mb_info = ps_sub_pic_rc_variables->s_mb_variables.ps_mb_info;
412 
413     UWORD8 u1_spatial_layer_id = ps_sub_pic_rc_variables->s_layer_variables.u1_spatial_layer_id;
414 
415     ps_layer_state = &ps_sub_pic_rc_state->as_sub_pic_rc_layer_states[u1_spatial_layer_id];
416     u4_mb_idx = ps_sub_pic_rc_variables->s_mb_variables.s_mb_pos.i4_abscissa +
417                 ps_sub_pic_rc_variables->s_mb_variables.s_mb_pos.i4_ordinate *
418                     (ps_layer_state->i4_wd / MB_SIZE);
419     ps_mb_bits_info = &ps_layer_state->ps_mb_bits_info[u4_mb_idx];
420 
421     /* Hypotheses used for header bits estimation - */
422     /* 1. mb_skip_run, base_mode_flag, mb_type, mb_pred, residual_prediction_flag,
423      * and cbp */
424     /*    are considered as contibuting to header bits. */
425     /* 2. mb_skip_run = 1 bit */
426     /* 3. base_mode_flag = 1 bit */
427     /* 4. mb_type = LUT mapping mbType to corresponding ue(v) */
428     /* 5. mb_pred.I4x4 = 1 bit for 16 'prev_intra4x4_pred_mode_flag';  */
429     /*                   3 bits for each explicitly signaled
430      * 'rem_intra4x4_pred_mode' */
431     /* 6. mb_pred.Inter = 1 bit for 'motion_prediction_flag_l0' and
432      * 'motion_prediction_flag_l1', when necessary; */
433     /*                    mvbits LUT for 'mvd_l0' and 'mvd_l1' */
434     /* 7. mb_pred.intra_chroma_pred_mode = LUT mapping intra_chroma_pred_mode to
435      * corresponding ue(v) */
436     /* 8. residual_prediction_flag = 1 bit */
437     /* 9. coded_block_pattern = LUT mapping mbType to corresponding me(v) */
438 
439     /* mb_skip_run is assumed to be either 0 or 1 */
440     ps_mb_bits_info->i8_header_bits += 1;
441 
442     /* 'base_mode_flag' */
443     if((ENABLE_ILP_MV || ENABLE_IBL_MODE) && u1_spatial_layer_id)
444     {
445         ps_mb_bits_info->i8_header_bits += 1;
446 
447         if(ps_mb_info->u1_base_mode_flag)
448         {
449             /* 'residual_prediction_flag' */
450             ps_mb_bits_info->i8_header_bits += isvce_sub_pic_rc_get_res_pred_flag_bits(
451                 ps_sub_pic_rc_variables, ps_sub_pic_rc_state);
452 
453             /* 'coded_block_pattern' */
454             ps_mb_bits_info->i8_header_bits +=
455                 isvce_sub_pic_rc_get_cbp_bits(ps_sub_pic_rc_variables, ps_sub_pic_rc_state);
456 
457             return;
458         }
459     }
460 
461     /* 'mb_type' */
462     ps_mb_bits_info->i8_header_bits +=
463         isvce_sub_pic_rc_get_mb_type_bits(ps_sub_pic_rc_variables, ps_sub_pic_rc_state);
464 
465     if(PSKIP == ps_mb_info->u2_mb_type)
466     {
467         return;
468     }
469 
470     /* 'mb_pred' */
471     ps_mb_bits_info->i8_header_bits +=
472         isvce_sub_pic_rc_get_mb_pred_bits(ps_sub_pic_rc_variables, ps_sub_pic_rc_state);
473 
474     /* 'residual_prediction_flag' */
475     ps_mb_bits_info->i8_header_bits +=
476         isvce_sub_pic_rc_get_res_pred_flag_bits(ps_sub_pic_rc_variables, ps_sub_pic_rc_state);
477 }
478 
isvce_sub_pic_rc_get_tu_residual_bits(svc_sub_pic_rc_variables_t * ps_sub_pic_rc_variables,WORD32 i4_coeff_start_idx,UWORD8 u1_num_coded_coeffs,UWORD8 u1_num_coeffs,bool b_is_chroma)479 static FORCEINLINE UWORD32 isvce_sub_pic_rc_get_tu_residual_bits(
480     svc_sub_pic_rc_variables_t *ps_sub_pic_rc_variables, WORD32 i4_coeff_start_idx,
481     UWORD8 u1_num_coded_coeffs, UWORD8 u1_num_coeffs, bool b_is_chroma)
482 {
483     WORD32 i;
484     UWORD32 u4_num_bits;
485 
486     UWORD32 u4_bits = 0;
487     WORD16 *pi2_coeff =
488         ((WORD16 *) ps_sub_pic_rc_variables->s_mb_variables.as_quant_coeffs[b_is_chroma ? UV : Y]
489              .pv_data) +
490         i4_coeff_start_idx;
491 
492     if(0 == u1_num_coded_coeffs)
493     {
494         return 0;
495     }
496 
497     GETRANGE(u4_num_bits, u1_num_coded_coeffs);
498     u4_bits += u4_num_bits;
499 
500     for(i = 0; i < u1_num_coeffs; i++)
501     {
502         if(pi2_coeff[i])
503         {
504             GETRANGE(u4_num_bits, pi2_coeff[i]);
505             u4_bits += u4_num_bits;
506         }
507     }
508     return u4_bits;
509 }
510 
ihevce_svc_sub_pic_rc_set_texture_bits(svc_sub_pic_rc_ctxt_t * ps_sub_pic_rc_ctxt)511 static void ihevce_svc_sub_pic_rc_set_texture_bits(svc_sub_pic_rc_ctxt_t *ps_sub_pic_rc_ctxt)
512 {
513     sub_pic_rc_layer_state_t *ps_layer_state;
514     mb_bits_info_t *ps_mb_bits_info;
515 
516     UWORD32 u4_mb_idx;
517     WORD32 i, j;
518 
519     svc_sub_pic_rc_constants_t *ps_sub_pic_rc_constants =
520         &ps_sub_pic_rc_ctxt->s_sub_pic_rc_constants;
521     svc_sub_pic_rc_variables_t *ps_sub_pic_rc_variables =
522         &ps_sub_pic_rc_ctxt->s_sub_pic_rc_variables;
523     sub_pic_rc_state_t *ps_sub_pic_rc_state =
524         (sub_pic_rc_state_t *) ps_sub_pic_rc_constants->pv_state;
525     isvce_mb_info_t *ps_mb_info = ps_sub_pic_rc_variables->s_mb_variables.ps_mb_info;
526 
527     UWORD8 u1_spatial_layer_id = ps_sub_pic_rc_variables->s_layer_variables.u1_spatial_layer_id;
528     UWORD32 au4_cbps[NUM_SP_COMPONENTS] = {ps_sub_pic_rc_variables->s_mb_variables.u4_cbp & 15,
529                                            ps_sub_pic_rc_variables->s_mb_variables.u4_cbp >> 4};
530 
531     if(0 == ps_sub_pic_rc_variables->s_mb_variables.u4_cbp)
532     {
533         return;
534     }
535 
536     if(MIN_TU_SIZE != ps_mb_info->u1_tx_size)
537     {
538         return;
539     }
540 
541     ps_layer_state = &ps_sub_pic_rc_state->as_sub_pic_rc_layer_states[u1_spatial_layer_id];
542     u4_mb_idx = ps_sub_pic_rc_variables->s_mb_variables.s_mb_pos.i4_abscissa +
543                 ps_sub_pic_rc_variables->s_mb_variables.s_mb_pos.i4_ordinate *
544                     (ps_layer_state->i4_wd / MB_SIZE);
545     ps_mb_bits_info = &ps_layer_state->ps_mb_bits_info[u4_mb_idx];
546 
547     /* Hypotheses used for texture bits estimation - */
548     /* 1. Only level information is considered. */
549     /* 2. nnz is used as a proxy for coeff_token. */
550     /* 3. Both of the above are assumed coded via i(n). */
551     if(au4_cbps[Y])
552     {
553         /* Y - DC */
554         if(I16x16 == ps_mb_info->u2_mb_type)
555         {
556             ps_mb_bits_info->i8_texture_bits += isvce_sub_pic_rc_get_tu_residual_bits(
557                 ps_sub_pic_rc_variables, 0, ps_sub_pic_rc_variables->s_mb_variables.apu1_nnzs[Y][0],
558                 NUM_COEFFS_IN_MIN_TU, false);
559         }
560 
561         for(i = 0; i < MIN_TU_IN_MB; i++)
562         {
563             if(au4_cbps[Y] & (1 << i))
564             {
565                 UWORD32 u4_csbp = (ps_mb_info->u4_csbp >> (4 * i)) & 15;
566 
567                 for(j = 0; j < NUM_4x4_IN_8x8; j++)
568                 {
569                     if(u4_csbp & (1 << j))
570                     {
571                         /* 1 added to account for DC TU */
572                         UWORD8 u1_blk_id = 1 + gau4_tu_zscan_id_to_rasterscan_id_map[i][j];
573                         UWORD8 u1_nnz =
574                             ps_sub_pic_rc_variables->s_mb_variables.apu1_nnzs[Y][u1_blk_id];
575 
576                         if(u1_nnz && (I16x16 == ps_mb_info->u2_mb_type))
577                         {
578                             u1_nnz -= !!(((WORD16 *) (ps_sub_pic_rc_variables->s_mb_variables
579                                                           .as_quant_coeffs[Y]
580                                                           .pv_data))[u1_blk_id - 1]);
581 
582                             ps_mb_bits_info->i8_texture_bits +=
583                                 isvce_sub_pic_rc_get_tu_residual_bits(
584                                     ps_sub_pic_rc_variables,
585                                     u1_blk_id * ps_sub_pic_rc_variables->s_mb_variables
586                                                     .as_quant_coeffs[Y]
587                                                     .i4_data_stride +
588                                         (I16x16 == ps_mb_info->u2_mb_type),
589                                     u1_nnz,
590                                     NUM_COEFFS_IN_MIN_TU - (I16x16 == ps_mb_info->u2_mb_type),
591                                     false);
592                         }
593                     }
594                 }
595             }
596         }
597     }
598 
599     if(au4_cbps[UV])
600     {
601         for(i = ((WORD32) U); i <= ((WORD32) V); i++)
602         {
603             bool b_is_v = (i == ((WORD32) V));
604 
605             ps_mb_bits_info->i8_texture_bits += isvce_sub_pic_rc_get_tu_residual_bits(
606                 ps_sub_pic_rc_variables, b_is_v * NUM_4x4_IN_8x8,
607                 ps_sub_pic_rc_variables->s_mb_variables
608                     .apu1_nnzs[UV][0 + b_is_v * (1 + NUM_4x4_IN_8x8)],
609                 NUM_4x4_IN_8x8, true);
610 
611             for(j = 0; j < NUM_4x4_IN_8x8; j++)
612             {
613                 UWORD8 u1_nnz = ps_sub_pic_rc_variables->s_mb_variables
614                                     .apu1_nnzs[UV][j + b_is_v * (1 + NUM_4x4_IN_8x8) + 1];
615 
616                 if(u1_nnz)
617                 {
618                     u1_nnz -=
619                         !!(((WORD16 *) (ps_sub_pic_rc_variables->s_mb_variables.as_quant_coeffs[UV]
620                                             .pv_data))[j + b_is_v * NUM_4x4_IN_8x8]);
621 
622                     ps_mb_bits_info->i8_texture_bits += isvce_sub_pic_rc_get_tu_residual_bits(
623                         ps_sub_pic_rc_variables,
624                         (j + b_is_v * NUM_4x4_IN_8x8 + 1) *
625                                 ps_sub_pic_rc_variables->s_mb_variables.as_quant_coeffs[UV]
626                                     .i4_data_stride +
627                             1,
628                         u1_nnz, NUM_COEFFS_IN_MIN_TU - 1, true);
629                 }
630             }
631         }
632     }
633 }
634 
isvce_sub_pic_rc_ctxt_update(svc_sub_pic_rc_ctxt_t * ps_sub_pic_rc_ctxt)635 void isvce_sub_pic_rc_ctxt_update(svc_sub_pic_rc_ctxt_t *ps_sub_pic_rc_ctxt)
636 {
637     sub_pic_rc_layer_state_t *ps_layer_state;
638     mb_bits_info_t *ps_mb_bits_info;
639 
640     UWORD32 u4_mb_idx;
641 
642     svc_sub_pic_rc_constants_t *ps_sub_pic_rc_constants =
643         &ps_sub_pic_rc_ctxt->s_sub_pic_rc_constants;
644     svc_sub_pic_rc_variables_t *ps_sub_pic_rc_variables =
645         &ps_sub_pic_rc_ctxt->s_sub_pic_rc_variables;
646     sub_pic_rc_state_t *ps_sub_pic_rc_state =
647         (sub_pic_rc_state_t *) ps_sub_pic_rc_constants->pv_state;
648     isvce_mb_info_t *ps_mb_info = ps_sub_pic_rc_variables->s_mb_variables.ps_mb_info;
649 
650     UWORD8 u1_spatial_layer_id = ps_sub_pic_rc_variables->s_layer_variables.u1_spatial_layer_id;
651     bool b_is_skip_mb = (PSKIP == ps_mb_info->u2_mb_type) || (BSKIP == ps_mb_info->u2_mb_type);
652 
653     if(!ENABLE_IN_FRAME_RC || (IVE_RC_NONE == ps_sub_pic_rc_state->e_rc_mode))
654     {
655         return;
656     }
657 
658     ps_layer_state = &ps_sub_pic_rc_state->as_sub_pic_rc_layer_states[u1_spatial_layer_id];
659     u4_mb_idx = ps_sub_pic_rc_variables->s_mb_variables.s_mb_pos.i4_abscissa +
660                 ps_sub_pic_rc_variables->s_mb_variables.s_mb_pos.i4_ordinate *
661                     (ps_layer_state->i4_wd / MB_SIZE);
662     ps_mb_bits_info = &ps_layer_state->ps_mb_bits_info[u4_mb_idx];
663 
664     memset(ps_mb_bits_info, 0, sizeof(ps_mb_bits_info[0]));
665 
666     if(!b_is_skip_mb)
667     {
668         ihevce_svc_sub_pic_rc_set_header_bits(ps_sub_pic_rc_ctxt);
669 
670         ihevce_svc_sub_pic_rc_set_texture_bits(ps_sub_pic_rc_ctxt);
671     }
672 
673     ithread_mutex_lock(ps_sub_pic_rc_state->pv_bits_accumulator_mutex);
674 
675     ps_layer_state->s_cumulative_mb_bits.i8_header_bits += ps_mb_bits_info->i8_header_bits;
676     ps_layer_state->s_cumulative_mb_bits.i8_texture_bits += ps_mb_bits_info->i8_texture_bits;
677     ps_layer_state->u4_num_mbs_sampled++;
678 
679     ithread_mutex_unlock(ps_sub_pic_rc_state->pv_bits_accumulator_mutex);
680 }
681 
isvce_sub_pic_rc_get_mb_qp(svc_sub_pic_rc_ctxt_t * ps_sub_pic_rc_ctxt,UWORD8 u1_cur_mb_qp)682 UWORD8 isvce_sub_pic_rc_get_mb_qp(svc_sub_pic_rc_ctxt_t *ps_sub_pic_rc_ctxt, UWORD8 u1_cur_mb_qp)
683 {
684     sub_pic_rc_layer_state_t *ps_layer_state;
685 
686     DOUBLE d_bit_consumption_ratio;
687     UWORD32 u4_frame_qscale;
688     UWORD8 u1_mb_qp;
689     UWORD32 u4_num_mbs_sampled;
690     WORD32 i4_cumulative_mb_bits;
691 
692     svc_sub_pic_rc_constants_t *ps_sub_pic_rc_constants =
693         &ps_sub_pic_rc_ctxt->s_sub_pic_rc_constants;
694     svc_sub_pic_rc_variables_t *ps_sub_pic_rc_variables =
695         &ps_sub_pic_rc_ctxt->s_sub_pic_rc_variables;
696     sub_pic_rc_state_t *ps_sub_pic_rc_state =
697         (sub_pic_rc_state_t *) ps_sub_pic_rc_constants->pv_state;
698 
699     UWORD8 u1_spatial_layer_id = ps_sub_pic_rc_variables->s_layer_variables.u1_spatial_layer_id;
700     UWORD8 u1_frame_qp = ps_sub_pic_rc_variables->s_layer_variables.u1_frame_qp;
701 
702     if(!ENABLE_IN_FRAME_RC || (IVE_RC_NONE == ps_sub_pic_rc_state->e_rc_mode))
703     {
704         return u1_cur_mb_qp;
705     }
706 
707     ps_layer_state = &ps_sub_pic_rc_state->as_sub_pic_rc_layer_states[u1_spatial_layer_id];
708 
709     ithread_mutex_lock(ps_sub_pic_rc_state->pv_bits_accumulator_mutex);
710 
711     u4_num_mbs_sampled = ps_layer_state->u4_num_mbs_sampled;
712 
713     if(u4_num_mbs_sampled <
714        ((UWORD32) ceil(MIN_SAMPLED_MB_RATIO * ((DOUBLE) ps_layer_state->i4_num_mbs))))
715     {
716         ithread_mutex_unlock(ps_sub_pic_rc_state->pv_bits_accumulator_mutex);
717 
718         return u1_cur_mb_qp;
719     }
720 
721     i4_cumulative_mb_bits = (WORD32) (ps_layer_state->s_cumulative_mb_bits.i8_header_bits +
722                                       ps_layer_state->s_cumulative_mb_bits.i8_texture_bits);
723 
724     if((0 == ps_layer_state->u4_allocated_bits) || (0 == u4_num_mbs_sampled))
725     {
726         d_bit_consumption_ratio = nextafter(BIT_RATIO_FOR_OVERCONSUMPTION, INFINITY);
727     }
728     else
729     {
730         d_bit_consumption_ratio =
731             (((DOUBLE) i4_cumulative_mb_bits) * ((DOUBLE) ps_layer_state->i4_num_mbs)) /
732             (((DOUBLE) ps_layer_state->u4_allocated_bits) * ((DOUBLE) u4_num_mbs_sampled));
733     }
734 
735     ithread_mutex_unlock(ps_sub_pic_rc_state->pv_bits_accumulator_mutex);
736 
737     if((d_bit_consumption_ratio > BIT_RATIO_FOR_OVERCONSUMPTION) ||
738        (d_bit_consumption_ratio < BIT_RATIO_FOR_UNDERCONSUMPTION))
739     {
740         u4_frame_qscale = ps_layer_state->s_qp_params.pu4_qp_to_qscale_map[u1_frame_qp] *
741                               d_bit_consumption_ratio +
742                           0.5;
743         u4_frame_qscale = CLIP3(ps_layer_state->s_qp_params.pu4_qp_to_qscale_map[0], MAX_SVC_QSCALE,
744                                 u4_frame_qscale);
745         u1_mb_qp = ps_layer_state->s_qp_params.pu1_qscale_to_qp_map[u4_frame_qscale];
746         u1_mb_qp = CLIP3(ps_layer_state->s_qp_params.u1_min_qp,
747                          ps_layer_state->s_qp_params.u1_max_qp, u1_mb_qp);
748         u1_mb_qp = CLIP3(MAX(MIN_H264_QP, ((WORD16) u1_cur_mb_qp) - MAX_MB_QP_DECREMENT),
749                          MIN(MAX_H264_QP, ((WORD16) u1_cur_mb_qp) + MAX_MB_QP_INCREMENT),
750                          ((WORD16) u1_mb_qp));
751         /* This ensures mb_qp_delta stays within the interval [-26, 25] */
752         u1_mb_qp = CLIP3(MAX(MIN_H264_QP, ((WORD16) u1_frame_qp) - MAX_FRAME_QP_DECREMENT),
753                          MIN(MAX_H264_QP, ((WORD16) u1_frame_qp) + MAX_FRAME_QP_INCREMENT),
754                          ((WORD16) u1_mb_qp));
755     }
756     else
757     {
758         u1_mb_qp = u1_cur_mb_qp;
759     }
760 
761     {
762         vbv_buf_status_e e_vbv_buf_status;
763         picture_type_e e_rc_pic_type;
764 
765         DOUBLE d_est_frame_bits;
766 
767         WORD32 i4_num_bits_to_prevent_vbv_underflow;
768 
769         d_est_frame_bits = ((DOUBLE) i4_cumulative_mb_bits) * ((DOUBLE) ps_layer_state->i4_num_mbs);
770         d_est_frame_bits /= u4_num_mbs_sampled;
771 
772         switch(ps_sub_pic_rc_variables->s_layer_variables.i4_slice_type)
773         {
774             case ISLICE:
775             {
776                 e_rc_pic_type = I_PIC;
777                 break;
778             }
779             case PSLICE:
780             {
781                 e_rc_pic_type = P_PIC;
782                 break;
783             }
784             default:
785             {
786                 e_rc_pic_type = B_PIC;
787                 break;
788             }
789         }
790 
791         e_vbv_buf_status =
792             irc_get_buffer_status(ps_layer_state->pv_layer_rc_ctxt, (WORD32) d_est_frame_bits,
793                                   e_rc_pic_type, &i4_num_bits_to_prevent_vbv_underflow);
794 
795         /* This models dec VBV buffer */
796         if(VBV_OVERFLOW == e_vbv_buf_status)
797         {
798             u1_mb_qp--;
799         }
800         else if(VBV_UNDERFLOW == e_vbv_buf_status)
801         {
802             u1_mb_qp++;
803         }
804 
805         /* This ensures mb_qp_delta stays within the interval [-26, 25] */
806         u1_mb_qp = CLIP3(ps_layer_state->s_qp_params.u1_min_qp,
807                          ps_layer_state->s_qp_params.u1_max_qp, u1_mb_qp);
808         u1_mb_qp = CLIP3(MAX(MIN_H264_QP, ((WORD16) u1_frame_qp) - MAX_FRAME_QP_DECREMENT),
809                          MIN(MAX_H264_QP, ((WORD16) u1_frame_qp) + MAX_FRAME_QP_INCREMENT),
810                          ((WORD16) u1_mb_qp));
811     }
812 
813     return u1_mb_qp;
814 }
815 
isvce_sub_pic_rc_get_entropy_data(svc_sub_pic_rc_ctxt_t * ps_sub_pic_rc_ctxt)816 void isvce_sub_pic_rc_get_entropy_data(svc_sub_pic_rc_ctxt_t *ps_sub_pic_rc_ctxt)
817 {
818 #if DUMP_SUB_PIC_RC_DATA
819     sub_pic_rc_layer_state_t *ps_layer_state;
820 
821     UWORD32 u4_mb_idx;
822 
823     svc_sub_pic_rc_constants_t *ps_sub_pic_rc_constants =
824         &ps_sub_pic_rc_ctxt->s_sub_pic_rc_constants;
825     svc_sub_pic_rc_entropy_variables_t *ps_sub_pic_rc_variables =
826         &ps_sub_pic_rc_ctxt->s_sub_pic_rc_entropy_variables;
827     sub_pic_rc_state_t *ps_sub_pic_rc_state =
828         (sub_pic_rc_state_t *) ps_sub_pic_rc_constants->pv_state;
829 
830     UWORD8 u1_spatial_layer_id = ps_sub_pic_rc_variables->u1_spatial_layer_id;
831 
832     if(!ENABLE_IN_FRAME_RC || (IVE_RC_NONE == ps_sub_pic_rc_state->e_rc_mode))
833     {
834         return;
835     }
836 
837     ps_layer_state = &ps_sub_pic_rc_state->as_sub_pic_rc_layer_states[u1_spatial_layer_id];
838     u4_mb_idx = ps_sub_pic_rc_variables->s_mb_pos.i4_abscissa +
839                 ps_sub_pic_rc_variables->s_mb_pos.i4_ordinate * (ps_layer_state->i4_wd / MB_SIZE);
840 
841     ps_layer_state->ps_mb_bits_actual[u4_mb_idx] = ps_sub_pic_rc_variables->s_mb_bits;
842 #else
843     UNUSED(ps_sub_pic_rc_ctxt);
844 #endif
845 }
846 
isvce_sub_pic_rc_dump_data(svc_sub_pic_rc_ctxt_t * ps_sub_pic_rc_ctxt)847 void isvce_sub_pic_rc_dump_data(svc_sub_pic_rc_ctxt_t *ps_sub_pic_rc_ctxt)
848 {
849 #if DUMP_SUB_PIC_RC_DATA
850     WORD32 i, j, k;
851 
852     svc_sub_pic_rc_constants_t *ps_sub_pic_rc_constants =
853         &ps_sub_pic_rc_ctxt->s_sub_pic_rc_constants;
854     sub_pic_rc_state_t *ps_sub_pic_rc_state =
855         (sub_pic_rc_state_t *) ps_sub_pic_rc_constants->pv_state;
856 
857     if(!ENABLE_IN_FRAME_RC || (IVE_RC_NONE == ps_sub_pic_rc_state->e_rc_mode))
858     {
859         return;
860     }
861 
862     for(i = 0; i < ps_sub_pic_rc_state->s_svc_params.u1_num_spatial_layers; i++)
863     {
864         sub_pic_rc_layer_state_t *ps_layer_state =
865             &ps_sub_pic_rc_state->as_sub_pic_rc_layer_states[i];
866 
867         for(j = 0; j < (ps_layer_state->i4_ht / MB_SIZE); j++)
868         {
869             for(k = 0; k < (ps_layer_state->i4_wd / MB_SIZE); k++)
870             {
871                 mb_bits_info_t *ps_mb_bits_est =
872                     &ps_layer_state->ps_mb_bits_info[k + j * (ps_layer_state->i4_wd / MB_SIZE)];
873                 mb_bits_info_t *ps_mb_bits_actual =
874                     &ps_layer_state->ps_mb_bits_actual[k + j * (ps_layer_state->i4_wd / MB_SIZE)];
875 
876                 fprintf(ps_layer_state->ps_data_dump_file, "%ld,%ld,%ld,%ld,\n",
877                         ps_mb_bits_est->i8_header_bits, ps_mb_bits_est->i8_texture_bits,
878                         ps_mb_bits_actual->i8_header_bits, ps_mb_bits_actual->i8_texture_bits);
879             }
880         }
881     }
882 #else
883     UNUSED(ps_sub_pic_rc_ctxt);
884 #endif
885 }
886 
isvce_sub_pic_rc_ctxt_delete(svc_sub_pic_rc_ctxt_t * ps_sub_pic_rc_ctxt)887 void isvce_sub_pic_rc_ctxt_delete(svc_sub_pic_rc_ctxt_t *ps_sub_pic_rc_ctxt)
888 {
889     sub_pic_rc_state_t *ps_sub_pic_rc_state =
890         (sub_pic_rc_state_t *) ps_sub_pic_rc_ctxt->s_sub_pic_rc_constants.pv_state;
891 
892     ithread_mutex_destroy(ps_sub_pic_rc_state->pv_bits_accumulator_mutex);
893 
894 #if DUMP_SUB_PIC_RC_DATA
895     {
896         WORD32 i;
897 
898         UWORD8 u1_num_spatial_layers = ps_sub_pic_rc_state->s_svc_params.u1_num_spatial_layers;
899 
900         for(i = u1_num_spatial_layers - 1; i >= 0; i--)
901         {
902             sub_pic_rc_layer_state_t *ps_layer_state =
903                 &ps_sub_pic_rc_state->as_sub_pic_rc_layer_states[i];
904 
905             if(ps_layer_state->ps_data_dump_file)
906             {
907                 fclose(ps_layer_state->ps_data_dump_file);
908             }
909 
910             ps_layer_state->ps_data_dump_file = NULL;
911         }
912     }
913 #endif
914 }
915