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_fmt_conv.c
22*
23* @brief
24*  Contains functions for format conversion or frame copy of output buffer
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_structs.h"
54#include "ihevc_macros.h"
55#include "ihevc_platform_macros.h"
56#include "ihevc_cabac_tables.h"
57#include "ihevc_disp_mgr.h"
58
59#include "ihevcd_defs.h"
60#include "ihevcd_function_selector.h"
61#include "ihevcd_structs.h"
62#include "ihevcd_error.h"
63#include "ihevcd_nal.h"
64#include "ihevcd_bitstream.h"
65#include "ihevcd_fmt_conv.h"
66#include "ihevcd_profile.h"
67
68/**
69*******************************************************************************
70*
71* @brief Function used from copying a 420SP buffer
72*
73* @par   Description
74* Function used from copying a 420SP buffer
75*
76* @param[in] pu1_y_src
77*   Input Y pointer
78*
79* @param[in] pu1_uv_src
80*   Input UV pointer (UV is interleaved either in UV or VU format)
81*
82* @param[in] pu1_y_dst
83*   Output Y pointer
84*
85* @param[in] pu1_uv_dst
86*   Output UV pointer (UV is interleaved in the same format as that of input)
87*
88* @param[in] wd
89*   Width
90*
91* @param[in] ht
92*   Height
93*
94* @param[in] src_y_strd
95*   Input Y Stride
96*
97* @param[in] src_uv_strd
98*   Input UV stride
99*
100* @param[in] dst_y_strd
101*   Output Y stride
102*
103* @param[in] dst_uv_strd
104*   Output UV stride
105*
106* @returns None
107*
108* @remarks In case there is a need to perform partial frame copy then
109* by passion appropriate source and destination pointers and appropriate
110* values for wd and ht it can be done
111*
112*******************************************************************************
113*/
114void ihevcd_fmt_conv_420sp_to_rgb565(UWORD8 *pu1_y_src,
115                                     UWORD8 *pu1_uv_src,
116                                     UWORD16 *pu2_rgb_dst,
117                                     WORD32 wd,
118                                     WORD32 ht,
119                                     WORD32 src_y_strd,
120                                     WORD32 src_uv_strd,
121                                     WORD32 dst_strd,
122                                     WORD32 is_u_first)
123{
124
125
126    WORD16  i2_r, i2_g, i2_b;
127    UWORD32  u4_r, u4_g, u4_b;
128    WORD16  i2_i, i2_j;
129    UWORD8  *pu1_y_src_nxt;
130    UWORD16 *pu2_rgb_dst_NextRow;
131
132    UWORD8 *pu1_u_src, *pu1_v_src;
133
134    if(is_u_first)
135    {
136        pu1_u_src = (UWORD8 *)pu1_uv_src;
137        pu1_v_src = (UWORD8 *)pu1_uv_src + 1;
138    }
139    else
140    {
141        pu1_u_src = (UWORD8 *)pu1_uv_src + 1;
142        pu1_v_src = (UWORD8 *)pu1_uv_src;
143    }
144
145    pu1_y_src_nxt   = pu1_y_src + src_y_strd;
146    pu2_rgb_dst_NextRow = pu2_rgb_dst + dst_strd;
147
148    for(i2_i = 0; i2_i < (ht >> 1); i2_i++)
149    {
150        for(i2_j = (wd >> 1); i2_j > 0; i2_j--)
151        {
152            i2_b = ((*pu1_u_src - 128) * COEFF4 >> 13);
153            i2_g = ((*pu1_u_src - 128) * COEFF2 + (*pu1_v_src - 128) * COEFF3) >> 13;
154            i2_r = ((*pu1_v_src - 128) * COEFF1) >> 13;
155
156            pu1_u_src += 2;
157            pu1_v_src += 2;
158            /* pixel 0 */
159            /* B */
160            u4_b = CLIP_U8(*pu1_y_src + i2_b);
161            u4_b >>= 3;
162            /* G */
163            u4_g = CLIP_U8(*pu1_y_src + i2_g);
164            u4_g >>= 2;
165            /* R */
166            u4_r = CLIP_U8(*pu1_y_src + i2_r);
167            u4_r >>= 3;
168
169            pu1_y_src++;
170            *pu2_rgb_dst++ = ((u4_r << 11) | (u4_g << 5) | u4_b);
171
172            /* pixel 1 */
173            /* B */
174            u4_b = CLIP_U8(*pu1_y_src + i2_b);
175            u4_b >>= 3;
176            /* G */
177            u4_g = CLIP_U8(*pu1_y_src + i2_g);
178            u4_g >>= 2;
179            /* R */
180            u4_r = CLIP_U8(*pu1_y_src + i2_r);
181            u4_r >>= 3;
182
183            pu1_y_src++;
184            *pu2_rgb_dst++ = ((u4_r << 11) | (u4_g << 5) | u4_b);
185
186            /* pixel 2 */
187            /* B */
188            u4_b = CLIP_U8(*pu1_y_src_nxt + i2_b);
189            u4_b >>= 3;
190            /* G */
191            u4_g = CLIP_U8(*pu1_y_src_nxt + i2_g);
192            u4_g >>= 2;
193            /* R */
194            u4_r = CLIP_U8(*pu1_y_src_nxt + i2_r);
195            u4_r >>= 3;
196
197            pu1_y_src_nxt++;
198            *pu2_rgb_dst_NextRow++ = ((u4_r << 11) | (u4_g << 5) | u4_b);
199
200            /* pixel 3 */
201            /* B */
202            u4_b = CLIP_U8(*pu1_y_src_nxt + i2_b);
203            u4_b >>= 3;
204            /* G */
205            u4_g = CLIP_U8(*pu1_y_src_nxt + i2_g);
206            u4_g >>= 2;
207            /* R */
208            u4_r = CLIP_U8(*pu1_y_src_nxt + i2_r);
209            u4_r >>= 3;
210
211            pu1_y_src_nxt++;
212            *pu2_rgb_dst_NextRow++ = ((u4_r << 11) | (u4_g << 5) | u4_b);
213
214        }
215
216        pu1_u_src = pu1_u_src + src_uv_strd - wd;
217        pu1_v_src = pu1_v_src + src_uv_strd - wd;
218
219        pu1_y_src = pu1_y_src + (src_y_strd << 1) - wd;
220        pu1_y_src_nxt = pu1_y_src_nxt + (src_y_strd << 1) - wd;
221
222        pu2_rgb_dst = pu2_rgb_dst_NextRow - wd + dst_strd;
223        pu2_rgb_dst_NextRow = pu2_rgb_dst_NextRow + (dst_strd << 1) - wd;
224    }
225
226
227}
228
229void ihevcd_fmt_conv_420sp_to_rgba8888(UWORD8 *pu1_y_src,
230                                       UWORD8 *pu1_uv_src,
231                                       UWORD32 *pu4_rgba_dst,
232                                       WORD32 wd,
233                                       WORD32 ht,
234                                       WORD32 src_y_strd,
235                                       WORD32 src_uv_strd,
236                                       WORD32 dst_strd,
237                                       WORD32 is_u_first)
238{
239
240
241    WORD16  i2_r, i2_g, i2_b;
242    UWORD32  u4_r, u4_g, u4_b;
243    WORD16  i2_i, i2_j;
244    UWORD8  *pu1_y_src_nxt;
245    UWORD32 *pu4_rgba_dst_NextRow;
246
247    UWORD8 *pu1_u_src, *pu1_v_src;
248
249    if(is_u_first)
250    {
251        pu1_u_src = (UWORD8 *)pu1_uv_src;
252        pu1_v_src = (UWORD8 *)pu1_uv_src + 1;
253    }
254    else
255    {
256        pu1_u_src = (UWORD8 *)pu1_uv_src + 1;
257        pu1_v_src = (UWORD8 *)pu1_uv_src;
258    }
259
260    pu1_y_src_nxt   = pu1_y_src + src_y_strd;
261    pu4_rgba_dst_NextRow = pu4_rgba_dst + dst_strd;
262
263    for(i2_i = 0; i2_i < (ht >> 1); i2_i++)
264    {
265        for(i2_j = (wd >> 1); i2_j > 0; i2_j--)
266        {
267            i2_b = ((*pu1_u_src - 128) * COEFF4 >> 13);
268            i2_g = ((*pu1_u_src - 128) * COEFF2 + (*pu1_v_src - 128) * COEFF3) >> 13;
269            i2_r = ((*pu1_v_src - 128) * COEFF1) >> 13;
270
271            pu1_u_src += 2;
272            pu1_v_src += 2;
273            /* pixel 0 */
274            /* B */
275            u4_b = CLIP_U8(*pu1_y_src + i2_b);
276            /* G */
277            u4_g = CLIP_U8(*pu1_y_src + i2_g);
278            /* R */
279            u4_r = CLIP_U8(*pu1_y_src + i2_r);
280
281            pu1_y_src++;
282            *pu4_rgba_dst++ = ((u4_r << 16) | (u4_g << 8) | (u4_b << 0));
283
284            /* pixel 1 */
285            /* B */
286            u4_b = CLIP_U8(*pu1_y_src + i2_b);
287            /* G */
288            u4_g = CLIP_U8(*pu1_y_src + i2_g);
289            /* R */
290            u4_r = CLIP_U8(*pu1_y_src + i2_r);
291
292            pu1_y_src++;
293            *pu4_rgba_dst++ = ((u4_r << 16) | (u4_g << 8) | (u4_b << 0));
294
295            /* pixel 2 */
296            /* B */
297            u4_b = CLIP_U8(*pu1_y_src_nxt + i2_b);
298            /* G */
299            u4_g = CLIP_U8(*pu1_y_src_nxt + i2_g);
300            /* R */
301            u4_r = CLIP_U8(*pu1_y_src_nxt + i2_r);
302
303            pu1_y_src_nxt++;
304            *pu4_rgba_dst_NextRow++ = ((u4_r << 16) | (u4_g << 8) | (u4_b << 0));
305
306            /* pixel 3 */
307            /* B */
308            u4_b = CLIP_U8(*pu1_y_src_nxt + i2_b);
309            /* G */
310            u4_g = CLIP_U8(*pu1_y_src_nxt + i2_g);
311            /* R */
312            u4_r = CLIP_U8(*pu1_y_src_nxt + i2_r);
313
314            pu1_y_src_nxt++;
315            *pu4_rgba_dst_NextRow++ = ((u4_r << 16) | (u4_g << 8) | (u4_b << 0));
316
317        }
318
319        pu1_u_src = pu1_u_src + src_uv_strd - wd;
320        pu1_v_src = pu1_v_src + src_uv_strd - wd;
321
322        pu1_y_src = pu1_y_src + (src_y_strd << 1) - wd;
323        pu1_y_src_nxt = pu1_y_src_nxt + (src_y_strd << 1) - wd;
324
325        pu4_rgba_dst = pu4_rgba_dst_NextRow - wd + dst_strd;
326        pu4_rgba_dst_NextRow = pu4_rgba_dst_NextRow + (dst_strd << 1) - wd;
327    }
328
329
330}
331
332/**
333*******************************************************************************
334*
335* @brief Function used from copying a 420SP buffer
336*
337* @par   Description
338* Function used from copying a 420SP buffer
339*
340* @param[in] pu1_y_src
341*   Input Y pointer
342*
343* @param[in] pu1_uv_src
344*   Input UV pointer (UV is interleaved either in UV or VU format)
345*
346* @param[in] pu1_y_dst
347*   Output Y pointer
348*
349* @param[in] pu1_uv_dst
350*   Output UV pointer (UV is interleaved in the same format as that of input)
351*
352* @param[in] wd
353*   Width
354*
355* @param[in] ht
356*   Height
357*
358* @param[in] src_y_strd
359*   Input Y Stride
360*
361* @param[in] src_uv_strd
362*   Input UV stride
363*
364* @param[in] dst_y_strd
365*   Output Y stride
366*
367* @param[in] dst_uv_strd
368*   Output UV stride
369*
370* @returns None
371*
372* @remarks In case there is a need to perform partial frame copy then
373* by passion appropriate source and destination pointers and appropriate
374* values for wd and ht it can be done
375*
376*******************************************************************************
377*/
378
379void ihevcd_fmt_conv_420sp_to_420sp(UWORD8 *pu1_y_src,
380                                    UWORD8 *pu1_uv_src,
381                                    UWORD8 *pu1_y_dst,
382                                    UWORD8 *pu1_uv_dst,
383                                    WORD32 wd,
384                                    WORD32 ht,
385                                    WORD32 src_y_strd,
386                                    WORD32 src_uv_strd,
387                                    WORD32 dst_y_strd,
388                                    WORD32 dst_uv_strd)
389{
390    UWORD8 *pu1_src, *pu1_dst;
391    WORD32 num_rows, num_cols, src_strd, dst_strd;
392    WORD32 i;
393
394    /* copy luma */
395    pu1_src = (UWORD8 *)pu1_y_src;
396    pu1_dst = (UWORD8 *)pu1_y_dst;
397
398    num_rows = ht;
399    num_cols = wd;
400
401    src_strd = src_y_strd;
402    dst_strd = dst_y_strd;
403
404    for(i = 0; i < num_rows; i++)
405    {
406        memcpy(pu1_dst, pu1_src, num_cols);
407        pu1_dst += dst_strd;
408        pu1_src += src_strd;
409    }
410
411    /* copy U and V */
412    pu1_src = (UWORD8 *)pu1_uv_src;
413    pu1_dst = (UWORD8 *)pu1_uv_dst;
414
415    num_rows = ht >> 1;
416    num_cols = wd;
417
418    src_strd = src_uv_strd;
419    dst_strd = dst_uv_strd;
420
421    for(i = 0; i < num_rows; i++)
422    {
423        memcpy(pu1_dst, pu1_src, num_cols);
424        pu1_dst += dst_strd;
425        pu1_src += src_strd;
426    }
427    return;
428}
429
430
431
432/**
433*******************************************************************************
434*
435* @brief Function used from copying a 420SP buffer
436*
437* @par   Description
438* Function used from copying a 420SP buffer
439*
440* @param[in] pu1_y_src
441*   Input Y pointer
442*
443* @param[in] pu1_uv_src
444*   Input UV pointer (UV is interleaved either in UV or VU format)
445*
446* @param[in] pu1_y_dst
447*   Output Y pointer
448*
449* @param[in] pu1_uv_dst
450*   Output UV pointer (UV is interleaved in the same format as that of input)
451*
452* @param[in] wd
453*   Width
454*
455* @param[in] ht
456*   Height
457*
458* @param[in] src_y_strd
459*   Input Y Stride
460*
461* @param[in] src_uv_strd
462*   Input UV stride
463*
464* @param[in] dst_y_strd
465*   Output Y stride
466*
467* @param[in] dst_uv_strd
468*   Output UV stride
469*
470* @returns None
471*
472* @remarks In case there is a need to perform partial frame copy then
473* by passion appropriate source and destination pointers and appropriate
474* values for wd and ht it can be done
475*
476*******************************************************************************
477*/
478void ihevcd_fmt_conv_420sp_to_420sp_swap_uv(UWORD8 *pu1_y_src,
479                                            UWORD8 *pu1_uv_src,
480                                            UWORD8 *pu1_y_dst,
481                                            UWORD8 *pu1_uv_dst,
482                                            WORD32 wd,
483                                            WORD32 ht,
484                                            WORD32 src_y_strd,
485                                            WORD32 src_uv_strd,
486                                            WORD32 dst_y_strd,
487                                            WORD32 dst_uv_strd)
488{
489    UWORD8 *pu1_src, *pu1_dst;
490    WORD32 num_rows, num_cols, src_strd, dst_strd;
491    WORD32 i;
492
493    /* copy luma */
494    pu1_src = (UWORD8 *)pu1_y_src;
495    pu1_dst = (UWORD8 *)pu1_y_dst;
496
497    num_rows = ht;
498    num_cols = wd;
499
500    src_strd = src_y_strd;
501    dst_strd = dst_y_strd;
502
503    for(i = 0; i < num_rows; i++)
504    {
505        memcpy(pu1_dst, pu1_src, num_cols);
506        pu1_dst += dst_strd;
507        pu1_src += src_strd;
508    }
509
510    /* copy U and V */
511    pu1_src = (UWORD8 *)pu1_uv_src;
512    pu1_dst = (UWORD8 *)pu1_uv_dst;
513
514    num_rows = ht >> 1;
515    num_cols = wd;
516
517    src_strd = src_uv_strd;
518    dst_strd = dst_uv_strd;
519
520    for(i = 0; i < num_rows; i++)
521    {
522        WORD32 j;
523        for(j = 0; j < num_cols; j += 2)
524        {
525            pu1_dst[j + 0] = pu1_src[j + 1];
526            pu1_dst[j + 1] = pu1_src[j + 0];
527        }
528        pu1_dst += dst_strd;
529        pu1_src += src_strd;
530    }
531    return;
532}
533/**
534*******************************************************************************
535*
536* @brief Function used from copying a 420SP buffer
537*
538* @par   Description
539* Function used from copying a 420SP buffer
540*
541* @param[in] pu1_y_src
542*   Input Y pointer
543*
544* @param[in] pu1_uv_src
545*   Input UV pointer (UV is interleaved either in UV or VU format)
546*
547* @param[in] pu1_y_dst
548*   Output Y pointer
549*
550* @param[in] pu1_u_dst
551*   Output U pointer
552*
553* @param[in] pu1_v_dst
554*   Output V pointer
555*
556* @param[in] wd
557*   Width
558*
559* @param[in] ht
560*   Height
561*
562* @param[in] src_y_strd
563*   Input Y Stride
564*
565* @param[in] src_uv_strd
566*   Input UV stride
567*
568* @param[in] dst_y_strd
569*   Output Y stride
570*
571* @param[in] dst_uv_strd
572*   Output UV stride
573*
574* @param[in] is_u_first
575*   Flag to indicate if U is the first byte in input chroma part
576*
577* @returns none
578*
579* @remarks In case there is a need to perform partial frame copy then
580* by passion appropriate source and destination pointers and appropriate
581* values for wd and ht it can be done
582*
583*******************************************************************************
584*/
585
586
587void ihevcd_fmt_conv_420sp_to_420p(UWORD8 *pu1_y_src,
588                                   UWORD8 *pu1_uv_src,
589                                   UWORD8 *pu1_y_dst,
590                                   UWORD8 *pu1_u_dst,
591                                   UWORD8 *pu1_v_dst,
592                                   WORD32 wd,
593                                   WORD32 ht,
594                                   WORD32 src_y_strd,
595                                   WORD32 src_uv_strd,
596                                   WORD32 dst_y_strd,
597                                   WORD32 dst_uv_strd,
598                                   WORD32 is_u_first,
599                                   WORD32 disable_luma_copy)
600{
601    UWORD8 *pu1_src, *pu1_dst;
602    UWORD8 *pu1_u_src, *pu1_v_src;
603    WORD32 num_rows, num_cols, src_strd, dst_strd;
604    WORD32 i, j;
605
606    if(0 == disable_luma_copy)
607    {
608        /* copy luma */
609        pu1_src = (UWORD8 *)pu1_y_src;
610        pu1_dst = (UWORD8 *)pu1_y_dst;
611
612        num_rows = ht;
613        num_cols = wd;
614
615        src_strd = src_y_strd;
616        dst_strd = dst_y_strd;
617
618        for(i = 0; i < num_rows; i++)
619        {
620            memcpy(pu1_dst, pu1_src, num_cols);
621            pu1_dst += dst_strd;
622            pu1_src += src_strd;
623        }
624    }
625    /* de-interleave U and V and copy to destination */
626    if(is_u_first)
627    {
628        pu1_u_src = (UWORD8 *)pu1_uv_src;
629        pu1_v_src = (UWORD8 *)pu1_uv_src + 1;
630    }
631    else
632    {
633        pu1_u_src = (UWORD8 *)pu1_uv_src + 1;
634        pu1_v_src = (UWORD8 *)pu1_uv_src;
635    }
636
637
638    num_rows = ht >> 1;
639    num_cols = wd >> 1;
640
641    src_strd = src_uv_strd;
642    dst_strd = dst_uv_strd;
643
644    for(i = 0; i < num_rows; i++)
645    {
646        for(j = 0; j < num_cols; j++)
647        {
648            pu1_u_dst[j] = pu1_u_src[j * 2];
649            pu1_v_dst[j] = pu1_v_src[j * 2];
650        }
651
652        pu1_u_dst += dst_strd;
653        pu1_v_dst += dst_strd;
654        pu1_u_src += src_strd;
655        pu1_v_src += src_strd;
656    }
657    return;
658}
659
660
661
662/**
663*******************************************************************************
664*
665* @brief Function used from format conversion or frame copy
666*
667* @par   Description
668* Function used from copying or converting a reference frame to display buffer
669* in non shared mode
670*
671* @param[in] pu1_y_dst
672*   Output Y pointer
673*
674* @param[in] pu1_u_dst
675*   Output U/UV pointer ( UV is interleaved in the same format as that of input)
676*
677* @param[in] pu1_v_dst
678*   Output V pointer ( used in 420P output case)
679*
680* @param[in] blocking
681*   To indicate whether format conversion should wait till frame is reconstructed
682*   and then return after complete copy is done. To be set to 1 when called at the
683*   end of frame processing and set to 0 when called between frame processing modules
684*   in order to utilize available MCPS
685*
686* @returns Error from IHEVCD_ERROR_T
687*
688*******************************************************************************
689*/
690IHEVCD_ERROR_T ihevcd_fmt_conv(codec_t *ps_codec,
691                               process_ctxt_t *ps_proc,
692                               UWORD8 *pu1_y_dst,
693                               UWORD8 *pu1_u_dst,
694                               UWORD8 *pu1_v_dst,
695                               WORD32 cur_row,
696                               WORD32 num_rows)
697{
698    IHEVCD_ERROR_T ret = (IHEVCD_ERROR_T)IHEVCD_SUCCESS;
699    pic_buf_t *ps_disp_pic;
700    UWORD8 *pu1_y_src, *pu1_uv_src;
701    UWORD8 *pu1_y_dst_tmp, *pu1_uv_dst_tmp;
702    UWORD8 *pu1_u_dst_tmp, *pu1_v_dst_tmp;
703    UWORD16 *pu2_rgb_dst_tmp;
704    UWORD32 *pu4_rgb_dst_tmp;
705    WORD32 is_u_first;
706    UWORD8 *pu1_luma;
707    UWORD8 *pu1_chroma;
708    sps_t *ps_sps;
709    WORD32 disable_luma_copy;
710    WORD32 crop_unit_x, crop_unit_y;
711
712    if(0 == num_rows)
713        return ret;
714
715    /* In case processing is disabled, then no need to format convert/copy */
716    PROFILE_DISABLE_FMT_CONV();
717    ps_sps = ps_proc->ps_sps;
718
719    crop_unit_x = 1;
720    crop_unit_y = 1;
721
722    if(CHROMA_FMT_IDC_YUV420 == ps_sps->i1_chroma_format_idc)
723    {
724        crop_unit_x = 2;
725        crop_unit_y = 2;
726    }
727
728    ps_disp_pic = ps_codec->ps_disp_buf;
729    pu1_luma = ps_disp_pic->pu1_luma;
730    pu1_chroma = ps_disp_pic->pu1_chroma;
731
732
733    /* Take care of cropping */
734    pu1_luma    += ps_codec->i4_strd * ps_sps->i2_pic_crop_top_offset * crop_unit_y + ps_sps->i2_pic_crop_left_offset * crop_unit_x;
735
736    /* Left offset is multiplied by 2 because buffer is UV interleaved */
737    pu1_chroma  += ps_codec->i4_strd * ps_sps->i2_pic_crop_top_offset + ps_sps->i2_pic_crop_left_offset * 2;
738
739
740    is_u_first = (IV_YUV_420SP_UV == ps_codec->e_ref_chroma_fmt) ? 1 : 0;
741
742    /* In case of 420P output luma copy is disabled for shared mode */
743    disable_luma_copy = 0;
744    if(1 == ps_codec->i4_share_disp_buf)
745    {
746        disable_luma_copy = 1;
747    }
748
749
750
751    {
752        pu1_y_src   = pu1_luma + cur_row * ps_codec->i4_strd;
753        pu1_uv_src  = pu1_chroma + (cur_row / 2) * ps_codec->i4_strd;
754
755        pu2_rgb_dst_tmp  = (UWORD16 *)pu1_y_dst;
756        pu2_rgb_dst_tmp  += cur_row * ps_codec->i4_disp_strd;
757        pu4_rgb_dst_tmp  = (UWORD32 *)pu1_y_dst;
758        pu4_rgb_dst_tmp  += cur_row * ps_codec->i4_disp_strd;
759        pu1_y_dst_tmp  = pu1_y_dst  + cur_row * ps_codec->i4_disp_strd;
760        pu1_uv_dst_tmp = pu1_u_dst  + (cur_row / 2) * ps_codec->i4_disp_strd;
761        pu1_u_dst_tmp = pu1_u_dst  + (cur_row / 2) * ps_codec->i4_disp_strd / 2;
762        pu1_v_dst_tmp = pu1_v_dst  + (cur_row / 2) * ps_codec->i4_disp_strd / 2;
763
764        /* In case of multi threaded implementation, format conversion might be called
765         * before reconstruction is completed. If the frame being converted/copied
766         * is same as the frame being reconstructed,
767         * Check how many rows can be format converted
768         * Convert those many rows and then check for remaining rows and so on
769         */
770
771        if((0 == ps_codec->i4_flush_mode) && (ps_codec->i4_disp_buf_id == ps_proc->i4_cur_pic_buf_id) && (1 < ps_codec->i4_num_cores))
772        {
773            WORD32 idx;
774            UWORD8 *pu1_buf;
775            WORD32 status;
776            WORD32 last_row = cur_row + num_rows;
777            WORD32 last_ctb_y;
778            UWORD32 ctb_in_row;
779
780            while(1)
781            {
782                last_row = cur_row + MAX(num_rows, (1 << ps_sps->i1_log2_ctb_size)) +
783                                ps_sps->i2_pic_crop_top_offset * crop_unit_y;
784                last_ctb_y = (last_row >> ps_sps->i1_log2_ctb_size) - 1;
785                /* Since deblocking works with a shift of -4, -4 ,wait till next CTB row is processed */
786                last_ctb_y++;
787                /* In case of a  conformance window, an extra wait of one row might be needed */
788                last_ctb_y++;
789                last_ctb_y = MIN(last_ctb_y, (ps_sps->i2_pic_ht_in_ctb - 1));
790
791                idx = (last_ctb_y * ps_sps->i2_pic_wd_in_ctb);
792
793                /*Check if the row below is completely processed before proceeding with format conversion*/
794                status = 1;
795                for(ctb_in_row = 0; (WORD32)ctb_in_row < ps_sps->i2_pic_wd_in_ctb; ctb_in_row++)
796                {
797                    pu1_buf = (ps_codec->pu1_proc_map + idx + ctb_in_row);
798                    status &= *pu1_buf;
799                }
800
801                if(status)
802                {
803                    break;
804                }
805                else
806                {
807                    ithread_yield();
808                }
809            }
810        }
811
812
813        if((IV_YUV_420SP_UV == ps_codec->e_chroma_fmt) || (IV_YUV_420SP_VU == ps_codec->e_chroma_fmt))
814        {
815
816            ps_codec->s_func_selector.ihevcd_fmt_conv_420sp_to_420sp_fptr(pu1_y_src, pu1_uv_src,
817                                                                          pu1_y_dst_tmp, pu1_uv_dst_tmp,
818                                                                          ps_codec->i4_disp_wd,
819                                                                          num_rows,
820                                                                          ps_codec->i4_strd,
821                                                                          ps_codec->i4_strd,
822                                                                          ps_codec->i4_disp_strd,
823                                                                          ps_codec->i4_disp_strd);
824        }
825        else if(IV_YUV_420P == ps_codec->e_chroma_fmt)
826        {
827
828            if(0 == disable_luma_copy)
829            {
830                // copy luma
831                WORD32 i;
832                WORD32 num_cols = ps_codec->i4_disp_wd;
833
834                for(i = 0; i < num_rows; i++)
835                {
836                    memcpy(pu1_y_dst_tmp, pu1_y_src, num_cols);
837                    pu1_y_dst_tmp += ps_codec->i4_disp_strd;
838                    pu1_y_src += ps_codec->i4_strd;
839                }
840
841                disable_luma_copy = 1;
842            }
843
844            ps_codec->s_func_selector.ihevcd_fmt_conv_420sp_to_420p_fptr(pu1_y_src, pu1_uv_src,
845                                                                         pu1_y_dst_tmp, pu1_u_dst_tmp, pu1_v_dst_tmp,
846                                                                         ps_codec->i4_disp_wd,
847                                                                         num_rows,
848                                                                         ps_codec->i4_strd,
849                                                                         ps_codec->i4_strd,
850                                                                         ps_codec->i4_disp_strd,
851                                                                         (ps_codec->i4_disp_strd / 2),
852                                                                         is_u_first,
853                                                                         disable_luma_copy);
854
855        }
856        else if(IV_RGB_565 == ps_codec->e_chroma_fmt)
857        {
858
859            ps_codec->s_func_selector.ihevcd_fmt_conv_420sp_to_rgb565_fptr(pu1_y_src, pu1_uv_src,
860                                                                           pu2_rgb_dst_tmp,
861                                                                           ps_codec->i4_disp_wd,
862                                                                           num_rows,
863                                                                           ps_codec->i4_strd,
864                                                                           ps_codec->i4_strd,
865                                                                           ps_codec->i4_disp_strd,
866                                                                           is_u_first);
867
868        }
869        else if(IV_RGBA_8888 == ps_codec->e_chroma_fmt)
870        {
871            ASSERT(is_u_first == 1);
872
873            ps_codec->s_func_selector.ihevcd_fmt_conv_420sp_to_rgba8888_fptr(pu1_y_src,
874                                                                             pu1_uv_src,
875                                                                             pu4_rgb_dst_tmp,
876                                                                             ps_codec->i4_disp_wd,
877                                                                             num_rows,
878                                                                             ps_codec->i4_strd,
879                                                                             ps_codec->i4_strd,
880                                                                             ps_codec->i4_disp_strd,
881                                                                             is_u_first);
882
883        }
884
885
886
887    }
888    return (ret);
889}
890
891