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