• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright (C) 2018 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 picture_type.c
23 *
24 * \brief
25 *    This file contain picture handling struct and functions
26 *
27 * \date
28 *
29 * \author
30 *    ittiam
31 *
32 ******************************************************************************
33 */
34 /*****************************************************************************/
35 /* File Includes                                                             */
36 /*****************************************************************************/
37 /* System include files */
38 #include <stdio.h>
39 #include <string.h>
40 #include <math.h>
41 
42 /* User include files */
43 #include "ittiam_datatypes.h"
44 #include "rc_common.h"
45 #include "rc_cntrl_param.h"
46 #include "mem_req_and_acq.h"
47 #include "picture_type.h"
48 #include "trace_support.h"
49 
50 #define MAX_INTER_FRM_INT 10
51 
52 /* Pic_details */
53 typedef struct
54 {
55     WORD32 i4_pic_id; /* The id sent by the codec */
56     WORD32 i4_pic_disp_order_no; /* The pics come in, in this order  */
57     picture_type_e e_pic_type; /* I,P,B */
58     WORD32 i4_is_scd;
59 } pic_details_t;
60 
61 /********** Pic_handling structure **********/
62 typedef struct pic_handling_t
63 {
64     /* Inputs from the codec */
65     WORD32
66     i4_intra_frm_int; /* Number of frames after which an I frame will repeat in display order */
67     WORD32 i4_inter_frm_int; /* (num_b_pics_in_subgop + 1) */
68     WORD32 i4_idr_period; /* IDR frame interval, HEVC specific implementation*/
69     WORD32
70     i4_max_inter_frm_int; /* After these many buffered frames, the pics are encoded */
71     WORD32 i4_is_gop_closed; /* OPEN or CLOSED */
72     WORD32
73     i4_num_gop_in_idr_period; /* number of open GOPs between two closed GOP*/
74     WORD32
75     i4_open_gop_count; /* when open GOP count ==  i4_num_open_gop then insert a closed GOP*/
76 
77     /* The pic stack */
78     pic_details_t
79         as_pic_stack[MAX_INTER_FRM_INT + 2]; /* Stack used to store the input pics in encode order */
80 
81     /* Counters */
82     WORD32 i4_buf_pic_no; /* Decides whether a B or ref pic */
83     WORD32
84     i4_pic_disp_order_no; /* Current pic's number in displayed, and gets reset after an I-frm */
85     WORD32
86     i4_p_count_in_gop; /* Number of P frms that have come, in the current gop, so far */
87     WORD32
88     i4_b_count_in_gop; /* Number of B frms that have come, in the current gop, so far */
89     WORD32
90     i4_b_count_in_subgop; /* Number of B frms that have come, in the current subgop, so far */
91 
92     /* Indices to the pic stack (Since we store the pics in the encode order, these vars are modified to meet that) */
93     WORD32 i4_b_pic_idx; /* B_PIC index */
94     WORD32 i4_ref_pic_idx; /* I,P PIC index */
95 
96     /* Variables operating on the input pics */
97     WORD32
98     i4_is_first_gop; /* Flag denoting whether it's the first gop or not */
99     WORD32 i4_b_in_incomp_subgop; /* Number of B_PICs in an incomplete subgop */
100     WORD32
101     i4_extra_p; /* In CLOSED_GOPs, even if inter_frm_int > 1, there can be 2 continous
102                                                P_PICs at the GOP end. This takes values of 0 or 1 */
103     /* Arrays storing the number of frms in the gop */
104     WORD32 i4_frms_in_gop
105         [MAX_PIC_TYPE]; /* In the steady state, what's the pic distribution in display order */
106     WORD32 i4_frms_in_cur_gop
107         [MAX_PIC_TYPE]; /* In case of a change in inter frm int call, the pic distribution in that gop in display order */
108     WORD32 i4_actual_frms_in_gop
109         [MAX_PIC_TYPE]; /*HEVC_RC: This holds true number of pics in GOP ignoring ref and non ref B pic*/
110 
111     /* WORD32 i4_rem_frms_in_gop[MAX_PIC_TYPE];*/ /* This is used to denote the number of frms remaining to be encoded in the current gop */
112     WORD32 i4_rem_frms_in_cur_gop;
113 
114     /* Variables operating on the output pics */
115     WORD32 i4_coded_pic_no; /* Counts the frms encoded in a gop */
116     WORD32
117     i4_stack_count; /* Counts from the start of stack to the end repeatedly */
118 
119     /* Tracking a change in the inputs from the codec */
120     WORD32
121     i4_change_in_inter_frm_int; /* A flag that is set when the codec calls for a change in inter_frm_int */
122     WORD32
123     i4_new_inter_frm_int; /* When a change_in_inter_frm_int is called, this stores the new inter_frm_int */
124     WORD32
125     i4_b_in_incomp_subgop_mix_gop; /* When a change_in_inter_frm_int is called in the middle of a gop,this stores
126                                                the B_PICs in the incomplete subgop of the mixed gop */
127     WORD32
128     i4_extra_p_mix_gop; /* For a CLOSED GOP, when a change_in_inter_frm_int is called in the middle of a gop,
129                                                this is a flag denoting if there is an extra P_PIC in the mixed gop */
130     WORD32
131     i4_change_in_intra_frm_int; /* A flag that is set when the codec calls for a change in intra_frm_int */
132     WORD32
133     i4_new_intra_frm_int; /* When a change_in_intra_frm_int is called, this stores the new intra_frm_int */
134 
135     /* Previous pic_stack_indices & details */
136     pic_details_t s_prev_pic_details;
137     WORD32 i4_prev_b_pic_idx;
138 
139     WORD32 i4_last_frm_in_gop;
140     WORD32 i4_first_gop_encoded;
141 
142     picture_type_e e_previous_pic_type; /* NITT TBR */
143     WORD32 i4_force_I_frame;
144     WORD32 i4_sum_remaining_frm_in_gop;
145     WORD32 i4_mod_temp_ref_cnt;
146     WORD32 i4_frames_in_fif_gop;
147     WORD32 i4_prev_intra_frame_interval;
148     WORD32 i4_pic_order_cnt_base_offset;
149     WORD32 i4_enable_modulo;
150     WORD32 i4_change_inter_frm_interval_correction;
151     WORD32 i4_non_ref_B_pic_count;
152     WORD32 i4_num_active_pic_type;
153     WORD32 i4_field_pic;
154 } pic_handling_t;
155 
156 static void update_pic_distbn(
157     pic_handling_t *ps_pic_handling,
158     WORD32 i4_intra_frm_int,
159     WORD32 i4_inter_frm_int,
160     WORD32 i4_gop_boundary);
161 
162 static void find_pic_distbn_in_gop(
163     WORD32 i4_frms_in_gop[MAX_PIC_TYPE],
164     WORD32 i4_actual_frms_in_gop[MAX_PIC_TYPE],
165     WORD32 i4_intra_frm_int,
166     WORD32 i4_inter_frm_int,
167     WORD32 i4_is_gop_closed,
168     WORD32 *pi4_b_in_incomp_subgop,
169     WORD32 *pi4_extra_p,
170     WORD32 i4_num_active_pic_type,
171     WORD32 i4_field_pic);
172 
173 #if NON_STEADSTATE_CODE
pic_handling_num_fill_use_free_memtab(pic_handling_t ** pps_pic_handling,itt_memtab_t * ps_memtab,ITT_FUNC_TYPE_E e_func_type)174 WORD32 pic_handling_num_fill_use_free_memtab(
175     pic_handling_t **pps_pic_handling, itt_memtab_t *ps_memtab, ITT_FUNC_TYPE_E e_func_type)
176 {
177     WORD32 i4_mem_tab_idx = 0;
178     static pic_handling_t s_pic_handling_temp;
179 
180     /* Hack for al alloc, during which we dont have any state memory.
181       Dereferencing can cause issues */
182     if(e_func_type == GET_NUM_MEMTAB || e_func_type == FILL_MEMTAB)
183         (*pps_pic_handling) = &s_pic_handling_temp;
184 
185     /*for src rate control state structure*/
186     if(e_func_type != GET_NUM_MEMTAB)
187     {
188         fill_memtab(
189             &ps_memtab[i4_mem_tab_idx], sizeof(pic_handling_t), MEM_TAB_ALIGNMENT, PERSISTENT, DDR);
190         use_or_fill_base(&ps_memtab[0], (void **)pps_pic_handling, e_func_type);
191     }
192     i4_mem_tab_idx++;
193 
194     return (i4_mem_tab_idx);
195 }
196 
197 /******************************************************************************
198   Function Name   : init_pic_handling
199   Description     : initializes the pic handling state struct
200   Arguments       :
201   Return Values   : void
202   Revision History:
203                     Creation
204 *****************************************************************************/
init_pic_handling(pic_handling_t * ps_pic_handling,WORD32 i4_intra_frm_int,WORD32 i4_max_inter_frm_int,WORD32 i4_is_gop_closed,WORD32 i4_idr_period,WORD32 i4_num_active_pic_type,WORD32 i4_field_pic)205 void init_pic_handling(
206     pic_handling_t *ps_pic_handling,
207     WORD32 i4_intra_frm_int,
208     WORD32 i4_max_inter_frm_int,
209     WORD32 i4_is_gop_closed,
210     WORD32 i4_idr_period,
211     WORD32 i4_num_active_pic_type,
212     WORD32 i4_field_pic)
213 {
214     /* Declarations */
215     WORD32 i;
216 
217     ps_pic_handling->i4_num_active_pic_type = i4_num_active_pic_type;
218     ps_pic_handling->i4_idr_period = i4_idr_period;
219     /*Possible only if cdr period is zero*/
220     if(i4_intra_frm_int == i4_idr_period)
221     {
222         ps_pic_handling->i4_num_gop_in_idr_period = 1;
223     }
224     /*when idr is zero. All GOPs are open GOP*/
225     else if(!ps_pic_handling->i4_idr_period)
226     {
227         ps_pic_handling->i4_num_gop_in_idr_period = 1;
228     }
229     else if(ps_pic_handling->i4_idr_period > 0)
230     {
231         ps_pic_handling->i4_num_gop_in_idr_period =
232             (ps_pic_handling->i4_idr_period + i4_max_inter_frm_int - 1) / i4_intra_frm_int;
233     }
234     /* Checks */
235     /* Codec Parameters */
236     ps_pic_handling->i4_intra_frm_int = i4_intra_frm_int;
237     ps_pic_handling->i4_inter_frm_int = i4_max_inter_frm_int;
238     ps_pic_handling->i4_max_inter_frm_int = i4_max_inter_frm_int;
239     ps_pic_handling->i4_is_gop_closed = i4_is_gop_closed;
240     ps_pic_handling->i4_field_pic = i4_field_pic;
241     /* Pic_stack */
242     memset(ps_pic_handling->as_pic_stack, 0, sizeof(ps_pic_handling->as_pic_stack));
243     memset(&ps_pic_handling->s_prev_pic_details, 0, sizeof(ps_pic_handling->s_prev_pic_details));
244 
245     /* Counters */
246     ps_pic_handling->i4_buf_pic_no = 0;
247     ps_pic_handling->i4_pic_disp_order_no = 0;
248 
249     /* Indices to the pic_stack */
250     ps_pic_handling->i4_ref_pic_idx = 0;
251     ps_pic_handling->i4_b_pic_idx = 2;
252     ps_pic_handling->i4_prev_b_pic_idx = 2;
253 
254     /* Variables working on the input frames */
255     ps_pic_handling->i4_is_first_gop = 1;
256     ps_pic_handling->i4_p_count_in_gop = 0;
257     ps_pic_handling->i4_b_count_in_gop = 0;
258     ps_pic_handling->i4_b_count_in_subgop = 0;
259 
260     /* Variables working on the output frames */
261     ps_pic_handling->i4_coded_pic_no = -1;
262     ps_pic_handling->i4_stack_count = -1;
263 
264     /* Tracks the changes in the Codec Parameters */
265     ps_pic_handling->i4_change_in_inter_frm_int = 0;
266     ps_pic_handling->i4_new_inter_frm_int = i4_max_inter_frm_int;
267 
268     /* Tracks the changes in the Codec Parameters */
269     ps_pic_handling->i4_change_in_intra_frm_int = 0;
270     ps_pic_handling->i4_new_intra_frm_int = i4_intra_frm_int;
271     ps_pic_handling->i4_open_gop_count = 1;
272 
273     /* Variables on which the bit allocation is dependent  */
274     /* Get the pic distribution in the gop */
275     find_pic_distbn_in_gop(
276         ps_pic_handling->i4_frms_in_gop,
277         ps_pic_handling->i4_actual_frms_in_gop,
278         i4_intra_frm_int,
279         i4_max_inter_frm_int,
280         i4_is_gop_closed,
281         &ps_pic_handling->i4_b_in_incomp_subgop,
282         &ps_pic_handling->i4_extra_p,
283         ps_pic_handling->i4_num_active_pic_type,
284         ps_pic_handling->i4_field_pic);
285 
286     ps_pic_handling->i4_rem_frms_in_cur_gop = 0;
287     for(i = 0; i < MAX_PIC_TYPE; i++)
288     {
289         ps_pic_handling->i4_frms_in_cur_gop[i] = ps_pic_handling->i4_frms_in_gop[i];
290         ps_pic_handling->i4_rem_frms_in_cur_gop += ps_pic_handling->i4_actual_frms_in_gop[i];
291     }
292     /*Since first GOP will be closed GOP in all condition make sure end of GOP flag is set before qp query is done for next I frame*/
293     /*HEVC_hierarchy*/
294     ps_pic_handling->i4_rem_frms_in_cur_gop -= i4_max_inter_frm_int - 1;
295 
296     ps_pic_handling->e_previous_pic_type = I_PIC;
297     ps_pic_handling->i4_force_I_frame = 0;
298     ps_pic_handling->i4_sum_remaining_frm_in_gop = 0;
299     ps_pic_handling->i4_mod_temp_ref_cnt = 0;
300 
301     ps_pic_handling->i4_b_in_incomp_subgop_mix_gop = ps_pic_handling->i4_b_in_incomp_subgop;
302     ps_pic_handling->i4_extra_p_mix_gop = ps_pic_handling->i4_extra_p;
303 
304     ps_pic_handling->i4_last_frm_in_gop = 0;
305     ps_pic_handling->i4_first_gop_encoded = 0;
306     ps_pic_handling->i4_frames_in_fif_gop = 0;
307     ps_pic_handling->i4_pic_order_cnt_base_offset = 0;
308     ps_pic_handling->i4_enable_modulo = 0;
309     ps_pic_handling->i4_change_inter_frm_interval_correction = 0;
310     ps_pic_handling->i4_prev_intra_frame_interval = i4_intra_frm_int; /*i_only*/
311     ps_pic_handling->i4_non_ref_B_pic_count = 0;
312 }
313 #endif /* #if NON_STEADSTATE_CODE */
314 
315 /* ******************************************************************************/
316 /**
317  * @brief registers the new intra frame interval value
318  *
319  * @param ps_pic_handling
320  * @param i4_intra_frm_int
321  */
322 /* ******************************************************************************/
pic_handling_register_new_int_frm_interval(pic_handling_t * ps_pic_handling,WORD32 i4_intra_frm_int)323 void pic_handling_register_new_int_frm_interval(
324     pic_handling_t *ps_pic_handling, WORD32 i4_intra_frm_int)
325 {
326     ps_pic_handling->i4_change_in_intra_frm_int = 1;
327     ps_pic_handling->i4_new_intra_frm_int = i4_intra_frm_int;
328 
329     /* The below call was made when a control call changes
330      * the intra frame interval before the first frame was getting encoded
331      * but i see that it is not required as of now NITT TBR
332     ps_pic_handling->i4_change_in_intra_frm_int = 0;
333     update_pic_distbn(ps_pic_handling,
334             ps_pic_handling->i4_new_intra_frm_int,
335             ps_pic_handling->i4_inter_frm_int,
336             1); */
337 }
338 /******************************************************************************
339   Function Name   : pic_handling_register_new_inter_frm_interval
340   Description     :
341   Arguments       : ps_pic_handling
342   Return Values   : void
343   Revision History:
344                     Creation
345 *****************************************************************************/
pic_handling_register_new_inter_frm_interval(pic_handling_t * ps_pic_handling,WORD32 i4_inter_frm_int)346 void pic_handling_register_new_inter_frm_interval(
347     pic_handling_t *ps_pic_handling, WORD32 i4_inter_frm_int)
348 {
349     /* Update the state structure with the latest values */
350     ps_pic_handling->i4_change_in_inter_frm_int = 1;
351     ps_pic_handling->i4_new_inter_frm_int = i4_inter_frm_int;
352 }
353 /******************************************************************************
354   Function Name   : start_new_gop
355   Description     :
356   Arguments       : ps_pic_handling
357   Return Values   : void
358   Revision History:
359                     Creation
360 *****************************************************************************/
start_new_gop(pic_handling_t * ps_pic_handling)361 static void start_new_gop(pic_handling_t *ps_pic_handling)
362 {
363     WORD32 i;
364     WORD32 i4_sum_remaining_frm_in_gop = 0;
365     /* Now, the end of gop updates */
366     ps_pic_handling->i4_pic_disp_order_no = 0;
367     ps_pic_handling->i4_buf_pic_no = 0;
368     ps_pic_handling->i4_is_first_gop = 0;
369     ps_pic_handling->i4_extra_p_mix_gop = ps_pic_handling->i4_extra_p;
370 
371     if(ps_pic_handling->i4_is_gop_closed)
372     {
373         ps_pic_handling->i4_b_in_incomp_subgop_mix_gop = ps_pic_handling->i4_b_in_incomp_subgop;
374     }
375     /* Store the number of frames in the gop that is encoded till now [just before Force I frame
376     call is made */
377     ps_pic_handling->i4_frames_in_fif_gop =
378         ps_pic_handling->i4_b_count_in_gop + ps_pic_handling->i4_p_count_in_gop + 1;
379 
380     i4_sum_remaining_frm_in_gop = ps_pic_handling->i4_rem_frms_in_cur_gop;
381 
382     ps_pic_handling->i4_sum_remaining_frm_in_gop = i4_sum_remaining_frm_in_gop;
383     ps_pic_handling->i4_rem_frms_in_cur_gop = 0;
384     for(i = 0; i < MAX_PIC_TYPE; i++)
385     {
386         ps_pic_handling->i4_frms_in_cur_gop[i] = ps_pic_handling->i4_frms_in_gop[i];
387         ps_pic_handling->i4_rem_frms_in_cur_gop += ps_pic_handling->i4_frms_in_cur_gop[i];
388     }
389 }
390 
391 /* ******************************************************************************/
392 /**
393  * @brief Fills the pic_stack with the incoming pics in encode order
394  *
395  * @param ps_pic_handling
396  * @param i4_enc_pic_id
397  */
398 /* ******************************************************************************/
add_pic_to_stack(pic_handling_t * ps_pic_handling,WORD32 i4_enc_pic_id,WORD32 i4_rc_in_pic)399 void add_pic_to_stack(pic_handling_t *ps_pic_handling, WORD32 i4_enc_pic_id, WORD32 i4_rc_in_pic)
400 {
401     /* Declarations */
402     WORD32 i4_inter_frm_int, i4_max_inter_frm_int, i4_intra_frm_int, i4_new_inter_frm_int;
403     WORD32 i4_is_gop_closed;
404     WORD32 i4_buf_pic_no, i4_pic_disp_order_no;
405     WORD32 i4_b_pic_idx, i4_ref_pic_idx;
406     WORD32 i4_is_first_gop, i4_b_in_incomp_subgop, i4_p_count_in_gop, i4_b_count_in_gop,
407         i4_b_count_in_subgop;
408     WORD32 i, i4_p_frms_in_prd, i4_b_frms_in_prd, i4_num_b_in_subgop, i4_extra_p;
409     WORD32 i4_condn_for_change_in_inter_frm_int;
410     picture_type_e e_previous_pic_type, e_cur_pic_type;
411     WORD32 i4_force_I_frame;
412     WORD32 i4_is_scd = 0;
413 
414     /* Just force an I picture if the input frame is an I frame. Normal I picture will anyway be taken care
415        inside add_pic_to_stack(). And inside add_pic_to_stack() let us take care of U(nexpected)I frame
416        for resetting the model */
417     if(i4_rc_in_pic == I_PIC || i4_rc_in_pic == I_PIC_SCD)
418     {
419         set_force_I_frame_flag(ps_pic_handling);
420     }
421 
422     /* Initialize the local vars with the state struct values needed by the change calls */
423     i4_intra_frm_int = ps_pic_handling->i4_intra_frm_int;
424     i4_inter_frm_int = ps_pic_handling->i4_inter_frm_int;
425     i4_max_inter_frm_int = ps_pic_handling->i4_max_inter_frm_int;
426     i4_is_gop_closed = ps_pic_handling->i4_is_gop_closed;
427 
428     i4_buf_pic_no = ps_pic_handling->i4_buf_pic_no;
429     i4_pic_disp_order_no = ps_pic_handling->i4_pic_disp_order_no;
430     i4_b_count_in_gop = ps_pic_handling->i4_b_count_in_gop;
431     i4_b_frms_in_prd = ps_pic_handling->i4_frms_in_cur_gop[B_PIC];
432     i4_is_first_gop = ps_pic_handling->i4_is_first_gop;
433     i4_new_inter_frm_int = ps_pic_handling->i4_new_inter_frm_int;
434     e_previous_pic_type = ps_pic_handling->e_previous_pic_type;
435     i4_force_I_frame = ps_pic_handling->i4_force_I_frame;
436     /******************************* Force I frame ******************************/
437     /* Two different cases
438     1)OPEN_GOP:
439        New GOP is started after number of B pictures in the last sub gop of a gop to mimic the
440        GOP structure.
441 
442     2)Closed GOP:Wait till P frame at input and The frame after a P frame a new GOP is started
443       to mimic the GOP structure.
444     */
445     if(i4_force_I_frame)
446     {
447         WORD32 i4_temp_is_gop_closed;
448         WORD32 i4_codn = 0;
449         /* A special case of Open GOP where the it behaves like Closed GOP*/
450         if((i4_intra_frm_int % i4_inter_frm_int) == 1)
451         {
452             i4_temp_is_gop_closed = 1;
453         }
454         else
455         {
456             i4_temp_is_gop_closed = i4_is_gop_closed;
457         }
458         /* Get the current picture type to aid decision to force an I frame*/
459         if((i4_buf_pic_no % i4_inter_frm_int) &&
460            !(i4_is_gop_closed && (i4_b_count_in_gop == i4_b_frms_in_prd)))
461         {
462             e_cur_pic_type = B_PIC;
463         }
464         else
465         {
466             if(i4_pic_disp_order_no == 0)
467             {
468                 e_cur_pic_type = I_PIC;
469             }
470             else
471             {
472                 e_cur_pic_type = P_PIC;
473             }
474         }
475         if((i4_intra_frm_int % i4_inter_frm_int) == 0)
476         {
477             i4_codn = (e_cur_pic_type == P_PIC);
478         }
479         else
480         {
481             i4_codn =
482                 (ps_pic_handling->i4_b_count_in_subgop == ps_pic_handling->i4_b_in_incomp_subgop);
483         }
484         if(e_cur_pic_type == I_PIC)
485         {
486             /*Don't do anything. Resetting the force I frame flag since the current picture
487             type is already a I frame */
488             i4_force_I_frame = 0;
489         }
490         else if(i4_inter_frm_int == 1)
491         {
492             /*IPP case , Force I frame immediately*/
493             start_new_gop(ps_pic_handling);
494         }
495         else if((!i4_temp_is_gop_closed) && i4_codn)
496         {
497             start_new_gop(ps_pic_handling);
498             if(ps_pic_handling->i4_b_count_in_subgop)
499             {
500                 ps_pic_handling->i4_b_pic_idx += 1;
501                 ps_pic_handling->i4_b_pic_idx %= (i4_max_inter_frm_int + 1);
502             }
503         }
504         else if(i4_temp_is_gop_closed && (e_previous_pic_type == P_PIC) && (e_cur_pic_type != P_PIC))
505         {
506             start_new_gop(ps_pic_handling);
507             ps_pic_handling->i4_b_pic_idx++;
508             ps_pic_handling->i4_b_pic_idx %= (i4_max_inter_frm_int + 1);
509         }
510         i4_is_first_gop = ps_pic_handling->i4_is_first_gop;
511 
512         /* Check for unexpected I frame and assume its a scene change. If so, reset the model */
513         if(((e_cur_pic_type != I_PIC) && (i4_rc_in_pic == I_PIC)) || (i4_rc_in_pic == I_PIC_SCD))
514         {
515             /* Set the SCD flag */
516             i4_is_scd = 1;
517         }
518     }
519 
520     /******************************* CHANGE_INTRA_FRM_INTERVAL ******************************/
521     /* Call the update_pic_distbn if
522     1)Change in intra frm interval flag is set
523     2)It's the first B_PIC of a gop
524     */
525     if((ps_pic_handling->i4_change_in_intra_frm_int == 1) && ((i4_pic_disp_order_no == 1)))
526     {
527         update_pic_distbn(
528             ps_pic_handling,
529             ps_pic_handling->i4_new_intra_frm_int,
530             ps_pic_handling->i4_inter_frm_int,
531             1);
532 
533         ps_pic_handling->i4_change_in_intra_frm_int = 0;
534 
535         if(ps_pic_handling->i4_new_intra_frm_int == 1)
536         {
537             ps_pic_handling->i4_pic_disp_order_no = 0;
538         }
539     }
540     /******************************* CHANGE_INTER_FRM_INTERVAL ******************************/
541 
542     /* Call update_pic_distbn if
543     1)Change in inter frm interval flag is set
544     2)It's the first B_PIC after gop/subgop start, and
545     3)The new inter-frm-interval won't cross the intra_frm_interval
546     */
547 
548     if((ps_pic_handling->i4_change_in_inter_frm_int == 1) &&
549        ((i4_buf_pic_no % i4_inter_frm_int == 1) || (i4_pic_disp_order_no == 1) ||
550         (i4_inter_frm_int == 1)))
551     {
552         /* Condn which checks if the new inter_frm_int will cross the intra_frm_int */
553         i4_condn_for_change_in_inter_frm_int =
554             ((i4_pic_disp_order_no + i4_new_inter_frm_int - 1) < i4_intra_frm_int);
555 
556         if(i4_condn_for_change_in_inter_frm_int)
557         {
558             /* If the inter_frm_int = 1, then the b_pic_idx needs to be modified */
559             if(i4_inter_frm_int == 1)
560             {
561                 ps_pic_handling->i4_b_pic_idx =
562                     (1 + ps_pic_handling->i4_ref_pic_idx) % (i4_max_inter_frm_int + 1);
563             }
564             /* Store a correction factor for calculating the picture display order */
565             if(i4_inter_frm_int != i4_new_inter_frm_int)
566             {
567                 ps_pic_handling->i4_change_inter_frm_interval_correction =
568                     i4_inter_frm_int - i4_new_inter_frm_int;
569                 /* ps_pic_handling->i4_change_inter_frm_interval_correction = 0; */
570             }
571 
572             /* Depending on the gop/subgop boundary, call the change_inter_frm_int */
573             /* TO DO: make a single call, change the name of the fxn to update_state,
574                       where state = frms_in_gop + b_incomp_subgop + extra_p */
575 
576             if(i4_pic_disp_order_no == 1) /*GOP boundary*/
577             {
578                 update_pic_distbn(
579                     ps_pic_handling,
580                     ps_pic_handling->i4_intra_frm_int,
581                     ps_pic_handling->i4_new_inter_frm_int,
582                     1);
583             }
584             else /*Subgop boundary*/
585             {
586                 update_pic_distbn(
587                     ps_pic_handling,
588                     ps_pic_handling->i4_intra_frm_int,
589                     ps_pic_handling->i4_new_inter_frm_int,
590                     0);
591             }
592 
593             ps_pic_handling->i4_change_in_inter_frm_int = 0;
594             ps_pic_handling->i4_new_inter_frm_int = ps_pic_handling->i4_inter_frm_int;
595         }
596     }
597 
598     /* Initialize the local vars with the state struct values */
599     i4_buf_pic_no = ps_pic_handling->i4_buf_pic_no;
600     i4_pic_disp_order_no = ps_pic_handling->i4_pic_disp_order_no;
601     i4_b_pic_idx = ps_pic_handling->i4_b_pic_idx;
602     i4_ref_pic_idx = ps_pic_handling->i4_ref_pic_idx;
603     i4_b_in_incomp_subgop = ps_pic_handling->i4_b_in_incomp_subgop_mix_gop;
604     i4_p_count_in_gop = ps_pic_handling->i4_p_count_in_gop;
605     i4_b_count_in_gop = ps_pic_handling->i4_b_count_in_gop;
606     i4_b_count_in_subgop = ps_pic_handling->i4_b_count_in_subgop;
607     i4_p_frms_in_prd = ps_pic_handling->i4_frms_in_cur_gop[P_PIC];
608     i4_b_frms_in_prd = ps_pic_handling->i4_frms_in_cur_gop[B_PIC];
609     i4_extra_p = ps_pic_handling->i4_extra_p_mix_gop;
610     i4_inter_frm_int = ps_pic_handling->i4_inter_frm_int;
611     i4_intra_frm_int = ps_pic_handling->i4_intra_frm_int;
612 
613     /* Initializing the prev_state vars */
614     ps_pic_handling->i4_prev_b_pic_idx = ps_pic_handling->i4_b_pic_idx;
615 
616     i4_num_b_in_subgop = (i4_inter_frm_int - 1);
617 
618     /***************************************** Fill the stack ***************************************/
619     /* The next part of the code is organized as
620 
621         if(B_PIC conditions satisfied)
622         {
623             Fill the pic_stack using the b_pic_index
624             Update the b_pic_index and the other b_pic related vars for the next B_PIC
625         }
626         else
627         {
628             if(I_PIC conditions are satisfied)
629             {
630                 Fill the pic_stack using the ref_pic_index
631                 Update the ref_pic_index and the other ref_pic related vars for the next I_PIC/P_PIC
632             }
633             else
634             {
635                 Fill the pic_stack using the ref_pic_index
636                 Update the ref_pic_index and the other ref_pic related vars for the next I_PIC/P_PIC
637             }
638         }
639     */
640     /* Condition for a B_PIC -
641     1) Other than the first I_PIC and the periodically appearing P_PICs, after every inter_frm_int,
642        rest all pics are B_PICs
643     2) In case of CLOSED_GOP, the last frame of the gop has to be a P_PIC */
644 
645     if(ps_pic_handling->i4_intra_frm_int ==
646        1) /*i only case insert the pic only at first location of stack*/
647     {
648         i4_ref_pic_idx = 0;
649         i4_b_pic_idx = 0;
650     }
651     if((i4_buf_pic_no % i4_inter_frm_int) &&
652        !(i4_is_gop_closed && (i4_b_count_in_gop == i4_b_frms_in_prd))) /**** B_PIC ****/
653     {
654         /* Fill the pic_stack */
655         ps_pic_handling->as_pic_stack[i4_b_pic_idx].i4_pic_id = i4_enc_pic_id;
656         ps_pic_handling->as_pic_stack[i4_b_pic_idx].e_pic_type = B_PIC;
657         ps_pic_handling->as_pic_stack[i4_b_pic_idx].i4_pic_disp_order_no = i4_pic_disp_order_no;
658         ps_pic_handling->as_pic_stack[i4_b_pic_idx].i4_is_scd = 0;
659 
660         /* Store Pic type*/
661         e_previous_pic_type = B_PIC;
662 
663         /* Update the prev_pic_details */
664         memcpy(
665             &ps_pic_handling->s_prev_pic_details,
666             &ps_pic_handling->as_pic_stack[i4_b_pic_idx],
667             sizeof(pic_details_t));
668 
669         i4_b_count_in_gop++;
670         i4_b_count_in_subgop++;
671 
672         /* Update the i4_b_pic_idx */
673         if(!i4_is_gop_closed)
674         {
675             /* If this B_PIC features in one of the complete subgops */
676             if((i4_b_count_in_subgop < i4_num_b_in_subgop) &&
677                !(i4_b_count_in_gop == i4_b_frms_in_prd))
678             {
679                 i4_b_pic_idx++;
680             }
681             else /* Else if this B_PIC is the last one in a subgop or gop  */
682             {
683                 /* If this is the last B_PIC of a GOP, depending on the number of incomp B_pics in
684                    the subgop, there can be either only I or I,P pics between this and the next B_PIC */
685                 if(i4_b_count_in_gop == i4_b_frms_in_prd)
686                 {
687                     i4_b_pic_idx += (2 + (!i4_b_in_incomp_subgop)); /*Prev*/
688                     i4_b_count_in_gop = 0;
689                 }
690                 else /* For the last B_PIC of a subgop, there's always a P b/w this & the next B_PIC */
691                 {
692                     i4_b_pic_idx += 2;
693                 }
694                 i4_b_count_in_subgop = 0;
695             }
696         }
697         else
698         {
699             /* For the last B_PIC of a gop
700                Normally,there will be 3 pics (P,I,P) between this and the next B_PIC for a CLOSED gop,
701                except when
702                1)Number of P_pics in the gop = 1
703                2)There is an extra P at the end of the gop
704                */
705             if(i4_b_count_in_gop == i4_b_frms_in_prd)
706             {
707                 i4_b_pic_idx +=
708                     (3 + ((i4_b_in_incomp_subgop == 0) && (i4_p_frms_in_prd > 1) &&
709                           (i4_pic_disp_order_no != (i4_p_frms_in_prd + i4_b_frms_in_prd - 1))));
710 
711                 i4_b_count_in_subgop = 0;
712             }
713             else if(
714                 i4_b_count_in_subgop <
715                 i4_num_b_in_subgop) /* For a B_PIC which is not the last one in a subgop */
716             {
717                 i4_b_pic_idx++;
718             }
719             else /* For the last B_PIC of a subgop */
720             {
721                 i4_b_pic_idx += 2;
722                 i4_b_count_in_subgop = 0;
723             }
724         }
725         i4_b_pic_idx %= (i4_max_inter_frm_int + 1);
726     }
727     else /*********** I or P pic *********/
728     {
729         ps_pic_handling->as_pic_stack[i4_ref_pic_idx].i4_pic_id = i4_enc_pic_id;
730         ps_pic_handling->as_pic_stack[i4_ref_pic_idx].i4_pic_disp_order_no = i4_pic_disp_order_no;
731         ps_pic_handling->as_pic_stack[i4_ref_pic_idx].i4_is_scd = i4_is_scd;
732         /* Store Pic type*/
733         e_previous_pic_type = I_PIC;
734         if(i4_pic_disp_order_no == 0) /**** I_PIC ****/
735         {
736             ps_pic_handling->as_pic_stack[i4_ref_pic_idx].e_pic_type = I_PIC;
737 
738             /* Update the prev_pic_details */
739             memcpy(
740                 &ps_pic_handling->s_prev_pic_details,
741                 &ps_pic_handling->as_pic_stack[i4_ref_pic_idx],
742                 sizeof(pic_details_t));
743 
744             /* In case of an I-frame depending on OPEN or CLOSED gop, the ref_pic_idx changes */
745             if((!i4_is_gop_closed) && (i4_is_first_gop == 0))
746             {
747                 if((i4_p_frms_in_prd <= 1) && (i4_b_in_incomp_subgop == 0))
748                 {
749                     i4_ref_pic_idx++;
750                 }
751                 else /* From the 2nd gop onwards, the I and first P frame are separated by the num_b_in_incomp_subgop */
752                 {
753                     i4_ref_pic_idx += (i4_b_in_incomp_subgop + 1);
754                 }
755 
756                 ps_pic_handling->i4_b_in_incomp_subgop_mix_gop =
757                     ps_pic_handling->i4_b_in_incomp_subgop;
758             }
759             else
760             {
761                 i4_ref_pic_idx++;
762             }
763 
764             i4_b_count_in_gop = 0;
765             i4_p_count_in_gop = 0;
766             i4_b_count_in_subgop = 0;
767         }
768         else /**** P_PIC ****/
769         {
770             ps_pic_handling->as_pic_stack[i4_ref_pic_idx].e_pic_type = P_PIC;
771             /* Store Pic type*/
772             e_previous_pic_type = P_PIC;
773 
774             /* Update the prev_pic_details */
775             memcpy(
776                 &ps_pic_handling->s_prev_pic_details,
777                 &ps_pic_handling->as_pic_stack[i4_ref_pic_idx],
778                 sizeof(pic_details_t));
779 
780             i4_p_count_in_gop++;
781             ps_pic_handling->i4_prev_intra_frame_interval = i4_intra_frm_int;
782 
783             /* In case of an P-frame depending on OPEN or CLOSED gop, the ref_pic_idx changes */
784             if(i4_is_gop_closed && (i4_p_count_in_gop == i4_p_frms_in_prd))
785             {
786                 /* For the last P_PIC in a gop, if extra_p or incomp_b are present, the
787                    number of such pics between this and the next ref_pic is (i4_b_in_incomp_subgop + 1) */
788                 if((i4_p_count_in_gop > 1) && (i4_b_in_incomp_subgop || i4_extra_p))
789                 {
790                     i4_ref_pic_idx += (i4_b_in_incomp_subgop + 1);
791                 }
792                 else
793                 {
794                     i4_ref_pic_idx += i4_inter_frm_int;
795                 }
796             }
797             else
798             {
799                 i4_ref_pic_idx += i4_inter_frm_int;
800             }
801         }
802 
803         i4_ref_pic_idx %= (i4_max_inter_frm_int + 1);
804     }
805 
806     /* Update those variables working on the input frames  */
807     i4_pic_disp_order_no++;
808     i4_buf_pic_no++;
809 
810     /* For any gop */
811     if(ps_pic_handling->i4_pic_disp_order_no ==
812        (i4_max_inter_frm_int - 1 -
813         ((!i4_is_gop_closed) * ps_pic_handling->i4_b_in_incomp_subgop_mix_gop)))
814     {
815         /* NITT DEBUG : COULD BE REMOVED. Replace i4_rem_frms_in_gop with a single variable thus getting rid of
816         the requirement to store rem frms in gop */
817         if((!i4_is_gop_closed) && (i4_is_first_gop) &&
818            (ps_pic_handling->i4_frms_in_cur_gop[B_PIC] >
819             ps_pic_handling->i4_b_in_incomp_subgop_mix_gop))
820         {
821             ps_pic_handling->i4_rem_frms_in_cur_gop -=
822                 ps_pic_handling->i4_b_in_incomp_subgop_mix_gop;
823         }
824     }
825 
826     /* End of GOP updates */
827     if(i4_pic_disp_order_no == (i4_p_frms_in_prd + i4_b_frms_in_prd + 1))
828     {
829         /* Now, the end of gop updates */
830         i4_pic_disp_order_no = 0;
831         i4_buf_pic_no = 0;
832         i4_is_first_gop = 0;
833         ps_pic_handling->i4_extra_p_mix_gop = ps_pic_handling->i4_extra_p;
834 
835         if(i4_is_gop_closed)
836         {
837             ps_pic_handling->i4_b_in_incomp_subgop_mix_gop = ps_pic_handling->i4_b_in_incomp_subgop;
838         }
839 
840         for(i = 0; i < MAX_PIC_TYPE; i++)
841         {
842             ps_pic_handling->i4_frms_in_cur_gop[i] = ps_pic_handling->i4_frms_in_gop[i];
843         }
844     }
845 
846     /* Updating the vars which work on the encoded pics */
847     /* For the first gop */
848     if(((ps_pic_handling->i4_is_first_gop) &&
849         (ps_pic_handling->i4_pic_disp_order_no == (i4_max_inter_frm_int - 1))) ||
850        (i4_intra_frm_int == 1))
851     {
852         ps_pic_handling->i4_coded_pic_no = 0;
853         ps_pic_handling->i4_stack_count = 0;
854     }
855 
856     /* Update the state struct with the modifiable local vars */
857     ps_pic_handling->i4_buf_pic_no = i4_buf_pic_no;
858     ps_pic_handling->i4_pic_disp_order_no = i4_pic_disp_order_no;
859     ps_pic_handling->i4_b_pic_idx = i4_b_pic_idx;
860     ps_pic_handling->i4_ref_pic_idx = i4_ref_pic_idx;
861     ps_pic_handling->i4_is_first_gop = i4_is_first_gop;
862     ps_pic_handling->i4_p_count_in_gop = i4_p_count_in_gop;
863     ps_pic_handling->i4_b_count_in_gop = i4_b_count_in_gop;
864     ps_pic_handling->i4_b_count_in_subgop = i4_b_count_in_subgop;
865     ps_pic_handling->e_previous_pic_type = e_previous_pic_type;
866     ps_pic_handling->i4_force_I_frame = i4_force_I_frame;
867 }
868 
869 /* ******************************************************************************/
870 /**
871  * @brief Returns the picture type, ip and display order number for the frame to be encoded
872  *
873  * @param ps_pic_handling
874  * @param pi4_pic_id
875  * @param pi4_pic_disp_order_no
876  * @param pe_pic_type
877  */
878 /* ******************************************************************************/
get_pic_from_stack(pic_handling_t * ps_pic_handling,WORD32 * pi4_pic_id,WORD32 * pi4_pic_disp_order_no,picture_type_e * pe_pic_type,WORD32 * pi4_is_scd)879 void get_pic_from_stack(
880     pic_handling_t *ps_pic_handling,
881     WORD32 *pi4_pic_id,
882     WORD32 *pi4_pic_disp_order_no,
883     picture_type_e *pe_pic_type,
884     WORD32 *pi4_is_scd)
885 {
886     pic_details_t s_pic_details;
887     pic_details_t *ps_pic_details = &s_pic_details;
888 
889     if(ps_pic_handling->i4_stack_count < 0)
890     {
891         ps_pic_details->e_pic_type = BUF_PIC;
892         ps_pic_details->i4_pic_disp_order_no = -1;
893         ps_pic_details->i4_pic_id = -1;
894         ps_pic_details->i4_is_scd = 0;
895     }
896     else
897     {
898         memcpy(
899             ps_pic_details,
900             &ps_pic_handling->as_pic_stack[ps_pic_handling->i4_stack_count],
901             sizeof(pic_details_t));
902         /* Force I frame updations */
903         if((ps_pic_handling->i4_force_I_frame == 1) && (ps_pic_details->e_pic_type == I_PIC))
904         {
905             ps_pic_handling->i4_force_I_frame = 0;
906             /* Indicates count for no. of Pictures whose temporal reference has to be modified
907                in the new GOP*/
908             ps_pic_handling->i4_mod_temp_ref_cnt = ps_pic_handling->i4_b_in_incomp_subgop + 1;
909             ps_pic_handling->i4_first_gop_encoded = 1;
910         }
911 
912         /* In MPEG2, the temporal reference of the first displayed frame in a gop is 0.
913            In case of an OPEN_GOP, the B_PICs of the last subgop in a gop,
914            maybe coded as a part of the next gop. Hence, in such conditions
915            the pic_disp_order needs to be modified so that it gives an indication
916            of the temoral reference */
917         if((!ps_pic_handling->i4_is_gop_closed) && (ps_pic_handling->i4_first_gop_encoded) &&
918            ps_pic_handling->i4_intra_frm_int !=
919                1) /*i_only: no change to temporal reference done in case of i only as it is always 0*/
920         {
921             WORD32 i4_pic_disp_order_no;
922             if(s_pic_details.e_pic_type == I_PIC)
923             {
924                 ps_pic_handling->i4_pic_order_cnt_base_offset =
925                     ps_pic_handling->i4_b_in_incomp_subgop;
926                 ps_pic_handling->i4_enable_modulo = 1;
927             }
928             else if(s_pic_details.e_pic_type == P_PIC)
929             {
930                 ps_pic_handling->i4_enable_modulo = 0;
931                 ps_pic_handling->i4_change_inter_frm_interval_correction = 0;
932             }
933 
934             i4_pic_disp_order_no =
935                 ps_pic_handling->as_pic_stack[ps_pic_handling->i4_stack_count].i4_pic_disp_order_no +
936                 ps_pic_handling->i4_pic_order_cnt_base_offset;
937 
938             if(ps_pic_handling->i4_enable_modulo)
939             {
940                 if(!ps_pic_handling->i4_mod_temp_ref_cnt)
941                 {
942                     i4_pic_disp_order_no =
943                         i4_pic_disp_order_no %
944                         (ps_pic_handling->i4_prev_intra_frame_interval +
945                          ps_pic_handling->i4_change_inter_frm_interval_correction);
946                 }
947                 else
948                 {
949                     /* due to force I frame First frame will have only ps_pic_handling->i4_frames_in_fif_gop number of frames*/
950                     i4_pic_disp_order_no =
951                         i4_pic_disp_order_no % ps_pic_handling->i4_frames_in_fif_gop;
952                     ps_pic_handling->i4_mod_temp_ref_cnt--;
953                 }
954             }
955             s_pic_details.i4_pic_disp_order_no = i4_pic_disp_order_no;
956         }
957     }
958 
959     /* Giving this to the Codec */
960     *pi4_pic_id = s_pic_details.i4_pic_id;
961     *pi4_pic_disp_order_no = s_pic_details.i4_pic_disp_order_no;
962     *pe_pic_type = s_pic_details.e_pic_type;
963     *pi4_is_scd = s_pic_details.i4_is_scd;
964 }
965 
966 /* ******************************************************************************/
967 /**
968  * @brief Updates the picture handling state whenever there is changes in input parameter
969  *
970  * @param ps_pic_handling
971  * @param i4_intra_frm_int
972  * @param i4_inter_frm_int
973  * @param i4_gop_boundary
974  */
975 /* ******************************************************************************/
update_pic_distbn(pic_handling_t * ps_pic_handling,WORD32 i4_intra_frm_int,WORD32 i4_inter_frm_int,WORD32 i4_gop_boundary)976 static void update_pic_distbn(
977     pic_handling_t *ps_pic_handling,
978     WORD32 i4_intra_frm_int,
979     WORD32 i4_inter_frm_int,
980     WORD32 i4_gop_boundary)
981 {
982     /* Declarations */
983     WORD32 i4_is_gop_closed;
984     WORD32 i, i4_prev_inter_frm_int, i4_max_inter_frm_int, i4_pic_disp_order_no;
985     WORD32 i4_b_in_incomp_subgop, i4_extra_p, i4_b_in_incomp_subgop_mix_gop, i4_extra_p_mix_gop;
986     WORD32 i4_pb_frms_till_prev_p;
987     WORD32 ai4_diff_in_frms[MAX_PIC_TYPE];
988 
989     /* Initialize the local vars from the state struct */
990     i4_is_gop_closed = ps_pic_handling->i4_is_gop_closed;
991     i4_prev_inter_frm_int = ps_pic_handling->i4_inter_frm_int;
992     i4_max_inter_frm_int = ps_pic_handling->i4_max_inter_frm_int;
993     i4_b_in_incomp_subgop = ps_pic_handling->i4_b_in_incomp_subgop;
994     i4_extra_p = ps_pic_handling->i4_extra_p;
995     i4_b_in_incomp_subgop_mix_gop = ps_pic_handling->i4_b_in_incomp_subgop_mix_gop;
996     i4_extra_p_mix_gop = ps_pic_handling->i4_extra_p_mix_gop;
997     i4_pic_disp_order_no = ps_pic_handling->i4_pic_disp_order_no;
998 
999     i4_pb_frms_till_prev_p = (ps_pic_handling->i4_p_count_in_gop * i4_prev_inter_frm_int);
1000 
1001     /* Check for the validity of the intra_frm_int */
1002     if(i4_intra_frm_int <= 0)
1003     {
1004         i4_intra_frm_int = ps_pic_handling->i4_intra_frm_int;
1005     }
1006     /* Check for the validity of the inter_frm_int */
1007     if((i4_inter_frm_int > i4_max_inter_frm_int) || (i4_inter_frm_int < 0))
1008     {
1009         i4_inter_frm_int = ps_pic_handling->i4_inter_frm_int;
1010     }
1011 
1012     /* Keep a copy of the older frms_in_gop */
1013     for(i = 0; i < MAX_PIC_TYPE; i++)
1014     {
1015         ai4_diff_in_frms[i] = ps_pic_handling->i4_frms_in_cur_gop[i];
1016     }
1017 
1018     /******* Update all the variables which are calculated from the inter_frm_int *******/
1019 
1020     /* Get the new pic distribution in the gop */
1021     find_pic_distbn_in_gop(
1022         ps_pic_handling->i4_frms_in_gop,
1023         ps_pic_handling->i4_actual_frms_in_gop,
1024         i4_intra_frm_int,
1025         i4_inter_frm_int,
1026         i4_is_gop_closed,
1027         &i4_b_in_incomp_subgop,
1028         &i4_extra_p,
1029         ps_pic_handling->i4_num_active_pic_type,
1030         ps_pic_handling->i4_field_pic);
1031 
1032     /* Find the other related variables */
1033     if(i4_gop_boundary == 0)
1034     {
1035         /* Since, the inter frame interval has changed between a gop the current gop will
1036            be a mixed gop. So, we need to find the values of the related varibles */
1037         find_pic_distbn_in_gop(
1038             ps_pic_handling->i4_frms_in_cur_gop,
1039             ps_pic_handling->i4_actual_frms_in_gop,
1040             (i4_intra_frm_int - i4_pb_frms_till_prev_p),
1041             i4_inter_frm_int,
1042             i4_is_gop_closed,
1043             &i4_b_in_incomp_subgop_mix_gop,
1044             &i4_extra_p_mix_gop,
1045             ps_pic_handling->i4_num_active_pic_type,
1046             ps_pic_handling->i4_field_pic);
1047 
1048         ps_pic_handling->i4_frms_in_cur_gop[P_PIC] += ps_pic_handling->i4_p_count_in_gop;
1049         ps_pic_handling->i4_frms_in_cur_gop[B_PIC] += ps_pic_handling->i4_b_count_in_gop;
1050     }
1051     else
1052     {
1053         /*  Since, the inter_frm_interval has changed at a gop boundary, the new gop will have
1054             all the subgops with the new inter_frm_interval */
1055         for(i = 0; i < MAX_PIC_TYPE; i++)
1056         {
1057             ps_pic_handling->i4_frms_in_cur_gop[i] = ps_pic_handling->i4_frms_in_gop[i];
1058         }
1059 
1060         i4_b_in_incomp_subgop_mix_gop = i4_b_in_incomp_subgop;
1061         i4_extra_p_mix_gop = i4_extra_p;
1062     }
1063 
1064     /* For bit-allocation the rem_frms_in_gop need to be updated */
1065     /* Checks needed:
1066     1) If the encoding is happening on the same gop as that of the buffering */
1067     if(ps_pic_handling->i4_pic_disp_order_no >=
1068        (i4_max_inter_frm_int - 1 -
1069         ((!i4_is_gop_closed) * ps_pic_handling->i4_b_in_incomp_subgop_mix_gop)))
1070     {
1071         for(i = 0; i < MAX_PIC_TYPE; i++)
1072         {
1073             ps_pic_handling->i4_rem_frms_in_cur_gop +=
1074                 (ps_pic_handling->i4_frms_in_cur_gop[i] - ai4_diff_in_frms[i]);
1075         }
1076         /* If gop is not closed then the difference in previous to next is to be added */
1077         if(!i4_is_gop_closed)
1078             ps_pic_handling->i4_rem_frms_in_cur_gop += (i4_prev_inter_frm_int - i4_inter_frm_int);
1079     }
1080 
1081     /* Update the vars which will affect the proper filling of the pic_stack */
1082     if(i4_pic_disp_order_no == 0) /*Check if redundant*/
1083     {
1084         ps_pic_handling->i4_buf_pic_no = 0;
1085     }
1086     else
1087     {
1088         ps_pic_handling->i4_buf_pic_no = 1;
1089     }
1090 
1091     ps_pic_handling->i4_b_count_in_subgop = 0;
1092 
1093     /* Update the state struct with the new inter_frm_int */
1094     ps_pic_handling->i4_inter_frm_int = i4_inter_frm_int;
1095     ps_pic_handling->i4_intra_frm_int = i4_intra_frm_int;
1096     ps_pic_handling->i4_b_in_incomp_subgop = i4_b_in_incomp_subgop;
1097     ps_pic_handling->i4_extra_p = i4_extra_p;
1098     ps_pic_handling->i4_b_in_incomp_subgop_mix_gop = i4_b_in_incomp_subgop_mix_gop;
1099     ps_pic_handling->i4_extra_p_mix_gop = i4_extra_p_mix_gop;
1100 }
1101 
1102 /* ******************************************************************************/
1103 /**
1104  * @brief Distributes the frames as I, P and B based on intra/inter frame interval.
1105  *  Along with it it fills the number of frames in sub-gop and extra p frame
1106  *
1107  * @param i4_frms_in_gop[MAX_PIC_TYPE]
1108  * @param i4_intra_frm_int
1109  * @param i4_inter_frm_int
1110  * @param i4_is_gop_closed
1111  * @param pi4_b_in_incomp_subgop
1112  * @param pi4_extra_p
1113  */
1114 /* ******************************************************************************/
find_pic_distbn_in_gop(WORD32 i4_frms_in_gop[MAX_PIC_TYPE],WORD32 i4_actual_frms_gop[MAX_PIC_TYPE],WORD32 i4_intra_frm_int,WORD32 i4_inter_frm_int,WORD32 i4_is_gop_closed,WORD32 * pi4_b_in_incomp_subgop,WORD32 * pi4_extra_p,WORD32 i4_num_active_pic_type,WORD32 i4_field_pic)1115 static void find_pic_distbn_in_gop(
1116     WORD32 i4_frms_in_gop[MAX_PIC_TYPE],
1117     WORD32 i4_actual_frms_gop[MAX_PIC_TYPE],
1118     WORD32 i4_intra_frm_int,
1119     WORD32 i4_inter_frm_int,
1120     WORD32 i4_is_gop_closed,
1121     WORD32 *pi4_b_in_incomp_subgop,
1122     WORD32 *pi4_extra_p,
1123     WORD32 i4_num_active_pic_type,
1124     WORD32 i4_field_pic)
1125 {
1126     /* Checks */
1127     WORD32 i;
1128     WORD32 i4_num_b_in_temp_lyr_1 = 0;
1129     /* Find the pic distribution in the gop depending on the inter and intra frm intervals */
1130 
1131     /*init for all pic type*/
1132     for(i = 0; i < MAX_PIC_TYPE; i++)
1133     {
1134         i4_frms_in_gop[i] = 0;
1135     }
1136     /*Atleast 1 in frame in a gop in all conditions possible*/
1137     i4_frms_in_gop[I_PIC] = 1;
1138 
1139     if(i4_intra_frm_int == 1) /* All I frames */
1140     {
1141         i4_frms_in_gop[P_PIC] = 0;
1142         i4_frms_in_gop[B_PIC] = 0;
1143         *pi4_b_in_incomp_subgop = 0;
1144         *pi4_extra_p = 0;
1145     }
1146     else
1147     {
1148         if(i4_is_gop_closed)
1149         {
1150             i4_frms_in_gop[P_PIC] = ((i4_intra_frm_int - 1) / i4_inter_frm_int);
1151         }
1152         else
1153         {
1154             i4_frms_in_gop[P_PIC] = ((i4_intra_frm_int - 1) / i4_inter_frm_int);
1155         }
1156 
1157         /*calculate B pic based on temporal hierarchy*/
1158         if(!i4_is_gop_closed)
1159         {
1160             i4_num_b_in_temp_lyr_1 = i4_frms_in_gop[P_PIC] + i4_frms_in_gop[I_PIC];
1161         }
1162         else
1163         {
1164             i4_num_b_in_temp_lyr_1 = i4_frms_in_gop[P_PIC] - 1 + i4_frms_in_gop[I_PIC];
1165         }
1166 
1167         if(i4_field_pic == 0)
1168         {
1169             /*HEVC_hierarchy*/
1170 
1171             for(i = 2; i < i4_num_active_pic_type; i++)
1172             {
1173                 i4_frms_in_gop[i] = (WORD32)(i4_num_b_in_temp_lyr_1 * pow(2, (i - 2)));
1174             }
1175         }
1176         if(i4_field_pic == 1)
1177         {
1178             i4_frms_in_gop[P1_PIC] = i4_frms_in_gop[P_PIC];
1179             i4_frms_in_gop[P1_PIC] += 1;
1180             /* for the first layer initialisation is done*/
1181             for(i = 2; i < i4_num_active_pic_type; i++)
1182             {
1183                 i4_frms_in_gop[i] = (WORD32)(i4_num_b_in_temp_lyr_1 * pow(2, (i - 2)));
1184                 i4_frms_in_gop[i + FIELD_OFFSET] = i4_frms_in_gop[i];
1185             }
1186         }
1187     }
1188     /*store the true number of pictures in GOP before altering it based on number of non ref and ref B pic*/
1189     for(i = 0; i < MAX_PIC_TYPE; i++)
1190     {
1191         i4_actual_frms_gop[i] = i4_frms_in_gop[i];
1192         trace_printf("PIC TYPES IN GOP of %d type = %d\n", i, i4_frms_in_gop[i]);
1193     }
1194 }
1195 
1196 /******************************************************************************
1197   Function Name   : pic_type_get_intra_frame_interval
1198   Description     :
1199   Arguments       :
1200   Return Values   : intra_frm_int
1201   Revision History:
1202                     Creation
1203 
1204 Assumptions -
1205 
1206 Checks      -
1207 *****************************************************************************/
pic_type_get_intra_frame_interval(pic_handling_t * ps_pic_handling)1208 WORD32 pic_type_get_intra_frame_interval(pic_handling_t *ps_pic_handling)
1209 {
1210     return (ps_pic_handling->i4_intra_frm_int);
1211 }
1212 
1213 /******************************************************************************
1214   Function Name   : pic_type_get_actual_intra_frame_interval
1215   Description     :
1216   Arguments       : ps_pic_handling
1217   Return Values   : void
1218   Revision History:
1219                     Creation
1220 *****************************************************************************/
pic_type_get_actual_intra_frame_interval(pic_handling_t * ps_pic_handling)1221 WORD32 pic_type_get_actual_intra_frame_interval(pic_handling_t *ps_pic_handling)
1222 {
1223     WORD32 i4_intra_frame_int = 0, i = 0;
1224     for(i = 0; i < MAX_PIC_TYPE; i++)
1225         i4_intra_frame_int += ps_pic_handling->i4_actual_frms_in_gop[i];
1226     return (i4_intra_frame_int);
1227 }
1228 /******************************************************************************
1229   Function Name   : pic_type_get_inter_frame_interval
1230   Description     :
1231   Arguments       :
1232   Return Values   : inter_frm_int
1233   Revision History:
1234                     Creation
1235 
1236 Assumptions -
1237 
1238 Checks      -
1239 *****************************************************************************/
pic_type_get_inter_frame_interval(pic_handling_t * ps_pic_handling)1240 WORD32 pic_type_get_inter_frame_interval(pic_handling_t *ps_pic_handling)
1241 {
1242     return (ps_pic_handling->i4_inter_frm_int);
1243 }
1244 
1245 /******************************************************************************
1246   Function Name   : pic_type_get_field_pic
1247   Description     :
1248   Arguments       :
1249   Return Values   : i4_field_pic
1250   Revision History:
1251                     Creation
1252 
1253 Assumptions -
1254 
1255 Checks      -
1256 *****************************************************************************/
pic_type_get_field_pic(pic_handling_t * ps_pic_handling)1257 WORD32 pic_type_get_field_pic(pic_handling_t *ps_pic_handling)
1258 {
1259     return (ps_pic_handling->i4_field_pic);
1260 }
1261 
1262 /******************************************************************************
1263   Function Name   : pic_type_is_gop_closed
1264   Description     :
1265   Arguments       : ps_pic_handling
1266   Return Values   : void
1267   Revision History:
1268                     Creation
1269 *****************************************************************************/
pic_type_is_gop_closed(pic_handling_t * ps_pic_handling)1270 WORD32 pic_type_is_gop_closed(pic_handling_t *ps_pic_handling)
1271 {
1272     return (ps_pic_handling->i4_is_gop_closed);
1273 }
1274 
1275 /******************************************************************************
1276   Function Name   : pic_type_get_rem_frms_in_gop
1277   Description     :
1278   Arguments       :
1279   Return Values   : void
1280   Revision History:
1281                     Creation
1282 
1283 Assumptions -
1284 
1285 Checks      -
1286 *****************************************************************************/
pic_type_get_rem_frms_in_gop(pic_handling_t * ps_pic_handling)1287 WORD32 pic_type_get_rem_frms_in_gop(pic_handling_t *ps_pic_handling)
1288 {
1289     /* memcpy(ai4_rem_frms_in_gop,ps_pic_handling->i4_rem_frms_in_gop,sizeof(ps_pic_handling->i4_rem_frms_in_gop)); */
1290     return (ps_pic_handling->i4_rem_frms_in_cur_gop);
1291 }
1292 /******************************************************************************
1293   Function Name   : pic_type_get_frms_in_gop_force_I_frm
1294   Description     :
1295   Arguments       : ps_pic_handling
1296   Return Values   : void
1297   Revision History:
1298                     Creation
1299 *****************************************************************************/
pic_type_get_frms_in_gop_force_I_frm(pic_handling_t * ps_pic_handling)1300 WORD32 pic_type_get_frms_in_gop_force_I_frm(pic_handling_t *ps_pic_handling)
1301 {
1302     return (ps_pic_handling->i4_frames_in_fif_gop);
1303 }
1304 /******************************************************************************
1305   Function Name   : pic_type_get_frms_in_gop
1306   Description     :
1307   Arguments       :
1308   Return Values   : void
1309   Revision History:
1310                     Creation
1311 
1312 Assumptions -
1313 
1314 Checks      -
1315 *****************************************************************************/
pic_type_get_frms_in_gop(pic_handling_t * ps_pic_handling,WORD32 ai4_frms_in_gop[MAX_PIC_TYPE])1316 void pic_type_get_frms_in_gop(pic_handling_t *ps_pic_handling, WORD32 ai4_frms_in_gop[MAX_PIC_TYPE])
1317 {
1318     memcpy(
1319         ai4_frms_in_gop,
1320         ps_pic_handling->i4_frms_in_cur_gop,
1321         sizeof(ps_pic_handling->i4_frms_in_cur_gop));
1322 }
1323 /******************************************************************************
1324   Function Name   : pic_type_get_actual_frms_in_gop
1325   Description     :
1326   Arguments       :
1327   Return Values   : void
1328   Revision History:
1329                     Creation
1330 
1331 Assumptions -
1332 
1333 Checks      -
1334 *****************************************************************************/
pic_type_get_actual_frms_in_gop(pic_handling_t * ps_pic_handling,WORD32 ai4_frms_in_gop[MAX_PIC_TYPE])1335 void pic_type_get_actual_frms_in_gop(
1336     pic_handling_t *ps_pic_handling, WORD32 ai4_frms_in_gop[MAX_PIC_TYPE])
1337 {
1338     memcpy(
1339         ai4_frms_in_gop,
1340         ps_pic_handling->i4_actual_frms_in_gop,
1341         sizeof(ps_pic_handling->i4_actual_frms_in_gop));
1342 }
1343 
1344 /******************************************************************************
1345   Function Name   : pic_type_get_frms_in_gop
1346   Description     :
1347   Arguments       :
1348   Return Values   : void
1349   Revision History:
1350                     Creation
1351 
1352 Assumptions -
1353 
1354 Checks      -
1355 *****************************************************************************/
pic_type_get_disp_order_no(pic_handling_t * ps_pic_handling)1356 WORD32 pic_type_get_disp_order_no(pic_handling_t *ps_pic_handling)
1357 {
1358     return (ps_pic_handling->i4_pic_disp_order_no);
1359 }
1360 
1361 /******************************************************************************
1362   Function Name   : pic_type_get_frms_in_gop
1363   Description     :
1364   Arguments       :
1365   Return Values   : void
1366   Revision History:
1367                     Creation
1368 
1369 Assumptions -
1370 
1371 Checks      -
1372 *****************************************************************************/
set_force_I_frame_flag(pic_handling_t * ps_pic_handling)1373 void set_force_I_frame_flag(pic_handling_t *ps_pic_handling)
1374 {
1375     ps_pic_handling->i4_force_I_frame = 1;
1376 }
1377 /******************************************************************************
1378   Function Name   : get_is_scd
1379   Description     :
1380   Arguments       : ps_pic_handling
1381   Return Values   : void
1382   Revision History:
1383                     Creation
1384 *****************************************************************************/
get_is_scd(pic_handling_t * ps_pic_handling)1385 WORD32 get_is_scd(pic_handling_t *ps_pic_handling)
1386 {
1387     return (ps_pic_handling->as_pic_stack[ps_pic_handling->i4_stack_count].i4_is_scd);
1388 }
1389 /******************************************************************************/
1390 /* Functions that work on the encoded frames */
1391 /******************************************************************************/
1392 /******************************************************************************
1393   Function Name   : update_pic_handling
1394   Description     : Will be called only for the frames to be encoded
1395   Arguments       :
1396   Return Values   : void
1397   Revision History:
1398                     Creation
1399 
1400 Assumptions -
1401 
1402 Checks      -
1403 *****************************************************************************/
update_pic_handling(pic_handling_t * ps_pic_handling,picture_type_e e_pic_type,WORD32 i4_is_non_ref_pic,WORD32 i4_is_scd_I_frame)1404 void update_pic_handling(
1405     pic_handling_t *ps_pic_handling,
1406     picture_type_e e_pic_type,
1407     WORD32 i4_is_non_ref_pic,
1408     WORD32 i4_is_scd_I_frame)
1409 {
1410     WORD32 i4_max_inter_frm_int;
1411     WORD32 i;
1412 
1413     /* Initializing the local vars with that of the state struct */
1414     i4_max_inter_frm_int = ps_pic_handling->i4_max_inter_frm_int;
1415 
1416     /* Update the variables working on the output frames */
1417     /* Update the stack count */
1418     ps_pic_handling->i4_stack_count++;
1419 
1420     /*i_only reset stack count everytime to zero*/
1421     if(ps_pic_handling->i4_stack_count == (i4_max_inter_frm_int + 1) ||
1422        ps_pic_handling->i4_intra_frm_int == 1)
1423     {
1424         ps_pic_handling->i4_stack_count = 0;
1425     }
1426     if(i4_is_non_ref_pic)
1427     {
1428         ps_pic_handling->i4_non_ref_B_pic_count++;
1429     }
1430 
1431     /*if scd frame assume one frame has been encoded and handle*/
1432     if(i4_is_scd_I_frame || e_pic_type == I_PIC)
1433     {
1434         ps_pic_handling->i4_rem_frms_in_cur_gop = 0;
1435         for(i = 0; i < MAX_PIC_TYPE; i++)
1436         {
1437             ps_pic_handling->i4_rem_frms_in_cur_gop += ps_pic_handling->i4_actual_frms_in_gop[i];
1438         }
1439     }
1440     /* Update the rem_frms_in_gop */
1441     /*HEVC_RC: update rem frms in cur gop counter only once for two reference pic (based on weightage)
1442      This is assuming non reference pic comes sequentially*/
1443     //if(!i4_is_non_ref_pic || ps_pic_handling->i4_non_ref_B_pic_count == NUM_NON_REF_B_EQE)
1444     {
1445         ps_pic_handling->i4_rem_frms_in_cur_gop--;
1446         ps_pic_handling->i4_non_ref_B_pic_count = 0;
1447     }
1448 
1449     /* Assumption : Rem_frms_in_gop needs to be taken care of, for every change in frms */
1450     ps_pic_handling->i4_last_frm_in_gop = 0;
1451     if(ps_pic_handling->i4_rem_frms_in_cur_gop == 0)
1452     {
1453         /* Copy the cur_frms_in_gop to the rem_frm_in_gop */
1454         ps_pic_handling->i4_rem_frms_in_cur_gop = 0;
1455         for(i = 0; i < MAX_PIC_TYPE; i++)
1456         {
1457             ps_pic_handling->i4_rem_frms_in_cur_gop += ps_pic_handling->i4_actual_frms_in_gop[i];
1458             //ASSERT(ps_pic_handling->i4_actual_frms_in_gop[B2_PIC] == 0);
1459         }
1460 
1461         ps_pic_handling->i4_last_frm_in_gop = 1;
1462         ps_pic_handling->i4_first_gop_encoded = 1;
1463     }
1464 }
1465 /******************************************************************************
1466   Function Name   : is_last_frame_in_gop
1467   Description     :
1468   Arguments       : ps_pic_handling
1469   Return Values   : void
1470   Revision History:
1471                     Creation
1472 *****************************************************************************/
is_last_frame_in_gop(pic_handling_handle ps_pic_handling)1473 WORD32 is_last_frame_in_gop(pic_handling_handle ps_pic_handling)
1474 {
1475     return (ps_pic_handling->i4_last_frm_in_gop);
1476 }
1477 
1478 /******************************************************************************
1479   Function Name   : skip_encoded_frame
1480   Description     : Needs to go to the current pic in the pic_stack.
1481                     If it's B_PIC don't do anything
1482                     If it's a reference picture, push all but the last B_PICs
1483                     in the current subgop one place down (i.e. just copy their pic_details)
1484                     and move the last B_PIC in that subgop to the next slot of the
1485                     skipped picture and convert it's pic_type to that of the reference picture
1486 
1487 
1488   Arguments       :
1489   Return Values   : void
1490   Revision History:
1491                     Creation
1492 
1493 Assumptions -
1494 
1495 Checks      -
1496 *****************************************************************************/
skip_encoded_frame(pic_handling_t * ps_pic_handling,picture_type_e e_pic_type)1497 void skip_encoded_frame(pic_handling_t *ps_pic_handling, picture_type_e e_pic_type)
1498 {
1499     pic_details_t s_pic_details;
1500     WORD32 i4_stack_count, i4_next_ref_pic_idx, i4_pic_idx;
1501     WORD32 i4_max_inter_frm_int, i4_last_b_pic_idx, i4_first_b_pic_idx;
1502     WORD32 i4_next_pic_idx;
1503 
1504     /* State variables used to initialize the local vars (Not to be changed) */
1505     i4_stack_count = ps_pic_handling->i4_stack_count;
1506     i4_next_ref_pic_idx = ps_pic_handling->i4_ref_pic_idx;
1507     i4_max_inter_frm_int = ps_pic_handling->i4_max_inter_frm_int;
1508 
1509     i4_next_pic_idx = ((i4_stack_count + 1) % (i4_max_inter_frm_int + 1));
1510 
1511     /* Check what is the encoded frm_type
1512        Changing a B_PIC to a ref_pic is not reqd if
1513        there are no B_PICs referring from the skipped ref_pic */
1514     if(((e_pic_type == P_PIC) || (e_pic_type == I_PIC)) && (i4_next_pic_idx != i4_next_ref_pic_idx))
1515     {
1516         /* Go to the last B_PIC before the next_ref_pic */
1517         if(i4_next_ref_pic_idx == 0)
1518         {
1519             i4_last_b_pic_idx = i4_max_inter_frm_int;
1520         }
1521         else
1522         {
1523             i4_last_b_pic_idx = (i4_next_ref_pic_idx - 1);
1524         }
1525 
1526         /* Keep a copy of the last B_PIC pic_details */
1527         memcpy(
1528             &s_pic_details,
1529             &ps_pic_handling->as_pic_stack[i4_last_b_pic_idx],
1530             sizeof(pic_details_t));
1531 
1532         i4_pic_idx = i4_last_b_pic_idx;
1533         i4_first_b_pic_idx = (i4_stack_count + 1) % (i4_max_inter_frm_int + 1);
1534 
1535         /* All the B_PICs other than the last one, need to be shifted one place in the stack */
1536         while((i4_pic_idx != i4_stack_count) && (i4_first_b_pic_idx != i4_last_b_pic_idx))
1537         {
1538             if(i4_pic_idx == 0)
1539             {
1540                 i4_pic_idx = i4_max_inter_frm_int;
1541             }
1542             else
1543             {
1544                 i4_pic_idx--;
1545             }
1546 
1547             memcpy(
1548                 &ps_pic_handling->as_pic_stack[(i4_pic_idx + 1) % (i4_max_inter_frm_int + 1)],
1549                 &ps_pic_handling->as_pic_stack[i4_pic_idx],
1550                 sizeof(pic_details_t));
1551         }
1552 
1553         /* Check what type of ref_pic it is */
1554         /*if(ps_pic_handling->i4_p_count_in_gop >= ps_pic_handling->i4_frms_in_cur_gop[P_PIC])
1555         {
1556             e_ref_pic_type = I_PIC;
1557         }
1558         else
1559         {
1560             e_ref_pic_type = P_PIC;
1561         }*/
1562 
1563         /* Copy the last B_PIC pic_details to the first B_PIC place and change it's pic type to the ref_PIC */
1564         ps_pic_handling->as_pic_stack[i4_first_b_pic_idx].e_pic_type = P_PIC; /*e_ref_pic_type*/
1565         ;
1566         ps_pic_handling->as_pic_stack[i4_first_b_pic_idx].i4_pic_disp_order_no =
1567             s_pic_details.i4_pic_disp_order_no;
1568         ps_pic_handling->as_pic_stack[i4_first_b_pic_idx].i4_pic_id = s_pic_details.i4_pic_id;
1569     }
1570 }
1571 
1572 /******************************************************************************
1573   Function Name   : flush_frame
1574   Description     : Since when a flush frame is called, there will be no valid
1575                     frames after it, the last frame cannot be a B_PIC, as there
1576                     will be no reference frame for it (Input in display order)
1577 
1578                     So,this fxn needs to go to the last added pic in the pic_stack.
1579                     If it's reference pic don't do anything
1580                     If it's a B_PIC, copy it's pic_details and put it in the
1581                     place of the next reference pic, changing the pic_type to
1582                     P_PIC
1583 
1584   Arguments       :
1585   Return Values   : void
1586   Revision History:
1587                     Creation
1588 
1589 Assumptions -
1590 
1591 Checks      -
1592 *****************************************************************************/
flush_frame_from_pic_stack(pic_handling_t * ps_pic_handling)1593 void flush_frame_from_pic_stack(pic_handling_t *ps_pic_handling)
1594 {
1595     pic_details_t s_prev_pic_details;
1596 
1597     /* Get the last entered pic_details (not to be modified here) */
1598     WORD32 i4_prev_b_pic_idx = ps_pic_handling->i4_prev_b_pic_idx;
1599     WORD32 i4_ref_pic_idx = ps_pic_handling->i4_ref_pic_idx;
1600     WORD32 i4_b_pic_idx = ps_pic_handling->i4_b_pic_idx;
1601 
1602     memcpy(&s_prev_pic_details, &ps_pic_handling->s_prev_pic_details, sizeof(pic_details_t));
1603 
1604     if(s_prev_pic_details.e_pic_type == B_PIC)
1605     {
1606         /* Copy the last B_PIC details to the next reference pic in display order */
1607         ps_pic_handling->as_pic_stack[i4_ref_pic_idx].i4_pic_disp_order_no =
1608             s_prev_pic_details.i4_pic_disp_order_no;
1609         ps_pic_handling->as_pic_stack[i4_ref_pic_idx].i4_pic_id = s_prev_pic_details.i4_pic_id;
1610         ps_pic_handling->as_pic_stack[i4_ref_pic_idx].e_pic_type = P_PIC;
1611 
1612         /* Modify the last B_PIC pic_type, so that codec gets to know when all the buffered frames
1613            are flushed */
1614         ps_pic_handling->as_pic_stack[i4_prev_b_pic_idx].e_pic_type = MAX_PIC_TYPE;
1615         ps_pic_handling->as_pic_stack[i4_prev_b_pic_idx].i4_pic_id = -1;
1616         ps_pic_handling->as_pic_stack[i4_prev_b_pic_idx].i4_pic_disp_order_no = -1;
1617     }
1618     else
1619     {
1620         /* Modify the next pic_type details in the stack, so that codec gets to know when all the
1621            buffered frames are flushed */
1622         ps_pic_handling->as_pic_stack[i4_ref_pic_idx].e_pic_type = MAX_PIC_TYPE;
1623         ps_pic_handling->as_pic_stack[i4_ref_pic_idx].i4_pic_id = -1;
1624         ps_pic_handling->as_pic_stack[i4_ref_pic_idx].i4_pic_disp_order_no = -1;
1625 
1626         if(ps_pic_handling->i4_inter_frm_int != 1)
1627         {
1628             ps_pic_handling->as_pic_stack[i4_b_pic_idx].e_pic_type = MAX_PIC_TYPE;
1629             ps_pic_handling->as_pic_stack[i4_b_pic_idx].i4_pic_id = -1;
1630             ps_pic_handling->as_pic_stack[i4_b_pic_idx].i4_pic_disp_order_no = -1;
1631         }
1632     }
1633 }
1634 
1635 /********************************************************************************************/
1636 /******************************************************************************
1637   Function Name   : add_pic_to_stack_re_enc
1638   Description     : In case of a re-enc, we can assume the pictures to be coming
1639                     in the encode order.
1640                     In case of re-encoder basically, there are 2 problematic cases.
1641                     1)Inter_frm_int is not known to start with
1642                     2)Inter_frm_int can keep changing
1643                     3)Intra_frm_int set by the application and that actually in the
1644                       decoded bitstream may be different
1645 
1646   Arguments       :
1647   Return Values   : WORD32
1648   Revision History:
1649                     Creation
1650 
1651 Assumptions -
1652 
1653 Checks      -
1654 *****************************************************************************/
add_pic_to_stack_re_enc(pic_handling_t * ps_pic_handling,WORD32 i4_enc_pic_id,picture_type_e e_pic_type)1655 WORD32 add_pic_to_stack_re_enc(
1656     pic_handling_t *ps_pic_handling, WORD32 i4_enc_pic_id, picture_type_e e_pic_type)
1657 {
1658     WORD32 i4_b_count_in_subgop;
1659     WORD32 i4_max_inter_frm_int, i4_inter_frm_int, i4_intra_frm_int;
1660     WORD32 i4_pic_disp_order_no;
1661     WORD32 i4_is_gop_closed;
1662     picture_type_e e_out_pic_type;
1663     WORD32 i4_b_in_incomp_subgop;
1664 
1665     /* Check if a change in intra_frm_int call has been made */
1666     if(ps_pic_handling->i4_change_in_intra_frm_int == 1)
1667     {
1668         update_pic_distbn(
1669             ps_pic_handling,
1670             ps_pic_handling->i4_new_intra_frm_int,
1671             ps_pic_handling->i4_inter_frm_int,
1672             1);
1673         ps_pic_handling->i4_change_in_intra_frm_int = 0;
1674     }
1675 
1676     /* Check if a change in inter_frm_int call has been made */
1677     if(ps_pic_handling->i4_change_in_inter_frm_int == 1)
1678     {
1679         update_pic_distbn(
1680             ps_pic_handling,
1681             ps_pic_handling->i4_intra_frm_int,
1682             ps_pic_handling->i4_new_inter_frm_int,
1683             1);
1684 
1685         ps_pic_handling->i4_change_in_inter_frm_int = 0;
1686     }
1687 
1688     /* Initialize the local vars with the state vars */
1689     i4_b_count_in_subgop = ps_pic_handling->i4_b_count_in_subgop;
1690     i4_max_inter_frm_int = ps_pic_handling->i4_max_inter_frm_int;
1691     i4_inter_frm_int = ps_pic_handling->i4_inter_frm_int;
1692     i4_intra_frm_int = ps_pic_handling->i4_intra_frm_int;
1693     i4_pic_disp_order_no = ps_pic_handling->i4_pic_disp_order_no;
1694     i4_is_gop_closed = ps_pic_handling->i4_is_gop_closed;
1695     i4_b_in_incomp_subgop = ps_pic_handling->i4_b_in_incomp_subgop;
1696 
1697     e_out_pic_type = e_pic_type;
1698 
1699     /* Initially the rate_control assumes an IPP sequence */
1700     if(e_pic_type == B_PIC)
1701     {
1702         /* Update the number of B_PICs in a subgop */
1703         i4_b_count_in_subgop++;
1704 
1705         if(i4_b_count_in_subgop > i4_max_inter_frm_int)
1706         {
1707             return (-1);
1708         }
1709 
1710         /* If the number of B_PICs exceed the set inter_frm_int then
1711            change the inter_frm_int */
1712         if(i4_b_count_in_subgop > (i4_inter_frm_int - 1))
1713         {
1714             i4_inter_frm_int = (i4_b_count_in_subgop + 1);
1715 
1716             update_pic_distbn(ps_pic_handling, i4_intra_frm_int, i4_inter_frm_int, 0);
1717         }
1718     }
1719     else if((e_pic_type == I_PIC) || (e_pic_type == P_PIC))
1720     {
1721         /* If the B_PICs in the prev subgop were fewer than the current (inter_frm_int-1)
1722            and none of these conditions occur, it'll mean the decrease in the inter_frm_int
1723            1)End of a GOP
1724            2)Beginning of an OPEN_GOP
1725         */
1726         if((i4_b_count_in_subgop < (i4_inter_frm_int - 1)) &&
1727            !((!i4_is_gop_closed) && (i4_b_count_in_subgop >= i4_b_in_incomp_subgop)) &&
1728            !((i4_pic_disp_order_no + (i4_inter_frm_int - 1 - i4_b_count_in_subgop)) >
1729              i4_intra_frm_int))
1730         {
1731             i4_inter_frm_int = (i4_b_count_in_subgop + 1);
1732 
1733             update_pic_distbn(ps_pic_handling, i4_intra_frm_int, i4_inter_frm_int, 0);
1734         }
1735 
1736         /* Reset the number of B_PICs in a subgop */
1737         i4_b_count_in_subgop = 0;
1738     }
1739 
1740     /* Updation of the frame level vars */
1741     i4_pic_disp_order_no++;
1742 
1743     /* End of gop condition
1744        Two cases can arise :
1745        1) The intra_frm_int set by the application is greater than the actual bitstream intra_frm_int
1746           (i.e. we will get an I frame before pic_disp_order_no goes to intra_frm_int)
1747        2) The intra_frm_int set by the application is smaller than the actual bitstream intra_frm_int
1748           (i.e. we won't get an I_PIC even if pic_disp_order_no goes to intra_frm_int)
1749        Constraints :
1750        1) I_PIC cannot be changed to B_PIC
1751        2) B_PIC cannot be changed to I_PIC */
1752     if(i4_pic_disp_order_no >= i4_intra_frm_int)
1753     {
1754         if(e_pic_type != B_PIC)
1755         {
1756             e_out_pic_type = I_PIC;
1757         }
1758         else
1759         {
1760             e_out_pic_type = B_PIC;
1761             ps_pic_handling->i4_rem_frms_in_cur_gop++;
1762             ps_pic_handling->i4_frms_in_cur_gop[B_PIC]++;
1763             ps_pic_handling->i4_frms_in_gop[B_PIC]++;
1764         }
1765     }
1766     else
1767     {
1768         if((e_pic_type == I_PIC) && (!ps_pic_handling->i4_is_first_gop))
1769         {
1770             e_out_pic_type = P_PIC;
1771             ps_pic_handling->i4_rem_frms_in_cur_gop++;
1772             ps_pic_handling->i4_frms_in_cur_gop[P_PIC]++;
1773             ps_pic_handling->i4_frms_in_gop[P_PIC]++;
1774         }
1775         else
1776         {
1777             e_out_pic_type = e_pic_type;
1778         }
1779     }
1780 
1781     /* Update the frm_vars at the end of the gop */
1782     if(i4_pic_disp_order_no == (ps_pic_handling->i4_frms_in_cur_gop[P_PIC] +
1783                                 ps_pic_handling->i4_frms_in_cur_gop[B_PIC] + 1))
1784     {
1785         i4_pic_disp_order_no = 0;
1786         ps_pic_handling->i4_is_first_gop = 0;
1787     }
1788 
1789     /* Update the vars working on the encoded pics */
1790     if((ps_pic_handling->i4_is_first_gop) && (ps_pic_handling->i4_stack_count == -1))
1791     {
1792         ps_pic_handling->i4_coded_pic_no = 0;
1793         ps_pic_handling->i4_stack_count = 0;
1794     }
1795 
1796     /* Add the pic_details to the pic_stack */
1797     ps_pic_handling->as_pic_stack[ps_pic_handling->i4_stack_count].e_pic_type = e_out_pic_type;
1798     ps_pic_handling->as_pic_stack[ps_pic_handling->i4_stack_count].i4_pic_disp_order_no =
1799         ps_pic_handling->i4_pic_disp_order_no;
1800     ps_pic_handling->as_pic_stack[ps_pic_handling->i4_stack_count].i4_pic_id = i4_enc_pic_id;
1801 
1802     /* Writing back those values which need to be updated */
1803     ps_pic_handling->i4_inter_frm_int = i4_inter_frm_int;
1804     ps_pic_handling->i4_pic_disp_order_no = i4_pic_disp_order_no;
1805     ps_pic_handling->i4_b_count_in_subgop = i4_b_count_in_subgop;
1806 
1807     return (0);
1808 }
1809 
1810 /******************************************************************************
1811   Function Name   : pic_type_update_frms_in_gop
1812   Description     : Update current gop from lap data
1813   Arguments       : ps_pic_handling
1814   Return Values   : void
1815   Revision History:
1816                     Creation
1817 *****************************************************************************/
1818 
pic_type_update_frms_in_gop(pic_handling_t * ps_pic_handling,WORD32 ai4_frms_in_gop[MAX_PIC_TYPE])1819 void pic_type_update_frms_in_gop(
1820     pic_handling_t *ps_pic_handling, WORD32 ai4_frms_in_gop[MAX_PIC_TYPE])
1821 {
1822     memmove(
1823         ps_pic_handling->i4_frms_in_cur_gop,
1824         ai4_frms_in_gop,
1825         sizeof(ps_pic_handling->i4_frms_in_cur_gop));
1826     memmove(
1827         ps_pic_handling->i4_actual_frms_in_gop,
1828         ai4_frms_in_gop,
1829         sizeof(ps_pic_handling->i4_actual_frms_in_gop));
1830 }
1831 /******************************************************************************
1832   Function Name   : get_default_intra_period
1833   Description     :
1834   Arguments       : ps_pic_handling
1835   Return Values   : void
1836   Revision History:
1837                     Creation
1838 *****************************************************************************/
get_default_intra_period(pic_handling_t * ps_pic_handling)1839 WORD32 get_default_intra_period(pic_handling_t *ps_pic_handling)
1840 {
1841     return (ps_pic_handling->i4_intra_frm_int);
1842 }
1843