1 /******************************************************************************
2 *
3 * Copyright (C) 2012 Ittiam Systems Pvt Ltd, Bangalore
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 /**
19 *******************************************************************************
20 * @file
21 * ihevcd_utils.c
22 *
23 * @brief
24 * Contains miscellaneous utility functions such as init() etc
25 *
26 * @author
27 * Harish
28 *
29 * @par List of Functions:
30 *
31 * @remarks
32 * None
33 *
34 *******************************************************************************
35 */
36 /*****************************************************************************/
37 /* File Includes */
38 /*****************************************************************************/
39 #include <stdio.h>
40 #include <stddef.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <assert.h>
44
45 #include "ihevc_typedefs.h"
46 #include "iv.h"
47 #include "ivd.h"
48 #include "ihevcd_cxa.h"
49 #include "ithread.h"
50
51 #include "ihevc_defs.h"
52 #include "ihevc_debug.h"
53 #include "ihevc_defs.h"
54 #include "ihevc_error.h"
55 #include "ihevc_structs.h"
56 #include "ihevc_buf_mgr.h"
57 #include "ihevc_dpb_mgr.h"
58 #include "ihevc_macros.h"
59 #include "ihevc_platform_macros.h"
60
61 #include "ihevc_common_tables.h"
62 #include "ihevc_buf_mgr.h"
63 #include "ihevc_disp_mgr.h"
64 #include "ihevc_cabac_tables.h"
65
66 #include "ihevcd_defs.h"
67
68 #include "ihevcd_function_selector.h"
69 #include "ihevcd_structs.h"
70 #include "ihevcd_error.h"
71 #include "ihevcd_nal.h"
72 #include "ihevcd_bitstream.h"
73 #include "ihevcd_utils.h"
74 #include "ihevcd_trace.h"
75 #include "ihevcd_process_slice.h"
76 #include "ihevcd_job_queue.h"
77 #define MAX_DPB_PIC_BUF 6
78
79 /* Function declarations */
80 mv_buf_t* ihevcd_mv_mgr_get_poc(buf_mgr_t *ps_mv_buf_mgr, UWORD32 abs_poc);
81
82 /**
83 *******************************************************************************
84 *
85 * @brief
86 * Used to get level index for a given level
87 *
88 * @par Description:
89 * Converts from level_idc (which is multiplied by 30) to an index that can be
90 * used as a lookup. Also used to ignore invalid levels like 2.2 , 3.2 etc
91 *
92 * @param[in] level
93 * Level of the stream
94 *
95 * @returns Level index for a given level
96 *
97 * @remarks
98 *
99 *
100 *******************************************************************************
101 */
ihevcd_get_lvl_idx(WORD32 level)102 WORD32 ihevcd_get_lvl_idx(WORD32 level)
103 {
104 WORD32 lvl_idx = 0;
105
106 if(level < IHEVC_LEVEL_20)
107 {
108 lvl_idx = 0;
109 }
110 else if(level >= IHEVC_LEVEL_20 && level < IHEVC_LEVEL_21)
111 {
112 lvl_idx = 1;
113 }
114 else if(level >= IHEVC_LEVEL_21 && level < IHEVC_LEVEL_30)
115 {
116 lvl_idx = 2;
117 }
118 else if(level >= IHEVC_LEVEL_30 && level < IHEVC_LEVEL_31)
119 {
120 lvl_idx = 3;
121 }
122 else if(level >= IHEVC_LEVEL_31 && level < IHEVC_LEVEL_40)
123 {
124 lvl_idx = 4;
125 }
126 else if(level >= IHEVC_LEVEL_40 && level < IHEVC_LEVEL_41)
127 {
128 lvl_idx = 5;
129 }
130 else if(level >= IHEVC_LEVEL_41 && level < IHEVC_LEVEL_50)
131 {
132 lvl_idx = 6;
133 }
134 else if(level >= IHEVC_LEVEL_50 && level < IHEVC_LEVEL_51)
135 {
136 lvl_idx = 7;
137 }
138 else if(level >= IHEVC_LEVEL_51 && level < IHEVC_LEVEL_52)
139 {
140 lvl_idx = 8;
141 }
142 else if(level >= IHEVC_LEVEL_52 && level < IHEVC_LEVEL_60)
143 {
144 lvl_idx = 9;
145 }
146 else if(level >= IHEVC_LEVEL_60 && level < IHEVC_LEVEL_61)
147 {
148 lvl_idx = 10;
149 }
150 else if(level >= IHEVC_LEVEL_61 && level < IHEVC_LEVEL_62)
151 {
152 lvl_idx = 11;
153 }
154 else if(level >= IHEVC_LEVEL_62)
155 {
156 lvl_idx = 12;
157 }
158
159 return (lvl_idx);
160 }
161
162 /**
163 *******************************************************************************
164 *
165 * @brief
166 * Used to get reference picture buffer size for a given level and
167 * and padding used
168 *
169 * @par Description:
170 * Used to get reference picture buffer size for a given level and padding used
171 * Each picture is padded on all four sides
172 *
173 * @param[in] pic_size
174 * Mumber of luma samples (Width * Height)
175 *
176 * @param[in] level
177 * Level
178 *
179 * @param[in] horz_pad
180 * Total padding used in horizontal direction
181 *
182 * @param[in] vert_pad
183 * Total padding used in vertical direction
184 *
185 * @returns Total picture buffer size
186 *
187 * @remarks
188 *
189 *
190 *******************************************************************************
191 */
ihevcd_get_total_pic_buf_size(codec_t * ps_codec,WORD32 wd,WORD32 ht)192 WORD32 ihevcd_get_total_pic_buf_size(codec_t *ps_codec,
193 WORD32 wd,
194 WORD32 ht)
195 {
196 WORD32 size;
197 WORD32 num_luma_samples;
198 WORD32 max_dpb_size;
199 WORD32 num_samples;
200
201
202 sps_t *ps_sps = (ps_codec->s_parse.ps_sps_base + ps_codec->i4_sps_id);
203
204 /* Get maximum number of buffers for the current picture size */
205 max_dpb_size = ps_sps->ai1_sps_max_dec_pic_buffering[ps_sps->i1_sps_max_sub_layers - 1];
206
207 if(ps_codec->e_frm_out_mode != IVD_DECODE_FRAME_OUT)
208 max_dpb_size += ps_sps->ai1_sps_max_num_reorder_pics[ps_sps->i1_sps_max_sub_layers - 1];
209
210 max_dpb_size++;
211 /* Allocation is required for
212 * (Wd + horz_pad) * (Ht + vert_pad) * (2 * max_dpb_size + 1)
213 */
214
215 /* Account for padding area */
216 num_luma_samples = (wd + PAD_WD) * (ht + PAD_HT);
217
218 /* Account for chroma */
219 num_samples = num_luma_samples * 3 / 2;
220
221 /* Number of bytes in reference pictures */
222 size = num_samples * max_dpb_size;
223
224
225 return size;
226 }
227 /**
228 *******************************************************************************
229 *
230 * @brief
231 * Used to get MV bank size for a given number of luma samples
232 *
233 * @par Description:
234 * For given number of luma samples one MV bank size is computed
235 * Each MV bank includes pu_map and pu_t for all the min PUs(4x4) in a picture
236 *
237 * @param[in] num_luma_samples
238 * Max number of luma pixels in the frame
239 *
240 * @returns Total MV Bank size
241 *
242 * @remarks
243 *
244 *
245 *******************************************************************************
246 */
ihevcd_get_pic_mv_bank_size(WORD32 num_luma_samples)247 WORD32 ihevcd_get_pic_mv_bank_size(WORD32 num_luma_samples)
248 {
249 WORD32 size;
250
251 WORD32 pic_size;
252
253 WORD32 mv_bank_size;
254 WORD32 num_pu;
255 WORD32 num_ctb;
256 pic_size = num_luma_samples;
257
258
259 num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE);
260 num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
261
262 mv_bank_size = 0;
263
264 /* Size for storing pu_t start index each CTB */
265 /* One extra entry is needed to compute number of PUs in the last CTB */
266 mv_bank_size += (num_ctb + 1) * sizeof(WORD32);
267
268 /* Size for pu_map */
269 mv_bank_size += num_pu;
270
271 /* Size for storing pu_t for each PU */
272 mv_bank_size += num_pu * sizeof(pu_t);
273
274 /* Size for storing slice_idx for each CTB */
275 mv_bank_size += ALIGN4(num_ctb * sizeof(UWORD16));
276
277 size = mv_bank_size;
278 return size;
279 }
280 /**
281 *******************************************************************************
282 *
283 * @brief
284 * Used to get TU data size for a given number luma samples
285 *
286 * @par Description:
287 * For a given number of luma samples TU data size is computed
288 * Each TU data includes tu_map and tu_t and coeff data for all
289 * the min TUs(4x4) in given CTB
290 *
291 * @param[in] num_luma_samples
292 * Number of 64 x 64 CTBs for which TU data has to be allocated.
293 *
294 * @returns Total TU data size
295 *
296 * @remarks Assumption is num_luma_samples will be at least
297 * 64 x 64 to handle CTB of size 64 x 64. Can be frame size as well
298 *
299 *******************************************************************************
300 */
ihevcd_get_tu_data_size(WORD32 num_luma_samples)301 WORD32 ihevcd_get_tu_data_size(WORD32 num_luma_samples)
302 {
303
304
305 WORD32 tu_data_size;
306 WORD32 num_ctb;
307 WORD32 num_luma_tu, num_chroma_tu, num_tu;
308 num_ctb = num_luma_samples / (MIN_CTB_SIZE * MIN_CTB_SIZE);
309
310 num_luma_tu = num_luma_samples / (MIN_TU_SIZE * MIN_TU_SIZE);
311 num_chroma_tu = num_luma_tu >> 1;
312
313 num_tu = num_luma_tu + num_chroma_tu;
314 tu_data_size = 0;
315
316 /* Size for storing tu_t start index each CTB */
317 /* One extra entry is needed to compute number of TUs in the last CTB */
318 tu_data_size += (num_ctb + 1) * sizeof(WORD32);
319
320 /* Size for storing tu map */
321 tu_data_size += num_luma_tu * sizeof(UWORD8);
322
323 /* Size for storing tu_t for each TU */
324 tu_data_size += num_tu * sizeof(tu_t);
325
326 /* Size for storing number of coded subblocks and scan_idx for each TU */
327 tu_data_size += num_tu * (sizeof(WORD8) + sizeof(WORD8));
328
329 /* Size for storing coeff data for each TU */
330 tu_data_size += num_tu * sizeof(tu_sblk_coeff_data_t);
331
332
333 return tu_data_size;
334 }
335
336
ihevcd_nctb_cnt(codec_t * ps_codec,sps_t * ps_sps)337 WORD32 ihevcd_nctb_cnt(codec_t *ps_codec, sps_t *ps_sps)
338 {
339 WORD32 nctb = 1;
340 UNUSED(ps_codec);
341 //TODO: Currently set to 1
342 /* If CTB size is less than 32 x 32 then set nCTB as 4 */
343 if(ps_sps->i1_log2_ctb_size < 5)
344 nctb = 1;
345
346 return nctb;
347 }
348
ihevcd_get_tile_pos(pps_t * ps_pps,sps_t * ps_sps,WORD32 ctb_x,WORD32 ctb_y,WORD32 * pi4_ctb_tile_x,WORD32 * pi4_ctb_tile_y,WORD32 * pi4_tile_idx)349 IHEVCD_ERROR_T ihevcd_get_tile_pos(pps_t *ps_pps,
350 sps_t *ps_sps,
351 WORD32 ctb_x,
352 WORD32 ctb_y,
353 WORD32 *pi4_ctb_tile_x,
354 WORD32 *pi4_ctb_tile_y,
355 WORD32 *pi4_tile_idx)
356 {
357
358 tile_t *ps_tile_tmp;
359 WORD32 i;
360 WORD32 tile_row, tile_col;
361
362 if(ctb_x < 0 || ctb_y < 0)
363 {
364 *pi4_ctb_tile_x = 0;
365 *pi4_ctb_tile_y = 0;
366 *pi4_tile_idx = 0;
367
368 return (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
369 }
370
371 tile_row = 0;
372 tile_col = 0;
373 ps_tile_tmp = ps_pps->ps_tile;
374 if(0 == ps_pps->i1_tiles_enabled_flag)
375 {
376 *pi4_ctb_tile_x = ctb_x;
377 *pi4_ctb_tile_y = ctb_y;
378 *pi4_tile_idx = 0;
379 }
380 else
381 {
382 for(i = 0; i < ps_pps->i1_num_tile_columns; i++)
383 {
384 WORD16 next_tile_ctb_x;
385 ps_tile_tmp = ps_pps->ps_tile + i; //* ps_pps->i1_num_tile_rows;
386 if((ps_pps->i1_num_tile_columns - 1) == i)
387 {
388 next_tile_ctb_x = ps_sps->i2_pic_wd_in_ctb;
389 }
390 else
391 {
392 tile_t *ps_tile_next_tmp;
393 ps_tile_next_tmp = ps_pps->ps_tile + i + 1;
394 next_tile_ctb_x = ps_tile_next_tmp->u1_pos_x;
395 }
396 if((ctb_x >= ps_tile_tmp->u1_pos_x) && (ctb_x < next_tile_ctb_x))
397 {
398 tile_col = i;
399 break;
400 }
401 }
402 *pi4_ctb_tile_x = ctb_x - ps_tile_tmp->u1_pos_x;
403
404 for(i = 0; i < ps_pps->i1_num_tile_rows; i++)
405 {
406 WORD16 next_tile_ctb_y;
407 ps_tile_tmp = ps_pps->ps_tile + i * ps_pps->i1_num_tile_columns;
408 if((ps_pps->i1_num_tile_rows - 1) == i)
409 {
410 next_tile_ctb_y = ps_sps->i2_pic_ht_in_ctb;
411 }
412 else
413 {
414 tile_t *ps_tile_next_tmp;
415 ps_tile_next_tmp = ps_pps->ps_tile + ((i + 1) * ps_pps->i1_num_tile_columns);
416 next_tile_ctb_y = ps_tile_next_tmp->u1_pos_y;
417 }
418 if((ctb_y >= ps_tile_tmp->u1_pos_y) && (ctb_y < next_tile_ctb_y))
419 {
420 tile_row = i;
421 break;
422 }
423
424 }
425 *pi4_ctb_tile_y = ctb_y - ps_tile_tmp->u1_pos_y;
426 *pi4_tile_idx = tile_row * ps_pps->i1_num_tile_columns
427 + tile_col;
428 }
429 return (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
430 }
431 /**
432 *******************************************************************************
433 *
434 * @brief
435 * Function to initialize ps_pic_buf structs add pic buffers to
436 * buffer manager in case of non-shared mode
437 *
438 * @par Description:
439 * Function to initialize ps_pic_buf structs add pic buffers to
440 * buffer manager in case of non-shared mode
441 * To be called once per stream or for every reset
442 *
443 * @param[in] ps_codec
444 * Pointer to codec context
445 *
446 * @returns Error from IHEVCD_ERROR_T
447 *
448 * @remarks
449 *
450 *
451 *******************************************************************************
452 */
ihevcd_pic_buf_mgr_add_bufs(codec_t * ps_codec)453 IHEVCD_ERROR_T ihevcd_pic_buf_mgr_add_bufs(codec_t *ps_codec)
454 {
455 IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
456 WORD32 i;
457 WORD32 max_dpb_size;
458 sps_t *ps_sps;
459 UWORD8 *pu1_buf;
460 pic_buf_t *ps_pic_buf;
461 WORD32 pic_buf_size_allocated;
462
463
464
465
466 /* Initialize Pic buffer manager */
467 ps_sps = ps_codec->s_parse.ps_sps;
468
469 /* Compute the number of Pic buffers needed */
470 max_dpb_size = ps_sps->ai1_sps_max_dec_pic_buffering[ps_sps->i1_sps_max_sub_layers - 1];
471
472 if(ps_codec->e_frm_out_mode != IVD_DECODE_FRAME_OUT)
473 max_dpb_size += ps_sps->ai1_sps_max_num_reorder_pics[ps_sps->i1_sps_max_sub_layers - 1];
474
475 /* Allocate one extra picture to handle current frame
476 * In case of asynchronous parsing and processing, number of buffers should increase here
477 * based on when parsing and processing threads are synchronized
478 */
479 max_dpb_size++;
480
481
482 pu1_buf = (UWORD8 *)ps_codec->pu1_ref_pic_buf_base;
483
484 ps_pic_buf = (pic_buf_t *)ps_codec->ps_pic_buf;
485
486 /* In case of non-shared mode, add picture buffers to buffer manager
487 * In case of shared mode buffers are added in the run-time
488 */
489 if(0 == ps_codec->i4_share_disp_buf)
490 {
491 WORD32 buf_ret;
492 WORD32 luma_samples;
493 WORD32 chroma_samples;
494 pic_buf_size_allocated = ps_codec->i4_total_pic_buf_size;
495
496 luma_samples = (ps_codec->i4_strd) *
497 (ps_sps->i2_pic_height_in_luma_samples + PAD_HT);
498
499 chroma_samples = luma_samples / 2;
500
501 /* Try to add as many buffers as possible since memory is already allocated */
502 /* If the number of buffers that can be added is less than max_num_bufs
503 * return with an error.
504 */
505 for(i = 0; i < max_dpb_size; i++)
506 {
507 pic_buf_size_allocated -= (luma_samples + chroma_samples);
508
509 if(pic_buf_size_allocated < 0)
510 {
511 ps_codec->s_parse.i4_error_code = IHEVCD_INSUFFICIENT_MEM_PICBUF;
512 return IHEVCD_INSUFFICIENT_MEM_PICBUF;
513 }
514
515 ps_pic_buf->pu1_luma = pu1_buf + ps_codec->i4_strd * PAD_TOP + PAD_LEFT;
516 pu1_buf += luma_samples;
517
518 ps_pic_buf->pu1_chroma = pu1_buf + ps_codec->i4_strd * (PAD_TOP / 2) + PAD_LEFT;
519 pu1_buf += chroma_samples;
520
521 buf_ret = ihevc_buf_mgr_add((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, ps_pic_buf, i);
522
523
524 if(0 != buf_ret)
525 {
526 ps_codec->s_parse.i4_error_code = IHEVCD_BUF_MGR_ERROR;
527 return IHEVCD_BUF_MGR_ERROR;
528 }
529 ps_pic_buf++;
530 }
531 }
532 else
533 {
534 /* In case of shared mode, buffers are added without adjusting for padding.
535 Update luma and chroma pointers here to account for padding as per stride.
536 In some cases stride might not be available when set_display_frame is called.
537 Hence updated luma and chroma pointers here */
538
539 for(i = 0; i < BUF_MGR_MAX_CNT; i++)
540 {
541 ps_pic_buf = ihevc_buf_mgr_get_buf((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, i);
542 if((NULL == ps_pic_buf) ||
543 (NULL == ps_pic_buf->pu1_luma) ||
544 (NULL == ps_pic_buf->pu1_chroma))
545 {
546 break;
547 }
548 ps_pic_buf->pu1_luma += ps_codec->i4_strd * PAD_TOP + PAD_LEFT;
549 ps_pic_buf->pu1_chroma += ps_codec->i4_strd * (PAD_TOP / 2) + PAD_LEFT;
550 }
551 }
552
553 return ret;
554 }
555 /**
556 *******************************************************************************
557 *
558 * @brief
559 * Function to add buffers to MV Bank buffer manager
560 *
561 * @par Description:
562 * Function to add buffers to MV Bank buffer manager
563 * To be called once per stream or for every reset
564 *
565 * @param[in] ps_codec
566 * Pointer to codec context
567 *
568 * @returns Error from IHEVCD_ERROR_T
569 *
570 * @remarks
571 *
572 *
573 *******************************************************************************
574 */
ihevcd_mv_buf_mgr_add_bufs(codec_t * ps_codec)575 IHEVCD_ERROR_T ihevcd_mv_buf_mgr_add_bufs(codec_t *ps_codec)
576 {
577 IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
578 WORD32 i;
579 WORD32 max_dpb_size;
580 WORD32 mv_bank_size_allocated;
581 WORD32 pic_mv_bank_size;
582
583 sps_t *ps_sps;
584 UWORD8 *pu1_buf;
585 mv_buf_t *ps_mv_buf;
586
587
588 /* Initialize MV Bank buffer manager */
589 ps_sps = ps_codec->s_parse.ps_sps;
590
591
592 /* Compute the number of MV Bank buffers needed */
593 max_dpb_size = ps_sps->ai1_sps_max_dec_pic_buffering[ps_sps->i1_sps_max_sub_layers - 1];
594
595 /* Allocate one extra MV Bank to handle current frame
596 * In case of asynchronous parsing and processing, number of buffers should increase here
597 * based on when parsing and processing threads are synchronized
598 */
599 max_dpb_size++;
600
601 pu1_buf = (UWORD8 *)ps_codec->pv_mv_bank_buf_base;
602
603 ps_mv_buf = (mv_buf_t *)pu1_buf;
604 pu1_buf += max_dpb_size * sizeof(mv_buf_t);
605 ps_codec->ps_mv_buf = ps_mv_buf;
606 mv_bank_size_allocated = ps_codec->i4_total_mv_bank_size - max_dpb_size * sizeof(mv_buf_t);
607
608 /* Compute MV bank size per picture */
609 pic_mv_bank_size = ihevcd_get_pic_mv_bank_size(ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
610 ALIGN64(ps_sps->i2_pic_height_in_luma_samples));
611
612 for(i = 0; i < max_dpb_size; i++)
613 {
614 WORD32 buf_ret;
615 WORD32 num_pu;
616 WORD32 num_ctb;
617 WORD32 pic_size;
618 pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
619 ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
620
621
622 num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE);
623 num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
624
625
626 mv_bank_size_allocated -= pic_mv_bank_size;
627
628 if(mv_bank_size_allocated < 0)
629 {
630 ps_codec->s_parse.i4_error_code = IHEVCD_INSUFFICIENT_MEM_MVBANK;
631 return IHEVCD_INSUFFICIENT_MEM_MVBANK;
632 }
633
634 ps_mv_buf->pu4_pic_pu_idx = (UWORD32 *)pu1_buf;
635 pu1_buf += (num_ctb + 1) * sizeof(WORD32);
636
637 ps_mv_buf->pu1_pic_pu_map = pu1_buf;
638 pu1_buf += num_pu;
639
640 ps_mv_buf->pu1_pic_slice_map = (UWORD16 *)pu1_buf;
641 pu1_buf += ALIGN4(num_ctb * sizeof(UWORD16));
642
643 ps_mv_buf->ps_pic_pu = (pu_t *)pu1_buf;
644 pu1_buf += num_pu * sizeof(pu_t);
645
646 buf_ret = ihevc_buf_mgr_add((buf_mgr_t *)ps_codec->pv_mv_buf_mgr, ps_mv_buf, i);
647
648 if(0 != buf_ret)
649 {
650 ps_codec->s_parse.i4_error_code = IHEVCD_BUF_MGR_ERROR;
651 return IHEVCD_BUF_MGR_ERROR;
652 }
653
654 ps_mv_buf++;
655
656 }
657 return ret;
658 }
659 /**
660 *******************************************************************************
661 *
662 * @brief
663 * Picture level initializations required during parsing
664 *
665 * @par Description:
666 * Initialize picture level context variables during parsing Initialize mv
667 * bank buffer manager in the first init call
668 *
669 * @param[in] ps_codec
670 * Pointer to codec context
671 *
672 * @returns Error from IHEVCD_ERROR_T
673 *
674 * @remarks
675 *
676 *
677 *******************************************************************************
678 */
ihevcd_parse_pic_init(codec_t * ps_codec)679 IHEVCD_ERROR_T ihevcd_parse_pic_init(codec_t *ps_codec)
680 {
681 IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
682 mv_buf_t *ps_mv_buf;
683 sps_t *ps_sps;
684 WORD32 num_min_cu;
685 WORD32 cur_pic_buf_id;
686 WORD32 cur_mv_bank_buf_id;
687 pic_buf_t *ps_cur_pic;
688 slice_header_t *ps_slice_hdr;
689 UWORD8 *pu1_cur_pic_luma, *pu1_cur_pic_chroma;
690 WORD32 i;
691
692 ps_codec->s_parse.i4_error_code = IHEVCD_SUCCESS;
693 ps_sps = ps_codec->s_parse.ps_sps;
694 ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr;
695 /* If parse_pic_init is called, then slice data is present in the input bitstrea stream */
696 ps_codec->i4_pic_present = 1;
697
698 /* Memset picture level intra map and transquant bypass map to zero */
699 num_min_cu = ((ps_sps->i2_pic_height_in_luma_samples + 7) / 8) * ((ps_sps->i2_pic_width_in_luma_samples + 63) / 64);
700 memset(ps_codec->s_parse.pu1_pic_intra_flag, 0, num_min_cu);
701 memset(ps_codec->s_parse.pu1_pic_no_loop_filter_flag, 0, num_min_cu);
702
703
704
705 if(0 == ps_codec->s_parse.i4_first_pic_init)
706 {
707 ret = ihevcd_mv_buf_mgr_add_bufs(ps_codec);
708 RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
709
710 ret = ihevcd_pic_buf_mgr_add_bufs(ps_codec);
711 RETURN_IF((ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS), ret);
712
713 ps_codec->s_parse.i4_first_pic_init = 1;
714 }
715
716 /* Initialize all the slice headers' slice addresses to zero */
717 {
718 WORD32 slice_idx;
719 WORD32 slice_start_idx;
720
721 slice_start_idx = ps_codec->i4_slice_error ? 2 : 1;
722
723 for(slice_idx = slice_start_idx; slice_idx < MAX_SLICE_HDR_CNT; slice_idx++)
724 {
725 slice_header_t *ps_slice_hdr_tmp = ps_codec->ps_slice_hdr_base + slice_idx;
726 ps_slice_hdr_tmp->i2_ctb_x = -1;
727 ps_slice_hdr_tmp->i2_ctb_y = -1;
728
729 }
730 }
731
732 /* Get free MV Bank to hold current picture's motion vector data */
733 {
734 ps_mv_buf = (mv_buf_t *)ihevc_buf_mgr_get_next_free((buf_mgr_t *)ps_codec->pv_mv_buf_mgr, &cur_mv_bank_buf_id);
735
736 /* If there are no free buffers then return with an error code.
737 * If the buffer is to be freed by another thread , change the
738 * following to call thread yield and wait for buffer to be freed
739 */
740 if(NULL == ps_mv_buf)
741 {
742 ps_codec->s_parse.i4_error_code = IHEVCD_NO_FREE_MVBANK;
743 ps_codec->i4_error_code = IHEVCD_NO_FREE_MVBANK;
744 return IHEVCD_NO_FREE_MVBANK;
745 }
746
747 ps_codec->s_parse.ps_cur_mv_buf = ps_mv_buf;
748 /* Set current ABS poc to ps_mv_buf, so that while freeing a reference buffer
749 * corresponding mv buffer can be found by looping through ps_codec->ps_mv_buf array
750 * and getting a buffer id to free
751 */
752 ps_mv_buf->i4_abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
753 }
754
755 /* Get free picture buffer to hold current picture recon data */
756 /* TODO: For asynchronous api the following initializations related to picture
757 * buffer should be moved to processing side
758 */
759 {
760
761 UWORD8 *pu1_buf;
762 ps_cur_pic = (pic_buf_t *)ihevc_buf_mgr_get_next_free((buf_mgr_t *)ps_codec->pv_pic_buf_mgr, &cur_pic_buf_id);
763
764 /* If there are no free buffers then return with an error code.
765 * TODO: If the buffer is to be freed by another thread , change the
766 * following to call thread yield and wait for buffer to be freed
767 */
768 if(NULL == ps_cur_pic)
769 {
770 ps_codec->s_parse.i4_error_code = IHEVCD_NO_FREE_PICBUF;
771 ps_codec->i4_error_code = IHEVCD_NO_FREE_PICBUF;
772 return IHEVCD_NO_FREE_PICBUF;
773 }
774
775 /* Store input timestamp sent with input buffer */
776 ps_cur_pic->u4_ts = ps_codec->u4_ts;
777 ps_cur_pic->i4_abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
778 ps_cur_pic->i4_poc_lsb = ps_slice_hdr->i4_pic_order_cnt_lsb;
779 pu1_buf = ps_cur_pic->pu1_luma;
780 pu1_cur_pic_luma = pu1_buf;
781
782 pu1_buf = ps_cur_pic->pu1_chroma;
783
784 pu1_cur_pic_chroma = pu1_buf;
785 }
786
787 if(0 == ps_codec->u4_pic_cnt)
788 {
789 memset(ps_cur_pic->pu1_luma, 128, (ps_sps->i2_pic_width_in_luma_samples + PAD_WD) * ps_sps->i2_pic_height_in_luma_samples);
790 memset(ps_cur_pic->pu1_chroma, 128, (ps_sps->i2_pic_width_in_luma_samples + PAD_WD) * ps_sps->i2_pic_height_in_luma_samples / 2);
791 }
792
793 /* Fill the remaining entries of the reference lists with the nearest POC
794 * This is done to handle cases where there is a corruption in the reference index */
795 {
796 pic_buf_t *ps_pic_buf_ref;
797 mv_buf_t *ps_mv_buf_ref;
798 WORD32 r_idx;
799 dpb_mgr_t *ps_dpb_mgr = (dpb_mgr_t *)ps_codec->pv_dpb_mgr;
800 buf_mgr_t *ps_mv_buf_mgr = (buf_mgr_t *)ps_codec->pv_mv_buf_mgr;
801
802 ps_pic_buf_ref = ihevc_dpb_mgr_get_ref_by_nearest_poc(ps_dpb_mgr, ps_slice_hdr->i4_abs_pic_order_cnt);
803 if(NULL == ps_pic_buf_ref)
804 {
805 WORD32 size;
806
807 WORD32 num_pu;
808 WORD32 num_ctb;
809 WORD32 pic_size;
810 /* In case current mv buffer itself is being used as reference mv buffer for colocated
811 * calculations, then memset all the buffers to zero.
812 */
813 pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
814 ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
815
816 num_pu = pic_size / (MIN_PU_SIZE * MIN_PU_SIZE);
817 num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
818
819 memset(ps_mv_buf->ai4_l0_collocated_poc, 0, sizeof(ps_mv_buf->ai4_l0_collocated_poc));
820 memset(ps_mv_buf->ai1_l0_collocated_poc_lt, 0, sizeof(ps_mv_buf->ai1_l0_collocated_poc_lt));
821 memset(ps_mv_buf->ai4_l1_collocated_poc, 0, sizeof(ps_mv_buf->ai4_l1_collocated_poc));
822 memset(ps_mv_buf->ai1_l1_collocated_poc_lt, 0, sizeof(ps_mv_buf->ai1_l1_collocated_poc_lt));
823
824 size = (num_ctb + 1) * sizeof(WORD32);
825 memset(ps_mv_buf->pu4_pic_pu_idx, 0, size);
826
827 size = num_pu;
828 memset(ps_mv_buf->pu1_pic_pu_map, 0, size);
829 size = ALIGN4(num_ctb * sizeof(UWORD16));
830 memset(ps_mv_buf->pu1_pic_slice_map, 0, size);
831 size = num_pu * sizeof(pu_t);
832 memset(ps_mv_buf->ps_pic_pu, 0, size);
833
834 ps_pic_buf_ref = ps_cur_pic;
835 ps_mv_buf_ref = ps_mv_buf;
836 }
837 else
838 {
839 ps_mv_buf_ref = ihevcd_mv_mgr_get_poc(ps_mv_buf_mgr, ps_pic_buf_ref->i4_abs_poc);
840 }
841
842 for(r_idx = 0; r_idx < ps_slice_hdr->i1_num_ref_idx_l0_active; r_idx++)
843 {
844 if(NULL == ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf)
845 {
846 ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
847 ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
848 }
849 }
850
851 for(r_idx = ps_slice_hdr->i1_num_ref_idx_l0_active; r_idx < MAX_DPB_SIZE; r_idx++)
852 {
853 ps_slice_hdr->as_ref_pic_list0[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
854 ps_slice_hdr->as_ref_pic_list0[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
855 }
856
857 for(r_idx = 0; r_idx < ps_slice_hdr->i1_num_ref_idx_l1_active; r_idx++)
858 {
859 if(NULL == ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf)
860 {
861 ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
862 ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
863 }
864 }
865
866 for(r_idx = ps_slice_hdr->i1_num_ref_idx_l1_active; r_idx < MAX_DPB_SIZE; r_idx++)
867 {
868 ps_slice_hdr->as_ref_pic_list1[r_idx].pv_pic_buf = (void *)ps_pic_buf_ref;
869 ps_slice_hdr->as_ref_pic_list1[r_idx].pv_mv_buf = (void *)ps_mv_buf_ref;
870 }
871 }
872
873
874 /* Reset the jobq to start of the jobq buffer */
875 ihevcd_jobq_reset((jobq_t *)ps_codec->pv_proc_jobq);
876
877 ps_codec->s_parse.i4_pic_pu_idx = 0;
878 ps_codec->s_parse.i4_pic_tu_idx = 0;
879
880 ps_codec->s_parse.pu1_pic_pu_map = ps_mv_buf->pu1_pic_pu_map;
881 ps_codec->s_parse.ps_pic_pu = ps_mv_buf->ps_pic_pu;
882 ps_codec->s_parse.pu4_pic_pu_idx = ps_mv_buf->pu4_pic_pu_idx;
883 ps_codec->s_parse.pu1_slice_idx = (UWORD16 *)ps_mv_buf->pu1_pic_slice_map;
884 for(i = 0; i < MAX_PROCESS_THREADS; i++)
885 {
886 ps_codec->as_process[i].pu1_slice_idx = (UWORD16 *)ps_mv_buf->pu1_pic_slice_map;
887 }
888 ps_codec->s_parse.pu1_pu_map = ps_codec->s_parse.pu1_pic_pu_map;
889 ps_codec->s_parse.ps_pu = ps_codec->s_parse.ps_pic_pu;
890
891 {
892 UWORD8 *pu1_buf;
893 WORD32 ctb_luma_min_tu_cnt, ctb_chroma_min_tu_cnt, ctb_min_tu_cnt;
894 WORD32 pic_size;
895 WORD32 num_ctb;
896
897 pic_size = ALIGN64(ps_sps->i2_pic_width_in_luma_samples) *
898 ALIGN64(ps_sps->i2_pic_height_in_luma_samples);
899
900 ctb_luma_min_tu_cnt = pic_size / (MIN_TU_SIZE * MIN_TU_SIZE);
901
902 ctb_chroma_min_tu_cnt = ctb_luma_min_tu_cnt >> 1;
903
904 ctb_min_tu_cnt = ctb_luma_min_tu_cnt + ctb_chroma_min_tu_cnt;
905
906 num_ctb = pic_size / (MIN_CTB_SIZE * MIN_CTB_SIZE);
907 pu1_buf = (UWORD8 *)ps_codec->pv_tu_data;
908 ps_codec->s_parse.pu4_pic_tu_idx = (UWORD32 *)pu1_buf;
909 pu1_buf += (num_ctb + 1) * sizeof(WORD32);
910
911 ps_codec->s_parse.pu1_pic_tu_map = pu1_buf;
912 pu1_buf += ctb_min_tu_cnt;
913
914 ps_codec->s_parse.ps_pic_tu = (tu_t *)pu1_buf;
915 pu1_buf += ctb_min_tu_cnt * sizeof(tu_t);
916
917 ps_codec->s_parse.pv_pic_tu_coeff_data = pu1_buf;
918
919 ps_codec->s_parse.pu1_tu_map = ps_codec->s_parse.pu1_pic_tu_map;
920 ps_codec->s_parse.ps_tu = ps_codec->s_parse.ps_pic_tu;
921 ps_codec->s_parse.pv_tu_coeff_data = ps_codec->s_parse.pv_pic_tu_coeff_data;
922 }
923
924 ps_codec->s_parse.s_bs_ctxt.ps_pic_pu = ps_codec->s_parse.ps_pic_pu;
925 ps_codec->s_parse.s_bs_ctxt.pu4_pic_pu_idx = ps_codec->s_parse.pu4_pic_pu_idx;
926 ps_codec->s_parse.s_bs_ctxt.pu4_pic_tu_idx = ps_codec->s_parse.pu4_pic_tu_idx;
927
928
929 /* Set number of CTBs to be processed simultaneously */
930 ps_codec->i4_proc_nctb = ihevcd_nctb_cnt(ps_codec, ps_sps);
931
932 /* Memset Parse Map and process map at the start of frame */
933 //TODO: In case of asynchronous API proc_map can not be set to zero here
934 {
935 WORD32 num_ctb;
936
937 num_ctb = ps_sps->i4_pic_size_in_ctb;
938
939 memset(ps_codec->pu1_parse_map, 0, num_ctb);
940
941 memset(ps_codec->pu1_proc_map, 0, num_ctb);
942 }
943
944
945
946 /* Initialize disp buf id to -1, this will be updated at the end of frame if there is
947 * buffer to be displayed
948 */
949 ps_codec->i4_disp_buf_id = -1;
950 ps_codec->ps_disp_buf = NULL;
951
952 ps_codec->i4_disable_deblk_pic = 0;
953 ps_codec->i4_disable_sao_pic = 0;
954 ps_codec->i4_fullpel_inter_pred = 0;
955 ps_codec->i4_mv_frac_mask = 0x7FFFFFFF;
956
957 /* If degrade is enabled, set the degrade flags appropriately */
958 if(ps_codec->i4_degrade_type && ps_codec->i4_degrade_pics)
959 {
960 WORD32 degrade_pic;
961 ps_codec->i4_degrade_pic_cnt++;
962 degrade_pic = 0;
963
964 /* If degrade is to be done in all frames, then do not check further */
965 switch(ps_codec->i4_degrade_pics)
966 {
967 case 4:
968 {
969 degrade_pic = 1;
970 break;
971 }
972 case 3:
973 {
974 if(ps_slice_hdr->i1_slice_type != ISLICE)
975 degrade_pic = 1;
976
977 break;
978 }
979 case 2:
980 {
981
982 /* If pic count hits non-degrade interval or it is an islice, then do not degrade */
983 if((ps_slice_hdr->i1_slice_type != ISLICE) &&
984 (ps_codec->i4_degrade_pic_cnt != ps_codec->i4_nondegrade_interval))
985 degrade_pic = 1;
986
987 break;
988 }
989 case 1:
990 {
991 /* Check if the current picture is non-ref */
992 if((ps_slice_hdr->i1_nal_unit_type < NAL_BLA_W_LP) &&
993 (ps_slice_hdr->i1_nal_unit_type % 2 == 0))
994 {
995 degrade_pic = 1;
996 }
997 break;
998 }
999
1000
1001 }
1002 if(degrade_pic)
1003 {
1004 if(ps_codec->i4_degrade_type & 0x1)
1005 ps_codec->i4_disable_sao_pic = 1;
1006
1007 if(ps_codec->i4_degrade_type & 0x2)
1008 ps_codec->i4_disable_deblk_pic = 1;
1009
1010 /* MC degrading is done only for non-ref pictures */
1011 if((ps_slice_hdr->i1_nal_unit_type < NAL_BLA_W_LP) &&
1012 (ps_slice_hdr->i1_nal_unit_type % 2 == 0))
1013 {
1014 if(ps_codec->i4_degrade_type & 0x4)
1015 ps_codec->i4_mv_frac_mask = 0;
1016
1017 if(ps_codec->i4_degrade_type & 0x8)
1018 ps_codec->i4_mv_frac_mask = 0;
1019 }
1020 }
1021 else
1022 ps_codec->i4_degrade_pic_cnt = 0;
1023 }
1024
1025
1026 {
1027 WORD32 i;
1028 for(i = 0; i < MAX_PROCESS_THREADS; i++)
1029 {
1030 ps_codec->as_process[i].pu4_pic_pu_idx = ps_codec->s_parse.pu4_pic_pu_idx;
1031 ps_codec->as_process[i].ps_pic_pu = ps_codec->s_parse.ps_pic_pu;
1032 ps_codec->as_process[i].pu1_pic_pu_map = ps_codec->s_parse.pu1_pic_pu_map;
1033 ps_codec->as_process[i].pu4_pic_tu_idx = ps_codec->s_parse.pu4_pic_tu_idx;
1034 ps_codec->as_process[i].ps_pic_tu = ps_codec->s_parse.ps_pic_tu;
1035 ps_codec->as_process[i].pu1_pic_tu_map = ps_codec->s_parse.pu1_pic_tu_map;
1036 ps_codec->as_process[i].pv_pic_tu_coeff_data = ps_codec->s_parse.pv_pic_tu_coeff_data;
1037 ps_codec->as_process[i].i4_cur_mv_bank_buf_id = cur_mv_bank_buf_id;
1038 ps_codec->as_process[i].s_sao_ctxt.pu1_slice_idx = ps_codec->as_process[i].pu1_slice_idx;
1039 ps_codec->as_process[i].s_sao_ctxt.pu1_tile_idx = ps_codec->as_process[i].pu1_tile_idx;
1040
1041 /* TODO: For asynchronous api the following initializations related to picture
1042 * buffer should be moved to processing side
1043 */
1044 ps_codec->as_process[i].pu1_cur_pic_luma = pu1_cur_pic_luma;
1045 ps_codec->as_process[i].pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1046 ps_codec->as_process[i].ps_cur_pic = ps_cur_pic;
1047 ps_codec->as_process[i].i4_cur_pic_buf_id = cur_pic_buf_id;
1048
1049 ps_codec->as_process[i].ps_out_buffer = ps_codec->ps_out_buffer;
1050 if(1 < ps_codec->i4_num_cores)
1051 {
1052 ps_codec->as_process[i].i4_check_parse_status = 1;
1053 ps_codec->as_process[i].i4_check_proc_status = 1;
1054 }
1055 else
1056 {
1057 ps_codec->as_process[i].i4_check_parse_status = 0;
1058 ps_codec->as_process[i].i4_check_proc_status = 0;
1059 }
1060 ps_codec->as_process[i].pu1_pic_intra_flag = ps_codec->s_parse.pu1_pic_intra_flag;
1061 ps_codec->as_process[i].pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
1062 ps_codec->as_process[i].i4_init_done = 0;
1063
1064 ps_codec->as_process[i].s_bs_ctxt.pu4_pic_tu_idx = ps_codec->as_process[i].pu4_pic_tu_idx;
1065 ps_codec->as_process[i].s_bs_ctxt.pu4_pic_pu_idx = ps_codec->as_process[i].pu4_pic_pu_idx;
1066 ps_codec->as_process[i].s_bs_ctxt.ps_pic_pu = ps_codec->as_process[i].ps_pic_pu;
1067 ps_codec->as_process[i].s_deblk_ctxt.pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
1068 ps_codec->as_process[i].s_deblk_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
1069 ps_codec->as_process[i].s_deblk_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1070 ps_codec->as_process[i].s_sao_ctxt.pu1_pic_no_loop_filter_flag = ps_codec->s_parse.pu1_pic_no_loop_filter_flag;
1071 ps_codec->as_process[i].s_sao_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
1072 ps_codec->as_process[i].s_sao_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1073 if(i < (ps_codec->i4_num_cores - 1))
1074 {
1075 ithread_create(ps_codec->apv_process_thread_handle[i], NULL,
1076 (void *)ihevcd_process_thread,
1077 (void *)&ps_codec->as_process[i]);
1078 ps_codec->ai4_process_thread_created[i] = 1;
1079 }
1080 else
1081 {
1082 ps_codec->ai4_process_thread_created[i] = 0;
1083 }
1084
1085 }
1086 ps_codec->s_parse.s_deblk_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
1087 ps_codec->s_parse.s_deblk_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1088
1089 ps_codec->s_parse.s_sao_ctxt.pu1_cur_pic_luma = pu1_cur_pic_luma;
1090 ps_codec->s_parse.s_sao_ctxt.pu1_cur_pic_chroma = pu1_cur_pic_chroma;
1091 }
1092 /* Since any input bitstream buffer that contains slice data will be sent to output(even in
1093 * case of error, this buffer is added to display queue and next buffer in the display queue
1094 * will be returned as the display buffer.
1095 * Note: If format conversion (or frame copy) is used and is scheduled
1096 * in a different thread then it has to check if the processing for the current row is complete before
1097 * it copies/converts a given row. In case of low delay or in case of B pictures, current frame being decoded has to be
1098 * returned, which requires a status check to ensure that the current row is reconstructed before copying.
1099 */
1100 /* Add current picture to display manager */
1101 {
1102 WORD32 abs_poc;
1103 slice_header_t *ps_slice_hdr;
1104 ps_slice_hdr = ps_codec->s_parse.ps_slice_hdr;
1105 abs_poc = ps_slice_hdr->i4_abs_pic_order_cnt;
1106 ihevc_disp_mgr_add((disp_mgr_t *)ps_codec->pv_disp_buf_mgr,
1107 ps_codec->as_process[0].i4_cur_pic_buf_id,
1108 abs_poc,
1109 ps_codec->as_process[0].ps_cur_pic);
1110 }
1111 ps_codec->ps_disp_buf = NULL;
1112 /* Get picture to be displayed if number of pictures decoded is more than max allowed reorder */
1113 /* Since the current will be decoded, check is fore >= instead of > */
1114 if(((WORD32)(ps_codec->u4_pic_cnt - ps_codec->u4_disp_cnt) >= ps_sps->ai1_sps_max_num_reorder_pics[ps_sps->i1_sps_max_sub_layers - 1]) ||
1115 (ps_codec->e_frm_out_mode == IVD_DECODE_FRAME_OUT))
1116
1117 {
1118 ps_codec->ps_disp_buf = (pic_buf_t *)ihevc_disp_mgr_get((disp_mgr_t *)ps_codec->pv_disp_buf_mgr, &ps_codec->i4_disp_buf_id);
1119 ps_codec->u4_disp_cnt++;
1120 }
1121
1122 ps_codec->s_fmt_conv.i4_cur_row = 0;
1123 /* Set number of rows to be processed at a time */
1124 ps_codec->s_fmt_conv.i4_num_rows = 4;
1125
1126 if(ps_codec->u4_enable_fmt_conv_ahead && (ps_codec->i4_num_cores > 1))
1127 {
1128 process_ctxt_t *ps_proc;
1129
1130 /* i4_num_cores - 1 contexts are currently being used by other threads */
1131 ps_proc = &ps_codec->as_process[ps_codec->i4_num_cores - 1];
1132
1133 /* If the frame being decoded and displayed are different, schedule format conversion jobs
1134 * this will keep the proc threads busy and lets parse thread decode few CTBs ahead
1135 * If the frame being decoded and displayed are same, then format conversion is scheduled later.
1136 */
1137 if((ps_codec->ps_disp_buf) && (ps_codec->i4_disp_buf_id != ps_proc->i4_cur_pic_buf_id) &&
1138 ((0 == ps_codec->i4_share_disp_buf) || (IV_YUV_420P == ps_codec->e_chroma_fmt)))
1139 {
1140
1141 for(i = 0; i < ps_sps->i2_pic_ht_in_ctb; i++)
1142 {
1143 proc_job_t s_job;
1144 IHEVCD_ERROR_T ret;
1145 s_job.i4_cmd = CMD_FMTCONV;
1146 s_job.i2_ctb_cnt = 0;
1147 s_job.i2_ctb_x = 0;
1148 s_job.i2_ctb_y = i;
1149 s_job.i2_slice_idx = 0;
1150 s_job.i4_tu_coeff_data_ofst = 0;
1151 ret = ihevcd_jobq_queue((jobq_t *)ps_codec->s_parse.pv_proc_jobq,
1152 &s_job, sizeof(proc_job_t), 1);
1153 if(ret != (IHEVCD_ERROR_T)IHEVCD_SUCCESS)
1154 return ret;
1155 }
1156 }
1157 }
1158
1159
1160 return ret;
1161 }
1162
1163
1164