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