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        /* In case of shared mode, with 420P output, get chroma destination */
756        if((1 == ps_codec->i4_share_disp_buf) && (IV_YUV_420P == ps_codec->e_chroma_fmt))
757        {
758            WORD32 i;
759            for(i = 0; i < ps_codec->i4_share_disp_buf_cnt; i++)
760            {
761                WORD32 diff = ps_disp_pic->pu1_luma - ps_codec->s_disp_buffer[i].pu1_bufs[0];
762                if(diff == (ps_codec->i4_strd * PAD_TOP + PAD_LEFT))
763                {
764                    pu1_u_dst = ps_codec->s_disp_buffer[i].pu1_bufs[1];
765                    pu1_u_dst += (ps_codec->i4_strd * PAD_TOP) / 4 + (PAD_LEFT / 2);
766
767                    pu1_v_dst = ps_codec->s_disp_buffer[i].pu1_bufs[2];
768                    pu1_v_dst += (ps_codec->i4_strd * PAD_TOP) / 4 + (PAD_LEFT / 2);
769                    break;
770                }
771            }
772        }
773        pu2_rgb_dst_tmp  = (UWORD16 *)pu1_y_dst;
774        pu2_rgb_dst_tmp  += cur_row * ps_codec->i4_disp_strd;
775        pu4_rgb_dst_tmp  = (UWORD32 *)pu1_y_dst;
776        pu4_rgb_dst_tmp  += cur_row * ps_codec->i4_disp_strd;
777        pu1_y_dst_tmp  = pu1_y_dst  + cur_row * ps_codec->i4_disp_strd;
778        pu1_uv_dst_tmp = pu1_u_dst  + (cur_row / 2) * ps_codec->i4_disp_strd;
779        pu1_u_dst_tmp = pu1_u_dst  + (cur_row / 2) * ps_codec->i4_disp_strd / 2;
780        pu1_v_dst_tmp = pu1_v_dst  + (cur_row / 2) * ps_codec->i4_disp_strd / 2;
781
782        /* In case of multi threaded implementation, format conversion might be called
783         * before reconstruction is completed. If the frame being converted/copied
784         * is same as the frame being reconstructed,
785         * Check how many rows can be format converted
786         * Convert those many rows and then check for remaining rows and so on
787         */
788
789        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))
790        {
791            WORD32 idx;
792            UWORD8 *pu1_buf;
793            WORD32 status;
794            WORD32 last_row = cur_row + num_rows;
795            WORD32 last_ctb_y;
796            UWORD32 ctb_in_row;
797
798            while(1)
799            {
800                last_row = cur_row + MAX(num_rows, (1 << ps_sps->i1_log2_ctb_size)) +
801                                ps_sps->i2_pic_crop_top_offset * crop_unit_y;
802                last_ctb_y = (last_row >> ps_sps->i1_log2_ctb_size) - 1;
803                /* Since deblocking works with a shift of -4, -4 ,wait till next CTB row is processed */
804                last_ctb_y++;
805                /* In case of a  conformance window, an extra wait of one row might be needed */
806                last_ctb_y++;
807                last_ctb_y = MIN(last_ctb_y, (ps_sps->i2_pic_ht_in_ctb - 1));
808
809                idx = (last_ctb_y * ps_sps->i2_pic_wd_in_ctb);
810
811                /*Check if the row below is completely processed before proceeding with format conversion*/
812                status = 1;
813                for(ctb_in_row = 0; (WORD32)ctb_in_row < ps_sps->i2_pic_wd_in_ctb; ctb_in_row++)
814                {
815                    pu1_buf = (ps_codec->pu1_proc_map + idx + ctb_in_row);
816                    status &= *pu1_buf;
817                }
818
819                if(status)
820                {
821                    break;
822                }
823                else
824                {
825                    ithread_yield();
826                }
827            }
828        }
829
830
831        if((IV_YUV_420SP_UV == ps_codec->e_chroma_fmt) || (IV_YUV_420SP_VU == ps_codec->e_chroma_fmt))
832        {
833
834            ps_codec->s_func_selector.ihevcd_fmt_conv_420sp_to_420sp_fptr(pu1_y_src, pu1_uv_src,
835                                                                          pu1_y_dst_tmp, pu1_uv_dst_tmp,
836                                                                          ps_codec->i4_disp_wd,
837                                                                          num_rows,
838                                                                          ps_codec->i4_strd,
839                                                                          ps_codec->i4_strd,
840                                                                          ps_codec->i4_disp_strd,
841                                                                          ps_codec->i4_disp_strd);
842        }
843        else if(IV_YUV_420P == ps_codec->e_chroma_fmt)
844        {
845
846            if(0 == disable_luma_copy)
847            {
848                // copy luma
849                WORD32 i;
850                WORD32 num_cols = ps_codec->i4_disp_wd;
851
852                for(i = 0; i < num_rows; i++)
853                {
854                    memcpy(pu1_y_dst_tmp, pu1_y_src, num_cols);
855                    pu1_y_dst_tmp += ps_codec->i4_disp_strd;
856                    pu1_y_src += ps_codec->i4_strd;
857                }
858
859                disable_luma_copy = 1;
860            }
861
862            ps_codec->s_func_selector.ihevcd_fmt_conv_420sp_to_420p_fptr(pu1_y_src, pu1_uv_src,
863                                                                         pu1_y_dst_tmp, pu1_u_dst_tmp, pu1_v_dst_tmp,
864                                                                         ps_codec->i4_disp_wd,
865                                                                         num_rows,
866                                                                         ps_codec->i4_strd,
867                                                                         ps_codec->i4_strd,
868                                                                         ps_codec->i4_disp_strd,
869                                                                         (ps_codec->i4_disp_strd / 2),
870                                                                         is_u_first,
871                                                                         disable_luma_copy);
872
873        }
874        else if(IV_RGB_565 == ps_codec->e_chroma_fmt)
875        {
876
877            ps_codec->s_func_selector.ihevcd_fmt_conv_420sp_to_rgb565_fptr(pu1_y_src, pu1_uv_src,
878                                                                           pu2_rgb_dst_tmp,
879                                                                           ps_codec->i4_disp_wd,
880                                                                           num_rows,
881                                                                           ps_codec->i4_strd,
882                                                                           ps_codec->i4_strd,
883                                                                           ps_codec->i4_disp_strd,
884                                                                           is_u_first);
885
886        }
887        else if(IV_RGBA_8888 == ps_codec->e_chroma_fmt)
888        {
889            ASSERT(is_u_first == 1);
890
891            ps_codec->s_func_selector.ihevcd_fmt_conv_420sp_to_rgba8888_fptr(pu1_y_src,
892                                                                             pu1_uv_src,
893                                                                             pu4_rgb_dst_tmp,
894                                                                             ps_codec->i4_disp_wd,
895                                                                             num_rows,
896                                                                             ps_codec->i4_strd,
897                                                                             ps_codec->i4_strd,
898                                                                             ps_codec->i4_disp_strd,
899                                                                             is_u_first);
900
901        }
902
903
904
905    }
906    return (ret);
907}
908
909